├── src ├── .idea │ ├── .name │ ├── copyright │ │ └── profiles_settings.xml │ ├── ant.xml │ ├── encodings.xml │ ├── vcs.xml │ ├── inspectionProfiles │ │ ├── profiles_settings.xml │ │ └── Project_Default.xml │ ├── libraries │ │ └── swt.xml │ ├── modules.xml │ ├── compiler.xml │ ├── runConfigurations │ │ └── MibewTray.xml │ ├── misc.xml │ └── uiDesigner.xml ├── org.mibew.jabber │ ├── resources │ │ ├── Mibew Notifier.app │ │ │ └── Contents │ │ │ │ ├── PkgInfo │ │ │ │ ├── MacOS │ │ │ │ └── MibewNotifier │ │ │ │ ├── Resources │ │ │ │ └── mibew.icns │ │ │ │ └── Info.plist │ │ ├── images │ │ │ └── mibew.gif │ │ ├── packdmg.sh │ │ └── build.xml │ ├── libs │ │ ├── smack.jar │ │ ├── smackx.jar │ │ ├── smackx-debug.jar │ │ └── smackx-jingle.jar │ ├── src │ │ ├── mibew-sample.ini │ │ └── org │ │ │ └── mibew │ │ │ └── jabber │ │ │ ├── Parameters.java │ │ │ └── Application.java │ ├── .classpath │ └── .project ├── org.mibew.notifier │ ├── libs │ │ ├── src.zip │ │ ├── swt.jar │ │ └── swt-debug.jar │ ├── src │ │ └── org │ │ │ └── mibew │ │ │ └── notifier │ │ │ ├── tray_on.png │ │ │ ├── tray_off.png │ │ │ ├── ConsoleApp.java │ │ │ ├── NotifyApp.java │ │ │ ├── BrowserUtil.java │ │ │ ├── Options.java │ │ │ └── MibewTray.java │ ├── .project │ ├── .classpath │ └── org.mibew.notifier.iml └── org.mibew.api │ ├── src │ └── org │ │ └── mibew │ │ └── api │ │ ├── MibewAgentListener.java │ │ ├── MibewTrackerListener.java │ │ ├── Utils.java │ │ ├── handlers │ │ ├── LoginHandler.java │ │ └── UpdateHandler.java │ │ ├── MibewResponse.java │ │ ├── MibewAgentOptions.java │ │ ├── MibewTracker.java │ │ ├── MibewThread.java │ │ ├── MibewAgent.java │ │ └── MibewConnection.java │ ├── .classpath │ ├── .project │ └── org.mibew.api.iml ├── .gitignore ├── .gitattributes ├── README.md └── LICENSE /src/.idea/.name: -------------------------------------------------------------------------------- 1 | mibew -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPL???? -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | src/.idea/workspace.xml 3 | src/org.mibew.notifier/resources/ 4 | mibew.ini 5 | .DS_Store 6 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/libs/smack.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/libs/smack.jar -------------------------------------------------------------------------------- /src/org.mibew.notifier/libs/src.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.notifier/libs/src.zip -------------------------------------------------------------------------------- /src/org.mibew.notifier/libs/swt.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.notifier/libs/swt.jar -------------------------------------------------------------------------------- /src/org.mibew.jabber/libs/smackx.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/libs/smackx.jar -------------------------------------------------------------------------------- /src/org.mibew.jabber/libs/smackx-debug.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/libs/smackx-debug.jar -------------------------------------------------------------------------------- /src/org.mibew.notifier/libs/swt-debug.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.notifier/libs/swt-debug.jar -------------------------------------------------------------------------------- /src/org.mibew.jabber/libs/smackx-jingle.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/libs/smackx-jingle.jar -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/images/mibew.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/resources/images/mibew.gif -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/tray_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.notifier/src/org/mibew/notifier/tray_on.png -------------------------------------------------------------------------------- /src/.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/tray_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.notifier/src/org/mibew/notifier/tray_off.png -------------------------------------------------------------------------------- /src/.idea/ant.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/MacOS/MibewNotifier: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/MacOS/MibewNotifier -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Resources/mibew.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mibew/java/master/src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Resources/mibew.icns -------------------------------------------------------------------------------- /src/.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.php text 2 | *.pl text 3 | properties text 4 | *.html text 5 | *.css text 6 | *.tpl text 7 | *.xml text 8 | *.java text 9 | *.sh eol=lf 10 | *.txt text 11 | .project text 12 | .classpath text 13 | .buildpath text 14 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/src/mibew-sample.ini: -------------------------------------------------------------------------------- 1 | # 2 | # Configuration file for Mibew-to-jabber gate 3 | # 4 | 5 | jabber.host=jabber.org 6 | jabber.login=webim_notifier 7 | jabber.password=123 8 | 9 | jabber.admin=yourmail@jabber.org 10 | -------------------------------------------------------------------------------- /src/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewAgentListener.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | public abstract class MibewAgentListener { 4 | 5 | protected void onlineStateChanged(boolean isOnline) { 6 | } 7 | 8 | protected void updated(MibewThread[] all, MibewThread[] created) { 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/packdmg.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf *.dmg 4 | hdiutil create mibew-notifier-temp.dmg -volname "Mibew Notifier 1.0" -fs HFS+ -srcfolder "Mibew Notifier.app" 5 | hdiutil convert "mibew-notifier-temp.dmg" -format UDZO -imagekey zlib-level=9 -o "mibew-1.0.0.dmg" 6 | rm mibew-notifier-temp.dmg 7 | -------------------------------------------------------------------------------- /src/org.mibew.api/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/.idea/libraries/swt.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewTrackerListener.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | 4 | /** 5 | * @author inspirer 6 | */ 7 | public abstract class MibewTrackerListener { 8 | 9 | public void threadCreated(MibewThread thread) { 10 | } 11 | 12 | public void threadChanged(MibewThread thread) { 13 | } 14 | 15 | public void threadClosed(MibewThread thread) { 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/org.mibew.api/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.mibew.api 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.mibew.jabber 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | org.mibew.notifier 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/org.mibew.api/org.mibew.api.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/org.mibew.notifier.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/ConsoleApp.java: -------------------------------------------------------------------------------- 1 | package org.mibew.notifier; 2 | 3 | import org.mibew.api.MibewAgent; 4 | import org.mibew.api.MibewAgentListener; 5 | 6 | public class ConsoleApp { 7 | 8 | public static void main(String[] args) { 9 | Options options = new Options(args); 10 | if(!options.load()) { 11 | return; 12 | } 13 | 14 | MibewAgent agent = new MibewAgent(options.getAgentOptions(), new MibewAgentListener() { 15 | @Override 16 | protected void onlineStateChanged(boolean isOnline) { 17 | System.out.println("now " + (isOnline ? "online" : "offline")); 18 | } 19 | }); 20 | agent.launch(); 21 | try { 22 | Thread.sleep(3500); 23 | } catch (InterruptedException e) { 24 | } 25 | 26 | agent.stop(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Mibew Java applications 2 | 3 | Mibew Java applications is a package of applications written in Java and designed 4 | to work with Mibew Messenger live support application. 5 | 6 | Mibew Java applications should be treated as separate applications tied 7 | to 1.6.x branch of Mibew Messenger by technology as well as by ideology. 8 | 9 | ## Terms of Use 10 | 11 | Mibew Java applications is a part of the Mibew project and licensed under the 12 | terms of [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0). 13 | 14 | ## Other repositories of the Mibew project 15 | 16 | 1. [Mibew Messenger core repository](https://github.com/Mibew/mibew) 17 | 2. [Mibew Messenger i18n repository](https://github.com/Mibew/i18n) 18 | 3. [Mibew Messenger design repository](https://github.com/Mibew/design) 19 | 4. [Mibew Tray repository](https://github.com/Mibew/tray) 20 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/Utils.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.security.MessageDigest; 5 | import java.security.NoSuchAlgorithmException; 6 | 7 | /** 8 | * @author inspirer 9 | */ 10 | public class Utils { 11 | 12 | private static final String HEX_DIGITS = "0123456789abcdef"; 13 | 14 | public static String md5(String string) throws NoSuchAlgorithmException, UnsupportedEncodingException { 15 | return md5(string.getBytes("utf-8")); 16 | } 17 | 18 | private static String md5(byte[] string) throws NoSuchAlgorithmException { 19 | MessageDigest md = MessageDigest.getInstance( "MD5" ); 20 | md.update(string); 21 | byte[] digest = md.digest(); 22 | StringBuilder sb = new StringBuilder(); 23 | for ( byte b : digest ) { 24 | sb.append(HEX_DIGITS.charAt((b&0xff)>>4)); 25 | sb.append(HEX_DIGITS.charAt(b&0xf)); 26 | } 27 | return sb.toString(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/NotifyApp.java: -------------------------------------------------------------------------------- 1 | package org.mibew.notifier; 2 | 3 | import org.eclipse.swt.widgets.Display; 4 | import org.eclipse.swt.widgets.Shell; 5 | import org.mibew.api.MibewAgent; 6 | import org.mibew.notifier.Options.JOptions; 7 | 8 | public class NotifyApp { 9 | 10 | public static void main(String[] args) { 11 | Display display = new Display(); 12 | Shell shell = new Shell(display); 13 | 14 | Options options = new JOptions(shell, args); 15 | if (!options.load()) { 16 | return; 17 | } 18 | 19 | MibewTray tray = new MibewTray(); 20 | MibewAgent agent = new MibewAgent(options.getAgentOptions(), tray); 21 | agent.launch(); 22 | 23 | tray.initTray(display, shell, agent); 24 | 25 | while (!shell.isDisposed()) { 26 | if (!display.readAndDispatch()) 27 | display.sleep(); 28 | } 29 | tray.dispose(); 30 | agent.stop(); 31 | display.dispose(); 32 | System.exit(0); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/handlers/LoginHandler.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api.handlers; 2 | 3 | import java.util.Stack; 4 | 5 | import org.xml.sax.Attributes; 6 | import org.xml.sax.SAXException; 7 | import org.xml.sax.helpers.DefaultHandler; 8 | 9 | /** 10 | * @author inspirer 11 | */ 12 | public class LoginHandler extends DefaultHandler { 13 | 14 | private Stack fPath = new Stack(); 15 | private String status = ""; 16 | 17 | @Override 18 | public void startElement(String uri, String localName, String name, 19 | Attributes attributes) throws SAXException { 20 | fPath.push(name); 21 | } 22 | 23 | @Override 24 | public void endElement(String uri, String localName, String name) 25 | throws SAXException { 26 | fPath.pop(); 27 | } 28 | 29 | @Override 30 | public void characters(char[] ch, int start, int length) throws SAXException { 31 | String current = fPath.peek(); 32 | if(fPath.size() != 2 || !current.equals("status") || !fPath.get(0).equals("login")) { 33 | throw new SAXException("unexpected characters"); 34 | } 35 | status += new String(ch,start,length); 36 | } 37 | 38 | public String getStatus() { 39 | return status; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/.idea/runConfigurations/MibewTray.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 24 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewResponse.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.io.InputStreamReader; 6 | import java.io.Reader; 7 | 8 | /** 9 | * @author inspirer 10 | */ 11 | public class MibewResponse { 12 | 13 | public int code; 14 | public byte[] response; 15 | 16 | public MibewResponse(int code, byte[] response) { 17 | this.code = code; 18 | this.response = response; 19 | } 20 | 21 | public int getCode() { 22 | return code; 23 | } 24 | 25 | public byte[] getResponse() { 26 | return response; 27 | } 28 | 29 | public String getResponseText() { 30 | try { 31 | Reader r = new InputStreamReader(new ByteArrayInputStream(response), "UTF-8"); 32 | StringBuilder sb = new StringBuilder(); 33 | char[] c = new char[1024]; 34 | int size = 0; 35 | while((size = r.read(c)) != -1) { 36 | sb.append(c, 0, size); 37 | } 38 | return sb.toString(); 39 | } catch(IOException ex) { 40 | return ""; 41 | } 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return 47 | "Response code: " + code + "\n" + 48 | "Text: " + getResponseText(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/src/org/mibew/jabber/Parameters.java: -------------------------------------------------------------------------------- 1 | package org.mibew.jabber; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.util.Properties; 6 | 7 | /** 8 | * @author inspirer 9 | */ 10 | public class Parameters { 11 | 12 | private final String[] fArguments; 13 | 14 | public String fJabberServer; 15 | public String fJabberLogin; 16 | public String fJabberPassword; 17 | 18 | public String fJabberAdmin; 19 | 20 | public Parameters(String[] args) { 21 | this.fArguments = args; 22 | } 23 | 24 | private String getProperty(Properties p, String name) throws IOException { 25 | String result = p.getProperty(name); 26 | if(result == null || result.trim().length() == 0) { 27 | throw new IOException("No '"+name+"' property"); 28 | } 29 | return result; 30 | } 31 | 32 | public boolean load() { 33 | try { 34 | InputStream is = getClass().getClassLoader().getResourceAsStream("mibew.ini"); 35 | if(is != null) { 36 | Properties p = new Properties(); 37 | p.load(is); 38 | 39 | fJabberServer = getProperty(p, "jabber.host"); 40 | fJabberLogin = getProperty(p, "jabber.login"); 41 | fJabberPassword = getProperty(p, "jabber.password"); 42 | fJabberAdmin = getProperty(p, "jabber.admin"); 43 | 44 | return true; 45 | } 46 | } catch (IOException e) { 47 | System.err.println(e.getMessage()); 48 | return false; 49 | } 50 | 51 | System.err.println("Cannot find mibew.ini"); 52 | return false; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/BrowserUtil.java: -------------------------------------------------------------------------------- 1 | package org.mibew.notifier; 2 | 3 | import java.io.IOException; 4 | import java.lang.reflect.Method; 5 | import java.util.Arrays; 6 | 7 | public class BrowserUtil { 8 | 9 | static final String[] browsers = { "firefox", "opera", "konqueror", "epiphany", "seamonkey", "galeon", 10 | "kazehakase", "mozilla", "netscape" }; 11 | 12 | /** 13 | * Bare Bones Browser Launch 14 | * Version 2.0 (May 26, 2009) 15 | * By Dem Pilafian 16 | * @param url 17 | */ 18 | public static void openURL(String url) throws IOException { 19 | String osName = System.getProperty("os.name"); 20 | try { 21 | if (osName.startsWith("Mac OS")) { 22 | Class fileMgr = Class.forName("com.apple.eio.FileManager"); 23 | Method openURL = fileMgr.getDeclaredMethod("openURL", new Class[] { String.class }); 24 | openURL.invoke(null, new Object[] { url }); 25 | } else if (osName.startsWith("Windows")) { 26 | Runtime.getRuntime().exec("rundll32 url.dll,FileProtocolHandler " + url); 27 | } else { // assume Unix or Linux 28 | boolean found = false; 29 | for (String browser : browsers) 30 | if (!found) { 31 | found = Runtime.getRuntime().exec(new String[] { "which", browser }).waitFor() == 0; 32 | if (found) 33 | Runtime.getRuntime().exec(new String[] { browser, url }); 34 | } 35 | if (!found) 36 | throw new Exception(Arrays.toString(browsers)); 37 | } 38 | } catch (Throwable th) { 39 | throw new IOException("Error attempting to launch web browser\n" + th.toString()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | 26 | 27 | http://www.w3.org/1999/xhtml 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/Mibew Notifier.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | Mibew Notifier 7 | CFBundleIdentifier 8 | org.mibew.notifier 9 | CFBundleVersion 10 | 100.0 11 | CFBundleAllowMixedLocalizations 12 | true 13 | CFBundleExecutable 14 | MibewNotifier 15 | CFBundleDevelopmentRegion 16 | English 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleGetInfoString 24 | Mibew Notifier 1.0, build 17 Jan, 2010 25 | CFBundleInfoDictionaryVersion 26 | 6.0 27 | CFBundleIconFile 28 | mibew.icns 29 | Java 30 | 31 | WorkingDirectory 32 | $APP_PACKAGE/Contents/Resources/Java 33 | VMOptions 34 | -Xms16mm 35 | MainClass 36 | org.mibew.trayapp.NotifyApp 37 | JVMVersion 38 | 1.6+ 39 | ClassPath 40 | 41 | $JAVAROOT/org.mibew.notifier.jar 42 | $JAVAROOT/smackx.jar 43 | $JAVAROOT/smackx-jingle.jar 44 | $JAVAROOT/smackx-debug.jar 45 | $JAVAROOT/smack.jar 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewAgentOptions.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.IOException; 4 | import java.util.Properties; 5 | 6 | /** 7 | * @author inspirer 8 | */ 9 | public class MibewAgentOptions { 10 | 11 | private String fUrl; 12 | private String fLogin; 13 | private String fPassword; 14 | private int fConnectionRefreshTimeout = 900; // in seconds (15 minutes by default) 15 | private int fPollingInterval = 2000; // 2 sec (in milliseconds) 16 | 17 | public MibewAgentOptions(String fUrl, String fLogin, String fPassword) { 18 | super(); 19 | this.fUrl = fUrl; 20 | this.fLogin = fLogin; 21 | this.fPassword = fPassword; 22 | } 23 | 24 | public String getLogin() { 25 | return fLogin; 26 | } 27 | 28 | public String getPassword() { 29 | return fPassword; 30 | } 31 | 32 | public String getUrl() { 33 | return fUrl; 34 | } 35 | 36 | public int getConnectionRefreshTimeout() { 37 | return fConnectionRefreshTimeout; 38 | } 39 | 40 | public int getPollingInterval() { 41 | return fPollingInterval; 42 | } 43 | 44 | private static String getProperty(Properties p, String name, String defaultValue) throws IOException { 45 | String result = p.getProperty(name); 46 | if(result == null) { 47 | if(defaultValue != null) { 48 | return defaultValue; 49 | } 50 | throw new IOException("No '"+name+"' property"); 51 | } 52 | return result; 53 | } 54 | 55 | public static MibewAgentOptions create(Properties p) throws IOException { 56 | String url = getProperty(p, "mibew.host", null); 57 | String login = getProperty(p, "mibew.login", null); 58 | String password = getProperty(p, "mibew.password", null); 59 | 60 | return new MibewAgentOptions(url, login, password); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/Options.java: -------------------------------------------------------------------------------- 1 | package org.mibew.notifier; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.widgets.MessageBox; 5 | import org.eclipse.swt.widgets.Shell; 6 | import org.mibew.api.MibewAgentOptions; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.util.Properties; 11 | 12 | public class Options { 13 | 14 | private MibewAgentOptions agentOptions; 15 | private Properties myProperties; 16 | 17 | public Options(String[] args) { 18 | } 19 | 20 | public boolean load() { 21 | try { 22 | InputStream is = getClass().getClassLoader().getResourceAsStream("mibew.ini"); 23 | if (is != null) { 24 | myProperties = new Properties(); 25 | myProperties.load(is); 26 | agentOptions = MibewAgentOptions.create(myProperties); 27 | return true; 28 | } else { 29 | handleError("cannot find mibew.ini"); 30 | } 31 | } catch (IOException e) { 32 | handleError(e.getMessage()); 33 | } 34 | return false; 35 | } 36 | 37 | protected void handleError(String message) { 38 | System.err.println(message); 39 | } 40 | 41 | public MibewAgentOptions getAgentOptions() { 42 | return agentOptions; 43 | } 44 | 45 | public static class JOptions extends Options { 46 | 47 | private final Shell fShell; 48 | 49 | public JOptions(Shell shell, String[] args) { 50 | super(args); 51 | fShell = shell; 52 | } 53 | 54 | @Override 55 | protected void handleError(final String message) { 56 | MessageBox messageBox = new MessageBox(fShell, SWT.OK | SWT.ICON_ERROR); 57 | messageBox.setText("Options error"); //$NON-NLS-1$ 58 | messageBox.setMessage(message); 59 | messageBox.open(); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/src/org/mibew/jabber/Application.java: -------------------------------------------------------------------------------- 1 | package org.mibew.jabber; 2 | 3 | import java.io.IOException; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | import javax.xml.parsers.ParserConfigurationException; 7 | 8 | import org.jivesoftware.smack.Chat; 9 | import org.jivesoftware.smack.MessageListener; 10 | import org.jivesoftware.smack.XMPPConnection; 11 | import org.jivesoftware.smack.XMPPException; 12 | import org.jivesoftware.smack.packet.Message; 13 | import org.mibew.api.MibewConnection; 14 | import org.mibew.api.MibewThread; 15 | import org.mibew.api.MibewTracker; 16 | import org.mibew.api.MibewTrackerListener; 17 | import org.xml.sax.SAXException; 18 | 19 | /** 20 | * @author inspirer 21 | */ 22 | public class Application { 23 | 24 | public static void main(String[] args) throws NoSuchAlgorithmException, IOException, XMPPException, InterruptedException, ParserConfigurationException, SAXException { 25 | System.out.println("Mibew Jabber transport application"); 26 | 27 | Parameters p = new Parameters(args); 28 | if(!p.load()) { 29 | return; 30 | } 31 | 32 | XMPPConnection connection = new XMPPConnection(p.fJabberServer); 33 | connection.connect(); 34 | connection.login(p.fJabberLogin, p.fJabberPassword); 35 | final Chat chat = connection.getChatManager().createChat(p.fJabberAdmin, new MessageListener() { 36 | 37 | public void processMessage(Chat chat, Message message) { 38 | System.out.println("Received message: " + message.getThread() + " " + message.getBody()); 39 | } 40 | }); 41 | 42 | MibewConnection conn = new MibewConnection("http://localhost:8080/webim/", "admin", "1"); 43 | if(!conn.connect()) { 44 | System.err.println("Wrong server, login or password."); 45 | return; 46 | } 47 | MibewTracker mt = new MibewTracker(conn, new MibewTrackerListener(){ 48 | 49 | @Override 50 | public void threadCreated(MibewThread thread) { 51 | try { 52 | chat.sendMessage(thread.getId() + ": " + thread.getAddress() + " " + thread.getClientName()); 53 | } catch (XMPPException e) { 54 | e.printStackTrace(); 55 | } 56 | } 57 | 58 | }); 59 | //mt.track(); 60 | 61 | connection.disconnect(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/org.mibew.jabber/resources/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewTracker.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.IOException; 5 | import java.util.Collection; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import javax.xml.parsers.ParserConfigurationException; 11 | import javax.xml.parsers.SAXParser; 12 | import javax.xml.parsers.SAXParserFactory; 13 | 14 | import org.mibew.api.handlers.UpdateHandler; 15 | import org.xml.sax.SAXException; 16 | 17 | /** 18 | * @author inspirer 19 | */ 20 | public class MibewTracker { 21 | 22 | private final MibewConnection fConnection; 23 | private final MibewTrackerListener fListener; 24 | private long fSince = 0; 25 | private long fLastUpdate = 0; 26 | 27 | private final Map fThreads; 28 | 29 | public MibewTracker(MibewConnection conn, MibewTrackerListener listener) { 30 | this.fConnection = conn; 31 | this.fListener = listener; 32 | this.fThreads = new HashMap(); 33 | } 34 | 35 | public void update() throws IOException, SAXException, ParserConfigurationException { 36 | MibewResponse response = fConnection.request("operator/update.php", "since=" + fSince); 37 | SAXParser sp = SAXParserFactory.newInstance().newSAXParser(); 38 | UpdateHandler handler = new UpdateHandler(); 39 | sp.parse(new ByteArrayInputStream(response.getResponse()), handler); 40 | handleResponse(response, handler); 41 | } 42 | 43 | private void handleResponse(MibewResponse response, UpdateHandler handler) throws IOException { 44 | if (handler.getResponse() == UpdateHandler.UPD_ERROR) { 45 | throw new IOException("Update error: " + handler.getMessage()); 46 | } else if (handler.getResponse() == UpdateHandler.UPD_SUCCESS) { 47 | fSince = handler.getRevision(); 48 | fLastUpdate = handler.getTime(); 49 | List threads = handler.getThreads(); 50 | if (threads != null && threads.size() > 0) { 51 | processUpdate(threads); 52 | } 53 | } else { 54 | throw new IOException("Update error: " + response.getResponseText()); 55 | } 56 | } 57 | 58 | private void processUpdate(List updated) { 59 | for (MibewThread mt : updated) { 60 | MibewThread existing = fThreads.get(mt.getId()); 61 | boolean isClosed = mt.getState().equals("closed"); 62 | if (existing == null) { 63 | if (!isClosed) { 64 | fThreads.put(mt.getId(), mt); 65 | fListener.threadCreated(mt); 66 | } 67 | } else if (isClosed) { 68 | fThreads.remove(mt.getId()); 69 | fListener.threadClosed(existing); 70 | } else { 71 | existing.updateFrom(mt); 72 | fListener.threadChanged(existing); 73 | } 74 | } 75 | } 76 | 77 | public long getLastUpdate() { 78 | return fLastUpdate; 79 | } 80 | 81 | public MibewThread[] getThreads() { 82 | Collection values = fThreads.values(); 83 | return values.toArray(new MibewThread[values.size()]); 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewThread.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | 4 | /** 5 | * @author inspirer 6 | */ 7 | public class MibewThread implements Comparable { 8 | 9 | private final long fId; 10 | private String fState; 11 | private String fClientName = ""; 12 | private String fAgent = ""; 13 | private String fAddress = ""; 14 | private String fFirstMessage = ""; 15 | private boolean fCanOpen = false; 16 | private boolean fCanView = false; 17 | private boolean fCanBan = false; 18 | private String fStateText; 19 | private long fWaitingTime; 20 | 21 | public MibewThread(long id, String state) { 22 | fId = id; 23 | fState = state; 24 | } 25 | 26 | public void updateFrom(MibewThread updated) { 27 | if(fId != updated.fId) { 28 | throw new IllegalArgumentException("different threads"); 29 | } 30 | fState = updated.fState; 31 | fClientName = updated.fClientName; 32 | fAgent = updated.fAgent; 33 | fAddress = updated.fAddress; 34 | fFirstMessage = updated.fFirstMessage; 35 | fCanOpen = updated.fCanOpen; 36 | fCanView = updated.fCanView; 37 | fCanBan = updated.fCanBan; 38 | fStateText = updated.fStateText; 39 | fWaitingTime = updated.fWaitingTime; 40 | } 41 | 42 | public long getId() { 43 | return fId; 44 | } 45 | 46 | public String getState() { 47 | return fState; 48 | } 49 | 50 | public String getStateText() { 51 | return fStateText; 52 | } 53 | 54 | public void setStateText(String stateText) { 55 | fStateText = stateText; 56 | } 57 | 58 | public String getAddress() { 59 | return fAddress; 60 | } 61 | 62 | public void setAddress(String address) { 63 | fAddress = address; 64 | } 65 | 66 | public String getAgent() { 67 | return fAgent; 68 | } 69 | 70 | public void setAgent(String agent) { 71 | fAgent = agent; 72 | } 73 | 74 | public String getClientName() { 75 | return fClientName; 76 | } 77 | 78 | public void setClientName(String clientName) { 79 | fClientName = clientName; 80 | } 81 | 82 | public String getFirstMessage() { 83 | return fFirstMessage; 84 | } 85 | 86 | public void setFirstMessage(String firstMessage) { 87 | fFirstMessage = firstMessage; 88 | } 89 | 90 | public boolean isCanBan() { 91 | return fCanBan; 92 | } 93 | 94 | public void setCanBan(boolean canBan) { 95 | fCanBan = canBan; 96 | } 97 | 98 | public boolean isCanOpen() { 99 | return fCanOpen; 100 | } 101 | 102 | public void setCanOpen(boolean canOpen) { 103 | fCanOpen = canOpen; 104 | } 105 | 106 | public boolean isCanView() { 107 | return fCanView; 108 | } 109 | 110 | public void setCanView(boolean canView) { 111 | fCanView = canView; 112 | } 113 | 114 | public long getWaitingTime() { 115 | return fWaitingTime; 116 | } 117 | 118 | public void setWaitingTime(long value) { 119 | fWaitingTime = value; 120 | } 121 | 122 | public int compareTo(MibewThread o) { 123 | int res = index(this).compareTo(index(o)); 124 | if(res != 0) { 125 | return res; 126 | } 127 | return getClientName().compareTo(o.getClientName()); 128 | } 129 | 130 | private Integer index(MibewThread th) { 131 | if("prio".equals(th.getState())) { 132 | return -1; 133 | } 134 | if("wait".equals(th.getState())) { 135 | return 0; 136 | } 137 | return 1; 138 | } 139 | 140 | @Override 141 | public String toString() { 142 | StringBuilder sb = new StringBuilder(); 143 | boolean isChat = "chat".equals(getState()); 144 | if(isChat) { 145 | sb.append("(chat) "); 146 | } 147 | sb.append(getClientName()); 148 | if(!isCanOpen() && isCanView()) { 149 | sb.append(" (view only)"); 150 | } 151 | if(!isChat) { 152 | sb.append(" - "); 153 | sb.append(formatWaitingTime((System.currentTimeMillis() - getWaitingTime())/1000)); 154 | } 155 | return sb.toString(); 156 | } 157 | 158 | private static String atLeast2(long i) { 159 | return i < 10 ? "0" + i : Long.toString(i); 160 | } 161 | 162 | private static String formatWaitingTime(long time) { 163 | String s = atLeast2(time/60%60) + ":" + atLeast2(time%60); 164 | if(time >= 3600) { 165 | s = atLeast2(time/3600%24) + ":" + s; 166 | if(time >= 24*3600) { 167 | s = time/24/3600 + "d, " + s; 168 | } 169 | } 170 | return s; 171 | } 172 | } 173 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewAgent.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.net.MalformedURLException; 5 | import java.security.NoSuchAlgorithmException; 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | import javax.xml.parsers.ParserConfigurationException; 10 | 11 | import org.xml.sax.SAXException; 12 | 13 | /** 14 | * @author inspirer 15 | */ 16 | public class MibewAgent { 17 | 18 | private final MibewAgentOptions fOptions; 19 | private final MibewAgentListener fListener; 20 | private final MibewUpdateThread fThread; 21 | private volatile boolean started; 22 | 23 | public MibewAgent(MibewAgentOptions options, MibewAgentListener listener) { 24 | fOptions = options; 25 | fListener = listener; 26 | fThread = new MibewUpdateThread(); 27 | started = false; 28 | } 29 | 30 | public synchronized void launch() { 31 | if(!started) { 32 | fThread.start(); 33 | started = true; 34 | } 35 | } 36 | 37 | public synchronized void stop() { 38 | if(started) { 39 | fThread.disconnect(); 40 | started = false; 41 | } 42 | } 43 | 44 | public boolean isOnline() { 45 | return fThread.isOnline(); 46 | } 47 | 48 | protected void logError(String message, Throwable th) { 49 | System.err.println(message); 50 | } 51 | 52 | public MibewAgentOptions getOptions() { 53 | return fOptions; 54 | } 55 | 56 | private class MibewUpdateThread extends Thread { 57 | 58 | private volatile boolean fExiting; 59 | private volatile boolean isOnline = false; 60 | private final Object fSync = new Object(); 61 | 62 | public MibewUpdateThread() { 63 | setName("Mibew Connection thread"); 64 | fExiting = false; 65 | } 66 | 67 | public void disconnect() { 68 | synchronized (fSync) { 69 | fExiting = true; 70 | fSync.notifyAll(); 71 | } 72 | } 73 | 74 | @Override 75 | public void run() { 76 | while(!fExiting) { 77 | try { 78 | connectAndTrack(); 79 | } catch(InterruptedException ex) { 80 | /* ignore */ 81 | } catch(Throwable th) { 82 | logError(th.getMessage(), th); 83 | } 84 | } 85 | setOnline(false); 86 | } 87 | 88 | private void setOnline(boolean online) { 89 | if(isOnline != online) { 90 | isOnline = online; 91 | fListener.onlineStateChanged(online); 92 | } 93 | } 94 | 95 | public boolean isOnline() { 96 | return isOnline; 97 | } 98 | 99 | private void connectAndTrack() throws InterruptedException, UnsupportedEncodingException, NoSuchAlgorithmException, MalformedURLException, ParserConfigurationException, SAXException { 100 | setOnline(false); 101 | MibewConnection conn = new MibewConnection(fOptions.getUrl(), fOptions.getLogin(), fOptions.getPassword()) { 102 | @Override 103 | protected void handleError(String message, Exception ex) { 104 | logError(message, ex); 105 | } 106 | }; 107 | if(!conn.connect()) { 108 | logError("Wrong server, login or password.", null); 109 | interruptableSleep(fOptions.getPollingInterval() * 3); 110 | return; 111 | } 112 | final List createdThreads = new LinkedList(); 113 | MibewTracker mt = new MibewTracker(conn, new MibewTrackerListener(){ 114 | @Override 115 | public void threadCreated(MibewThread thread) { 116 | createdThreads.add(thread); 117 | } 118 | }); 119 | long maxTime = System.currentTimeMillis() + fOptions.getConnectionRefreshTimeout()*1000; 120 | 121 | int errorsCount = 0; 122 | while(!fExiting && (System.currentTimeMillis() < maxTime)) { 123 | try { 124 | createdThreads.clear(); 125 | mt.update(); 126 | fListener.updated(mt.getThreads(), createdThreads.toArray(new MibewThread[createdThreads.size()])); 127 | errorsCount = 0; 128 | setOnline(true); 129 | } catch (Throwable th) { 130 | setOnline(false); 131 | errorsCount++; 132 | logError("not updated", th); 133 | interruptableSleep(errorsCount < 10 ? fOptions.getPollingInterval() / 2 : fOptions.getPollingInterval() * 2); 134 | continue; 135 | } 136 | interruptableSleep(fOptions.getPollingInterval()); 137 | } 138 | 139 | conn.disconnect(); 140 | } 141 | 142 | private void interruptableSleep(long millis) throws InterruptedException { 143 | synchronized (fSync ) { 144 | if(fExiting) { 145 | return; 146 | } 147 | fSync.wait(millis); 148 | } 149 | } 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/MibewConnection.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api; 2 | 3 | import java.io.ByteArrayInputStream; 4 | import java.io.ByteArrayOutputStream; 5 | import java.io.DataOutputStream; 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.io.UnsupportedEncodingException; 9 | import java.net.HttpURLConnection; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | import java.net.URLEncoder; 13 | import java.security.NoSuchAlgorithmException; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | import java.util.Map.Entry; 18 | import java.util.regex.Matcher; 19 | import java.util.regex.Pattern; 20 | 21 | import javax.xml.parsers.ParserConfigurationException; 22 | import javax.xml.parsers.SAXParser; 23 | import javax.xml.parsers.SAXParserFactory; 24 | 25 | import org.mibew.api.handlers.LoginHandler; 26 | 27 | /** 28 | * @author inspirer 29 | */ 30 | public class MibewConnection { 31 | 32 | private static final int REQUEST_TIMEOUT = 5000; 33 | 34 | private final String fUrl; 35 | 36 | private final Map fCookies; 37 | 38 | /** 39 | * @param url Ex: http://yourserver.com/webim/ 40 | * @param login admin 41 | * @param password operators password 42 | */ 43 | public MibewConnection(String url, String login, String password) 44 | throws UnsupportedEncodingException, NoSuchAlgorithmException, 45 | MalformedURLException { 46 | this.fUrl = url; 47 | this.fCookies = new HashMap(); 48 | this.fCookies.put("webim_lite", URLEncoder.encode(login + "," + Utils.md5(Utils.md5(password)), "UTF-8")); 49 | } 50 | 51 | /** 52 | * Connects to the server and tries to login, returns true if successful. 53 | */ 54 | public boolean connect() throws ParserConfigurationException { 55 | try { 56 | MibewResponse response = request("operator/autologin.php", ""); 57 | SAXParser sp = SAXParserFactory.newInstance().newSAXParser(); 58 | LoginHandler handler = new LoginHandler(); 59 | sp.parse(new ByteArrayInputStream(response.getResponse()), handler); 60 | String status = handler.getStatus(); 61 | return status.equals("OK"); 62 | } catch(Exception e) { 63 | handleError(e.getMessage(), e); 64 | return false; 65 | } 66 | } 67 | 68 | public void disconnect() { 69 | } 70 | 71 | /** 72 | * Request server. 73 | * @param suburl ex: operator/update.php 74 | * @param urlParameters post content 75 | */ 76 | public final synchronized MibewResponse request(String suburl, String urlParameters) throws IOException { 77 | HttpURLConnection connection = null; 78 | 79 | try { 80 | connection = (HttpURLConnection) new URL(fUrl+suburl).openConnection(); 81 | connection.setConnectTimeout(REQUEST_TIMEOUT); 82 | connection.setReadTimeout(REQUEST_TIMEOUT); 83 | 84 | connection.setRequestMethod("POST"); 85 | connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); 86 | connection.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes().length)); 87 | if(fCookies.size() > 0) { 88 | StringBuilder sb = new StringBuilder(); 89 | for(Entry cookie : fCookies.entrySet()) { 90 | if(sb.length() > 0) { 91 | sb.append("; "); 92 | } 93 | sb.append(cookie.getKey()+"="+cookie.getValue()); 94 | } 95 | connection.addRequestProperty("Cookie", sb.toString()); 96 | } 97 | 98 | 99 | connection.setUseCaches(false); 100 | connection.setDoInput(true); 101 | connection.setDoOutput(true); 102 | 103 | // create request 104 | DataOutputStream wr = new DataOutputStream(connection.getOutputStream()); 105 | wr.writeBytes(urlParameters); 106 | wr.flush(); 107 | wr.close(); 108 | 109 | // read response 110 | InputStream is = connection.getInputStream(); 111 | int len = connection.getContentLength(); 112 | ByteArrayOutputStream buffer = new ByteArrayOutputStream(len < 256 ? 256 : len); 113 | byte b[] = new byte[1024]; 114 | int size = 0; 115 | while((size=is.read(b)) >= 0) { 116 | buffer.write(b, 0, size); 117 | } 118 | is.close(); 119 | 120 | // load cookies 121 | List cookies = connection.getHeaderFields().get("Set-Cookie"); 122 | if(cookies != null) { 123 | for(String cookie : cookies) { 124 | Matcher matcher = COOKIESET.matcher(cookie); 125 | if(matcher.find()) { 126 | String name = matcher.group(1); 127 | String value = matcher.group(2); 128 | fCookies.put(name, value); 129 | } 130 | } 131 | } 132 | return new MibewResponse(connection.getResponseCode(), buffer.toByteArray()); 133 | } catch (Exception e) { 134 | if(e instanceof IOException) { 135 | throw (IOException)e; 136 | } 137 | throw new IOException("cannot connect: " + e.getMessage()); 138 | } finally { 139 | if (connection != null) { 140 | connection.disconnect(); 141 | } 142 | } 143 | } 144 | 145 | protected void handleError(String message, Exception ex) { 146 | System.err.println(message); 147 | } 148 | 149 | private static Pattern COOKIESET = Pattern.compile("\\A(\\w+)=([^;]+);"); 150 | } 151 | -------------------------------------------------------------------------------- /src/org.mibew.notifier/src/org/mibew/notifier/MibewTray.java: -------------------------------------------------------------------------------- 1 | package org.mibew.notifier; 2 | 3 | import org.eclipse.swt.SWT; 4 | import org.eclipse.swt.graphics.Image; 5 | import org.eclipse.swt.widgets.*; 6 | import org.eclipse.swt.widgets.Event; 7 | import org.eclipse.swt.widgets.Menu; 8 | import org.eclipse.swt.widgets.MenuItem; 9 | import org.mibew.api.MibewAgent; 10 | import org.mibew.api.MibewAgentListener; 11 | import org.mibew.api.MibewThread; 12 | 13 | import java.awt.*; 14 | import java.io.IOException; 15 | 16 | public class MibewTray extends MibewAgentListener { 17 | 18 | private volatile boolean isStopped = false; 19 | 20 | private Image fImageOn; 21 | private Image fImageOff; 22 | private TrayItem fItem; 23 | private Menu fMenu; 24 | private MibewAgent fAgent; 25 | 26 | void initTray(Display display, Shell shell, MibewAgent agent) { 27 | fAgent = agent; 28 | fImageOn = new Image(display, getClass().getClassLoader().getResourceAsStream("org/mibew/notifier/tray_on.png")); 29 | fImageOff = new Image(display, getClass().getClassLoader().getResourceAsStream("org/mibew/notifier/tray_off.png")); 30 | 31 | final Tray tray = display.getSystemTray(); 32 | if (tray == null) { 33 | System.out.println("The system tray is not available"); 34 | } else { 35 | fItem = new TrayItem(tray, SWT.NONE); 36 | fItem.setToolTipText("SWT TrayItem"); 37 | fItem.addListener(SWT.Show, new Listener() { 38 | public void handleEvent(Event event) { 39 | System.out.println("show"); 40 | } 41 | }); 42 | fItem.addListener(SWT.Hide, new Listener() { 43 | public void handleEvent(Event event) { 44 | System.out.println("hide"); 45 | } 46 | }); 47 | fMenu = new Menu(shell, SWT.POP_UP); 48 | for (int i = 0; i < 8; i++) { 49 | MenuItem mi = new MenuItem(fMenu, SWT.PUSH); 50 | mi.setText("Item" + i); 51 | mi.addListener(SWT.Selection, new Listener() { 52 | public void handleEvent(Event event) { 53 | System.out.println("selection " + event.widget); 54 | } 55 | }); 56 | } 57 | Listener listener = new Listener() { 58 | public void handleEvent(Event event) { 59 | fMenu.setVisible(true); 60 | } 61 | }; 62 | fItem.addListener(SWT.MenuDetect, listener); 63 | fItem.addListener(SWT.Selection, listener); 64 | fItem.setImage(fImageOff); 65 | } 66 | shell.setBounds(50, 50, 300, 200); 67 | //shell.open(); 68 | } 69 | 70 | @Override 71 | protected synchronized void onlineStateChanged(final boolean isOnline) { 72 | if(isStopped) 73 | return; 74 | 75 | Display.getDefault().asyncExec(new Runnable() { 76 | public void run() { 77 | if(isStopped) 78 | return; 79 | 80 | fItem.setImage(isOnline ? fImageOn : fImageOff); 81 | } 82 | }); 83 | } 84 | 85 | @Override 86 | protected synchronized void updated(final MibewThread[] all, final MibewThread[] created) { 87 | if(isStopped) 88 | return; 89 | 90 | Display.getDefault().asyncExec(new Runnable() { 91 | public void run() { 92 | if(isStopped) 93 | return; 94 | 95 | for (MenuItem menuItem : fMenu.getItems()) { 96 | menuItem.dispose(); 97 | } 98 | for(MibewThread m : all) { 99 | MenuItem mi = new MenuItem(fMenu, SWT.PUSH); 100 | mi.setText(m.getClientName()); 101 | mi.addListener(SWT.Selection, new LinkActionListener(null, fAgent.getOptions().getUrl() + "operator/agent.php?thread=" + m.getId())); 102 | } 103 | 104 | if(created.length == 1) { 105 | fItem.setToolTipText(created[0].getClientName() + "\n" + created[0].getFirstMessage()); 106 | } else if(created.length > 1) { 107 | fItem.setToolTipText("New " + created.length + " visitors"); 108 | } 109 | 110 | } 111 | }); 112 | } 113 | 114 | synchronized void dispose() { 115 | isStopped = true; 116 | fItem.dispose(); 117 | fImageOn.dispose(); 118 | fImageOff.dispose(); 119 | } 120 | 121 | private static class LinkActionListener implements Listener { 122 | private final Shell shell; 123 | private final String link; 124 | 125 | public LinkActionListener(Shell shell, String link) { 126 | this.shell = shell; 127 | this.link = link; 128 | } 129 | 130 | public void handleEvent(Event event) { 131 | try { 132 | BrowserUtil.openURL(link); 133 | } catch (IOException e1) { 134 | MessageBox messageBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR); 135 | messageBox.setText("Browser error"); //$NON-NLS-1$ 136 | messageBox.setMessage(e1.getMessage()); 137 | messageBox.open(); 138 | } 139 | } 140 | }} 141 | -------------------------------------------------------------------------------- /src/org.mibew.api/src/org/mibew/api/handlers/UpdateHandler.java: -------------------------------------------------------------------------------- 1 | package org.mibew.api.handlers; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.Stack; 6 | 7 | import org.mibew.api.MibewThread; 8 | import org.xml.sax.Attributes; 9 | import org.xml.sax.SAXException; 10 | import org.xml.sax.helpers.DefaultHandler; 11 | 12 | /** 13 | * @author inspirer 14 | */ 15 | public class UpdateHandler extends DefaultHandler { 16 | 17 | public static final int UPD_ERROR = 1; 18 | public static final int UPD_SUCCESS = 2; 19 | 20 | private static final int STATE_READING_THREADS = 1; 21 | 22 | private int fResponse = 0; 23 | private String fMessage = ""; 24 | private long fRevision; 25 | private long fTime; 26 | private List fUpdated; 27 | 28 | private int state = 0; 29 | 30 | private Stack fPath = new Stack(); 31 | private MibewThread fCurrentThread; 32 | 33 | @Override 34 | public void startElement(String uri, String localName, String name, 35 | Attributes attributes) throws SAXException { 36 | try { 37 | if (fPath.size() == 0) { 38 | if (name.equals("error")) { 39 | fResponse = UPD_ERROR; 40 | } else if (name.equals("update")) { 41 | fResponse = UPD_SUCCESS; 42 | } else { 43 | throw new SAXException("unknown root element: " + name); 44 | } 45 | } else if(fResponse == UPD_SUCCESS) { 46 | if(fPath.size() == 1) { 47 | if (name.equals("threads")) { 48 | fTime = Long.parseLong(attributes.getValue("time")); 49 | fRevision = Long.parseLong(attributes.getValue("revision")); 50 | fUpdated = new ArrayList(); 51 | state = STATE_READING_THREADS; 52 | } 53 | /* ignore others for compatibility reasons */ 54 | } 55 | if (fPath.size() == 2 && state == STATE_READING_THREADS && name.equals("thread")) { 56 | long id = Long.parseLong(attributes.getValue("id")); 57 | String stateid = attributes.getValue("stateid"); 58 | fCurrentThread = new MibewThread(id, stateid); 59 | 60 | if(!stateid.equals("closed")) { 61 | fCurrentThread.setStateText(attributes.getValue("state")); 62 | fCurrentThread.setCanOpen(booleanAttribute(attributes.getValue("canopen"))); 63 | fCurrentThread.setCanView(booleanAttribute(attributes.getValue("canview"))); 64 | fCurrentThread.setCanBan(booleanAttribute(attributes.getValue("canban"))); 65 | } 66 | 67 | } 68 | } 69 | } catch (NumberFormatException ex) { 70 | throw new SAXException(ex.getMessage()); 71 | } 72 | fPath.push(name); 73 | } 74 | 75 | private boolean booleanAttribute(String value) { 76 | if(value != null && value.equals("true")) { 77 | return true; 78 | } 79 | return false; 80 | } 81 | 82 | private long longValue(String value) throws SAXException { 83 | try { 84 | return Long.parseLong(value); 85 | } catch(NumberFormatException ex) { 86 | throw new SAXException(ex); 87 | } 88 | } 89 | 90 | @Override 91 | public void endElement(String uri, String localName, String name) 92 | throws SAXException { 93 | fPath.pop(); 94 | if (fResponse == UPD_SUCCESS && fPath.size() == 2 && state == STATE_READING_THREADS && name.equals("thread")) { 95 | fUpdated.add(fCurrentThread); 96 | fCurrentThread = null; 97 | } else if(fPath.size() == 1 && state == STATE_READING_THREADS) { 98 | state = 0; 99 | } 100 | } 101 | 102 | @Override 103 | public void characters(char[] ch, int start, int length) 104 | throws SAXException { 105 | if (fResponse == UPD_ERROR) { 106 | String current = fPath.peek(); 107 | if (fPath.size() != 2 || !current.equals("descr")) { 108 | throw new SAXException("unexpected characters"); 109 | } 110 | fMessage += new String(ch, start, length); 111 | } else if (fResponse == UPD_SUCCESS && fCurrentThread != null) { 112 | if(fCurrentThread == null || fPath.size() != 4) { 113 | throw new SAXException("unknown characters"); 114 | } 115 | 116 | String subvar = fPath.peek(); 117 | String value = new String(ch, start, length); 118 | if("name".equals(subvar)) { 119 | fCurrentThread.setClientName(fCurrentThread.getClientName() + value); 120 | } else if("addr".equals(subvar)) { 121 | fCurrentThread.setAddress(fCurrentThread.getAddress() + value); 122 | } else if("message".equals(subvar)) { 123 | fCurrentThread.setFirstMessage(fCurrentThread.getFirstMessage() + value); 124 | } else if("agent".equals(subvar)) { 125 | fCurrentThread.setAgent(fCurrentThread.getAgent() + value); 126 | } else if("modified".equals(subvar)) { 127 | if(fCurrentThread.getWaitingTime() != 0) { 128 | throw new SAXException("error: waiting time is already set"); 129 | } 130 | fCurrentThread.setWaitingTime(longValue(value) - fTime + System.currentTimeMillis()); 131 | } 132 | 133 | // TODO 134 | 135 | } else { 136 | throw new SAXException("unexpected characters: no root"); 137 | } 138 | } 139 | 140 | public int getResponse() { 141 | return fResponse; 142 | } 143 | 144 | public String getMessage() { 145 | return fMessage; 146 | } 147 | 148 | public long getTime() { 149 | return fTime; 150 | } 151 | 152 | public long getRevision() { 153 | return fRevision; 154 | } 155 | 156 | public List getThreads() { 157 | return fUpdated; 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /src/.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | --------------------------------------------------------------------------------