Pastebin launched a little side project called HostCabi.net, check it out ;-)Don't like ads? PRO users don't see any ads ;-)
Guest

TimmyDude

By: a guest on Apr 14th, 2008  |  syntax: Java  |  size: 10.10 KB  |  hits: 325  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. //
  2.  
  3. // GCALDaemon is an OS-independent Java program that offers two-way
  4.  
  5. // synchronization between Google Calendar and various iCalalendar (RFC 2445)
  6.  
  7. // compatible calendar applications (Sunbird, Rainlendar, iCal, Lightning, etc).
  8.  
  9. //
  10.  
  11. // Apache License
  12.  
  13. // Version 2.0, January 2004
  14.  
  15. // http://www.apache.org/licenses/
  16.  
  17. //
  18.  
  19. // Project home:
  20.  
  21. // http://gcaldaemon.sourceforge.net
  22.  
  23. //
  24.  
  25. package org.gcaldaemon.core.mailterm;
  26.  
  27.  
  28.  
  29. import java.io.File;
  30.  
  31. import java.nio.charset.Charset;
  32.  
  33. import java.util.LinkedList;
  34.  
  35. import java.util.Set;
  36.  
  37. import java.util.SortedMap;
  38.  
  39.  
  40.  
  41. import org.apache.commons.logging.Log;
  42.  
  43. import org.apache.commons.logging.LogFactory;
  44.  
  45. import org.gcaldaemon.core.Configurator;
  46.  
  47. import org.gcaldaemon.core.FilterMask;
  48.  
  49. import org.gcaldaemon.core.GmailEntry;
  50.  
  51. import org.gcaldaemon.core.GmailMessage;
  52.  
  53. import org.gcaldaemon.core.GmailPool;
  54.  
  55. import org.gcaldaemon.core.StringUtils;
  56.  
  57. import org.gcaldaemon.logger.QuickWriter;
  58.  
  59.  
  60.  
  61. import com.google.gdata.data.HtmlTextConstruct;
  62.  
  63.  
  64.  
  65. /**
  66.  
  67.  * Gmail-based command line interface.
  68.  
  69.  *
  70.  
  71.  * Created: Jan 03, 2007 12:50:56 PM
  72.  
  73.  *
  74.  
  75.  * @author Andras Berkes
  76.  
  77.  */
  78.  
  79. public final class MailTerminal extends Thread {
  80.  
  81.  
  82.  
  83.         // --- CONSTANTS ---
  84.  
  85.  
  86.  
  87.         private static final String QUIT_COMMAND = "quit";
  88.  
  89.  
  90.  
  91.         private static final byte COMMAND_NOT_FOUND = 0;
  92.  
  93.         private static final byte COMMAND_EXECUTED = 1;
  94.  
  95.         private static final byte QUIT_REQUESTED = 2;
  96.  
  97.  
  98.  
  99.         private static final long FAST_POLLING_TIMEOUT = 60000L;
  100.  
  101.         private static final long SCRIPT_TIMEOUT = 30000L;
  102.  
  103.  
  104.  
  105.         // --- LOGGER ---
  106.  
  107.  
  108.  
  109.         private static final Log log = LogFactory.getLog(MailTerminal.class);
  110.  
  111.  
  112.  
  113.         // --- VARIABLES ---
  114.  
  115.  
  116.  
  117.         private final Configurator configurator;
  118.  
  119.         private final long pollingTimeout;
  120.  
  121.         private final String username;
  122.  
  123.         private final String password;
  124.  
  125.         private final String subject;
  126.  
  127.         private final String encoding;
  128.  
  129.         private final File scriptDir;
  130.  
  131.  
  132.  
  133.         private final FilterMask[] addresses;
  134.  
  135.  
  136.  
  137.         // --- CONSTRUCTOR ---
  138.  
  139.  
  140.  
  141.         public MailTerminal(ThreadGroup mainGroup, Configurator configurator)
  142.  
  143.                         throws Exception {
  144.  
  145.                 super(mainGroup, "Mail terminal");
  146.  
  147.                 this.configurator = configurator;
  148.  
  149.  
  150.  
  151.                 // Get inbox polling time
  152.  
  153.                 long timeout = configurator.getConfigProperty(
  154.  
  155.                                 Configurator.MAILTERM_POLLING_GOOGLE, 10000L);
  156.  
  157.                 if (timeout < 60000L) {
  158.  
  159.                         log.warn("The fastest Gmail inbox polling period is '1 min'!");
  160.  
  161.                         timeout = 60000L;
  162.  
  163.                 }
  164.  
  165.                 pollingTimeout = timeout;
  166.  
  167.  
  168.  
  169.                 // Get Gmail user
  170.  
  171.                 username = configurator.getConfigProperty(
  172.  
  173.                                 Configurator.MAILTERM_GOOGLE_USERNAME, null);
  174.  
  175.                 if (username == null) {
  176.  
  177.                         throw new NullPointerException("Missing username ("
  178.  
  179.                                         + Configurator.MAILTERM_GOOGLE_USERNAME + ")!");
  180.  
  181.                 }
  182.  
  183.  
  184.  
  185.                 // Get Gmail password
  186.  
  187.                 password = configurator
  188.  
  189.                                 .getPasswordProperty(Configurator.MAILTERM_GOOGLE_PASSWORD);
  190.  
  191.  
  192.  
  193.                 // Get subject of the command mails
  194.  
  195.                 subject = configurator
  196.  
  197.                                 .getPasswordProperty(Configurator.MAILTERM_MAIL_SUBJECT);
  198.  
  199.  
  200.  
  201.                 // Get script directory
  202.  
  203.                 String path = configurator.getConfigProperty(
  204.  
  205.                                 Configurator.MAILTERM_DIR_PATH, "/scripts");
  206.  
  207.                 scriptDir = new File(path);
  208.  
  209.                 if (!scriptDir.isDirectory()) {
  210.  
  211.                         scriptDir.mkdirs();
  212.  
  213.                         if (!scriptDir.isDirectory()) {
  214.  
  215.                                 throw new Exception("Unable to read script directory (" + path
  216.  
  217.                                                 + ")! Permission denied!");
  218.  
  219.                         }
  220.  
  221.                 }
  222.  
  223.  
  224.  
  225.                 // Get native console encoding
  226.  
  227.                 String consoleEncoding = configurator.getConfigProperty(
  228.  
  229.                                 Configurator.MAILTERM_CONSOLE_ENCODING, StringUtils.US_ASCII);
  230.  
  231.                 try {
  232.  
  233.                         StringUtils.US_ASCII.getBytes(consoleEncoding);
  234.  
  235.                 } catch (Exception unsupportedEncoding) {
  236.  
  237.  
  238.  
  239.                         // Dump supported encodings
  240.  
  241.                         SortedMap map = Charset.availableCharsets();
  242.  
  243.                         if (map != null) {
  244.  
  245.                                 Set set = map.keySet();
  246.  
  247.                                 if (set != null) {
  248.  
  249.                                         String[] array = new String[set.size()];
  250.  
  251.                                         set.toArray(array);
  252.  
  253.                                         QuickWriter writer = new QuickWriter();
  254.  
  255.                                         writer.write("Invalid charset (");
  256.  
  257.                                         writer.write(consoleEncoding);
  258.  
  259.                                         writer.write(")! Supported console encodings:\r\n");
  260.  
  261.                                         for (int i = 0; i < array.length; i++) {
  262.  
  263.                                                 writer.write(array[i]);
  264.  
  265.                                                 if (i < array.length - 1) {
  266.  
  267.                                                         writer.write(", ");
  268.  
  269.                                                 }
  270.  
  271.                                                 if (i % 6 == 5) {
  272.  
  273.                                                         writer.write("\r\n");
  274.  
  275.                                                 }
  276.  
  277.                                         }
  278.  
  279.                                         log.warn(writer.toString().trim());
  280.  
  281.                                 }
  282.  
  283.                         }
  284.  
  285.                         consoleEncoding = StringUtils.US_ASCII;
  286.  
  287.                 }
  288.  
  289.                 encoding = consoleEncoding;
  290.  
  291.  
  292.  
  293.                 // Get acceptable e-mail addresses
  294.  
  295.                 addresses = configurator.getFilterProperty(
  296.  
  297.                                 Configurator.MAILTERM_ALLOWED_ADDRESSES, true);
  298.  
  299.  
  300.  
  301.                 // Start listener
  302.  
  303.                 log.info("Mailterm service started successfully.");
  304.  
  305.                 start();
  306.  
  307.         }
  308.  
  309.  
  310.  
  311.         // --- DIRECTORY LISTENER LOOP ---
  312.  
  313.  
  314.  
  315.         public final void run() {
  316.  
  317.                 try {
  318.  
  319.                         sleep(5000L);
  320.  
  321.                 } catch (InterruptedException interrupt) {
  322.  
  323.                         log.info("Mailterm service stopped.");
  324.  
  325.                         return;
  326.  
  327.                 }
  328.  
  329.                 for (;;) {
  330.  
  331.                         try {
  332.  
  333.  
  334.  
  335.                                 // Borrow pooled Gmail connection
  336.  
  337.                                 GmailPool pool = configurator.getGmailPool();
  338.  
  339.                                 byte responseType = COMMAND_NOT_FOUND;
  340.  
  341.                                 GmailEntry entry = null;
  342.  
  343.                                 try {
  344.  
  345.                                         entry = pool.borrow(username, password);
  346.  
  347.  
  348.  
  349.                                         // Receive mails
  350.  
  351.                                         responseType = receiveMails(entry);
  352.  
  353.                                 } finally {
  354.  
  355.  
  356.  
  357.                                         // Recycle pooled connection
  358.  
  359.                                         pool.recycle(entry);
  360.  
  361.                                 }
  362.  
  363.  
  364.  
  365.                                 // Shutdown mailterm
  366.  
  367.                                 if (responseType == QUIT_REQUESTED) {
  368.  
  369.                                         throw new InterruptedException();
  370.  
  371.                                 }
  372.  
  373.  
  374.  
  375.                                 // Wait
  376.  
  377.                                 if (responseType == COMMAND_NOT_FOUND) {
  378.  
  379.                                         sleep(pollingTimeout);
  380.  
  381.                                 } else {
  382.  
  383.                                         sleep(FAST_POLLING_TIMEOUT);
  384.  
  385.                                 }
  386.  
  387.  
  388.  
  389.                         } catch (InterruptedException interrupt) {
  390.  
  391.                                 log.info("Mailterm service stopped.");
  392.  
  393.                                 return;
  394.  
  395.                         } catch (Exception poolException) {
  396.  
  397.                                 log.warn("Unexpected mailterm error!", poolException);
  398.  
  399.                                 log
  400.  
  401.                                                 .debug("Please verify your username/password and IMAP settings!");
  402.  
  403.                                 try {
  404.  
  405.                                         sleep(pollingTimeout);
  406.  
  407.                                 } catch (InterruptedException interrupt) {
  408.  
  409.                                         log.info("Mailterm service stopped.");
  410.  
  411.                                         return;
  412.  
  413.                                 }
  414.  
  415.                         }
  416.  
  417.                 }
  418.  
  419.         }
  420.  
  421.  
  422.  
  423.         // --- MAIL RECEIVER ---
  424.  
  425.  
  426.  
  427.         private final byte receiveMails(GmailEntry client) throws Exception {
  428.  
  429.  
  430.  
  431.                 // Find new mails
  432.  
  433.                 log.debug("Searching commands in mailbox...");
  434.  
  435.                 GmailMessage[] unreadMails = client.receive(subject);
  436.  
  437.                 if (unreadMails == null || unreadMails.length == 0) {
  438.  
  439.                         log.debug("Mailbox is empty or subject not found.");
  440.  
  441.                         return COMMAND_NOT_FOUND;
  442.  
  443.                 }
  444.  
  445.  
  446.  
  447.                 // Read mails
  448.  
  449.                 byte responseType = COMMAND_NOT_FOUND;
  450.  
  451.                 GmailMessage message;
  452.  
  453.                 for (int i = 0; i < unreadMails.length; i++) {
  454.  
  455.                         message = unreadMails[i];
  456.  
  457.  
  458.  
  459.                         // Get reply address
  460.  
  461.                         String replyAddress = message.from;
  462.  
  463.  
  464.  
  465.                         // Check access by reply address
  466.  
  467.                         if (addresses != null) {
  468.  
  469.                                 if (!isAddressMatch(replyAddress)) {
  470.  
  471.                                         log.warn("Request refused, forbidden e-mail address ("
  472.  
  473.                                                         + replyAddress + ")!");
  474.  
  475.                                         continue;
  476.  
  477.                                 }
  478.  
  479.                         }
  480.  
  481.  
  482.  
  483.                         // Get command
  484.  
  485.                         String command = message.memo;
  486.  
  487.                         if (command == null) {
  488.  
  489.                                 log.debug("Missing command body!");
  490.  
  491.                                 continue;
  492.  
  493.                         }
  494.  
  495.                         HtmlTextConstruct html = new HtmlTextConstruct(command);
  496.  
  497.                         command = html.getPlainText();
  498.  
  499.                         command = command.replace('\r', ' ').replace('\n', ' ').trim();
  500.  
  501.                         if (command.length() == 0) {
  502.  
  503.                                 log.debug("Missing command!");
  504.  
  505.                                 continue;
  506.  
  507.                         }
  508.  
  509.                         log.debug("Executing command from " + replyAddress + " (" + command
  510.  
  511.                                         + ")...");
  512.  
  513.                         String reply;
  514.  
  515.                         if (command.equals(QUIT_COMMAND)) {
  516.  
  517.  
  518.  
  519.                                 // Shutdown requested
  520.  
  521.                                 reply = "Mailterm service terminated. Bye!";
  522.  
  523.                                 responseType = QUIT_REQUESTED;
  524.  
  525.                         } else {
  526.  
  527.  
  528.  
  529.                                 // Parse command
  530.  
  531.                                 String[] args = parseLine(command);
  532.  
  533.  
  534.  
  535.                                 // Execute script
  536.  
  537.                                 ScriptRunner runner = new ScriptRunner(scriptDir, encoding,
  538.  
  539.                                                 args);
  540.  
  541.                                 runner.join(SCRIPT_TIMEOUT);
  542.  
  543.                                 reply = runner.getScriptOutput();
  544.  
  545.                                 if (responseType != QUIT_REQUESTED) {
  546.  
  547.                                         responseType = COMMAND_EXECUTED;
  548.  
  549.                                 }
  550.  
  551.                         }
  552.  
  553.  
  554.  
  555.                         // Send reply
  556.  
  557.                         log.debug("Command output:\r\n" + reply);
  558.  
  559.                         client.send(replyAddress, null, null, "Re:" + subject, "<pre>"
  560.  
  561.                                         + reply.trim() + "</pre>", true);
  562.  
  563.  
  564.  
  565.                         // Wait
  566.  
  567.                         Thread.sleep(500);
  568.  
  569.                 }
  570.  
  571.                 return responseType;
  572.  
  573.         }
  574.  
  575.  
  576.  
  577.         private final boolean isAddressMatch(String string) {
  578.  
  579.                 for (int i = 0; i < addresses.length; i++) {
  580.  
  581.                         if (addresses[i].match(string)) {
  582.  
  583.                                 return true;
  584.  
  585.                         }
  586.  
  587.                 }
  588.  
  589.                 return false;
  590.  
  591.         }
  592.  
  593.  
  594.  
  595.         // --- COMMAND LINE PARSER ---
  596.  
  597.  
  598.  
  599.         /**
  600.  
  601.          * Splitting a string into a command-array.
  602.  
  603.          *
  604.  
  605.          * <BR>
  606.  
  607.          * <BR>
  608.  
  609.          * word1 word2 word3 -> "word1", "word2", "word3" <BR>
  610.  
  611.          * word1 word2="word3 'abc' def" -> "word1", "word2", "word3 'abc' def" <BR>
  612.  
  613.          * 'wo"rd1'="word2" word3 -> "wo\"rd1", "word2", "word3" <BR>
  614.  
  615.          * etc.
  616.  
  617.          *
  618.  
  619.          * @param cmdLine
  620.  
  621.          * @return String[]
  622.  
  623.          */
  624.  
  625.         private static final String[] parseLine(String cmdLine) {
  626.  
  627.                 char delimiter = ' ';
  628.  
  629.                 boolean inToken = false;
  630.  
  631.                 QuickWriter writer = new QuickWriter(100);
  632.  
  633.                 LinkedList tokens = new LinkedList();
  634.  
  635.                 for (int i = 0; i < cmdLine.length(); i++) {
  636.  
  637.                         char c = cmdLine.charAt(i);
  638.  
  639.                         if (inToken) {
  640.  
  641.                                 if (c == delimiter || (delimiter == ' ' && c == '=')) {
  642.  
  643.                                         tokens.add(writer.toString());
  644.  
  645.                                         writer.flush();
  646.  
  647.                                         if (c == '-') {
  648.  
  649.                                                 writer.write(c);
  650.  
  651.                                         }
  652.  
  653.                                         inToken = false;
  654.  
  655.                                         continue;
  656.  
  657.                                 }
  658.  
  659.                                 writer.write(c);
  660.  
  661.                         } else {
  662.  
  663.                                 if (c == '\'') {
  664.  
  665.                                         delimiter = '\'';
  666.  
  667.                                         inToken = true;
  668.  
  669.                                 } else {
  670.  
  671.                                         if (c == '"') {
  672.  
  673.                                                 delimiter = '"';
  674.  
  675.                                                 inToken = true;
  676.  
  677.                                         } else if (c == ' ') {
  678.  
  679.  
  680.  
  681.                                                 // Skip
  682.  
  683.                                         } else {
  684.  
  685.                                                 delimiter = ' ';
  686.  
  687.                                                 writer.write(c);
  688.  
  689.                                                 inToken = true;
  690.  
  691.                                         }
  692.  
  693.                                 }
  694.  
  695.                         }
  696.  
  697.                         if (i == cmdLine.length() - 1 && writer.length() != 0) {
  698.  
  699.                                 tokens.add(writer.toString());
  700.  
  701.                         }
  702.  
  703.                 }
  704.  
  705.                 String[] array = new String[tokens.size()];
  706.  
  707.                 tokens.toArray(array);
  708.  
  709.                 return array;
  710.  
  711.         }
  712.  
  713.  
  714.  
  715. }