Exemplo n.º 1
0
 static function lookupByToken($token)
 {
     //Expecting well formatted token see getAuthToken routine for details.
     $matches = array();
     if (!preg_match(static::$token_regex, $token, $matches)) {
         return null;
     }
     //Unpack the user and ticket ids
     $matches += unpack('Vuid/Vtid', Base32::decode(strtolower(substr($matches['hash'], 0, 13))));
     $user = null;
     switch ($matches['type']) {
         case 'c':
             //Collaborator c
             if (($user = Collaborator::lookup($matches['uid'])) && $user->getTicketId() != $matches['tid']) {
                 $user = null;
             }
             break;
         case 'o':
             //Ticket owner
             if ($ticket = Ticket::lookup($matches['tid'])) {
                 if (($user = $ticket->getOwner()) && $user->getId() != $matches['uid']) {
                     $user = null;
                 }
             }
             break;
     }
     if (!$user || !$user instanceof TicketUser || strcasecmp($user->getAuthToken($matches['algo']), $token)) {
         return false;
     }
     return $user;
 }
Exemplo n.º 2
0
 function viewCollaborator($cid)
 {
     global $thisstaff;
     if (!($collaborator = Collaborator::lookup($cid)) || !($ticket = $collaborator->getTicket()) || !$ticket->checkStaffAccess($thisstaff)) {
         Http::response(404, 'Unknown collaborator');
     }
     return self::_collaborator($collaborator);
 }
Exemplo n.º 3
0
 function _getTicketUser($ticket, $user)
 {
     // Ticket owner?
     if ($ticket->getUserId() == $user->getId()) {
         $user = $ticket->getOwner();
     } elseif (!($user = Collaborator::lookup(array('userId' => $user->getId(), 'ticketId' => $ticket->getId())))) {
         return false;
     }
     //Bro, we don't know you!
     return $user;
 }
Exemplo n.º 4
0
 function changeOwner($user)
 {
     global $thisstaff;
     if (!$user || $user->getId() == $this->getOwnerId() || !$thisstaff->canEditTickets()) {
         return false;
     }
     $sql = 'UPDATE ' . TICKET_TABLE . ' SET updated = NOW() ' . ', user_id = ' . db_input($user->getId()) . ' WHERE ticket_id = ' . db_input($this->getId());
     if (!db_query($sql) || !db_affected_rows()) {
         return false;
     }
     $this->ht['user_id'] = $user->getId();
     $this->user = null;
     $this->collaborators = null;
     $this->recipients = null;
     //Log an internal note
     $note = sprintf(_S('%s changed ticket ownership to %s'), $thisstaff->getName(), $user->getName());
     //Remove the new owner from list of collaborators
     $c = Collaborator::lookup(array('userId' => $user->getId(), 'ticketId' => $this->getId()));
     if ($c && $c->remove()) {
         $note .= ' ' . _S('(removed as collaborator)');
     }
     $this->logNote('Ticket ownership changed', $note);
     return true;
 }
Exemplo n.º 5
0
 static function lookup($criteria)
 {
     $id = is_numeric($criteria) ? $criteria : self::getIdByInfo($criteria);
     return $id && ($c = new Collaborator($id)) && $c->getId() == $id ? $c : null;
 }
 /**
  * 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 thread_id, email_mid FROM ' . TICKET_EMAIL_INFO_TABLE . ' WHERE email_mid=%s ORDER BY thread_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('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
         $thread = null;
         foreach (array_reverse($matches[0]) as $mid) {
             //Try to determine if it's a reply to a tagged email.
             $ref = null;
             if (strpos($mid, '+')) {
                 list($left, $right) = explode('@', $mid);
                 list($left, $ref) = explode('+', $left);
                 $mid = "{$left}@{$right}";
             }
             $res = db_query(sprintf($search, db_input($mid)));
             while (list($id) = db_fetch_row($res)) {
                 if (!($t = ThreadEntry::lookup($id))) {
                     continue;
                 }
                 // Capture the first match thread item
                 if (!$thread) {
                     $thread = $t;
                 }
                 // We found a match  - see if we can ID the user.
                 // XXX: Check access of ref is enough?
                 if ($ref && ($uid = $t->getUIDFromEmailReference($ref))) {
                     if ($ref[0] == 's') {
                         //staff
                         $mailinfo['staffId'] = $uid;
                     } else {
                         // user or collaborator.
                         $mailinfo['userId'] = $uid;
                     }
                     // Best possible case — found the thread and the
                     // user
                     return $t;
                 }
             }
         }
         // Second best case — found a thread but couldn't identify the
         // user from the header. Return the first thread entry matched
         if ($thread) {
             return $thread;
         }
     }
     // 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("/\\b#(\\S+)/u", $subject, $match) && ($ticket = Ticket::lookupByNumber($match[1])) && ($user = User::lookup(array('emails__address' => $mailinfo['email'])))) {
         //We have a valid ticket and user
         if ($ticket->getUserId() == $user->getId() || ($c = Collaborator::lookup(array('userId' => $user->getId(), 'ticketId' => $ticket->getId())))) {
             $mailinfo['userId'] = $user->getId();
             return $ticket->getLastMessage();
         }
     }
     // Search for the message-id token in the body
     if (preg_match('`(?:data-mid="|Ref-Mid: )([^"\\s]*)(?:$|")`', $mailinfo['message'], $match)) {
         if ($thread = ThreadEntry::lookupByRefMessageId($match[1], $mailinfo['email'])) {
             return $thread;
         }
     }
     return null;
 }