diff --git a/include/class.import.php b/include/class.import.php index dc9a027c1d4af5606a6f9f2df293f9e097d5b72f..7e887e7690a3d042505f0b4f9e8a74e1b47dc93d 100644 --- a/include/class.import.php +++ b/include/class.import.php @@ -39,7 +39,7 @@ class CsvImporter { rewind($this->stream); } else { - throw new ImportError(__('Unable to parse submitted csv: ').print_r($stream, true)); + throw new ImportError(__('Unable to parse submitted csv: ').print_r(Format::htmlchars($stream), true)); } } @@ -59,7 +59,7 @@ class CsvImporter { throw new ImportError(__('Whoops. Perhaps you meant to send some CSV records')); $headers = array(); - foreach ($data as $h) { + foreach (Format::htmlchars($data) as $h) { $h = trim($h); $found = false; foreach ($all_fields as $f) { @@ -68,7 +68,7 @@ class CsvImporter { $found = true; if (!$f->get('name')) throw new ImportError(sprintf(__( - '%s: Field must have `variable` set to be imported'), $h)); + '%s: Field must have `variable` set to be imported'), Format::htmlchars($h))); $headers[$f->get('name')] = $f->get('label'); break; } @@ -85,7 +85,7 @@ class CsvImporter { } else { throw new ImportError(sprintf( - __('%s: Unable to map header to the object field'), $h)); + __('%s: Unable to map header to the object field'), Format::htmlchars($h))); } } } diff --git a/include/class.mailfetch.php b/include/class.mailfetch.php index fec76bc01d961c93bbd7d559e04e7539a0a89228..2db19fc7bf7166082a223c038fcbbb8b7a9942b7 100644 --- a/include/class.mailfetch.php +++ b/include/class.mailfetch.php @@ -384,8 +384,17 @@ class MailFetcher { return $header; } + function fetchBody($mid, $index, $encoding) { + $body = imap_fetchbody($this->mbox, $mid, $index); + if ($body && $encoding) + $body = $this->decode($body, $encoding); + + return $body; + } + //search for specific mime type parts....encoding is the desired encoding. - function getPart($mid, $mimeType, $encoding=false, $struct=null, $partNumber=false, $recurse=-1, $recurseIntoRfc822=true) { + function getPart($mid, $mimeType, $encoding=false, $struct=null, + $partNumber=false, $recurse=-1, $recurseIntoRfc822=false) { if(!$struct && $mid) $struct=@imap_fetchstructure($this->mbox, $mid); @@ -475,8 +484,9 @@ class MailFetcher { */ function getAttachments($part, $index=0) { - - if($part && !$part->parts) { + $ctype = $part ? $this->getMimeType($part) : false; + if($part && (!$part->parts + || strcasecmp($ctype, 'message/rfc822') === 0)) { //Check if the part is an attachment. $filename = false; if ($part->ifdisposition && $part->ifdparameters @@ -501,6 +511,12 @@ class MailFetcher { $filename = _S('image').'-'.Misc::randCode(4).'.'.strtolower($part->subtype); } + // Attached message/rfc822 without filename. + if (!$filename + && $ctype + && strcasecmp($ctype, 'message/rfc822') === 0) + $filename = 'email-message-'.Misc::randCode(4).'.eml'; + if($filename) { return array( array( @@ -658,11 +674,13 @@ class MailFetcher { return true; //Report success (moved or delete) } - // Parse MS TNEF emails + // Process overloaded attachments if (($struct = imap_fetchstructure($this->mbox, $mid)) && ($attachments = $this->getAttachments($struct))) { foreach ($attachments as $i=>$info) { - if (0 === strcasecmp('application/ms-tnef', $info['type'])) { + switch (strtolower($info['type'])) { + // Parse MS TNEF emails + case 'application/ms-tnef': try { $data = $this->decode(imap_fetchbody($this->mbox, $mid, $info['index']), $info['encoding']); @@ -675,6 +693,26 @@ class MailFetcher { } catch (TnefException $ex) { // Noop -- winmail.dat remains an attachment } + break; + // Parse attached email message + case 'message/rfc822': + try { + // Fetch the header of attached mime message. + $body = $this->fetchBody($mid, $info['index'].'.0', + $info['encoding']); + // Add fake body to make the parser happy + if ($body) + $body.="\n\nJunk"; + + $parser = new Mail_Parse($body); + if ($parser->decode() + && ($subj = $parser->getSubject())) + $attachments[$i]['name'] = $subj.'.eml'; + } catch(Exception $ex) { + // Noop -- use random name + } + $body = $parser = null; + break; } } } @@ -928,7 +966,8 @@ class MailFetcher { db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($emailId)); if (++$errors>=$MAXERRORS) { //We've reached the MAX consecutive errors...will attempt logins at delayed intervals - $msg="\n"._S('osTicket is having trouble fetching emails from the following mail account').": \n". + // XXX: Translate me + $msg="\nosTicket is having trouble fetching emails from the following mail account: \n". "\n"._S('User').": ".$fetcher->getUsername(). "\n"._S('Host').": ".$fetcher->getHost(). "\n"._S('Error').": ".$fetcher->getLastError(). diff --git a/include/class.staff.php b/include/class.staff.php index 941f8baba2abd7849ed3c3d9036be434de26b3d7..6d0a6e92cb54caad28f596727ffbb68eef2bcf39 100644 --- a/include/class.staff.php +++ b/include/class.staff.php @@ -946,8 +946,8 @@ implements AuthenticatedUser, EmailContact, TemplateVariable { } else { throw new ImportError(sprintf(__('Unable to import (%s): %s'), - $data['username'], - print_r($errors, true) + Format::htmlchars($data['username']), + print_r(Format::htmlchars($errors), true) )); } $imported++; diff --git a/include/class.user.php b/include/class.user.php index e16259ce7e30f50ba15d619de90a24de4f6924f8..f991e10ad54d0223c5b7976ce88ba0ba036a84e7 100644 --- a/include/class.user.php +++ b/include/class.user.php @@ -456,7 +456,7 @@ implements TemplateVariable { throw new ImportError('Both `name` and `email` fields are required'); if (!($user = static::fromVars($data, true, true))) throw new ImportError(sprintf(__('Unable to import user: %s'), - print_r($data, true))); + print_r(Format::htmlchars($data), true))); $imported++; } db_autocommit(true);