Example #1
0
         $_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();
         $_SESSION['daylight'] = $cfg->observeDaylightSaving();
         //Log login info...
         $msg = sprintf("%s/%s logged in [%s]", $ticket->getEmail(), $ticket->getExtId(), $_SERVER['REMOTE_ADDR']);
         Sys::log(LOG_DEBUG, 'User login', $msg);
         //Redirect tickets.php
         session_write_close();
         session_regenerate_id();
         @header("Location: tickets.php");
         require_once 'tickets.php';
         //Just incase. of header already sent error.
 while ($_FILES['attachment']['name'][$i]) {
     if (!$cfg->allowOnlineAttachments()) {
         //Something wrong with the form...user shouldn't have an option to attach
         $errors['attachment'] = 'File [ ' . $_FILES['attachment']['name'] . ' ] rejected: no upload permission.';
     } elseif (!$cfg->canUploadFiles()) {
         //TODO: saved vs emailed attachments...admin config??
         $errors['attachment'] = _('Upload dir invalid. Contact admin.');
     } elseif (!$cfg->canUploadFileType($_FILES['attachment']['name'][$i])) {
         $errors['attachment'] = _('Invalid file type') . ' [ ' . Format::htmlchars($_FILES['attachment']['name'][$i]) . ' ]';
     } elseif ($_FILES['attachment']['size'][$i] > $cfg->getMaxFileSize()) {
         $errors['attachment'] = _('File is too big') . ': ' . $_FILES['attachment']['size'][$i] . ' bytes';
     }
     $i++;
 }
 //Make sure the email is not banned
 if (!$errors && BanList::isbanned($ticket->getEmail())) {
     $errors['err'] = _('Email is in banlist. Must be removed to reply');
 }
 //If no error...do the do.
 if (!$errors && ($respId = $ticket->postResponse($_POST['response'], $_POST['signature'], $_FILES['attachment']))) {
     $msg = _('Response Posted Successfully');
     //Set status if any.
     $wasOpen = $ticket->isOpen();
     if (isset($_POST['ticket_status']) && $_POST['ticket_status']) {
         if ($ticket->setStatus($_POST['ticket_status']) && $ticket->reload()) {
             $note = sprintf(_('%s %s the ticket on reply'), $thisuser->getName(), $ticket->isOpen() ? _('reopened') : _('closed'));
             $ticket->logActivity(sprintf(_('Ticket status changed to %s'), $ticket->isOpen() ? _('Open') : _('Closed')), $note);
         }
     }
     //Finally upload attachment if any
     if ($_FILES['attachment'] && $_FILES['attachment']['size']) {
Example #3
0
         $_SESSION['_user']['laststrike'] = null;
         $_SESSION['_user']['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 that a ticket with the given number exists.
     $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 email match...create session goodies for the user.
         $user = new UserSession($email, $ticket->getId());
         $_SESSION['_user'] = array();
         //clear.
         $_SESSION['_user']['userID'] = $ticket->getEmail();
         //Email
         $_SESSION['_user']['key'] = $ticket->getExtId();
         //Ticket ID --acts as password when used with email. See above.
         $_SESSION['_user']['token'] = $user->getSessionToken();
         $_SESSION['TZ_OFFSET'] = $cfg->getTZoffset();
         $_SESSION['daylight'] = $cfg->observeDaylightSaving();
         //Log login info...
         $msg = sprintf("%s/%s " . _("logged in"), $ticket->getEmail(), $ticket->getExtId());
         Sys::log(LOG_DEBUG, 'User login', $msg, $ticket->getEmail());
         //Redirect tickets.php
         session_write_close();
         session_regenerate_id();
         @header("Location: tickets.php");
         require_once 'tickets.php';
         //Just incase. of header already sent error.
Example #4
0
 function create($var, &$errors, $origin, $autorespond = true, $alertstaff = true)
 {
     global $cfg, $thisclient, $_FILES;
     /* Coders never code so fully and joyfully as when they do it for free  - Peter Rotich */
     $id = 0;
     $fields = array();
     $fields['name'] = array('type' => 'string', 'required' => 1, 'error' => 'Name required');
     $fields['email'] = array('type' => 'email', 'required' => 1, 'error' => 'Valid email required');
     $fields['subject'] = array('type' => 'string', 'required' => 1, 'error' => 'Subject required');
     $fields['message'] = array('type' => 'text', 'required' => 1, 'error' => 'Message required');
     if (strcasecmp($origin, 'web') == 0) {
         //Help topic only applicable on web tickets.
         $fields['topicId'] = array('type' => 'int', 'required' => 1, 'error' => 'Select help topic');
     } elseif (strcasecmp($origin, 'staff') == 0) {
         //tickets created by staff...e.g on callins.
         $fields['deptId'] = array('type' => 'int', 'required' => 1, 'error' => 'Dept. required');
         $fields['source'] = array('type' => 'string', 'required' => 1, 'error' => 'Indicate source');
         $fields['duedate'] = array('type' => 'date', 'required' => 0, 'error' => 'Invalid date - must be MM/DD/YY');
     } else {
         //Incoming emails
         $fields['emailId'] = array('type' => 'int', 'required' => 1, 'error' => 'Email unknown');
     }
     $fields['pri'] = array('type' => 'int', 'required' => 0, 'error' => 'Invalid Priority');
     $fields['phone'] = array('type' => 'phone', 'required' => 0, 'error' => 'Valid phone # required');
     $validate = new Validator($fields);
     if (!$validate->validate($var)) {
         $errors = array_merge($errors, $validate->errors());
     }
     //Make sure the email is not banned
     if (!$errors && BanList::isbanned($var['email'])) {
         $errors['err'] = 'Ticket denied. Error #403';
         //We don't want to tell the user the real reason...Psssst.
         Sys::log(LOG_WARNING, 'Ticket denied', 'Banned email - ' . $var['email']);
         //We need to let admin know which email got banned.
     }
     if (!$errors && $thisclient && strcasecmp($thisclient->getEmail(), $var['email'])) {
         $errors['email'] = 'Email mismatch.';
     }
     //Make sure phone extension is valid
     if ($var['phone_ext']) {
         if (!is_numeric($var['phone_ext']) && !$errors['phone']) {
             $errors['phone'] = 'Invalid phone ext.';
         } elseif (!$var['phone']) {
             //make sure they just didn't enter ext without phone #
             $errors['phone'] = 'Phone number required';
         }
     }
     //Make sure the due date is valid
     if ($var['duedate']) {
         if (!$var['time'] || strpos($var['time'], ':') === false) {
             $errors['time'] = 'Select time';
         } elseif (strtotime($var['duedate'] . ' ' . $var['time']) === false) {
             $errors['duedate'] = 'Invalid duedate';
         } elseif (strtotime($var['duedate'] . ' ' . $var['time']) <= time()) {
             $errors['duedate'] = 'Due date must be in the future';
         }
     }
     //check attachment..if any is set ...only set on webbased tickets..
     if ($_FILES['attachment']['name'] && $cfg->allowOnlineAttachments()) {
         if (!$cfg->canUploadFileType($_FILES['attachment']['name'])) {
             $errors['attachment'] = 'Invalid file type [ ' . Format::htmlchars($_FILES['attachment']['name']) . ' ]';
         } elseif ($_FILES['attachment']['size'] > $cfg->getMaxFileSize()) {
             $errors['attachment'] = 'File is too big. Max ' . $cfg->getMaxFileSize() . ' bytes allowed';
         }
     }
     //check ticket limits..if limit set is >0
     //TODO: Base ticket limits on SLA...
     if ($var['email'] && !$errors && $cfg->getMaxOpenTickets() > 0 && strcasecmp($origin, 'staff')) {
         $openTickets = Ticket::getOpenTicketsByEmail($var['email']);
         if ($openTickets >= $cfg->getMaxOpenTickets()) {
             $errors['err'] = "You've reached the maximum open tickets allowed.";
             //Send the notice only once (when the limit is reached) incase of autoresponders at client end.
             if ($cfg->getMaxOpenTickets() == $openTickets && $cfg->sendOverlimitNotice()) {
                 if ($var['deptId']) {
                     $dept = new Dept($var['deptId']);
                 }
                 if (!$dept || !($tplId = $dept->getTemplateId())) {
                     $tplId = $cfg->getDefaultTemplateId();
                 }
                 $sql = 'SELECT ticket_overlimit_subj,ticket_overlimit_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($tplId);
                 $resp = db_query($sql);
                 if (db_num_rows($resp) && (list($subj, $body) = db_fetch_row($resp))) {
                     $body = str_replace("%name", $var['name'], $body);
                     $body = str_replace("%email", $var['email'], $body);
                     $body = str_replace("%url", $cfg->getBaseUrl(), $body);
                     $body = str_replace('%signature', $dept && $dept->isPublic() ? $dept->getSignature() : '', $body);
                     if (!$dept || !($email = $dept->getAutoRespEmail())) {
                         $email = $cfg->getDefaultEmail();
                     }
                     if ($email) {
                         $email->send($var['email'], $subj, $body);
                     }
                 }
                 //Alert admin...this might be spammy (no option to disable)...but it is helpful..I think.
                 $msg = 'Support ticket request denied for ' . $var['email'] . "\n" . 'Open ticket:' . $openTickets . "\n" . 'Max Allowed:' . $cfg->getMaxOpenTickets() . "\n\nNotice only sent once";
                 Sys::alertAdmin('Overlimit Notice', $msg);
             }
         }
     }
     //Any error above is fatal.
     if ($errors) {
         return 0;
     }
     // OK...just do it.
     $deptId = $var['deptId'];
     //pre-selected Dept if any.
     $priorityId = $var['pri'];
     $source = ucfirst($var['source']);
     $topic = NULL;
     // Intenal mapping magic...see if we need to overwrite anything
     if (isset($var['topicId'])) {
         //Ticket created via web by user/or staff
         if ($var['topicId'] && ($topic = new Topic($var['topicId'])) && $topic->getId()) {
             $deptId = $deptId ? $deptId : $topic->getDeptId();
             $priorityId = $priorityId ? $priorityId : $topic->getPriorityId();
             $topicDesc = $topic->getName();
             if ($autorespond) {
                 $autorespond = $topic->autoRespond();
             }
         }
         $source = $var['source'] ? $var['source'] : 'Web';
     } elseif ($var['emailId'] && !$var['deptId']) {
         //Emailed Tickets
         $email = new Email($var['emailId']);
         if ($email && $email->getId()) {
             $deptId = $email->getDeptId();
             $priorityId = $priorityId ? $priorityId : $email->getPriorityId();
             if ($autorespond) {
                 $autorespond = $email->autoRespond();
             }
         }
         $email = null;
         $source = 'Email';
     } elseif ($var['deptId']) {
         //Opened by staff.
         $deptId = $var['deptId'];
         $source = ucfirst($var['source']);
     }
     //Don't auto respond to mailer daemons.
     if (strpos(strtolower($var['email']), 'mailer-daemon@') !== false || strpos(strtolower($var['email']), 'postmaster@') !== false) {
         $autorespond = false;
     }
     //Last minute checks
     $priorityId = $priorityId ? $priorityId : $cfg->getDefaultPriorityId();
     $deptId = $deptId ? $deptId : $cfg->getDefaultDeptId();
     $topicId = $var['topicId'] ? $var['topicId'] : 0;
     $ipaddress = $var['ip'] ? $var['ip'] : $_SERVER['REMOTE_ADDR'];
     //We are ready son...hold on to the rails.
     $extId = Ticket::genExtRandID();
     $sql = 'INSERT INTO ' . TICKET_TABLE . ' SET created=NOW() ' . ',ticketID=' . db_input($extId) . ',dept_id=' . db_input($deptId) . ',topic_id=' . db_input($topicId) . ',priority_id=' . db_input($priorityId) . ',email=' . db_input($var['email']) . ',name=' . db_input(Format::striptags($var['name'])) . ',subject=' . db_input(Format::striptags($var['subject'])) . ',helptopic=' . db_input(Format::striptags($topicDesc)) . ',phone="' . db_input($var['phone'], false) . '"' . ',phone_ext=' . db_input($var['phone_ext'] ? $var['phone_ext'] : '') . ',ip_address=' . db_input($ipaddress) . ',source=' . db_input($source);
     //Make sure the origin is staff - avoid firebug hack!
     if ($var['duedate'] && !strcasecmp($origin, 'staff')) {
         $sql .= ',duedate=' . db_input(date('Y-m-d G:i', Misc::dbtime($var['duedate'] . ' ' . $var['time'])));
     }
     //echo $sql;
     $ticket = null;
     //return $ticket;
     if (db_query($sql) && ($id = db_insert_id())) {
         if (!$cfg->useRandomIds()) {
             //Sequential ticketIDs support really..really suck arse.
             $extId = $id;
             //To make things really easy we are going to use autoincrement ticket_id.
             db_query('UPDATE ' . TICKET_TABLE . ' SET ticketID=' . db_input($extId) . ' WHERE ticket_id=' . $id);
             //TODO: RETHING what happens if this fails?? [At the moment on failure random ID is used...making stuff usable]
         }
         //Load newly created ticket.
         $ticket = new Ticket($id);
         //post the message.
         $msgid = $ticket->postMessage($var['message'], $source, $var['mid'], $var['header'], true);
         //TODO: recover from postMessage error??
         //Upload attachments...web based.
         if ($_FILES['attachment']['name'] && $cfg->allowOnlineAttachments() && $msgid) {
             if (!$cfg->allowAttachmentsOnlogin() || $cfg->allowAttachmentsOnlogin() && ($thisclient && $thisclient->isValid())) {
                 $ticket->uploadAttachment($_FILES['attachment'], $msgid, 'M');
                 //TODO: recover from upload issues?
             }
         }
         $dept = $ticket->getDept();
         if (!$dept || !($tplId = $dept->getTemplateId())) {
             $tplId = $cfg->getDefaultTemplateId();
         }
         //Overwrite auto responder if the FROM email is one of the internal emails...loop control.
         if ($autorespond && Email::getIdByEmail($ticket->getEmail())) {
             $autorespond = false;
         }
         //SEND OUT NEW TICKET AUTORESP && ALERTS.
         //New Ticket AutoResponse..
         if ($autorespond && $cfg->autoRespONNewTicket() && $dept->autoRespONNewTicket()) {
             $sql = 'SELECT ticket_autoresp_subj,ticket_autoresp_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($tplId);
             if (($resp = db_query($sql)) && db_num_rows($resp) && (list($subj, $body) = db_fetch_row($resp))) {
                 $body = $ticket->replaceTemplateVars($body);
                 $subj = $ticket->replaceTemplateVars($subj);
                 $body = str_replace('%message', $var['issue'] ? $var['issue'] : $var['message'], $body);
                 $body = str_replace('%signature', $dept && $dept->isPublic() ? $dept->getSignature() : '', $body);
                 if (!$dept || !($email = $dept->getAutoRespEmail())) {
                     $email = $cfg->getDefaultEmail();
                 }
                 if ($email) {
                     //Reply separator tag.
                     if ($cfg->stripQuotedReply() && ($tag = $cfg->getReplySeparator())) {
                         $body = "\n{$tag}\n\n" . $body;
                     }
                     $email->send($ticket->getEmail(), $subj, $body);
                 }
             } else {
                 Sys::log(LOG_WARNING, 'Template Fetch Error', "Unable to fetch autoresponse template #{$tplId}");
             }
         }
         //If enabled...send alert to staff (New Ticket Alert)
         if ($alertstaff && $cfg->alertONNewTicket() && is_object($ticket)) {
             $sql = 'SELECT ticket_alert_subj,ticket_alert_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($tplId);
             if (($resp = db_query($sql)) && db_num_rows($resp) && (list($subj, $body) = db_fetch_row($resp))) {
                 $body = $ticket->replaceTemplateVars($body);
                 $subj = $ticket->replaceTemplateVars($subj);
                 $body = str_replace('%message', $var['issue'] ? $var['issue'] : $var['message'], $body);
                 if (!($email = $cfg->getAlertEmail())) {
                     $email = $cfg->getDefaultEmail();
                 }
                 if ($email && $email->getId()) {
                     $sentlist = array();
                     //Admin Alert.
                     if ($cfg->alertAdminONNewTicket()) {
                         $alert = str_replace("%staff", 'Admin', $body);
                         $email->send($cfg->getAdminEmail(), $subj, $alert);
                         $sentlist[] = $cfg->getAdminEmail();
                     }
                     //get the list
                     $recipients = array();
                     //Dept. Manager
                     if ($cfg->alertDeptManagerONNewTicket()) {
                         $recipients[] = $dept->getManager();
                     }
                     //Staff members
                     if ($cfg->alertDeptMembersONNewTicket()) {
                         $sql = 'SELECT staff_id FROM ' . STAFF_TABLE . ' WHERE onvacation=0 AND dept_id=' . db_input($dept->getId());
                         if (($users = db_query($sql)) && db_num_rows($users)) {
                             while (list($id) = db_fetch_row($users)) {
                                 $recipients[] = new Staff($id);
                             }
                         }
                     }
                     foreach ($recipients as $k => $staff) {
                         if (!$staff || !is_object($staff) || !$staff->isAvailable()) {
                             continue;
                         }
                         if (in_array($staff->getEmail(), $sentlist)) {
                             continue;
                         }
                         //avoid duplicate emails.
                         $alert = str_replace("%staff", $staff->getFirstName(), $body);
                         $email->send($staff->getEmail(), $subj, $alert);
                         $sentlist[] = $staff->getEmail();
                     }
                 }
             } else {
                 Sys::log(LOG_WARNING, 'Template Fetch Error', "Unable to fetch 'new ticket' alert template #{$tplId}");
             }
         }
     }
     return $ticket;
 }
Example #5
0
    $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()) {
    $errors = array();
Example #6
0
 if ($lock && $lock->getStaffId() != $thisuser->getId()) {
     $errors['err'] = 'Action Denied. Ticket is locked by someone else!';
 }
 //Check attachments restrictions.
 if ($_FILES['attachment'] && $_FILES['attachment']['size']) {
     if (!$_FILES['attachment']['name'] || !$_FILES['attachment']['tmp_name']) {
         $errors['attachment'] = 'Invalid attachment';
     } elseif (!$cfg->canUploadFiles()) {
         //TODO: saved vs emailed attachments...admin config??
         $errors['attachment'] = 'upload dir invalid. Contact admin.';
     } elseif (!$cfg->canUploadFileType($_FILES['attachment']['name'])) {
         $errors['attachment'] = 'Invalid file type';
     }
 }
 //Make sure the email is not banned
 if (!$errors && BanList::isbanned($ticket->getEmail())) {
     $errors['err'] = 'Email is in banlist. Must be removed to reply';
 }
 //If no error...do the do.
 if (!$errors && ($respId = $ticket->postResponse($_POST['msg_id'], $_POST['response'], $_POST['signature'], $_FILES['attachment']))) {
     $msg = 'Response Posted Successfully';
     //Set status if any.
     if (isset($_POST['ticket_status']) && $_POST['ticket_status']) {
         $ticket->setStatus($_POST['ticket_status']);
     }
     //Finally upload attachment if any
     if ($_FILES['attachment'] && $_FILES['attachment']['size']) {
         $ticket->uploadAttachment($_FILES['attachment'], $respId, 'R');
     }
 } else {
     $errors['err'] = $errors['err'] ? $errors['err'] : 'Unable to post the response.';
Example #7
0
 //Must wait for 5 minutes after each strike.
 if ($_SESSION['_client']['laststrike'] && time() - $_SESSION['_client']['laststrike'] < 5 * 60) {
     $errors['err'] = 'You\'ve reached maximum failed login attempts allowed. Try again after 5 minutes or <a href="new.php">open a new ticket</a>';
 }
 //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();
         $_SESSION['daylight'] = $cfg->observeDaylightSaving();
         //Redirect view.php
         @header("Location: view.php");
         require 'view.php';
         //Just incase. of header already sent error.
         exit;
     }
 }
 //If we get to this point we know the login failed.
 //TODO: login strikes should be DB based for better security checks ( session can be reset!)
Example #8
0
    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;
    }
 function create($var, &$errors, $origin, $autorespond = true, $alertstaff = true)
 {
     global $cfg, $thisclient, $_FILES;
     $id = 0;
     $fields = array();
     $fields['name'] = array('type' => 'string', 'required' => 1, 'error' => 'Name required');
     $fields['email'] = array('type' => 'email', 'required' => 1, 'error' => 'Valid email required');
     $fields['subject'] = array('type' => 'string', 'required' => 1, 'error' => 'Subject required');
     $fields['message'] = array('type' => 'text', 'required' => 1, 'error' => 'Message required');
     if (strcasecmp($origin, 'web') == 0) {
         //Help topic only applicable on web tickets.
         $fields['topicId'] = array('type' => 'int', 'required' => 1, 'error' => 'Select help topic');
     } elseif (strcasecmp($origin, 'staff') == 0) {
         //tickets created by staff...e.g on callins.
         $fields['deptId'] = array('type' => 'int', 'required' => 1, 'error' => 'Dept. required');
         $fields['source'] = array('type' => 'string', 'required' => 1, 'error' => 'Indicate source');
     } else {
         //Incoming emails (PIPE or POP.
         $fields['emailId'] = array('type' => 'int', 'required' => 1, 'error' => 'Email unknown');
     }
     $fields['pri'] = array('type' => 'int', 'required' => 0, 'error' => 'Invalid Priority');
     $fields['phone'] = array('type' => 'phone', 'required' => 0, 'error' => 'Phone # required');
     $validate = new Validator($fields);
     if (!$validate->validate($var)) {
         $errors = array_merge($errors, $validate->errors());
     }
     //Make sure the email is not banned
     if (!$errors && BanList::isbanned($var['email'])) {
         $errors['err'] = 'Ticket denied Error #403';
     }
     if (!$errors && $thisclient && strcasecmp($thisclient->getEmail(), $var['email'])) {
         $errors['email'] = 'Email mismatch.';
     }
     //check attachment..if any is set ...only set on webbased tickets..
     if ($_FILES['attachment']['name'] && $cfg->allowOnlineAttachments()) {
         if (!$cfg->canUploadFileType($_FILES['attachment']['name'])) {
             $errors['attachment'] = 'Invalid file type [ ' . $_FILES['attachment']['name'] . ' ]';
         } elseif ($_FILES['attachment']['size'] > $cfg->getMaxFileSize()) {
             $errors['attachment'] = 'File is too big. Max ' . $cfg->getMaxFileSize() . ' bytes allowed';
         }
     }
     //check ticket limits..if limit set is >0
     //TODO: Base ticket limits on SLA...
     if ($var['email'] && !$errors && $cfg->getMaxOpenTickets() > 0) {
         $openTickets = Ticket::getOpenTicketsByEmail($var['email']);
         if ($openTickets >= $cfg->getMaxOpenTickets()) {
             $errors['err'] = "You've reached the maximum open tickets allowed.";
             //Send the notice only once (when the limit is reached) incase of autoresponders at client end.
             if ($cfg->getMaxOpenTickets() == $openTickets && $cfg->sendOverlimitNotice()) {
                 $sql = 'SELECT ticket_overlimit_subj,ticket_overlimit_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($cfg->getDefaultTemplateId());
                 $resp = db_query($sql);
                 if (db_num_rows($resp) && (list($subj, $body) = db_fetch_row($resp))) {
                     $body = str_replace("%name", $var['name'], $body);
                     $body = str_replace("%email", $var['email'], $body);
                     $body = str_replace("%url", $cfg->getBaseUrl(), $body);
                     Misc::sendmail($var['email'], $subj, $body, $cfg->getNoReplyEmail());
                 }
             }
             //Alert admin...this might be spammy (no option to disable)...but it is helpful..I think.
             $msg = 'Support ticket request denied for ' . $var['email'] . "\n" . 'Open ticket:' . $openTickets . "\n" . 'Max Allowed:' . $cfg->getMaxOpenTickets() . "\n";
             Misc::alertAdmin('Overlimit Notice', $msg);
         }
     }
     //Any error above is fatal.
     if ($errors) {
         return 0;
     }
     // OK...just do it.
     $deptId = $var['deptId'];
     //pre-selected Dept if any.
     $priorityId = $var['pri'];
     $source = ucfirst($var['source']);
     // Intenal mapping magic...see if we need to overwrite anything
     if (isset($var['topicId']) && !$var['deptId']) {
         //Ticket created via web by user
         if ($var['topicId'] && ($topic = new Topic($var['topicId'])) && $topic->getId()) {
             $deptId = $topic->getDeptId();
             $priorityId = $priorityId ? $priorityId : $topic->getPriorityId();
             $autorespond = $topic->autoRespond();
         }
         $topic = null;
         $source = 'Web';
     } elseif ($var['emailId'] && !$var['deptId']) {
         //Emailed Tickets
         $email = new Email($var['emailId']);
         if ($email && $email->getId()) {
             $deptId = $email->getDeptId();
             $autorespond = $email->autoRespond();
             $priorityId = $priorityId ? $priorityId : $email->getPriorityId();
         }
         $email = null;
         $source = 'Email';
     } elseif ($var['deptId']) {
         //Opened by staff.
         $deptId = $var['deptId'];
         $source = ucfirst($var['source']);
     }
     //Last minute checks
     $priorityId = $priorityId ? $priorityId : $cfg->getDefaultPriorityId();
     $deptId = $deptId ? $deptId : $cfg->getDefaultDeptId();
     $ipaddress = $var['ip'] ? $var['ip'] : $_SERVER['REMOTE_ADDR'];
     //We are ready son...hold on to the rails.
     $extId = Ticket::genExtRandID();
     $sql = 'INSERT INTO ' . TICKET_TABLE . ' SET created=NOW() ' . ',ticketID=' . db_input($extId) . ',dept_id=' . db_input($deptId) . ',priority_id=' . db_input($priorityId) . ',email=' . db_input($var['email']) . ',name=' . db_input(Format::striptags($var['name'])) . ',subject=' . db_input(Format::striptags($var['subject'])) . ',phone=' . db_input($var['phone']) . ',ip_address=' . db_input($ipaddress) . ',source=' . db_input($source);
     //echo $sql;
     $ticket = null;
     //return $ticket;
     if (db_query($sql) && ($id = db_insert_id())) {
         if (!$cfg->useRandomIds()) {
             //Sequential ticketIDs support really..really suck arse.
             $extId = $id;
             //To make things really easy we are going to use autoincrement ticket_id.
             db_query('UPDATE ' . TICKET_TABLE . ' SET ticketID=' . db_input($extId) . ' WHERE ticket_id=' . $id);
             //TODO: RETHING what happens if this fails?? [At the moment on failure random ID is used...making stuff usable]
         }
         //Load newly created ticket.
         $ticket = new Ticket($id);
         //post the message.
         $msgid = $ticket->postMessage($var['message'], $var['header'], $source, true);
         //TODO: recover from postMessage error??
         //Upload attachments...web based.
         if ($_FILES['attachment']['name'] && $cfg->allowOnlineAttachments() && $msgid) {
             if (!$cfg->allowAttachmentsOnlogin() || $cfg->allowAttachmentsOnlogin() && ($thisclient && $thisclient->isValid())) {
                 $ticket->uploadAttachment($_FILES['attachment'], $msgid, 'M');
                 //TODO: recover from upload issues?
             }
         }
         $dept = $ticket->getDept();
         //SEND OUT NEW TICKET AUTORESP && ALERTS.
         //New Ticket AutoResponse..
         if ($autorespond && $cfg->autoRespONNewTicket() && $dept->autoRespONNewTicket()) {
             $sql = 'SELECT ticket_autoresp_subj,ticket_autoresp_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($cfg->getDefaultTemplateId());
             $resp = db_query($sql);
             if ($resp && (list($subj, $body) = db_fetch_row($resp))) {
                 $subj = str_replace("%ticket", $ticket->getExtId(), $subj);
                 $body = str_replace("%ticket", $ticket->getExtId(), $body);
                 $body = str_replace("%name", $ticket->getName(), $body);
                 $body = str_replace("%email", $ticket->getEmail(), $body);
                 $body = str_replace("%url", $cfg->getBaseUrl(), $body);
                 $body = str_replace("%signature", $dept ? $dept->getSignature() : '', $body);
                 $email = $from = $fromName = null;
                 if (!$dept->noreplyAutoResp() && ($email = $dept->getEmail())) {
                     $from = $email->getEmail();
                     $fromName = $email->getName();
                     //Reply separator tag.
                     if ($cfg->stripQuotedReply() && ($tag = $cfg->getReplySeparator())) {
                         $body = "\n{$tag}\n\n" . $body;
                     }
                 } else {
                     $from = $cfg->getNoReplyEmail();
                 }
                 Misc::sendmail($ticket->getEmail(), $subj, $body, $from, $fromName);
             }
         }
         //If enabled...send alert to staff (New Ticket Alert)
         if ($alertstaff && $cfg->alertONNewTicket() && is_object($ticket)) {
             $sql = 'SELECT ticket_alert_subj,ticket_alert_body FROM ' . EMAIL_TEMPLATE_TABLE . ' WHERE cfg_id=' . db_input($cfg->getId()) . ' AND tpl_id=' . db_input($cfg->getDefaultTemplateId());
             $resp = db_query($sql);
             if ($resp && (list($subj, $body) = db_fetch_row($resp))) {
                 $body = str_replace("%ticket", $ticket->getExtId(), $body);
                 $body = str_replace("%name", $ticket->getName(), $body);
                 $body = str_replace("%email", $ticket->getEmail(), $body);
                 $body = str_replace("%subject", $ticket->getSubject(), $body);
                 $body = str_replace("%dept", $dept ? $dept->getName() : '', $body);
                 $body = str_replace("%message", $var['message'], $body);
                 $body = str_replace("%url", $cfg->getBaseUrl(), $body);
                 $sentlist = array();
                 //Admin Alert.
                 if ($cfg->alertAdminONNewTicket()) {
                     $alert = str_replace("%staff", 'Admin', $body);
                     Misc::sendmail($cfg->getAdminEmail(), $subj, $alert, $cfg->getAlertEmail());
                     $sentlist[] = $cfg->getAdminEmail();
                 }
                 //get the list
                 $recipients = array();
                 //Dept. Manager
                 if ($cfg->alertDeptManagerONNewTicket()) {
                     $recipients[] = $dept->getManager();
                 }
                 //Staff members
                 if ($cfg->alertDeptMembersONNewTicket()) {
                     $sql = 'SELECT staff_id FROM ' . STAFF_TABLE . ' WHERE onvacation=0 AND dept_id=' . db_input($dept->getId());
                     if (($users = db_query($sql)) && db_num_rows($users)) {
                         while (list($id) = db_fetch_row($users)) {
                             $recipients[] = new Staff($id);
                         }
                     }
                 }
                 //Ok...we are ready to go...baby!
                 foreach ($recipients as $k => $staff) {
                     if (!$staff || !is_object($staff) || !$staff->isAvailable()) {
                         continue;
                     }
                     if (in_array($staff->getEmail(), $sentlist)) {
                         continue;
                     }
                     //avoid duplicate emails.
                     $alert = str_replace("%staff", $staff->getFirstName(), $body);
                     Misc::sendmail($staff->getEmail(), $subj, $alert, $cfg->getAlertEmail());
                     $sentlist[] = $staff->getEmail();
                 }
             }
         }
     }
     return $ticket;
 }