user.php
上传用户:gzy2002
上传日期:2010-02-11
资源大小:1785k
文件大小:24k
- #!/usr/bin/php -q
- <?php
- // +-------------------------------------------------------------+
- // | DeskPRO v [2.0.1 Production]
- // | Copyright (C) 2001 - 2004 Headstart Solutions Limited
- // | Supplied by WTN-WDYL
- // | Nullified by WTN-WDYL
- // | Distribution via WebForum, ForumRU and associated file dumps
- // +-------------------------------------------------------------+
- // | DESKPRO IS NOT FREE SOFTWARE
- // +-------------------------------------------------------------+
- // | License ID : Full Enterprise License =) ...
- // | License Owner : WTN-WDYL Team
- // +-------------------------------------------------------------+
- // | $RCSfile: user.php,v $
- // | $Date: 2004/02/11 20:32:13 $
- // | $Revision: 1.108 $
- // +-------------------------------------------------------------+
- // | File Details:
- // | - process() provider for user-mailed e-mails.
- // +-------------------------------------------------------------+
- error_reporting(E_ALL ^ E_NOTICE ^ E_WARNING);
- //////////////////// PART 1 INCLUDES ////////////////////
- define('USERZONE', 1);
- include("mail_config.php");
- include("mail.php");
- ###################### FUNCTION PROCESS() #######################
- /*
- Deals with incoming user email for new ticket and reply creation
- $message: the email after it has been decoded (array of elements)
- $source : the source of the email
- $gateway: array containing gateway information (for POP3); if not
- provided, we try to figure it out ourselves here.
- */
- function process(&$message, &$source, $gateway = NULL) {
-
- global $db, $settings, $template_cache, $output, $sourceid, $user;
- // rename a few variables for ease of access
- $email['from'] = trim(strtolower($message->fromEmail));
- $for_error = $email['from'];
- $headers = $message->headers;
- $subject = $headers['subject'];
- //////////////////////////////////////////////////////////////
- /* 1. STANDARD PROCESSING INDEPENDANT OF REPLY / NEW TICKET */
- //////////////////////////////////////////////////////////////
- // insert the full email
- $sourceid = store_mail($headers, $source);
- // no valid return email (decoding functions look at various mail headers)
- if (!$email['from']) {
- log_error('no_email', $message);
- return true;
- }
- // the from email is invalid
- if (!(validate_email($email['from']))) {
- log_error('invalid_email', $message);
- return true;
- }
- // Handle e-mail bans. First, if this sender is banned, reject it.
- if (banned_email($email['from'])) {
- log_error('banned_email', $message);
- return true;
- }
- // Next, if the sender is ourselves, ignore the message (because that's
- // a common spam trick and we'll never be mailing ourselves anyway)
- if (strtolower($settings[email_from]) == $email['from']) {
- log_error('self_email', $message);
- return true;
- }
- // check the email is not a gateway email, if so we will get autoresponder loops.
- // Note this does not stop the problem where an email address is sent to user.php but
- // there is no gateway account for it.
- $db->query("
- SELECT id
- FROM gateway_accounts
- WHERE email = '" . mysql_escape_string($email['from']) . "'
- ");
- if ($db->num_rows() > 0) {
- log_error('gateway_email', $message);
- return true;
- }
- // check there actually is some text. We first use the text portion of the email, but if that is empty
- // we use the HTML portion
- if (trim($message->text) != '') {
- $body = $message->text;
- } elseif (trim($message->html != '')) {
- $body = $message->html;
- } else {
- log_error('no_message', $message);
- return true;
- }
- // Stops us looping with other mail software
- if ($headers['x-loop-detect'] == 3) {
- $no_autoresponse = 1;
- } elseif ($headers['x-loop-detect'] == 5) {
- log_error('x-loop', $message);
- return true;
- }
- // Incremement the x-loop-detect
- $extra_mail_info['headers']['X-Loop-Detect'] = (int)$headers['X-Loop-Detect'];
- $extra_mail_info['headers']['X-Loop-Detect']++;
- // we don't want to autorespond to another DeskPRO
- if (in_string('DeskPRO', $headers['X-Mailer'])) {
- $no_autoresponse = 1;
- }
- //////////////////////////////////////////////////////////////
- /* 2. REPLY v NEW TICKET */
- //////////////////////////////////////////////////////////////
- /*
- Need to check which ticket this is
- i) a dp1.x email, for those upgrade
- ii) [AAAA-0000-AAAA] [xxxxxxxx] in subject
- iii) <=== Ticket Ref AAAA-0000-AAAA ===> / <=== $ticket[authcode] ===>
- */
- // dp1 check, we have the ticketid not ref and the auth code
- if (ereg("[([0-9].*)--([A-Za-z0-9]{8})]", $subject, $arr)) {
- $new = false;
- $ticketid = $arr[1];
- $ticketauth = $arr[2];
- // get the ref from the id
- $result = $db->query_return("SELECT ref FROM ticket WHERE id = '" . addslashes($ticketid) . "'");
- $ticketref = $result['ref'];
- } else {
- // not dp1, now we need to run the checks to get ticketref/authcode, both are needed
- // subject check
- if (ereg("[([0-9]{4}-[A-Za-z]{4}-[0-9]{4})]", $subject, $arr)) {
- $ticketref = $arr[1];
- // footer check
- } elseif (ereg("<=== ([0-9]{4}-[A-Za-z]{4}-[0-9]{4}) ===>", $body, $arr)) {
- $ticketref = $arr[1];
- // nothing found, we are creating a new ticket
- }
- // subject check
- if (ereg("[([a-zA-Z0-9]{8})]", $subject, $arr)) {
- $ticketauth = $arr[1];
- // footer check
- } elseif (ereg("<=== ([a-zA-Z0-9]{8}) ===>", $body, $arr)) {
- $ticketauth = $arr[1];
- }
- }
- // We have got ticketid / ref lets check they exist
- // if not then we need to create a new ticket
- if ($ticketref) {
- $ticket = get_ticket_from_ref($ticketref);
- // ticket not found, check if ticket was merged
- if (!is_array($ticket)) {
- $ticket = $db->query_return("
- SELECT * FROM ticket_merge
- WHERE old_ref = '" . addslashes($ticketref) . "'
- ");
- if ($ticket['new_id']) {
- $ticket = get_ticket_from_ref($ticket['new_id']);
- }
- }
- }
- if (is_array($ticket)) {
- $do = 'reply';
- } else {
- $do = 'new';
- // unset any variables we have set
- unset($ticketref, $authcode, $ticketid, $result);
- // need to remove any current ticket refs / auths from the subject
- $subject = ereg_replace("[[a-zA-Z0-9]{8}]", "", $subject);
- $subject = ereg_replace("[([0-9]{4}-[A-Za-z]{4}-[0-9]{4})]", "", $subject);
- }
- //////////////////////////////////////////////////////////////
- /* GET GATEWAY DETAILS */
- //////////////////////////////////////////////////////////////
- if (!is_array($gateway)) {
- $gateway = $db->query_return("
- SELECT
- gateway_accounts.auto_new, gateway_accounts.auto_reply, gateway_accounts.email,
- gateway_accounts.is_default, gateway_accounts.id,
- ticket_pri.id AS priority_id, ticket_pri.name AS priority,
- ticket_cat.id AS category_id, ticket_cat.name AS category,
- tech.id AS tech_id, tech.email AS tech_email
- FROM gateway_accounts
- LEFT JOIN ticket_pri ON (ticket_pri.id = gateway_accounts.priority)
- LEFT JOIN ticket_cat ON (ticket_cat.id = gateway_accounts.category)
- LEFT JOIN tech ON (tech.id = gateway_accounts.tech)
- WHERE gateway_accounts.email IN " . array2sql($message->recipientAddresses) . "
- OR gateway_accounts.is_default = 1
- ORDER BY is_default ASC
- LIMIT 0,1
- ");
- if (!$db->num_rows()) {
- // if admin has not created a gateway account
- log_error('no_gateway', $message);
- return false;
- }
- }
- // spam check
- if ($spam_check = spam_check($subject, $body)) {
- if ($spam_check == 'delete') {
- log_error('spam', $message);
- return true;
- } else {
- $is_spam = 1;
- }
- }
- #############################################################################################
- // NEW TICKET //
- if ($do == 'new') {
- if (!max_limits('tickets', 1)) {
- log_error('license_no_new_tickets', $message);
- return true;
- }
- //////////////////////////////////////////////////////////////
- /* 3. CREATE USER IF DOES NOT ALREADY EXIST */
- //////////////////////////////////////////////////////////////
- // get user fields
- $user = $db->query_return("SELECT * FROM user WHERE email = '$email[from]'");
-
- if (!$db->num_rows()) {
- $userid = $db->query_return("SELECT userid FROM user_email WHERE email = '$email[from]'");
- if ($db->num_rows()) {
- $user = $db->query_return("SELECT * FROM user WHERE id = '$userid[userid]'");
- }
- }
- if (!is_array($user)) {
-
- // fail if no user and require regisration
- if ($settings[gateway_require_reg] == "1") {
- log_error('unregistered', $message);
- return true;
- }
- // Get the sender's name
- $fromemaillastspace = strrpos($headers['from'], ' ');
- $fromname = trim(substr($headers['from'], 0, $fromemaillastspace - strlen($headers['from'])), " rnt x0b"'");
- // create user
- $password = make_pass(8);
- $password_cookie = md5($session[sessionid] . $password . uniqid(rand(),1));
- $password_cookie = substr($password_cookie, 0, 8);
- $password_url = md5($password . uniqid(rand(),1) . $session[sessionid]);
- $password_url = substr($password_url, 0, 8);
- $username = make_username($email['from']);
- // require email validation
- if ($settings[validate_email]) {
- $validate_number = substr(md5(time()),0,6);
- $user_query .= " validate_key = '$validate_number', awaiting_validation = 1, ";
- $nodisplay = 2;
- }
- if ($settings[manual_validation]) {
- $user_query .= " awaiting_manual_validation = '1', ";
- $nodisplay = 3;
- }
- $db->query("
- INSERT into user SET
- $user_query
- name = '" . mysql_escape_string($fromname) . "',
- password = '" . mysql_escape_string($password) . "',
- username = '" . mysql_escape_string($username) . "',
- email = '" . mysql_escape_string($email['from']) . "',
- password_url = '" . mysql_escape_string($password_url) . "',
- password_cookie = '" . mysql_escape_string($password_cookie) . "',
- date_registered = '" . mktime() . "'
- ");
- $id = $db->last_id();
- $user = $db->query_return("SELECT * FROM user WHERE id = '$id'");
- $new_user = true;
- }
- //////////////////////////////////////////////////////////////
- /* 4. CHECK TICKETS FOR DUPLICATION */
- //////////////////////////////////////////////////////////////
- // no point running duplication checks if we have just created the user
- if (!$new_user) {
-
- /*
- - checks for identical subjects in last 24 hours:
- i) if 3, we process ticket but also email the user explaining they can't do it again
- ii) if 4, we don't process the message
- - checks for identical bodies in the last 24 hours:
- i) any email with identical body is ignored. These is no reason to send two identical emails
- These protections:
- a) catch autoresponder messages that change the subject/body of the message
- and thus look like new tickets. If they do this then it is likely that the message
- that will be sent will be identical (e.g. vacation reply) and thus should be ignored.
- b) An identical message is always going to be useless, an identical subject can be the result
- of two different emails hence the warning and higher limit
- */
- // subject check in last 6 hours
- $time_expire = mktime() - (3600 * 6);
- $result = $db->query_return("
- SELECT count(*) AS total
- FROM ticket
- WHERE ticket.userid = '$user[id]'
- AND ticket.date_opened > '$time_expire'
- AND subject = '" . addslashes($subject) . "'
- ");
- // if this is the 3rd identical email we need to inform the user they need to change subject
- if ($result['total'] == 2) {
- extra_email('duplicate_subject', $user);
- }
-
- if ($result['total'] > 2) {
- log_error('duplicate_subject', $message);
- return true;
- }
- // subject check in last 24 hours
- $time_expire = mktime() - (3600 * 24);
- $db->query("SELECT ticket.subject, ticket_message.message
- FROM ticket
- LEFT JOIN ticket_message ON (ticket.id = ticket_message.ticketid)
- WHERE ticket.userid = $user[id] AND ticket_message.userid = $user[id]
- AND (ticket.date_opened > '$time_expire')
- OR (ticket_message.date > '$time_expire')
- ");
- while ($result = $db->row_array()) {
- if ($result[message] == $body) {
- log_error('duplicate_message', $message);
- return true;
- }
- }
- /*
- - check number of tickets created by user in certain amount of time
- i) if we reach warning amount, tell user and mark as autoresponder
- ii) too many we just stop processing
- This protection:
- a) another check on autoresponding users. This is useful when the autoresponder
- changes the email to remove the subject and body but makes the message unique (e.g. with a timestamp on outgoing). This is increasingly common with lines such as Thank you for your email received xxxx.
- b) Tolerances should be set relativly low to ensure that a user who just sends 5
- new tickets very rapidly is not penialised.
- c) The setting of the autoresponder status stops an autoresponder causing the problem.
- The only reason that we should get more emails after that is if someone is on purpose trying to send a lot of emails from one email account. This emails would not be valid (as the user is warned)
- */
- // 1 hour window
- $time_expire = mktime() - (3600 * 1);
- $result = $db->query_return("
- SELECT COUNT(*) AS total
- FROM ticket
- WHERE userid = '$user[id]'
- AND date_opened > '$time_expire'
- ");
- // we have reached the max new tickets, generate error and stop processing
- if ($settings['max_new']) {
- if ($result[total] > $settings['max_new']) {
- log_error('new_user_limit', $message);
- return true;
- }
- }
- // if we have reached warning amount of new tickets, mark as autoresponder and send warning email
- if ($settings['max_new_warning']) {
- if ($result[total] > $settings['max_new_warning']) {
- $db->query("
- UPDATE user SET autoresponds = 1
- WHERE id = '$user[id]'
- ");
- extra_email('too_many_new_tickets', $user);
- }
- }
- }
- //////////////////////////////////////////////////////////////
- /* 5. CREATE TICKET */
- //////////////////////////////////////////////////////////////
- $exp = user_expired($user['id']);
- if (is_array($exp)) {
- log_error('user_expired', $message);
- return true;
- }
- $ref = make_ticket_ref();
- // set a nodisplay if spam or user requires validation
- if (!$nodisplay) {
- if ($is_spam) {
- $nodisplay = 1;
- }
- }
- $authcode = substr(md5(rand(0,100000) . mktime()), 0, 8);
- // ticket query
- $db->query("
- INSERT INTO ticket SET
- subject = '" . mysql_escape_string($subject) . "',
- date_opened = '" . mktime() . "',
- is_open = '1',
- awaiting_tech = '1',
- date_awaiting_toggled = '" . mktime() . "',
- userid = '$user[id]',
- category = '$gateway[category_id]',
- priority = '$gateway[priority_id]',
- tech = '$gateway[tech]',
- gatewayid = '$gateway[id]',
- ref = '$ref',
- authcode = '$authcode',
- nodisplay = '$nodisplay'
- ");
-
- $id = $db->last_id();
- ticketlog($id, 'created');
- $ticket = $db->query_return("
- SELECT ticket.*
- FROM ticket
- WHERE ticket.id = '$id'
- ");
- // add the processed message
- $db->query("
- INSERT into ticket_message SET
- message = '" . mysql_escape_string($body) . "',
- ticketid = '$id',
- sourceid = '$sourceid',
- date = '" . mktime() . "',
- striptags = '$striptags',
- userid = '$user[id]'
- ");
- $ticket['body'] = $body;
- if ($new_user) {
- $ticket['newuser'] = 1;
- $ticket['username'] = $user['username'];
- $ticket['password'] = $user['password'];
- }
- //////////////////////////////////////////////////////////////
- /* 6. PROCESS ATTACHMENTS */
- //////////////////////////////////////////////////////////////
- $email_attachments = process_attachments($message->attachments, $message->embedded, $ticket[id], $user[id]);
- //////////////////////////////////////////////////////////////
- /* 7. SEND EMAIL TO USERS */
- //////////////////////////////////////////////////////////////
- // Trim message to be quoted in response e-mail to 16k at most
- $message = substr($body, NULL, 16384);
- /* send email if:
- i) set up for this gateway account
- ii) the user does not autorespond
- iii) there is not something about the specific email that makes us want to not autorespond
- */
- if ($gateway['auto_new'] AND !$user['autoresponds'] AND !$no_autoresponse) {
- notify_user('new_user', $ticket, $user, $message, $email_attachments, $gateway[id], $extra_mail_info);
- }
- //////////////////////////////////////////////////////////////
- /* 8. SEND EMAL TO TECHS */
- //////////////////////////////////////////////////////////////
- notify_technicians('new', $ticket, $user, $message, $email_attachments, $gateway[id], $extra_mail_info);
-
- return true;
-
- }
- #############################################################################################
- // TICKET REPLY //
- if ($do == 'reply') {
- //////////////////////////////////////////////////////////////
- /* 3. PROCESS / ERROR CHECKING */
- //////////////////////////////////////////////////////////////
- // check ticket auth is correct
- if ($ticket['authcode'] != $ticketauth) {
- log_error('bad_auth', $message);
- return true;
- }
- // check ticket is open
- if ($ticket[is_open] == "0" AND !$settings['gateway_ticket_reopen']) {
- log_error('ticket_closed', $message);
- return true;
- }
- //////////////////////////////////////////////////////////////
- /* 4. GET USER DATA */
- //////////////////////////////////////////////////////////////
- // check the user hastn't been deleted
- $user = $db->query_return("
- SELECT * FROM user
- WHERE id = '$ticket[userid]'
- ");
- if (!$db->num_rows()) {
- log_error('no_user', $message);
- return true;
- }
- $user['email'] = $email['from'];
- //////////////////////////////////////////////////////////////
- /* 5. AUTORESPONSE PROTECTION */
- //////////////////////////////////////////////////////////////
- /*
- - check for too many replies to the ticket in unit time.
- i) firstly we email the user and stop autoresponding
- ii) we stop processing the emails at all
- This protection:
- a) An autoresponder that changes the message will be stopped once the limits are reached. Note that the limit is reset if a tech replies so that a quick conversation is possible
- */
- // 1 hour
- $auto_time = mktime() - (3600 * 1);
-
- $result = $db->query_return(
- "SELECT COUNT(*) AS total FROM ticket_message
- WHERE ticketid = '$ticket[id]'
- AND date > $auto_time
- AND date > $ticket[date_lastreply_tech]
- ");
- // we have reached the max new replies to tickets, generate error and stop processing
- if ($settings['max_reply']) {
- if ($result[total] > $settings['max_reply']) {
- log_error('autoresponder_reply', $message);
- return true;
- }
- }
- // if we have reached warning amount number of ticket replies, mark as autoresponder and send warning email
- if ($settings['max_reply_warning']) {
- if ($result[total] > $settings['max_reply_warning']) {
- $db->query("
- UPDATE user SET autoresponds = 1
- WHERE id = '$user[id]'
- ");
- extra_email('too_many_replies', $user);
- }
- }
- //////////////////////////////////////////////////////////////
- /* 6. IF SET BY ADMIN, ATTEMPT TO IGNORE PREVIOUS QUOTED REPLIES */
- //////////////////////////////////////////////////////////////
- if ($settings['gateway_reply_cut']) {
- $gateway_cut = $db->query_return_array("SELECT text FROM template_words WHERE wordref = 'gateway_reply_cut'");
-
- if (!is_array($gateway_cut)) {
- $gateway_cut = array();
- }
- foreach ($gateway_cut AS $var) {
- if (trim($var) != '') {
- // position of the start of the quote
- $end = strpos($body, $var['text']);
- if ($end) {
- // We do $end - 3 here because "usually" mail clients do quotes like this:
- // > original message
- // That's a quote marker, a space, then the text. We want to kill those two
- // characters, plus the newline preceeding them. This has a slight chance of
- // deleting the last character in the reply if the quote isn't shown by two
- // characters, or if it's otherwise malformed.
- $body = substr($body, 0, ($end - 3));
- if (trim($body == '')) {
- log_error('no_message', $message);
- return true;
- }
- }
- }
- }
- }
- //////////////////////////////////////////////////////////////
- /* 5. AUTORESPONSE PROTECTION */
- //////////////////////////////////////////////////////////////
- /*
- - check for identical message to the ticket in the last hour (with the identical message being the last one in the ticket, so we can allow for two "Yes" replies for example. This has to be done after "cutting" of any extra quoted content
- i) the email is error logged
- These protections:
- a) catch autoresponders that send identical emails, once one autoresponse has been added, the 2nd one would be ignored if it was identical
- */
- // 1 hour
- $auto_time = mktime() - (3600 * 1);
- // duplication check
- $db->query("SELECT ticket_message.id
- FROM ticket_message
- WHERE ticket_message.userid = $user[id]
- AND ticket_message.date > '$time_expire'
- AND date > '$ticket[date_lastreply_tech]'
- ");
- while ($result = $db->row_array()) {
- if ($result[message] == $body) {
- log_error('duplicate_message', $message);
- return true;
- }
- }
- //////////////////////////////////////////////////////////////
- /* 7. ADD REPLY TO TICKET */
- //////////////////////////////////////////////////////////////
- // add the new post to database
- $db->query("INSERT into ticket_message SET
- message = '" . mysql_escape_string($body) . "',
- ticketid = '$ticket[id]',
- striptags = '$striptags',
- sourceid = '$sourceid',
- date = '" . mktime() . "',
- userid = '$ticket[userid]'
- ");
- $ticket['body'] = $body;
- ticketlog($ticket['id'], 'user_replied');
- //////////////////////////////////////////////////////////////
- /* 8. UPDATE TICKET */
- //////////////////////////////////////////////////////////////
- $db->query("
- UPDATE ticket SET
- awaiting_tech = '1',
- date_awaiting_toggled = '" . mktime() . "',
- is_open = '1',
- date_lastreply = '" . mktime() . "'
- WHERE id = $ticket[id]
- ");
- //////////////////////////////////////////////////////////////
- /* 9. PROCESS ATTACHMENTS */
- //////////////////////////////////////////////////////////////
- $email_attachments = process_attachments($message->attachments, $message->embedded, $ticket[id], $user[id]);
- // Trim message to be quoted in return e-mail to 16k at most
- $message = substr($body, NULL, 16384);
- //////////////////////////////////////////////////////////////
- /* 10. SEND EMAIL TO USERS */
- //////////////////////////////////////////////////////////////
- if ($gateway[auto_reply] AND !$user[autoresponds] AND !$no_autoresponse) {
- notify_user('reply_user', $ticket, $user, $message, '', $gateway[id], $extra_mail_info);
- }
- //////////////////////////////////////////////////////////////
- /* 11. SEND EMAIL TO TECHS */
- //////////////////////////////////////////////////////////////
- notify_technicians('reply', $ticket, $user, $message, $email_attachments, $gateway[id], $extra_mail_info);
-
- }
- return true;
- }
- /*
- Function specific to user.php that gets ticket details from a
- ticket ref
- */
- function get_ticket_from_ref($ref) {
- global $db;
- if (is_int($ref)) {
- $field = 'ticket.id';
- } else {
- $field = 'ticket.ref';
- }
- $ticket = $db->query_return("
- SELECT
- ticket.*, ticket_pri.id AS priority_id, ticket_pri.name AS priority_name,
- ticket_cat.id AS category_id, ticket_cat.name AS category_name,
- tech.id AS tech_id, tech.email AS tech_email
- FROM ticket
- LEFT JOIN ticket_pri ON (ticket.priority = ticket_pri.id)
- LEFT JOIN ticket_cat ON (ticket.category = ticket_cat.id)
- LEFT JOIN tech ON (ticket.tech = tech.id)
- WHERE $field = '" . addslashes($ref) . "'
- ");
- if ($db->num_rows()) {
- return $ticket;
- } else {
- return null;
- }
- }
- ?>