diff --git a/class.RewriterPlugin.php b/class.RewriterPlugin.php
index 444f2d0..888f409 100644
--- a/class.RewriterPlugin.php
+++ b/class.RewriterPlugin.php
@@ -1,725 +1,749 @@
log("Bootstrappin..");
- }
- // Listen for new tickets being created:
- Signal::connect('ticket.create.before',
- function ($obj, &$vars) {
+ /**
+ * Which config class to load
+ *
+ * @var string
+ */
+ var $config_class = 'RewriterPluginConfig';
+
+ /**
+ * Set to TRUE to enable webserver logging, and extra logging.
+ *
+ * @var boolean
+ */
+ const DEBUG = FALSE;
+
+ /**
+ * Turn on to fill your cron logs with every piece of data we have to play
+ * with. Great for development/debugging.. not so great in a busy ticket
+ * system.
+ *
+ * @var boolean
+ */
+ const DUMPWHOLETHING = FALSE;
+
+ /**
+ * Hook the bootstrap process, wait for tickets to be created. Run on every
+ * instantiation, so needs to be concise.
+ *
+ * {@inheritdoc}
+ *
+ * @see Plugin::bootstrap()
+ */
+ public function bootstrap() {
if (self::DUMPWHOLETHING) {
- $this->log("Received signal ticket.create.before");
- if (function_exists('xdebug_var_dump')) { // shouldn't be enabled on prod, but if it is, and DUMPWHOLETHING is enabled, then woo:
- xdebug_break();
- }
- else {
- print_r($vars);
- }
- }
- // Only email would send a mail ID.. right? (API can simply set the sender's email manually, the web isn't forwarding.. )
- if (isset($vars['mid'])) {
- $this->process_ticket($vars);
- }
- elseif (self::DEBUG) {
- $this->log("Ignoring invalid ticket source.");
- }
- });
-
- // See if admin wants to remove all attachments:
- if ($this->getConfig()->get('delete-attachments')) {
- // Listen to the mail.processed signal, and simply drop any attachments..
- // if you wanted to delete all attachments, but didn't want to turn them off
- // in the admin config for some reason..
- // Note: Haven't found any signals for piped email..
- // Really wish there was one before the attachments were downloaded.
- // apparently not.
- Signal::connect('mail.processed',
- function ($mf, &$vars) {
- $this->log("All Attachments Purged, as instructed.");
- $vars['attachments'] = array();
- });
- }
- elseif ($this->getConfig()->get('delete-for-departments')) {
- // Little bit tricker, we need to wait for the thread to be created for the ticket,
- // check it's department, if known, match it with the admin specified departments
- // then purge any attachments found.
- Signal::connect('threadentry.created',
- function ($entry) {
- $this->log(
- "Received threadentry.created signal, told to check for departments.");
- $this->purgeAttachmentsByDepartment($entry);
+ $this->log("Bootstrappin..");
+ }
+ // Listen for new tickets being created:
+ Signal::connect('ticket.create.before', function ($obj, &$vars) {
+ if (self::DUMPWHOLETHING) {
+ $this->log("Received signal ticket.create.before");
+ if (function_exists('xdebug_var_dump')) { // shouldn't be enabled on prod, but if it is, and DUMPWHOLETHING is enabled, then woo:
+ xdebug_break();
+ } else {
+ print_r($vars);
+ }
+ }
+ // Only email would send a mail ID.. right? (API can simply set the sender's email manually, the web isn't forwarding.. )
+ if (isset($vars['mid'])) {
+ $this->process_ticket($vars);
+ } elseif (self::DEBUG) {
+ $this->log("Ignoring invalid ticket source.");
+ }
});
- }
- }
-
- /**
- * Takes an array of variables and checks to see if it matches the normal
- * "Forwarded Message" attributes.. Need to find the earliest sender combo in
- * the array. There could be quite a chain Customer email's Dealer Dealer
- * forwards to Distributor Distributor forwards to Manufacturer Manufacturer
- * internally forwards to Ticketing system ETC.. We actually want the Customer
- * one. the First one. Which, in this case, is the LAST one. There is
- * apparently no RFC for forwarded messages (as per:
- * http://stackoverflow.com/a/4743303)
- *
- * @param array $vars
- */
- private function process_ticket(&$vars) {
- // This only works for email.. Tickets created by admins with manually entered "Fwd" stuff,
- // get's filtered by redactor or whatever that is called, so it doesn't work there.
- if (! $vars['message'] instanceof ThreadEntryBody) {
- if (self::DEBUG)
- $this->log(
- "Unable to process ticket, message body wasn't in expected format, this plugin only works for 1.10+. ");
- return;
- }
- $restrict_forwarding_to_these_domains = $this->getConfig()->get('domains');
- // if no domains are specified, we just allow NO domains to forward..
- if (strlen($restrict_forwarding_to_these_domains)) {
- $this->rewriteForward($vars, $restrict_forwarding_to_these_domains);
- }
+ // See if admin wants to prune metadata from responses (different signal)
+ if ($this->getConfig()->get('strip-metadata')) {
+ Signal::connect('threadentry.created', function(ThreadEntry $entry) {
+ $this->stripMetadata($entry);
+ });
+ }
- // Test for Drupal messages:
- if ($this->getConfig()->get('drupal') &&
- preg_match('/sent a message using the contact form at/i', $message_body)) {
-
- // The message body indicates it could be sent from a Drupal /contact form
- // Luckily the default is PlainText (for Drupal 7 and lower at least)
- if (self::DEBUG)
- $this->log("Matched Drupal message.");
-
- // Attempt to locate the sender in the first line.
- // Will fetch the name, then the email which is in (braces)
- $sender = array();
- // TODO: Figure out what this would be for different languages?
- if (preg_match_all(
- '#([\w ]+) \((.*)\) sent a message using the contact form at#i',
- $message_body, $sender)) {
- $this->rewrite($vars, $sender);
- }
+ // See if admin wants to remove all attachments:
+ if ($this->getConfig()->get('delete-attachments')) {
+ // Listen to the mail.processed signal, and simply drop any attachments..
+ // if you wanted to delete all attachments, but didn't want to turn them off
+ // in the admin config for some reason..
+ // Note: Haven't found any signals for piped email..
+ // Really wish there was one before the attachments were downloaded.
+ // apparently not.
+ Signal::connect('mail.processed', function ($mf, &$vars) {
+ $this->log("All Attachments Purged, as instructed.");
+ $vars['attachments'] = array();
+ });
+ } elseif ($this->getConfig()->get('delete-for-departments')) {
+ // Little bit tricker, we need to wait for the thread to be created for the ticket,
+ // check it's department, if known, match it with the admin specified departments
+ // then purge any attachments found.
+ Signal::connect('threadentry.created', function ($entry) {
+ $this->log(
+ "Received threadentry.created signal, told to check for departments.");
+ $this->purgeAttachmentsByDepartment($entry);
+ });
+ }
}
- // See if admin has added any email rewriting rules:
- if ($rules = $this->getConfig()->get('email-rewrite')) {
- $this->rewriteEmail($vars, $rules);
- }
- // See if admin has added any text rewriting rules:
- if ($rules = $this->getConfig()->get('text-rewrite')) {
- $this->rewriteText($vars, $rules);
- }
- // See if admin has added any regex rewriting rules:
- if ($rules = $this->getConfig()->get('regex-rewrite')) {
- $this->rewriteTextRegex($vars, $rules);
- }
- }
-
- private function rewriteForward($vars, $restrict_forwarding_to_these_domains) {
- // Build a fancy regex to match domain names, restricts the people who can forward
- // Will likely break horribly if they put anything but commas in there.
- // TODO: Make admin option simply "the regex"..? could be good.
- // Alternately, it would mean every osTicket admin would have to learn Regular Expressions..
- $regex_of_allowed_domains = '/.+@(' .
- str_replace(',', '|', $restrict_forwarding_to_these_domains) . ')/i';
- if (! preg_match($regex_of_allowed_domains, $vars['email'])) {
- if (self::DEBUG) {
- $this->log("Sender wasn't in list of allowed domains.");
- }
- else {
-
- // Retrieve the text from the ThreadEntryBody, as per v1.10
- $message_body = $vars['message']->getClean();
-
- // Could trim in regex.. but easier to trim here.
- // Only works if the Issue Summary field is a "Short Answer" textbox.. not a choice. :-|
- $subject = trim($vars['subject']);
- if (! $subject) {
- $this->log("Message had no subject, ignoring.");
- return;
- }
-
- // Need to find if the message was forwarded.
- // Check the subject for "Fwd: ", "[Fwd:...]", "... (fwd)" as per http://stackoverflow.com/a/4743303
- // TODO: Combine $subject matches into one regex, the first is more likely though.
- // note the second ?, because Office365 forwards with "Fw: subject".. special.
- if (preg_match('/^\[?Fwd?: /i', $subject) ||
- preg_match('/\(fwd\)$/i', $subject)) {
-
- // We have a forwarded message (according to the subject)
- $this->log("Matched forwarded subject: $subject");
-
- // Have to find the original sender
- // Attempting to find this from the body text:
- // // From: SomeName <username@domain.name>
- // The body will be html gibberish though.. have to decode it before checking
- // if (self::DUMPWHOLETHING)
- // print "Message as parser sees it: \n$message_body\n";
-
-
- // We'll start with the regex check, if it works, we get the name & email in one go:
- if ($sender = $this->optimisticSearch($message_body)) {
- $this->rewrite($vars, $sender);
- }
- else {
- // ok, "simple" mode didn't work.. darn.. (expletives have been deleted)
- // by passing the full $vars['message'] item, we can check the text-version as well.
- $sender = $this->deepSearchForSender($vars['message']);
- if ($sender) {
- $this->rewrite($vars, $sender);
+ /**
+ * Takes an array of variables and checks to see if it matches the normal
+ * "Forwarded Message" attributes.. Need to find the earliest sender combo in
+ * the array. There could be quite a chain Customer email's Dealer Dealer
+ * forwards to Distributor Distributor forwards to Manufacturer Manufacturer
+ * internally forwards to Ticketing system ETC.. We actually want the Customer
+ * one. the First one. Which, in this case, is the LAST one. There is
+ * apparently no RFC for forwarded messages (as per:
+ * http://stackoverflow.com/a/4743303)
+ *
+ * @param array $vars
+ */
+ private function process_ticket(&$vars) {
+ // This only works for email.. Tickets created by admins with manually entered "Fwd" stuff,
+ // get's filtered by redactor or whatever that is called, so it doesn't work there.
+ if (!$vars['message'] instanceof ThreadEntryBody) {
+ if (self::DEBUG)
+ $this->log(
+ "Unable to process ticket, message body wasn't in expected format, this plugin only works for 1.10+. ");
+ return;
+ }
+
+ $restrict_forwarding_to_these_domains = $this->getConfig()->get('domains');
+ // if no domains are specified, we just allow NO domains to forward..
+ if (strlen($restrict_forwarding_to_these_domains)) {
+ $this->rewriteForward($vars, $restrict_forwarding_to_these_domains);
+ }
+
+ // Test for Drupal messages:
+ if ($this->getConfig()->get('drupal') &&
+ preg_match('/sent a message using the contact form at/i', $message_body)) {
+
+ // The message body indicates it could be sent from a Drupal /contact form
+ // Luckily the default is PlainText (for Drupal 7 and lower at least)
+ if (self::DEBUG) {
+ $this->log("Matched Drupal message.");
}
- else {
- // Disaster, it is a forwarded message, yet we can't find the details inside it.
- $this->log(
- "Unable to rewrite $subject, No 'From: {name} <{email}>' found.");
+
+ // Attempt to locate the sender in the first line.
+ // Will fetch the name, then the email which is in (braces)
+ $sender = array();
+ // TODO: Figure out what this would be for different languages?
+ if (preg_match_all(
+ '#([\w ]+) \((.*)\) sent a message using the contact form at#i', $message_body, $sender)) {
+ $this->rewrite($vars, $sender);
}
- }
}
- }
+
+ // See if admin has added any email rewriting rules:
+ if ($rules = $this->getConfig()->get('email-rewrite')) {
+ $this->rewriteEmail($vars, $rules);
+ }
+ // See if admin has added any text rewriting rules:
+ if ($rules = $this->getConfig()->get('text-rewrite')) {
+ $this->rewriteText($vars, $rules);
+ }
+ // See if admin has added any regex rewriting rules:
+ if ($rules = $this->getConfig()->get('regex-rewrite')) {
+ $this->rewriteTextRegex($vars, $rules);
+ }
}
- }
-
- /**
- * This should match the text: From: "Name" <"User@Email"> Which most
- * forwarded messages seem to have, possibly because of
- * https://tools.ietf.org/html/rfc821#page-7 note, names can have almost
- * anything.. "James O'Brian" etc.. strip_tags should leave it with a line
- * like: "From: Name sender@domain.com>" we need to match the word "From:",
- * anything (with spaces around it) followed by something with an @ symbol
- * between it and the string ">" Those two things are what we need to
- * rewrite with. Except fucking gmail.. of course: From: Name <name@domain.com> From: Sender Name name@domain.com> wtf is that regex? Where is my will to
- * live? Whyyyy also, how the fuck did I write that? check out regexr.com and
- * play till you get it working.. many complicated! why don't we just match
- * the email address, fuck the name!
- *
- * @param string $message_body
- * @return array|boolean
- */
- private function optimisticSearch($message_body) {
- $sender = array();
- if (preg_match_all(
- '/From:(.*)(?: |<|;|>)([\w\d_\-\.]+@[\w\d_\-\.]+)(?:&|>| )/i',
- $matchable_body, $sender)) {
- if (self::DUMPWHOLETHING) {
- print "Found sender using optimisticSearch: " . print_r($sender, true);
- }
- return $sender;
+
+ /**
+ * Idea is to remove the extraneous details of a message that is included before the
+ * reply separator for some reason.
+ *
+ * @param ThreadEntry $entry
+ */
+ private function stripMetadata(ThreadEntry $entry) {
+ if (!$entry instanceof MessageThreadEntry) {
+ return; // don't need to strip from any other entry types
+ }
+ $body = $entry->getBody();
+ $text = $body->getClean();
+
+ // Break the text into manageable chunks:
+ $searchable = array();
+ if ($body instanceof HtmlThreadEntryBody) {
+ // ok, fine, split by
+ $packer = "
";
+ $searchable = explode($packer, str_replace('
', $packer, $text));
+ } else {
+ // Text can be split on newlines.
+ $packer = "\n";
+ $searchable = explode($packer, $text);
+ }
+ // Could search for a date, or every email address that can send emails.. hmm
+ foreach (array_reverse($searchable) as $idx => $line) {
+ //TODO: Get an international version of matching regex..
+ if (preg_match('/On.+wrote:/i', $line)) {
+ // drop everything from len-idx+1 & repack back where we found it:
+ $body->body = implode($packer, array_slice($searchable, 0, count($searchable) - ++$idx));
+ $entry->setBody($body);
+ return;
+ }
+ }
}
- return FALSE;
- }
-
- /**
- * Uses advanced technique known as Brute Force to locate the original sender.
- * We convert the HTML of the message into a DOMDocument, then iterate through
- * all the nodes that make it up. In each of the nodes, we search the text of
- * the node looking for email addresses, because, From: Name
- * will appear at some point as a piece of text. When
- * we've found the email address, we look through the lines that make up that
- * node's text and find the From: part, looking backwards. When we find the
- * From: line, we trim that off, and trim off the email address, and we're
- * just left with the name.
- *
- * @param unknown $html
- * @return boolean|string[][]
- */
- private function deepSearchForSender($html) {
- $name = $email = '';
-
- // because the $vars['message'] is actually different to $vars['message']->getClean()
- // we should try the optmitistic search again.
- if ($sender = $this->optimisticSearch($html)) {
- return $sender;
+
+ private function rewriteForward($vars, $restrict_forwarding_to_these_domains) {
+// Build a fancy regex to match domain names, restricts the people who can forward
+// Will likely break horribly if they put anything but commas in there.
+// TODO: Make admin option simply "the regex"..? could be good.
+// Alternately, it would mean every osTicket admin would have to learn Regular Expressions..
+ $regex_of_allowed_domains = '/.+@(' .
+ str_replace(',', '|', $restrict_forwarding_to_these_domains) . ')/i';
+ if (!preg_match($regex_of_allowed_domains, $vars['email'])) {
+ if (self::DEBUG) {
+ $this->log("Sender wasn't in list of allowed domains.");
+ } else {
+
+// Retrieve the text from the ThreadEntryBody, as per v1.10
+ $message_body = $vars['message']->getClean();
+
+// Could trim in regex.. but easier to trim here.
+// Only works if the Issue Summary field is a "Short Answer" textbox.. not a choice. :-|
+ $subject = trim($vars['subject']);
+ if (!$subject) {
+ $this->log("Message had no subject, ignoring.");
+ return;
+ }
+
+// Need to find if the message was forwarded.
+// Check the subject for "Fwd: ", "[Fwd:...]", "... (fwd)" as per http://stackoverflow.com/a/4743303
+// TODO: Combine $subject matches into one regex, the first is more likely though.
+// note the second ?, because Office365 forwards with "Fw: subject".. special.
+ if (preg_match('/^\[?Fwd?: /i', $subject) ||
+ preg_match('/\(fwd\)$/i', $subject)) {
+
+ // We have a forwarded message (according to the subject)
+ $this->log("Matched forwarded subject: $subject");
+
+ // Have to find the original sender
+ // Attempting to find this from the body text:
+ // // From: SomeName <username@domain.name>
+ // The body will be html gibberish though.. have to decode it before checking
+ // if (self::DUMPWHOLETHING)
+ // print "Message as parser sees it: \n$message_body\n";
+ // We'll start with the regex check, if it works, we get the name & email in one go:
+ if ($sender = $this->optimisticSearch($message_body)) {
+ $this->rewrite($vars, $sender);
+ } else {
+ // ok, "simple" mode didn't work.. darn.. (expletives have been deleted)
+ // by passing the full $vars['message'] item, we can check the text-version as well.
+ $sender = $this->deepSearchForSender($vars['message']);
+ if ($sender) {
+ $this->rewrite($vars, $sender);
+ } else {
+ // Disaster, it is a forwarded message, yet we can't find the details inside it.
+ $this->log(
+ "Unable to rewrite $subject, No 'From: {name} <{email}>' found.");
+ }
+ }
+ }
+ }
+ }
}
- // no dice?
- // ok
- // Let's try loading the message into a DOMDocument, and finding the From text, then an adjacent email address.. right?
- // I mean, how hard can it be. .. famous last words.
- libxml_use_internal_errors(TRUE); // ignore libxml parser errors
- $dom = new DOMDocument();
- @$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED); // don't automatically add or tags if absent.
- foreach ($dom->getElementsByTagName('*') as $node) { // iterate over the document's DOMNodeList
- if (self::DUMPWHOLETHING)
- print "DS: Checking node with text: " . $node->nodeValue . "\n";
-
- // Find any email addresses.. From: Name should SHOULD be fairly near the top
- $possibles = $this->findEmailAddresses($node->nodeValue);
-
- // Depending on how many email addresses we found in that block, it could be the bit we're after!
- if (count($possibles) > 0) {
-
- // let's go for broke, ANY addresses in that block is likely to be us.
- $lines = explode(PHP_EOL, $node->nodeValue);
-
- // Go over each email address, check each line of text that we found the addresses in:
- foreach ($possibles as $email) {
- foreach ($lines as $line) {
+
+ /**
+ * This should match the text: From: "Name" <"User@Email"> Which most
+ * forwarded messages seem to have, possibly because of
+ * https://tools.ietf.org/html/rfc821#page-7 note, names can have almost
+ * anything.. "James O'Brian" etc.. strip_tags should leave it with a line
+ * like: "From: Name sender@domain.com>" we need to match the word "From:",
+ * anything (with spaces around it) followed by something with an @ symbol
+ * between it and the string ">" Those two things are what we need to
+ * rewrite with. Except fucking gmail.. of course: From: Name <name@domain.com> From: Sender Name name@domain.com> wtf is that regex? Where is my will to
+ * live? Whyyyy also, how the fuck did I write that? check out regexr.com and
+ * play till you get it working.. many complicated! why don't we just match
+ * the email address, fuck the name!
+ *
+ * @param string $message_body
+ * @return array|boolean
+ */
+ private function optimisticSearch($message_body) {
+ $sender = array();
+ if (preg_match_all(
+ '/From:(.*)(?: |<|;|>)([\w\d_\-\.]+@[\w\d_\-\.]+)(?:&|>| )/i', $matchable_body, $sender)) {
+ if (self::DUMPWHOLETHING) {
+ print "Found sender using optimisticSearch: " . print_r($sender, true);
+ }
+ return $sender;
+ }
+ return FALSE;
+ }
+
+ /**
+ * Uses advanced technique known as Brute Force to locate the original sender.
+ * We convert the HTML of the message into a DOMDocument, then iterate through
+ * all the nodes that make it up. In each of the nodes, we search the text of
+ * the node looking for email addresses, because, From: Name
+ * will appear at some point as a piece of text. When
+ * we've found the email address, we look through the lines that make up that
+ * node's text and find the From: part, looking backwards. When we find the
+ * From: line, we trim that off, and trim off the email address, and we're
+ * just left with the name.
+ *
+ * @param unknown $html
+ * @return boolean|string[][]
+ */
+ private function deepSearchForSender($html) {
+ $name = $email = '';
+
+// because the $vars['message'] is actually different to $vars['message']->getClean()
+// we should try the optmitistic search again.
+ if ($sender = $this->optimisticSearch($html)) {
+ return $sender;
+ }
+// no dice?
+// ok
+// Let's try loading the message into a DOMDocument, and finding the From text, then an adjacent email address.. right?
+// I mean, how hard can it be. .. famous last words.
+ libxml_use_internal_errors(TRUE); // ignore libxml parser errors
+ $dom = new DOMDocument();
+ @$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED); // don't automatically add or tags if absent.
+ foreach ($dom->getElementsByTagName('*') as $node) { // iterate over the document's DOMNodeList
if (self::DUMPWHOLETHING)
- print "DS: Looking for $email in line: $line\n";
- // Let's find the "From: " bit in that line that has the email address, then call the line a winner.
- if (stripos($line, 'From:') !== FALSE &&
- stripos($line, $email) !== FALSE) {
- if (self::DUMPWHOLETHING) {
- print "DS: Found match for /From:.*$email/ \n"; // pretty sure two stripos's is faster than preg_match.. dunno
- }
- // Success, this line has the text we want.
- // Need the text after From as the sender, and we already know the address.
- $name = str_replace(
- array(
- '<',
- '>'
- ), '', strip_tags($line)); // is strip_tags what we want?
- $name = str_replace('From:', '', $name); // remove From: from the line
- $name = str_replace($email, '', $name); // remove the email address from the line
+ print "DS: Checking node with text: " . $node->nodeValue . "\n";
+
+// Find any email addresses.. From: Name should SHOULD be fairly near the top
+ $possibles = $this->findEmailAddresses($node->nodeValue);
+
+// Depending on how many email addresses we found in that block, it could be the bit we're after!
+ if (count($possibles) > 0) {
+
+// let's go for broke, ANY addresses in that block is likely to be us.
+ $lines = explode(PHP_EOL, $node->nodeValue);
+
+// Go over each email address, check each line of text that we found the addresses in:
+ foreach ($possibles as $email) {
+ foreach ($lines as $line) {
+ if (self::DUMPWHOLETHING)
+ print "DS: Looking for $email in line: $line\n";
+ // Let's find the "From: " bit in that line that has the email address, then call the line a winner.
+ if (stripos($line, 'From:') !== FALSE &&
+ stripos($line, $email) !== FALSE) {
+ if (self::DUMPWHOLETHING) {
+ print "DS: Found match for /From:.*$email/ \n"; // pretty sure two stripos's is faster than preg_match.. dunno
+ }
+ // Success, this line has the text we want.
+ // Need the text after From as the sender, and we already know the address.
+ $name = str_replace(
+ array(
+ '<',
+ '>'
+ ), '', strip_tags($line)); // is strip_tags what we want?
+ $name = str_replace('From:', '', $name); // remove From: from the line
+ $name = str_replace($email, '', $name); // remove the email address from the line
+
+
+ if (self::DUMPWHOLETHING)
+ print "Found our guy? name: $name with email: $email\n";
+
+ // Skip back up the three foreach's
+ break 3;
+ }
+ elseif (self::DUMPWHOLETHING) {
+ print "DS: DID NOT MATCH LINE: $line\n";
+ }
+ }
+ }
+ }
+ }
+ if (!$email) {
+// we can always pull the first half of the email as the name, but without the email, nothing doin.
+ return FALSE;
+ }
- if (self::DUMPWHOLETHING)
- print "Found our guy? name: $name with email: $email\n";
+// recreate the structure of the output of preg_match_all
+// $matches[0][..] == 'Pattern matches, not the capture groups.. so, skip this'
+// $matches[1][..] == 'Names'
+// $matches[2][..] == 'Email addresses'
+ $sender = array(
+ array(),
+ array(
+ trim($name)
+ ),
+ array(
+ trim($email)
+ )
+ );
+ if (self::DUMPWHOLETHING)
+ print "Found sender in deepSearch: " . print_r($sender, true);
+
+ return $sender;
+ }
+
+ /**
+ * Finds any email addresses in a piece of text, Returns an array of those
+ * addresses.
+ *
+ * @see https://stackoverflow.com/a/3901303
+ * @see https://stackoverflow.com/a/8131211
+ *
+ *
+ * @param string $text
+ * @return mixed
+ */
+ private function findEmailAddresses($text) {
+ $matches = array();
+ $matches[0] = array();
+
+// this regex handles more email address formats like a+b@google.com.sg
+// calm your tits email: https://en.wikipedia.org/wiki/Email_address#Examples
+// wow.
+ $pattern = "/(?:[A-Za-z0-9!#$%&'*+=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[A-Za-z0-9-]*[A-Za-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/";
+
+// fill $matches with email addresses found in $text
+ preg_match_all($pattern, $text, $matches);
+
+ return $matches[0];
+ }
+
+ /**
+ * A little more powerful.. It's assumed you know what you're doing when you
+ * write a regex. Let's get creative.
+ *
+ * @param array $vars
+ * @param array $rules
+ */
+ private function rewriteTextRegex($vars, $rules) {
+ $needles = $replacements = array();
+
+ foreach (explode(PHP_EOL, $rules) as $rule) {
+ list ($find, $replace) = explode(':', $rule);
+ if (!$find) {
+// skip blank patterns.
+ continue;
+ }
- // Skip back up the three foreach's
- break 3;
+ $replace = $replace ?: ''; // Replace things with nothing if no replacement string.
+// validate pattern before run
+ if (!@preg_match($find, null) === false) {
+ $this->log("Pattern $find wasn't a valid regex.");
+ continue;
}
- elseif (self::DUMPWHOLETHING) {
- print "DS: DID NOT MATCH LINE: $line\n";
+
+ $needles[] = $find;
+ $replacements[] = $replace;
+ }
+ if (self::DUMPWHOLETHING) {
+ $this->log(
+ "Going to get brutal with regex against the ticket.. hold onto your hat!");
+ print_r($needles);
+ print_r($replacements);
+ }
+
+ foreach ($vars as $key => $val) {
+ if ($val instanceof ThreadEntryBody) {
+// ie: $vars['message']
+// This will work regardless of the type, ie: Text/Html
+ $new_val = preg_replace($needles, $replacements, (string) $val->body);
+// preg_replace error value is null, so if we don't have an error, assume it worked:
+ $vars[$key]->body = $new_val ?: $val->body;
+ } elseif (is_string($val)) {
+// we can work with text:
+ $new_val = preg_replace($needles, $replacements, $val);
+ $vars[$key] = $new_val ?: $val;
}
- }
+// TODO: Decide how deep the rabbit hole we want to go..
+// attachments/recipients/etc are in a sub array
}
- }
}
- if (! $email) {
- // we can always pull the first half of the email as the name, but without the email, nothing doin.
- return FALSE;
- }
+ /**
+ * Rewrite Text things, like, the subject/body Simple find & replace
+ * implementation.
+ *
+ * @param array $vars
+ * (the values osTicket constructed)
+ * @param string $rules
+ * (the find:replace pairs admin entered, \n seperating each rule)
+ */
+ private function rewriteText(&$vars, &$rules) {
+ foreach (explode(PHP_EOL, $rules) as $rule) {
+ list ($find, $replace) = explode(':', $rule); // PHP 5/7 inverts the order of applying this.. FFS, why?
- // recreate the structure of the output of preg_match_all
- // $matches[0][..] == 'Pattern matches, not the capture groups.. so, skip this'
- // $matches[1][..] == 'Names'
- // $matches[2][..] == 'Email addresses'
- $sender = array(
- array(),
- array(
- trim($name)
- ),
- array(
- trim($email)
- )
- );
- if (self::DUMPWHOLETHING)
- print "Found sender in deepSearch: " . print_r($sender, true);
-
- return $sender;
- }
-
- /**
- * Finds any email addresses in a piece of text, Returns an array of those
- * addresses.
- *
- * @see https://stackoverflow.com/a/3901303
- * @see https://stackoverflow.com/a/8131211
- *
- *
- * @param string $text
- * @return mixed
- */
- private function findEmailAddresses($text) {
- $matches = array();
- $matches[0] = array();
-
- // this regex handles more email address formats like a+b@google.com.sg
- // calm your tits email: https://en.wikipedia.org/wiki/Email_address#Examples
- // wow.
- $pattern = "/(?:[A-Za-z0-9!#$%&'*+=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*\")@(?:(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[A-Za-z0-9-]*[A-Za-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/";
-
- // fill $matches with email addresses found in $text
- preg_match_all($pattern, $text, $matches);
-
- return $matches[0];
- }
-
- /**
- * A little more powerful.. It's assumed you know what you're doing when you
- * write a regex. Let's get creative.
- *
- * @param array $vars
- * @param array $rules
- */
- private function rewriteTextRegex($vars, $rules) {
- $needles = $replacements = array();
-
- foreach (explode(PHP_EOL, $rules) as $rule) {
- list ($find, $replace) = explode(':', $rule);
- if (! $find) {
- // skip blank patterns.
- continue;
- }
-
- $replace = $replace ?: ''; // Replace things with nothing if no replacement string.
-
-
- // validate pattern before run
- if (! @preg_match($find, null) === false) {
- $this->log("Pattern $find wasn't a valid regex.");
- continue;
- }
-
- $needles[] = $find;
- $replacements[] = $replace;
- }
- if (self::DUMPWHOLETHING) {
- $this->log(
- "Going to get brutal with regex against the ticket.. hold onto your hat!");
- print_r($needles);
- print_r($replacements);
- }
- foreach ($vars as $key => $val) {
- if ($val instanceof ThreadEntryBody) {
- // ie: $vars['message']
- // This will work regardless of the type, ie: Text/Html
- $new_val = preg_replace($needles, $replacements, (string) $val->body);
- // preg_replace error value is null, so if we don't have an error, assume it worked:
- $vars[$key]->body = $new_val ?: $val->body;
- }
- elseif (is_string($val)) {
- // we can work with text:
- $new_val = preg_replace($needles, $replacements, $val);
- $vars[$key] = $new_val ?: $val;
- }
- // TODO: Decide how deep the rabbit hole we want to go..
- // attachments/recipients/etc are in a sub array
- }
- }
-
- /**
- * Rewrite Text things, like, the subject/body Simple find & replace
- * implementation.
- *
- * @param array $vars
- * (the values osTicket constructed)
- * @param string $rules
- * (the find:replace pairs admin entered, \n seperating each rule)
- */
- private function rewriteText(&$vars, &$rules) {
- foreach (explode(PHP_EOL, $rules) as $rule) {
- list ($find, $replace) = explode(':', $rule); // PHP 5/7 inverts the order of applying this.. FFS, why?
-
-
- if (! $find)
- continue;
-
- if (self::DEBUG)
- $this->log(
- "Using $find => $replace text rule on ticket with subject $subject\n");
-
- if ($vars['message'] instanceof ThreadEntryBody &&
- stripos($vars['message']->body, $find) !== FALSE) {
- $vars['message']->body = str_ireplace($find, $replace,
- (string) $vars['message']->body);
- }
- if (stripos($vars['subject'], $find) !== FALSE) {
- $vars['subject'] = str_ireplace($find, $replace, $vars['subject']);
- }
- }
- }
+ if (!$find)
+ continue;
- private function rewriteEmail(&$vars, &$rules) {
- foreach (explode(PHP_EOL, $rules) as $rule) {
- list ($find, $replace) = explode(':', $rule); // PHP 5/7 inverts the order of applying this.. FFS, why?
+ if (self::DEBUG)
+ $this->log(
+ "Using $find => $replace text rule on ticket with subject $subject\n");
+ if ($vars['message'] instanceof ThreadEntryBody &&
+ stripos($vars['message']->body, $find) !== FALSE) {
+ $vars['message']->body = str_ireplace($find, $replace, (string) $vars['message']->body);
+ }
+ if (stripos($vars['subject'], $find) !== FALSE) {
+ $vars['subject'] = str_ireplace($find, $replace, $vars['subject']);
+ }
+ }
+ }
- if (! $find)
- continue;
+ private function rewriteEmail(&$vars, &$rules) {
+ foreach (explode(PHP_EOL, $rules) as $rule) {
+ list ($find, $replace) = explode(':', $rule); // PHP 5/7 inverts the order of applying this.. FFS, why?
- if (self::DEBUG)
- $this->log(
- "Using $find => $replace email rule on ticket with subject $subject\n");
- {
- if (stripos($vars['email'], $find) !== FALSE) {
- $vars['email'] = str_ireplace($find, $replace, $vars['email']);
+ if (!$find)
+ continue;
+
+ if (self::DEBUG)
+ $this->log(
+ "Using $find => $replace email rule on ticket with subject $subject\n");
+ {
+ if (stripos($vars['email'], $find) !== FALSE) {
+ $vars['email'] = str_ireplace($find, $replace, $vars['email']);
+ }
+ break;
+ }
}
- break;
- }
- }
- }
-
- /**
- * Rewrites the variables for the new ticket Owner The structure we are
- * expecting back from either preg_match_all will be a 2-level array $matches
- * $matches[1][..] == 'Names' $matches[2][..] == 'Email addresses' Now, to
- * find the LAST one.. we look at the end of the array
- *
- * @param array $vars
- * @param array $matches
- * (output from preg_match_all with two capture groups name/email in
- * that order)
- */
- private function rewrite(array &$vars, array $matches) {
- // Check for valid data.
- if (! isset($matches[1][0]) || ! isset($matches[2][0])) {
- if (self::DEBUG)
- error_log(
- "Unable to match with invalid data, check the regex? check the domains? something borked.");
-
- return; // Bail.
}
- // Get the last entry in each array as the proposed "Original Sender" of the first message in the chain.
- $original_name = array_pop($matches[1]);
- $original_email = array_pop($matches[2]);
- $original_name = strip_tags($original_name); // there's a chance we captured some HTML with the name.. strip it.
+ /**
+ * Rewrites the variables for the new ticket Owner The structure we are
+ * expecting back from either preg_match_all will be a 2-level array $matches
+ * $matches[1][..] == 'Names' $matches[2][..] == 'Email addresses' Now, to
+ * find the LAST one.. we look at the end of the array
+ *
+ * @param array $vars
+ * @param array $matches
+ * (output from preg_match_all with two capture groups name/email in
+ * that order)
+ */
+ private function rewrite(array &$vars, array $matches) {
+// Check for valid data.
+ if (!isset($matches[1][0]) || !isset($matches[2][0])) {
+ if (self::DEBUG)
+ error_log(
+ "Unable to match with invalid data, check the regex? check the domains? something borked.");
+
+ return; // Bail.
+ }
+// Get the last entry in each array as the proposed "Original Sender" of the first message in the chain.
+ $original_name = array_pop($matches[1]);
+ $original_email = array_pop($matches[2]);
+ $original_name = strip_tags($original_name); // there's a chance we captured some HTML with the name.. strip it.
+// The current details of the soon-to-be-ticket
+ $current_sender_name = $vars['name'];
+ $current_sender_email = $vars['email']; // We don't validate email because User::fromVars will do it
- // The current details of the soon-to-be-ticket
- $current_sender_name = $vars['name'];
- $current_sender_email = $vars['email']; // We don't validate email because User::fromVars will do it
+ if (self::DUMPWHOLETHING) {
+ print
+ "Going into rewrite with these details:\nOriginal: $current_sender_name <$current_sender_email>\nNew: $original_name <$original_email>\n";
+ }
- if (self::DUMPWHOLETHING) {
- print
- "Going into rewrite with these details:\nOriginal: $current_sender_name <$current_sender_email>\nNew: $original_name <$original_email>\n";
- }
+// Verify that the new email isn't the same as the current one, no point rewriting things if it's the same.
+ if ($original_email == $current_sender_email) {
+ if (self::DEBUG)
+ error_log(
+ "The forwarded message is from the same person, they forwarded to themselves? bailing");
+ return;
+ }
- // Verify that the new email isn't the same as the current one, no point rewriting things if it's the same.
- if ($original_email == $current_sender_email) {
- if (self::DEBUG)
- error_log(
- "The forwarded message is from the same person, they forwarded to themselves? bailing");
- return;
- }
+// All Good? We're ready!
+// Rewrite the ticket variables with the new data
+// Uses osTicket v1.10 semantics
+ $vars['name'] = $original_name;
+ $vars['email'] = $original_email;
- // All Good? We're ready!
- // Rewrite the ticket variables with the new data
- // Uses osTicket v1.10 semantics
- $vars['name'] = $original_name;
- $vars['email'] = $original_email;
-
- $user = User::fromVars(
- array(
- 'name' => $original_name,
- 'email' => $original_email
- ));
- if (self::DUMPWHOLETHING) {
- $this->log(
- "Attempted to make/find user for $original_name and $original_email");
- print_r($user); // DEBUG
- }
- if (! $user instanceof User) {
- // Was denied/spammer?
- // We can't use the $user object if it's not a User!
- // Also fails if Registration (user/pass) is required for users and the new one isn't actually a user.
- $this->log(
- "Unable to rewrite to this User $original_email, as we are unable to make an account for them.");
- // put it back!
- $vars['name'] = $current_sender_name;
- $vars['email'] = $current_sender_email;
- return;
- }
- $vars['uid'] = $user->getId();
- $msg = "Rewrote ticket details: $current_sender_name -> {$original_name}";
- $this->log($msg);
- if (self::DEBUG) {
- print $msg;
- }
- $this->addAdminNote($vars);
- }
-
- private function addAdminNote($vars) {
- // See if admin want's us to add a note about this in the message. (Ticket hasn't been created yet, so can't add an Admin Note to the thread)
- if ($this->getConfig()->get('note')) {
- $admin_note = $this->getConfig()->get('note-text') . "\n\n";
- $vars['message']->prepend($admin_note); // Another reason to test for ThreadEntryBody, we can use it's methods!
- }
- }
-
- /**
- * Tiny function that purges attachments for specified departments only
- *
- * @param ThreadEntry $entry
- */
- private function purgeAttachmentsByDepartment(ThreadEntry &$entry) {
- $departments = $this->getConfig()->get('delete-for-departments');
- $matchable_departments = (strpos($departments, ',') !== FALSE) ?
- // many entered: fill an array with each name
- explode(',', $departments) :
- // one entered: make it an array anyway:
- array(
- $departments
- );
-
- $this->log(
- "Purging attachments for departments: " .
- print_r($matchable_departments, true));
-
- // Get the ticket, to get the department
- $ticket = $this->getTicket($entry);
- if (! $ticket instanceof Ticket) {
- $this->log("Unable to find/get ticket for thread");
- return;
- }
- $ticket_department = $ticket->getDept();
- if (! $ticket_department instanceof Dept) {
- $this->log("Unable to find/get department for thread");
- return;
+ $user = User::fromVars(
+ array(
+ 'name' => $original_name,
+ 'email' => $original_email
+ ));
+ if (self::DUMPWHOLETHING) {
+ $this->log(
+ "Attempted to make/find user for $original_name and $original_email");
+ print_r($user); // DEBUG
+ }
+ if (!$user instanceof User) {
+// Was denied/spammer?
+// We can't use the $user object if it's not a User!
+// Also fails if Registration (user/pass) is required for users and the new one isn't actually a user.
+ $this->log(
+ "Unable to rewrite to this User $original_email, as we are unable to make an account for them.");
+// put it back!
+ $vars['name'] = $current_sender_name;
+ $vars['email'] = $current_sender_email;
+ return;
+ }
+ $vars['uid'] = $user->getId();
+ $msg = "Rewrote ticket details: $current_sender_name -> {$original_name}";
+ $this->log($msg);
+ if (self::DEBUG) {
+ print $msg;
+ }
+ $this->addAdminNote($vars);
}
- $thread = $entry->getThread();
- if (! $thread instanceof Thread) {
- return;
+
+ private function addAdminNote($vars) {
+// See if admin want's us to add a note about this in the message. (Ticket hasn't been created yet, so can't add an Admin Note to the thread)
+ if ($this->getConfig()->get('note')) {
+ $admin_note = $this->getConfig()->get('note-text') . "\n\n";
+ $vars['message']->prepend($admin_note); // Another reason to test for ThreadEntryBody, we can use it's methods!
+ }
}
- // We have enough pieces, let's check the departments the admin specified:
- foreach ($matchable_departments as $d) {
- $this->log("Looking up department: $d");
- if (is_string($d)) {
- $dept_id = Dept::getIdByName($d);
- $dept = Dept::lookup($dept_id);
- }
- else {
- $dept = Dept::lookup($d);
- }
- if (! $dept instanceof Dept) {
- $this->log("ERROR: unable to instantiate $d as department.");
- }
- if (self::DUMPWHOLETHING)
+
+ /**
+ * Tiny function that purges attachments for specified departments only
+ *
+ * @param ThreadEntry $entry
+ */
+ private function purgeAttachmentsByDepartment(ThreadEntry &$entry) {
+ $departments = $this->getConfig()->get('delete-for-departments');
+ $matchable_departments = (strpos($departments, ',') !== FALSE) ?
+ // many entered: fill an array with each name
+ explode(',', $departments) :
+ // one entered: make it an array anyway:
+ array(
+ $departments
+ );
+
$this->log(
- "Checking " . $dept->getName() . ' against . ' .
- $ticket_department->getName());
- if ($dept instanceof Dept && $dept->getId() == $ticket_department->getId()) {
- $this->log("Going to delete the attachments from the thread..");
-
- // Match, let's purge the attachments
- foreach ($entry->getAttachments() as $att) {
- if (! $att instanceof Attachment) {
- $this->log("Error, unable to delete attachment");
- continue;
- }
- $this->log("Deleting file attachment: " . $att->getFileName());
- Attachment::objects()->filter(
- array(
- 'file_id' => $att->getFileId()
- ))
- ->delete();
+ "Purging attachments for departments: " .
+ print_r($matchable_departments, true));
+
+// Get the ticket, to get the department
+ $ticket = $this->getTicket($entry);
+ if (!$ticket instanceof Ticket) {
+ $this->log("Unable to find/get ticket for thread");
+ return;
}
+ $ticket_department = $ticket->getDept();
+ if (!$ticket_department instanceof Dept) {
+ $this->log("Unable to find/get department for thread");
+ return;
+ }
+ $thread = $entry->getThread();
+ if (!$thread instanceof Thread) {
+ return;
+ }
+// We have enough pieces, let's check the departments the admin specified:
+ foreach ($matchable_departments as $d) {
+ $this->log("Looking up department: $d");
+ if (is_string($d)) {
+ $dept_id = Dept::getIdByName($d);
+ $dept = Dept::lookup($dept_id);
+ } else {
+ $dept = Dept::lookup($d);
+ }
+ if (!$dept instanceof Dept) {
+ $this->log("ERROR: unable to instantiate $d as department.");
+ }
+ if (self::DUMPWHOLETHING)
+ $this->log(
+ "Checking " . $dept->getName() . ' against . ' .
+ $ticket_department->getName());
+ if ($dept instanceof Dept && $dept->getId() == $ticket_department->getId()) {
+ $this->log("Going to delete the attachments from the thread..");
+
+// Match, let's purge the attachments
+ foreach ($entry->getAttachments() as $att) {
+ if (!$att instanceof Attachment) {
+ $this->log("Error, unable to delete attachment");
+ continue;
+ }
+ $this->log("Deleting file attachment: " . $att->getFileName());
+ Attachment::objects()->filter(
+ array(
+ 'file_id' => $att->getFileId()
+ ))
+ ->delete();
+ }
+
+// Return early, in case the first matches, no need to instantiate the next Department.
+ return;
+ }
+ }
+ }
- // Return early, in case the first matches, no need to instantiate the next Department.
- return;
- }
+ /**
+ * Fetches a ticket from a ThreadEntry Copied from mentioner plugin! :-)
+ *
+ * @param ThreadEntry $entry
+ * @return Ticket
+ */
+ private static function getTicket(ThreadEntry $entry) {
+ static $ticket;
+ if (!$ticket) {
+// aquire ticket from $entry.. I suspect there is a more efficient way.
+ $ticket_id = Thread::objects()->filter(
+ [
+ 'id' => $entry->getThreadId()
+ ])
+ ->values_flat('object_id')
+ ->first()[0];
+
+// Force lookup rather than use cached data..
+ $ticket = Ticket::lookup(
+ array(
+ 'ticket_id' => $ticket_id
+ ));
+ }
+ return $ticket;
+ }
+
+ /**
+ * Logging function, Ensures we have permission to log before doing so
+ * Attempts to log to the Admin logs, and to the webserver logs if debugging
+ * is enabled.
+ *
+ * @param string $message
+ */
+ private function log($message) {
+ global $ost;
+
+// hmm.. might not be available if bootstrapping isn't finished.
+ if ($ost instanceof osTicket &&
+ (self::DEBUG || $this->getConfig()->get('log')) && $message) {
+ $ost->logDebug("RewritePlugin", $message);
+ }
+ if (self::DEBUG)
+ error_log("osTicket RewritePlugin: $message");
}
- }
-
- /**
- * Fetches a ticket from a ThreadEntry Copied from mentioner plugin! :-)
- *
- * @param ThreadEntry $entry
- * @return Ticket
- */
- private static function getTicket(ThreadEntry $entry) {
- static $ticket;
- if (! $ticket) {
- // aquire ticket from $entry.. I suspect there is a more efficient way.
- $ticket_id = Thread::objects()->filter(
- [
- 'id' => $entry->getThreadId()
- ])
- ->values_flat('object_id')
- ->first()[0];
-
- // Force lookup rather than use cached data..
- $ticket = Ticket::lookup(
- array(
- 'ticket_id' => $ticket_id
- ));
+
+ /**
+ * Required stub.
+ *
+ * {@inheritdoc}
+ *
+ * @see Plugin::uninstall()
+ */
+ function uninstall() {
+ $errors = array();
+// Do we send an email to the admin telling him about the space used by the archive?
+ global $ost;
+ $ost->alertAdmin('Plugin: Rewriter has been uninstalled', "Forwarded messages will now appear from the forwarder, as with normal email.", true);
+
+ parent::uninstall($errors);
}
- return $ticket;
- }
-
- /**
- * Logging function, Ensures we have permission to log before doing so
- * Attempts to log to the Admin logs, and to the webserver logs if debugging
- * is enabled.
- *
- * @param string $message
- */
- private function log($message) {
- global $ost;
-
- // hmm.. might not be available if bootstrapping isn't finished.
- if ($ost instanceof osTicket &&
- (self::DEBUG || $this->getConfig()->get('log')) && $message) {
- $ost->logDebug("RewritePlugin", $message);
+
+ /**
+ * Plugins seem to want this.
+ */
+ public function getForm() {
+ return array();
}
- if (self::DEBUG)
- error_log("osTicket RewritePlugin: $message");
- }
-
- /**
- * Required stub.
- *
- * {@inheritdoc}
- *
- * @see Plugin::uninstall()
- */
- function uninstall() {
- $errors = array();
- // Do we send an email to the admin telling him about the space used by the archive?
- global $ost;
- $ost->alertAdmin('Plugin: Rewriter has been uninstalled',
- "Forwarded messages will now appear from the forwarder, as with normal email.",
- true);
-
- parent::uninstall($errors);
- }
-
- /**
- * Plugins seem to want this.
- */
- public function getForm() {
- return array();
- }
-}
\ No newline at end of file
+
+}
diff --git a/config.php b/config.php
index ea8d552..8bb9227 100644
--- a/config.php
+++ b/config.php
@@ -1,174 +1,182 @@
get('helpdesk_url').. except it's not available yet (in bootstrap cycle I mean)
- return array(
- 'ri' => new SectionBreakField(
- array(
- 'label' => $__('Rewriter Configuration')
- )),
- 'log' => new BooleanField(
- array(
- 'default' => FALSE,
- 'label' => $__('Show rewriting in logs'),
- 'hint' => $__(
- "Enable to aid debugging, logs appear in Admin -> Dashboard -> System Logs")
- )),
- 'domains' => new TextareaField(
- array(
- 'label' => $__('Forward Rewritable Domains'),
- 'placeholder' => $__(
- 'Enter your trusted domain names, ie: company.com.tld'),
- 'hint' => $__(
- "Separate with a comma if more than one required, not email addresses, full domains (the part after @), if empty, Nobody is allowed to forward."),
- 'configuration' => array(
- 'html' => FALSE
- )
- )),
- 'note' => new BooleanField(
- array(
- 'default' => TRUE,
- 'label' => $__('Show rewriting in text'),
- 'hint' => $__('Adds the following note.')
- )),
- 'note-text' => new TextareaField(
- array(
- 'default' => $__(
- 'Ticket modified upon receipt as it was forwarded to us.'),
- 'label' => $__('Note Text'),
- 'hint' => $__('This get\'s prepended to the message body')
- )),
- 'dr' => new SectionBreakField(
- array(
- 'label' => 'Drupal Contact Parser'
- )),
- 'drupal' => new BooleanField(
- array(
- 'default' => TRUE,
- 'label' => $__('Rewrite Drupal Contact Form emails'),
- 'hint' => $__(
- "Drupal sends specific email formats that we can look for.")
- )),
- 'dsf' => new SectionBreakField(
- array(
- 'label' => $__('Attachment Deletion Options')
- )),
- 'delete-attachments' => new BooleanField(
- array(
- 'default' => FALSE,
- 'label' => $__('Delete all attachments'),
- 'hint' => $__('Removes all attachments from all incoming emails.')
- )),
- 'delete-for-departments' => new TextboxField(
- array(
- 'label' => $__('Purge email attachments for a department.'),
- 'default' => FALSE,
- 'hint' => $__(
- "Enter the name of the department or it's ID number to purge incoming email attachments for that department (multiple, seperate with commas).")
- )),
+ /**
+ * Build an Admin settings page.
+ *
+ * {@inheritdoc}
+ *
+ * @see PluginConfig::getOptions()
+ */
+ function getOptions() {
+ list ($__, $_N) = self::translate();
+ // TODO: figure out the domain-name from $cfg->get('helpdesk_url').. except it's not available yet (in bootstrap cycle I mean)
+ return array(
+ 'ri' => new SectionBreakField(
+ array(
+ 'label' => $__('Rewriter Configuration')
+ )),
+ 'log' => new BooleanField(
+ array(
+ 'default' => FALSE,
+ 'label' => $__('Show rewriting in logs'),
+ 'hint' => $__(
+ "Enable to aid debugging, logs appear in Admin -> Dashboard -> System Logs")
+ )),
+ 'domains' => new TextareaField(
+ array(
+ 'label' => $__('Forward Rewritable Domains'),
+ 'placeholder' => $__(
+ 'Enter your trusted domain names, ie: company.com.tld'),
+ 'hint' => $__(
+ "Separate with a comma if more than one required, not email addresses, full domains (the part after @), if empty, Nobody is allowed to forward."),
+ 'configuration' => array(
+ 'html' => FALSE
+ )
+ )),
+ 'note' => new BooleanField(
+ array(
+ 'default' => TRUE,
+ 'label' => $__('Show rewriting in text'),
+ 'hint' => $__('Adds the following note.')
+ )),
+ 'note-text' => new TextareaField(
+ array(
+ 'default' => $__(
+ 'Ticket modified upon receipt as it was forwarded to us.'),
+ 'label' => $__('Note Text'),
+ 'hint' => $__('This get\'s prepended to the message body')
+ )),
+ 'dr' => new SectionBreakField(
+ array(
+ 'label' => 'Drupal Contact Parser'
+ )),
+ 'drupal' => new BooleanField(
+ array(
+ 'default' => TRUE,
+ 'label' => $__('Rewrite Drupal Contact Form emails'),
+ 'hint' => $__(
+ "Drupal sends specific email formats that we can look for.")
+ )),
+ 'dsf' => new SectionBreakField(
+ array(
+ 'label' => $__('Deletion Options')
+ )),
+ 'strip-metadata' => new BooleanField(
+ array(
+ 'default' => FALSE,
+ 'hint' => $__('Cleans up replies to tickets, removes metadata from users messages.'),
+ 'label' => $__('Remove Metadata from replies')
+ )
+ ),
+ 'delete-attachments' => new BooleanField(
+ array(
+ 'default' => FALSE,
+ 'label' => $__('Delete all attachments'),
+ 'hint' => $__('Removes all attachments from all incoming emails.')
+ )),
+ 'delete-for-departments' => new TextboxField(
+ array(
+ 'label' => $__('Purge email attachments for a department.'),
+ 'default' => FALSE,
+ 'hint' => $__(
+ "Enter the name of the department or it's ID number to purge incoming email attachments for that department (multiple, seperate with commas).")
+ )),
+ 'sba' => new SectionBreakField(
+ array(
+ 'label' => $__(
+ 'Find & Replace: one per line, seperate split with : case insensitive'),
+ 'hint' => $__(
+ 'A missing second value indicates delete the match.')
+ )),
+ 'email-rewrite' => new TextareaField(
+ array(
+ 'label' => $__('Arbitrary Rewrite email Addresses'),
+ 'hint' => $__(
+ 'Use find:replace pairs, like: @internal.local:@company.com'),
+ 'configuration' => array(
+ 'html' => FALSE
+ )
+ )),
+ 'text-rewrite' => new TextareaField(
+ array(
+ 'label' => $__('Arbitrary Rewrite on Subject & Message'),
+ 'hint' => $__('Use find:replace pairs'),
+ 'configuration' => array(
+ 'html' => FALSE
+ )
+ )),
+ 'sbr' => new SectionBreakField(
+ array(
+ 'label' => $__('DANGER! DANGER!'),
+ 'hint' => 'http://php.net/manual/en/function.preg-replace.php Learn this!, the $pattern is the value on the left, the $replacement is the value on the right, the $subject is the entire $vars array.'
+ )),
+ 'regex-rewrite' => new TextareaField(
+ array(
+ 'configuration' => array(
+ 'html' => FALSE
+ ),
+ 'label' => $__('DANGERZONE: Regex Rewriter'),
+ 'hint' => $__('Use pattern:replacement one per line')
+ ))
+ );
+ }
- 'sba' => new SectionBreakField(
- array(
- 'label' => $__(
- 'Find & Replace: one per line, seperate split with : case insensitive'),
- 'hint' => $__(
- 'A missing second value indicates delete the match.')
- )),
- 'email-rewrite' => new TextareaField(
- array(
- 'label' => $__('Arbitrary Rewrite email Addresses'),
- 'hint' => $__(
- 'Use find:replace pairs, like: @internal.local:@company.com'),
- 'configuration' => array(
- 'html' => FALSE
- )
- )),
- 'text-rewrite' => new TextareaField(
- array(
- 'label' => $__('Arbitrary Rewrite on Subject & Message'),
- 'hint' => $__('Use find:replace pairs'),
- 'configuration' => array(
- 'html' => FALSE
- )
- )),
- 'sbr' => new SectionBreakField(
- array(
- 'label' => $__('DANGER! DANGER!'),
- 'hint' => 'http://php.net/manual/en/function.preg-replace.php Learn this!, the $pattern is the value on the left, the $replacement is the value on the right, the $subject is the entire $vars array.'
- )),
- 'regex-rewrite' => new TextareaField(
- array(
- 'configuration' => array(
- 'html' => FALSE
- ),
- 'label' => $__('DANGERZONE: Regex Rewriter'),
- 'hint' => $__('Use pattern:replacement one per line')
- ))
- );
- }
-}
\ No newline at end of file
+}