diff --git a/WebCallerID/pom.xml b/WebCallerID/pom.xml index 1c9bc49..affae25 100755 --- a/WebCallerID/pom.xml +++ b/WebCallerID/pom.xml @@ -15,5 +15,15 @@ commons-codec 20041127.091804 + + javax.mail + mail + 1.4.5 + + + com.martiansoftware + jsap + 2.1 + \ No newline at end of file diff --git a/WebCallerID/src/main/java/de/tilman/callerId/CallerIdClient.java b/WebCallerID/src/main/java/de/tilman/callerId/CallerIdClient.java index 34b2217..297ba28 100755 --- a/WebCallerID/src/main/java/de/tilman/callerId/CallerIdClient.java +++ b/WebCallerID/src/main/java/de/tilman/callerId/CallerIdClient.java @@ -7,36 +7,64 @@ import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; +import java.util.Calendar; +import java.util.Properties; + +import javax.mail.Message; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; import org.apache.commons.codec.binary.Base64; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.ConsoleAppender; +import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; +import com.martiansoftware.jsap.JSAP; +import com.martiansoftware.jsap.JSAPException; +import com.martiansoftware.jsap.JSAPResult; +import com.martiansoftware.jsap.Switch; +import com.martiansoftware.jsap.UnflaggedOption; + public class CallerIdClient { private final static Logger log = Logger.getLogger(CallerIdClient.class); + private static final String TEXT_UNKNOWN = "unbekannt"; + private static final String TEXT_MAILPREFIX = "Anruf von "; + String password; + int updateInterval; + JSAPResult config; String cookie = null; - public CallerIdClient(String routerPassword) { - BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%d{ISO8601} - %m%n"))); - this.password = new String(Base64.encodeBase64(routerPassword.getBytes())); + public CallerIdClient(JSAPResult config) { + this.config = config; + this.password = new String(Base64.encodeBase64(config.getString("router password").getBytes())); + this.updateInterval = config.getInt("update interval"); try { + log.info("logging in to Speedport router"); postUrl("https://speedport.ip/index/login.cgi", "Username=" + URLEncoder.encode("admin", "UTF-8") + "&" + "Password=" + password); + + log.info("retrieving call list"); getUrl("https://speedport.ip/auth/hcti_status_telanrl.php?cookie=SessionID_R3," + cookie); + + log.info("logging out"); postUrl("https://speedport.ip/auth/logout.cgi?RequestFile=/pub/top_beenden.php&cookie=SessionID_R3," + cookie, ""); } catch (Exception e) { - e.printStackTrace(); + log.error(e.getMessage(), e); } + + log.info("done"); } private void getUrl(String urlString) throws Exception { - log.info("getUrl(" + urlString + ")"); + log.debug("getUrl(" + urlString + ")"); URL url = new URL(urlString); URLConnection connection = url.openConnection(); @@ -48,16 +76,46 @@ public class CallerIdClient { while ((line = in.readLine()) != null) { if (line.startsWith("var in_call_list")) { - // TODO get list + // analyze caller list + + String s = line.substring(39); + log.debug(" " + line); + + String[] result = s.split("new Array\\("); + for (int x = 0; x < result.length; x++) { + // check for unanswered calls + if (result[x].substring(result[x].lastIndexOf('"') - 8, result[x].lastIndexOf('"')).equals("00:00:00")) { + log.debug("Unanswered call: " + result[x]); + + // determine call time + int year = Integer.parseInt(result[x].substring(7, 11)); + int month = Integer.parseInt(result[x].substring(4, 6)); + int date = Integer.parseInt(result[x].substring(1, 3)); + int hour = Integer.parseInt(result[x].substring(12, 14)); + int min = Integer.parseInt(result[x].substring(15, 17)); + int sec = Integer.parseInt(result[x].substring(18, 20)); + + Calendar callTime = Calendar.getInstance(); + callTime.set(year, month - 1, date, hour, min, sec); + + Calendar lastCheck = Calendar.getInstance(); + lastCheck.setTimeInMillis(System.currentTimeMillis() - updateInterval * 1000 * 60); + + if (callTime.after(lastCheck)) { + sendNotification(result[x].substring(1, 20), result[x].substring(23, result[x].indexOf('"', 23))); + } + } + } + } -// log.info(" " + line); + log.debug(" " + line); } in.close(); } private void postUrl(String urlString, String payload) throws Exception { - log.info("postUrl(" + urlString + ", " + payload + ")"); + log.debug("postUrl(" + urlString + ", " + payload + ")"); URL url = new URL(urlString); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); @@ -72,7 +130,7 @@ public class CallerIdClient { connection.setRequestProperty("Cookie", "SessionID_R3=" + cookie); } // connection.setRequestProperty("Referer", "https://speedport.ip/auth/hcti_status_telanrl.php?cookie=SessionID_R3," + cookie); - + OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream()); if (payload.length() > 0) { writer.write(payload); @@ -85,13 +143,13 @@ public class CallerIdClient { if (line.startsWith("SessionID_R3")) { cookie = line.substring(13); } else { - log.info(" Received unexpected response: " + line); + log.error(" Received unexpected response: " + line); } } writer.close(); reader.close(); - + showHeaders(connection); } @@ -106,21 +164,131 @@ public class CallerIdClient { } if (headerName == null) { // The header value contains the server's HTTP version - log.info(" Server HTTP version, Response code: " + headerValue); + log.debug(" Server HTTP version, Response code: " + headerValue); } else { - log.info(" Header: " + headerName + ", Value: " + headerValue); + log.debug(" Header: " + headerName + ", Value: " + headerValue); } } } - + + private void sendNotification(String time, String number) throws Exception { + log.info("Sende Nachricht: " + "Anruf von " + number + "\n" + time); + + if (number.equals(" ")) + number = TEXT_UNKNOWN; + + String host = config.getString("SMTP server address"); // "smtp.gmail.com" + String from = config.getString("e-mail adress"); + String pass = config.getString("e-mail password"); + Properties props = System.getProperties(); + props.put("mail.smtp.starttls.enable", "true"); + props.put("mail.smtp.host", host); + props.put("mail.smtp.user", from); + props.put("mail.smtp.password", pass); + props.put("mail.smtp.port", "587"); + props.put("mail.smtp.auth", "true"); + + String[] to = config.getStringArray("recipient"); + + Session session = Session.getDefaultInstance(props, null); + MimeMessage message = new MimeMessage(session); + message.setFrom(new InternetAddress(from)); + + InternetAddress[] toAddress = new InternetAddress[to.length]; + + for (int i = 0; i < to.length; i++) { + toAddress[i] = new InternetAddress(to[i]); + } + System.out.println(Message.RecipientType.TO); + + for (int i = 0; i < toAddress.length; i++) { + message.addRecipient(Message.RecipientType.TO, toAddress[i]); + } + + message.setSubject(TEXT_MAILPREFIX + number); + message.setText(TEXT_MAILPREFIX + number + "\n" + time); + + log.info("sending message for call from " + number + " at " + time); + + Transport transport = session.getTransport("smtp"); + transport.connect(host, from, pass); + transport.sendMessage(message, message.getAllRecipients()); + transport.close(); + } + /** * @param args */ public static void main(String[] args) { - if (args.length != 1) - System.out.println("usage: CallerIdClient "); - else - new CallerIdClient(args[0]); + BasicConfigurator.configure(new ConsoleAppender(new PatternLayout("%d{ISO8601} - %m%n"))); + log.info("Starting CallerIdClient version 1.0.0"); + + JSAP jsap = new JSAP(); + + try { + UnflaggedOption routerPassword = new UnflaggedOption("router password").setStringParser(JSAP.STRING_PARSER) + .setRequired(true); + routerPassword.setHelp("the login password for the Speedport W 723V (A) router"); + jsap.registerParameter(routerPassword); + + UnflaggedOption updateInterval = new UnflaggedOption("update interval").setStringParser(JSAP.INTEGER_PARSER) + .setRequired(true); + updateInterval.setHelp("the interval beetween runs in minutes"); + jsap.registerParameter(updateInterval); + + UnflaggedOption smtpServer = new UnflaggedOption("SMTP server address").setStringParser(JSAP.INETADDRESS_PARSER) + .setRequired(true); + smtpServer.setHelp("the SMTP server to send notifications with"); + jsap.registerParameter(smtpServer); + + UnflaggedOption fromAddress = new UnflaggedOption("e-mail adress").setStringParser(JSAP.STRING_PARSER).setRequired( + true); + fromAddress.setHelp("e-mail address to send from"); + jsap.registerParameter(fromAddress); + + UnflaggedOption emailPassword = new UnflaggedOption("e-mail password").setStringParser(JSAP.STRING_PARSER) + .setRequired(true); + emailPassword.setHelp("the login password for the e-mail account"); + jsap.registerParameter(emailPassword); + + UnflaggedOption recipients = new UnflaggedOption("recipient").setStringParser(JSAP.STRING_PARSER).setRequired(true) + .setGreedy(true); + recipients.setHelp("e-mail addresses to send notifications to"); + jsap.registerParameter(recipients); + + Switch debugSwitch = new Switch("debug").setLongFlag("debug"); + debugSwitch.setHelp("print debug messages"); + jsap.registerParameter(debugSwitch); + + Switch helpSwitch = new Switch("help").setLongFlag("help").setShortFlag('?'); + helpSwitch.setHelp("print help and exit"); + jsap.registerParameter(helpSwitch); + + } catch (JSAPException e) { + log.fatal(e.getMessage(), e); + System.exit(-1001); + } + + JSAPResult config = jsap.parse(args); + + if (!config.success() || config.getBoolean("help")) { + for (java.util.Iterator errs = config.getErrorMessageIterator(); errs.hasNext();) { + log.error("Error: " + errs.next()); + } + + log.error("Usage: java -jar speedportcallerid.jar " + jsap.getUsage() + "\n\n" + jsap.getHelp()); + System.exit(-1002); + } + + if (config.getBoolean("debug")) { + log.setLevel(Level.DEBUG); + } + else { + log.setLevel(Level.INFO); + } + log.info("Log level set to " + log.getLevel()); + + new CallerIdClient(config); } } diff --git a/WebCallerID/src/main/java/de/tilman/callerId/ClientApp.java b/WebCallerID/src/main/java/de/tilman/callerId/ClientApp.java deleted file mode 100755 index b80afdf..0000000 --- a/WebCallerID/src/main/java/de/tilman/callerId/ClientApp.java +++ /dev/null @@ -1,212 +0,0 @@ -//package de.tilman.callerId; -// -///* -// * $HeadURL$ -// * $Revision$ -// * $Date$ -// * ==================================================================== -// * -// * Licensed to the Apache Software Foundation (ASF) under one or more -// * contributor license agreements. See the NOTICE file distributed with -// * this work for additional information regarding copyright ownership. -// * The ASF licenses this file to You under the Apache License, Version 2.0 -// * (the "License"); you may not use this file except in compliance with -// * the License. You may obtain a copy of the License at -// * -// * http://www.apache.org/licenses/LICENSE-2.0 -// * -// * Unless required by applicable law or agreed to in writing, software -// * distributed under the License is distributed on an "AS IS" BASIS, -// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// * See the License for the specific language governing permissions and -// * limitations under the License. -// * ==================================================================== -// * -// * This software consists of voluntary contributions made by many -// * individuals on behalf of the Apache Software Foundation. For more -// * information on the Apache Software Foundation, please see -// * . -// * -// * [Additional notices, if required by prior licensing conditions] -// * -// */ -// -//import java.awt.BorderLayout; -//import java.awt.FlowLayout; -//import java.awt.event.ActionEvent; -//import java.awt.event.ActionListener; -//import java.awt.event.WindowAdapter; -//import java.awt.event.WindowEvent; -//import java.io.ByteArrayInputStream; -//import java.io.IOException; -// -//import javax.swing.JButton; -//import javax.swing.JComboBox; -//import javax.swing.JEditorPane; -//import javax.swing.JFrame; -//import javax.swing.JLabel; -//import javax.swing.JPanel; -//import javax.swing.JScrollPane; -//import javax.swing.JSplitPane; -//import javax.swing.JTextArea; -//import javax.swing.SwingUtilities; -//import javax.swing.text.BadLocationException; -//import javax.swing.text.html.HTMLDocument; -// -//import org.apache.commons.httpclient.HttpClient; -//import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; -//import org.apache.commons.httpclient.methods.GetMethod; -// -///** -// * A simple Swing application that demonstrates how to use the Jakarta -// * HttpClient API. This application loads HTML from servers and displays the -// * content as text and as rendered HTML. -// * -// * @author Sean C. Sullivan -// * @author Ortwin Glück -// * @author Michael Becke -// */ -//public class ClientApp { -// -// public static void main(String[] args) { -// HttpClientFrame f = new HttpClientFrame(); -// f.setTitle("HttpClient demo application"); -// f.setSize(700, 500); -// f.addWindowListener(new WindowAdapter() { -// public void windowClosing(WindowEvent e) { -// System.exit(0); -// } -// }); -// f.setVisible(true); -// } -// -// public static class HttpClientFrame extends JFrame { -// -// private JComboBox cmbURL; -// private JTextArea taTextResponse; -// private JEditorPane htmlPane; -// -// private HttpClient client; -// -// public HttpClientFrame() { -// client = new HttpClient(new MultiThreadedHttpConnectionManager()); -// client.getHttpConnectionManager().getParams() -// .setConnectionTimeout(30000); -// -// JPanel panInput = new JPanel(new FlowLayout()); -// -// String[] aURLs = { "http://www.apache.org/", -// "http://www.google.com/", "http://www.opensource.org/", -// "http://www.anybrowser.org/", "http://jakarta.apache.org/", -// "http://www.w3.org/" }; -// -// final JButton btnGET = new JButton("GET"); -// btnGET.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent ae) { -// String url = (String) cmbURL.getSelectedItem(); -// if (url != null && url.length() > 0) { -// loadPage(url); -// } -// } -// }); -// -// cmbURL = new JComboBox(aURLs); -// cmbURL.setToolTipText("Enter a URL"); -// cmbURL.setEditable(true); -// cmbURL.setSelectedIndex(0); -// -// JLabel lblURL = new JLabel("URL:"); -// -// panInput.add(lblURL); -// panInput.add(cmbURL); -// panInput.add(btnGET); -// -// taTextResponse = new JTextArea(); -// taTextResponse.setEditable(false); -// taTextResponse.setCaretPosition(0); -// -// htmlPane = new JEditorPane(); -// htmlPane.setContentType("text/html"); -// htmlPane.setEditable(false); -// -// JSplitPane splitResponsePane = new JSplitPane( -// JSplitPane.HORIZONTAL_SPLIT, -// new JScrollPane(taTextResponse), new JScrollPane(htmlPane)); -// splitResponsePane.setOneTouchExpandable(false); -// splitResponsePane.setDividerLocation(350); -// // it would be better to set resizeWeight, but this method does -// // not exist in JRE 1.2.2 -// // splitResponsePane.setResizeWeight(0.5); -// -// this.getContentPane().setLayout(new BorderLayout()); -// this.getContentPane().add(panInput, BorderLayout.NORTH); -// this.getContentPane().add(splitResponsePane, BorderLayout.CENTER); -// } -// -// /** -// * Sets the HTML content to be displayed. -// * -// * @param content -// * an HTML document -// */ -// private void setDocumentContent(String content) { -// -// HTMLDocument doc = new HTMLDocument(); -// try { -// doc.remove(0, doc.getLength()); -// } catch (BadLocationException e) { -// e.printStackTrace(); -// } -// doc.putProperty("IgnoreCharsetDirective", Boolean.TRUE); -// -// try { -// htmlPane.read(new ByteArrayInputStream(content.getBytes()), doc); -// } catch (IOException e) { -// e.printStackTrace(); -// } -// -// htmlPane.setDocument(doc); -// htmlPane.setCaretPosition(0); -// -// taTextResponse.setText(content); -// taTextResponse.setCaretPosition(0); -// taTextResponse.requestFocus(); -// } -// -// /** -// * Loads the page at the given URL from a separate thread. -// * -// * @param url -// */ -// private void loadPage(final String url) { -// // create a new thread to load the URL from -// new Thread() { -// public void run() { -// GetMethod get = new GetMethod(url); -// get.setFollowRedirects(true); -// -// try { -// int iGetResultCode = client.executeMethod(get); -// final String strGetResponseBody = get -// .getResponseBodyAsString(); -// -// if (strGetResponseBody != null) { -// // set the HTML on the UI thread -// SwingUtilities.invokeLater(new Runnable() { -// public void run() { -// setDocumentContent(strGetResponseBody); -// } -// }); -// } -// } catch (Exception ex) { -// ex.printStackTrace(); -// } finally { -// get.releaseConnection(); -// } -// } -// }.start(); -// } -// -// } -// -//}