function save($id, $vars, &$errors) { global $cfg; //very basic checks $vars['name'] = Format::striptags(trim($vars['name'])); if ($id && $id != $vars['id']) { $errors['err'] = 'Internal error. Get technical help.'; } if (!$vars['email'] || !Validator::is_email($vars['email'])) { $errors['email'] = 'Valid email required'; } elseif (($eid = Email::getIdByEmail($vars['email'])) && $eid != $id) { $errors['email'] = 'Email already exits'; } elseif ($cfg && !strcasecmp($cfg->getAdminEmail(), $vars['email'])) { $errors['email'] = 'Email already used as admin email!'; } elseif (Staff::getIdByEmail($vars['email'])) { //make sure the email doesn't belong to any of the staff $errors['email'] = 'Email in-use by a staff member'; } if (!$vars['name']) { $errors['name'] = 'Email name required'; } if ($vars['mail_active'] || $vars['smtp_active'] && $vars['smtp_auth']) { if (!$vars['userid']) { $errors['userid'] = 'Username missing'; } if (!$id && !$vars['passwd']) { $errors['passwd'] = 'Password required'; } } if ($vars['mail_active']) { //Check pop/imapinfo only when enabled. if (!function_exists('imap_open')) { $errors['mail_active'] = 'IMAP doesn\'t exist. PHP must be compiled with IMAP enabled.'; } if (!$vars['mail_host']) { $errors['mail_host'] = 'Host name required'; } if (!$vars['mail_port']) { $errors['mail_port'] = 'Port required'; } if (!$vars['mail_protocol']) { $errors['mail_protocol'] = 'Select protocol'; } if (!$vars['mail_fetchfreq'] || !is_numeric($vars['mail_fetchfreq'])) { $errors['mail_fetchfreq'] = 'Fetch interval required'; } if (!$vars['mail_fetchmax'] || !is_numeric($vars['mail_fetchmax'])) { $errors['mail_fetchmax'] = 'Maximum emails required'; } if (!$vars['dept_id'] || !is_numeric($vars['dept_id'])) { $errors['dept_id'] = 'You must select a Dept.'; } if (!$vars['priority_id']) { $errors['priority_id'] = 'You must select a priority'; } if (!isset($vars['postfetch'])) { $errors['postfetch'] = 'Indicate what to do with fetched emails'; } elseif (!strcasecmp($vars['postfetch'], 'archive')) { if (!$vars['mail_archivefolder']) { $errors['postfetch'] = 'Valid folder required'; } } } if ($vars['smtp_active']) { if (!$vars['smtp_host']) { $errors['smtp_host'] = 'Host name required'; } if (!$vars['smtp_port']) { $errors['smtp_port'] = 'Port required'; } } //abort on errors if ($errors) { return false; } if (!$errors && ($vars['mail_host'] && $vars['userid'])) { $sql = 'SELECT email_id FROM ' . EMAIL_TABLE . ' WHERE mail_host=' . db_input($vars['mail_host']) . ' AND userid=' . db_input($vars['userid']); if ($id) { $sql .= ' AND email_id!=' . db_input($id); } if (db_num_rows(db_query($sql))) { $errors['userid'] = $errors['host'] = 'Host/userid combination already in-use.'; } } $passwd = $vars['passwd'] ? $vars['passwd'] : $vars['cpasswd']; if (!$errors && $vars['mail_active']) { //note: password is unencrypted at this point...MailFetcher expect plain text. $fetcher = new MailFetcher($vars['userid'], $passwd, $vars['mail_host'], $vars['mail_port'], $vars['mail_protocol'], $vars['mail_encryption']); if (!$fetcher->connect()) { $errors['err'] = 'Invalid login. Check ' . Format::htmlchars($vars['mail_protocol']) . ' settings'; $errors['mail'] = '<br>' . $fetcher->getLastError(); } elseif ($vars['mail_archivefolder'] && !$fetcher->checkMailbox($vars['mail_archivefolder'], true)) { $errors['postfetch'] = 'Invalid or unknown mail folder! >> ' . $fetcher->getLastError() . ''; if (!$errors['mail']) { $errors['mail'] = 'Invalid or unknown archive folder!'; } } } if (!$errors && $vars['smtp_active']) { //Check SMTP login only. require_once 'Mail.php'; // PEAR Mail package $smtp = mail::factory('smtp', array('host' => $vars['smtp_host'], 'port' => $vars['smtp_port'], 'auth' => $vars['smtp_auth'] ? true : false, 'username' => $vars['userid'], 'password' => $passwd, 'timeout' => 20, 'debug' => false)); $mail = $smtp->connect(); if (PEAR::isError($mail)) { $errors['err'] = 'Unable to login. Check SMTP settings.'; $errors['smtp'] = '<br>' . $mail->getMessage(); } else { $smtp->disconnect(); //Thank you, sir! } } if ($errors) { return false; } //Default to default priority and dept.. if (!$vars['priority_id'] && $cfg) { $vars['priority_id'] = $cfg->getDefaultPriorityId(); } if (!$vars['dept_id'] && $cfg) { $vars['dept_id'] = $cfg->getDefaultDeptId(); } $sql = 'updated=NOW(),mail_errors=0, mail_lastfetch=NULL' . ',email=' . db_input($vars['email']) . ',name=' . db_input(Format::striptags($vars['name'])) . ',dept_id=' . db_input($vars['dept_id']) . ',priority_id=' . db_input($vars['priority_id']) . ',noautoresp=' . db_input(isset($vars['noautoresp']) ? 1 : 0) . ',userid=' . db_input($vars['userid']) . ',mail_active=' . db_input($vars['mail_active']) . ',mail_host=' . db_input($vars['mail_host']) . ',mail_protocol=' . db_input($vars['mail_protocol'] ? $vars['mail_protocol'] : 'POP') . ',mail_encryption=' . db_input($vars['mail_encryption']) . ',mail_port=' . db_input($vars['mail_port'] ? $vars['mail_port'] : 0) . ',mail_fetchfreq=' . db_input($vars['mail_fetchfreq'] ? $vars['mail_fetchfreq'] : 0) . ',mail_fetchmax=' . db_input($vars['mail_fetchmax'] ? $vars['mail_fetchmax'] : 0) . ',smtp_active=' . db_input($vars['smtp_active']) . ',smtp_host=' . db_input($vars['smtp_host']) . ',smtp_port=' . db_input($vars['smtp_port'] ? $vars['smtp_port'] : 0) . ',smtp_auth=' . db_input($vars['smtp_auth']) . ',smtp_spoofing=' . db_input(isset($vars['smtp_spoofing']) ? 1 : 0) . ',notes=' . db_input($vars['notes']); //Post fetch email handling... if ($vars['postfetch'] && !strcasecmp($vars['postfetch'], 'delete')) { $sql .= ',mail_delete=1,mail_archivefolder=NULL'; } elseif ($vars['postfetch'] && !strcasecmp($vars['postfetch'], 'archive') && $vars['mail_archivefolder']) { $sql .= ',mail_delete=0,mail_archivefolder=' . db_input($vars['mail_archivefolder']); } else { $sql .= ',mail_delete=0,mail_archivefolder=NULL'; } if ($vars['passwd']) { //New password - encrypt. $sql .= ',userpass='******'passwd'], SECRET_SALT)); } if ($id) { //update $sql = 'UPDATE ' . EMAIL_TABLE . ' SET ' . $sql . ' WHERE email_id=' . db_input($id); if (db_query($sql) && db_affected_rows()) { return true; } $errors['err'] = 'Unable to update email. Internal error occurred'; } else { $sql = 'INSERT INTO ' . EMAIL_TABLE . ' SET ' . $sql . ',created=NOW()'; if (db_query($sql) && ($id = db_insert_id())) { return $id; } $errors['err'] = 'Unable to add email. Internal error'; } return false; }
function save($id, $vars, &$errors) { $vars['username'] = Format::striptags($vars['username']); $vars['firstname'] = Format::striptags($vars['firstname']); $vars['lastname'] = Format::striptags($vars['lastname']); if ($id && $id != $vars['id']) { $errors['err'] = __('Internal Error'); } if (!$vars['firstname']) { $errors['firstname'] = __('First name required'); } if (!$vars['lastname']) { $errors['lastname'] = __('Last name required'); } $error = ''; if (!$vars['username'] || !Validator::is_username($vars['username'], $error)) { $errors['username'] = $error ? $error : __('Username is required'); } elseif (($uid = Staff::getIdByUsername($vars['username'])) && $uid != $id) { $errors['username'] = __('Username already in use'); } if (!$vars['email'] || !Validator::is_valid_email($vars['email'])) { $errors['email'] = __('Valid email is required'); } elseif (Email::getIdByEmail($vars['email'])) { $errors['email'] = __('Already in use system email'); } elseif (($uid = Staff::getIdByEmail($vars['email'])) && $uid != $id) { $errors['email'] = __('Email already in use by another agent'); } if ($vars['phone'] && !Validator::is_phone($vars['phone'])) { $errors['phone'] = __('Valid phone number is required'); } if ($vars['mobile'] && !Validator::is_phone($vars['mobile'])) { $errors['mobile'] = __('Valid phone number is required'); } if ($vars['passwd1'] || $vars['passwd2'] || !$id) { if ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2'])) { $errors['passwd2'] = __('Passwords do not match'); } elseif ($vars['backend'] != 'local' || $vars['welcome_email']) { // Password can be omitted } elseif (!$vars['passwd1'] && !$id) { $errors['passwd1'] = __('Temporary password is required'); $errors['temppasswd'] = __('Required'); } elseif ($vars['passwd1'] && strlen($vars['passwd1']) < 6) { $errors['passwd1'] = __('Password must be at least 6 characters'); } } if (!$vars['dept_id']) { $errors['dept_id'] = __('Department is required'); } if (!$vars['group_id']) { $errors['group_id'] = __('Group is required'); } if (!$vars['timezone_id']) { $errors['timezone_id'] = __('Time zone selection is required'); } // Ensure we will still have an administrator with access if ($vars['isadmin'] !== '1' || $vars['isactive'] !== '1') { $sql = 'select count(*), max(staff_id) from ' . STAFF_TABLE . ' WHERE isadmin=1 and isactive=1'; if (($res = db_query($sql)) && (list($count, $sid) = db_fetch_row($res))) { if ($count == 1 && $sid == $id) { $errors['isadmin'] = __('Cowardly refusing to remove or lock out the only active administrator'); } } } if ($errors) { return false; } $sql = 'SET updated=NOW() ' . ' ,isadmin=' . db_input($vars['isadmin']) . ' ,isactive=' . db_input($vars['isactive']) . ' ,isvisible=' . db_input(isset($vars['isvisible']) ? 1 : 0) . ' ,onvacation=' . db_input(isset($vars['onvacation']) ? 1 : 0) . ' ,assigned_only=' . db_input(isset($vars['assigned_only']) ? 1 : 0) . ' ,dept_id=' . db_input($vars['dept_id']) . ' ,group_id=' . db_input($vars['group_id']) . ' ,timezone_id=' . db_input($vars['timezone_id']) . ' ,daylight_saving=' . db_input(isset($vars['daylight_saving']) ? 1 : 0) . ' ,username='******'username']) . ' ,firstname=' . db_input($vars['firstname']) . ' ,lastname=' . db_input($vars['lastname']) . ' ,email=' . db_input($vars['email']) . ' ,backend=' . db_input($vars['backend']) . ' ,phone="' . db_input(Format::phone($vars['phone']), false) . '"' . ' ,phone_ext=' . db_input($vars['phone_ext']) . ' ,mobile="' . db_input(Format::phone($vars['mobile']), false) . '"' . ' ,signature=' . db_input(Format::sanitize($vars['signature'])) . ' ,notes=' . db_input(Format::sanitize($vars['notes'])); if ($vars['passwd1']) { $sql .= ' ,passwd=' . db_input(Passwd::hash($vars['passwd1'])); if (isset($vars['change_passwd'])) { $sql .= ' ,change_passwd=1'; } } elseif (!isset($vars['change_passwd'])) { $sql .= ' ,change_passwd=0'; } if ($id) { $sql = 'UPDATE ' . STAFF_TABLE . ' ' . $sql . ' WHERE staff_id=' . db_input($id); if (db_query($sql) && db_affected_rows()) { return true; } $errors['err'] = sprintf(__('Unable to update %s.'), __('this agent')) . ' ' . __('Internal error occurred'); } else { $sql = 'INSERT INTO ' . STAFF_TABLE . ' ' . $sql . ', created=NOW()'; if (db_query($sql) && ($uid = db_insert_id())) { return $uid; } $errors['err'] = sprintf(__('Unable to create %s.'), __('this agent')) . ' ' . __('Internal error occurred'); } return false; }
/** * postEmail * * After some security and sanity checks, attaches the body and subject * of the message in reply to this thread item * * Parameters: * mailinfo - (array) of information about the email, with at least the * following keys * - mid - (string) email message-id * - name - (string) personal name of email originator * - email - (string<email>) originating email address * - subject - (string) email subject line (decoded) * - body - (string) email message body (decoded) */ function postEmail($mailinfo) { global $ost; // +==================+===================+=============+ // | Orig Thread-Type | Reply Thread-Type | Requires | // +==================+===================+=============+ // | * | Message (M) | From: Owner | // | * | Note (N) | From: Staff | // | Response (R) | Message (M) | | // | Message (M) | Response (R) | From: Staff | // +------------------+-------------------+-------------+ if (!($ticket = $this->getTicket())) { // Kind of hard to continue a discussion without a ticket ... return false; } elseif ($this->getEmailMessageId() == $mailinfo['mid']) { // Reporting success so the email can be moved or deleted. return true; } // Mail sent by this system will have a message-id format of // <*****@*****.**> // where code is a predictable string based on the SECRET_SALT of // this osTicket installation. If this incoming mail matches the // code, then it very likely originated from this system and looped @(list($code) = explode('-', $mailinfo['mid'], 2)); if (0 === strcasecmp(ltrim($code, '<'), substr(md5('mail' . SECRET_SALT), -9))) { // This mail was sent by this system. It was received due to // some kind of mail delivery loop. It should not be considered // a response to an existing thread entry if ($ost) { $ost->log(LOG_ERR, _S('Email loop detected'), sprintf(_S('It appears as though <%s> is being used as a forwarded or fetched email account and is also being used as a user / system account. Please correct the loop or seek technical assistance.'), $mailinfo['email']), false, true); } return true; } $vars = array('mid' => $mailinfo['mid'], 'header' => $mailinfo['header'], 'ticketId' => $ticket->getId(), 'poster' => $mailinfo['name'], 'origin' => 'Email', 'source' => 'Email', 'ip' => '', 'reply_to' => $this, 'recipients' => $mailinfo['recipients'], 'to-email-id' => $mailinfo['to-email-id']); $errors = array(); if (isset($mailinfo['attachments'])) { $vars['attachments'] = $mailinfo['attachments']; } $body = $mailinfo['message']; // Disambiguate if the user happens also to be a staff member of the // system. The current ticket owner should _always_ post messages // instead of notes or responses if ($mailinfo['userId'] || strcasecmp($mailinfo['email'], $ticket->getEmail()) == 0) { $vars['message'] = $body; $vars['userId'] = $mailinfo['userId'] ? $mailinfo['userId'] : $ticket->getUserId(); return $ticket->postMessage($vars, 'Email'); } elseif ($mailinfo['staffId'] || ($mailinfo['staffId'] = Staff::getIdByEmail($mailinfo['email']))) { $vars['staffId'] = $mailinfo['staffId']; $poster = Staff::lookup($mailinfo['staffId']); $vars['note'] = $body; return $ticket->postNote($vars, $errors, $poster); } elseif (Email::getIdByEmail($mailinfo['email'])) { // Don't process the email -- it came FROM this system return true; } elseif (isset($mailinfo['thread-type'])) { switch ($mailinfo['thread-type']) { case 'N': $vars['note'] = $body; $poster = $mailinfo['email']; return $ticket->postNote($vars, $errors, $poster); } } else { //XXX: Are we potentially leaking the email address to // collaborators? $vars['message'] = sprintf("Received From: %s\n\n%s", $mailinfo['email'], $body); $vars['userId'] = 0; //Unknown user! //XXX: Assume ticket owner? return $ticket->postMessage($vars, 'Email'); } // Currently impossible, but indicate that this thread object could // not append the incoming email. return false; }
function save($id, $vars, &$errors) { $vars['username'] = Format::striptags($vars['username']); $vars['firstname'] = Format::striptags($vars['firstname']); $vars['lastname'] = Format::striptags($vars['lastname']); if ($id && $id != $vars['id']) { $errors['err'] = 'Internal Error'; } if (!$vars['firstname']) { $errors['firstname'] = 'First name required'; } if (!$vars['lastname']) { $errors['lastname'] = 'Last name required'; } $error = ''; if (!$vars['username'] || !Validator::is_username($vars['username'], $error)) { $errors['username'] = $error ? $error : 'Username required'; } elseif (($uid = Staff::getIdByUsername($vars['username'])) && $uid != $id) { $errors['username'] = '******'; } if (!$vars['email'] || !Validator::is_email($vars['email'])) { $errors['email'] = 'Valid email required'; } elseif (Email::getIdByEmail($vars['email'])) { $errors['email'] = 'Already in-use system email'; } elseif (($uid = Staff::getIdByEmail($vars['email'])) && $uid != $id) { $errors['email'] = 'Email already in use by another staff member'; } if ($vars['phone'] && !Validator::is_phone($vars['phone'])) { $errors['phone'] = 'Valid number required'; } if ($vars['mobile'] && !Validator::is_phone($vars['mobile'])) { $errors['mobile'] = 'Valid number required'; } if ($vars['passwd1'] || $vars['passwd2'] || !$id) { if ($vars['passwd1'] && strcmp($vars['passwd1'], $vars['passwd2'])) { $errors['passwd2'] = 'Password(s) do not match'; } elseif ($vars['backend'] != 'local' || $vars['welcome_email']) { // Password can be omitted } elseif (!$vars['passwd1'] && !$id) { $errors['passwd1'] = 'Temp. password required'; $errors['temppasswd'] = 'Required'; } elseif ($vars['passwd1'] && strlen($vars['passwd1']) < 6) { $errors['passwd1'] = 'Must be at least 6 characters'; } } if (!$vars['dept_id']) { $errors['dept_id'] = 'Department required'; } if (!$vars['group_id']) { $errors['group_id'] = 'Group required'; } if (!$vars['timezone_id']) { $errors['timezone_id'] = 'Time zone required'; } if ($errors) { return false; } $sql = 'SET updated=NOW() ' . ' ,isadmin=' . db_input($vars['isadmin']) . ' ,isactive=' . db_input($vars['isactive']) . ' ,isvisible=' . db_input(isset($vars['isvisible']) ? 1 : 0) . ' ,onvacation=' . db_input(isset($vars['onvacation']) ? 1 : 0) . ' ,assigned_only=' . db_input(isset($vars['assigned_only']) ? 1 : 0) . ' ,dept_id=' . db_input($vars['dept_id']) . ' ,group_id=' . db_input($vars['group_id']) . ' ,timezone_id=' . db_input($vars['timezone_id']) . ' ,daylight_saving=' . db_input(isset($vars['daylight_saving']) ? 1 : 0) . ' ,username='******'username']) . ' ,firstname=' . db_input($vars['firstname']) . ' ,lastname=' . db_input($vars['lastname']) . ' ,email=' . db_input($vars['email']) . ' ,backend=' . db_input($vars['backend']) . ' ,phone="' . db_input(Format::phone($vars['phone']), false) . '"' . ' ,phone_ext=' . db_input($vars['phone_ext']) . ' ,mobile="' . db_input(Format::phone($vars['mobile']), false) . '"' . ' ,signature=' . db_input(Format::sanitize($vars['signature'])) . ' ,notes=' . db_input(Format::sanitize($vars['notes'])); if ($vars['passwd1']) { $sql .= ' ,passwd=' . db_input(Passwd::hash($vars['passwd1'])); if (isset($vars['change_passwd'])) { $sql .= ' ,change_passwd=1'; } } elseif (!isset($vars['change_passwd'])) { $sql .= ' ,change_passwd=0'; } if ($id) { $sql = 'UPDATE ' . STAFF_TABLE . ' ' . $sql . ' WHERE staff_id=' . db_input($id); if (db_query($sql) && db_affected_rows()) { return true; } $errors['err'] = 'Unable to update the user. Internal error occurred'; } else { $sql = 'INSERT INTO ' . STAFF_TABLE . ' ' . $sql . ', created=NOW()'; if (db_query($sql) && ($uid = db_insert_id())) { return $uid; } $errors['err'] = 'Unable to create user. Internal error'; } return false; }
/** * postEmail * * After some security and sanity checks, attaches the body and subject * of the message in reply to this thread item * * Parameters: * mailinfo - (array) of information about the email, with at least the * following keys * - mid - (string) email message-id * - name - (string) personal name of email originator * - email - (string<email>) originating email address * - subject - (string) email subject line (decoded) * - body - (string) email message body (decoded) */ function postEmail($mailinfo) { // +==================+===================+=============+ // | Orig Thread-Type | Reply Thread-Type | Requires | // +==================+===================+=============+ // | * | Message (M) | From: Owner | // | * | Note (N) | From: Staff | // | Response (R) | Message (M) | | // | Message (M) | Response (R) | From: Staff | // +------------------+-------------------+-------------+ if (!($ticket = $this->getTicket())) { // Kind of hard to continue a discussion without a ticket ... return false; } elseif ($this->getEmailMessageId() == $mailinfo['mid']) { // Reporting success so the email can be moved or deleted. return true; } $vars = array('mid' => $mailinfo['mid'], 'header' => $mailinfo['header'], 'ticketId' => $ticket->getId(), 'poster' => $mailinfo['name'], 'origin' => 'Email', 'source' => 'Email', 'ip' => '', 'reply_to' => $this); if (isset($mailinfo['attachments'])) { $vars['attachments'] = $mailinfo['attachments']; } $body = $mailinfo['message']; // Disambiguate if the user happens also to be a staff member of the // system. The current ticket owner should _always_ post messages // instead of notes or responses if (strcasecmp($mailinfo['email'], $ticket->getEmail()) == 0) { $vars['message'] = $body; return $ticket->postMessage($vars, 'Email'); } elseif ($staff_id = Staff::getIdByEmail($mailinfo['email'])) { $vars['staffId'] = $staff_id; $poster = Staff::lookup($staff_id); $errors = array(); $vars['note'] = $body; return $ticket->postNote($vars, $errors, $poster); } elseif (Email::getIdByEmail($mailinfo['email'])) { // Don't process the email -- it came FROM this system return true; } else { $vars['message'] = sprintf("Received From: %s\n\n%s", $mailinfo['email'], $body); return $ticket->postMessage($vars, 'Email'); } // Currently impossible, but indicate that this thread object could // not append the incoming email. return false; }