import java.io.*; import java.net.*; import java.util.*; import java.text.*; import java.awt.*; import java.awt.event.*; import sun.audio.*; public final class JavaCM extends Thread implements WindowListener, MouseListener, KeyListener { //共通項目 private static final boolean DefaultMS932 = sun.io.ByteToCharConverter.getDefault().getCharacterEncoding().equals("MS932");; private static final boolean OS_Windows = System.getProperty("os.name", "").toUpperCase().indexOf("WINDOWS") != -1; private static String UserAgent = "Chat Monitor version 0.08a"; private static int io_timeout = 60000; private static boolean use_proxy = false; private static String proxy_server = null; private static int proxy_port = 0; private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss yyyy/MM/dd"); private static final AudioPlayer ap = AudioPlayer.player; private static final Runtime runtime = Runtime.getRuntime(); private static FileInputStream current_stream = null; private static Frame f = new Frame("Chat Monitor"); private static Insets insets = null; //個別項目 private String url = null; private int interval = 30000; private String encode = null; private String prev_result = null; private String ignore_until = null; private String ignore_after = null; private String ignore_list = null; private String lastmodified = "最終更新:不明"; private String soundfile = null; private String openpage = null; private String caption = null; private Label statuslabel = null; private Button shellbutton = null; private Button switchbutton = null; private volatile boolean sleeping = false; //初期設定 JavaCM(String url, int interval, String encode, String ignore_until, String ignore_after, String ignore_list, int i, String caption, String soundfile, String openpage) { this.url = url; this.interval = interval * 1000; this.encode = encode; this.ignore_until = ignore_until; this.ignore_after = ignore_after; this.ignore_list = ignore_list; this.openpage = openpage; this.caption = caption; this.soundfile = soundfile; if (insets == null) { f.addWindowListener(this); f.pack(); insets = f.getInsets(); } Label titlelabel = new Label(caption); titlelabel.setBounds(5, insets.top + 28 * i, 270, 28); f.add(titlelabel); statuslabel = new Label(lastmodified); statuslabel.setBounds(275, insets.top + 28 * i, 270, 28); f.add(statuslabel); if (openpage != null) { shellbutton = new Button("開く"); shellbutton.addMouseListener(this); shellbutton.addKeyListener(this); shellbutton.setBounds(550, insets.top + 28 * i, 41, 28); f.add(shellbutton); } switchbutton = new Button("停止"); switchbutton.addMouseListener(this); switchbutton.addKeyListener(this); switchbutton.setBounds(595, insets.top + 28 * i, 41, 28); f.add(switchbutton); } //メインループ public void run() { String lasterror = null; while(true) { statuslabel.setText("最新の情報を取得中です。" + lastmodified); //System.out.println("最新の情報を取得中です。"); lasterror = CompareProc(GET(url)); if (lasterror.length() != 0) System.out.println(caption + ":" + lasterror); statuslabel.setText(lasterror + lastmodified); try { sleep(interval); if (sleeping) synchronized (this) { while (sleeping) wait(); } } catch (InterruptedException e){} } } private synchronized void turnswitch () { if (switchbutton.getLabel().equals("停止")) { switchbutton.setLabel("再開"); sleeping = true; //停止する。 } else { sleeping = false; //再開する。 notifyAll(); switchbutton.setLabel("停止"); } } //マウスのクリック処理 public void mouseClicked(MouseEvent e) { if (e.getSource() == shellbutton) shell(openpage); else turnswitch(); } //キーボードの処理 public void keyTyped(KeyEvent e) { if (e.getKeyChar() == KeyEvent.VK_ENTER) { if (e.getSource() == shellbutton) shell(openpage); else turnswitch(); } } public void windowActivated(WindowEvent e) {} public void windowClosed(WindowEvent e) {} public void windowDeactivated(WindowEvent e) {} public void windowDeiconified(WindowEvent e) {} public void windowIconified(WindowEvent e) {} public void windowOpened(WindowEvent e) {} public void windowClosing(WindowEvent e) { System.exit(0); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void keyPressed(KeyEvent e) {} public void keyReleased(KeyEvent e) {} private String CompareProc(String result) { int i = 0; byte temp[] = null; if (result == null) return "取得に失敗しました。"; StringTokenizer st = new StringTokenizer(result, "\r\n"); if (!st.hasMoreTokens()) return "応答がありませんでした。"; String header = st.nextToken(); try { st = new StringTokenizer(header); st.nextToken(); i = Integer.parseInt(st.nextToken()); if (i < 200 || i >= 300) throw new Exception(); } catch (Exception e) { return header + " "; } if ((i = result.indexOf("\r\n\r\n")) != -1) result = result.substring(i + 4); else if ((i = result.indexOf("\n\n")) != -1) result = result.substring(i + 2); else return "応答がありませんでした。"; try { temp = result.getBytes("8859_1"); result = new String(temp, encode); } catch (UnsupportedEncodingException e) { if (encode.equals("EUC_JP_LINUX") && temp != null) { result = EUC2UnicodeSJIS(temp); } else { return "変換に失敗しました。"; } } if (DefaultMS932) { if (encode.startsWith("JIS") || encode.equals("SJIS") || encode.startsWith("EUC_JP") || encode.equals("ISO-2022-JP") || encode.startsWith("CP943")) result = UNICODEforMS932(result); } result = result.replace('\t', ' '); if (ignore_until != null) { if ((i = result.indexOf(ignore_until)) == -1) return "検索位置を特定できません。"; result = result.substring(i + ignore_until.length()); } if (ignore_after != null) { if ((i = result.indexOf(ignore_after)) == -1) return "検索位置を特定できません。"; result = result.substring(0, i); } if (ignore_list != null) { StringBuffer sb = new StringBuffer(result.length()); st = new StringTokenizer(result, ignore_list); while (st.hasMoreTokens()) sb.append(st.nextToken()); result = sb.toString(); if (result.length() == 0) return "ページの内容がありません。"; } if (prev_result != null && !result.equals(prev_result)) { lastmodified = "最終更新:" + sdf.format(new Date()); System.out.println(caption + " " + lastmodified); f.toFront(); play(soundfile); } prev_result = result; return ""; } private String EUC2UnicodeSJIS(byte byte_source[]) { if (byte_source == null) return null; if (byte_source.length == 0) return ""; int i = 0, j = byte_source.length, v = 0, v2 = 0; char source[] = new char[j]; ByteArrayOutputStream buf = new ByteArrayOutputStream(source.length); for (i = 0; i < j; i++) source[i] = (char) (byte_source[i] & 0xFF); i = 0; try { while (i < j) { if ((v = source[i]) <= 0x7E) { // ASCII buf.write(v); } else if (v == 0x8E) { // 1 byte KANA v = source[i + 1]; if (v < 0xA1 || v > 0xDF) v = '?'; buf.write(v); i++; } else if (v == 0x8F) { // JIS X 0212-1990 buf.write('?'); buf.write('?'); i += 2; } else if (v <= 0xA0 || (v2 = source[i + 1]) <= 0xA0) { // Out of range buf.write('?'); } else { v = (((v & 0x7F) - 0x21) * 94) + ((v2 & 0x7F) - 0x21); i++; v2 = (v / 188) + 0x81; if (v2 >= 0xA0) v2 += 0x40; buf.write(v2); v2 = (v % 188) + 0x40; if (v2 >= 0x7F) v2++; buf.write(v2); } i++; } } catch (ArrayIndexOutOfBoundsException e) { } try { return new String(buf.toByteArray(), "SJIS"); } catch (UnsupportedEncodingException e) { return ""; } } private String UNICODEforMS932(String s) { if (s == null) return null; return s.replace((char) 0xA5, (char) 0x5C).replace((char) 0x203E, (char) 0x7E).replace((char) 0x2014, (char) 0x2015).replace((char) 0x301C, (char) 0xFF5E).replace((char) 0x2016, (char) 0x2225).replace((char) 0x22EF, (char) 0x2026).replace((char) 0x2212, (char) 0xFF0D).replace((char) 0xA2, (char) 0xFFE0).replace((char) 0xA3, (char) 0xFFE1).replace((char) 0xAC, (char) 0xFFE2); } private String GET(String url) { String contents = null; boolean success = false, iotimeout = false; try { URL url1 = new URL(url); String host = url1.getHost(); int port = url1.getPort(); if (port == -1) port = 80; Socket socket = null; if (!use_proxy) socket = new Socket(host, port); else socket = new Socket(proxy_server, proxy_port); socket.setSoTimeout(io_timeout); OutputStream os = socket.getOutputStream(); InputStream is = socket.getInputStream(); StringBuffer request = new StringBuffer(256); request.append("GET "); if (!use_proxy) request.append(url1.getFile()); else request.append(url1.toString()); request.append(" HTTP/1.0\r\n"); request.append("User-Agent: "); request.append(UserAgent); request.append("\r\n"); request.append("Host: "); request.append(host); if (port != 80) { request.append(':'); request.append(port); } request.append("\r\n"); if (use_proxy) request.append("Pragma: No-Cache\r\nProxy-"); request.append("Connection: Close\r\n"); request.append("\r\n"); os.write(request.toString().getBytes()); byte buffer[] = new byte [1024]; ByteArrayOutputStream buf = new ByteArrayOutputStream(1024 * 10); int len = 0; try { while ((len = is.read(buffer)) != -1) buf.write(buffer, 0, len); } catch (InterruptedIOException e) { iotimeout = true; } socket.close(); contents = buf.toString("8859_1"); // new String(buf.toByteArray(), "8859_1"); success = true; } catch (IOException e) { System.out.println(e); } if (!success || iotimeout) contents = null; return contents; } private static void play(String soundfile) { if (soundfile != null) { if (OS_Windows && soundfile.toUpperCase().endsWith(".WAV")) { synchronized (runtime) { try { runtime.exec("RUNDLL MMSYSTEM,sndPlaySound " + soundfile); } catch (Exception e) { System.out.println(e); } } } else { synchronized (ap) { try { if (current_stream != null) { ap.stop(current_stream); current_stream.close(); } current_stream = new FileInputStream(soundfile); ap.start(current_stream); } catch (Exception e) { System.out.println(e); } System.gc(); } } } } private static void shell(String openpage) { if (openpage != null) synchronized (runtime) { try { runtime.exec(openpage); } catch (Exception e) { System.out.println(e); } } } public static void main(String args[]) { System.out.println("Chat Monitor version 0.08a\nCopyright (C) 1999-2001 PANDA (a5497108@anet.ne.jp)"); String configfile = "cm.dat"; String configfile_encoding = null; if (args.length > 0) configfile = args[0]; if (args.length > 1) configfile_encoding = args[1]; File config = new File(configfile); System.out.println(config.getAbsolutePath() + "を読み込んでいます。"); f.setBackground(Color.yellow); try { FileInputStream fis = new FileInputStream(config); byte buf[] = new byte[fis.available()]; fis.read(buf); fis.close(); String data = null; if (configfile_encoding != null) data = new String(buf, configfile_encoding); else data = new String(buf); int i = 0; Vector list = new Vector(10, 1); boolean common = false; String buffer = null, value = null; String caption = null, url = null, encode = null, ignoreuntil = null, ignoreafter = null, ignorelist = null, openpage = null, soundfile = null; int interval = 0; StringTokenizer st = new StringTokenizer(data, "\r\n"); while (st.hasMoreTokens()) { buffer = st.nextToken().trim(); if (buffer.toUpperCase().equals("[COMMON]")) common = true; else if (buffer.startsWith("[") && buffer.endsWith("]")) { common = false; if (url != null && interval >= 10 && interval <= 3600 && encode != null && caption != null && soundfile != null) list.addElement(new JavaCM(url, interval, encode, ignoreuntil, ignoreafter, ignorelist, list.size(), caption, soundfile, openpage)); caption = buffer.substring(1, buffer.length() - 1); url = encode = ignoreuntil = ignoreafter = ignorelist = openpage = soundfile = null; interval = 0; } else if ((i = buffer.indexOf('=')) != -1) { value = buffer.substring(i + 1).trim(); if (value.length() != 0) { buffer = buffer.toUpperCase(); if (common) { if (buffer.startsWith("USERAGENT")) UserAgent = value; else if (buffer.startsWith("USEPROXY")) { try { use_proxy = (Integer.parseInt(value) != 0); } catch (Exception e) { } } else if (buffer.startsWith("PROXYSERVER")) proxy_server = value; else if (buffer.startsWith("PROXYPORT")) proxy_port = Integer.parseInt(value); else if (buffer.startsWith("TIMEOUT")) io_timeout = Integer.parseInt(value) * 1000; } else if (caption != null) { if (buffer.startsWith("URL")) url = value; else if (buffer.startsWith("INTERVAL")) interval = Integer.parseInt(value); else if (buffer.startsWith("ENCODE")) encode = value; else if (buffer.startsWith("IGNOREUNTIL")) ignoreuntil = value; else if (buffer.startsWith("IGNOREAFTER")) ignoreafter = value; else if (buffer.startsWith("IGNORELIST")) ignorelist = value; else if (buffer.startsWith("OPEN")) openpage = value; else if (buffer.startsWith("SOUND")) soundfile = value; } } } } if (url != null && interval >= 10 && interval <= 3600 && encode != null && caption != null && soundfile != null) list.addElement(new JavaCM(url, interval, encode, ignoreuntil, ignoreafter, ignorelist, list.size(), caption, soundfile, openpage)); if (list.size() == 0 || io_timeout <= 0) throw new Exception(); if (use_proxy && (proxy_server == null || proxy_server.length() == 0 || proxy_port <= 0 || proxy_port > 65535)) throw new Exception(); for (i = 0; i < list.size(); i++) ((JavaCM) list.elementAt(i)).start(); f.setBounds(50, 50, 640, insets.top + insets.bottom + 28 * list.size()); f.setLayout(null); f.setResizable(false); list = null; System.gc(); f.setVisible(true); } catch (UnsupportedEncodingException e) { System.out.println("文字コードの指定が無効です。" + configfile_encoding); System.exit(1); } catch (Exception e) { System.out.println(config.getAbsolutePath() + " の読み込みに失敗しました。"); System.exit(1); } } }