Xataface 2.0
Xataface Application Framework
Dataface/Application.php
Go to the documentation of this file.
00001 <?php
00002 /*-------------------------------------------------------------------------------
00003  * Xataface Web Application Framework
00004  * Copyright (C) 2005-2008 Web Lite Solutions Corp (shannah@sfu.ca)
00005  * 
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version.
00010  * 
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  * 
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *-------------------------------------------------------------------------------
00020  */
00021  
00022  
00023 if ( !function_exists('sys_get_temp_dir') )
00024 {
00025  // Based on http://www.phpit.net/
00026  // article/creating-zip-tar-archives-dynamically-php/2/
00027  function sys_get_temp_dir()
00028  {
00029    // Try to get from environment variable
00030    if ( !empty($_ENV['TMP']) )
00031    {
00032      return realpath( $_ENV['TMP'] );
00033    }
00034    else if ( !empty($_ENV['TMPDIR']) )
00035    {
00036      return realpath( $_ENV['TMPDIR'] );
00037    }
00038    else if ( !empty($_ENV['TEMP']) )
00039    {
00040      return realpath( $_ENV['TEMP'] );
00041    }
00042 
00043    // Detect by creating a temporary file
00044    else
00045    {
00046      // Try to use system's temporary directory
00047      // as random name shouldn't exist
00048      $temp_file = tempnam( md5(uniqid(rand(), TRUE)), '' );
00049      if ( $temp_file )
00050      {
00051        $temp_dir = realpath( dirname($temp_file) );
00052        unlink( $temp_file );
00053        return $temp_dir;
00054      }
00055      else
00056      {
00057        return FALSE;
00058      }
00059    }
00060  }
00061 }
00062 
00063 require_once dirname(__FILE__)."/../config.inc.php";
00064 import('Dataface/PermissionsTool.php');
00065 import('Dataface/LanguageTool.php');
00066 define('DATAFACE_STRICT_PERMISSIONS', 100);
00067         // the minimum security level that is deemed as strict permissions.  
00068         // strict permissions mean that permissions must be explicitly granted to a 
00069         // table, record, or action or they will not be accessible
00070 
00087 class Dataface_Application {
00088 
00089         const EX_FAILED_TO_CREATE_SESSION_DIR = 5500;
00090         
00091         
00117         public $redirectHandler = null;
00118 
00122         var $sessionCookieKey;
00123 
00124         
00128         var $autoSession = false;
00129 
00133         var $_url_filters = array();
00138         var $_tables = array();
00139         
00144         var $tableIndex = array();
00145         
00150         var $_baseUrl;
00151         
00155         var $_currentTable;
00156         
00157         
00161         var $memcache;
00162         
00167         var $_db;
00174         var $_query;
00175         
00182         var $rawQuery;
00183         
00187         var $queryTool = null;
00188         
00192         var $currentRecord = null;
00193         
00197         var $_customPages;
00198         
00205         var $locations = null;
00206         
00214         var $eventListeners = array();
00215         
00219         var $prefs = array(
00220                 'show_result_stats'=>1, // The result statistics (e.g. found x of y records in table z)
00221                 'show_jump_menu'=>1,    // The drop-down menu that allows you to "jump" to any record in the found set.
00222                 'show_result_controller'=>1,    // Next, previous, page number .. links...
00223                 'show_table_tabs'=>1,                   // Details, List, Find, etc...
00224                 'show_actions_menu'=>1,                 // New record, Show all, delete, etc...
00225                 'show_logo'=>1,                                 // Show logo at top right of app
00226                 'show_tables_menu'=>1,                  // The tabs to select a table.
00227                 'show_search'=>1,                               // Show search field in upper right.
00228                 'show_record_actions'=>1,               // Show actions related to particular record
00229                 'show_recent_records_menu'=>1,  // Menu to jump to recently visited record (deprecated)
00230                 'show_bread_crumbs' => 1,               // Bread crumbs at top of page to show where you are
00231                 'show_record_tabs' => 1,                // View, Edit, Translate, History, etc...
00232                 'show_record_tree' => 1,                // Tree to navigate the relationships of this record.
00233                 'list_view_scroll_horizontal'=>1, // Whether to scroll list horizontal if it exceeds page width
00234                 'list_view_scroll_vertical'=>1  // Whether to scroll list vertical if it exceeds page height.
00235         
00236         );
00237         
00243         var $tableNamesUsed = array();
00244         
00248         var $main_content_only = false;
00249                 // IF true then output only includes main content - not the 
00250                 // surrounding frame.
00251         
00258         var $delegate = -1;
00259         
00260         
00261         
00265         var $errors=array();
00266         
00270         var $messages = array();
00271         
00275         var $debugLog = array();
00276         
00280         var $authenticationTool = null;
00281         
00288         var $headContent=array();
00289         
00295         var $mysqlVersion = null;
00296         
00297         
00298         
00299         // @{
00322          var $_locales = array(
00323                 'zh_CN'=>'zh',
00324                 'zh_TW'=>'zt',
00325                 'zh_HK'=>'zt',
00326                 'en_US'=>'en'
00327         );
00328         
00338         var $_languages = array(
00339                 'zt'=>'zh'
00340         );
00341         
00368         function getLanguage($langCode){
00369                 if ( isset($this->_languages[$langCode]) ){
00370                         return $this->_languages[$langCode];
00371                 } else {
00372                         return $langCode;
00373                 }
00374         }
00375         
00394         function getLanguageCode($locale){
00395                 if ( isset($this->_locales[$locale]) ) return $this->_locales[$locale];
00396                 else {
00397                         list($langCode) = explode('_', $locale);
00398                         return $langCode;
00399                 }
00400         }
00401         
00431         function getAvailableLanguages(){
00432                 $langs = array_keys($this->_conf['languages']);
00433                 if ( @$this->_conf['default_language'] ) $langs[] = $this->_conf['default_language'];
00434                 else $langs[] = 'en';
00435                 $out = array();
00436                 foreach ($langs as $lang){
00437                         $out[$this->getLanguage($lang)] = true;
00438                 }
00439                 return array_keys($out);
00440                 
00441         }
00442         
00443         
00444         // @}
00445         // END LANGUAGES
00446         
00447         
00448         // @{
00459         function db(){ return $this->_db;}
00460         
00464         var $_conf;
00465         
00469         function Dataface_Application($conf = null){
00470                 $this->sessionCookieKey = md5(DATAFACE_SITE_URL.'#'.__FILE__);
00471                 $this->_baseUrl  = $_SERVER['PHP_SELF'];
00472                 if ( !is_array($conf) ) $conf = array();
00473                 if ( is_readable(DATAFACE_SITE_PATH.'/conf.ini') ){
00474                         $conf = array_merge(parse_ini_file(DATAFACE_SITE_PATH.'/conf.ini', true), $conf);
00475                         if ( @$conf['__include__'] ){
00476                                 $includes = array_map('trim',explode(',', $conf['__include__']));
00477                                 foreach ($includes as $i){
00478                                         if ( is_readable($i) ){
00479                                                 $conf = array_merge($conf, parse_ini_file($i, true));
00480                                         }
00481                                 }
00482                         }
00483                 }
00484                 
00485                 
00486                 
00487                 if ( !isset( $conf['_tables'] ) ){
00488                         throw new Exception('Error loading config file.  No tables specified.', E_USER_ERROR);
00489 
00490                 }
00491 
00492                 
00493                 
00494                 if ( isset( $conf['db'] ) and is_resource($conf['db']) ){
00495                         $this->_db = $conf['db'];
00496                 } else {
00497                         if ( !isset( $conf['_database'] ) ){
00498                                 throw new Exception('Error loading config file. No database specified.', E_USER_ERROR);
00499 
00500                         }
00501                         $dbinfo =& $conf['_database'];
00502                         if ( !is_array( $dbinfo ) || !isset($dbinfo['host']) || !isset( $dbinfo['user'] ) || !isset( $dbinfo['password'] ) || !isset( $dbinfo['name'] ) ){
00503                                 throw new Exception('Error loading config file.  The database information was not entered correctly.<br>
00504                                          Please enter the database information int its own section of the config file as follows:<br>
00505                                          <pre>
00506                                          [_database]
00507                                          host = localhost
00508                                          user = foo
00509                                          password = bar
00510                                          name = database_name
00511                                          </pre>', E_USER_ERROR);
00512 
00513                         }
00514                         if ( @$dbinfo['persistent'] ){
00515                                 $this->_db = mysql_pconnect( $dbinfo['host'], $dbinfo['user'], $dbinfo['password'] );
00516                         } else {
00517                                 $this->_db = mysql_connect( $dbinfo['host'], $dbinfo['user'], $dbinfo['password'] );
00518                         }
00519                         if ( !$this->_db ){
00520                                 throw new Exception('Error connecting to the database: '.mysql_error());
00521 
00522                         }
00523                         $this->mysqlVersion = mysql_get_server_info($this->_db);
00524                         mysql_select_db( $dbinfo['name'] ) or die("Could not select DB: ".mysql_error($this->_db));
00525                 }
00526                 if ( !defined( 'DATAFACE_DB_HANDLE') ) define('DATAFACE_DB_HANDLE', $this->_db);
00527                 
00528                 
00529                 if ( !is_array( $conf['_tables'] ) ){
00530                         throw new Exception("<pre>
00531                                 Error reading table information from the config file.  Please enter the table information in its own section
00532                                 of the ini file as follows:
00533                                 [_tables]
00534                                 table1 = Table 1 Label
00535                                 table2 = Table 2 Label
00536                                 </pre>");
00537 
00538                 }
00539                 
00540                 $this->_tables = $conf['_tables'];
00541                 
00542                 
00543                 
00544                 if ( count($this->_tables) <= 10 ){
00545                         $this->prefs['horizontal_tables_menu'] = 1;
00546                 }
00547                 
00548                 // We will register a _cleanup method to run after code execution is complete.
00549                 register_shutdown_function(array(&$this, '_cleanup'));
00550 
00551                 // Set up memcache if it is installed.
00552                 if ( DATAFACE_EXTENSION_LOADED_MEMCACHE ){
00553                         if ( isset($conf['_memcache']) ){
00554                                 if ( !isset($conf['_memcache']['host']) ){
00555                                         $conf['_memcache']['host'] = 'localhost';
00556                                 }
00557                                 if ( !isset($conf['_memcache']['port']) ){
00558                                         $conf['_memcache']['port'] = 11211;
00559                                 }
00560                                 $this->memcache = new Memcache;
00561                                 $this->memcache->connect($conf['_memcache']['host'], $conf['_memcache']['port']) or die ("Could not connect to memcache on port 11211");
00562                                 
00563                         }
00564                 }
00565                 
00566                 //
00567                 // -------- Set up the CONF array ------------------------
00568                 $this->_conf = $conf;
00569                 
00570                 if ( !isset($this->_conf['_disallowed_tables']) ){
00571                         $this->_conf['_disallowed_tables'] = array();
00572                 }
00573                 
00574                 $this->_conf['_disallowed_tables']['history'] = '/__history$/';
00575                 $this->_conf['_disallowed_tables']['cache'] = '__output_cache';
00576                 $this->_conf['_disallowed_tables']['dataface'] = '/^dataface__/';
00577                 if ( !@$this->_conf['_modules'] or !is_array($this->_conf['_modules']) ){
00578                         $this->_conf['_modules'] = array();
00579                 }
00580                 
00581                 // Include XataJax module always.
00582                 $mods = array('modules_XataJax'=>'modules/XataJax/XataJax.php');
00583                 foreach ($this->_conf['_modules'] as $k=>$v){
00584                         $mods[$k] = $v;
00585                 }
00586                 $this->_conf['_modules'] = $mods;
00587                 
00588                 
00589                 if ( isset($this->_conf['_modules'])  and count($this->_conf['_modules'])>0 ){
00590                         import('Dataface/ModuleTool.php');
00591                 }
00592 
00593                 if ( isset($this->_conf['languages']) ){
00594                         $this->_conf['language_labels'] = $this->_conf['languages'];
00595                         foreach ( array_keys($this->_conf['language_labels']) as $lang_code){
00596                                 $this->_conf['languages'][$lang_code] = $lang_code;
00597                         }
00598                 }
00599                 
00600                 if ( @$this->_conf['support_transactions'] ){
00601                         // We will support transactions
00602                         @mysql_query('SET AUTOCOMMIT=0', $this->_db);
00603                         @mysql_query('START TRANSACTION', $this->_db);
00604                 
00605                 }
00606                 if ( !isset($this->_conf['default_ie']) ) $this->_conf['default_ie'] = 'ISO-8859-1';
00607                 if ( !isset($this->_conf['default_oe']) ) $this->_conf['default_oe'] = 'ISO-8859-1';
00608                 if ( isset( $this->_conf['multilingual_content']) || isset($this->_conf['languages']) ){
00609                         $this->_conf['oe'] = 'UTF-8';
00610                         $this->_conf['ie'] = 'UTF-8';
00611                         
00612                         if (function_exists('mb_substr') ){
00613                                 // The mbstring extension is loaded
00614                                 ini_set('mbstring.internal_encoding', 'UTF-8');
00615                                 //ini_set('mbstring.encoding_translation', 'On');
00616                                 ini_set('mbstring.func_overload', 7);
00617                                 
00618                         }
00619                         
00620                         if ( !isset($this->_conf['default_language']) ){
00621                                 if ( count($this->_conf['languages']) > 0 )
00622                                         $this->_conf['default_language'] = reset($this->_conf['languages']);
00623                                         
00624                                 else 
00625                                         $this->_conf['default_language'] = 'en';
00626                                         
00627                         }
00628                         
00629                 } else {
00630                         $this->_conf['oe'] = $this->_conf['default_oe'];
00631                         $this->_conf['ie'] = $this->_conf['default_ie'];
00632                 }
00633                 
00634                 if ( $this->_conf['oe'] == 'UTF-8' ){
00635                         $res = mysql_query('set character_set_results = \'utf8\'', $this->_db);
00636                         mysql_query("SET NAMES utf8", $this->_db);
00637                 }
00638                 if ( $this->_conf['ie'] == 'UTF-8' ){
00639                         $res = mysql_query('set character_set_client = \'utf8\'', $this->_db);
00640                         
00641                 }
00642                 
00643                 
00644                 if ( isset($this->_conf['use_cache']) and $this->_conf['use_cache'] and !defined('DATAFACE_USE_CACHE') ){
00645                         define('DATAFACE_USE_CACHE', true);
00646                 }
00647                 
00648                 if ( isset($this->_conf['debug']) and $this->_conf['debug'] and !defined('DATAFACE_DEBUG') ){
00649                         define('DATAFACE_DEBUG', true);
00650                 } else if ( !defined('DATAFACE_DEBUG') ){
00651                         define('DATAFACE_DEBUG',false);
00652                 }
00653                 
00654                 if ( !@$this->_conf['config_storage'] ) $this->_conf['config_storage'] = DATAFACE_DEFAULT_CONFIG_STORAGE;
00655                         // Set the storage type for config information.  It can either be stored in ini files or
00656                         // in the database.  Database will give better performance, but INI files may be simpler
00657                         // to manage for simple applications.
00658                 
00659                 if ( !isset($this->_conf['garbage_collector_threshold']) ){
00665                         $this->_conf['garbage_collector_threshold'] = 10*60;
00666                 }
00667                 
00668                 if ( !isset($this->_conf['multilingual_content']) ) $this->_conf['multilingual_content'] = false;
00669                         // whether or not the application will use multilingual content.
00670                         // multilingual content enables translated versions of content to be stored in
00671                         // tables using naming conventions.
00672                         // Default to false because this takes a performance hit (sql queries take roughly twice
00673                         // as long because they have to be parsed first.
00674                 
00675                 if ( !isset($this->_conf['cookie_prefix']) ) $this->_conf['cookie_prefix'] = 'dataface__';
00676                 
00677                 if ( !isset($this->_conf['security_level']) ){
00678                         // Default security is strict if security is not specified.  This change is effectivce
00679                         // for Dataface 0.6 .. 0.5.3 and earlier had a loose permissions model by default that 
00680                         // could be tightened using delegate classes.
00681                         $this->_conf['security_level'] = 0; //DATAFACE_STRICT_PERMISSIONS;
00682                 }
00683                 
00684                 
00685                 if ( !isset($this->_conf['default_action']) ){
00686                         // The default action defines the action that should be set if no
00687                         // other action is specified.
00688                         $this->_conf['default_action'] = 'list';
00689                 }
00690                 
00691                 if ( !isset($this->_conf['default_browse_action']) ){
00692                         $this->_conf['default_browse_action'] = 'view';
00693                 }
00694                 
00695                 
00696                 if ( !isset($this->_conf['default_mode'] ) ) $this->_conf['default_mode'] = 'list';
00697                 
00698                 if ( !isset($this->_conf['default_limit']) ){
00699                         $this->_conf['default_limit'] = 30;
00700                 }
00701                 
00702                 if ( !isset($this->_conf['default_table'] ) ){
00703                         // The default table is the table that is used if no other table is specified.
00704                         foreach ($this->_tables as $key=>$value){
00705                                 $this->_conf['default_table'] = $key;
00706                                 
00707                                 break;
00708                         }
00709                 }
00710                 
00711                 if ( !isset($this->_conf['auto_load_results']) ) $this->_conf['auto_load_results'] = false;
00712                 
00713                 if ( !isset( $this->_conf['cache_dir'] ) ){
00714                         if ( ini_get('upload_tmp_dir') ) $this->_conf['cache_dir'] = ini_get('upload_tmp_dir');
00715                         else $this->_conf['cache_dir'] = '/tmp';
00716                 }
00717                 
00718                 if ( !isset( $this->_conf['default_table_role'] ) ){
00719                         
00720                         if ( $this->_conf['security_level'] >= DATAFACE_STRICT_PERMISSIONS ){
00721                                 $this->_conf['default_table_role'] = 'NO ACCESS';
00722                         } else {
00723                                 $this->_conf['default_table_role'] = 'ADMIN';
00724                         }
00725                         
00726                 }
00727                 
00728                 if ( !isset( $this->_conf['default_field_role'] ) ){
00729                         if ( $this->_conf['security_level'] >= DATAFACE_STRICT_PERMISSIONS ){
00730                                 $this->_conf['default_field_role'] = 'NO ACCESS';
00731                         } else {
00732                                 $this->_conf['default_field_role'] = 'ADMIN';
00733                                 
00734                         }
00735                 }
00736                 
00737                 if ( !isset( $this->_conf['default_relationship_role'] ) ){
00738                         if ( $this->_conf['security_level'] >= DATAFACE_STRICT_PERMISSIONS ){
00739                                 $this->_conf['default_relationship_role'] = 'READ ONLY';
00740                         } else {
00741                                 $this->_conf['default_relationship_role'] = 'ADMIN';
00742                                 
00743                         }
00744                 }
00745                 
00746                 if ( !isset( $this->_conf['languages'] ) ) $this->_conf['languages'] = array('en');
00747                 else if ( !is_array($this->_conf['languages']) ) $this->_conf['languages'] = array($this->_conf['languages']);
00748                 
00749                 if ( isset($this->_conf['_language_codes']) ){
00750                         $this->_languages = array_merge($this->_languages, $this->_conf['_language_codes']);
00751                 }
00752                 if ( isset($this->_conf['_locales']) ){
00753                         $this->_locales = array_merge($this->_locales, $this->_conf['_locales']);
00754                 }
00755                 
00756                 // Set the language.
00757                 // Language is stored in a cookie.  It can be changed by passing the -lang GET var with the value
00758                 // of a language.  e.g. fr, en, cn
00759                 if ( !isset( $this->_conf['default_language'] ) ) $this->_conf['default_language'] = 'en';
00760                 $prefix = $this->_conf['cookie_prefix'];
00761                 //print_r($_COOKIE);
00762                 if ( isset($_REQUEST['--lang']) ){
00763                         $_REQUEST['--lang'] = basename($_REQUEST['--lang']);
00764                         $this->_conf['lang'] = $_REQUEST['--lang'];
00765                 } else if ( isset( $_REQUEST['-lang'] ) ){
00766                         $_REQUEST['-lang'] = basename($_REQUEST['-lang']);
00767                         $this->_conf['lang'] = $_REQUEST['-lang'];
00768                         if ( @$_COOKIE[$prefix.'lang'] !== $_REQUEST['-lang'] ){
00769                                 setcookie($prefix.'lang', $_REQUEST['-lang'], null, '/');
00770                         }
00771                 } else if (isset( $_COOKIE[$prefix.'lang']) ){
00772                         $this->_conf['lang'] = $_COOKIE[$prefix.'lang'];
00773                 } else {
00774                         import('I18Nv2/I18Nv2.php');
00775                         $negotiator = I18Nv2::createNegotiator($this->_conf['default_language'], 'UTF-8');
00776                         $this->_conf['lang'] = $this->getLanguageCode(
00777                                 $negotiator->getLocaleMatch(
00778                                         $this->getAvailableLanguages()
00779                                 )
00780                         );
00781                         setcookie($prefix.'lang', $this->_conf['lang'], null, '/');
00782                 }
00783                 
00784                 $this->_conf['lang'] = basename($this->_conf['lang']);
00785                 
00786                 
00787                 // Set the mode (edit or view)
00788                 if ( isset($_REQUEST['-usage_mode'] )){
00789                         $this->_conf['usage_mode'] = $_REQUEST['-usage_mode'];
00790                         if (@$_COOKIE[$prefix.'usage_mode'] !== $_REQUEST['-usage_mode']){
00791                                 setcookie($prefix.'usage_mode', $_REQUEST['-usage_mode'], null, '/');
00792                         }
00793                 } else if ( isset( $_COOKIE[$prefix.'usage_mode'] ) ){
00794                         $this->_conf['usage_mode'] = $_COOKIE[$prefix.'usage_mode'];
00795                 } else if ( !isset($this->_conf['usage_mode']) ){
00796                         $this->_conf['usage_mode'] = 'view';
00797                 }
00798                 
00799                 define('DATAFACE_USAGE_MODE', $this->_conf['usage_mode']);
00800                 
00801                 if ( @$this->_conf['enable_workflow'] ){
00802                         import('Dataface/WorkflowTool.php');
00803                 }
00804                 
00805                 
00806                 
00807                 
00808                 // ------- Set up the current query ---------------------------------
00809                 
00810                 if ( isset($_REQUEST['__keys__']) and is_array($_REQUEST['__keys__']) ){
00811                         $query = $_REQUEST['__keys__'];
00812                         foreach ( array_keys($_REQUEST) as $key ){
00813                                 if ( $key{0} == '-' and !in_array($key, array('-search','-cursor','-skip','-limit'))){
00814                                         $query[$key] = $_REQUEST[$key];
00815                                 }
00816                         }
00817                 } else {
00818                         $query = array_merge($_GET, $_POST);
00819                 }
00820                 if ( @$query['-action'] ){
00821                         $query['-action'] = trim($query['-action']);
00822                         if ( !preg_match('/^[a-zA-Z0-9_]+$/', $query['-action']) ){
00823                                 throw new Exception("Illegal action name.");
00824                         }
00825                         $query['-action'] = basename($query['-action']);
00826                 }
00827                 if ( @$query['-table'] ){
00828                         $query['-table'] = trim($query['-table']);
00829                         if ( !preg_match('/^[a-zA-Z0-9_]+$/', $query['-table']) ){
00830                                 throw new Exception("Illegal table name.");
00831                         }
00832                         $query['-table'] = basename($query['-table']);
00833                 }
00834                 if ( @$query['-lang'] ){
00835                         $query['-lang'] = trim($query['-lang']);
00836                         if ( !preg_match('/^[a-zA-Z0-9]{2}$/', $query['-lang']) ){
00837                                 throw new Exception("Illegal language code: ".$query['-lang']);
00838                         }
00839                         $query['-lang'] = basename($query['-lang']);
00840                 }
00841                 
00842                 if ( @$query['--lang'] ){
00843                         $query['--lang'] = trim($query['--lang']);
00844                         if ( !preg_match('/^[a-zA-Z0-9]{2}$/', $query['--lang']) ){
00845                                 throw new Exception("Illegal language code: ".$query['--lang']);
00846                         }
00847                         $query['--lang'] = basename($query['--lang']);
00848                 }
00849                 
00850                 if ( @$query['-theme'] ){
00851                         $query['-theme'] = trim($query['-theme']);
00852                         if ( !preg_match('/^[a-zA-Z0-9_]+$/', $query['-theme']) ){
00853                                 throw new Exception("Illegal theme name.");
00854                         }
00855                         $query['-theme'] = basename($query['-theme']);
00856                 }
00857                 
00858                 if ( @$query['-cursor']){
00859                         $query['-cursor'] = intval($query['-cursor']);
00860                 }
00861                 if ( @$query['-limit'] ){
00862                         $query['-limit'] = intval($query['-limit']);
00863                 }
00864                 if ( @$query['-skip'] ){
00865                         $query['-skip'] = intval($query['-skip']);
00866                 }
00867                 if ( @$query['-related-limit'] ){
00868                         $query['-related-limit'] = intval($query['-related-limit']);
00869                 }
00870                 if ( @$query['-relationship'] ){
00871                         if ( !preg_match('/^[a-zA-Z0-9_]+$/', $query['-relationship']) ){
00872                                 throw new Exception("Illegal relationship name.");
00873                         }
00874                 }
00875                 
00876                 
00877                 
00878                 
00879                 $this->rawQuery = $query;
00880                 
00881                 if ( !isset( $query['-table'] ) ) $query['-table'] = $this->_conf['default_table'];
00882                 $this->_currentTable = $query['-table'];
00883                 
00884                 
00885                 if ( !@$query['-action'] ) {
00886                         $query['-action'] = $this->_conf['default_action'];
00887                         $this->_conf['using_default_action'] = true;
00888                 }
00889                 
00890                 $query['--original_action'] = $query['-action'];
00891                 if ( $query['-action'] == 'browse') {
00892                         if ( isset($query['-relationship']) ){
00893                                 $query['-action'] = 'related_records_list';
00894                         } else if ( isset($query['-new']) and $query['-new']) {
00895                                 $query['-action'] = 'new';
00896                         } else {
00897                                 $query['-action'] = $this->_conf['default_browse_action']; // for backwards compatibility to 0.5.x
00898                         }
00899                 } else if ( $query['-action'] == 'find_list' ){
00900                         $query['-action'] = 'list';
00901                 }
00902                 if ( !isset( $query['-cursor'] ) ) $query['-cursor'] = 0;
00903                 if ( !isset( $query['-skip'] ) ) $query['-skip'] = 0;
00904                 if ( !isset( $query['-limit'] ) ) $query['-limit'] = $this->_conf['default_limit'];
00905                 
00906                 if ( !isset( $query['-mode'] ) ) $query['-mode'] = $this->_conf['default_mode'];
00907                 $this->_query =& $query;
00908                 
00909                 
00910                 if ( isset( $query['--msg'] ) ) {
00911                         $query['--msg'] = preg_replace('#<[^>]*>#','', $query['--msg']);
00912                         if ( preg_match('/^@@$/', $query['--msg']) ){
00913                                 
00914                                 if ( @$_SESSION['--msg'] ){
00915                                         $this->addMessage(@$_SESSION['--msg']);
00916                                         unset($_SESSION['--msg']);
00917                                 }
00918                         } else {
00919                                 
00920                                 $this->addMessage($query['--msg']);
00921                         }
00922                 }
00923                 
00924                 
00925                 
00926                 
00927                 if ( isset($query['--error']) and trim($query['--error']) ){
00928                         $query['--error'] = preg_replace('#<[^>]*>#','', $query['--error']);
00929                         $this->addError(PEAR::raiseError($query['--error']));
00930                 }
00931                 
00932                 // Now allow custom setting of theme
00933                 if ( isset($query['-theme']) ){
00934                         if ( !isset($this->_conf['_themes']) ) $this->_conf['_themes'] = array();
00935                         $this->_conf['_themes'][basename($query['-theme'])] = 'themes/'.basename($query['-theme']);
00936                 }
00937                 
00938                 // Check to see if we should set a custom default preview length
00939                 if ( isset($query['--default-preview-length']) ){
00940                         $len = intval($query['--default-preview-length']);
00941                         if ( $len > 0 && !defined('XATAFACE_DEFAULT_PREVIEW_LENGTH') ){
00942                                 define('XATAFACE_DEFAULT_PREVIEW_LENGTH', $len);
00943                         }
00944                 }
00945                 
00946                 
00947 
00948         }
00949         
00950         
00969         public static function &getInstance($conf=null){
00970                 static $instance = array();
00971                 //static $blobRequestCount = 0;
00972                 if ( !isset( $instance[0] ) ){
00973                         $instance[0] = new Dataface_Application($conf);
00974                         if ( !defined('DATAFACE_APPLICATION_LOADED') ){
00975                                 define('DATAFACE_APPLICATION_LOADED', true);
00976                         }
00977                 }
00978                 
00979                 return $instance[0];
00980         }
00981         
00982         
00983         
00995         function &conf(){       
00996                 static $loaded = false;
00997                 if ( !$loaded ){
00998                         $loaded = true;
00999                         $del = $this->getDelegate();
01000                         if ( isset($del) and method_exists($del,'conf') ){
01001                                 $conf = $del->conf();
01002                                 if ( !is_array($conf) ) throw new Exception("The Application Delegate class defined a method 'conf' that must return an array, but returns something else.", E_USER_ERROR);
01003                                 foreach ( $conf as $key=>$val){
01004                                         if ( isset($this->_conf[$key]) ){
01005                                                 if ( is_array($this->_conf[$key]) and is_array($val) ){
01006                                                         $this->_conf[$key] = array_merge($this->_conf[$key], $val);
01007                                                 } else {
01008                                                         $this->_conf[$key] = $val;
01009                                                 }
01010                                         } else {
01011                                                 $this->_conf[$key] = $val;
01012                                         }
01013                                 }
01014                                 
01015                         }
01016                         
01017                 }
01018                 return $this->_conf;
01019                 
01020         }
01021         
01022         
01027         function getMySQLMajorVersion(){
01028                 if ( !isset($this->mysqlVersion) ){
01029                         $this->mysqlVersion = mysql_get_server_info($this->_db);
01030                 }
01031                 list($mv) = explode('.',$this->mysqlVersion);
01032                 return intval($mv);
01033         }
01034         
01035         
01045         function getSiteTitle(){
01046                 $query =& $this->getQuery();
01047                 if ( isset($this->_conf['title']) ) {
01048                         try {
01049                                 return $this->parseString($this->_conf['title']);
01050                         } catch (Exception $ex){
01051                                 return $this->_conf['title'];
01052                         }
01053                 } else if ( ($record = $this->getRecord()) && $query['-mode'] == 'browse'  ){
01054                         return $record->getTitle().' - Dataface Application';
01055                 } else {
01056                         try {
01057                                 return $this->parseString('{$tableLabel} - Dataface Application');
01058                         } catch (Exception $ex){
01059                                 $tableLabel = Dataface_Table::loadTable($query['-table'])->getLabel();
01060                                 return $tableLabel.' - Dataface Application';
01061                         }
01062                 }
01063         
01064         }
01065         
01066         
01067         // @}
01068         // END CONFIGURATION
01069         
01070         
01071         // @{
01094         function &getQuery(){
01095                 return $this->_query;
01096         }
01097         
01121         function &getQueryParam($key){
01122                 if ( isset( $this->_query['-'.$key] ) ){
01123                         return $this->_query['-'.$key];
01124                 } else {
01125                         $null = null;
01126                         return $null;
01127                 }
01128         }
01129         
01134         function &getResultSet(){
01135                 if ( $this->queryTool === null ){
01136                         import('Dataface/QueryTool.php');
01137                         $this->queryTool = Dataface_QueryTool::loadResult($this->_query['-table'], $this->db(), $this->_query);
01138                 }
01139                 return $this->queryTool;
01140         
01141         }
01142         
01187         function &getRecord(){
01188                 $null = null;
01189                 if ( $this->currentRecord === null ){
01190                         $query =& $this->getQuery();
01191                         if ( @$query['--no-query'] ){
01192                                 $null = null;
01193                                 return $null;
01194                         }
01195                         $q=array();
01196                         if ( isset($_REQUEST['__keys__']) and is_array($_REQUEST['__keys__']) ){
01197                                 foreach ($_REQUEST['__keys__'] as $key=>$val) $q[$key] = '='.$val;
01198                                 $this->currentRecord = df_get_record($query['-table'], $q);
01199                         } else if ( isset($_REQUEST['-__keys__']) and is_array($_REQUEST['-__keys__']) ){
01200                                 foreach ($_REQUEST['-__keys__'] as $key=>$val) $q[$key] = '='.$val;
01201                                 $this->currentRecord = df_get_record($query['-table'], $q);
01202                         } else if ( isset($_REQUEST['--__keys__']) and is_array($_REQUEST['--__keys__']) ){
01203                                 foreach ($_REQUEST['--__keys__'] as $key=>$val) $q[$key] = '='.$val;
01204                                 $this->currentRecord = df_get_record($query['-table'], $q);
01205                         } else if ( isset($_REQUEST['--recordid']) ){
01206                                 $this->currentRecord = df_get_record_by_id($_REQUEST['--recordid']);
01207                         } else if ( isset($_REQUEST['-recordid']) ){
01208                                 $this->currentRecord = df_get_record_by_id($_REQUEST['-recordid']);
01209                         } else {
01210                                 $rs = $this->getResultSet();
01211                                 $this->currentRecord = $rs->loadCurrent();
01212                         }
01213                         if ( $this->currentRecord === null ) $this->currentRecord = -1;
01214                 }
01215                 if ( $this->currentRecord === -1 || !$this->currentRecord ) return $null;
01216                 return $this->currentRecord;
01217         }
01218         
01226         function recordLoaded(){
01227                 return ( $this->currentRecord !== null);
01228         }
01229          
01230          
01237         function &getAction(){
01238                 import('Dataface/ActionTool.php');
01239                 $actionTool = Dataface_ActionTool::getInstance();
01240                 return $actionTool->getAction(array('name'=>$this->_query['-action']));
01241         }
01242          
01243         // @}
01244         // END Request Context
01245         
01246         // @{
01269         function saveMessage($str){
01270                 $_SESSION['--msg'] = $str;
01271         }
01272         
01282         function enableSessions(){
01283                 setcookie($this->sessionCookieKey, 1, 0, DATAFACE_SITE_URL);
01284         }
01285         
01295         function disableSessions(){
01296                 setcookie($this->sessionCookieKey, 1, time()-3600*25, DATAFACE_SITE_URL);
01297         }
01298         
01307         function sessionEnabled(){
01308                 return @$_COOKIE[$this->sessionCookieKey];
01309         }
01310         
01322         function startSession($conf=null){
01323                 //echo "In startSession()";
01324                 
01325                 if ( session_id() == "" ){
01326                         $this->enableSessions();
01327                         if ( !isset($conf) ){
01328                                 if ( isset($this->_conf['_auth']) ) $conf = $this->_conf['_auth'];
01329                                 else $conf = array();
01330                         }
01331                         
01332                         $delegate =& $this->getDelegate();
01333                         if ( isset($delegate) and method_exists($delegate, 'startSession') ){
01334                                 $delegate->startSession($conf);
01335                         } else {
01336                                 
01337                                 // path for cookies
01338                                 $cookie_path = "/";
01339                                 if ( isset($conf['cookie_path']) ){
01340                                         $cookie_path = $conf['cookie_path'];
01341                                         if ( substr($cookie_path,0,4) == 'php:' ){
01342                                                 $cookie_path_expr = substr($cookie_path,4);
01343                                                 eval('$cookie_path = '.$cookie_path_expr.';');
01344                                         }
01345                                 }
01346                                 
01347                                 if ( $cookie_path{strlen($cookie_path)-1} != '/' ) $cookie_path .= '/';
01348                                 
01349                                 // timeout value for the cookie
01350                                 $cookie_timeout = (isset($conf['session_timeout']) ? intval($conf['session_timeout']) : 24*60*60);
01351                                 
01352                                 
01353                                 // timeout value for the garbage collector
01354                                 //   we add 300 seconds, just in case the user's computer clock
01355                                 //   was synchronized meanwhile; 600 secs (10 minutes) should be
01356                                 //   enough - just to ensure there is session data until the
01357                                 //   cookie expires
01358                                 $garbage_timeout = $cookie_timeout + 600; // in seconds
01359                                 
01360                                 // set the PHP session id (PHPSESSID) cookie to a custom value
01361                                 session_set_cookie_params($cookie_timeout, $cookie_path);
01362                                 
01363                                 // set the garbage collector - who will clean the session files -
01364                                 //   to our custom timeout
01365                                 ini_set('session.gc_maxlifetime', $garbage_timeout);
01366                                 if ( isset($conf['session_timeout']) and ini_get('session.save_handler') == 'files' ){
01367                                         // we need a distinct directory for the session files,
01368                                         //   otherwise another garbage collector with a lower gc_maxlifetime
01369                                         //   will clean our files aswell - but in an own directory, we only
01370                                         //   clean sessions with our "own" garbage collector (which has a
01371                                         //   custom timeout/maxlifetime set each time one of our scripts is
01372                                         //   executed)
01373                                         strstr(strtoupper(substr(@$_SERVER["OS"], 0, 3)), "WIN") ? 
01374                                                 $sep = "\\" : $sep = "/";
01375                                         $sessdir = session_save_path(); //ini_get('session.save_path');
01376                                         $levels = '';
01377                                         if (strpos($sessdir, ";") !== FALSE){
01378                                                 $levels = substr($sessdir, 0, strpos($sessdir, ";")).';';
01379                                                  $sessdir = substr($sessdir, strpos($sessdir, ";")+1);
01380                                         }
01381                                         if ( !$sessdir ) $sessdir = sys_get_temp_dir(); //'/tmp';
01382                                         if ( $sessdir and $sessdir{strlen($sessdir)-1} == '/' ) $sessdir = substr($sessdir,0, strlen($sessdir)-1);
01383                                         
01384                                         if ( @$conf['subdir'] ) $subdir = $conf['subdir'];
01385                                         else $subdir = md5(DATAFACE_SITE_PATH);
01386                                         if ( !$subdir ) $subdir = 'dataface';
01387                                         $sessdir .= "/".$subdir;
01388                                         
01389                         
01390                                         if (!is_dir($sessdir)) { 
01391                                                 $res = @mkdir($sessdir, 0777);
01392                                                 if ( !$res ){
01393                                                         error_log("Failed to create session directory '$sessdir' to store session files in ".__FILE__." on line ".__LINE__);
01394                                                         
01395                                                 }
01396                                         }
01397                                         if (is_dir($levels.$sessdir) ){
01398                                                 session_save_path($levels.$sessdir);
01399                                         }
01400                                 } else {
01401                                         // We need to set a unique session name if we're not changing the directory
01402                                         if ( !@$conf['session_name'] ){
01403                                                 $conf['session_name'] = md5(DATAFACE_SITE_PATH);
01404                                         }
01405                                 }
01406                                 if ( @$conf['session_name'] ) session_name($conf['session_name']);
01407                                 session_start();        // start the session
01408                                 header('P3P: CP="IDC DSP COR CURa ADMa OUR IND PHY ONL COM STA"');
01409                                 
01410                                 // This updates the session timeout on page load
01411                                 if ( isset($_COOKIE[session_name()]) ){
01412                                         setcookie(session_name(), $_COOKIE[session_name()], time() + $cookie_timeout, $cookie_path);
01413                                 }
01414                         }
01415                 } else {
01416                         //echo "Session already started";
01417                 }
01418                 
01419                 if ( isset( $_SESSION['--msg'] ) ){
01420                         $this->addMessage($_SESSION['--msg']);
01421                         unset($_SESSION['--msg']);
01422                 }
01423         
01424         
01425         }
01426         
01430         function writeSessionData(){
01431         
01432                 if ( isset($this->locations) ) $_SESSION['locations'] = serialize($this->locations);
01433         }
01434         
01438         function encodeLocation($url){
01439                 if ( !isset($this->locations) and isset($_SESSION['locations']) ) $this->locations = unserialize($_SESSION['locations']);
01440                 else if ( !isset($this->locations) ) $this->locations = array();
01441                 $key = md5($url);
01442                 $this->locations[$key] = $url;
01443                 return $key;
01444         }
01445         
01449         function decodeLocation($key){
01450                 if ( !isset($this->locations) and isset($_SESSION['locations']) ) $this->locations = unserialize($_SESSION['locations']);
01451                 else if ( !isset($this->locations) ) $this->locations = array();
01452                 
01453                 if ( isset($this->locations[$key]) ){
01454                         $url = $this->locations[$key];
01455                         unset($this->locations[$key]);
01456                         return $url;
01457                 
01458                 } else {
01459                         return null;
01460                 }
01461         
01462         }
01463          
01464          
01471         function &getAuthenticationTool(){
01472                 $null = null;
01473                 if ( !isset($this->authenticationTool) ){
01474                         
01475                         if ( isset($this->_conf['_auth']) ){
01476                                 import('Dataface/AuthenticationTool.php');
01477                                 $this->authenticationTool = Dataface_AuthenticationTool::getInstance($this->_conf['_auth']);
01478                         } else {
01479                                 return $null;
01480                         }
01481                 }
01482                         
01483                 return $this->authenticationTool;
01484         }
01485         
01486         
01487          
01488          
01489          
01490         // @}
01491         // END Session Handling
01492         //=====================================================================================================
01493         
01494         // @{
01524         function addHeadContent($content){
01525                 $this->headContent[] = $content;
01526         }
01527         
01528         
01549         function getNavItem($key, $label=null){
01550                 $del =& $this->getDelegate();
01551                 $override = array();
01552                 if ( isset($del) and method_exists($del, 'getNavItem') ){
01553                         try {
01554                                 $override = $del->getNavItem($key, $label?$label:$key);
01555                         } catch (Exception $ex){}
01556                 }
01557                 if ( !isset($override) ){
01558                         return $override;
01559                 }
01560                 return array_merge(array(
01561                         'href'=> DATAFACE_SITE_HREF.'?-table='.urlencode($key),
01562                         'label'=> $label ? $label:$key,
01563                         'selected' => $this->isNavItemSelected($key)
01564                 ), $override);
01565         }
01566         
01567         
01583         function isNavItemSelected($key){
01584                 $del =& $this->getDelegate();
01585                 if ( isset($del) and method_exists($del, 'isNavItemSelected') ){
01586                         try {
01587                                 return $del->isNavItemSelected($key);
01588                         } catch (Exception $ex){}
01589                 }
01590                 $query =& $this->getQuery();
01591                 return ($query['-table'] == $key);
01592         }
01593         
01594         
01595         
01606         function addError($err){
01607                 $this->errors[] = $err;
01608         }
01609         
01618         function numErrors(){ return count($this->errors); }
01619         
01627         function getErrors(){
01628                 return $this->errors;
01629         }
01630         
01639         function addMessage($msg){
01640                 $this->messages[] = $msg;
01641         }
01642         
01654         function getMessages(){
01655                 if ( trim(@$_SESSION['msg']) ){
01656                         array_push($this->messages, $_SESSION['msg']);
01657                         unset($_SESSION['msg']);
01658                 }
01659                 $msgs = $this->messages;
01660                 $response = $this->getResponse();
01661                 if ( @$response['--msg'] ){
01662                         array_push($msgs, $response['--msg']);
01663                 }
01664                 //print_r($msgs);
01665                 return $msgs;
01666         }
01667         
01672         function clearMessages(){
01673                 $this->messages = array();
01674         }
01675         
01680         function numMessages(){
01681                 $count = count($this->messages);
01682                 $response = $this->getResponse();
01683                 if ( @$response['--msg'] ) $count++;
01684                 return $count;
01685         }
01686         
01687         
01698         public static function &getResponse(){
01699                 static $response = 0;
01700                 if ( !$response ){
01701                         $response = array('--msg'=>'');
01702                 }
01703                 return $response;
01704         }
01705          
01706          
01707         // @}
01708         // END Template & UI Interaction
01709         //====================================================================================
01710         
01711         // {@
01729         function fireEvent($name, $params=null){
01730                 $listeners = $this->getEventListeners($name);
01731                 foreach ($listeners as $listener){
01732                         $res = call_user_func($listener, $params);
01733                         if ( PEAR::isError($res) ) return $res;
01734                 }
01735                 return true;
01736         }
01737         
01748         function registerEventListener($name, $callback){
01749                 if ( !isset($this->eventListeners[$name]) ) $this->eventListeners[$name] = array();
01750                 $this->eventListeners[$name][] = $callback;
01751         }
01752         
01753         
01760         function unregisterEventListener($name, $callback){
01761                 if ( isset($this->eventListeners[$name]) ){
01762                         $listeners =& $this->eventListeners[$name];
01763                         foreach ( $listeners as $key=>$listener ){
01764                                 if ( $listener == $callback ) unset($listeners[$key]);
01765                         }
01766                 }
01767         }
01768         
01774         function getEventListeners($name=null){
01775                 if ( !isset($name) ) return $this->eventListeners;
01776                 else if (isset($this->eventListeners[$name])){
01777                         return $this->eventListeners[$name];
01778                 } else {
01779                         return array();
01780                 }
01781         }
01782         
01783          
01784          
01785         // @}
01786         // END Event Handling
01787         //=====================================================================================
01788         
01789         
01790         
01791         // @{
01824         function handleRequest($disableCache=false){
01825                 
01826                 
01827                 if ( !$disableCache and (@$_GET['-action'] != 'getBlob') and isset( $this->_conf['_output_cache'] ) and @$this->_conf['_output_cache']['enabled'] and count($_POST) == 0){
01828                         import('Dataface/OutputCache.php');
01829                         $oc = new Dataface_OutputCache($this->_conf['_output_cache']);
01830                         $oc->ob_start();
01831                         
01832                 }
01833                 import('Dataface/ActionTool.php');
01834                 import('Dataface/PermissionsTool.php');
01835                 import('Dataface/Table.php');
01836                 
01837                 if ( isset($this->_conf['_modules']) and count($this->_conf['_modules']) > 0 ){
01838                         $mt = Dataface_ModuleTool::getInstance();
01839                         foreach ($this->_conf['_modules'] as $modname=>$modpath){
01840                                 $mt->loadModule($modname);
01841                                 
01842                         }
01843                 }
01844                 
01845                 $this->fireEvent('beforeHandleRequest');
01846                 $applicationDelegate = $this->getDelegate();
01847                 if ( isset($applicationDelegate) and method_exists($applicationDelegate, 'beforeHandleRequest') ){
01848                         // Do whatever we need to do before the request is handled.
01849                         $applicationDelegate->beforeHandleRequest();
01850                 }
01851                 
01852                 // Set up security filters
01853                 $query =& $this->getQuery();
01854                 $table = Dataface_Table::loadTable($query['-table']);
01855 
01856                 //$table->setSecurityFilter();
01857                 /*
01858                  * Set up some preferences for the display of the application.
01859                  * These can be overridden by the getPreferences() method in the
01860                  * application delegate class.
01861                  */
01862                 if ( isset($this->_conf['_prefs']) and is_array($this->_conf['_prefs']) ){
01863                         $this->prefs = array_merge($this->prefs,$this->_conf['_prefs']);
01864                 }
01865                 if ( @$this->_conf['hide_nav_menu'] ){
01866                         $this->prefs['show_tables_menu'] = 0;
01867                 }
01868                 
01869                 if ( @$this->_conf['hide_view_tabs'] ){
01870                         $this->prefs['show_table_tabs'] = 0;
01871                 }
01872                 
01873                 if ( @$this->_conf['hide_result_controller'] ){
01874                         $this->prefs['show_result_controller'] = 0;
01875                 }
01876                 
01877                 if ( @$this->_conf['hide_table_result_stats'] ){
01878                         $this->prefs['show_result_stats'] = 0;
01879                 }
01880                 
01881                 if ( @$this->_conf['hide_search'] ){
01882                         $this->prefs['show_search'] = 0;
01883                 }
01884                 
01885                 if ( !isset($this->prefs['disable_ajax_record_details']) ){
01886                         $this->prefs['disable_ajax_record_details'] = 1;
01887                 }
01888                 
01889                 if ( $query['-action'] == 'login_prompt' ) $this->prefs['no_history'] = 1;
01890                 
01891                 
01892                 if ( isset($applicationDelegate) and method_exists($applicationDelegate, 'getPreferences') ){
01893                         $this->prefs = array_merge($this->prefs, $applicationDelegate->getPreferences());
01894                 }
01895                 $this->prefs = array_map('intval', $this->prefs);
01896                 
01897                 // Check to make sure that this table hasn't been disallowed
01898                 $disallowed = false;
01899                 if ( isset($this->_conf['_disallowed_tables']) ){
01900                         foreach ( $this->_conf['_disallowed_tables'] as $name=>$pattern ){
01901                                 if ( $pattern{0} == '/' and preg_match($pattern, $query['-table']) ){
01902                                         $disallowed = true;
01903                                         break;
01904                                 } else if ( $pattern == $query['-table'] ){
01905                                         $disallowed = true;
01906                                         break;
01907                                 }
01908                         }
01909                 }
01910                 
01911                 if ( $disallowed and isset($this->_conf['_allowed_tables']) ){
01912                         foreach ($this->_conf['_allowed_tables'] as $name=>$pattern ){
01913                                 if ( $pattern{0} == '/' and preg_match($pattern, $query['-table']) ){
01914                                         $disallowed = false;
01915                                         break;
01916                                 } else if ( $pattern == $query['-table'] ){
01917                                         $disallowed = false;
01918                                         break;
01919                                 }
01920                         }
01921                 }
01922                 
01923                 
01924                 if ( $disallowed ){
01925                         return Dataface_Error::permissionDenied(
01926                                 Dataface_LanguageTool::translate(
01927                                         /*i18n id*/
01928                                         "Permission Denied. This table has been disallowed in the conf.ini file",
01929                                         /* default error message */
01930                                         "Permission denied because this table has been disallowed in the conf.ini file '"
01931                                 )
01932                         );
01933                         
01934                 }
01935                 
01936                 
01937                 $actionTool = Dataface_ActionTool::getInstance();
01938                 
01939                 //if ( $this->_conf['multilingual_content'] ){
01940                         //import('I18Nv2/I18Nv2.php');
01941                 //I18Nv2::autoConv();
01942         //}
01943                 
01944                 $params = array(
01945                         'table'=>$query['-table'],
01946                         'name'=>$query['-action']);
01947                 if ( strpos($query['-action'], 'custom_') === 0 ){
01948                         $action = array(
01949                                 'name' => $query['-action'],
01950                                 'page' => substr($query['-action'], 7),
01951                                 'permission' => 'view',
01952                                 'mode' => 'browse',
01953                                 'custom' => true
01954                                 );
01955                 } else {
01956                         $action = $actionTool->getAction($params);
01957                         if ( is_array($action)  and @$action['related'] and @$query['-relationship'] and preg_match('/relationships\.ini/', @$action['allow_override']) ){
01958                                 // This action is to be performed on the currently selected relationship.
01959                                 $raction = $table->getRelationshipsAsActions(array(), $query['-relationship']);
01960                                 if ( is_array($raction) ){
01961                                         $action = array_merge($action,$raction); 
01962                                 }
01963                         }
01964                         if ( is_array($action) and isset($action['delegate']) ){
01965                                 $params['name'] = $query['-action'] = $action['delegate'];
01966                                 $tmp = $actionTool->getActions($params);
01967                                 unset($action);
01968                                 $action =& $tmp;
01969                                 unset($tmp);
01970                         } 
01971                         if ( is_array($action) and isset($action['auth_type']) ){
01972                                 $authTool = $this->getAuthenticationTool();
01973                                 $authTool->setAuthType($action['auth_type']);
01974                         }
01975                         
01976                 }
01977         
01978         
01979                 if ( (PEAR::isError($action) or !@$action['permission']) and $this->_conf['security_level'] >= DATAFACE_STRICT_PERMISSIONS ){
01980                         // The only reason getAction() will return an error is if the specified action could not be found.
01981                         // If the application is set to use strict permissions and no action was defined in the ini file
01982                         // then this action cannot be performed.  Strict permissions mode requires that permissions be 
01983                         // strictly set or permission will be denied.
01984                         return Dataface_Error::permissionDenied(
01985                                 Dataface_LanguageTool::translate(
01986                                         /*i18n id*/
01987                                         "Permission Denied. No action found in strict permissions mode",
01988                                         /* default error message */
01989                                         "Permission denied for action '".
01990                                                 $query['-action'].
01991                                         "'.  No entry for this action was found in the actions.ini file.  
01992                                         You are currently using strict permissions mode which requires that you define all actions that you want to use in the actions.ini file with appropriate permissions information.", 
01993                                         /* i18n parameters */
01994                                         array('action'=>$query['-action'])
01995                                 )
01996                         );
01997                         
01998                 } 
01999                 
02000                 else if ( PEAR::isError($action) ){
02001                         $action = array('name'=>$query['-action'], 'label'=>$query['-action']);
02002                 }
02003                 
02004                 // Step 1:  See if the delegate class has a handler.
02005                 
02006                 $delegate = $table->getDelegate();
02007                 $handled = false;
02008                 if ( method_exists($delegate,'handleRequest') ){
02009                         $result = $delegate->handleRequest();
02010                         if ( PEAR::isError($result) and $result->getCode() === DATAFACE_E_REQUEST_NOT_HANDLED ){
02011                                 $handled = false;
02012                         } else if ( PEAR::isError($result) ){
02013                                 return $result;
02014                         } else {
02015                                 $handled = true;
02016                         }
02017                 }
02018                 if ( isset($action['mode']) and $action['mode'] ) $query['-mode'] = $action['mode'];
02019                 
02020                 // Step 2: Look to see if there is a handler defined
02021                 if ( isset($action['custom']) ){
02022                         $locations = array( DATAFACE_PATH.'/actions/custom.php'=>'dataface_actions_custom');
02023                 } else {
02024                         $locations = array();
02025                         
02026                         $locations[ Dataface_Table::getBasePath($query['-table']).'/tables/'.basename($query['-table']).'/actions/'.basename($query['-action']).'.php' ] = 'tables_'.$query['-table'].'_actions_'.$query['-action'];
02027                         $locations[ DATAFACE_SITE_PATH.'/actions/'.basename($query['-action']).'.php' ] = 'actions_'.$query['-action'];
02028                         
02029                         if ( isset($this->_conf['_modules']) and count($this->_conf['_modules']) > 0 ){
02030                                 $mt = Dataface_ModuleTool::getInstance();
02031                                 foreach ($this->_conf['_modules'] as $modname=>$modpath){
02032                                         $mt->loadModule($modname);
02033                                         if ( $modpath{0} == '/' )
02034                                                 $locations[ dirname($modpath).'/actions/'.basename($query['-action']).'.php' ] = 'actions_'.$query['-action'];
02035                                         else {
02036                                                 $locations[ DATAFACE_SITE_PATH.'/'.dirname($modpath).'/actions/'.basename($query['-action']).'.php' ] = 'actions_'.$query['-action'];
02037                                                 $locations[ DATAFACE_PATH.'/'.dirname($modpath).'/actions/'.basename($query['-action']).'.php' ] = 'actions_'.$query['-action'];
02038                                         }
02039                                 }
02040                         }
02041                         
02042                         $locations[ DATAFACE_PATH.'/actions/'.basename($query['-action']).'.php' ] = 'dataface_actions_'.$query['-action'];
02043                         $locations[ DATAFACE_PATH.'/actions/default.php' ] = 'dataface_actions_default';
02044                                 
02045                 }
02046                 $doParams = array('action'=>&$action);
02047                         //parameters to be passed to the do method of the handler
02048                         
02049                 
02050                 foreach ($locations as $handlerPath=>$handlerClassName){
02051                         if ( is_readable($handlerPath) ){
02052                                 import($handlerPath);
02053                                 $handler = new $handlerClassName;
02054                                 $params  = array();
02055                                 if ( is_array($action) and @$action['related'] and @$query['-relationship'] ){
02056                                         $params['relationship'] = $query['-relationship'];
02057                                 }
02058                                 if ( !PEAR::isError($action) and method_exists($handler, 'getPermissions') ){
02059                                         // check the permissions on this action to make sure that we are 'allowed' to perform it
02060                                         // this method will return an array of Strings that are names of permissions granted to
02061                                         // the current user.
02062                                         
02063                                         
02064                                         //echo "Checking permissions:";
02065                                         //print_r($params);
02066                                         $permissions = $handler->getPermissions($params);
02067                                 //} else if ( $applicationDelegate !== null and method_exists($applicationDelegate, 'getPermissions') ){
02068                                 //      $permissions =& $applicationDelegate->getPermissions($params);
02069                                         
02070                         
02071                                 
02072                                 } else {
02073                                         //print_r($params);
02074                                         //print_r($action);
02075                                         $permissions = $this->getPermissions($params);
02076                                 }
02077                                 
02078                                 if ( isset($action['permission']) && !(isset($permissions[$action['permission']]) and $permissions[$action['permission']]) ){
02079                                         return Dataface_Error::permissionDenied(
02080                                                 Dataface_LanguageTool::translate(
02081                                                         "Permission Denied for action.", /*i18n id*/
02082                                                         /* Default error message */
02083                                                         "Permission to perform action '".
02084                                                         $action['name'].
02085                                                         "' denied.  
02086                                                         Requires permission '".
02087                                                         $action['permission'].
02088                                                         "' but only granted '".
02089                                                         Dataface_PermissionsTool::namesAsString($permissions)."'.", 
02090                                                         /* i18n parameters */
02091                                                         array('action'=>$action, 'permissions_granted'=>Dataface_PermissionsTool::namesAsString($permissions))
02092                                                 )
02093                                         );
02094                                 
02095                                 }
02096                                 
02097                                 if ( method_exists($handler, 'handle') ){
02098                                         
02099                                         
02100                                         $result = $handler->handle($doParams);
02101                                         if ( PEAR::isError($result) and $result->getCode() === DATAFACE_E_REQUEST_NOT_HANDLED ){
02102                                                 continue;
02103                                         }
02104                                         return $result;
02105                                 }
02106                                 
02107                                 
02108                         }
02109                         
02110                 }
02111                 
02112                 throw new Exception(df_translate('scripts.Dataface.Application.handleRequest.NO_HANDLER_FOUND',"No handler found for request.  This should never happen because, at the very least, the default handler at dataface/actions/default.php should be called.  Check the permissions on dataface/actions/default.php to make sure that it is readable by the web server."), E_USER_ERROR);
02113                 
02114                 
02115                 
02116         
02117         }
02118          
02119          
02120          
02134         function display($main_content_only=false, $disableCache=false){
02135                 // ---------------- Set the Default Character set for output -----------
02136                 foreach ($this->_tables as $key=>$value){
02137                         $this->_tables[$key] = $this->_conf['_tables'][$key] = df_translate('tables.'.$key.'.label', $value);
02138                 }
02139                 
02140                 $this->main_content_only = $main_content_only;
02141                 if ( $this->autoSession or $this->sessionEnabled() ){
02142                         $this->startSession();
02143                 }
02144                 if ( !@$this->_conf['disable_session_ip_check'] ){
02145                         if ( !@$_SESSION['XATAFACE_REMOTE_ADDR'] ){
02146                                 $_SESSION['XATAFACE_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
02147                         }
02148                         $ipAddressError = null;
02149                         if ( $_SESSION['XATAFACE_REMOTE_ADDR'] != $_SERVER['REMOTE_ADDR'] ){
02150                                 $msg = sprintf(
02151                                         "Session address does not match the remote address.  Possible hacking attempt.  Session address was '%s', User address was '%s'",
02152                                         htmlspecialchars($_SESSION['XATAFACE_REMOTE_ADDR']),
02153                                         htmlspecialchars($_SERVER['REMOTE_ADDR'])
02154                                 );
02155                                 error_log($msg);
02156                                 //die('Your IP address doesn\'t match the session address.  To continue, please clear your cookies or restart your browser and try again.');
02157                                 session_destroy();
02158                                 $this->startSession();
02159                                 if ( !@$_SESSION['XATAFACE_REMOTE_ADDR'] ){
02160                                         $_SESSION['XATAFACE_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
02161                                 }
02162                                 
02163                         }
02164                 }
02165                 // handle authentication
02166                 if ( isset($this->_conf['_auth']) ){
02167                         // The config file _auth section is there so we will be using authentication.
02168         
02169                         $loginPrompt = false;   // flag to indicate if we should show the login prompt
02170                         $permissionDenied = false;// flag to indicate if we should show permission denied
02171                         $permissionError = ''; //Placeholder for permissions error messages
02172                         $loginError = ''; // Placeholder for login error messages.
02173                         
02174                         $authTool = $this->getAuthenticationTool();
02175                         
02176                         $auth_result = $authTool->authenticate();
02177                         
02178                         if ( PEAR::isError($auth_result) and $auth_result->getCode() == DATAFACE_E_LOGIN_FAILURE ){
02179                                 // There was a login failure, show the login prompt
02180                                 $loginPrompt = true;
02181                                 $loginError = $auth_result->getMessage();
02182                         } else if ( $authTool->isLoggedIn() ){
02183                                 // The user is logged in ok
02184                                 // Handle the request
02185                                 $result = $this->handleRequest();
02186                                 if ( Dataface_Error::isPermissionDenied($result) ){
02187                                         // Permission was denied on the request.  Since the user is already
02188                                         // logged in, there is no use giving him the login prompt.  Just give
02189                                         // him the permission denied screen.
02190                                         $permissionDenied = true;
02191                                         $permissionError = $result->getMessage();
02192                                 }
02193                         } else if ( isset($this->_conf['_auth']['require_login']) and $this->_conf['_auth']['require_login'] ){
02194                                 // The user is not logged in and login is required for this application
02195                                 // Show the login prompt
02196                                 $loginPrompt = true;
02197 
02198                         } else {
02199                                 // The user is not logged in, but login is not required for this application.
02200                                 // Allow the user to perform the action.
02201 
02202                                 $result = $this->handleRequest($disableCache);
02203                                 if ( Dataface_Error::isPermissionDenied($result) ){
02204                                         // The user did not have permission to perform the action
02205                                         // Give the user a login prompt.
02206                                         
02207                                         $loginPrompt = true;
02208                                 }
02209                                 
02210                         }
02211                         if ( $loginPrompt ){
02212                                 // The user is supposed to see a login prompt to log in.
02213                                 // Show the login prompt.
02214                                 
02215                                 $authTool->showLoginPrompt($loginError);
02216                         } else if ($permissionDenied) {
02217                                 // The user is supposed to see the permissionm denied page.
02218                                 $query =& $this->getQuery();
02219                                 
02220                                 if ( $query['--original_action'] == 'browse' and $query['-action'] != 'view' ){
02221                                         $this->redirect($this->url('-action=view'));
02222                                 }
02223                                 $this->addError($result);
02224                                 header("HTTP/1.1 403 Permission Denied");
02225                                 df_display(array(), 'Dataface_Permission_Denied.html');
02226                         } else if ( PEAR::isError($result) ){
02227                                 // Some other error occurred in handling the request.  Just show an
02228                                 // ugly stack trace.
02229                                 
02230                                 throw new Exception($result->toString().$result->getDebugInfo(), E_USER_ERROR);
02231                         }
02232                 } else {
02233                         // Authentication is not enabled for this application.
02234                         // Just process the request.
02235                         
02236                         $result = $this->handleRequest($disableCache);
02237                         if ( Dataface_Error::isPermissionDenied($result) ){
02238                                 $query =& $this->getQuery();
02239                                 
02240                                 if ( $query['--original_action'] == 'browse' and $query['-action'] != 'view' ){
02241                                         $this->redirect($this->url('-action=view'));
02242                                 }
02243                                 $this->addError($result);
02244                                 header("HTTP/1.1 403 Permission Denied");
02245                                 df_display(array(), 'Dataface_Permission_Denied.html');
02246                         } else if ( PEAR::isError($result) ){
02247                                 
02248                                 throw new Exception($result->toString().$result->getDebugInfo(), E_USER_ERROR);
02249                         }
02250                 }
02251         
02252         }
02253         
02263         function _handleGetBlob($request){
02264                 import('Dataface/Application/blob.php');
02265                 return Dataface_Application_blob::_handleGetBlob($request);
02266         }
02267         
02268          
02269         // @}
02270         // END Request Handling
02271         //======================================================================================
02272         
02273         
02274         // @{
02282         var $_parseStringContext=array();
02350         function parseString($expression, $context=null){
02351                 // make sure that the expression doesn't try to break the double quotes.
02352                 if ( strpos($expression, '"') !== false ){
02353                         throw new Exception(
02354                                 df_translate(
02355                                         'scripts.Dataface.Application.parseString.ERROR_PARSING_EXPRESSION_DBL_QUOTE',
02356                                         "Invalid expression (possible hacking attempt in Dataface_Application::eval().  Expression cannot include double quotes '\"', but recieved '".$expression."'.",
02357                                         array('expression'=>$expression))
02358                                         , E_USER_ERROR);
02359                 }
02360  
02361                 $site_url = DATAFACE_SITE_URL;
02362                 $site_href = DATAFACE_SITE_HREF;
02363                 $dataface_url = DATAFACE_URL;
02364                 $table = $this->_currentTable;
02365                 $tableObj = Dataface_Table::loadTable($table);
02366                 if ( PEAR::isError($tableObj) ){
02367                         throw new Exception($tableObj->getMessage(), $tableObj->getCode());
02368                 }
02369                 $query =& $this->getQuery();
02370                 $app = $this;
02371                 $resultSet = $app->getResultSet();
02372                 if ( isset($context['record']) ){
02373 
02374                         $record = $context['record'];
02375                 } else {
02376                         $record = $app->getRecord();
02377                 }
02378                 
02379                 if ( isset($context['relationship']) ){
02380                         //$tableObj = Dataface_Table::loadTable($table);
02381                         
02382                         if ( is_string($context['relationship']) ){
02383                                 $relationship = $tableObj->getRelationship($context['relationship']);
02384                                 if ( !($relationship instanceof Dataface_Relationship) ){
02385                                         $relationship = null;
02386                                 }
02387                         } else if ( $context['relationship'] instanceof Dataface_Relationship ){
02388                                 $relationship = $context['relationship'];
02389                         }
02390                         //unset($tableObj);
02391                 }
02392                 
02393                 @eval('$parsed = "'.$expression.'";');
02394                 
02395                 if ( !isset( $parsed ) ){
02396                         throw new Exception(df_translate('scripts.Dataface.Application.parseString.ERROR_PARSING_EXPRESSION',"Error parsing expression '$expression'. ", array('expression'=>$expression)), E_USER_ERROR);
02397                 }
02398                 return $parsed;
02399         
02400         }
02401         
02402         
02407         function _parsePregMatch($matches){
02408                 extract($this->_parseStringContext);
02409                 return @eval('return '.$matches[1].$matches[2].';');
02410         }
02411         
02412         
02479         function testCondition($condition, $context=null){
02480 
02481                 $site_url = DATAFACE_SITE_URL;
02482                 $site_href = DATAFACE_SITE_HREF;
02483                 $dataface_url = DATAFACE_URL;
02484                 $table = $this->_currentTable;
02485                 $tableObj = Dataface_Table::loadTable($table);
02486                 if ( PEAR::isError($tableObj) ) throw new Exception($tableObj->getMessage(), $tableObj->getCode());
02487                 $query =& $this->getQuery();
02488                 $app = $this;
02489                 $resultSet = $app->getResultSet();
02490                 if ( isset($context['record']) ) $record = $context['record'];
02491                 else $record = $app->getRecord();
02492                 
02493                 if ( isset($context['relationship']) ){
02494                         //$tableObj =& Dataface_Table::loadTable($table);
02495                         if ( is_string($context['relationship'])  ){
02496                                 $relationship = $tableObj->getRelationship($context['relationship']);
02497                                 if ( !($relationship instanceof Dataface_Relationship) ){
02498                                         $relationship = null;
02499                                 }
02500                         } else if ( $context['relationship'] instanceof Dataface_Relationship ){
02501                                 $relationship = $context['relationship'];
02502                         }
02503                         //unset($tableObj);
02504                 }
02505                 
02506                 return @eval('return ('.$condition.');');
02507         }
02508         
02509         
02510         
02537         function url($query, $useContext=true, $forceContext=false){
02538                 import('Dataface/LinkTool.php');
02539                 return Dataface_LinkTool::buildLInk($query, $useContext, $forceContext);
02540         
02541         }
02542         
02543         
02544                 
02545         
02546         
02547         
02548         
02549         
02550         
02551         
02552         
02581         function registerUrlFilter( $filter ){
02582                 $this->_url_filters[] = $filter;
02583         }
02584         
02585         
02595         function filterUrl($url){
02596                 if ( !preg_match( '/[&\?]-table/i', $url ) ){
02597                         if ( preg_match( '/\?/i', $url ) ){
02598                                 $url .= '&-table='.$this->_currentTable;
02599                         } else {
02600                                 $url .= '?-table='.$this->_currentTable;
02601                         }
02602                 }
02603                 
02604                 foreach ($this->_url_filters as $filter){
02605                         $url = call_user_func($filter, $url);
02606                 }
02607                 return $url;
02608         
02609         }
02610         
02611         
02612         
02616         function init(){
02617         
02618         }
02619         
02620         
02633         function redirect($url){
02634                 if ( isset($this->redirectHandler) and method_exists('redirect', $this->redirectHandler) ){
02635                         $this->redirectHandler->redirect($url);
02636                         throw new Dataface_Application_RedirectException($url);
02637                 }
02638                 header('Location: '.$url);
02639                 exit;
02640                 
02641         }
02642         
02643         // @}
02644         // End Utility Functions
02645         //=======================================================================================
02646         
02647         
02648         
02649         // @{
02666         function &getDelegate(){
02667                 if ( $this->delegate === -1 ){
02668                         $delegate_path = DATAFACE_SITE_PATH.'/conf/ApplicationDelegate.php';
02669                         if ( is_readable($delegate_path) ){
02670                                 import($delegate_path);
02671                                 $this->delegate = new conf_ApplicationDelegate();
02672                         } else {
02673                                 $this->delegate = null;
02674                         }
02675                 }
02676                 return $this->delegate;
02677                                 
02678         }
02679         
02680         
02681          
02682          
02683         // END Delegate Class
02684         // @}
02685         //========================================================================================
02686 
02687 
02688         // @{
02714         function getPermissions($params=array()){
02715                 $query =& $this->getQuery();
02716                 $record = $this->getRecord();
02717                 if ( $record and is_a($record, 'Dataface_Record') ){
02718                         //$params = array();
02719                         return Dataface_PermissionsTool::getPermissions($record, $params);
02720                 } else {
02721                         $table = Dataface_Table::loadTable($query['-table']);
02722                         //$params = array();
02723                         return Dataface_PermissionsTool::getPermissions($table, $params);
02724                 }
02725                 
02726         }
02727         
02741         function checkPermission($perm){
02742                 $perms = $this->getPermissions();
02743                 $result = (isset($perms[$perm]) and $perms[$perm]);
02744                 return $result;
02745         }
02746         
02747         
02748          
02749          
02750         // @}
02751         // END Permissions
02752         //=========================================================================================
02753         
02754         
02755         
02768          function refreshSchemas($tablename){
02769                 if ( @$this->_conf['metadata_enabled'] ){
02770                         $metadataTool = new Dataface_MetadataTool();
02771                         $metadataTool->updateWorkflowTable($tablename);
02772                 }
02773         }
02774         
02775         
02776         
02777         
02778         
02788         function _parseRelatedBlobRequest($request){
02789                 import('Dataface/Application/blob.php');
02790                 return Dataface_Application_blob::_parseRelatedBlobRequest($request);
02791         }
02792         
02793 
02795 
02822         function &getCustomPages(){
02823                 if ( !isset( $this->_customPages ) ){
02824                         $this->_customPages = array();
02825                         $path = DATAFACE_SITE_PATH.'/pages/';
02826                         if ( is_dir($path) ){
02827                                 if ( $dh = opendir($path) ){
02828                                         while ( ( $file = readdir($dh) ) !== false ){
02829                                                 if ( preg_match('/\.php$/', $file) ){
02830                                                         list($name) = explode('.', $file);
02831                                                         //$name = str_replace('_', ' ', $name);
02832                                                         
02833                                                         $this->_customPages[$name] = $path.$file;
02834                                                 }
02835                                         }
02836                                 }
02837                         }
02838                 }
02839                 return $this->_customPages;
02840         }
02841         
02849         function getCustomPagePath($name){
02850                 $pages =& $this->getCustomPages();
02851                 return $pages[$name];
02852         }
02853         
02862         function getCustomPageLabel($name){
02863                 $name = str_replace('_',' ', $name);
02864                 return ucwords($name);
02865         }
02866         
02867 
02868         // @}
02869         // END Custom Pages
02870         //=====================================================================================
02871 
02872 
02873         
02879         function addDebugInfo($info){
02880                 $this->debugLog[] = $info;
02881         }
02882         
02888         function displayDebugInfo(){
02889                 echo '<ul class="debug-info"><li>
02890                 '; echo implode('</li><li>', $this->debugLog);
02891                 echo '</li></ul>';
02892         }
02893         
02897         function _cleanup(){
02898                 if ( session_id() != "" ){
02899                         $this->writeSessionData();
02900                 }
02901                 if ( @$this->_conf['support_transactions'] ){
02902                         @mysql_query('COMMIT', $this->_db);
02903                 }
02904         }
02905         
02906         
02907 
02908         
02909         
02910         
02911         
02912         
02913 
02914 }
02915 
02920 class Dataface_Application_RedirectException extends Exception {
02921         private $url;
02922         public function __construct($url, $code = 0, Exception $previous = null ){
02923                 $this->url = $url;
02924                 parent::__construct('Request to redirect to '.$url, $code, $previous);
02925         }
02926         
02927         public function getURL(){
02928                 return $this->url;
02929         }
02930 
02931 }
02932 
 All Data Structures Namespaces Files Functions Variables Enumerations