//$_SESSION['_client']=array(); #Uncomment to disable login strikes. //Check time for last max failed login attempt strike. $loginmsg = 'Invalid login'; if ($_SESSION['_client']['laststrike']) { if (time() - $_SESSION['_client']['laststrike'] < $cfg->getClientLoginTimeout()) { $loginmsg = 'Excessive failed login attempts'; $errors['err'] = 'You\'ve reached maximum failed login attempts allowed. Try again later or <a href="open.php">open a new ticket</a>'; } else { //Timeout is over. //Reset the counter for next round of attempts after the timeout. $_SESSION['_client']['laststrike'] = null; $_SESSION['_client']['strikes'] = 0; } } //See if we can fetch local ticket id associated with the ID given if (!$errors && is_numeric($ticketID) && Validator::is_email($email) && ($tid = Ticket::getIdByExtId($ticketID))) { //At this point we know the ticket is valid. $ticket = new Ticket($tid); //TODO: 1) Check how old the ticket is...3 months max?? 2) Must be the latest 5 tickets?? //Check the email given. if ($ticket->getId() && strcasecmp($ticket->getEMail(), $email) == 0) { //valid match...create session goodies for the client. $user = new ClientSession($email, $ticket->getId()); $_SESSION['_client'] = array(); //clear. $_SESSION['_client']['userID'] = $ticket->getEmail(); //Email $_SESSION['_client']['key'] = $ticket->getExtId(); //Ticket ID --acts as password when used with email. See above. $_SESSION['_client']['token'] = $user->getSessionToken(); $_SESSION['TZ_OFFSET'] = $cfg->getTZoffset();
$subj = utf8_encode($parser->getSubject()); if (!($body = Format::stripEmptyLines($parser->getBody())) && $subj) { $body = $subj; } $var['mid'] = $parser->getMessageId(); $var['email'] = $from->mailbox . '@' . $from->host; $var['name'] = $name ? utf8_encode($name) : $var['email']; $var['emailId'] = $emailId ? $emailId : $cfg->getDefaultEmailId(); $var['subject'] = $subj ? $subj : '[No Subject]'; $var['message'] = utf8_encode(Format::stripEmptyLines($body)); $var['header'] = $parser->getHeader(); $var['priorityId'] = $cfg->useEmailPriority() ? $parser->getPriority() : 0; $ticket = null; if (preg_match("[[#][0-9]{1,10}]", $var['subject'], $regs)) { $extid = trim(preg_replace("/[^0-9]/", "", $regs[0])); $ticket = new Ticket(Ticket::getIdByExtId($extid)); //Allow mismatched emails?? For now hell NO. if (!is_object($ticket) || strcasecmp($ticket->getEmail(), $var['email'])) { $ticket = null; } } $errors = array(); $msgid = 0; if (!$ticket) { //New tickets... $ticket = Ticket::create($var, $errors, 'email'); if (!is_object($ticket) || $errors) { api_exit(EX_DATAERR, 'Ticket create Failed ' . implode("\n", $errors) . "\n\n"); } $msgid = $ticket->getLastMsgId(); } else {
function createTicket($mid,$emailid=0){ global $cfg; $mailinfo=$this->getHeaderInfo($mid); //Make sure the email is NOT one of the undeleted emails. if($mailinfo['mid'] && ($id=Ticket::getIdByMessageId(trim($mailinfo['mid']),$mailinfo['from']['email']))){ //TODO: Move emails to a fetched folder when delete is false?? return false; } $var['name']=$this->mime_decode($mailinfo['from']['name']); $var['email']=$mailinfo['from']['email']; $var['subject']=$mailinfo['subject']?$this->mime_decode($mailinfo['subject']):'[No Subject]'; $var['message']=Format::stripEmptyLines($this->getBody($mid)); $var['header']=$this->getHeader($mid); $var['emailId']=$emailid?$emailid:$cfg->getDefaultEmailId(); //ok to default? $var['name']=$var['name']?$var['name']:$var['email']; //No name? use email $var['mid']=$mailinfo['mid']; if($cfg->useEmailPriority()) $var['pri']=$this->getPriority($mid); $ticket=null; $newticket=true; //Check the subject line for possible ID. if(preg_match ("[[#][0-9]{1,10}]",$var['subject'],$regs)) { $extid=trim(preg_replace("/[^0-9]/", "", $regs[0])); $ticket= new Ticket(Ticket::getIdByExtId($extid)); //Allow mismatched emails?? For now NO. if(!$ticket || strcasecmp($ticket->getEmail(),$var['email'])) $ticket=null; } $errors=array(); if(!$ticket) { if(!($ticket=Ticket::create($var,$errors,'Email')) || $errors) return null; $msgid=$ticket->getLastMsgId(); }else{ $message=$var['message']; //Strip quoted reply...TODO: figure out how mail clients do it without special tag.. if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()) && strpos($var['message'],$tag)) list($message)=split($tag,$var['message']); $msgid=$ticket->postMessage($message,'Email',$var['mid'],$var['header']); } //Save attachments if any. if($msgid && $cfg->allowEmailAttachments()){ if(($struct = imap_fetchstructure($this->mbox,$mid)) && $struct->parts) { if($ticket->getLastMsgId()!=$msgid) $ticket->setLastMsgId($msgid); $this->saveAttachments($ticket,$mid,$struct); } } return $ticket; }
vim: expandtab sw=4 ts=4 sts=4: $Id: $ **********************************************************************/ require 'secure.inc.php'; if (!is_object($thisclient) || !$thisclient->isValid()) { die('Access denied'); } //Double check again. require_once INCLUDE_DIR . 'class.ticket.php'; $ticket = null; $inc = 'tickets.inc.php'; //Default page...show all tickets. //Check if any id is given... if (($id = $_REQUEST['id'] ? $_REQUEST['id'] : $_POST['ticket_id']) && is_numeric($id)) { //id given fetch the ticket info and check perm. $ticket = new Ticket(Ticket::getIdByExtId((int) $id)); if (!$ticket or !$ticket->getEmail()) { $ticket = null; //clear. $errors['err'] = 'Access Denied. Possibly invalid ticket ID'; } elseif (strcasecmp($thisclient->getEmail(), $ticket->getEmail())) { $errors['err'] = 'Security violation. Repeated violations will result in your account being locked.'; $ticket = null; //clear. } else { //Everything checked out. $inc = 'viewticket.inc.php'; } } //Process post...depends on $ticket object above. if ($_POST && is_object($ticket) && $ticket->getId()) {
/** * Parameters: * mailinfo (hash<String>) email header information. Must include keys * - "mid" => Message-Id header of incoming mail * - "in-reply-to" => Message-Id the email is a direct response to * - "references" => List of Message-Id's the email is in response * - "subject" => Find external ticket number in the subject line * * seen (by-ref:bool) a flag that will be set if the message-id was * positively found, indicating that the message-id has been * previously seen. This is useful if no thread-id is associated * with the email (if it was rejected for instance). */ function lookupByEmailHeaders($mailinfo, &$seen = false) { // Search for messages using the References header, then the // in-reply-to header $search = 'SELECT message_id, email_mid FROM ' . TICKET_EMAIL_INFO_TABLE . ' WHERE email_mid=%s ORDER BY message_id DESC'; if (list($id, $mid) = db_fetch_row(db_query(sprintf($search, db_input($mailinfo['mid']))))) { $seen = true; return ThreadEntry::lookup($id); } foreach (array('mid', 'in-reply-to', 'references') as $header) { $matches = array(); if (!isset($mailinfo[$header]) || !$mailinfo[$header]) { continue; } elseif (!preg_match_all('/<[^>@]+@[^>]+>/', $mailinfo[$header], $matches)) { continue; } // The References header will have the most recent message-id // (parent) on the far right. // @see rfc 1036, section 2.2.5 // @see http://www.jwz.org/doc/threading.html foreach (array_reverse($matches[0]) as $mid) { $res = db_query(sprintf($search, db_input($mid))); while (list($id) = db_fetch_row($res)) { if ($t = ThreadEntry::lookup($id)) { return $t; } } } } // Search for ticket by the [#123456] in the subject line // This is the last resort - emails must match to avoid message // injection by third-party. $subject = $mailinfo['subject']; $match = array(); if ($subject && $mailinfo['email'] && preg_match("/#(?:[\\p{L}-]+)?([0-9]{1,10})/u", $subject, $match) && ($tid = Ticket::getIdByExtId((int) $match[1], $mailinfo['email']))) { // Return last message for the thread return Message::lastByTicketId($tid); } return null; }