golden hour
/home/doctorbruno/public_html/doctorbruno.info/taeionline/support/include
⬆️ Go Up
Upload
File/Folder
Size
Actions
.MANIFEST
194.97 KB
Del
OK
.htaccess
14 B
Del
OK
JSON.php
33.13 KB
Del
OK
PasswordHash.php
6.92 KB
Del
OK
Spyc.php
31.74 KB
Del
OK
UniversalClassLoader.php
8.61 KB
Del
OK
ajax.admin.php
7.29 KB
Del
OK
ajax.config.php
4.61 KB
Del
OK
ajax.content.php
9.76 KB
Del
OK
ajax.draft.php
13.03 KB
Del
OK
ajax.email.php
2.33 KB
Del
OK
ajax.export.php
1006 B
Del
OK
ajax.filter.php
874 B
Del
OK
ajax.forms.php
13.84 KB
Del
OK
ajax.i18n.php
5.1 KB
Del
OK
ajax.kbase.php
2.93 KB
Del
OK
ajax.note.php
2.05 KB
Del
OK
ajax.orgs.php
11.73 KB
Del
OK
ajax.plugins.php
2.15 KB
Del
OK
ajax.schedule.php
4.29 KB
Del
OK
ajax.search.php
12.72 KB
Del
OK
ajax.sequence.php
3.2 KB
Del
OK
ajax.staff.php
11.62 KB
Del
OK
ajax.tasks.php
33.87 KB
Del
OK
ajax.thread.php
8.81 KB
Del
OK
ajax.tickets.php
79.7 KB
Del
OK
ajax.tips.php
1.66 KB
Del
OK
ajax.upgrader.php
2.24 KB
Del
OK
ajax.users.php
18.33 KB
Del
OK
api.cron.php
1.06 KB
Del
OK
api.tickets.php
10.36 KB
Del
OK
class.2fa.php
7.76 KB
Del
OK
class.ajax.php
1.45 KB
Del
OK
class.api.php
15.31 KB
Del
OK
class.app.php
1.49 KB
Del
OK
class.attachment.php
6.95 KB
Del
OK
class.auth.php
50.73 KB
Del
OK
class.avatar.php
6.44 KB
Del
OK
class.banlist.php
2.58 KB
Del
OK
class.base32.php
4.07 KB
Del
OK
class.businesshours.php
7.08 KB
Del
OK
class.canned.php
9.05 KB
Del
OK
class.captcha.php
1.73 KB
Del
OK
class.category.php
11.14 KB
Del
OK
class.charset.php
3.41 KB
Del
OK
class.cli.php
9.48 KB
Del
OK
class.client.php
15.39 KB
Del
OK
class.collaborator.php
5.65 KB
Del
OK
class.company.php
2.65 KB
Del
OK
class.config.php
60.36 KB
Del
OK
class.controller.php
1.15 KB
Del
OK
class.cron.php
3.6 KB
Del
OK
class.crypto.php
18.92 KB
Del
OK
class.csrf.php
2.38 KB
Del
OK
class.dept.php
33.21 KB
Del
OK
class.dispatcher.php
7.12 KB
Del
OK
class.draft.php
6.23 KB
Del
OK
class.dynamic_forms.php
64.98 KB
Del
OK
class.email.php
49 KB
Del
OK
class.error.php
1.69 KB
Del
OK
class.export.php
32.92 KB
Del
OK
class.faq.php
15.05 KB
Del
OK
class.file.php
34.59 KB
Del
OK
class.filter.php
31.9 KB
Del
OK
class.filter_action.php
23.67 KB
Del
OK
class.format.php
44.3 KB
Del
OK
class.forms.php
195.58 KB
Del
OK
class.http.php
7.16 KB
Del
OK
class.i18n.php
24.28 KB
Del
OK
class.import.php
6.9 KB
Del
OK
class.json.php
2.71 KB
Del
OK
class.knowledgebase.php
5.8 KB
Del
OK
class.list.php
42 KB
Del
OK
class.lock.php
4.05 KB
Del
OK
class.log.php
1.55 KB
Del
OK
class.mail.php
35.76 KB
Del
OK
class.mailer.php
25.75 KB
Del
OK
class.mailfetch.php
9.72 KB
Del
OK
class.mailparse.php
30.99 KB
Del
OK
class.message.php
6.42 KB
Del
OK
class.migrater.php
5.2 KB
Del
OK
class.misc.php
7.5 KB
Del
OK
class.model.php
2.3 KB
Del
OK
class.nav.php
14.15 KB
Del
OK
class.note.php
2.39 KB
Del
OK
class.oauth2.php
4.04 KB
Del
OK
class.organization.php
22.45 KB
Del
OK
class.orm.php
120.9 KB
Del
OK
class.osticket.php
20.64 KB
Del
OK
class.ostsession.php
21.86 KB
Del
OK
class.page.php
10.59 KB
Del
OK
class.pagenate.php
5.53 KB
Del
OK
class.passwd.php
1.21 KB
Del
OK
class.pdf.php
3.83 KB
Del
OK
class.plugin.php
36.13 KB
Del
OK
class.priority.php
1.81 KB
Del
OK
class.queue.php
103.51 KB
Del
OK
class.report.php
11.76 KB
Del
OK
class.role.php
11.27 KB
Del
OK
class.schedule.php
46.28 KB
Del
OK
class.search.php
61.66 KB
Del
OK
class.sequence.php
7.27 KB
Del
OK
class.session.php
19.25 KB
Del
OK
class.setup.php
3.55 KB
Del
OK
class.signal.php
4.16 KB
Del
OK
class.sla.php
9.11 KB
Del
OK
class.staff.php
60.21 KB
Del
OK
class.task.php
56.21 KB
Del
OK
class.team.php
12.31 KB
Del
OK
class.template.php
23.45 KB
Del
OK
class.thread.php
108.96 KB
Del
OK
class.thread_actions.php
17.08 KB
Del
OK
class.ticket.php
167.39 KB
Del
OK
class.timezone.php
21.94 KB
Del
OK
class.topic.php
20.06 KB
Del
OK
class.translation.php
34.79 KB
Del
OK
class.upgrader.php
13.76 KB
Del
OK
class.user.php
43.4 KB
Del
OK
class.usersession.php
7.55 KB
Del
OK
class.util.php
10.07 KB
Del
OK
class.validator.php
12.94 KB
Del
OK
class.variable.php
11.93 KB
Del
OK
class.xml.php
3.23 KB
Del
OK
class.yaml.php
1.15 KB
Del
OK
cli
-
Del
OK
client
-
Del
OK
config
-
Del
OK
fpdf
-
Del
OK
htmLawed.php
53.53 KB
Del
OK
html2text.php
33.71 KB
Del
OK
i18n
-
Del
OK
index.php
37 B
Del
OK
laminas-mail
-
Del
OK
mpdf
-
Del
OK
mysqli.php
9.55 KB
Del
OK
ost-config.php
5.63 KB
Del
OK
ost-sampleconfig.php
6.24 KB
Del
OK
pear
-
Del
OK
plugins
-
Del
OK
staff
-
Del
OK
tnef_decoder.php
19.82 KB
Del
OK
upgrader
-
Del
OK
Edit: class.user.php
<?php /********************************************************************* class.user.php External end-user identification for osTicket Peter Rotich <peter@osticket.com> Jared Hancock <jared@osticket.com> Copyright (c) 2006-2013 osTicket http://www.osticket.com Released under the GNU General Public License WITHOUT ANY WARRANTY. See LICENSE.TXT for details. vim: expandtab sw=4 ts=4 sts=4: **********************************************************************/ require_once INCLUDE_DIR . 'class.orm.php'; require_once INCLUDE_DIR . 'class.util.php'; require_once INCLUDE_DIR . 'class.variable.php'; require_once INCLUDE_DIR . 'class.search.php'; require_once INCLUDE_DIR . 'class.organization.php'; class UserEmailModel extends VerySimpleModel { static $meta = array( 'table' => USER_EMAIL_TABLE, 'pk' => array('id'), 'joins' => array( 'user' => array( 'constraint' => array('user_id' => 'UserModel.id') ) ) ); function __toString() { return (string) $this->address; } static function getIdByEmail($email) { $row = UserEmailModel::objects() ->filter(array('address'=>$email)) ->values_flat('user_id') ->first(); return $row ? $row[0] : 0; } } class UserModel extends VerySimpleModel { static $meta = array( 'table' => USER_TABLE, 'pk' => array('id'), 'select_related' => array('default_email', 'org', 'account'), 'joins' => array( 'emails' => array( 'reverse' => 'UserEmailModel.user', ), 'tickets' => array( 'null' => true, 'reverse' => 'Ticket.user', ), 'account' => array( 'list' => false, 'null' => true, 'reverse' => 'ClientAccount.user', ), 'org' => array( 'null' => true, 'constraint' => array('org_id' => 'Organization.id') ), 'default_email' => array( 'null' => true, 'constraint' => array('default_email_id' => 'UserEmailModel.id') ), 'cdata' => array( 'constraint' => array('id' => 'UserCdata.user_id'), 'null' => true, ), 'entries' => array( 'constraint' => array( 'id' => 'DynamicFormEntry.object_id', "'U'" => 'DynamicFormEntry.object_type', ), 'list' => true, ), ) ); const PRIMARY_ORG_CONTACT = 0x0001; const PERM_CREATE = 'user.create'; const PERM_EDIT = 'user.edit'; const PERM_DELETE = 'user.delete'; const PERM_MANAGE = 'user.manage'; const PERM_DIRECTORY = 'user.dir'; static protected $perms = array( self::PERM_CREATE => array( 'title' => /* @trans */ 'Create', 'desc' => /* @trans */ 'Ability to add new users', 'primary' => true, ), self::PERM_EDIT => array( 'title' => /* @trans */ 'Edit', 'desc' => /* @trans */ 'Ability to manage user information', 'primary' => true, ), self::PERM_DELETE => array( 'title' => /* @trans */ 'Delete', 'desc' => /* @trans */ 'Ability to delete users', 'primary' => true, ), self::PERM_MANAGE => array( 'title' => /* @trans */ 'Manage Account', 'desc' => /* @trans */ 'Ability to manage active user accounts', 'primary' => true, ), self::PERM_DIRECTORY => array( 'title' => /* @trans */ 'User Directory', 'desc' => /* @trans */ 'Ability to access the user directory', 'primary' => true, ), ); function getId() { return $this->id; } function getDefaultEmailAddress() { return $this->getDefaultEmail()->address; } function getDefaultEmail() { return $this->default_email; } function hasAccount() { return !is_null($this->account); } function getAccount() { return $this->account; } function getOrgId() { return $this->get('org_id'); } function getOrganization() { return $this->org; } function setOrganization($org, $save=true) { $this->set('org', $org); if ($save) $this->save(); return true; } public function setFlag($flag, $val) { if ($val) $this->status |= $flag; else $this->status &= ~$flag; } protected function hasStatus($flag) { return $this->get('status') & $flag !== 0; } protected function clearStatus($flag) { return $this->set('status', $this->get('status') & ~$flag); } protected function setStatus($flag) { return $this->set('status', $this->get('status') | $flag); } function isPrimaryContact() { return $this->hasStatus(User::PRIMARY_ORG_CONTACT); } function setPrimaryContact($flag) { if ($flag) $this->setStatus(User::PRIMARY_ORG_CONTACT); else $this->clearStatus(User::PRIMARY_ORG_CONTACT); } static function getPermissions() { return self::$perms; } } include_once INCLUDE_DIR.'class.role.php'; RolePermission::register(/* @trans */ 'Users', UserModel::getPermissions()); class UserCdata extends VerySimpleModel { static $meta = array( 'table' => USER_CDATA_TABLE, 'pk' => array('user_id'), 'joins' => array( 'user' => array( 'constraint' => array('user_id' => 'UserModel.id'), ), ), ); } class User extends UserModel implements TemplateVariable, Searchable { var $_email; var $_entries; var $_forms; var $_queue; static function fromVars($vars, $create=true, $update=false) { // Try and lookup by email address $user = static::lookupByEmail($vars['email']); if (!$user // can create user? && $create // Make sure at least email is valid && Validator::is_email($vars['email'])) { $name = $vars['name']; if (is_array($name)) $name = implode(', ', $name); elseif (!$name) list($name) = explode('@', $vars['email'], 2); $user = new User(array( 'name' => Format::htmldecode(Format::sanitize($name, false)), 'created' => new SqlFunction('NOW'), 'updated' => new SqlFunction('NOW'), //XXX: Do plain create once the cause // of the detached emails is fixed. 'default_email' => UserEmail::ensure($vars['email']) )); // Is there an organization registered for this domain list($mailbox, $domain) = explode('@', $vars['email'], 2); if (isset($vars['org_id'])) $user->set('org_id', $vars['org_id']); elseif ($org = Organization::forDomain($domain)) $user->setOrganization($org, false); try { $user->save(true); $user->emails->add($user->default_email); // Attach initial custom fields $user->addDynamicData($vars); } catch (OrmException $e) { return null; } $type = array('type' => 'created'); Signal::send('object.created', $user, $type); Signal::send('user.created', $user); } elseif ($update && $user) { $errors = array(); $user->updateInfo($vars, $errors, true); } return $user; } static function fromForm($form, $create=true) { global $thisstaff; if(!$form) return null; //Validate the form $valid = true; $filter = function($f) use ($thisstaff) { return !isset($thisstaff) || $f->isRequiredForStaff() || $f->isVisibleToStaff(); }; if (!$form->isValid($filter)) $valid = false; //Make sure the email is not in-use if (($field=$form->getField('email')) && $field->getClean() && User::lookup(array('emails__address'=>$field->getClean()))) { $field->addError(__('Email is assigned to another user')); $valid = false; } return $valid ? self::fromVars($form->getClean(), $create) : null; } function getEmail() { if (!isset($this->_email)) $this->_email = new EmailAddress(sprintf('"%s" <%s>', addcslashes($this->getName(), '"'), $this->default_email->address)); return $this->_email; } function getAvatar($size=null) { global $cfg; $source = $cfg->getClientAvatarSource(); $avatar = $source->getAvatar($this); if (isset($size)) $avatar->setSize($size); return $avatar; } function getFullName() { return $this->name; } function getPhoneNumber() { foreach ($this->getDynamicData() as $e) if ($a = $e->getAnswer('phone')) return $a; } function getName() { if (!$this->name) list($name) = explode('@', $this->getDefaultEmailAddress(), 2); else $name = $this->name; return new UsersName($name); } function getUpdateDate() { return $this->updated; } function getCreateDate() { return $this->created; } function getTimezone() { global $cfg; if (($acct = $this->getAccount()) && ($tz = $acct->getTimezone())) { return $tz; } return $cfg->getDefaultTimezone(); } function addForm($form, $sort=1, $data=null) { $entry = $form->instanciate($sort, $data); $entry->set('object_type', 'U'); $entry->set('object_id', $this->getId()); $entry->save(); return $entry; } function getLanguage($flags=false) { if ($acct = $this->getAccount()) return $acct->getLanguage($flags); } function to_json() { $info = array( 'id' => $this->getId(), 'name' => Format::htmlchars($this->getName()), 'email' => (string) $this->getEmail(), 'phone' => (string) $this->getPhoneNumber()); return Format::json_encode($info); } function __toString() { return $this->asVar(); } function asVar() { return (string) $this->getName(); } function getVar($tag) { $tag = mb_strtolower($tag); foreach ($this->getDynamicData() as $e) if ($a = $e->getAnswer($tag)) return $a; } static function getVarScope() { $base = array( 'email' => array( 'class' => 'EmailAddress', 'desc' => __('Default email address') ), 'name' => array( 'class' => 'PersonsName', 'desc' => 'User name, default format' ), 'organization' => array('class' => 'Organization', 'desc' => __('Organization')), ); $extra = VariableReplacer::compileFormScope(UserForm::getInstance()); return $base + $extra; } static function getSearchableFields() { $base = array(); $uform = UserForm::getUserForm(); $base = array(); foreach ($uform->getFields() as $F) { $fname = $F->get('name') ?: ('field_'.$F->get('id')); # XXX: email in the model corresponds to `emails__address` ORM path if ($fname == 'email') $fname = 'emails__address'; if (!$F->hasData() || $F->isPresentationOnly()) continue; if (!$F->isStorable()) $base[$fname] = $F; else $base["cdata__{$fname}"] = $F; } return $base; } static function supportsCustomData() { return true; } function addDynamicData($data) { return $this->addForm(UserForm::objects()->one(), 1, $data); } function getDynamicData($create=true) { if (!isset($this->_entries)) { $this->_entries = DynamicFormEntry::forObject($this->id, 'U')->all(); if (!$this->_entries && $create) { $g = UserForm::getNewInstance(); $g->setClientId($this->id); $g->save(); $this->_entries[] = $g; } } return $this->_entries ?: array(); } function getFilterData() { $vars = array(); foreach ($this->getDynamicData() as $entry) { $vars += $entry->getFilterData(); // Add in special `name` and `email` fields if ($entry->getDynamicForm()->get('type') != 'U') continue; foreach (array('name', 'email') as $name) { if ($f = $entry->getField($name)) $vars['field.'.$f->get('id')] = $name == 'name' ? $this->getName() : $this->getEmail(); } } return $vars; } function getForms($data=null, $cb=null) { if (!isset($this->_forms)) { $this->_forms = array(); $cb = $cb ?: function ($f) use($data) { return ($data); }; foreach ($this->getDynamicData() as $entry) { $entry->addMissingFields(); if(($form = $entry->getDynamicForm()) && $form->get('type') == 'U' ) { foreach ($entry->getFields() as $f) { if ($f->get('name') == 'name' && !$cb($f)) $f->value = $this->getFullName(); elseif ($f->get('name') == 'email' && !$cb($f)) $f->value = $this->getEmail(); } } $this->_forms[] = $entry; } } return $this->_forms; } function getAccountStatus() { if (!($account=$this->getAccount())) return __('Guest'); return (string) $account->getStatus(); } function canSeeOrgTickets() { return $this->org && ( $this->org->shareWithEverybody() || ($this->isPrimaryContact() && $this->org->shareWithPrimaryContacts())); } function register($vars, &$errors) { // user already registered? if ($this->getAccount()) return true; return UserAccount::register($this, $vars, $errors); } static function importCsv($stream, $defaults=array()) { require_once INCLUDE_DIR . 'class.import.php'; $importer = new CsvImporter($stream); $imported = 0; try { db_autocommit(false); $records = $importer->importCsv(UserForm::getUserForm()->getFields(), $defaults); foreach ($records as $data) { if (!Validator::is_email($data['email']) || empty($data['name'])) throw new ImportError('Both `name` and `email` fields are required'); if (!($user = static::fromVars($data, true, true))) throw new ImportError(sprintf(__('Unable to import user: %s'), print_r(Format::htmlchars($data), true))); $imported++; } db_autocommit(true); } catch (Exception $ex) { db_rollback(); return $ex->getMessage(); } return $imported; } static function importFromPost($stream, $extra=array()) { if (!is_array($stream)) $stream = sprintf('name, email%s %s',PHP_EOL, $stream); return User::importCsv($stream, $extra); } function updateInfo($vars, &$errors, $staff=false) { $isEditable = function ($f) use($staff) { return ($staff ? $f->isEditableToStaff() : $f->isEditableToUsers()); }; $valid = true; $forms = $this->getForms($vars, $isEditable); foreach ($forms as $entry) { $entry->setSource($vars); if ($staff && !$entry->isValidForStaff(true)) $valid = false; elseif (!$staff && !$entry->isValidForClient(true)) $valid = false; elseif ($entry->getDynamicForm()->get('type') == 'U' && ($f=$entry->getField('email')) && $isEditable($f) && $f->getClean() && ($u=User::lookup(array('emails__address'=>$f->getClean()))) && $u->id != $this->getId()) { $valid = false; $f->addError(__('Email is assigned to another user')); } if (!$valid) $errors = array_merge($errors, $entry->errors()); } if (!$valid) return false; // Save the entries foreach ($forms as $entry) { $fields = $entry->getFields(); foreach ($fields as $field) { $changes = $field->getChanges(); if ((is_array($changes) && $changes[0]) || $changes && !is_array($changes)) { $type = array('type' => 'edited', 'key' => $field->getLabel()); Signal::send('object.edited', $this, $type); } } if ($entry->getDynamicForm()->get('type') == 'U') { // Name field if (($name = $entry->getField('name')) && $isEditable($name) ) { $name = $name->getClean(); if (is_array($name)) $name = implode(', ', $name); if ($this->name != $name) { $type = array('type' => 'edited', 'key' => 'Name'); Signal::send('object.edited', $this, $type); } $this->name = $name; } // Email address field if (($email = $entry->getField('email')) && $isEditable($email)) { if ($this->default_email->address != $email->getClean()) { $type = array('type' => 'edited', 'key' => 'Email'); Signal::send('object.edited', $this, $type); } $this->default_email->address = $email->getClean(); $this->default_email->save(); } } // DynamicFormEntry::saveAnswers returns the number of answers updated if ($entry->saveAnswers($isEditable)) { $this->updated = SqlFunction::NOW(); } } return $this->save(); } function save($refetch=false) { // Drop commas and reorganize the name without them $parts = array_map('trim', explode(',', $this->name)); switch (count($parts)) { case 2: // Assume last, first --or-- last suff., first $this->name = $parts[1].' '.$parts[0]; // XXX: Consider last, first suff. break; case 3: // Assume last, first, suffix, write 'first last suffix' $this->name = $parts[1].' '.$parts[0].' '.$parts[2]; break; } // Handle email addresses -- use the box name if (Validator::is_email($this->name)) { list($box, $domain) = explode('@', $this->name, 2); if (strpos($box, '.') !== false) $this->name = str_replace('.', ' ', $box); else $this->name = $box; $this->name = mb_convert_case($this->name, MB_CASE_TITLE); } if (count($this->dirty)) //XXX: doesn't work?? $this->set('updated', new SqlFunction('NOW')); return parent::save($refetch); } function delete() { // Refuse to delete a user with tickets if ($this->tickets->count()) return false; // Delete account record (if any) if ($this->getAccount()) $this->getAccount()->delete(); // Delete emails. $this->emails->expunge(); // Drop dynamic data foreach ($this->getDynamicData() as $entry) { $entry->delete(); } $type = array('type' => 'deleted'); Signal::send('object.deleted', $this, $type); // Delete user return parent::delete(); } function deleteAllTickets() { $status_id = TicketStatus::lookup(array('state' => 'deleted')); foreach($this->tickets as $ticket) { if (!$T = Ticket::lookup($ticket->getId())) continue; if (!$T->setStatus($status_id)) return false; } $this->tickets->reset(); return true; } static function lookupByEmail($email) { return static::lookup(array('emails__address'=>$email)); } static function getNameById($id) { if ($user = static::lookup($id)) return $user->getName(); } static function getLink($id) { global $thisstaff; if (!$id || !$thisstaff) return false; return ROOT_PATH . sprintf('scp/users.php?id=%s', $id); } function getTicketsQueue($collabs=true) { global $thisstaff; if (!$this->_queue) { $email = $this->getDefaultEmailAddress(); $filter = [ ['user__id', 'equal', $this->getId()], ]; if ($collabs) $filter = [ ['user__emails__address', 'equal', $email], ['thread__collaborators__user__emails__address', 'equal', $email], ]; $this->_queue = new AdhocSearch(array( 'id' => 'adhoc,uid'.$this->getId(), 'root' => 'T', 'staff_id' => $thisstaff->getId(), 'title' => $this->getName() )); $this->_queue->config = $filter; } return $this->_queue; } } class EmailAddress implements TemplateVariable { var $email; var $address; protected $_info; function __construct($address) { $this->_info = self::parse($address); $this->email = sprintf('%s@%s', $this->getMailbox(), $this->getDomain()); if ($this->getName()) $this->address = sprintf('"%s" <%s>', $this->getName(), $this->email); else $this->address = $this->email; } function __toString() { return (string) $this->email; } function getVar($what) { if (!isset($this->_info)) return ''; switch ($what) { case 'host': case 'domain': return $this->_info->host; case 'personal': return trim($this->_info->personal, '"'); case 'mailbox': return $this->_info->mailbox; } } function getAddress() { return $this->address ?: $this->getEmail(); } function getEmail() { return $this->email; } function getHost() { return $this->getVar('host'); } function getDomain() { return $this->getHost(); } function getName() { return $this->getVar('personal'); } function getMailbox() { return $this->getVar('mailbox'); } // Parse and email adddress (RFC822) into it's parts. // @address - one address is expected static function parse($address) { require_once PEAR_DIR . 'PEAR.php'; if (($parts = Mail_Parse::parseAddressList($address)) && !PEAR::isError($parts)) return current($parts); } static function getVarScope() { return array( 'domain' => __('Domain'), 'mailbox' => __('Mailbox'), 'personal' => __('Personal name'), ); } } class PersonsName implements TemplateVariable { var $format; var $parts; var $name; static $formats = array( 'first' => array( /*@trans*/ "First", 'getFirst'), 'last' => array( /*@trans*/ "Last", 'getLast'), 'full' => array( /*@trans*/ "First Last", 'getFull'), 'legal' => array( /*@trans*/ "First M. Last", 'getLegal'), 'lastfirst' => array( /*@trans*/ "Last, First", 'getLastFirst'), 'formal' => array( /*@trans*/ "Mr. Last", 'getFormal'), 'short' => array( /*@trans*/ "First L.", 'getShort'), 'shortformal' => array(/*@trans*/ "F. Last", 'getShortFormal'), 'complete' => array( /*@trans*/ "Mr. First M. Last Sr.", 'getComplete'), 'original' => array( /*@trans*/ '-- As Entered --', 'getOriginal'), ); function __construct($name, $format=null) { global $cfg; if ($format && isset(static::$formats[$format])) $this->format = $format; else $this->format = 'original'; if (!is_array($name)) { $this->parts = static::splitName($name); $this->name = $name; } else { $this->parts = $name; $this->name = implode(' ', $name); } } function getFirst() { return $this->parts['first']; } function getLast() { return $this->parts['last']; } function getMiddle() { return $this->parts['middle']; } function getFirstInitial() { if ($this->parts['first']) return mb_substr($this->parts['first'],0,1).'.'; return ''; } function getMiddleInitial() { if ($this->parts['middle']) return mb_substr($this->parts['middle'],0,1).'.'; return ''; } function getLastInitial() { if ($this->parts['last']) return mb_substr($this->parts['last'],0,1).'.'; return ''; } function getFormal() { return trim($this->parts['salutation'].' '.$this->parts['last']); } function getFull() { return trim($this->parts['first'].' '.$this->parts['last']); } function getLegal() { $parts = array( $this->parts['first'], $this->getMiddleInitial(), $this->parts['last'], ); return implode(' ', array_filter($parts)); } function getComplete() { $parts = array( $this->parts['salutation'], $this->parts['first'], $this->getMiddleInitial(), $this->parts['last'], $this->parts['suffix'] ); return implode(' ', array_filter($parts)); } function getLastFirst() { $name = $this->parts['last'].', '.$this->parts['first']; $name = trim($name, ', '); if ($this->parts['suffix']) $name .= ', '.$this->parts['suffix']; return $name; } function getShort() { return $this->parts['first'].' '.$this->getLastInitial(); } function getShortFormal() { return $this->getFirstInitial().' '.$this->parts['last']; } function getOriginal() { return $this->name; } function getInitials() { $names = array($this->parts['first']); $names = array_merge($names, explode(' ', $this->parts['middle'])); $names[] = $this->parts['last']; $initials = ''; foreach (array_filter($names) as $n) $initials .= mb_substr($n,0,1); return mb_convert_case($initials, MB_CASE_UPPER); } function getName() { return $this; } function getNameFormats($user, $type) { $nameFormats = array(); foreach (PersonsName::allFormats() as $format => $func) { $nameFormats[$type . '.name.' . $format] = $user->getName()->$func[1](); } return $nameFormats; } function asVar() { return $this->__toString(); } static function getVarScope() { $formats = array(); foreach (static::$formats as $name=>$info) { if (in_array($name, array('original', 'complete'))) continue; $formats[$name] = $info[0]; } return $formats; } function __toString() { @list(, $func) = static::$formats[$this->format]; if (!$func) $func = 'getFull'; return (string) call_user_func(array($this, $func)); } static function allFormats() { return static::$formats; } /** * Thanks, http://stackoverflow.com/a/14420217 */ static function splitName($name) { $results = array(); $r = explode(' ', $name); $size = count($r); //check if name is bad format (ex: J.Everybody), and fix them if($size==1 && mb_strpos($r[0], '.') !== false) { $r = explode('.', $name); $size = count($r); } //check first for period, assume salutation if so if (mb_strpos($r[0], '.') === false) { $results['salutation'] = ''; $results['first'] = $r[0]; } else { $results['salutation'] = $r[0]; $results['first'] = $r[1]; } //check last for period, assume suffix if so if (mb_strpos($r[$size - 1], '.') === false) { $results['suffix'] = ''; } else { $results['suffix'] = $r[$size - 1]; } //combine remains into last $start = ($results['salutation']) ? 2 : 1; $end = ($results['suffix']) ? $size - 2 : $size - 1; $middle = array(); for ($i = $start; $i <= $end; $i++) { $middle[] = $r[$i]; } if (count($middle) > 1) { $results['last'] = array_pop($middle); $results['middle'] = implode(' ', $middle); } else { $results['last'] = $middle[0]; $results['middle'] = ''; } return $results; } } class AgentsName extends PersonsName { function __construct($name, $format=null) { global $cfg; if (!$format && $cfg) $format = $cfg->getAgentNameFormat(); parent::__construct($name, $format); } } class UsersName extends PersonsName { function __construct($name, $format=null) { global $cfg; if (!$format && $cfg) $format = $cfg->getClientNameFormat(); parent::__construct($name, $format); } } class UserEmail extends UserEmailModel { static function ensure($address) { $email = static::lookup(array('address'=>$address)); if (!$email) { $email = new static(array('address'=>$address)); $email->save(); } return $email; } } class UserAccount extends VerySimpleModel { static $meta = array( 'table' => USER_ACCOUNT_TABLE, 'pk' => array('id'), 'joins' => array( 'user' => array( 'null' => false, 'constraint' => array('user_id' => 'User.id') ), ), ); const LANG_MAILOUTS = 1; // Language preference for mailouts var $_status; var $_extra; function getStatus() { if (!isset($this->_status)) $this->_status = new UserAccountStatus($this->get('status')); return $this->_status; } function statusChanged($flag, $var) { if (($this->hasStatus($flag) && !$var) || (!$this->hasStatus($flag) && $var)) return true; } protected function hasStatus($flag) { return $this->getStatus()->check($flag); } protected function clearStatus($flag) { return $this->set('status', $this->get('status') & ~$flag); } protected function setStatus($flag) { return $this->set('status', $this->get('status') | $flag); } function confirm() { $this->setStatus(UserAccountStatus::CONFIRMED); return $this->save(); } function isConfirmed() { return $this->getStatus()->isConfirmed(); } function lock() { $this->setStatus(UserAccountStatus::LOCKED); return $this->save(); } function unlock() { $this->clearStatus(UserAccountStatus::LOCKED); return $this->save(); } function isLocked() { return $this->getStatus()->isLocked(); } function isActive() { return (!$this->isLocked() && $this->isConfirmed()); } function forcePasswdReset() { $this->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); return $this->save(); } function isPasswdResetForced() { return $this->hasStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); } function isPasswdResetEnabled() { return !$this->hasStatus(UserAccountStatus::FORBID_PASSWD_RESET); } function getInfo() { return $this->ht; } function getId() { return $this->get('id'); } function getUserId() { return $this->get('user_id'); } function getUser() { return $this->user; } function getUserName() { return $this->getUser()->getName(); } function getExtraAttr($attr=false, $default=null) { if (!isset($this->_extra)) $this->_extra = JsonDataParser::decode($this->get('extra', '')); return $attr ? (@$this->_extra[$attr] ?: $default) : $this->_extra; } function setExtraAttr($attr, $value) { $this->getExtraAttr(); $this->_extra[$attr] = $value; } /** * Function: getLanguage * * Returns the language preference for the user or false if no * preference is defined. False indicates the browser indicated * preference should be used. For requests apart from browser requests, * the last language preference of the browser is set in the * 'browser_lang' extra attribute upon logins. Send the LANG_MAILOUTS * flag to also consider this saved value. Such is useful when sending * the user a message (such as an email), and the user's browser * preference is not available in the HTTP request. * * Parameters: * $flags - (int) Send UserAccount::LANG_MAILOUTS if the user's * last-known browser preference should be considered. Normally * only the user's saved language preference is considered. * * Returns: * Current or last-known language preference or false if no language * preference is currently set or known. */ function getLanguage($flags=false) { $lang = $this->get('lang', false); if (!$lang && ($flags & UserAccount::LANG_MAILOUTS)) $lang = $this->getExtraAttr('browser_lang', false); return $lang; } function getTimezone() { return $this->timezone; } function save($refetch=false) { // Serialize the extra column on demand if (isset($this->_extra)) { $this->extra = JsonDataEncoder::encode($this->_extra); } return parent::save($refetch); } function hasPassword() { return (bool) $this->get('passwd'); } function sendResetEmail() { return $this->sendUnlockEmail('pwreset-client') === true; } function sendConfirmEmail() { return $this->sendUnlockEmail('registration-client') === true; } function setPassword($new) { $this->set('passwd', Passwd::hash($new)); // Clean sessions Signal::send('auth.clean', $this->getUser()); } protected function sendUnlockEmail($template) { global $ost, $cfg; $token = Misc::randCode(48); // 290-bits $email = $cfg->getDefaultEmail(); $content = Page::lookupByType($template); if (!$email || !$content) return new BaseError(sprintf(_S('%s: Unable to retrieve template'), $template)); $vars = array( 'url' => $ost->getConfig()->getBaseUrl(), 'token' => $token, 'user' => $this->getUser(), 'recipient' => $this->getUser(), 'link' => sprintf( "%s/pwreset.php?token=%s", $ost->getConfig()->getBaseUrl(), $token), ); $vars['reset_link'] = &$vars['link']; $info = array('email' => $email, 'vars' => &$vars, 'log'=>true); Signal::send('auth.pwreset.email', $this->getUser(), $info); $lang = $this->getLanguage(UserAccount::LANG_MAILOUTS); $msg = $ost->replaceTemplateVariables(array( 'subj' => $content->getLocalName($lang), 'body' => $content->getLocalBody($lang), ), $vars); $_config = new Config('pwreset'); $_config->set($vars['token'], 'c'.$this->getUser()->getId()); $email->send($this->getUser()->getEmail(), Format::striptags($msg['subj']), $msg['body']); return true; } function __toString() { return (string) $this->getStatus(); } /* * Updates may be done by Staff or by the User if registration * options are set to Public */ function update($vars, &$errors) { // TODO: Make sure the username is unique // Timezone selection is not required. System default is a valid // fallback // Changing password? if ($vars['passwd1'] || $vars['passwd2']) { if (!$vars['passwd1']) $errors['passwd1'] = __('New password is required'); else { try { self::checkPassword($vars['passwd1']); } catch (BadPassword $ex) { $errors['passwd1'] = $ex->getMessage(); } } } // Make sure the username is not an email. if ($vars['username'] && Validator::is_email($vars['username'])) $errors['username'] = __('Users can always sign in with their email address'); if ($errors) return false; //flags $pwreset = $this->statusChanged(UserAccountStatus::REQUIRE_PASSWD_RESET, $vars['pwreset-flag']); $locked = $this->statusChanged(UserAccountStatus::LOCKED, $vars['locked-flag']); $forbidPwChange = $this->statusChanged(UserAccountStatus::FORBID_PASSWD_RESET, $vars['forbid-pwchange-flag']); $info = $this->getInfo(); foreach ($vars as $key => $value) { if (($key != 'id' && $info[$key] && $info[$key] != $value) || ($pwreset && $key == 'pwreset-flag' || $locked && $key == 'locked-flag' || $forbidPwChange && $key == 'forbid-pwchange-flag')) { $type = array('type' => 'edited', 'key' => $key); Signal::send('object.edited', $this, $type); } } $this->set('timezone', $vars['timezone']); $this->set('username', Format::sanitize($vars['username'])); if ($vars['passwd1']) { $this->setPassword($vars['passwd1']); $this->setStatus(UserAccountStatus::CONFIRMED); $type = array('type' => 'edited', 'key' => 'password'); Signal::send('object.edited', $this, $type); } // Set flags foreach (array( 'pwreset-flag' => UserAccountStatus::REQUIRE_PASSWD_RESET, 'locked-flag' => UserAccountStatus::LOCKED, 'forbid-pwchange-flag' => UserAccountStatus::FORBID_PASSWD_RESET ) as $ck=>$flag) { if ($vars[$ck]) $this->setStatus($flag); else { if (($pwreset && $ck == 'pwreset-flag') || ($locked && $ck == 'locked-flag') || ($forbidPwChange && $ck == 'forbid-pwchange-flag')) { $type = array('type' => 'edited', 'key' => $ck); Signal::send('object.edited', $this, $type); } $this->clearStatus($flag); } } return $this->save(true); } static function createForUser($user, $defaults=false) { $acct = new static(array('user_id'=>$user->getId())); if ($defaults && is_array($defaults)) { foreach ($defaults as $k => $v) $acct->set($k, $v); } return $acct; } static function lookupByUsername($username) { if (Validator::is_email($username)) $user = static::lookup(array('user__emails__address' => $username)); elseif (Validator::is_userid($username)) $user = static::lookup(array('username' => $username)); return $user; } static function register($user, $vars, &$errors) { if (!$user || !$vars) return false; //Require temp password. if ((!$vars['backend'] || $vars['backend'] != 'client') && !isset($vars['sendemail'])) { if (!$vars['passwd1']) $errors['passwd1'] = 'Temporary password required'; elseif ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2'])) $errors['passwd2'] = 'Passwords do not match'; else { try { self::checkPassword($vars['passwd1']); } catch (BadPassword $ex) { $errors['passwd1'] = $ex->getMessage(); } } } if ($errors) return false; $account = new UserAccount(array( 'user_id' => $user->getId(), 'timezone' => $vars['timezone'], 'backend' => $vars['backend'], )); if ($vars['username'] && strcasecmp($vars['username'], $user->getEmail())) $account->set('username', Format::sanitize($vars['username'])); if ($vars['passwd1'] && !$vars['sendemail']) { $account->set('passwd', Passwd::hash($vars['passwd1'])); $account->setStatus(UserAccountStatus::CONFIRMED); if ($vars['pwreset-flag']) $account->setStatus(UserAccountStatus::REQUIRE_PASSWD_RESET); if ($vars['forbid-pwreset-flag']) $account->setStatus(UserAccountStatus::FORBID_PASSWD_RESET); } elseif ($vars['backend'] && $vars['backend'] != 'client') { // Auto confirm remote accounts $account->setStatus(UserAccountStatus::CONFIRMED); } $account->save(true); if (!$account->isConfirmed() && $vars['sendemail']) $account->sendConfirmEmail(); return $account; } static function checkPassword($new, $current=null) { osTicketClientAuthentication::checkPassword($new, $current); } } class UserAccountStatus { var $flag; const CONFIRMED = 0x0001; const LOCKED = 0x0002; const REQUIRE_PASSWD_RESET = 0x0004; const FORBID_PASSWD_RESET = 0x0008; function __construct($flag) { $this->flag = $flag; } function check($flag) { return 0 !== ($this->flag & $flag); } function isLocked() { return $this->check(self::LOCKED); } function isConfirmed() { return $this->check(self::CONFIRMED); } function __toString() { if ($this->isLocked()) return __('Locked (Administrative)'); if (!$this->isConfirmed()) return __('Locked (Pending Activation)'); // ... Other flags here (password reset, etc). return __('Active (Registered)'); } } /* * Generic user list. */ class UserList extends MailingList { function add($user) { if (!$user instanceof ITicketUser) throw new InvalidArgumentException('User expected'); return parent::add($user); } } ?>
Save