[ Index ]

PHP Cross Reference of Joomla 2.5.4 DE

title

Body

[close]

/libraries/joomla/user/ -> user.php (source)

   1  <?php
   2  /**
   3   * @package     Joomla.Platform
   4   * @subpackage  User
   5   *
   6   * @copyright   Copyright (C) 2005 - 2012 Open Source Matters, Inc. All rights reserved.
   7   * @license     GNU General Public License version 2 or later; see LICENSE
   8   */
   9  
  10  defined('JPATH_PLATFORM') or die;
  11  
  12  /**
  13   * User class.  Handles all application interaction with a user
  14   *
  15   * @package     Joomla.Platform
  16   * @subpackage  User
  17   * @since       11.1
  18   */
  19  class JUser extends JObject
  20  {
  21      /**
  22       * A cached switch for if this user has root access rights.
  23       *
  24       * @var    boolean
  25       * @since  11.1
  26       */
  27      protected $isRoot = null;
  28  
  29      /**
  30       * Unique id
  31       *
  32       * @var    integer
  33       * @since  11.1
  34       */
  35      public $id = null;
  36  
  37      /**
  38       * The users real name (or nickname)
  39       * @var    string
  40       * @since  11.1
  41       */
  42      public $name = null;
  43  
  44      /**
  45       * The login name
  46       *
  47       * @var    string
  48       * @since  11.1
  49       */
  50      public $username = null;
  51  
  52      /**
  53       * The email
  54       *
  55       * @var    string
  56       * @since  11.1
  57       */
  58      public $email = null;
  59  
  60      /**
  61       * MD5 encrypted password
  62       *
  63       * @var    string
  64       * @since  11.1
  65       */
  66      public $password = null;
  67  
  68      /**
  69       * Clear password, only available when a new password is set for a user
  70       *
  71       * @var    string
  72       * @since  11.1
  73       */
  74      public $password_clear = '';
  75  
  76      /**
  77       * User type
  78       * Used in Joomla 1.0 and 1.5 for access control.
  79       *
  80       * @var    string
  81       * @deprecated    12.1
  82       * @see    $_authGroups
  83       * @see    JAccess
  84       * @since  11.1
  85       */
  86      public $usertype = null;
  87  
  88      /**
  89       * Block status
  90       *
  91       * @var    integer
  92       * @since  11.1
  93       */
  94      public $block = null;
  95  
  96      /**
  97       * Should this user receive system email
  98       *
  99       * @var    integer
 100       * @since  11.1
 101       */
 102      public $sendEmail = null;
 103  
 104      /**
 105       * Date the user was registered
 106       *
 107       * @var    datetime
 108       * @since  11.1
 109       */
 110      public $registerDate = null;
 111  
 112      /**
 113       * Date of last visit
 114       *
 115       * @var    datetime
 116       * @since  11.1
 117       */
 118      public $lastvisitDate = null;
 119  
 120      /**
 121       * Activation hash
 122       *
 123       * @var    string
 124       * @since  11.1
 125       */
 126      public $activation = null;
 127  
 128      /**
 129       * User parameters
 130       *
 131       * @var    string
 132       * @since  11.1
 133       */
 134      public $params = null;
 135  
 136      /**
 137       * Array of ids of groups that user belongs to
 138       *
 139       * @var    array
 140       * @since  11.1
 141       */
 142      public $groups = array();
 143  
 144      /**
 145       * Guest status
 146       *
 147       * @var    boolean
 148       * @since  11.1
 149       */
 150      public $guest = null;
 151  
 152      /**
 153       * User parameters
 154       * @var    object
 155       * @since  11.1
 156       */
 157      protected $_params = null;
 158  
 159      /**
 160       * Authorised access groups
 161       *
 162       * @var    array
 163       * @since  11.1
 164       */
 165      protected $_authGroups = null;
 166  
 167      /**
 168       * Authorised access levels
 169       *
 170       * @var    array
 171       * @since  11.1
 172       */
 173      protected $_authLevels = null;
 174  
 175      /**
 176       * Authorised access actions
 177       *
 178       * @var    array
 179       * @since  11.1
 180       */
 181      protected $_authActions = null;
 182  
 183      /**
 184       * Error message
 185       *
 186       * @var    string
 187       * @since  11.1
 188       */
 189      protected $_errorMsg = null;
 190  
 191      /**
 192       * @var    array  JUser instances container.
 193       * @since  11.3
 194       */
 195      protected static $instances = array();
 196  
 197      /**
 198       * Constructor activating the default information of the language
 199       *
 200       * @param   integer  $identifier  The primary key of the user to load (optional).
 201       *
 202       * @since   11.1
 203       */
 204  	public function __construct($identifier = 0)
 205      {
 206          // Create the user parameters object
 207          $this->_params = new JRegistry;
 208  
 209          // Load the user if it exists
 210          if (!empty($identifier))
 211          {
 212              $this->load($identifier);
 213          }
 214          else
 215          {
 216              //initialise
 217              $this->id = 0;
 218              $this->sendEmail = 0;
 219              $this->aid = 0;
 220              $this->guest = 1;
 221          }
 222      }
 223  
 224      /**
 225       * Returns the global User object, only creating it if it
 226       * doesn't already exist.
 227       *
 228       * @param   integer  $identifier  The user to load - Can be an integer or string - If string, it is converted to ID automatically.
 229       *
 230       * @return  JUser  The User object.
 231       *
 232       * @since   11.1
 233       */
 234  	public static function getInstance($identifier = 0)
 235      {
 236          // Find the user id
 237          if (!is_numeric($identifier))
 238          {
 239              if (!$id = JUserHelper::getUserId($identifier))
 240              {
 241                  JError::raiseWarning('SOME_ERROR_CODE', JText::sprintf('JLIB_USER_ERROR_ID_NOT_EXISTS', $identifier));
 242                  $retval = false;
 243                  return $retval;
 244              }
 245          }
 246          else
 247          {
 248              $id = $identifier;
 249          }
 250  
 251          if (empty(self::$instances[$id]))
 252          {
 253              $user = new JUser($id);
 254              self::$instances[$id] = $user;
 255          }
 256  
 257          return self::$instances[$id];
 258      }
 259  
 260      /**
 261       * Method to get a parameter value
 262       *
 263       * @param   string  $key      Parameter key
 264       * @param   mixed   $default  Parameter default value
 265       *
 266       * @return  mixed  The value or the default if it did not exist
 267       *
 268       * @since   11.1
 269       */
 270  	public function getParam($key, $default = null)
 271      {
 272          return $this->_params->get($key, $default);
 273      }
 274  
 275      /**
 276       * Method to set a parameter
 277       *
 278       * @param   string  $key    Parameter key
 279       * @param   mixed   $value  Parameter value
 280       *
 281       * @return  mixed  Set parameter value
 282       *
 283       * @since   11.1
 284       */
 285  	public function setParam($key, $value)
 286      {
 287          return $this->_params->set($key, $value);
 288      }
 289  
 290      /**
 291       * Method to set a default parameter if it does not exist
 292       *
 293       * @param   string  $key    Parameter key
 294       * @param   mixed   $value  Parameter value
 295       *
 296       * @return  mixed  Set parameter value
 297       *
 298       * @since   11.1
 299       */
 300  	public function defParam($key, $value)
 301      {
 302          return $this->_params->def($key, $value);
 303      }
 304  
 305      /**
 306       * Proxy to authorise
 307       *
 308       * @param   string  $action     The name of the action to check for permission.
 309       * @param   string  $assetname  The name of the asset on which to perform the action.
 310       *
 311       * @return  boolean  True if authorised
 312       *
 313       * @deprecated    12.1
 314       * @note    Use the authorise method instead.
 315       * @since   11.1
 316       */
 317  	public function authorize($action, $assetname = null)
 318      {
 319          // Deprecation warning.
 320          JLog::add('JUser::authorize() is deprecated.', JLog::WARNING, 'deprecated');
 321  
 322          return $this->authorise($action, $assetname);
 323      }
 324  
 325      /**
 326       * Method to check JUser object authorisation against an access control
 327       * object and optionally an access extension object
 328       *
 329       * @param   string  $action     The name of the action to check for permission.
 330       * @param   string  $assetname  The name of the asset on which to perform the action.
 331       *
 332       * @return  boolean  True if authorised
 333       *
 334       * @since   11.1
 335       */
 336  	public function authorise($action, $assetname = null)
 337      {
 338          // Make sure we only check for core.admin once during the run.
 339          if ($this->isRoot === null)
 340          {
 341              $this->isRoot = false;
 342  
 343              // Check for the configuration file failsafe.
 344              $config = JFactory::getConfig();
 345              $rootUser = $config->get('root_user');
 346  
 347              // The root_user variable can be a numeric user ID or a username.
 348              if (is_numeric($rootUser) && $this->id > 0 && $this->id == $rootUser)
 349              {
 350                  $this->isRoot = true;
 351              }
 352              elseif ($this->username && $this->username == $rootUser)
 353              {
 354                  $this->isRoot = true;
 355              }
 356              else
 357              {
 358                  // Get all groups against which the user is mapped.
 359                  $identities = $this->getAuthorisedGroups();
 360                  array_unshift($identities, $this->id * -1);
 361  
 362                  if (JAccess::getAssetRules(1)->allow('core.admin', $identities))
 363                  {
 364                      $this->isRoot = true;
 365                      return true;
 366                  }
 367              }
 368          }
 369  
 370          return $this->isRoot ? true : JAccess::check($this->id, $action, $assetname);
 371      }
 372  
 373      /**
 374       * Gets an array of the authorised access levels for the user
 375       *
 376       * @return  array
 377       *
 378       * @deprecated  12.1
 379       * @note    Use the getAuthorisedViewLevels method instead.
 380       * @since   11.1
 381       */
 382  	public function authorisedLevels()
 383      {
 384          // Deprecation warning.
 385          JLog::add('JUser::authorisedLevels() is deprecated.', JLog::WARNING, 'deprecated');
 386  
 387          return $this->getAuthorisedViewLevels();
 388      }
 389  
 390      /**
 391       * Method to return a list of all categories that a user has permission for a given action
 392       *
 393       * @param   string  $component  The component from which to retrieve the categories
 394       * @param   string  $action     The name of the section within the component from which to retrieve the actions.
 395       *
 396       * @return  array  List of categories that this group can do this action to (empty array if none). Categories must be published.
 397       *
 398       * @since   11.1
 399       */
 400  	public function getAuthorisedCategories($component, $action)
 401      {
 402          // Brute force method: get all published category rows for the component and check each one
 403          // TODO: Modify the way permissions are stored in the db to allow for faster implementation and better scaling
 404          $db = JFactory::getDbo();
 405          $query = $db->getQuery(true)->select('c.id AS id, a.name AS asset_name')->from('#__categories AS c')
 406              ->innerJoin('#__assets AS a ON c.asset_id = a.id')->where('c.extension = ' . $db->quote($component))->where('c.published = 1');
 407          $db->setQuery($query);
 408          $allCategories = $db->loadObjectList('id');
 409          $allowedCategories = array();
 410          foreach ($allCategories as $category)
 411          {
 412              if ($this->authorise($action, $category->asset_name))
 413              {
 414                  $allowedCategories[] = (int) $category->id;
 415              }
 416          }
 417          return $allowedCategories;
 418      }
 419  
 420      /**
 421       * Gets an array of the authorised access levels for the user
 422       *
 423       * @return  array
 424       *
 425       * @since   11.1
 426       */
 427  	public function getAuthorisedViewLevels()
 428      {
 429          if ($this->_authLevels === null)
 430          {
 431              $this->_authLevels = array();
 432          }
 433  
 434          if (empty($this->_authLevels))
 435          {
 436              $this->_authLevels = JAccess::getAuthorisedViewLevels($this->id);
 437          }
 438  
 439          return $this->_authLevels;
 440      }
 441      /**
 442       * Gets an array of the authorised user groups
 443       *
 444       * @return  array
 445       *
 446       * @since   11.1
 447       */
 448  	public function getAuthorisedGroups()
 449      {
 450          if ($this->_authGroups === null)
 451          {
 452              $this->_authGroups = array();
 453          }
 454  
 455          if (empty($this->_authGroups))
 456          {
 457              $this->_authGroups = JAccess::getGroupsByUser($this->id);
 458          }
 459  
 460          return $this->_authGroups;
 461      }
 462      /**
 463       * Pass through method to the table for setting the last visit date
 464       *
 465       * @param   integer  $timestamp  The timestamp, defaults to 'now'.
 466       *
 467       * @return  boolean  True on success.
 468       *
 469       * @since   11.1
 470       */
 471  	public function setLastVisit($timestamp = null)
 472      {
 473          // Create the user table object
 474          $table = $this->getTable();
 475          $table->load($this->id);
 476  
 477          return $table->setLastVisit($timestamp);
 478      }
 479  
 480      /**
 481       * Method to get the user parameters
 482       *
 483       * This function tries to load an XML file based on the user's usertype. The filename of the xml
 484       * file is the same as the usertype. The functionals has a static variable to store the parameters
 485       * setup file base path. You can call this function statically to set the base path if needed.
 486       *
 487       * @param   boolean  $loadsetupfile  If true, loads the parameters setup file. Default is false.
 488       * @param   path     $path           Set the parameters setup file base path to be used to load the user parameters.
 489       *
 490       * @return  object   The user parameters object.
 491       *
 492       * @since   11.1
 493       */
 494  	public function getParameters($loadsetupfile = false, $path = null)
 495      {
 496          static $parampath;
 497  
 498          // Set a custom parampath if defined
 499          if (isset($path))
 500          {
 501              $parampath = $path;
 502          }
 503  
 504          // Set the default parampath if not set already
 505          if (!isset($parampath))
 506          {
 507              $parampath = JPATH_ADMINISTRATOR . 'components/com_users/models';
 508          }
 509  
 510          if ($loadsetupfile)
 511          {
 512              $type = str_replace(' ', '_', strtolower($this->usertype));
 513  
 514              $file = $parampath . '/' . $type . '.xml';
 515              if (!file_exists($file))
 516              {
 517                  $file = $parampath . '/' . 'user.xml';
 518              }
 519  
 520              $this->_params->loadSetupFile($file);
 521          }
 522  
 523          return $this->_params;
 524      }
 525  
 526      /**
 527       * Method to get the user parameters
 528       *
 529       * @param   object  $params  The user parameters object
 530       *
 531       * @return  void
 532       *
 533       * @since   11.1
 534       */
 535  	public function setParameters($params)
 536      {
 537          $this->_params = $params;
 538      }
 539  
 540      /**
 541       * Method to get the user table object
 542       *
 543       * This function uses a static variable to store the table name of the user table to
 544       * instantiate. You can call this function statically to set the table name if
 545       * needed.
 546       *
 547       * @param   string  $type    The user table name to be used
 548       * @param   string  $prefix  The user table prefix to be used
 549       *
 550       * @return  object  The user table object
 551       *
 552       * @since   11.1
 553       */
 554  	public static function getTable($type = null, $prefix = 'JTable')
 555      {
 556          static $tabletype;
 557  
 558          // Set the default tabletype;
 559          if (!isset($tabletype))
 560          {
 561              $tabletype['name'] = 'user';
 562              $tabletype['prefix'] = 'JTable';
 563          }
 564  
 565          // Set a custom table type is defined
 566          if (isset($type))
 567          {
 568              $tabletype['name'] = $type;
 569              $tabletype['prefix'] = $prefix;
 570          }
 571  
 572          // Create the user table object
 573          return JTable::getInstance($tabletype['name'], $tabletype['prefix']);
 574      }
 575  
 576      /**
 577       * Method to bind an associative array of data to a user object
 578       *
 579       * @param   array  &$array  The associative array to bind to the object
 580       *
 581       * @return  boolean  True on success
 582       *
 583       * @since   11.1
 584       */
 585  	public function bind(&$array)
 586      {
 587          // Let's check to see if the user is new or not
 588          if (empty($this->id))
 589          {
 590              // Check the password and create the crypted password
 591              if (empty($array['password']))
 592              {
 593                  $array['password'] = JUserHelper::genRandomPassword();
 594                  $array['password2'] = $array['password'];
 595              }
 596  
 597              // TODO: Backend controller checks the password, frontend doesn't but should.
 598              // Hence this code is required:
 599              if (isset($array['password2']) && $array['password'] != $array['password2'])
 600              {
 601                  $this->setError(JText::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH'));
 602                  return false;
 603              }
 604  
 605              $this->password_clear = JArrayHelper::getValue($array, 'password', '', 'string');
 606  
 607              $salt = JUserHelper::genRandomPassword(32);
 608              $crypt = JUserHelper::getCryptedPassword($array['password'], $salt);
 609              $array['password'] = $crypt . ':' . $salt;
 610  
 611              // Set the registration timestamp
 612  
 613              $this->set('registerDate', JFactory::getDate()->toSql());
 614  
 615              // Check that username is not greater than 150 characters
 616              $username = $this->get('username');
 617              if (strlen($username) > 150)
 618              {
 619                  $username = substr($username, 0, 150);
 620                  $this->set('username', $username);
 621              }
 622  
 623              // Check that password is not greater than 100 characters
 624              $password = $this->get('password');
 625              if (strlen($password) > 100)
 626              {
 627                  $password = substr($password, 0, 100);
 628                  $this->set('password', $password);
 629              }
 630          }
 631          else
 632          {
 633              // Updating an existing user
 634              if (!empty($array['password']))
 635              {
 636                  if ($array['password'] != $array['password2'])
 637                  {
 638                      $this->setError(JText::_('JLIB_USER_ERROR_PASSWORD_NOT_MATCH'));
 639                      return false;
 640                  }
 641  
 642                  $this->password_clear = JArrayHelper::getValue($array, 'password', '', 'string');
 643  
 644                  $salt = JUserHelper::genRandomPassword(32);
 645                  $crypt = JUserHelper::getCryptedPassword($array['password'], $salt);
 646                  $array['password'] = $crypt . ':' . $salt;
 647              }
 648              else
 649              {
 650                  $array['password'] = $this->password;
 651              }
 652          }
 653  
 654          // TODO: this will be deprecated as of the ACL implementation
 655          //        $db = JFactory::getDbo();
 656  
 657          if (array_key_exists('params', $array))
 658          {
 659              $params = '';
 660  
 661              $this->_params->loadArray($array['params']);
 662  
 663              if (is_array($array['params']))
 664              {
 665                  $params = (string) $this->_params;
 666              }
 667              else
 668              {
 669                  $params = $array['params'];
 670              }
 671  
 672              $this->params = $params;
 673          }
 674  
 675          // Bind the array
 676          if (!$this->setProperties($array))
 677          {
 678              $this->setError(JText::_('JLIB_USER_ERROR_BIND_ARRAY'));
 679              return false;
 680          }
 681  
 682          // Make sure its an integer
 683          $this->id = (int) $this->id;
 684  
 685          return true;
 686      }
 687  
 688      /**
 689       * Method to save the JUser object to the database
 690       *
 691       * @param   boolean  $updateOnly  Save the object only if not a new user
 692       *                                Currently only used in the user reset password method.
 693       *
 694       * @return  boolean  True on success
 695       *
 696       * @since   11.1
 697       * @throws  exception
 698       */
 699  	public function save($updateOnly = false)
 700      {
 701          // Create the user table object
 702          $table = $this->getTable();
 703          $this->params = (string) $this->_params;
 704          $table->bind($this->getProperties());
 705  
 706          // Allow an exception to be thrown.
 707          try
 708          {
 709              // Check and store the object.
 710              if (!$table->check())
 711              {
 712                  $this->setError($table->getError());
 713                  return false;
 714              }
 715  
 716              // If user is made a Super Admin group and user is NOT a Super Admin
 717              //
 718              // @todo ACL - this needs to be acl checked
 719              //
 720              $my = JFactory::getUser();
 721  
 722              //are we creating a new user
 723              $isNew = empty($this->id);
 724  
 725              // If we aren't allowed to create new users return
 726              if ($isNew && $updateOnly)
 727              {
 728                  return true;
 729              }
 730  
 731              // Get the old user
 732              $oldUser = new JUser($this->id);
 733  
 734              //
 735              // Access Checks
 736              //
 737  
 738              // The only mandatory check is that only Super Admins can operate on other Super Admin accounts.
 739              // To add additional business rules, use a user plugin and throw an Exception with onUserBeforeSave.
 740  
 741              // Check if I am a Super Admin
 742              $iAmSuperAdmin = $my->authorise('core.admin');
 743  
 744              // We are only worried about edits to this account if I am not a Super Admin.
 745              if ($iAmSuperAdmin != true)
 746              {
 747                  if ($isNew)
 748                  {
 749                      // Check if the new user is being put into a Super Admin group.
 750                      foreach ($this->groups as $groupId)
 751                      {
 752                          if (JAccess::checkGroup($groupId, 'core.admin'))
 753                          {
 754                              throw new Exception(JText::_('JLIB_USER_ERROR_NOT_SUPERADMIN'));
 755                          }
 756                      }
 757                  }
 758                  else
 759                  {
 760                      // I am not a Super Admin, and this one is, so fail.
 761                      if (JAccess::check($this->id, 'core.admin'))
 762                      {
 763                          throw new Exception(JText::_('JLIB_USER_ERROR_NOT_SUPERADMIN'));
 764                      }
 765  
 766                      if ($this->groups != null)
 767                      {
 768                          // I am not a Super Admin and I'm trying to make one.
 769                          foreach ($this->groups as $groupId)
 770                          {
 771                              if (JAccess::checkGroup($groupId, 'core.admin'))
 772                              {
 773                                  throw new Exception(JText::_('JLIB_USER_ERROR_NOT_SUPERADMIN'));
 774                              }
 775                          }
 776                      }
 777                  }
 778              }
 779  
 780              // Fire the onUserBeforeSave event.
 781              JPluginHelper::importPlugin('user');
 782              $dispatcher = JDispatcher::getInstance();
 783  
 784              $result = $dispatcher->trigger('onUserBeforeSave', array($oldUser->getProperties(), $isNew, $this->getProperties()));
 785              if (in_array(false, $result, true))
 786              {
 787                  // Plugin will have to raise its own error or throw an exception.
 788                  return false;
 789              }
 790  
 791              // Store the user data in the database
 792              if (!($result = $table->store()))
 793              {
 794                  throw new Exception($table->getError());
 795              }
 796  
 797              // Set the id for the JUser object in case we created a new user.
 798              if (empty($this->id))
 799              {
 800                  $this->id = $table->get('id');
 801              }
 802  
 803              if ($my->id == $table->id)
 804              {
 805                  $registry = new JRegistry;
 806                  $registry->loadString($table->params);
 807                  $my->setParameters($registry);
 808              }
 809  
 810              // Fire the onUserAfterSave event
 811              $dispatcher->trigger('onUserAfterSave', array($this->getProperties(), $isNew, $result, $this->getError()));
 812          }
 813          catch (Exception $e)
 814          {
 815              $this->setError($e->getMessage());
 816  
 817              return false;
 818          }
 819  
 820          return $result;
 821      }
 822  
 823      /**
 824       * Method to delete the JUser object from the database
 825       *
 826       * @return  boolean  True on success
 827       *
 828       * @since   11.1
 829       */
 830  	public function delete()
 831      {
 832          JPluginHelper::importPlugin('user');
 833  
 834          // Trigger the onUserBeforeDelete event
 835          $dispatcher = JDispatcher::getInstance();
 836          $dispatcher->trigger('onUserBeforeDelete', array($this->getProperties()));
 837  
 838          // Create the user table object
 839          $table = $this->getTable();
 840  
 841          $result = false;
 842          if (!$result = $table->delete($this->id))
 843          {
 844              $this->setError($table->getError());
 845          }
 846  
 847          // Trigger the onUserAfterDelete event
 848          $dispatcher->trigger('onUserAfterDelete', array($this->getProperties(), $result, $this->getError()));
 849  
 850          return $result;
 851      }
 852  
 853      /**
 854       * Method to load a JUser object by user id number
 855       *
 856       * @param   mixed  $id  The user id of the user to load
 857       *
 858       * @return  boolean  True on success
 859       *
 860       * @since   11.1
 861       */
 862  	public function load($id)
 863      {
 864          // Create the user table object
 865          $table = $this->getTable();
 866  
 867          // Load the JUserModel object based on the user id or throw a warning.
 868          if (!$table->load($id))
 869          {
 870              JError::raiseWarning('SOME_ERROR_CODE', JText::sprintf('JLIB_USER_ERROR_UNABLE_TO_LOAD_USER', $id));
 871              return false;
 872          }
 873  
 874          // Set the user parameters using the default XML file.  We might want to
 875          // extend this in the future to allow for the ability to have custom
 876          // user parameters, but for right now we'll leave it how it is.
 877  
 878          $this->_params->loadString($table->params);
 879  
 880          // Assuming all is well at this point lets bind the data
 881          $this->setProperties($table->getProperties());
 882  
 883          return true;
 884      }
 885  }


Generated: Tue Apr 3 11:40:28 2012 Cross-referenced by PHPXref 0.7.1