ProShell v2.0
Dashboard
Server Info
Server: 158.106.128.192
PHP: 8.2.33
home
planet5
public_html
bansibaba.com
2026-09-12 14:18:54
Editing: User.php
Cancel
Save Changes
<?php /** * Class represents records from table user * {autogenerated} * @property int $user_id * @property string $login * @property string $pass * @property string $email * @property string $name_f * @property string $name_l * @property string $street * @property string $street2 * @property string $city * @property string $state * @property string $zip * @property string $country * @property string $phone * @property datetime $added * @property string $remote_addr * @property int $status * @property int $unsubscribed * @property int $email_verified * @property string $security_code * @property datetime $securitycode_expire * @property string $lang * @property int $i_agree * @property int $is_approved * @property int $is_locked * @property int $reseller_id * @property string $comment * @property int $aff_id * @property int $is_affiliate * @property string $aff_payout_type * @see Am_Table */ class User extends Am_Record_WithData { /** @var string available after call to setPass() only */ protected $_plaintextPass; /** @var bool if the password was changed, additional event handlers will be called after save */ protected $_passwordChanged = false; const STATUS_PENDING = 0; const STATUS_ACTIVE = 1; const STATUS_EXPIRED = 2; const NEED_SESSION_REFRESH = 'need_session_refresh'; function delete() { if ($this->user_id <= 0) throw new Am_Exception_InternalError('Could not delete user, user_id is null'); $this->getDi()->hook->call(Am_Event::USER_BEFORE_DELETE, array('user' => $this)); $this->getDi()->invoiceTable->deleteByUserId($this->user_id); $this->getDi()->accessTable->deleteByUserId($this->user_id); $this->checkSubscriptions(false); $this->getDi()->hook->call(new Am_Event_SubscriptionRemoved($this)); $this->getTable()->delete($this->pk()); foreach (array('?_access_log', '?_access_cache') as $table) $this->getAdapter()->query("DELETE FROM $table WHERE user_id=?", $this->user_id); $this->getDi()->couponBatchTable->deleteByUserId($this->user_id); $this->getDi()->hook->call(new Am_Event_UserAfterDelete($this)); } function insert($reload = true){ if (!isset($this->is_approved)) $this->is_approved = !$this->getDi()->config->get('manually_approve'); if (empty($this->remote_addr)) $this->remote_addr = htmlentities(@$_SERVER['REMOTE_ADDR']); if (empty($this->added)) $this->added = $this->getDi()->sqlDateTime; $this->getDi()->hook->call(new Am_Event_UserBeforeInsert($this)); $ret = parent::insert($reload); if ($this->_passwordChanged) { $event = new Am_Event_SetPassword($this, $this->getPlaintextPass()); $this->getDi()->savedPassTable->setPass($event); $this->getDi()->hook->call($event); } $this->getDi()->hook->call(new Am_Event_UserAfterInsert($this)); $this->_passwordChanged = false; return $ret; } function update(){ $oldU = new stdclass; $oldU->user_id = null; if ($this->getDi()->hook->have(array( 'userBeforeUpdate', 'userAfterUpdate', 'subscriptionUpdated')) || $this->getDi()->config->get('manually_approve') ) { // do loading only if hooks are set $oldU = $this->getTable()->load($this->user_id, false); if (!$oldU) $oldU = new self; // avoid errors here $this->getDi()->hook->call(new Am_Event_UserBeforeUpdate($this, $oldU)); } $ret = parent::update(); if ($this->_passwordChanged) { $this->data()->set(self::NEED_SESSION_REFRESH, true)->update(); $event = new Am_Event_SetPassword($this, $this->getPlaintextPass()); $this->getDi()->savedPassTable->setPass($event); $this->getDi()->hook->call($event); } if ($oldU->user_id) { if ($this->is_approved && !$oldU->is_approved) $this->approve(); $this->getDi()->hook->call(new Am_Event_UserAfterUpdate($this, $oldU)); } if ($this->status && $oldU->user_id) { $this->getDi()->hook->call(new Am_Event_SubscriptionUpdated($this, $oldU)); } $this->_passwordChanged = false; return $ret; } function approve() { foreach($this->getDi()->invoiceTable->findByUserId($this->pk()) as $invoice) $invoice->approve(); if(!$this->is_approved) $this->updateQuick('is_approved', 1); $this->sendSignupEmailIfNecessary(); } protected function _prepareForSet(&$vars) { if (isset($vars['pass'])) unset($vars['pass']); return parent::_prepareForSet($vars); } /** * @param string submitted password * @return bool true if ok, false if not */ function checkPassword($pass){ if (!strlen($pass) || !isset($this->pass) || !strlen($this->pass)) { return false; } $ph = new PasswordHash(8, true); return $ph->CheckPassword($pass, $this->pass); } /** * Set new password * (important! - it does not save the password!) */ function setPass($pass, $quick = false){ $this->_plaintextPass = $pass; $this->_passwordChanged = true; $this->pass = self::cryptPass($pass, $quick); return $this; } static function cryptPass($pass, $quick = false) { $ph = new PasswordHash($quick ? 4 : 8, true); return $ph->HashPassword($pass); } /** It is only exists after call of @method setPass() */ function getPlaintextPass() { return $this->_plaintextPass; } function getLoginCookie() { return sha1($this->user_id.$this->login.md5($this->pass)); } function generateLogin() { // usernames to try $try = array(); if (!empty($this->email) && preg_match("/^([a-zA-Z0-9_]+)\@/", $this->email, $regs)) $try[] = $regs[1]; $fn = strtolower(preg_replace('/[^\w\d_]/', '', @$this->name_f)); $ln = strtolower(preg_replace('/[^\w\d_]/', '', @$this->name_l)); if ($fn || $ln) { if ($fn && $ln) $try[] = $fn.'_'.$ln; else $try[] = $fn . $ln; $try[] = $try[ count($try)-1 ] . rand(100, 999); } foreach ($try as $login) { if (strlen($login) > $this->getDi()->config->get('login_max_length')) $login = substr($login, 0, $this->getDi()->config->get('login_max_length')); if ((strlen($login)>=$this->getDi()->config->get('login_min_length')) && $this->getDi()->userTable->checkUniqLogin($login)) { $this->login = $login; return $this; } } // will generate it // a bit of configuration $min_length=$this->getDi()->config->get('login_min_length') < 4 ? 4 : $this->getDi()->config->get('login_min_length'); $max_length=$this->getDi()->config->get('login_max_length') > 10 ? 10 : $this->getDi()->config->get('login_max_length'); /// let's go do { $pass = $this->getDi()->app->generateRandomString(rand($min_length, $max_length), "qwertyuiopasdfghjklzxcvbnm"); } while (!$this->getDi()->userTable->checkUniqLogin($pass)); $this->login = $pass; return $this; } function generatePassword(){ // a bit of configuration $min_length = max($this->getDi()->config->get('pass_min_length', 8), 8); $max_length = min($this->getDi()->config->get('pass_max_length', 12), 14); $all_g = "aeiyo"; $all_gn = $all_g . "1234567890"; $all_s = "bcdfghjkmnpqrstwxz"; /// let's go $pass = ""; $length = rand($min_length, $max_length); for($i=0;$i<$length;$i++) { if ($i % 2) if ($i < $min_length) $pass .= $all_g[ rand(0, strlen($all_g) - 1) ]; else $pass .= $all_gn[ rand(0, strlen($all_gn) - 1) ]; else $pass .= $all_s[ rand(0, strlen($all_s) - 1) ]; } $this->setPass($pass); return $this; } private function _trueIfActive($v){ return $v == self::STATUS_ACTIVE; } private function _trueIfExpired($v){ return $v == self::STATUS_EXPIRED; } function checkSubscriptions($updateCache = false) { if (!$this->user_id) throw new Am_Exception_InternalError("Could not do User->checkSubscriptions() : user_id is empty"); if ($updateCache) $this->getDi()->resourceAccessTable->updateCache($this->user_id); $newStatus = $this->getDi()->accessTable->getStatusByUserId($this->user_id); $active = array_keys(array_filter($newStatus, array($this, '_trueIfActive'))); $oldStatus = $this->getProductsStatus(); $saved = array_keys(array_filter($oldStatus, array($this, '_trueIfActive'))); $merged = array_unique(array_merge($active, $saved)); $added = array_diff($merged, $saved); $deleted = array_diff($merged, $active); foreach ($added as $product_id) { $e = new Am_Event_SubscriptionAdded($this, $this->getDi()->productTable->load($product_id)); $this->getDi()->hook->call($e); } foreach ($deleted as $product_id) { $e = new Am_Event_SubscriptionDeleted($this, $this->getDi()->productTable->load($product_id)); $this->getDi()->hook->call($e); } if ($active) $newUserStatus = self::STATUS_ACTIVE; elseif (array_filter($newStatus, array($this, '_trueIfExpired'))) $newUserStatus = self::STATUS_EXPIRED; else $newUserStatus = self::STATUS_PENDING; if ($newUserStatus != @$this->status) { $this->sendSignupEmailIfNecessary(); $this->updateQuick('status', $newUserStatus); } if ($added || $deleted || array_diff_assoc($newStatus, $oldStatus)) { $this->data()->set(self::NEED_SESSION_REFRESH, true)->update(); $this->getDi()->userStatusTable->setByUserId($this->user_id, $newStatus); $e = new Am_Event_SubscriptionChanged($this, $added, $deleted); $this->getDi()->hook->call($e); } } /** * This function is called upon completion of payment * If user signup e-mail was not set before, it will be sent from there * It checks if : * - email is enabled in config * - user has at least one completed payment * - the e-mail was not sent before * - customer was approved */ function sendSignupEmailIfNecessary(InvoicePayment $p = null){ if (!$this->getDi()->config->get('send_signup_mail')) return ; if ($this->data()->get('signup_email_sent')) return ; // was already sent if (!$this->isApproved()) return ; // is not yet approved $this->sendSignupEmail($p); } function sendSignupEmail(InvoicePayment $p = null) { if ($et = Am_Mail_Template::load('send_signup_mail', $this->lang)) { $et->setUser($this); if (empty($p)) $p = $this->getDi()->invoicePaymentTable->findFirstByUserId($this->user_id); if ($p) $et->setPayment($p); $et->send($this); $this->data()->set('signup_email_sent', 1)->update(); } } function sendRegistrationEmail() { if ($et = Am_Mail_Template::load('registration_mail', $this->lang)) { $et->setUser($this); $et->password = $this->getPlaintextPass(); $et->send($this); } } function sendNotApprovedEmail(){ if($et = Am_Mail_Template::load('manually_approve', $this->lang)) { $et->setUser($this); $et->send($this); } if($et = Am_Mail_Template::load('manually_approve_admin', $this->lang)) { $et->setUser($this); $et->send(Am_Mail_Template::TO_ADMIN); } } /** * @return bool true if user have any active subscriptions */ function isActive() { return $this->status == self::STATUS_ACTIVE; } /** * Return true if customer paid at least once * @return bool */ function isPaid(){ return (bool)$this->getAdapter()->selectCell( "SELECT SUM(amount)>0 FROM ?_invoice_payment p WHERE user_id=?d" , $this->user_id); } /** * @return true if user is approved */ function isApproved(){ return !empty($this->is_approved) && ($this->is_approved > 0); } function isLocked(){ return !empty($this->is_locked) && ($this->is_locked>0); } function lock($flag = true) { $this->updateQuick('is_locked', (int)$flag); } /** * @return array of Access objects */ function getAccessRecords(){ return $this->getDi()->accessTable->findByUserId($this->user_id); } function getActiveProducts() { return $this->getDi()->productTable->loadIds($this->getActiveProductIds()); } function getExpiredProducs() { return $this->getDi()->productTable->loadIds($this->getExpiredProductIds()); } /** * Returns max expiration date * if product or array of products are specified, returns it * for given products only */ function getExpire($productIdOrIds = array()) { $productIdOrIds = (array)$productIdOrIds; $productIdOrIds = array_filter(array_map('intval', $productIdOrIds)); return $this->getDi()->db->selectCell("SELECT MAX(expire_date) FROM ?_access WHERE user_id=?d { AND product_id IN (?a) }", $this->pk(), $productIdOrIds ? $productIdOrIds : DBSIMPLE_SKIP ); } function getActiveProductsExpiration(){ $ret = array(); foreach($this->getActiveProductIds() as $pid){ $ret[$pid] = $this->getExpire($pid); } return $ret; } /** @return array of int active product# */ function getActiveProductIds(){ return $this->getAdapter()->selectCol("SELECT product_id FROM ?_user_status WHERE user_id=?d AND status=?d", $this->user_id, self::STATUS_ACTIVE); } /** @return array of int active product# */ function getExpiredProductIds(){ return $this->getAdapter()->selectCol("SELECT product_id FROM ?_user_status WHERE user_id=?d AND status=?d", $this->user_id, self::STATUS_EXPIRED); } /** * @return array product_id => status (@see self::STATUS_ACTIVE, ... constants) */ function getProductsStatus() { return $this->getDi()->userStatusTable->getByUserId($this->user_id); } /// -- implementing IMailReceiver interface */ public function getEmail() { return $this->email; } public function getName() { return @$this->name_f . ' ' . @$this->name_l; } public function isUnsubscribed() { return (bool)$this->unsubscribed; } public function canUnsubscribe() { return true; } /** param array $groups - array of id# */ function setGroups(array $groups) { $this->getAdapter()->query("DELETE FROM ?_user_user_group WHERE user_id=?d {AND user_group_id NOT IN (?a)}", $this->user_id, $groups ? $groups : DBSIMPLE_SKIP); if ($groups) { $vals = array(); foreach ($groups as $id) $vals[] = sprintf("(%d,%d)", $this->user_id, $id); $this->getAdapter()->query("INSERT IGNORE INTO ?_user_user_group (user_id, user_group_id) VALUES " . implode(", ", $vals)); } return $this; } /** @return array of id# */ function getGroups() { if (empty($this->user_id)) return array(); return $this->getAdapter()->selectCol( "SELECT DISTINCT user_group_id FROM ?_user_user_group WHERE user_id=?d", $this->user_id); } } /** * @method findFirstByLogin($login) * @method findFirstByEmail($login) */ class UserTable extends Am_Table_WithData { protected $_key = 'user_id'; protected $_table = '?_user'; protected $_recordClass = 'User'; public function init() { $this->customFields()->addCallback(array($this, 'addFieldsFromSavedConfig')); } public function clearPending($date) { $q = $this->_db->queryResultOnly("SELECT u.* FROM ?_user u LEFT JOIN ?_access a ON a.user_id = u.user_id LEFT JOIN ?_invoice_payment ip ON ip.user_id = u.user_id WHERE u.status = 0 AND IFNULL(u.is_affiliate,0)=0 AND a.access_id IS NULL AND ip.invoice_payment_id is NULL AND u.added < ? GROUP BY u.user_id", sqlTime($date)); while ($r = $this->_db->fetchRow($q)) { $u = $this->createRecord($r); $u->delete(); } } public function clearExpired($date) { // this function deletes only 500 records at time, to do not work over limits $q = $this->_db->queryResultOnly("SELECT u.* FROM ?_user u LEFT JOIN ?_access a ON a.user_id = u.user_id LEFT JOIN ?_invoice_payment ip ON ip.user_id = u.user_id WHERE u.status = 2 AND IFNULL(u.is_affiliate,0)=0 GROUP BY u.user_id HAVING GREATEST( IFNULL(MAX(ip.dattm), '2000-01-01'), IFNULL(MAX(a.expire_date), '2000-01-01')) < ? LIMIT 500 ", sqlTime($date), sqlTime($date)); while ($r = $this->_db->fetchRow($q)) { $u = $this->createRecord($r); $u->delete(); } } function addFieldsFromSavedConfig(){ foreach ((array)$this->getDi()->config->get('member_fields') as $f){ $this->customFields()->add($f['name'], $f['title'], $f['type'], $f['description'], $f['validate_func'], (array)$f['additional_fields']+array('from_config'=>1)); } } function getLoginRegex(){ return $this->getDi()->config->get('login_disallow_spaces') ? '/^[0-9a-zA-Z_]+$/D' : '/^[0-9a-zA-Z_][0-9a-zA-Z_ ]+[0-9a-zA-Z_]$/D'; } /** * Check for username iniqueness only * @param string $login * @return bool True if record unique (no such login exists), false if not-unique */ function checkUniqLogin($login, $user_id = null){ $u = $this->_db->selectCell("SELECT user_id FROM ?_user WHERE login=? { AND user_id <> ?d}", $login, $user_id ? $user_id : DBSIMPLE_SKIP); if ($u) return 0; $event = $this->getDi()->hook->call(new Am_Event_CheckUniqLogin(null, array('login' => $login, 'userId' => $user_id))); return $event->isUnique() ? -1 : false; } /** * Check for username iniqueness only * @param string $login * @return bool True if record unique (no such login exists), false if not-unique */ function checkUniqEmail($email, $user_id = null){ $u = $this->_db->selectCell("SELECT user_id FROM ?_user WHERE email=? { AND user_id <> ?d}", $email, $user_id ? $user_id : DBSIMPLE_SKIP); if ($u) return 0; $event = $this->getDi()->hook->call(new Am_Event_CheckUniqEmail(null, array('email' => $email, 'userId' => $user_id))); return $event->isUnique() ? -1 : false; } function checkAllSubscriptionsFindChanged() { $db = $this->_db; // update resource_access_cache $this->getDi()->resourceAccessTable->updateCache(); $db->query("DROP TABLE IF EXISTS ?_user_status_temp"); $db->query("CREATE TEMPORARY TABLE ?_user_status_temp ( user_id int not null, product_id int not null, status tinyint not null, INDEX(user_id,product_id)) "); // create table with calculated records from "access" $db->query(" INSERT INTO ?_user_status_temp SELECT a.user_id,a.product_id, CASE WHEN SUM(IF(a.expire_date>=?, 1, 0)) THEN 1 WHEN SUM(IF(a.expire_date< ?, 1, 0)) THEN 2 ELSE 0 END as status FROM ?_access a GROUP BY user_id,product_id ", $this->getDi()->sqlDate, $this->getDi()->sqlDate); // now select differences $ids0 = $db->selectCol(" SELECT DISTINCT ms.user_id FROM ?_user_status ms LEFT JOIN ?_user_status_temp mst ON ms.user_id =mst.user_id AND ms.product_id=mst.product_id AND ms.status =mst.status WHERE mst.user_id IS NULL GROUP BY ms.user_id,ms.product_id"); // select if there is no such a record in user_status table $ids1 = $db->selectCol("SELECT DISTINCT mst.user_id FROM ?_user_status_temp mst LEFT JOIN ?_user_status ms ON ms.user_id =mst.user_id AND ms.product_id=mst.product_id AND ms.status =mst.status WHERE ms.user_id IS NULL GROUP BY mst.user_id,mst.product_id "); // select if user record has different "status" value $ids2 = $db->selectCol("SELECT DISTINCT m.user_id, CASE WHEN SUM(IF(mst.status=1, 1, 0)) THEN 1 WHEN SUM(IF(mst.status=2, 1, 0)) THEN 2 ELSE 0 END AS calcStatus, m.status FROM ?_user m LEFT JOIN ?_user_status_temp mst USING (user_id) GROUP BY m.user_id HAVING IFNULL(calcStatus,0) <> IFNULL(m.status, 0) "); return array_unique(array_merge($ids0, $ids1, $ids2)); } /** * If this function changed, check also AdminRebuildController - it must be changed too */ function checkAllSubscriptions(){ $changed = $this->checkAllSubscriptionsFindChanged(); foreach ($changed as $user_id) { $u = $this->load($user_id, false); if ($u) $u->checkSubscriptions(false); // checked in checkAllSubscriptionsFindChanged } } /** * Find user record by email (if $login looks like an email) * or by username * @param string $login e-mail or username * @return User|null */ function getByLoginOrEmail($login){ if (!strlen($login)) return null; if (strpos($login, '@')!==false) return $this->findFirstByEmail($login); else return $this->findFirstByLogin($login); } /** * Find record by login, check password and return it if all OK * with login/password * sets $resultCode from Am_Auth_Result * @return User */ function getAuthenticatedRow($login, $pass, & $code = null){ if(empty($login) || empty($pass)) { $code = Am_Auth_Result::INVALID_INPUT; return; } $u = $this->getByLoginOrEmail($login); if (!$u) { $code = Am_Auth_Result::USER_NOT_FOUND; return; } if (!$u->checkPassword($pass)) { $code = Am_Auth_Result::WRONG_CREDENTIALS; return; } $code = Am_Auth_Result::SUCCESS; return $u; } function getAuthenticatedCookieRow($cLogin, $cPass, & $code = null){ if (empty($cLogin) || empty($cPass)) { $code = Am_Auth_Result::INVALID_INPUT; return null; } $u = $this->getByLoginOrEmail($cLogin); if (!$u) { $code = Am_Auth_Result::USER_NOT_FOUND; return; } if ($u->getLoginCookie() !== $cPass) { $code = Am_Auth_Result::WRONG_CREDENTIALS; return null; } $code = Am_Auth_Result::SUCCESS; return $u; } function selectLast($num) { return $this->selectObjects("SELECT m.*, SUM(p.amount) AS paid FROM ?_user m LEFT JOIN ?_invoice_payment p USING (user_id) GROUP BY m.user_id ORDER BY m.user_id DESC LIMIT ?d", $num); } }
Upload Files
Cancel
Upload
Create New
Cancel
Create
Change Permissions
Cancel
Save
Change Date
Cancel
Save
Rename Item
Cancel
Save
Confirm Delete
Are you sure you want to delete the selected items?
Cancel
Delete