diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..fc2c921 --- /dev/null +++ b/.classpath @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..91913be --- /dev/null +++ b/.project @@ -0,0 +1,15 @@ + + + iJab + iJab project + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.jdt.core.javanature + + diff --git a/iJab-compile.cmd b/iJab-compile.cmd new file mode 100644 index 0000000..ccaf672 --- /dev/null +++ b/iJab-compile.cmd @@ -0,0 +1 @@ +@java -Xmx256M -cp "%~dp0\src;%~dp0\bin;D:/gwt-windows-1.5.3/gwt-user.jar;D:/gwt-windows-1.5.3/gwt-dev-windows.jar" com.google.gwt.dev.GWTCompiler -out "%~dp0\www" %* com.anzsoft.iJab \ No newline at end of file diff --git a/iJab-shell.cmd b/iJab-shell.cmd new file mode 100644 index 0000000..a87b228 --- /dev/null +++ b/iJab-shell.cmd @@ -0,0 +1 @@ +@java -Xmx256M -cp "%~dp0\src;%~dp0\bin;D:/gwt-windows-1.5.3/gwt-user.jar;D:/gwt-windows-1.5.3/gwt-dev-windows.jar" com.google.gwt.dev.GWTShell -port auto -out "%~dp0\www" %* com.anzsoft.iJab/iJab.html \ No newline at end of file diff --git a/iJab.launch b/iJab.launch new file mode 100644 index 0000000..2032d54 --- /dev/null +++ b/iJab.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/anzsoft/client/JabberApp.java b/src/com/anzsoft/client/JabberApp.java new file mode 100644 index 0000000..2e4a51f --- /dev/null +++ b/src/com/anzsoft/client/JabberApp.java @@ -0,0 +1,405 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client; + +import java.util.HashMap; +import java.util.Map; + +import com.allen_sauer.gwt.voices.client.Sound; +import com.allen_sauer.gwt.voices.client.SoundController; +import com.anzsoft.client.XMPP.Debugger; +import com.anzsoft.client.XMPP.PresenceShow; +import com.anzsoft.client.XMPP.XmppConnection; +import com.anzsoft.client.XMPP.XmppError; +import com.anzsoft.client.XMPP.XmppEventAdapter; +import com.anzsoft.client.XMPP.XmppFactory; +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppMessageListener; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppPresenceListener; +import com.anzsoft.client.XMPP.XmppUserSettings; +import com.anzsoft.client.XMPP.XmppUserSettings.AuthType; +import com.anzsoft.client.XMPP.impl.JsJacFactory; +import com.anzsoft.client.XMPP.log.DebugPanel; +import com.anzsoft.client.XMPP.log.GWTLoggerOutput; +import com.anzsoft.client.XMPP.mandioca.XmppContact; +import com.anzsoft.client.XMPP.mandioca.XmppContactStatus; +import com.anzsoft.client.XMPP.mandioca.XmppRosterListener; +import com.anzsoft.client.XMPP.mandioca.XmppSession; +import com.anzsoft.client.ui.ChatWindow; +import com.anzsoft.client.ui.LoginDialog; +import com.anzsoft.client.ui.MainWindow; +import com.anzsoft.client.ui.RosterPanel; +import com.extjs.gxt.ui.client.widget.MessageBox; +import com.extjs.gxt.ui.client.widget.Window; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.RootPanel; +public class JabberApp +{ + public interface LoginListener + { + public void onLogined(); + } + private static JabberApp _instance = null; + private XmppSession session = null; + private XmppConnection connection = null; + private XmppPresenceListener presenceListener = null; + private XmppEventAdapter eventAdapter = null; + private XmppMessageListener messageListener = null; + private LoginListener loginListener = null; + + private boolean silent = false; + //private boolean serviceMode = false; + private String httpBind = "/http-bind/"; + private String host = "samespace.anzsoft.com"; + int port = 5222; + private String domain = "anzsoft.com"; + private String authType = "sasl"; + + private Window debugWindow = null; + private DebugPanel debugPanel = null; + final boolean Debug = false; + + private LoginDialog loginDlg = new LoginDialog(); + + + static iJabConstants constants = null; + private RosterPanel rosterPanel = null; + private MainWindow mainWindow = null; + private Map contactDatas = null; + private HashMap statusMap = new HashMap(); + + public static JabberApp instance() + { + if(_instance == null) + _instance = new JabberApp(); + return _instance; + } + + private JabberApp() + { + initParament(); + } + + private native void initParament() + /*-{ + this.@com.anzsoft.client.JabberApp::httpBind = $wnd.httpBind; + this.@com.anzsoft.client.JabberApp::host = $wnd.host; + this.@com.anzsoft.client.JabberApp::port = $wnd.port; + this.@com.anzsoft.client.JabberApp::domain = $wnd.domain; + this.@com.anzsoft.client.JabberApp::authType = $wnd.authType; + }-*/; + + + + public void run(boolean silent) + { + this.silent = silent; + doLogin(); + } + + public void run(final String userName,final String password,boolean slient,LoginListener loginListener) + { + this.silent = slient; + this.loginListener = loginListener; + onLogin(userName,password,null); + } + + public void doLogin() + { + if(mainWindow != null) + { + mainWindow.close(); + mainWindow = null; + } + + if(debugWindow != null) + { + debugWindow.close(); + debugWindow = null; + } + + if(loginDlg == null) + loginDlg = new LoginDialog(); + loginDlg.show(); + } + + public void onLogin(final String user,final String pass,XmppEventAdapter eventAdapter) + { + initConnection(); + if(eventAdapter != null) + connection.addEventListener(eventAdapter); + session = new XmppSession(connection, true); + XmppUserSettings userSetting = new XmppUserSettings(host,port,domain, user, pass, AuthType.fromString(authType)); + session.login(userSetting); + session.getUser().getRoster().addRosterListener(createRosterListener()); + } + + public void onLogin(final String host,final int port,final String domain,boolean sasl,final String user,final String pass,XmppEventAdapter eventAdapter) + { + initConnection(); + if(eventAdapter != null) + connection.addEventListener(eventAdapter); + session = new XmppSession(connection, true); + XmppUserSettings userSetting = new XmppUserSettings(host,port,domain, user, pass, XmppUserSettings.SASL); + session.login(userSetting); + session.getUser().getRoster().addRosterListener(createRosterListener()); + } + + public void logout() + { + ChatWindow.clear(); + session.logout(); + } + + public String getContactNick(final String bareJid) + { + if(silent) + { + XmppContact contact = contactDatas.get(bareJid); + if(contact != null) + return contact.getName(); + else + return ""; + } + else + return rosterPanel.getContactData(bareJid).get("alias"); + } + + public String getContactStatusText(final String bareJid) + { + if(silent) + { + XmppContactStatus status = statusMap.get(bareJid); + if(status!=null) + return status.status(); + else + return ""; + } + else + return rosterPanel.getContactData(bareJid).get("statustext"); + } + + public XmppSession getSession() + { + return this.session; + } + + private void createDebugWindow() + { + if(!Debug) + return; + debugWindow = new Window(); + debugWindow.setLayout(new FitLayout()); + + debugPanel = new DebugPanel(); + debugWindow.add(debugPanel); + + debugWindow.setWidth(500); + debugWindow.setHeight(300); + debugWindow.show(); + debugWindow.setTitle("Debugger"); + Debugger.debug(connection,debugPanel); + } + + public static iJabConstants getConstants() + { + if(constants == null) + constants = (iJabConstants)GWT.create(iJabConstants.class); + return constants; + } + + private void initConnection() + { + XmppFactory xmppFactory = JsJacFactory.getInstance(); + connection = xmppFactory.createBindingConnection(httpBind, 2000, GWTLoggerOutput.instance); + connection.addEventListener(createEventAdapter()); + connection.addPreseceListener(createPresenceListener()); + connection.addMessageListener(createMessageListener()); + createDebugWindow(); + } + + private XmppEventAdapter createEventAdapter() + { + eventAdapter = new XmppEventAdapter() + { + public void onConnect() + { + session.getUser().getRoster().sendQuery(); + } + + public void onDisconnect() + { + if(!silent) + doLogin(); + } + + public void onError(final XmppError error) + { + System.out.println("onError..."); + if(!silent) + doLogin(); + } + + public void onResume() + { + if(!silent) + doLogin(); + } + + public void onStatusChanged(final String status) + { + System.out.println("OnStatusChanged.................."); + System.out.println(status); + } + }; + return eventAdapter; + } + + private XmppPresenceListener createPresenceListener() + { + presenceListener = new XmppPresenceListener() + { + public void onPresenceReceived(XmppPresence presence) + { + try + { + XmppID id = presence.getFromID(); + String jid = id.toStringNoResource(); + String show = new String(""); + PresenceShow presenceShow = presence.getShow(); + if(presenceShow!=null) + show = presenceShow.toString(); + String statusString = presence.getStatus(); + int priority = presence.getPriority(); + boolean avaiable = true; + String type = presence.getType(); + if(type != null&&!type.isEmpty()) + { + if(type.equalsIgnoreCase("unavailable")) + avaiable = false; + } + XmppContactStatus status = new XmppContactStatus(show,statusString,priority,avaiable); + if(rosterPanel != null&&!silent) + rosterPanel.updateContactStatus(jid, status); + + if(silent) + statusMap.put(jid, status); + } + catch(Exception e) + { + MessageBox.alert(e.toString(), null, null); + } + } + + public void onPresenceSent(XmppPresence presence) + { + + } + + }; + return presenceListener; + } + + private XmppMessageListener createMessageListener() + { + messageListener = new XmppMessageListener() + { + public void onMessageReceived(XmppMessage message) + { + ChatWindow window = ChatWindow.openChat(message.getFromID()); + + SoundController soundController = new SoundController(); + Sound sound = soundController.createSound(Sound.MIME_TYPE_AUDIO_MPEG, + "sound/im.wav"); + sound.play(); + + window.addMessage(getContactNick(message.getFromID().toStringNoResource()), message.getBody(),false); + } + public void onMessageSent(XmppMessage message) + { + + } + + }; + return messageListener; + } + + private XmppRosterListener createRosterListener() + { + XmppRosterListener listener = new XmppRosterListener() + { + + public void onRoster(Map contacts) + { + if(silent) + contactDatas = contacts; + else + try + { + mainWindow = new MainWindow(session); + rosterPanel = mainWindow.getRosterPanel(); + rosterPanel.setRoster(contacts); + mainWindow.layout(); + loginDlg.close(); + loginDlg = null; + + mainWindow.show(); + + RootPanel root = RootPanel.get(); + int x = root.getOffsetWidth() - mainWindow.getOffsetWidth(); + mainWindow.setPosition(x, 0); + } + catch(Exception e) + { + MessageBox.alert(e.toString(), null, null); + } + + if(loginListener != null) + loginListener.onLogined(); + } + }; + return listener; + } + + public String getAvatarUrl(final String bareJid) + { + if(silent) + { + XmppContact contact = contactDatas.get(bareJid); + if(contact!=null) + return contact.getAvatar(); + else + return "images/default_avatar.png"; + } + else + return rosterPanel.getAvatarUrl(bareJid); + } + + public boolean connected() + { + if(connection == null) + return false; + return connection.isConnected(); + } +} diff --git a/src/com/anzsoft/client/MyMessages_zh.properties b/src/com/anzsoft/client/MyMessages_zh.properties new file mode 100644 index 0000000..0207559 --- /dev/null +++ b/src/com/anzsoft/client/MyMessages_zh.properties @@ -0,0 +1,101 @@ +# UpdateManager +updateManager_indicatorText=
???...
+ +# Grid +grid_ddText={0} ???? + +# TabPanelItem +tabPanelItem_closeText=??????? + +# Field +field_invalidText=???????? + +# LoadMask +loadMask_msg=???... + +# MessageBox +messageBox_ok=\u786e\u5b9a +messageBox_cancel=\u53d6\u6d88 +messageBox_yes=\u662f +messageBox_no=\u5426 +messageBox_close=\u5173\u95ed + +# DatePicker +datePicker_todayText=?? +datePicker_minText=?????????? +datePicker_maxText=?????????? +datePicker_disabledDaysText= +datePicker_disabledDatesText= +datePicker_nextText=???? +datePicker_prevText=???? +datePicker_monthYearText=?????? +datePicker_todayTip={0} +datePicker_okText= ?? +datePicker_cancelText=?? +datePicker_startDay=0 + +# PagingToolBar +pagingToolBar_beforePageText=? +pagingToolBar_afterPageText=?? {0} +pagingToolBar_firstText=??? +pagingToolBar_prevText=??? +pagingToolBar_nextText=??? +pagingToolBar_lastText=???? +pagingToolBar_refreshText=?? +pagingToolBar_displayMsg=??? {2} ?? {0} - {1} +pagingToolBar_emptyMsg=??????? + +# TextField +textField_minLengthText=???????? {0} +textField_maxLengthText=???????? {0} +textField_blankText=?????? +textField_regexText= +textField_emptyText= + +# NumberField +numberField_minText=??????? {0} +numberField_maxText=??????? {0} +numberField_nanText={0} ???????? + +# DateField +dateField_disabledDaysText=?? +dateField_disabledDatesText=?? +dateField_minText=????????? {0} ?? +dateField_maxText=????????? {0} ?? +dateField_invalidText={0} ????? - ????? {1} +#dateField_format=?/?/? +#dateField_altFormats=?/?/?(??)|?-?-?|?-?-?(??)|?/?|?-?|??|???|???(??)|?|?(??)-?-? +dateField_format=m/d/y +dateField_altFormats=m/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d + +# ComboBox +comboBox_loading=???... + +# TimeField +timeField_minText=????????? {0} ??????? +timeField_maxText=????????? {0} ??????? +timeField_invalidText={0} ????? +timeField_format=g:i A +timeField_altFormats=g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H + +#GridView +gridView_sortAscText=???? +gridView_sortDescText=???? +gridView_columnsText=? + +#GroupingView +groupingView_emptyGroupText=(?) +groupingView_groupByText=????? +groupingView_showGroupsText=????? + +# PropertyColumnModel +propertyColumnModel_nameText=?? +propertyColumnModel_valueText=? + +# BorderLayout +borderLayout_splitTip=???????????. +borderLayout_collapsibleSplitTip=???????????. ???????. + +# ThemeSelector +themeSelector_blueTheme=???? +themeSelector_grayTheme=???? \ No newline at end of file diff --git a/src/com/anzsoft/client/ServiceData.java b/src/com/anzsoft/client/ServiceData.java new file mode 100644 index 0000000..d8a6a66 --- /dev/null +++ b/src/com/anzsoft/client/ServiceData.java @@ -0,0 +1,53 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client; + +import com.google.gwt.core.client.JavaScriptObject; + +public class ServiceData extends JavaScriptObject +{ + static class Service extends JavaScriptObject + { + protected Service() + { + + } + + public final native String getName() + /*-{ + return this.name; + }-*/; + + public final native String getJid() + /*-{ + return this.jid; + }-*/; + } + + protected ServiceData() + { + + } + + public final native int length() /*-{ return this.length; }-*/; + public final native E get(int i) /*-{ return this[i]; }-*/; +} diff --git a/src/com/anzsoft/client/XMPP/Debugger.java b/src/com/anzsoft/client/XMPP/Debugger.java new file mode 100644 index 0000000..67168f9 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/Debugger.java @@ -0,0 +1,61 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +import com.anzsoft.client.XMPP.log.LoggerEventListener; +import com.anzsoft.client.XMPP.log.LoggerInfoQueryListener; +import com.anzsoft.client.XMPP.log.LoggerMessageListener; +import com.anzsoft.client.XMPP.log.LoggerOuput; +import com.anzsoft.client.XMPP.log.LoggerPacketListener; +import com.anzsoft.client.XMPP.log.LoggerPresenceListener; +import com.google.gwt.core.client.GWT; + +public class Debugger { + public static LoggerOuput logger; + + // default logger + static { + logger = new LoggerOuput () { + public void log(final String text) { + GWT.log(text, null); + } + }; + } + + public static void initLogger(final LoggerOuput logger) { + Debugger.logger = logger; + } + + public static void log(final String text) { + logger.log(text); + } + + public static void debug(final XmppConnection connection, final LoggerOuput logger) { + connection.addPacketListener(new LoggerPacketListener(logger)); + connection.addEventListener(new LoggerEventListener(logger)); + connection.addMessageListener(new LoggerMessageListener(logger)); + connection.addInfoQueryListener(new LoggerInfoQueryListener(logger)); + connection.addPreseceListener(new LoggerPresenceListener(logger)); + } + +} diff --git a/src/com/anzsoft/client/XMPP/HandlerCollection.java b/src/com/anzsoft/client/XMPP/HandlerCollection.java new file mode 100644 index 0000000..65b68ae --- /dev/null +++ b/src/com/anzsoft/client/XMPP/HandlerCollection.java @@ -0,0 +1,65 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + + +import java.util.ArrayList; +import java.util.Iterator; + +public class HandlerCollection { + private static final ArrayList EMPTY_LIST = new ArrayList(); + + private ArrayList handlers; + + public void add(Object handler) { + handlers = (handlers == null) ? new ArrayList() : new ArrayList(handlers); + handlers.add(handler); + } + + public void remove(Object handler) { + if (handlers == null || handler == null) { + return; + } + + Iterator it = handlers.iterator(); + handlers = new ArrayList(); + while (it.hasNext()) { + Object obj = it.next(); + if (obj != handler) { + handlers.add(obj); + } + } + } + + public Iterator iterator() { + return (handlers == null) ? EMPTY_LIST.iterator() + : handlers.iterator(); + } + + public int size() { + return (handlers == null) ? 0 : handlers.size(); + } + + public void clear() { + handlers = null; + } +} \ No newline at end of file diff --git a/src/com/anzsoft/client/XMPP/PresenceShow.java b/src/com/anzsoft/client/XMPP/PresenceShow.java new file mode 100644 index 0000000..b3e6ad3 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/PresenceShow.java @@ -0,0 +1,60 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + +import java.util.HashMap; +import java.util.Map; + +public class PresenceShow { + public static final PresenceShow CHAT = new PresenceShow("chat"); + public static final PresenceShow AWAY = new PresenceShow("away"); + public static final PresenceShow NOT_AVAILABLE= new PresenceShow("xa"); + public static final PresenceShow DO_NOT_DISTURB = new PresenceShow("dnd"); + private static final Map shows; + + static { + shows = new HashMap(); + shows.put(CHAT.getID(), CHAT); + shows.put(AWAY.getID(), AWAY); + shows.put(NOT_AVAILABLE.getID(), NOT_AVAILABLE); + shows.put(DO_NOT_DISTURB.getID(), DO_NOT_DISTURB); + } + private final String token; + + private PresenceShow(final String token) { + this.token = token; + } + public String getID() { + return token; + } + public String toString() { + return token; + } + public static PresenceShow emptyShow() + { + return new PresenceShow(""); + } + + public static PresenceShow get(final String showID) { + return (PresenceShow) shows.get(showID); + } +} \ No newline at end of file diff --git a/src/com/anzsoft/client/XMPP/XmppConnection.java b/src/com/anzsoft/client/XMPP/XmppConnection.java new file mode 100644 index 0000000..74fedc4 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppConnection.java @@ -0,0 +1,51 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + +public interface XmppConnection { + + void addEventListener(XmppEventListener eventListener); + + void addInfoQueryListener(XmppInfoQueryListener infoQueryListener); + + void addMessageListener(XmppMessageListener messageListener); + + void addPacketListener(XmppPacketListener packetListener); + + void addPreseceListener(XmppPresenceListener presenceListener); + + void connect(XmppUserSettings user); + + void disconnect(); + + XmppFactory getFactory(); + + void resume(); + + void send(XmppPacket packet); + + void send(XmppPacket packet, XmppPacketListener listener); + + void addConnectionListener(XmppConnectionListener xmppConnectionListener); + + boolean isConnected(); +} diff --git a/src/com/anzsoft/client/XMPP/XmppConnectionListener.java b/src/com/anzsoft/client/XMPP/XmppConnectionListener.java new file mode 100644 index 0000000..69c4ef6 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppConnectionListener.java @@ -0,0 +1,27 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + +public interface XmppConnectionListener { + void onConnect(); + void onDisconnect(); +} diff --git a/src/com/anzsoft/client/XMPP/XmppEntryPoint.java b/src/com/anzsoft/client/XMPP/XmppEntryPoint.java new file mode 100644 index 0000000..66ffb62 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppEntryPoint.java @@ -0,0 +1,30 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +import com.google.gwt.core.client.EntryPoint; + +public class XmppEntryPoint implements EntryPoint{ + public void onModuleLoad() { + } +} diff --git a/src/com/anzsoft/client/XMPP/XmppError.java b/src/com/anzsoft/client/XMPP/XmppError.java new file mode 100644 index 0000000..a4ac59a --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppError.java @@ -0,0 +1,26 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + +public interface XmppError { + +} diff --git a/src/com/anzsoft/client/XMPP/XmppEventAdapter.java b/src/com/anzsoft/client/XMPP/XmppEventAdapter.java new file mode 100644 index 0000000..c816947 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppEventAdapter.java @@ -0,0 +1,41 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + + +public class XmppEventAdapter implements XmppEventListener { + public void onConnect() { + } + + public void onDisconnect() { + } + + public void onError(final XmppError error) { + } + + public void onResume() { + } + + public void onStatusChanged(final String status) { + } + +} diff --git a/src/com/anzsoft/client/XMPP/XmppEventListener.java b/src/com/anzsoft/client/XMPP/XmppEventListener.java new file mode 100644 index 0000000..002e8e1 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppEventListener.java @@ -0,0 +1,31 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP; + + +public interface XmppEventListener { + public void onConnect(); + public void onDisconnect(); + public void onResume(); + public void onStatusChanged(String status); + public void onError(XmppError error); +} diff --git a/src/com/anzsoft/client/XMPP/XmppFactory.java b/src/com/anzsoft/client/XMPP/XmppFactory.java new file mode 100644 index 0000000..61750a4 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppFactory.java @@ -0,0 +1,35 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +import com.anzsoft.client.XMPP.log.LoggerOuput; + + + +public interface XmppFactory { + XmppMessage createMessage(); + XmppPresence createRoomPresence(); + XmppConnection createBindingConnection(String httpBase, int pollInterval, LoggerOuput logger); + XmppPresence createPresence(); + XmppQuery createQuery(); +} diff --git a/src/com/anzsoft/client/XMPP/XmppID.java b/src/com/anzsoft/client/XMPP/XmppID.java new file mode 100644 index 0000000..4de8119 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppID.java @@ -0,0 +1,135 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +// var JSJACJID_FORBIDDEN = ['"',' ','&','\'','/',':','<','>','@']; + +public class XmppID { + private String domain; + private String node; + private String resource; + + public XmppID(final String node, final String domain, final String resource) { + this.node = node; + this.domain = domain; + this.resource = resource; + } + + public String getDomain() { + return domain; + } + + public void setDomain(final String domain) { + this.domain = domain; + } + + public String getNode() { + return node; + } + + public void setNode(final String node) { + this.node = node; + } + + public String getResource() { + return resource; + } + + public void setResource(final String resource) { + this.resource = resource; + } + + public String toString() { + return render(node, domain, resource); + } + + public static XmppID parseId(String sid) { + String node = null; + String domain; + String resource = null; + + if (sid == null) { + return null; + } + + int indexOfAt = sid.indexOf('@'); + if (indexOfAt > 0) { + node = sid.substring(0, indexOfAt); + sid = sid.substring(indexOfAt + 1); + } + int indexOfSlash = sid.indexOf('/'); + if (indexOfSlash > 0) { + resource = sid.substring(indexOfSlash + 1); + sid = sid.substring(0, indexOfSlash); + } + domain = sid; + return new XmppID(node, domain, resource); + } + + + public static String render(final String node, final String domain, final String resource) { + String nodeString = node != null ? node + "@" : ""; + String resString = resource != null ? "/" + resource : ""; + return nodeString + domain + resString; + } + + public String toStringNoResource() { + return render(node, domain, null); + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((domain == null) ? 0 : domain.hashCode()); + result = prime * result + ((node == null) ? 0 : node.hashCode()); + result = prime * result + ((resource == null) ? 0 : resource.hashCode()); + return result; + } + + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + final XmppID other = (XmppID) obj; + if (domain == null) { + if (other.domain != null) + return false; + } else if (!domain.equals(other.domain)) + return false; + if (node == null) { + if (other.node != null) + return false; + } else if (!node.equals(other.node)) + return false; + if (resource == null) { + if (other.resource != null) + return false; + } else if (!resource.equals(other.resource)) + return false; + return true; + } + + + +} diff --git a/src/com/anzsoft/client/XMPP/XmppInfoQueryListener.java b/src/com/anzsoft/client/XMPP/XmppInfoQueryListener.java new file mode 100644 index 0000000..7c8e378 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppInfoQueryListener.java @@ -0,0 +1,29 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + + +public interface XmppInfoQueryListener extends XmppListener { + public void onInfoQueryReceived(XmppPacket packet); + public void onInfoQuerySent(XmppPacket packet); +} diff --git a/src/com/anzsoft/client/XMPP/XmppListener.java b/src/com/anzsoft/client/XMPP/XmppListener.java new file mode 100644 index 0000000..6e016d5 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppListener.java @@ -0,0 +1,27 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public interface XmppListener { + +} diff --git a/src/com/anzsoft/client/XMPP/XmppMessage.java b/src/com/anzsoft/client/XMPP/XmppMessage.java new file mode 100644 index 0000000..94cad49 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppMessage.java @@ -0,0 +1,43 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public interface XmppMessage extends XmppPacket{ + + public static final String TYPE_CHAT = "chat"; + public static final String TYPE_MULTI = "groupchat"; + + String getBody(); + + String getSubject(); + + String getThread(); + + void setBody(String body); + + void setTo(String id); + + void setType(String typeChat); + + +} diff --git a/src/com/anzsoft/client/XMPP/XmppMessageListener.java b/src/com/anzsoft/client/XMPP/XmppMessageListener.java new file mode 100644 index 0000000..affaa2e --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppMessageListener.java @@ -0,0 +1,30 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + + + +public interface XmppMessageListener extends XmppListener { + public void onMessageReceived(XmppMessage message); + public void onMessageSent(XmppMessage message); +} diff --git a/src/com/anzsoft/client/XMPP/XmppPacket.java b/src/com/anzsoft/client/XMPP/XmppPacket.java new file mode 100644 index 0000000..4f71108 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppPacket.java @@ -0,0 +1,59 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public interface XmppPacket { + + String getFrom(); + + XmppID getFromID(); + + String getID(); + + String getRootType(); + + String getTo(); + + XmppID getToID(); + + String getType(); + + String getXMLLang(); + + String getXMLNS(); + + String toXML(); + + void setFrom(String from); + + void setFrom(XmppID id); + + void setID(String id); + + void setTo(String stringID); + + void setTo(XmppID toId); + + void setType(String type); + +} diff --git a/src/com/anzsoft/client/XMPP/XmppPacketListener.java b/src/com/anzsoft/client/XMPP/XmppPacketListener.java new file mode 100644 index 0000000..cb307e5 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppPacketListener.java @@ -0,0 +1,29 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + + +public interface XmppPacketListener { + public void onPacketReceived(XmppPacket packet); + public void onPacketSent(XmppPacket packet); +} diff --git a/src/com/anzsoft/client/XMPP/XmppPresence.java b/src/com/anzsoft/client/XMPP/XmppPresence.java new file mode 100644 index 0000000..97c3e18 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppPresence.java @@ -0,0 +1,42 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public interface XmppPresence extends XmppPacket { + // FIXME: create a class for this (gwt style)! + String TYPE_UNAVAILABLE = "unavailable"; + + + int getPriority(); + + PresenceShow getShow(); + + String getStatus(); + + void setPriority(int i); + + void setShow(PresenceShow presenceShow); + + void setStatus(String message); + +} diff --git a/src/com/anzsoft/client/XMPP/XmppPresenceListener.java b/src/com/anzsoft/client/XMPP/XmppPresenceListener.java new file mode 100644 index 0000000..65d858f --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppPresenceListener.java @@ -0,0 +1,30 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + + +public interface XmppPresenceListener extends XmppListener { + public void onPresenceReceived(XmppPresence presence); + public void onPresenceSent(XmppPresence presence); + +} diff --git a/src/com/anzsoft/client/XMPP/XmppQuery.java b/src/com/anzsoft/client/XMPP/XmppQuery.java new file mode 100644 index 0000000..3647b67 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppQuery.java @@ -0,0 +1,31 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public interface XmppQuery extends XmppPacket { + String TYPE_SET = "set"; + String TYPE_GET = "get"; + String getQueryXMLNS(); + void createQueryNode(String xmlns); + +} diff --git a/src/com/anzsoft/client/XMPP/XmppStatus.java b/src/com/anzsoft/client/XMPP/XmppStatus.java new file mode 100644 index 0000000..b229777 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppStatus.java @@ -0,0 +1,81 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +import java.util.HashMap; + +public class XmppStatus { + public static final XmppStatus INITIALIZING = new XmppStatus("initializing", false); + public static final XmppStatus CONNECTING = new XmppStatus("connecting", false); + public static final XmppStatus RESUMING = new XmppStatus("resuming", false); + public static final XmppStatus PROCESSING = new XmppStatus("processing", false); + public static final XmppStatus SUSPENDING = new XmppStatus("suspending", false); + public static final XmppStatus ABORTED = new XmppStatus("aborted", false); + public static final XmppStatus DISCONNECTING = new XmppStatus("disconnecting", false); + public static final XmppStatus ERROR_REQUEST = new XmppStatus("onerror_fallback", true); + public static final XmppStatus ERROR_PROTOCOL = new XmppStatus("protoerror_fallback", true); + public static final XmppStatus ERROR_SERVER = new XmppStatus("internal_server_error", true); + public static final XmppStatus ERROR_UNKNOWN = new XmppStatus("unknown", true); + private static final HashMap constants = new HashMap(); + + static { + constants.put(INITIALIZING.getID(), INITIALIZING); + constants.put(CONNECTING.getID(), CONNECTING); + constants.put(RESUMING.getID(), RESUMING); + constants.put(PROCESSING.getID(), PROCESSING); + constants.put(SUSPENDING.getID(), SUSPENDING); + constants.put(ABORTED.getID(), ABORTED); + constants.put(DISCONNECTING.getID(), DISCONNECTING); + constants.put(ERROR_REQUEST.getID(), ERROR_REQUEST); + constants.put(ERROR_PROTOCOL.getID(), ERROR_PROTOCOL); + constants.put(ERROR_SERVER.getID(), ERROR_SERVER); + } + + private final boolean isError; + private final String id; + + private XmppStatus(final String id, final boolean isError) { + this.id = id; + this.isError = isError; + } + + public static XmppStatus getStatus(final String statusId) { + XmppStatus status = (XmppStatus) constants.get(statusId); + if (status == null) + status = ERROR_UNKNOWN; + return status; + } + + public String getID() { + return id; + } + + public String toString() { + return id; + } + + public boolean isError() { + return isError; + } + +} diff --git a/src/com/anzsoft/client/XMPP/XmppUserSettings.java b/src/com/anzsoft/client/XMPP/XmppUserSettings.java new file mode 100644 index 0000000..382b200 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/XmppUserSettings.java @@ -0,0 +1,92 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP; + +public class XmppUserSettings { + public static final AuthType SASL = new AuthType("sasl"); + public static final AuthType NON_SASL = new AuthType("nonsasl"); + + public static class AuthType + { + private final String constant; + + public static AuthType fromString(final String type) + { + if(!type.equalsIgnoreCase("sasl")&&!type.equalsIgnoreCase("nosasl")) + return new AuthType("sasl"); + return new AuthType(type); + } + private AuthType(final String constant) + { + this.constant = constant; + } + public String toString() + { + return constant; + } + } + + public String domain; + public String userName; + public String password; + public String resource; + public String host; + public int port; + private AuthType authType; + public boolean shouldRegister; + String auth; + public boolean isSecure; + + public XmppUserSettings(final String host,final int port,final String domain, final String userName, final String password, final String resource, final AuthType authType, final boolean shouldRegister) { + this.domain = domain; + this.userName = userName; + this.password = password; + this.resource = resource; + this.shouldRegister = shouldRegister; + this.host = host; + this.port = port; + this.isSecure = false; + setAuthType(authType); + } + + public XmppUserSettings(final String host,final int port,final String domain, final String userName, final String password, final AuthType authType) { + this(host,port,domain, userName, password, "iJab", authType, false); + } + + public String getID() { + return XmppID.render(userName, domain, resource); + } + + public String toString() { + return getID(); + } + + public AuthType getAuthType() { + return authType; + } + + public void setAuthType(final AuthType authType) { + this.authType = authType; + this.auth = authType.toString(); + } +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacConnection.java b/src/com/anzsoft/client/XMPP/impl/JsJacConnection.java new file mode 100644 index 0000000..c2870ea --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacConnection.java @@ -0,0 +1,204 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.Debugger; +import com.anzsoft.client.XMPP.XmppConnection; +import com.anzsoft.client.XMPP.XmppConnectionListener; +import com.anzsoft.client.XMPP.XmppEventAdapter; +import com.anzsoft.client.XMPP.XmppEventListener; +import com.anzsoft.client.XMPP.XmppFactory; +import com.anzsoft.client.XMPP.XmppInfoQueryListener; +import com.anzsoft.client.XMPP.XmppMessageListener; +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppPacketListener; +import com.anzsoft.client.XMPP.XmppPresenceListener; +import com.anzsoft.client.XMPP.XmppStatus; +import com.anzsoft.client.XMPP.XmppUserSettings; +import com.google.gwt.core.client.JavaScriptException; +import com.google.gwt.core.client.JavaScriptObject; + +abstract class JsJacConnection implements XmppConnection { + protected final JavaScriptObject connection; + private final XmppFactory factory; + + public JsJacConnection(final XmppFactory factory, final JavaScriptObject connection) { + this.factory = factory; + this.connection = connection; + } + + public void addConnectionListener(final XmppConnectionListener listener) { + this.addEventListener(new XmppEventAdapter() { + public void onConnect() { + listener.onConnect(); + } + + public void onDisconnect() { + listener.onDisconnect(); + } + }); + } + + + + public void connect(final XmppUserSettings user, int delayMillis) { + if (delayMillis <= 0) + delayMillis = 1; + Debugger.log("Trying to connect in " + delayMillis + " miliseconds."); + connect(user); + } + + public native void addEventListener(XmppEventListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.registerHandler('onConnect', function() { + listener.@com.anzsoft.client.XMPP.XmppEventListener::onConnect()(); + }); + delegate.registerHandler('onDisconnect', function() { + listener.@com.anzsoft.client.XMPP.XmppEventListener::onDisconnect()(); + }); + delegate.registerHandler('onResume', function() { + listener.@com.anzsoft.client.XMPP.XmppEventListener::onResume()(); + }); + delegate.registerHandler('onStatusChanged', function(statusID) { + listener.@com.anzsoft.client.XMPP.XmppEventListener::onStatusChanged(Ljava/lang/String;)(statusID); + }); + delegate.registerHandler('onError', function(error) { + var e = @com.anzsoft.client.XMPP.impl.JsJacError::newError(Lcom/google/gwt/core/client/JavaScriptObject;)(error); + listener.@com.anzsoft.client.XMPP.XmppEventListener::onError(Lcom/anzsoft/client/XMPP/XmppError;)(e); + }); + }-*/; + + public native void addInfoQueryListener(XmppInfoQueryListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.registerHandler('iq_in', function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPacket::newPacket(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppInfoQueryListener::onInfoQueryReceived(Lcom/anzsoft/client/XMPP/XmppPacket;)(p); + }); + delegate.registerHandler('iq_out', function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPacket::newPacket(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppInfoQueryListener::onInfoQuerySent(Lcom/anzsoft/client/XMPP/XmppPacket;)(p); + }); + }-*/; + + public native void addMessageListener(XmppMessageListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.registerHandler('message_in', function(packet) { + var m = @com.anzsoft.client.XMPP.impl.JsJacMessage::newMessage(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppMessageListener::onMessageReceived(Lcom/anzsoft/client/XMPP/XmppMessage;)(m); + }); + delegate.registerHandler('message_out', function(packet) { + var m = @com.anzsoft.client.XMPP.impl.JsJacMessage::newMessage(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppMessageListener::onMessageSent(Lcom/anzsoft/client/XMPP/XmppMessage;)(m); + }); + }-*/; + + public native void addPacketListener(XmppPacketListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.registerHandler('packet_in', function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPacket::newPacket(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppPacketListener::onPacketReceived(Lcom/anzsoft/client/XMPP/XmppPacket;)(p); + }); + delegate.registerHandler('packet_out', function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPacket::newPacket(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppPacketListener::onPacketSent(Lcom/anzsoft/client/XMPP/XmppPacket;)(p); + }); + }-*/; + + public native void addPreseceListener(XmppPresenceListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.registerHandler('presence_in', function(packet) + { + var p = @com.anzsoft.client.XMPP.impl.JsJacPresence::newPresence(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppPresenceListener::onPresenceReceived(Lcom/anzsoft/client/XMPP/XmppPresence;)(p); + }); + delegate.registerHandler('presence_out', function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPresence::newPresence(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppPresenceListener::onPresenceSent(Lcom/anzsoft/client/XMPP/XmppPresence;)(p); + }); + }-*/; + + public abstract void connect(XmppUserSettings user) throws JavaScriptException; + + public abstract void disconnect() throws JavaScriptException; + + public JavaScriptObject getDelegate() { + return connection; + } + + public XmppFactory getFactory() { + return factory; + } + + public native int getPollInterval() /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + return delegate.getPollInterval(); + }-*/; + + public XmppStatus getStatus() { + return XmppStatus.getStatus(getStatusID()); + } + + public native String getStatusID() /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + return delegate.status(); + }-*/; + + public native boolean isConnected() /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + return delegate.connected(); + }-*/; + + /** + * Resumes this connection from saved state (cookie) + */ + public native void resume() /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.resume(); + }-*/; + + // FIXME: only one method for both sends!! + public native void send(XmppPacket packet) throws JavaScriptException /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + var jsPacket = packet.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate; + delegate.send(jsPacket); + }-*/; + + public native void send(final XmppPacket packet, final XmppPacketListener listener) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + var jsPacket = packet.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate; + delegate.send(jsPacket, function(packet) { + var p = @com.anzsoft.client.XMPP.impl.JsJacPacket::newPacket(Lcom/google/gwt/core/client/JavaScriptObject;)(packet); + listener.@com.anzsoft.client.XMPP.XmppPacketListener::onPacketReceived(Lcom/anzsoft/client/XMPP/XmppPacket;)(p); + }); + }-*/; + + /** + * Suspsends this connection (saving state for later resume) + * + * @throws JavaScriptException + */ + public native void suspend() throws JavaScriptException /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.suspend(); + }-*/; +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacError.java b/src/com/anzsoft/client/XMPP/impl/JsJacError.java new file mode 100644 index 0000000..b18a61c --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacError.java @@ -0,0 +1,52 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppError; +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacError implements XmppError{ + final JavaScriptObject delegate; + + JsJacError(final JavaScriptObject delegate) { + this.delegate = delegate; + } + + public static JsJacError newError(final JavaScriptObject delegate) { + return new JsJacError(delegate); + } + +// return this.@com.anzsoft.client.XMPP.impl.JsJacError::delegate.getXml(); +// return (new $wnd.XMLSerializer()).serializeToString(node); + + + public native String toString() /*-{ + if ($wnd.XMLSerializer) { + var node = this.@com.anzsoft.client.XMPP.impl.JsJacError::delegate; + var serializer = new $wnd.XMLSerializer(typeof(node)); + return serializer.serializeToString(node); + } else { + return "use firefox to see the error!!!"; + } + }-*/; +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacFactory.java b/src/com/anzsoft/client/XMPP/impl/JsJacFactory.java new file mode 100644 index 0000000..f378f5d --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacFactory.java @@ -0,0 +1,68 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppConnection; +import com.anzsoft.client.XMPP.XmppFactory; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppQuery; +import com.anzsoft.client.XMPP.log.LogHelper; +import com.anzsoft.client.XMPP.log.LoggerOuput; + +public class JsJacFactory implements XmppFactory { + + private static JsJacFactory instance; + + JsJacFactory() { + } + + public static XmppFactory getInstance() { + if (instance == null) { + instance = new JsJacFactory(); + } + return instance; + } + + public XmppConnection createBindingConnection(final String httpBase, final int pollInterval, LoggerOuput logger) { + LogHelper.log("Creating binding connection to # with #msecs.", httpBase, LogHelper.p(pollInterval), logger); + return new JsJacHttpBindingConnection(this, httpBase, pollInterval, logger); + } + + public XmppMessage createMessage() { + return new JsJacMessage(); + } + + public XmppPresence createRoomPresence() { + return new JsJacRoomPresence(); + } + + public XmppPresence createPresence() { + return new JsJacPresence(); + } + + public XmppQuery createQuery() { + return new JsJacQuery(); + } + +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacHttpBindingConnection.java b/src/com/anzsoft/client/XMPP/impl/JsJacHttpBindingConnection.java new file mode 100644 index 0000000..7769282 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacHttpBindingConnection.java @@ -0,0 +1,82 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppFactory; +import com.anzsoft.client.XMPP.XmppUserSettings; +import com.anzsoft.client.XMPP.log.LoggerOuput; +import com.google.gwt.core.client.JavaScriptException; +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacHttpBindingConnection extends JsJacConnection { + public JsJacHttpBindingConnection(final XmppFactory factory, final String httpBase, final int pollInterval, LoggerOuput logger) throws JavaScriptException{ + super(factory, create(httpBase, pollInterval, logger)); + } + + private static native JavaScriptObject create(String httpBase, int pollInterval, LoggerOuput logger) throws JavaScriptException /*-{ + var oArgs = new Object(); + oArgs.httpbase = httpBase; + oArgs.timerval = pollInterval; + oArgs.oDbg = new Object(); + oArgs.oDbg.log = function (text) { + logger.@com.anzsoft.client.XMPP.log.LoggerOuput::log(Ljava/lang/String;)(text); + }; + var con = new $wnd.JSJaCHttpBindingConnection(oArgs); + return con; + }-*/; + + public native void connect(XmppUserSettings user) throws JavaScriptException /*-{ + var args = new Object(); + args.domain = user.@com.anzsoft.client.XMPP.XmppUserSettings::domain; + args.username = user.@com.anzsoft.client.XMPP.XmppUserSettings::userName; + args.pass = user.@com.anzsoft.client.XMPP.XmppUserSettings::password; + args.resource = user.@com.anzsoft.client.XMPP.XmppUserSettings::resource; + args.register = user.@com.anzsoft.client.XMPP.XmppUserSettings::shouldRegister; + //args.authtype = 'nonsasl'; + args.authtype = user.@com.anzsoft.client.XMPP.XmppUserSettings::auth; + args.host = user.@com.anzsoft.client.XMPP.XmppUserSettings::host; + args.port = user.@com.anzsoft.client.XMPP.XmppUserSettings::port; + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.connect(args); + }-*/; + + public native void disconnect() throws JavaScriptException /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.disconnect(); + }-*/; + + // TODO: + public native void inherit() /*-{ + }-*/; + + public native boolean isPolling() /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + return delegate.isPolling(); + }-*/; + + public native void setPollInterval(int pollInterval) /*-{ + var delegate = this.@com.anzsoft.client.XMPP.impl.JsJacConnection::connection; + delegate.setPollInterval(pollInterval); + }-*/; + +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacMessage.java b/src/com/anzsoft/client/XMPP/impl/JsJacMessage.java new file mode 100644 index 0000000..45527e6 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacMessage.java @@ -0,0 +1,68 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppMessage; +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacMessage extends JsJacPacket implements XmppMessage { + + public JsJacMessage() { + this(create()); + } + + private native static JavaScriptObject create() /*-{ + return new $wnd.JSJaCMessage(); + }-*/; + + JsJacMessage(final JavaScriptObject jso) { + super(jso); + } + + public native String getBody() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getBody(); + }-*/; + + public native void setBody(String body) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setBody(body); + }-*/; + + public native String getBodyAsHTML() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getBody().htmlEnc(); + }-*/; + + + public native String getSubject() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getSubject(); + }-*/; + + public native String getThread() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getThread(); + }-*/; + + + public static JsJacMessage newMessage(final JavaScriptObject jso) { + return new JsJacMessage(jso); + } + +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacPacket.java b/src/com/anzsoft/client/XMPP/impl/JsJacPacket.java new file mode 100644 index 0000000..9092448 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacPacket.java @@ -0,0 +1,109 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.XmppPacket; +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacPacket implements XmppPacket { + protected final JavaScriptObject delegate; + + JsJacPacket(final JavaScriptObject jso) { + this.delegate = jso; + } + + static JsJacPacket newPacket(final JavaScriptObject jso) { + return new JsJacPacket(jso); + } + + public native String getFrom() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getFrom(); + }-*/; + + + public XmppID getFromID() { + return XmppID.parseId(getFrom()); + } + + public native void setFrom(String from) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setFrom(from); + }-*/; + + public void setFrom(final XmppID from) { + setFrom(from.toString()); + } + + + public native String getID() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getID(); + }-*/; + + public native void setID(final String id) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setID(id); + }-*/; + + public native String getTo() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getTo(); + }-*/; + + + public XmppID getToID() { + return XmppID.parseId(getTo()); + } + + public native void setTo(String toUserID) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setTo(toUserID); + }-*/; + + public void setTo(final XmppID id) { + setTo(id.toString()); + } + + + public native String getType() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getType(); + }-*/; + + public native void setType(String type) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setType(type); + }-*/; + + + public native String getXMLLang() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getXMLLang(); + }-*/; + + public native String getXMLNS() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getXMLNS(); + }-*/; + + public native String getRootType() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.pType(); + }-*/; + + public native String toXML() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.xml(); + }-*/; + +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacPresence.java b/src/com/anzsoft/client/XMPP/impl/JsJacPresence.java new file mode 100644 index 0000000..ad174a0 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacPresence.java @@ -0,0 +1,91 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.PresenceShow; +import com.anzsoft.client.XMPP.XmppPresence; +import com.google.gwt.core.client.JavaScriptException; +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacPresence extends JsJacPacket implements XmppPresence{ + + public JsJacPresence() { + this(create()); + } + + + private static native JavaScriptObject create() throws JavaScriptException /*-{ + return new $wnd.JSJaCPresence(); + }-*/; + + JsJacPresence(final JavaScriptObject jso) { + super(jso); + } + + static JsJacPresence newPresence(final JavaScriptObject jso) { + return new JsJacPresence(jso); + } + + public int getPriority() { + try { + return new Integer(getNativePriority()).intValue(); + } catch (NumberFormatException e) { + return 0; + } + } + + public native String getNativePriority() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getPriority(); + }-*/; + + public native void setPriority(int priority) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setPriority(priority); + }-*/; + + public native String getStatus() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getStatus(); + }-*/; + + public native void setStatus(String message) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setStatus(message); + }-*/; + + public void setShow(final PresenceShow presenceShow) { + setShowID(presenceShow.toString()); + } + + public PresenceShow getShow() { + return PresenceShow.get(getShowID()); + } + + private native String getShowID() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getShow(); + }-*/; + + + private native void setShowID(String showID) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setShow(showID); + }-*/; + + +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacQuery.java b/src/com/anzsoft/client/XMPP/impl/JsJacQuery.java new file mode 100644 index 0000000..60f41f5 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacQuery.java @@ -0,0 +1,44 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.anzsoft.client.XMPP.XmppQuery; +import com.google.gwt.core.client.JavaScriptObject; + +public class JsJacQuery extends JsJacPacket implements XmppQuery { + public JsJacQuery() { + super(create()); + } + + private static native JavaScriptObject create()/*-{ + return new $wnd.JSJaCIQ(); + }-*/; + + public native String getQueryXMLNS() /*-{ + return this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.getQueryXMLNS(); + }-*/; + + public native void createQueryNode(String xmlns) /*-{ + this.@com.anzsoft.client.XMPP.impl.JsJacPacket::delegate.setQuery(xmlns); + }-*/; +} diff --git a/src/com/anzsoft/client/XMPP/impl/JsJacRoomPresence.java b/src/com/anzsoft/client/XMPP/impl/JsJacRoomPresence.java new file mode 100644 index 0000000..f46db06 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/impl/JsJacRoomPresence.java @@ -0,0 +1,48 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.impl; + +import com.google.gwt.core.client.JavaScriptObject; + +class JsJacRoomPresence extends JsJacPresence { + + public JsJacRoomPresence() { + this(create()); + } + + JsJacRoomPresence(final JavaScriptObject delegate) { + super(delegate); + } + + static native JavaScriptObject create() /*-{ + var presence = new $wnd.JSJaCPresence(); + var x = presence.getDoc().createElement('x'); + x.setAttribute('xmlns','http://jabber.org/protocol/muc'); + presence.getNode().appendChild(x); + return presence; + }-*/; + +// if (typeof(pass) != 'undefined' && pass != '') +// x.appendChild(aPresence.getDoc().createElement('password')).appendChild(aPresence.getDoc().createTextNode(pass)); + +} diff --git a/src/com/anzsoft/client/XMPP/log/DebugPanel.java b/src/com/anzsoft/client/XMPP/log/DebugPanel.java new file mode 100644 index 0000000..30aa289 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/DebugPanel.java @@ -0,0 +1,50 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP.log; + +import com.extjs.gxt.ui.client.widget.LayoutContainer; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.TextArea; +import com.google.gwt.user.client.ui.Widget; + + +public class DebugPanel extends LayoutContainer implements LoggerOuput { + private final TextArea area; + + public DebugPanel() { + setLayout(new FitLayout()); + area = new TextArea(); + //area.setWidth("500"); + //area.setHeight("500"); + add(area); + add(new Button("clear", new ClickListener () { + public void onClick(final Widget sender) { + area.setText(""); + } + })); + } + + public void log(final String message) { + area.setText(area.getText() + message + "\n"); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/GWTLoggerOutput.java b/src/com/anzsoft/client/XMPP/log/GWTLoggerOutput.java new file mode 100644 index 0000000..3a5c614 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/GWTLoggerOutput.java @@ -0,0 +1,36 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP.log; + +import com.google.gwt.core.client.GWT; + +public class GWTLoggerOutput implements LoggerOuput { + public static final LoggerOuput instance = new GWTLoggerOutput(); + + private GWTLoggerOutput() { + } + + public void log(String text) { + GWT.log(text, null); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/LogHelper.java b/src/com/anzsoft/client/XMPP/log/LogHelper.java new file mode 100644 index 0000000..4512665 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LogHelper.java @@ -0,0 +1,46 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +public class LogHelper { + + private LogHelper() { + } + + /** + * Convert to param method + * @param integer + * @return as string + */ + public static String p(int value) { + return new Integer(value).toString(); + } + + public static void log(String pattern, String value1, String value2, LoggerOuput logger) { + pattern = pattern.replaceFirst("#", value1); + pattern = pattern.replaceFirst("#", value2); + logger.log(pattern); + } + + +} diff --git a/src/com/anzsoft/client/XMPP/log/LoggerEventListener.java b/src/com/anzsoft/client/XMPP/log/LoggerEventListener.java new file mode 100644 index 0000000..2ba3cb5 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerEventListener.java @@ -0,0 +1,56 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppError; +import com.anzsoft.client.XMPP.XmppEventListener; + +public class LoggerEventListener implements XmppEventListener { + private final LoggerOuput output; + + public LoggerEventListener(final LoggerOuput output) { + this.output = output; + } + + public void onConnect() { + output.log("CONNECTED EVENT!"); + } + + public void onDisconnect() { + output.log("DISCONNECTED!"); + + } + + public void onError(final XmppError error) { + output.log("!!! ERROR EVENT : " + error.toString() + "'"); + } + + public void onResume() { + output.log("RESUME!"); + } + + public void onStatusChanged(final String status) { + output.log("STATUS CHANGED! : '" + status + "'"); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/LoggerInfoQueryListener.java b/src/com/anzsoft/client/XMPP/log/LoggerInfoQueryListener.java new file mode 100644 index 0000000..ed56acb --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerInfoQueryListener.java @@ -0,0 +1,45 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppInfoQueryListener; +import com.anzsoft.client.XMPP.XmppPacket; + +public class LoggerInfoQueryListener implements XmppInfoQueryListener{ + private final LoggerOuput output; + + public LoggerInfoQueryListener(final LoggerOuput logger) { + this.output = logger; + } + + public void onInfoQueryReceived(XmppPacket packet) { + output.log("INFO QUERY RECEIVED"); + XmppLogHelper.writePacket(packet, output); + } + + public void onInfoQuerySent(XmppPacket packet) { + output.log("INFO QUERY SENT"); + XmppLogHelper.writePacket(packet, output); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/LoggerMessageListener.java b/src/com/anzsoft/client/XMPP/log/LoggerMessageListener.java new file mode 100644 index 0000000..dd0cce8 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerMessageListener.java @@ -0,0 +1,45 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppMessageListener; + +public class LoggerMessageListener implements XmppMessageListener { + private final LoggerOuput output; + + public LoggerMessageListener(final LoggerOuput output) { + this.output = output; + } + + public void onMessageReceived(final XmppMessage message) { + output.log("MESSAGE RECEIVED"); + XmppLogHelper.writeMessage(message, output); + } + + public void onMessageSent(final XmppMessage message) { + output.log("MESSAGE SENT"); + XmppLogHelper.writeMessage(message, output); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/LoggerOuput.java b/src/com/anzsoft/client/XMPP/log/LoggerOuput.java new file mode 100644 index 0000000..f1a12c1 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerOuput.java @@ -0,0 +1,26 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP.log; + +public interface LoggerOuput { + void log(String text); +} \ No newline at end of file diff --git a/src/com/anzsoft/client/XMPP/log/LoggerPacketListener.java b/src/com/anzsoft/client/XMPP/log/LoggerPacketListener.java new file mode 100644 index 0000000..1774d68 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerPacketListener.java @@ -0,0 +1,46 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppPacketListener; + +public class LoggerPacketListener implements XmppPacketListener { + + private final LoggerOuput output; + + public LoggerPacketListener(final LoggerOuput output) { + this.output = output; + } + + public void onPacketReceived(final XmppPacket packet) { + output.log("PACKET RECEIVED"); + XmppLogHelper.writePacket(packet, output); + } + + public void onPacketSent(final XmppPacket packet) { + output.log("PACKET SENT"); + XmppLogHelper.writePacket(packet, output); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/LoggerPresenceListener.java b/src/com/anzsoft/client/XMPP/log/LoggerPresenceListener.java new file mode 100644 index 0000000..b3b95f7 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/LoggerPresenceListener.java @@ -0,0 +1,46 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppPresenceListener; + +public class LoggerPresenceListener implements XmppPresenceListener { + + private final LoggerOuput output; + + public LoggerPresenceListener(final LoggerOuput output) { + this.output = output; + } + + public void onPresenceReceived(XmppPresence presence) { + output.log("PRESENCE RECEIVED"); + XmppLogHelper.writePresence(presence, output); + } + + public void onPresenceSent(XmppPresence presence) { + output.log("PRESENCE SENT"); + XmppLogHelper.writePresence(presence, output); + } + +} diff --git a/src/com/anzsoft/client/XMPP/log/XmppLogHelper.java b/src/com/anzsoft/client/XMPP/log/XmppLogHelper.java new file mode 100644 index 0000000..c0d517c --- /dev/null +++ b/src/com/anzsoft/client/XMPP/log/XmppLogHelper.java @@ -0,0 +1,87 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ +package com.anzsoft.client.XMPP.log; + +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppQuery; +import com.anzsoft.client.XMPP.XmppStatus; + +public class XmppLogHelper { + + public static void writeStatus(final XmppStatus xmppStatus, final LoggerOuput output) { + output.log("[status - id: " + xmppStatus.getID() + "]"); + } + + public static void writePacket(final XmppPacket packet, final LoggerOuput output) { + output.log(packet.toXML()); + /* + output.log("[packet - root type: " + packet.getRootType()+ "]"); + output.log("[packet - from: " + packet.getFrom() + "]"); + output.log("[packet - to: " + packet.getTo() + "]"); + output.log("[packet - id: " + packet.getID() + "]"); + output.log("[packet - type: " + packet.getType() + "]"); + output.log("[packet - xml:lang: " + packet.getXMLLang() + "]"); + output.log("[packet - xmlns: " + packet.getXMLNS() + "]"); + */ + // FIXME: these methods are not secure! +// LogHelper.writeID(xmppPacket.getFromID(), output); +// LogHelper.writeID(xmppPacket.getToID(), output); + } + + public static void writeMessage(final XmppMessage message, final LoggerOuput output) { + writePacket(message, output); + /* + output.log("[message - body: " + message.getBody() + "]"); + output.log("[message - subject: " + message.getSubject() + "]"); + output.log("[message - thread: " + message.getThread() + "]"); + */ + } + + public static void writePresence(final XmppPresence presence, final LoggerOuput output) { + writePacket(presence, output); + /* + output.log("[presence - priority: " + presence.getPriority() + "]"); + output.log("[presence - status (msg): " + presence.getStatus() + "]"); + output.log("[presence - show: " + presence.getShow() + "]"); + */ + } + + // TODO: put it again when getFromJID and getToJID are more secure! + static void writeID(final XmppID id, final LoggerOuput output) { + /* + output.log("[id - domain: " + id.getDomain()+ "]"); + output.log("[id - node: " + id.getNode()+ "]"); + output.log("[id - resource: " + id.getResource() + "]"); + */ + + } + + public static void writeQuery(final XmppQuery query, final LoggerOuput output) { + writePacket(query, output); + output.log("[query - xmlns: " + query.getQueryXMLNS()+ "]"); + } + + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/MessageRouter.java b/src/com/anzsoft/client/XMPP/mandioca/MessageRouter.java new file mode 100644 index 0000000..fd51357 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/MessageRouter.java @@ -0,0 +1,51 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import com.anzsoft.client.XMPP.XmppListener; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppMessageListener; +import com.anzsoft.client.XMPP.XmppPacket; + +class MessageRouter extends Router implements XmppMessageListener { + + public void onMessageReceived(final XmppMessage message) { + filterIncoming(message, new XmppPacketHandler () { + public void handle(final XmppPacket message, final XmppListener listener) { + ((XmppMessageListener) listener).onMessageReceived((XmppMessage) message); + } + }); + } + + public void onMessageSent(final XmppMessage message) { + filterOutcoming(message, new XmppPacketHandler () { + public void handle(final XmppPacket message, final XmppListener listener) { + ((XmppMessageListener) listener).onMessageSent((XmppMessage) message); + } + }); + } + + public void add(final XmppMessageListener messageListener, final XmppPacketFilter filter) { + super.addListener(messageListener, filter); + } +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/PresenceRouter.java b/src/com/anzsoft/client/XMPP/mandioca/PresenceRouter.java new file mode 100644 index 0000000..6fc305b --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/PresenceRouter.java @@ -0,0 +1,51 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import com.anzsoft.client.XMPP.XmppListener; +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppPresenceListener; + +class PresenceRouter extends Router implements XmppPresenceListener { + public void onPresenceReceived(final XmppPresence presence) { + filterIncoming(presence, new XmppPacketHandler () { + public void handle(final XmppPacket message, final XmppListener listener) { + ((XmppPresenceListener) listener).onPresenceReceived((XmppPresence) message); + } + }); + } + + public void onPresenceSent(final XmppPresence presence) { + filterOutcoming(presence, new XmppPacketHandler () { + public void handle(final XmppPacket message, final XmppListener listener) { + ((XmppPresenceListener) listener).onPresenceSent((XmppPresence) message); + } + }); + } + + public void add(final XmppPresenceListener listener, final XmppPacketFilter filter) { + addListener(listener, filter); + } + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/Router.java b/src/com/anzsoft/client/XMPP/mandioca/Router.java new file mode 100644 index 0000000..c1b667d --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/Router.java @@ -0,0 +1,71 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.ArrayList; + +import com.anzsoft.client.XMPP.XmppListener; +import com.anzsoft.client.XMPP.XmppPacket; + +abstract class Router { + protected final ArrayList listeners; + protected final ArrayList filters; + + public Router() { + this.listeners = new ArrayList(); + this.filters = new ArrayList(); + } + + protected void addListener(final XmppListener listener, final XmppPacketFilter filter) { + listeners.add(listener); + filters.add(filter); + } + + protected XmppPacketFilter getFilter(final int index) { + return (XmppPacketFilter) filters.get(index); + } + + private XmppListener getListener(final int index) { + return (XmppListener) listeners.get(index); + } + + + protected void filterIncoming(final XmppPacket message, final XmppPacketHandler handler) { + int total = listeners.size(); + for (int index = 0; index < total ; index++) { + if (getFilter(index).filterIncoming(message)) { + handler.handle(message, getListener(index)); + } + } + } + + protected void filterOutcoming(final XmppPacket message, final XmppPacketHandler handler) { + int total = listeners.size(); + for (int index = 0; index < total ; index++) { + if (getFilter(index).filterOutcoming(message)) { + handler.handle(message, getListener(index)); + } + } + } + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppChat.java b/src/com/anzsoft/client/XMPP/mandioca/XmppChat.java new file mode 100644 index 0000000..e9568d1 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppChat.java @@ -0,0 +1,80 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppMessageListener; +import com.anzsoft.client.XMPP.XmppPresenceListener; + +public class XmppChat { + protected final String sessionUserId; + protected final XmppSession session; + protected XmppIdPacketListener filter; + + // FIXME: + // id = name@host + // clientID = name@host/resource + public static String buildId(final String name, final String host) { + return name + "@" + host; + } + + public XmppChat(final XmppSession session, final String name, final String host) { + this(session, buildId(name, host), new XmppIdPacketListener(buildId(name, host))); + } + + protected XmppChat(final XmppSession session, final String id, final XmppIdPacketListener filter) { + this.session = session; + this.sessionUserId = id; + this.filter = filter; + } + + public boolean isRoom() { + return false; + } + + public void sendMessage(final String body) { + XmppMessage message = createMessage(body); + session.send(message); + } + + protected XmppMessage createMessage(final String body) { + XmppMessage message = session.getFactory().createMessage(); + message.setFrom(session.getUser().getID()); + message.setTo(sessionUserId); + message.setBody(body); + message.setType(XmppMessage.TYPE_CHAT); + return message; + } + + public void addMessageListener(final XmppMessageListener messageListener) { + session.addMessageListener(messageListener, filter); + } + + protected void addPresenceListener(final XmppPresenceListener listener) { + session.addPresenceListener(listener, filter); + } + + public void logout() { + } + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppContact.java b/src/com/anzsoft/client/XMPP/mandioca/XmppContact.java new file mode 100644 index 0000000..13433b5 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppContact.java @@ -0,0 +1,127 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.ArrayList; +import java.util.List; + +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.utils.XMLHelper; +import com.google.gwt.xml.client.Element; + +public class XmppContact +{ + public static enum Subscription { + /** + * "both" -- both the user and the contact have subscriptions to each + * other's presence information + */ + both, + /** + * "from" -- the contact has a subscription to the user's presence + * information, but the user does not have a subscription to the + * contact's presence information + */ + from, + /** + * "none" -- the user does not have a subscription to the contact's + * presence information, and the contact does not have a subscription to + * the user's presence information + */ + none, + /** + * "to" -- the user has a subscription to the contact's presence + * information, but the contact does not have a subscription to the + * user's presence information + */ + to + } + + private final ArrayList groups; + private final XmppID jid; + private final String name; + private XmppContactStatus status; + private Subscription subscription; + + public static XmppContact fromXml(Element e) + { + XmppID jid = XmppID.parseId(e.getAttribute("jid")); + String subscription = e.getAttribute("subscription"); + String name = e.getAttribute("name"); + ArrayList groups = XMLHelper.getSubTagsConents(e, "group"); + return new XmppContact(jid,Subscription.valueOf(subscription),name,groups); + + } + + public XmppContact(final XmppID jid,final Subscription subscription,String name,ArrayList groups) + { + this.jid = jid; + this.subscription = subscription; + this.name = name; + this.groups = groups; + this.status = new XmppContactStatus(); + } + + //get attr + public List getGroups() + { + return this.groups; + } + + public XmppID getJID() + { + return this.jid; + } + + public XmppContactStatus getStatus() + { + return this.status; + } + + public Subscription getSubscription() + { + return this.subscription; + } + + public String getName() + { + return this.name; + } + + public String getAvatar() + { + return "images/default_avatar.png"; + } + + //get attr + public void setStatus(final XmppContactStatus status) + { + this.status = status; + } + + public void setSubscription(Subscription subscription) + { + this.subscription = subscription; + } + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppContactStatus.java b/src/com/anzsoft/client/XMPP/mandioca/XmppContactStatus.java new file mode 100644 index 0000000..3170e5f --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppContactStatus.java @@ -0,0 +1,88 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +public class XmppContactStatus +{ + public enum Type{Offline,Invisible,DND,XA,Away,Online,FFC} + + private String v_show,v_status; + private boolean v_isAvaiable; + private int v_priority; + + public XmppContactStatus(final String show,final String status,int priority,boolean avaiable) + { + this.v_priority = priority; + this.v_show = show; + this.v_status = status; + this.v_isAvaiable = avaiable; + }; + + public XmppContactStatus() + { + this.v_show = ""; + this.v_status = ""; + this.v_priority = 0; + this.v_isAvaiable = false; + } + + public String show() + { + return this.v_show; + } + + public String status() + { + return this.v_status; + } + + public int priority() + { + return this.v_priority; + } + + public boolean isAvaiable() + { + return this.v_isAvaiable; + } + + public Type type() + { + Type ret = Type.Online; + if(!isAvaiable()) + ret = Type.Offline; + else + { + String s = show(); + if(s.equals("away")) + ret = Type.Away; + else if(s.equals("xa")) + ret = Type.XA; + else if(s.equals("dnd")) + ret = Type.DND; + else if(s.equals("chat")) + ret = Type.FFC; + } + return ret; + } +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppIdPacketListener.java b/src/com/anzsoft/client/XMPP/mandioca/XmppIdPacketListener.java new file mode 100644 index 0000000..77b9b7b --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppIdPacketListener.java @@ -0,0 +1,48 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; +import com.anzsoft.client.XMPP.Debugger; +import com.anzsoft.client.XMPP.XmppPacket; + + +public class XmppIdPacketListener implements XmppPacketFilter{ + private final String selfID; + + public XmppIdPacketListener(final String id) { + this.selfID = id; + } + + public boolean filterIncoming(final XmppPacket packet) { + String packetFrom = packet.getFromID().toStringNoResource(); + boolean shouldFilter = packetFrom.equals(selfID); + Debugger.log("ChatPacket FILTER IN(" + selfID + "): " + packetFrom + "=> " + shouldFilter); + return shouldFilter; + } + + public boolean filterOutcoming(final XmppPacket packet) { + String packetTo = packet.getTo(); + boolean shouldFilter = packetTo.equals(selfID); + Debugger.log("ChatPacket FILTER OUT(" + selfID + "): " + packetTo + "=> " + shouldFilter); + return shouldFilter; + } +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppPacketFilter.java b/src/com/anzsoft/client/XMPP/mandioca/XmppPacketFilter.java new file mode 100644 index 0000000..4f136ca --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppPacketFilter.java @@ -0,0 +1,33 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import com.anzsoft.client.XMPP.XmppPacket; + +public interface XmppPacketFilter { + + boolean filterIncoming(XmppPacket packet); + + boolean filterOutcoming(XmppPacket packet); + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppPacketHandler.java b/src/com/anzsoft/client/XMPP/mandioca/XmppPacketHandler.java new file mode 100644 index 0000000..ca92dab --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppPacketHandler.java @@ -0,0 +1,30 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import com.anzsoft.client.XMPP.XmppListener; +import com.anzsoft.client.XMPP.XmppPacket; + +public interface XmppPacketHandler { + void handle(XmppPacket message, XmppListener listener); +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppRoster.java b/src/com/anzsoft/client/XMPP/mandioca/XmppRoster.java new file mode 100644 index 0000000..ca9789c --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppRoster.java @@ -0,0 +1,117 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import com.anzsoft.client.XMPP.Debugger; +import com.anzsoft.client.XMPP.HandlerCollection; +import com.anzsoft.client.XMPP.PresenceShow; +import com.anzsoft.client.XMPP.XmppInfoQueryListener; +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppQuery; +import com.anzsoft.client.utils.XMLHelper; +import com.google.gwt.xml.client.Document; +import com.google.gwt.xml.client.NodeList; +import com.google.gwt.xml.client.XMLParser; +import com.google.gwt.xml.client.Element; + + +public class XmppRoster +{ + private final XmppInfoQueryListener rosterListener; + private final XmppSession session; + public Map contacts = new HashMap(); + private final HandlerCollection /* */rosterListeners = new HandlerCollection(); + public XmppRoster(final XmppSession session) + { + this.session = session; + rosterListener = new XmppInfoQueryListener(){ + public void onInfoQueryReceived(XmppPacket packet) + { + if(!packet.getID().equalsIgnoreCase("roster_1")||!packet.getType().equalsIgnoreCase("result")) + { + return; + } + parseRoster(packet.toXML()); + session.getUser().sendPresence(PresenceShow.emptyShow(), "http://www.anzsoft.com"); + } + public void onInfoQuerySent(XmppPacket packet) { + } + + }; + this.session.addInfoQueryListener(rosterListener); + } + + public void sendQuery() + { + Debugger.log("SENDING ROSTER QUERY!!"); + XmppQuery query = session.getFactory().createQuery(); + query.setType(XmppQuery.TYPE_GET); + query.setID("roster_1"); + query.createQueryNode("jabber:iq:roster"); + session.send(query); + } + + private void parseRoster(String xml) + { + contacts.clear(); + Document doc = XMLParser.parse(xml); + Element query = XMLHelper.queryTag(doc.getDocumentElement()); + if(query !=null && query.getAttribute("xmlns").equals("jabber:iq:roster")) + { + NodeList itemList = query.getElementsByTagName("item"); + for(int index = 0;index + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.Map; + +public interface XmppRosterListener { + public void onRoster(final Map contacts); +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppSession.java b/src/com/anzsoft/client/XMPP/mandioca/XmppSession.java new file mode 100644 index 0000000..61f0b69 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppSession.java @@ -0,0 +1,125 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.ArrayList; + +import com.anzsoft.client.XMPP.XmppConnection; +import com.anzsoft.client.XMPP.XmppConnectionListener; +import com.anzsoft.client.XMPP.XmppEventAdapter; +import com.anzsoft.client.XMPP.XmppFactory; +import com.anzsoft.client.XMPP.XmppInfoQueryListener; +import com.anzsoft.client.XMPP.XmppMessageListener; +import com.anzsoft.client.XMPP.XmppPacket; +import com.anzsoft.client.XMPP.XmppPacketListener; +import com.anzsoft.client.XMPP.XmppPresenceListener; +import com.anzsoft.client.XMPP.XmppUserSettings; +import com.anzsoft.client.XMPP.mandioca.rooms.XmppRoom; + +public class XmppSession { + private static final int INITIAL_RECONNECT_INTERVAL = 1000; + private final XmppConnection connection; + private final MessageRouter messageRouter; + private final PresenceRouter presenceRouter; + private final ArrayList activeChats; + private XmppUser user; + private int reconnectInterval; + private final boolean reconnectOnFail; + + public XmppSession(final XmppConnection connection, final boolean reconnectOnFail) { + this.reconnectOnFail = reconnectOnFail; + this.reconnectInterval = INITIAL_RECONNECT_INTERVAL; + this.connection = connection; + this.activeChats = new ArrayList(); + this.messageRouter = new MessageRouter(); + connection.addMessageListener(messageRouter); + this.presenceRouter = new PresenceRouter(); + connection.addPreseceListener(presenceRouter); + } + + public void login(final XmppUserSettings userSettings) { + connection.connect(userSettings); + this.user = new XmppUser(this, userSettings.getID()); + } + + public void addEventListener(final XmppEventAdapter listener) { + connection.addEventListener(listener); + } + + public XmppUser getUser() { + return user; + } + + public XmppChat openChat(final String name, final String host) { + XmppChat chat = new XmppChat(this, name, host); + activeChats.add(chat); + return chat; + } + + public XmppRoom joinRoom(final String host, final String roomName, final String nick) { + XmppRoom room = new XmppRoom(this, roomName, host, nick); + activeChats.add(room); + room.join(user); + return room; + } + + public void logout() { + XmppChat chat; + int total = activeChats.size(); + for (int index = 0; index < total; index++) { + chat = (XmppChat) activeChats.get(index); + chat.logout(); + } + user = null; + connection.disconnect(); + } + + public void send(final XmppPacket packet) { + connection.send(packet); + } + + public void addMessageListener(final XmppMessageListener listener, final XmppPacketFilter filter) { + messageRouter.add(listener, filter); + } + + public void addPresenceListener(final XmppPresenceListener listener, final XmppPacketFilter filter) { + presenceRouter.add(listener, filter); + } + + public XmppFactory getFactory() { + return connection.getFactory(); + } + + public void send(final XmppPacket packet, final XmppPacketListener listener) { + connection.send(packet, listener); + } + + public void addConnectionListener(XmppConnectionListener xmppConnectionListener) { + connection.addConnectionListener(xmppConnectionListener); + } + + public void addInfoQueryListener(XmppInfoQueryListener listener) + { + connection.addInfoQueryListener(listener); + } +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/XmppUser.java b/src/com/anzsoft/client/XMPP/mandioca/XmppUser.java new file mode 100644 index 0000000..06e66d3 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/XmppUser.java @@ -0,0 +1,109 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca; + +import java.util.Iterator; + +import com.anzsoft.client.XMPP.HandlerCollection; +import com.anzsoft.client.XMPP.PresenceShow; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppPresence; + +public class XmppUser +{ + public interface XmppUserListener + { + public void onPresenceChanged(XmppPresence presence); + } + private final XmppSession session; + private final String userID; + private final XmppRoster roster; + private XmppPresence presence; + private final HandlerCollection /* */userListeners = new HandlerCollection(); + + public XmppUser(final XmppSession session, final String userID) + { + this.session = session; + this.userID = userID; + roster = new XmppRoster(session); + } + + public void sendPresence(final PresenceShow presenceShow, final String message) + { + presence = session.getFactory().createPresence(); + presence.setFrom(userID); + presence.setPriority(5); + presence.setShow(presenceShow); + presence.setStatus(message); + session.send(presence); + fireOnPresenceChanged(); + } + + public void sendMessage(final String body, final String destination) + { + XmppMessage message = session.getFactory().createMessage(); + message.setFrom(session.getUser().getID()); + message.setTo(userID); + message.setBody(body); + message.setType(XmppMessage.TYPE_CHAT); + session.send(message); + } + + + public String getID() + { + return userID; + } + + public String toString() + { + return userID; + } + + public XmppRoster getRoster() + { + return roster; + } + + public void addUserListener(XmppUserListener listener) + { + userListeners.add(listener); + } + + public void removeUserListener(XmppUserListener listener) + { + userListeners.remove(listener); + } + + public void fireOnPresenceChanged() + { + Iterator iter = userListeners.iterator(); + while (iter.hasNext()) + { + XmppUserListener listener = (XmppUserListener) iter.next(); + listener.onPresenceChanged(presence); + } + } + + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListener.java b/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListener.java new file mode 100644 index 0000000..30caa12 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListener.java @@ -0,0 +1,28 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca.rooms; + +public interface RoomPresenceListener { + void onUserLeft(String alias); + void onUserEntered(String alias, String status); +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListenerCollection.java b/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListenerCollection.java new file mode 100644 index 0000000..5fc3471 --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/rooms/RoomPresenceListenerCollection.java @@ -0,0 +1,45 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca.rooms; + +import java.util.ArrayList; +import java.util.Iterator; + + +class RoomPresenceListenerCollection extends ArrayList { + public void fireUserLeaves(final String alias) { + for(Iterator it = iterator(); it.hasNext(); ) { + ((RoomPresenceListener) it.next()).onUserLeft(alias); + } + } + + public void fireUserEntered(final String alias, final String status) { + for(Iterator it = iterator(); it.hasNext(); ) { + ((RoomPresenceListener) it.next()).onUserEntered(alias, status); + } + } + + + + +} diff --git a/src/com/anzsoft/client/XMPP/mandioca/rooms/XmppRoom.java b/src/com/anzsoft/client/XMPP/mandioca/rooms/XmppRoom.java new file mode 100644 index 0000000..556ee6f --- /dev/null +++ b/src/com/anzsoft/client/XMPP/mandioca/rooms/XmppRoom.java @@ -0,0 +1,113 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + Some code copied form gwtjsjac + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.XMPP.mandioca.rooms; + +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.XmppMessage; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.XmppPresenceListener; +import com.anzsoft.client.XMPP.mandioca.XmppChat; +import com.anzsoft.client.XMPP.mandioca.XmppIdPacketListener; +import com.anzsoft.client.XMPP.mandioca.XmppSession; +import com.anzsoft.client.XMPP.mandioca.XmppUser; + +public class XmppRoom extends XmppChat { + private final String roomId; + private String userId; + private final String sessionRoomId; + private final RoomPresenceListenerCollection presenceListeners; + + public XmppRoom(final XmppSession session, final String roomName, final String host, final String nick) { + this(session, XmppID.render(roomName, host, nick), XmppID.render(roomName, host, null)); + } + + XmppRoom(final XmppSession session, final String userInRoomId, final String roomId) { + super(session, userInRoomId, new XmppIdPacketListener(roomId)); + this.roomId = roomId; + this.sessionRoomId = userInRoomId; + this.presenceListeners = new RoomPresenceListenerCollection(); + + addPresenceListener(new XmppPresenceListener() { + public void onPresenceReceived(final XmppPresence presence) { + String alias = presence.getFromID().getResource(); + String type = presence.getType(); + if (type != null && type.equals(XmppPresence.TYPE_UNAVAILABLE)) { + presenceListeners.fireUserLeaves(alias); + } else { + presenceListeners.fireUserEntered(alias, presence.getStatus()); + } + } + + public void onPresenceSent(final XmppPresence presence) { + } + }); + } + + + public boolean isRoom() { + return true; + } + + private XmppPresence createRoomPresence() { + XmppPresence presence = session.getFactory().createRoomPresence(); + presence.setFrom(userId); + presence.setTo(sessionRoomId); + return presence; + } + + /** + * @param user + * @see http://www.xmpp.org/extensions/xep-0045.html#enter + */ + public void join(final XmppUser user) { + userId = user.getID(); + XmppPresence presence = createRoomPresence(); + session.send(presence); + } + + + /** + * + * @see http://www.xmpp.org/extensions/xep-0045.html#exit + */ + public void logout() { + XmppPresence presence = createRoomPresence(); + presence.setType(XmppPresence.TYPE_UNAVAILABLE); + session.send(presence); + } + + public void addRoomPresenceListener(final RoomPresenceListener listener) { + presenceListeners.add(listener); + } + + protected XmppMessage createMessage(final String body) { + XmppMessage message = session.getFactory().createMessage(); + message.setFrom(session.getUser().getID()); + message.setTo(roomId); + message.setBody(body); + message.setType(XmppMessage.TYPE_MULTI); + return message; + } + + +} diff --git a/src/com/anzsoft/client/iJab.java b/src/com/anzsoft/client/iJab.java new file mode 100644 index 0000000..14b5188 --- /dev/null +++ b/src/com/anzsoft/client/iJab.java @@ -0,0 +1,175 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client; + + +import com.anzsoft.client.JabberApp.LoginListener; +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.ui.ChatWindow; +import com.google.gwt.core.client.EntryPoint; + +/** + * Entry point classes define onModuleLoad(). + */ +public class iJab implements EntryPoint +{ + + /** + * This is the entry point method. + */ + public void onModuleLoad() + { + defineBridgeMethod(); + /* + if(!silent) + { + JabberApp.instance().run(silent); + onUnloadbefore(JabberApp.getConstants().leavePrompt()); + } + */ + } + + public native static void onUnloadbefore(String msg) + /*-{ + window.onbeforeunload = function (evt) + { + var message = msg; + if (typeof evt == 'undefined') { + evt = window.event; + } + if (evt) { + evt.returnValue = message; + } + return message; + } + }-*/; + + public static void talkTo(final String jid) + { + if(JabberApp.instance().connected()) + ChatWindow.openChat(XmppID.parseId(jid)); + else + { + String randomId = createRandomUserName(); + JabberApp.instance().run(randomId,randomId,true,new LoginListener() + { + public void onLogined() + { + ChatWindow.openChat(XmppID.parseId(jid)); + } + + }); + } + } + + public static void talkTo(final String userName,final String password,final String target) + { + if(JabberApp.instance().connected()) + ChatWindow.openChat(XmppID.parseId(target)); + else + { + JabberApp.instance().run(userName,password,true,new LoginListener() + { + public void onLogined() + { + ChatWindow.openChat(XmppID.parseId(target)); + } + + }); + } + } + + private static String createRandomUserName() + { + char[] s = new char[5]; + char itoh[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + for (int i = 0; i < 5; i++) + { + s[i] = (char) Math.floor(Math.random()*0x10); + } + + //s[14] = 4; + //s[19] =(char) ((s[19] & 0x3) | 0x8); + + for (int i = 0; i < 5; i++) + s[i] = itoh[s[i]]; + + //s[8] = s[13] = s[18] = s[23] = '-'; + + return (("Visitor")+ "("+new String(s)+")"); + } + + public static void loginUser(final String user,final String password, boolean silent) + { + JabberApp.instance().run(user,password,silent,null); + } + + public static void loginAnonymouse(boolean silent) + { + String randomId = createRandomUserName(); + JabberApp.instance().run(randomId,randomId,silent,null); + } + + public static void login() + { + JabberApp.instance().run(false); + onUnloadbefore(JabberApp.getConstants().leavePrompt()); + } + + public static void logout() + { + JabberApp.instance().logout(); + } + + private native void defineBridgeMethod() + /*-{ + $wnd.talkTo = function(jid) + { + return @com.anzsoft.client.iJab::talkTo(Ljava/lang/String;)(jid); + } + + $wnd.loginUser = function(user,password,silent) + { + return @com.anzsoft.client.iJab::loginUser(Ljava/lang/String;Ljava/lang/String;Z)(user,password,silent); + } + + $wnd.loginAnonymouse = function(silent) + { + return @com.anzsoft.client.iJab::loginAnonymouse(Z)(silent); + } + + $wnd.logoutJabber = function() + { + return @com.anzsoft.client.iJab::logout(); + } + + $wnd.doJabberLogin = function() + { + return @com.anzsoft.client.iJab::login()(); + } + + $wnd.loginAndTalkTo = function(user,password,target) + { + return @com.anzsoft.client.iJab::talkTo(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)(user,password,target); + } + }-*/; +} diff --git a/src/com/anzsoft/client/iJabConstants.java b/src/com/anzsoft/client/iJabConstants.java new file mode 100644 index 0000000..760cd4d --- /dev/null +++ b/src/com/anzsoft/client/iJabConstants.java @@ -0,0 +1,55 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client; + +import com.google.gwt.i18n.client.Constants; + +public interface iJabConstants extends Constants +{ + String login(); + String logout(); + String iJabLogin(); + String user(); + String inputUserId(); + String password(); + String userPassword(); + String moreOptions(); + String host(); + String port(); + String domain(); + String defineServerConfig(); + String online(); + String buddies(); + String freeChat(); + String dnd(); + String away(); + String xa(); + String searchAllContacts(); + String send(); + String typeAMessage(); + String reset(); + String loginPrompt(); + String getRosterPrompt(); + String error(); + String user_or_pwd_error(); + String leavePrompt(); + String visitor(); +} diff --git a/src/com/anzsoft/client/iJabConstants.properties b/src/com/anzsoft/client/iJabConstants.properties new file mode 100644 index 0000000..f7eb2fc --- /dev/null +++ b/src/com/anzsoft/client/iJabConstants.properties @@ -0,0 +1,28 @@ +login = Login +iJabLogin = iJab Login +user = User +inputUserId = Input user id +password = password +userPassword = User password +moreOptions = More Options +host = Host +port = Port +domain = Domain +defineServerConfig = Set Server Config +buddies = Buddies +online = Online +freeChat = Free Chat +dnd = Do not disturb +away = Away +xa = Extended away +searchAllContacts = Search All Contacts +send = Send +typeAMessage = Type a message... +reset = Reset +loginPrompt = Login,Please wait... +getRosterPrompt = Connected,get the roster... +error = Error +user_or_pwd_error = UserName or password error! +logout = Logout +leavePrompt = Are you sure to leave this page?The session will not keep alive! +visitor = Visitor \ No newline at end of file diff --git a/src/com/anzsoft/client/iJabConstants_zh.properties b/src/com/anzsoft/client/iJabConstants_zh.properties new file mode 100644 index 0000000..02f7cb6 --- /dev/null +++ b/src/com/anzsoft/client/iJabConstants_zh.properties @@ -0,0 +1,28 @@ +login = \u767b\u5f55 +iJabLogin = iJab\u767b\u5f55 +user = \u7528\u6237 +inputUserId = \u8f93\u5165\u7528\u6237\u5e10\u6237 +password = \u5bc6\u7801 +userPassword = \u7528\u6237\u5bc6\u7801 +moreOptions = \u66f4\u591a\u9009\u9879 +host = \u670d\u52a1\u5668\u5730\u5740 +port = \u7aef\u53e3 +domain = \u57df +defineServerConfig = \u81ea\u5b9a\u4e49\u670d\u52a1\u5668 +buddies = \u8054\u7cfb\u4eba +online = \u5728\u7ebf +freeChat = \u81ea\u7531\u804a\u5929 +dnd = \u8bf7\u52ff\u6253\u6270 +away = \u79bb\u5f00 +xa = \u957f\u65f6\u95f4\u79bb\u5f00 +searchAllContacts = \u641c\u7d22\u8054\u7cfb\u4eba +send = \u53d1\u9001 +typeAMessage = \u8f93\u5165\u6d88\u606f... +reset = \u91cd\u7f6e +loginPrompt = \u6b63\u5728\u767b\u5f55\uff0c\u8bf7\u7a0d\u7b49... +getRosterPrompt = \u6b63\u5728\u83b7\u53d6\u7528\u6237\u5217\u8868\uff0c\u8bf7\u7a0d\u7b49... +error = \u9519\u8bef +user_or_pwd_error = \u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef +logout = \u6ce8\u9500 +leavePrompt = \u60a8\u786e\u8ba4\u8981\u79bb\u5f00iJab\u9875\u9762\uff1fiJab\u4f1a\u8bdd\u5c06\u4f1a\u88ab\u5173\u95ed\uff01 +visitor = \u6e38\u5ba2 \ No newline at end of file diff --git a/src/com/anzsoft/client/ui/BasicDialog.java b/src/com/anzsoft/client/ui/BasicDialog.java new file mode 100644 index 0000000..3c55df6 --- /dev/null +++ b/src/com/anzsoft/client/ui/BasicDialog.java @@ -0,0 +1,68 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.ui; + +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.widget.Window; + + + +public class BasicDialog extends Window { + + public BasicDialog(final String caption, final boolean modal, final boolean autoScroll) { + setAutoWidth(true); + // Param values + setTitle(caption); + setModal(modal); + //setAutoScroll(autoScroll); + // Def values + setShadow(true); + setPlain(true); + setClosable(true); + setCollapsible(true); + setResizable(true); + this.setCloseAction(CloseAction.HIDE); + //setCloseAction(Window.HIDE); + this.setButtonAlign(HorizontalAlignment.RIGHT); + } + + public BasicDialog(final String caption, final boolean modal) { + this(caption, modal, false); + } + + public BasicDialog(final String caption, final boolean modal, final boolean autoScroll, final int width, + final int height, final int minWidth, final int minHeight) { + this(caption, modal, autoScroll); + setAutoWidth(false); + // Param values + setWidth(width); + setHeight(height); + setMinWidth(minWidth); + setMinHeight(minHeight); + } + + public BasicDialog(final String caption, final boolean modal, final boolean autoScroll, final int width, + final int height) { + this(caption, modal, autoScroll, width, height, width, height); + } + +} + diff --git a/src/com/anzsoft/client/ui/ChatWindow.java b/src/com/anzsoft/client/ui/ChatWindow.java new file mode 100644 index 0000000..6ac4f44 --- /dev/null +++ b/src/com/anzsoft/client/ui/ChatWindow.java @@ -0,0 +1,452 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.ui; + +import java.util.ArrayList; +import java.util.List; + +import com.allen_sauer.gwt.voices.client.Sound; +import com.allen_sauer.gwt.voices.client.SoundController; +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.mandioca.XmppChat; +import com.anzsoft.client.utils.ChatTextFormatter; +import com.anzsoft.client.utils.emotions.EmoticonPaletteListener; +import com.anzsoft.client.utils.emotions.EmoticonPalettePanel; +import com.extjs.gxt.ui.client.Events; +import com.extjs.gxt.ui.client.Style.Scroll; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.ComponentEvent; +import com.extjs.gxt.ui.client.event.KeyListener; +import com.extjs.gxt.ui.client.event.Listener; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.event.WindowEvent; +import com.extjs.gxt.ui.client.widget.ContentPanel; +import com.extjs.gxt.ui.client.widget.Html; +import com.extjs.gxt.ui.client.widget.Window; +import com.extjs.gxt.ui.client.widget.WindowManager; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.extjs.gxt.ui.client.widget.layout.TableData; +import com.extjs.gxt.ui.client.widget.toolbar.AdapterToolItem; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.ImageElement; +import com.google.gwt.dom.client.Style; +import com.google.gwt.dom.client.TableElement; +import com.google.gwt.i18n.client.DateTimeFormat; + +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.ui.Widget; + + +public class ChatWindow extends Window +{ + static private List chatWindows = new ArrayList(); + static private Window lastActive = null; + static public ChatWindow openChat(XmppID id) + { + String bareJid = id.toStringNoResource(); + ChatWindow window = get(bareJid); + if(window == null) + { + XmppChat chat = JabberApp.instance().getSession().openChat(id.getNode(), id.getDomain()); + window = new ChatWindow(bareJid,chat); + registerChatWindow(window); + } + + + /* + if(lastActive != null&&lastActive != window) + window.setPosition(lastActive.getPosition(true).x+20, lastActive.getPosition(true).y + 20); + */ + + if(!window.isVisible()) + window.setVisible(true); + + WindowManager.get().bringToFront(window); + lastActive = window; + return window; + } + + static public void clear() + { + int count = chatWindows.size(); + for (int i = 0; i < count; i++) { + ChatWindow w = (ChatWindow) chatWindows.get(i); + w.close(); + w.removeFromParent(); + } + chatWindows.clear(); + lastActive = null; + } + + static void registerChatWindow(ChatWindow window) + { + chatWindows.add(window); + } + + static void unRegisterChatWindow(String jid) + { + ChatWindow window = get(jid); + if(window == null) + return; + chatWindows.remove(window); + } + + private static ChatWindow get(String jid) + { + int count = chatWindows.size(); + for (int i = 0; i < count; i++) { + ChatWindow w = (ChatWindow) chatWindows.get(i); + if (jid.equals(w.getJid())) { + return w; + } + } + return null; + } + + private final ContentPanel childPanel; + private Button emoticonButton; + private Button sendButton; + private EmoticonPalettePanel emoticonPalettePanel; + + private TextField input; + private String jid; + + private XmppChat chat; + private boolean lastIsLocal = false; + private String lastMsgID = null; + + private ChatWindow(final String jid,XmppChat chat) + { + this.jid = jid; + this.chat = chat; + + setLayout(new FitLayout()); + + setClosable(true); + //setCloseAction(CloseAction.HIDE); + setCloseAction(CloseAction.HIDE); + + childPanel = new ContentPanel(); + childPanel.addStyleName("message_view"); + childPanel.setHeaderVisible(false); + childPanel.setBorders(false); + childPanel.setFrame(false); + childPanel.setHeight("100%"); + childPanel.setScrollMode(Scroll.AUTO); + + add(childPanel); + + setBottomComponent(createBottomWidget()); + setWidth(400); + setHeight(300); + updateCaption(); + setMinimizable(false); + setCollapsible(true); + setAnimCollapse(true); + setMaximizable(true); + setFocusWidget(input); + + this.addListener(Events.Show, new Listener() + { + public void handleEvent(WindowEvent be) + { + input.focus(); + } + + }); + + this.addListener(Events.Close, new Listener() + { + + public void handleEvent(WindowEvent be) + { + if(lastActive == be.window) + lastActive = null; + } + + }); + input.focus(); + } + + private InputContainer createBottomWidget() + { + InputContainer inputContainer = new InputContainer(); + //inputContainer.setWidth("99%"); + + input = new TextField(); + input.setWidth("100%"); + input.setEmptyText(JabberApp.getConstants().typeAMessage()); + input.addKeyListener(new KeyListener() + { + public void componentKeyPress(ComponentEvent event) + { + if(event.getKeyCode() == 13) + doSend(); + } + }); + TableData data = new TableData(); + data.setWidth("100%"); + inputContainer.addInputItem(new AdapterToolItem(input), data); + + emoticonButton = new Button(); + emoticonButton.setIconStyle("emoticon_button"); + emoticonButton.setStyleName("x-btn-icon x-btn-focus"); + emoticonButton.setToolTip("Insert a emoticon"); + emoticonButton.addSelectionListener(new SelectionListener() + { + public void componentSelected(ButtonEvent ce) + { + showEmoticonPalette(emoticonButton.getElement().getAbsoluteLeft(),emoticonButton.getElement().getAbsoluteTop()); + } + + }); + + data = new TableData(); + data.setWidth("30px"); + inputContainer.addInputItem(new AdapterToolItem(emoticonButton), data); + + sendButton = new Button(JabberApp.getConstants().send()); + sendButton.addSelectionListener(new SelectionListener() + { + public void componentSelected(ButtonEvent ce) + { + doSend(); + } + }); + + data = new TableData(); + data.setWidth("30px"); + inputContainer.addInputItem(new AdapterToolItem(sendButton), data); + + return inputContainer; + } + + private void showEmoticonPalette(final int x, final int y) + { + if (emoticonPalettePanel == null) { + emoticonPalettePanel = new EmoticonPalettePanel(new EmoticonPaletteListener() { + public void onEmoticonSelected(final String emoticonText) { + setInputText(getInputText() + " " + emoticonText + " "); + emoticonPalettePanel.hide(); + input.focus(); + } + }); + } + emoticonPalettePanel.showAt(x, y); + } + + public String getInputText() + { + return input.getRawValue(); + } + + private void updateCaption() + { + String nick = JabberApp.instance().getContactNick(jid); + String status = JabberApp.instance().getContactStatusText(jid); + if(nick == null || nick.isEmpty()) + nick = this.jid; + if(status == null||status.isEmpty()) + setHeading(nick); + else + setHeading(nick+"("+status+")"); + setIconStyle("chat-icon"); + } + + public void setInputText(final String text) + { + input.setRawValue(text); + } + + public void addMessage(final String userAlias,final String message,boolean local) + { + if(lastMsgID!=null&&lastIsLocal == local) + { + Element msgDiv = DOM.getElementById(lastMsgID); + if(msgDiv != null) + { + Element messageElement = DOM.createSpan(); + messageElement.setInnerHTML("
"+ChatTextFormatter.format(message == null ? "" : message).getHTML()); + msgDiv.appendChild(messageElement); + if (childPanel.isRendered()) + { + childPanel.layout(); + } + childPanel.fly((com.google.gwt.user.client.Element) messageElement).scrollIntoView(childPanel.getLayoutTarget().dom, true); + return; + } + } + String messageString = createMessage(userAlias,message).getString(); + Html messageHtml = new Html(messageString); + addWidget(messageHtml); + lastIsLocal = local; + } + + private DivElement createMessage(final String user,final String message) + { + Element element = DOM.createDiv(); + DivElement messageDiv = DivElement.as(element); + lastMsgID = DOM.createUniqueId(); + messageDiv.setId(lastMsgID); + messageDiv.setClassName("selected-article"); + + //create the avatar table + element = DOM.createTable(); + TableElement avatarTable = TableElement.as(element); + messageDiv.appendChild(avatarTable); + avatarTable.setAttribute("hspace", "4"); + avatarTable.setAttribute("cellspacing","0"); + avatarTable.setAttribute("vspace", "2"); + avatarTable.setAttribute("border", "0"); + avatarTable.setAttribute("align", "left"); + + Element tbodyElement = DOM.createTBody(); + avatarTable.appendChild(tbodyElement); + + Element trElement = DOM.createTR(); + tbodyElement.appendChild(trElement); + + Element tdElement = DOM.createTD(); + trElement.appendChild(tdElement); + tdElement.setAttribute("height", "45"); + tdElement.setAttribute("width", "45"); + tdElement.setAttribute("align", "middle"); + Style style = tdElement.getStyle(); + style.setProperty("border", "1px solid black"); + style.setProperty("background-color", "white"); + + Element imgElement = DOM.createImg(); + ImageElement imageElement = ImageElement.as(imgElement); + tdElement.appendChild(imageElement); + imageElement.setAttribute("height", "45"); + imageElement.setAttribute("widht", "45"); + imageElement.setSrc(JabberApp.instance().getAvatarUrl(jid)); + + tdElement = DOM.createTD(); + tdElement.setInnerHTML("  "); + trElement.appendChild(tdElement); + + //create the div for timestamp and nick + element = DOM.createDiv(); + DivElement tnDiv = DivElement.as(element); + tnDiv.setClassName("msg_header"); + messageDiv.appendChild(tnDiv); + //style = tnDiv.getStyle(); + //style.setProperty("border-bottom", "1px solid black"); + + element = DOM.createTable(); + TableElement tnTableElement = TableElement.as(element); + tnDiv.appendChild(tnTableElement); + tnTableElement.setAttribute("cellspacing", "0"); + tnTableElement.setAttribute("cellpadding", "0"); + tnTableElement.setAttribute("width", "80%"); + tnTableElement.setAttribute("border", "0"); + + tbodyElement = DOM.createTBody(); + tnTableElement.appendChild(tbodyElement); + + trElement = DOM.createTR(); + tbodyElement.appendChild(trElement); + + Element nickElement = DOM.createTD(); + trElement.appendChild(nickElement); + nickElement.setClassName("msg-nick"); + nickElement.setAttribute("valign", "bottom"); + nickElement.setAttribute("align", "left"); + nickElement.setInnerHTML(""+user+""); + + Element timeElement = DOM.createTD(); + trElement.appendChild(timeElement); + timeElement.setClassName("msg-nick"); + timeElement.setAttribute("valign","bottom"); + timeElement.setAttribute("align", "right"); + DateTimeFormat timeFormat = DateTimeFormat.getMediumTimeFormat(); + String datetime = timeFormat.format(new java.util.Date()); + timeElement.setInnerHTML(""+datetime+""); + + Element messageElement = DOM.createSpan(); + messageElement.setInnerHTML(ChatTextFormatter.format(message == null ? "" : message).getHTML()); + + messageDiv.appendChild(messageElement); + return messageDiv; + } + + private void addWidget(final Widget widget) + { + childPanel.add(widget); + if (childPanel.isRendered()) + { + childPanel.layout(); + } + childPanel.scrollIntoView(widget); + } + + private void doSend() + { + final String inputText = getInputText(); + if(inputText.isEmpty()) + { + input.focus(); + return; + } + + SoundController soundController = new SoundController(); + Sound sound = soundController.createSound(Sound.MIME_TYPE_AUDIO_MPEG, + "sound/im_send.wav"); + sound.play(); + + addMessage(XmppID.parseId(JabberApp.instance().getSession().getUser().getID()).toStringNoResource(),inputText,true); + chat.sendMessage(inputText); + setInputText(""); + input.focus(); + } + + + public String getJid() + { + return this.jid; + } + + public static String randomUUID() + { + char[] s = new char[36]; + char itoh[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + for (int i = 0; i < 36; i++) + { + s[i] = (char) Math.floor(Math.random()*0x10); + } + + s[14] = 4; + s[19] =(char) ((s[19] & 0x3) | 0x8); + + for (int i = 0; i < 36; i++) + s[i] = itoh[s[i]]; + + s[8] = s[13] = s[18] = s[23] = '-'; + + return new String(s); + + } +} diff --git a/src/com/anzsoft/client/ui/InputContainer.java b/src/com/anzsoft/client/ui/InputContainer.java new file mode 100644 index 0000000..bd82284 --- /dev/null +++ b/src/com/anzsoft/client/ui/InputContainer.java @@ -0,0 +1,50 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.ui; + +import com.extjs.gxt.ui.client.Style.VerticalAlignment; +import com.extjs.gxt.ui.client.widget.ComponentHelper; +import com.extjs.gxt.ui.client.widget.layout.TableData; +import com.extjs.gxt.ui.client.widget.toolbar.ToolBar; +import com.extjs.gxt.ui.client.widget.toolbar.ToolItem; + +public class InputContainer extends ToolBar +{ + public InputContainer() + { + baseStyle = "x-toolbar"; + layoutOnChange = true; + enableLayout = true; + } + + public boolean addInputItem(ToolItem item,TableData data) + { + int index = getItemCount(); + boolean added = super.insert(item, index); + if (added) + { + data.setVerticalAlign(VerticalAlignment.MIDDLE); + ComponentHelper.setLayoutData(item, data); + } + return added; + } +} diff --git a/src/com/anzsoft/client/ui/LoginDialog.java b/src/com/anzsoft/client/ui/LoginDialog.java new file mode 100644 index 0000000..6ee8084 --- /dev/null +++ b/src/com/anzsoft/client/ui/LoginDialog.java @@ -0,0 +1,167 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.ui; + +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.XMPP.XmppError; +import com.anzsoft.client.XMPP.XmppEventAdapter; +import com.extjs.gxt.ui.client.Events; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.ComponentEvent; +import com.extjs.gxt.ui.client.event.KeyListener; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.Dialog; +import com.extjs.gxt.ui.client.widget.MessageBox; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.button.StatusButtonBar; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.extjs.gxt.ui.client.widget.layout.FormLayout; + +public class LoginDialog extends Dialog { + + protected StatusButtonBar buttonBar; + protected TextField userName; + protected TextField password; + protected Button reset; + protected Button login; + + public LoginDialog() { + FormLayout layout = new FormLayout(); + layout.setLabelWidth(90); + layout.setDefaultWidth(175); + setLayout(layout); + + setButtons(""); + setIconStyle("user"); + setHeading(JabberApp.getConstants().iJabLogin()); + setModal(false); + setBodyBorder(true); + setInsetBorder(true); + setBodyStyle("padding: 8px;background: none"); + setWidth(350); + setResizable(false); + setClosable(false); + setCollapsible(true); + + KeyListener keyListener = new KeyListener() { + public void componentKeyPress(ComponentEvent event) + { + validate(); + if(event.getKeyCode() == 13&&login.isEnabled()) + { + onSubmit(); + } + } + + }; + + userName = new TextField(); + userName.setMinLength(1); + userName.setFieldLabel(JabberApp.getConstants().user()); + userName.addKeyListener(keyListener); + add(userName); + + password = new TextField(); + password.setMinLength(1); + password.setPassword(true); + password.setFieldLabel(JabberApp.getConstants().password()); + password.addKeyListener(keyListener); + add(password); + + setFocusWidget(userName); + + buttonBar = new StatusButtonBar(); + setButtonBar(buttonBar); + + } + + @Override + protected void createButtons() { + reset = new Button(JabberApp.getConstants().reset()); + reset.addSelectionListener(new SelectionListener() { + public void componentSelected(ButtonEvent ce) { + userName.reset(); + password.reset(); + validate(); + userName.focus(); + buttonBar.getStatusBar().clear(); + buttonBar.enable(); + } + + }); + + login = new Button(JabberApp.getConstants().login()); + login.disable(); + login.addSelectionListener(new SelectionListener() { + public void componentSelected(ButtonEvent ce) { + onSubmit(); + } + }); + + buttonBar.add(reset); + buttonBar.add(login); + } + + protected void onSubmit() + { + buttonBar.getStatusBar().showBusy(JabberApp.getConstants().loginPrompt()); + buttonBar.disable(); + XmppEventAdapter xmppEventAdapter = new XmppEventAdapter() + { + public void onConnect() + { + buttonBar.getStatusBar().showBusy(JabberApp.getConstants().getRosterPrompt()); + } + + public void onDisconnect() + { + + } + + public void onError(final XmppError error) + { + //buttonBar.getStatusBar().showBusy("Login error:"+error.toString()); + MessageBox.alert(JabberApp.getConstants().error(), JabberApp.getConstants().user_or_pwd_error(), null); + reset.fireEvent(Events.Select); + } + + public void onResume() + { + //buttonBar.getStatusBar().showBusy("On Resume"); + } + + public void onStatusChanged(final String status) + { + //buttonBar.getStatusBar().showBusy(status); + } + }; + JabberApp.instance().onLogin(userName.getValue(),password.getValue(), xmppEventAdapter); + } + + protected boolean hasValue(TextField field) { + return field.getValue() != null && field.getValue().length() > 0; + } + + protected void validate() { + login.setEnabled(hasValue(userName) && hasValue(password) && password.getValue().length() > 3); + } + +} diff --git a/src/com/anzsoft/client/ui/LoginForm.java b/src/com/anzsoft/client/ui/LoginForm.java new file mode 100644 index 0000000..9a3a9be --- /dev/null +++ b/src/com/anzsoft/client/ui/LoginForm.java @@ -0,0 +1,170 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.ui; + +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.iJabConstants; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.CheckBox; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.DisclosurePanel; +import com.google.gwt.user.client.ui.FlexTable; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.PasswordTextBox; +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; + + +public class LoginForm extends SimplePanel +{ + public LoginForm() + { + add(createAdvancedForm()); + //setWidget(createAdvancedForm()); + } + + private Widget createAdvancedForm() + { + iJabConstants constants = (iJabConstants) GWT.create(iJabConstants.class); + // Create a table to layout the form options + FlexTable layout = new FlexTable(); + layout.setCellSpacing(6); + layout.setWidth("300px"); + FlexCellFormatter cellFormatter = layout.getFlexCellFormatter(); + + // Add a title to the form + /* + layout.setHTML(0, 0,constants.iJabLogin()); + cellFormatter.setColSpan(0, 0, 2); + cellFormatter.setHorizontalAlignment(0, 0, + HasHorizontalAlignment.ALIGN_CENTER); + */ + // Add some standard form options + final TextBox userBox = new TextBox(); + userBox.setText("imdev"); + layout.setHTML(0, 0, constants.user()); + layout.setWidget(0, 1, userBox); + final PasswordTextBox passBox = new PasswordTextBox (); + passBox.setText("imdev631"); + + layout.setHTML(1, 0, constants.password()); + layout.setWidget(1, 1, passBox); + + // Create some advanced options + Grid advancedOptions = new Grid(5, 2); + advancedOptions.setCellSpacing(6); + + final TextBox hostBox = new TextBox(); + final TextBox portBox = new TextBox(); + final TextBox domainBox = new TextBox(); + final CheckBox authCheck = new CheckBox("SASL"); + authCheck.setChecked(false); + + hostBox.setEnabled(false); + portBox.setEnabled(false); + domainBox.setEnabled(false); + authCheck.setEnabled(false); + + final CheckBox serverConfig = new CheckBox(constants.defineServerConfig()); + advancedOptions.setWidget(0, 0, serverConfig); + serverConfig.addClickListener(new ClickListener() + { + public void onClick(Widget sender) { + if(serverConfig.isChecked()) + { + hostBox.setEnabled(true); + portBox.setEnabled(true); + domainBox.setEnabled(true); + authCheck.setEnabled(true); + } + else + { + hostBox.setEnabled(false); + portBox.setEnabled(false); + domainBox.setEnabled(false); + authCheck.setEnabled(false); + } + + } + + }); + + serverConfig.setChecked(false); + + advancedOptions.setHTML(1, 0, constants.domain()); + advancedOptions.setWidget(1, 1, hostBox); + + advancedOptions.setHTML(2, 0, constants.host()); + advancedOptions.setWidget(2, 1, portBox); + + advancedOptions.setHTML(3, 0, constants.port()); + advancedOptions.setWidget(3, 1, domainBox); + + advancedOptions.setWidget(4, 0, authCheck); + + // Add advanced options to form in a disclosure panel + DisclosurePanel advancedDisclosure = new DisclosurePanel( + constants.moreOptions()); + advancedDisclosure.setAnimationEnabled(true); + advancedDisclosure.ensureDebugId("cwDisclosurePanel"); + advancedDisclosure.setContent(advancedOptions); + layout.setWidget(2, 0, advancedDisclosure); + + Button loginButton = new Button(constants.login()); + + layout.setWidget(3, 0,loginButton); + loginButton.addSelectionListener(new SelectionListener() + { + public void componentSelected(ButtonEvent ce) + { + String user = userBox.getText(); + String pass = passBox.getText(); + String domain = domainBox.getText(); + String host = domainBox.getText(); + boolean sasl = authCheck.isChecked(); + if(serverConfig.isChecked()) + { + int port = Integer.parseInt(portBox.getText()); + //JabberApp.instance().onLogin(host, port, domain, sasl, user, pass); + } + else + { + //JabberApp.instance().onLogin(user, pass); + } + } + + }); + + cellFormatter.setHorizontalAlignment(3, 0, + HasHorizontalAlignment.ALIGN_CENTER); + + cellFormatter.setColSpan(3, 0, 2); + + return layout; + } +} diff --git a/src/com/anzsoft/client/ui/MainWindow.java b/src/com/anzsoft/client/ui/MainWindow.java new file mode 100644 index 0000000..8eadca3 --- /dev/null +++ b/src/com/anzsoft/client/ui/MainWindow.java @@ -0,0 +1,87 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.ui; + +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.mandioca.XmppSession; +import com.extjs.gxt.ui.client.Style.HorizontalAlignment; +import com.extjs.gxt.ui.client.event.ButtonEvent; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.Window; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.button.StatusButtonBar; +import com.extjs.gxt.ui.client.widget.layout.RowData; +import com.extjs.gxt.ui.client.widget.layout.RowLayout; + + +public class MainWindow extends Window +{ + private RosterPanel rosterPanel; + private UserIndicator indicator; + protected StatusButtonBar buttonBar; + + private Button logoutButton; + public MainWindow(XmppSession session) + { + setLayout(new RowLayout()); + setWidth(280); + setHeight(600); + setHeading("iJab"); + //setIconCls("MainWindow-Icon"); + setClosable(false); + setCollapsible(true); + setAnimCollapse(true); + //setCls("MainWindow"); + this.setMinimizable(false); + this.setMaximizable(true); + + rosterPanel = new RosterPanel(JabberApp.getConstants().buddies()); + indicator = new UserIndicator(XmppID.parseId(session.getUser().toString()).getNode()); + add(indicator,new RowData(1,-1)); + add(rosterPanel,new RowData(1,1)); + + buttonBar = new StatusButtonBar(); + buttonBar.setButtonAlign(HorizontalAlignment.LEFT); + setButtonBar(buttonBar); + + logoutButton = new Button(JabberApp.getConstants().logout()); + logoutButton.addSelectionListener(new SelectionListener() + { + public void componentSelected(ButtonEvent ce) + { + JabberApp.instance().logout(); + } + }); + + buttonBar.add(logoutButton); + } + + public RosterPanel getRosterPanel() + { + return this.rosterPanel; + } + + public UserIndicator getIndicator() + { + return this.indicator; + } +} diff --git a/src/com/anzsoft/client/ui/RosterPanel.java b/src/com/anzsoft/client/ui/RosterPanel.java new file mode 100644 index 0000000..782be48 --- /dev/null +++ b/src/com/anzsoft/client/ui/RosterPanel.java @@ -0,0 +1,407 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.ui; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.utils.ChatIcons; +import com.extjs.gxt.ui.client.Events; +import com.extjs.gxt.ui.client.Style.SelectionMode; +import com.extjs.gxt.ui.client.Style.SortDir; +import com.extjs.gxt.ui.client.data.BaseModel; +import com.extjs.gxt.ui.client.data.ModelData; +import com.extjs.gxt.ui.client.event.ComponentEvent; +import com.extjs.gxt.ui.client.event.GridEvent; +import com.extjs.gxt.ui.client.event.KeyListener; +import com.extjs.gxt.ui.client.event.Listener; +import com.extjs.gxt.ui.client.store.GroupingStore; +import com.extjs.gxt.ui.client.store.ListStore; +import com.extjs.gxt.ui.client.store.Store; +import com.extjs.gxt.ui.client.store.StoreFilter; +import com.extjs.gxt.ui.client.util.Format; +import com.extjs.gxt.ui.client.util.Params; +import com.extjs.gxt.ui.client.widget.ContentPanel; +import com.extjs.gxt.ui.client.widget.form.TextField; +import com.extjs.gxt.ui.client.widget.grid.ColumnConfig; +import com.extjs.gxt.ui.client.widget.grid.ColumnData; +import com.extjs.gxt.ui.client.widget.grid.ColumnModel; +import com.extjs.gxt.ui.client.widget.grid.Grid; +import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer; +import com.extjs.gxt.ui.client.widget.grid.GridGroupRenderer; +import com.extjs.gxt.ui.client.widget.grid.GroupColumnData; +import com.extjs.gxt.ui.client.widget.grid.GroupingView; +import com.extjs.gxt.ui.client.widget.layout.FitLayout; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.Image; + +import com.anzsoft.client.XMPP.XmppID; +import com.anzsoft.client.XMPP.mandioca.XmppContact; +import com.anzsoft.client.XMPP.mandioca.XmppContactStatus; + + +public class RosterPanel extends ContentPanel +{ + + public class ContactData extends BaseModel + { + /** + * + */ + private static final long serialVersionUID = 1L; + + public ContactData() + { + + } + + public ContactData(final String img,final String jid,final String alias,final String statusImg, + final String statusText,final String group,int statusValue) + { + set(IMG,img); + set(JID,jid); + set(ALIAS,alias); + set(STATUSIMG,statusImg); + set(STATUSTEXT,statusText); + set(USER_GROUP_DD,group); + set(STATUSVALUE,statusValue); + + } + } + public static final String USER_GROUP_DD = "userGroupDD"; + public static final String JID = "jid"; + public static final int DEFAULT_INITIAL_WIDTH = 150; + private static final String ALIAS = "alias"; + //private static final String COLOR = "color"; + private static final String IMG = "img"; + public static final String STATUSIMG = "status"; + public static final String STATUSTEXT = "statustext"; + public static final String STATUSVALUE = "statusvalue"; + + private GroupingStore store; + private Grid grid; + //private StoreFilterField filterField; + + public RosterPanel(final String emptyText) + { + setBorders(false); + setHeaderVisible(false); + setWidth("100%"); + setHeight("100%"); + setLayout(new FitLayout()); + createGrid(emptyText); + setTopComponent(createFilterToolBar()); + } + + public void setRoster(final Map contacts) + { + store.removeAll(); + for(String jid : contacts.keySet()) + { + XmppContact contact = contacts.get(jid); + addContact(contact); + } + store.groupBy(USER_GROUP_DD); + doLayoutIfNeeded(); + } + + public void addContact(XmppContact contact) + { + final String statusIcon = formatStatusIcon(contact.getStatus()); + addRecord(contact,statusIcon); + } + + private void addRecord(final XmppContact contact,final String statusIcon) + { + String alias = contact.getName(); + if(alias == null || alias.isEmpty()) + { + alias = contact.getJID().getNode(); + } + final String jid = contact.getJID().toString(); + final String statusFormated = formatStatus(contact.getStatus()); + String group = JabberApp.getConstants().buddies(); + if(contact.getGroups().size()>0) + group = contact.getGroups().get(0); + if(group!=null&&group.equalsIgnoreCase("@everybody@")) + group = JabberApp.getConstants().buddies(); + + final ContactData data = new ContactData(contact.getAvatar(),jid, alias, + statusIcon, statusFormated,group,contact.getStatus().type().ordinal()); + store.add(data); + //sort(); + //doLayoutIfNeeded(); + } + + public ContactData getContactData(final String bareJid) + { + return store.findModel(JID, bareJid); + } + + public String getContactNick(final String bareJid) + { + final ContactData data = store.findModel(JID, bareJid); + if(data == null) + return null; + return data.get(ALIAS); + } + + public String getContactStatusText(final String bareJid) + { + final ContactData data = store.findModel(JID, bareJid); + if(data == null) + return null; + return data.get("statustext"); + } + + public String getAvatarUrl(final String bareJid) + { + final ContactData data = store.findModel(JID, bareJid); + if(data == null) + return null; + return data.get(IMG); + } + + public void updateContactStatus(final String jid,final XmppContactStatus status) + { + final ContactData dataToUpdate = store.findModel(JID, jid); + if(dataToUpdate == null) + return; + final String statusFormated = formatStatus(status); + dataToUpdate.set(STATUSTEXT, statusFormated); + dataToUpdate.set(STATUSIMG, formatStatusIcon(status)); + dataToUpdate.set(STATUSVALUE, status.type().ordinal()); + store.update(dataToUpdate); + //store.commitChanges(); + sort(); + doLayoutIfNeeded(); + } + + public void setWidth(final int width) + { + // Log.info("Grid width: " + width); + grid.setWidth(width - 27); + super.setWidth(width - 25); + doLayoutIfNeeded(); + } + + private void sort() + { + store.sort(STATUSVALUE,SortDir.DESC); + } + + private void doLayoutIfNeeded() + { + if (isRendered()) + { + this.doLayout(); + } + } + + private TextField createFilterToolBar() + { + final TextField field = new TextField(); + field.setEmptyText(JabberApp.getConstants().searchAllContacts()); + field.setWidth("100%"); + StoreFilter filter = new StoreFilter() + { + public boolean select(Store store, ContactData parent, + ContactData item, String property) + { + String filterText = field.getRawValue(); + String alias = item.get(ALIAS); + String jid = item.get(JID); + if(alias.startsWith(filterText.toLowerCase())||jid.startsWith(filterText.toLowerCase())) + return true; + return false; + } + + }; + store.addFilter(filter); + + field.addKeyListener(new KeyListener() + { + public void componentKeyUp(ComponentEvent event) + { + if(field.getRawValue().length()>0) + store.applyFilters(""); + else + store.clearFilters(); + } + }); + return field; + } + + private void createGrid(String emptyText) + { + store = new GroupingStore (); + store.setSortField(STATUSVALUE); + ColumnConfig avatarColumnConfig = new ColumnConfig(IMG,"Image",44); + avatarColumnConfig.setRenderer(new GridCellRenderer() + { + + public String render(ModelData model, String property, + ColumnData config, int rowIndex, int colIndex, + ListStore store) + { + Params p = new Params(); + String img = model.get(IMG); + p.add(img); + return Format.substitute("
", p); + } + + }); + avatarColumnConfig.setFixed(true); + + + ColumnConfig statusImgColumnConfig = new ColumnConfig(STATUSIMG,"Status", 20); + statusImgColumnConfig.setRenderer(new GridCellRenderer() + { + public String render(ModelData model, String property, + ColumnData config, int rowIndex, int colIndex, + ListStore store) + { + Params p = new Params(); + p.add(model.get(STATUSIMG)); + return Format.substitute("{0}", p); + } + + }); + statusImgColumnConfig.setFixed(true); + + ColumnConfig groupColumnConfig = new ColumnConfig(USER_GROUP_DD,"Group", 0); + groupColumnConfig.setHidden(true); + + ColumnConfig aliasColumnConfig = new ColumnConfig(ALIAS,"Alias",32); + aliasColumnConfig.setRenderer(new GridCellRenderer() + { + public String render(ModelData model, String property, + ColumnData config, int rowIndex, int colIndex, + ListStore store) + { + Params p = new Params(); + p.add(model.get(ALIAS)); + p.add(model.get(STATUSTEXT)); + return Format.substitute("{0}
{1}", + p); + } + + }); + + List config = new ArrayList(); + config.add(statusImgColumnConfig); + config.add(aliasColumnConfig); + config.add(avatarColumnConfig); + config.add(groupColumnConfig); + final ColumnModel columnModel = new ColumnModel(config); + + + + final GroupingView view = new GroupingView(); + // i18n + view.setForceFit(true); + view.setGroupRenderer(new GridGroupRenderer() + { + public String render(GroupColumnData data) + { + int total = data.models.size(); + int online = 0; + for(int index = 0;index grid = new Grid(store,columnModel); + grid.setWidth("100%"); + grid.setHeight("100%"); + grid.setView(view); + grid.setHideHeaders(true); + grid.setBorders(false); + grid.setStyleName("roster_list"); + grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + grid.addListener(Events.RowClick , new Listener() + { + public void handleEvent(GridEvent be) + { + List datas = store.getModels(); + ContactData data = datas.get(be.rowIndex); + String jid = data.get(JID); + ChatWindow.openChat(XmppID.parseId(jid)); + } + + }); + + super.add(grid); + } + + private String formatStatusIcon(XmppContactStatus status) + { + final AbstractImagePrototype icon = iconFromStatus(status); + final Image iconImg = new Image(); + icon.applyTo(iconImg); + return iconImg.toString(); + } + + private String formatStatus(XmppContactStatus status) + { + if(status.status() == null||status.status().isEmpty()) + return status.type().toString(); + else + return status.status(); + } + + private AbstractImagePrototype iconFromStatus(XmppContactStatus status) + { + + final ChatIcons icons = ChatIcons.App.getInstance(); + switch(status.type()) + { + case Online: + return icons.online(); + case Offline: + return icons.offline(); + case Invisible: + return icons.offline(); + case DND: + return icons.busy(); + case XA: + return icons.xa(); + case Away: + return icons.away(); + case FFC: + return icons.chat(); + } + return icons.offline(); + + } +} diff --git a/src/com/anzsoft/client/ui/UserIndicator.java b/src/com/anzsoft/client/ui/UserIndicator.java new file mode 100644 index 0000000..a9f0dde --- /dev/null +++ b/src/com/anzsoft/client/ui/UserIndicator.java @@ -0,0 +1,364 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.ui; + +import com.anzsoft.client.JabberApp; +import com.anzsoft.client.iJabConstants; +import com.anzsoft.client.XMPP.PresenceShow; +import com.anzsoft.client.XMPP.XmppPresence; +import com.anzsoft.client.XMPP.mandioca.XmppContactStatus; +import com.anzsoft.client.XMPP.mandioca.XmppSession; +import com.anzsoft.client.XMPP.mandioca.XmppUser.XmppUserListener; +import com.anzsoft.client.utils.ChatIcons; +import com.extjs.gxt.ui.client.event.MenuEvent; +import com.extjs.gxt.ui.client.event.SelectionListener; +import com.extjs.gxt.ui.client.widget.button.Button; +import com.extjs.gxt.ui.client.widget.menu.Menu; +import com.extjs.gxt.ui.client.widget.menu.MenuItem; +import com.google.gwt.i18n.client.HasDirection.Direction; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.FlexTable; +import com.google.gwt.user.client.ui.FocusListener; +import com.google.gwt.user.client.ui.HasVerticalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.KeyboardListener; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwt.user.client.ui.VerticalPanel; +import com.google.gwt.user.client.ui.Widget; + + +public class UserIndicator extends FlexTable +{ + private Image statusImg; + private Image avatarImg; + private Label nickName; + private Label statusLabel; + //private Label statusMenuLabel; + private TextBox statusEditor; + private XmppContactStatus status; + //private HorizontalPanel linksPanel; + private Button statusButton; + + private Menu statusMenu; + private MenuItem onlineItem,chatItem,awayItem,dndItem,xaItem; + public UserIndicator(final String nick) + { + createStatusMenu(); + setWidth("100%"); + setCellPadding(0); + setCellSpacing(0); + setStyleName("indicator"); + FlexCellFormatter formatter = getFlexCellFormatter(); + + // Setup the links cell + /* + linksPanel = new HorizontalPanel(); + setWidget(0, 0, linksPanel); + formatter.setStyleName(0, 0, "indicator-links"); + formatter.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_RIGHT); + formatter.setColSpan(0, 0, 2); + */ + + // Setup the title cell + setTitleWidget(null); + formatter.setStyleName(0, 0, "indicator-title"); + + getRowFormatter().setVerticalAlign(0,HasVerticalAlignment.ALIGN_TOP); + getRowFormatter().setVerticalAlign(1,HasVerticalAlignment.ALIGN_TOP); + + + + final ChatIcons icons = ChatIcons.App.getInstance(); + statusImg = new Image(); + statusImg.setWidth("16px"); + statusImg.setHeight("16px"); + icons.online().applyTo(statusImg); + + avatarImg = new Image("images/default_avatar.png"); + avatarImg.setWidth("32px"); + avatarImg.setHeight("32px"); + + nickName = new Label(nick); + nickName.setDirection(Direction.LTR); + nickName.setWidth("100%"); + + statusLabel = new Label(); + statusLabel.setStyleName("status_label"); + statusLabel.setWidth("100%"); + + statusEditor = new TextBox(); + statusEditor.setVisible(false); + statusEditor.setWidth("100%"); + + statusButton = new Button(); + statusButton.setMenu(statusMenu); + statusButton.setStyleName("Status-Menu-Button"); + + //statusMenuLabel = new Label(); + //statusMenuLabel.setStyleName("status_menu_label"); + + //addLink(new HTML("SameSpace")); + // Add the title and some images to the title bar + HorizontalPanel titlePanel = new HorizontalPanel(); + titlePanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE); + titlePanel.setWidth("100%"); + titlePanel.setSpacing(3); + + VerticalPanel statusPanel = new VerticalPanel(); + statusPanel.setWidth("100%"); + statusPanel.add(nickName); + + HorizontalPanel hPanel = new HorizontalPanel(); + hPanel.setWidth("100%"); + hPanel.setSpacing(2); + hPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_TOP); + hPanel.add(statusLabel); + hPanel.add(statusEditor); + hPanel.add(statusButton); + + statusPanel.add(hPanel); + + titlePanel.add(statusImg); + titlePanel.add(statusPanel); + titlePanel.add(avatarImg); + + titlePanel.setCellWidth(statusImg, "20px"); + titlePanel.setCellWidth(statusPanel, "100%"); + titlePanel.setCellWidth(avatarImg, "32px"); + setTitleWidget(titlePanel); + + + JabberApp.instance().getSession().getUser().addUserListener(new XmppUserListener() + { + public void onPresenceChanged(XmppPresence presence) + { + String show = new String(""); + PresenceShow presenceShow = presence.getShow(); + if(presenceShow!=null) + show = presenceShow.toString(); + String statusString = presence.getStatus(); + int priority = presence.getPriority(); + boolean avaiable = true; + String type = presence.getType(); + if(type != null&&!type.isEmpty()) + { + if(type.equalsIgnoreCase("unavailable")) + avaiable = false; + } + status = new XmppContactStatus(show,statusString,priority,avaiable); + statusLabel.setText(status.status()); + iconFromStatus(status).applyTo(statusImg); + } + }); + + statusLabel.addClickListener(new ClickListener() + { + public void onClick(Widget sender) + { + statusLabel.setVisible(false); + statusEditor.setVisible(true); + statusEditor.setText(statusLabel.getText()); + } + + }); + + statusEditor.addKeyboardListener(new KeyboardListener() + { + + public void onKeyDown(Widget sender, char keyCode, int modifiers) + { + + } + public void onKeyPress(Widget sender, char keyCode, int modifiers) + { + + } + + public void onKeyUp(Widget sender, char keyCode, int modifiers) + { + if(keyCode == 13) + doneChangeStatusString(); + } + + }); + + statusEditor.addFocusListener(new FocusListener() + { + public void onFocus(Widget sender) + { + } + + public void onLostFocus(Widget sender) + { + doneChangeStatusString(); + } + + }); + } + + public void setNickName(final String nick) + { + nickName.setText(nick); + } + + private AbstractImagePrototype iconFromStatus(XmppContactStatus status) + { + + final ChatIcons icons = ChatIcons.App.getInstance(); + switch(status.type()) + { + case Online: + return icons.online(); + case Offline: + return icons.offline(); + case Invisible: + return icons.offline(); + case DND: + return icons.busy(); + case XA: + return icons.xa(); + case Away: + return icons.away(); + case FFC: + return icons.chat(); + } + return icons.offline(); + } + + private void doneChangeStatusString() + { + String newStatus = statusEditor.getText(); + if(!newStatus.equalsIgnoreCase(status.status())) + { + String show = status.show(); + XmppSession session = JabberApp.instance().getSession(); + if(show == null||show.isEmpty()) + { + + session.getUser().sendPresence(PresenceShow.emptyShow(), newStatus); + } + else + { + session.getUser().sendPresence(PresenceShow.get(show), newStatus); + } + } + statusLabel.setVisible(true); + statusEditor.setVisible(false); + } + + private void setTitleWidget(Widget title) + { + setWidget(1, 0, title); + } + + /* + private void addLink(Widget link) + { + if (linksPanel.getWidgetCount() > 0) + { + linksPanel.add(new HTML(" | ")); + } + linksPanel.add(link); + } + */ + + private void createStatusMenu() + { + iJabConstants constants = JabberApp.getConstants(); + statusMenu = new Menu(); + + onlineItem = new MenuItem(); + onlineItem.setText(constants.online()); + onlineItem.addSelectionListener(new SelectionListener() + { + public void componentSelected(MenuEvent ce) { + changeShow(""); + + } + }); + + onlineItem.setIconStyle("contact-icon-online"); + statusMenu.add(onlineItem); + + chatItem = new MenuItem(); + chatItem.setText(constants.freeChat()); + chatItem.addSelectionListener(new SelectionListener() + { + public void componentSelected(MenuEvent ce) { + changeShow("chat"); + } + }); + + chatItem.setIconStyle("contact-icon-online"); + statusMenu.add(chatItem); + + awayItem = new MenuItem(); + awayItem.setText(constants.away()); + awayItem.addSelectionListener(new SelectionListener() + { + public void componentSelected(MenuEvent ce) { + changeShow("away"); + } + }); + awayItem.setIconStyle("contact-icon-away"); + statusMenu.add(awayItem); + + dndItem = new MenuItem(); + dndItem.setText(constants.dnd()); + dndItem.setIconStyle("contact-icon-busy"); + dndItem.addSelectionListener(new SelectionListener() + { + public void componentSelected(MenuEvent ce) { + changeShow("dnd"); + } + }); + statusMenu.add(dndItem); + + xaItem = new MenuItem(); + xaItem.setText(constants.xa()); + xaItem.addSelectionListener(new SelectionListener() + { + public void componentSelected(MenuEvent ce) { + changeShow("xa"); + } + }); + xaItem.setIconStyle("contact-icon-busy"); + statusMenu.add(xaItem); + } + + private void changeShow(final String show) + { + if(!show.equals(status.show())) + { + + XmppSession session = JabberApp.instance().getSession(); + if(show == null||show.isEmpty()) + session.getUser().sendPresence(PresenceShow.emptyShow(),status.status()); + else + session.getUser().sendPresence(PresenceShow.get(show),status.status()); + } + } + +} diff --git a/src/com/anzsoft/client/utils/ChatIcons.java b/src/com/anzsoft/client/utils/ChatIcons.java new file mode 100644 index 0000000..d193615 --- /dev/null +++ b/src/com/anzsoft/client/utils/ChatIcons.java @@ -0,0 +1,121 @@ +/* + * + * ((e)) emite: A pure gwt (Google Web Toolkit) xmpp (jabber) library + * + * (c) 2008 The emite development team (see CREDITS for details) + * This file is part of emite. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package com.anzsoft.client.utils; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.ImageBundle; + +public interface ChatIcons extends ImageBundle { + + public static class App { + private static ChatIcons ourInstance = null; + + public static synchronized ChatIcons getInstance() { + if (ourInstance == null) { + ourInstance = (ChatIcons) GWT.create(ChatIcons.class); + } + return ourInstance; + } + } + + @Resource("add.png") + AbstractImagePrototype add(); + + @Resource("away.png") + AbstractImagePrototype away(); + + @Resource("busy.png") + AbstractImagePrototype busy(); + + @Resource("cancel.png") + AbstractImagePrototype cancel(); + + @Resource("chat.png") + AbstractImagePrototype chat(); + + @Resource("chat-new-message-small.png") + AbstractImagePrototype chatNewMessageSmall(); + + @Resource("chat-small.png") + AbstractImagePrototype chatSmall(); + + @Resource("del.png") + AbstractImagePrototype del(); + + @Resource("group-chat.png") + AbstractImagePrototype groupChat(); + + @Resource("info.png") + AbstractImagePrototype info(); + + @Resource("info-lamp.png") + AbstractImagePrototype infoLamp(); + + @Resource("invisible.png") + AbstractImagePrototype invisible(); + + @Resource("message.png") + AbstractImagePrototype message(); + + @Resource("new-chat.png") + AbstractImagePrototype newChat(); + + @Resource("new-email.png") + AbstractImagePrototype newEmail(); + + @Resource("new-message.png") + AbstractImagePrototype newMessage(); + + @Resource("not-authorized.png") + AbstractImagePrototype notAuthorized(); + + @Resource("offline.png") + AbstractImagePrototype offline(); + + @Resource("online.png") + AbstractImagePrototype online(); + + @Resource("question.png") + AbstractImagePrototype question(); + + @Resource("room-new-message-small.png") + AbstractImagePrototype roomNewMessageSmall(); + + @Resource("room-small.png") + AbstractImagePrototype roomSmall(); + + @Resource("unavailable.png") + AbstractImagePrototype unavailable(); + + @Resource("user_add.png") + AbstractImagePrototype userAdd(); + + @Resource("xa.png") + AbstractImagePrototype xa(); + + @Resource("icon-search.gif") + AbstractImagePrototype iconSearch(); + + @Resource("icon-close.gif") + AbstractImagePrototype iconClose(); +} diff --git a/src/com/anzsoft/client/utils/ChatTextFormatter.java b/src/com/anzsoft/client/utils/ChatTextFormatter.java new file mode 100644 index 0000000..54e23f7 --- /dev/null +++ b/src/com/anzsoft/client/utils/ChatTextFormatter.java @@ -0,0 +1,197 @@ +/* + * + * ((e)) emite: A pure gwt (Google Web Toolkit) xmpp (jabber) library + * + * (c) 2008 The emite development team (see CREDITS for details) + * This file is part of emite. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +package com.anzsoft.client.utils; + +import com.anzsoft.client.utils.TextUtils; +import com.anzsoft.client.utils.emotions.Emoticons; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Image; + +public class ChatTextFormatter { + + private static final String JOYFUL = "KuneProtIniJOYFULKuneProtEnd"; + private static final String ANGRY = "KuneProtIniANGRYKuneProtEnd"; + private static final String BLUSHING = "KuneProtIniBLUSHINGKuneProtEnd"; + private static final String CRYING = "KuneProtIniCRYINGKuneProtEnd"; + private static final String POUTY = "KuneProtIniPOUTYKuneProtEnd"; + private static final String SURPRISED = "KuneProtIniSURPRISEDKuneProtEnd"; + private static final String GRIN = "KuneProtIniGRINKuneProtEnd"; + private static final String ANGEL = "KuneProtIniANGELKuneProtEnd"; + private static final String KISSING = "KuneProtIniKISSINGKuneProtEnd"; + private static final String SMILE = "KuneProtIniSMILEKuneProtEnd"; + private static final String TONGUE = "KuneProtIniTONGUEKuneProtEnd"; + private static final String UNCERTAIN = "KuneProtIniUNCERTAINKuneProtEnd"; + private static final String COOL = "KuneProtIniCOOLKuneProtEnd"; + private static final String WINK = "KuneProtIniWINKKuneProtEnd"; + private static final String HAPPY = "KuneProtIniHAPPYKuneProtEnd"; + private static final String ALIEN = "KuneProtIniALIENKuneProtEnd"; + private static final String ANDY = "KuneProtIniANDYKuneProtEnd"; + private static final String DEVIL = "KuneProtIniDEVILKuneProtEnd"; + private static final String LOL = "KuneProtIniLOLKuneProtEnd"; + private static final String NINJA = "KuneProtIniNINJAKuneProtEnd"; + private static final String SAD = "KuneProtIniSADKuneProtEnd"; + private static final String SICK = "KuneProtIniSICKKuneProtEnd"; + private static final String SIDEWAYS = "KuneProtIniSIDEWAYSKuneProtEnd"; + private static final String SLEEPING = "KuneProtIniSLEEPINGKuneProtEnd"; + private static final String UNSURE = "KuneProtIniUNSUREKuneProtEnd"; + private static final String WONDERING = "KuneProtIniWONDERINGKuneProtEnd"; + private static final String LOVE = "KuneProtIniLOVEKuneProtEnd"; + private static final String PINCHED = "KuneProtIniPINCHEDKuneProtEnd"; + private static final String POLICEMAN = "KuneProtIniPOLICEMANKuneProtEnd"; + private static final String W00T = "KuneProtIniWOOTKuneProtEnd"; + private static final String WHISTLING = "KuneProtIniWHISLINGKuneProtEnd"; + private static final String WIZARD = "KuneProtIniWIZARDKuneProtEnd"; + private static final String BANDIT = "KuneProtIniBANDITKuneProtEnd"; + private static final String HEART = "KuneProtIniHEARTKuneProtectRepEnd"; + + public static HTML format(final String messageOrig) { + String message = messageOrig; + message = escapeHtmlLight(message); + message = message.replaceAll("\n", "
\n"); + message = formatUrls(message); + message = formatEmoticons(message); + + return new HTML(message); + } + + static String formatUrls(String message) { + return message = message.replaceAll(TextUtils.URL_REGEXP, "$1"); + } + + static String escapeHtmlLight(String textOrig) + { + String text = textOrig; + text = text.replaceAll("&", "&"); + text = text.replaceAll("\"", """); + text = text.replaceAll("<", "<"); + text = text.replaceAll(">", ">"); + return text; + } + + static String preFormatEmoticons(String message) { + message = replace(message, new String[] { ">:\\)" }, DEVIL); + message = replace(message, new String[] { "O:\\)", "o:\\)", "o:-\\)", "O:-\\)", "0:\\)", "0:-\\)" }, ANGEL); + message = replace(message, new String[] { "\\^_\\^", "\\^-\\^", "\\^\\^", ":\\)\\)", ":-\\)\\)" }, JOYFUL); + message = replace(message, new String[] { "\\(police\\)", "\\(cop\\)", "\\{\\):\\)" }, POLICEMAN); + message = replace(message, new String[] { "=:\\)", "\\(alien\\)" }, ALIEN); + message = replace(message, new String[] { "o_O", "o_0", "O_O", "o_o", "O_o", "0_o", "o0", "0o", "oO", "Oo", + "0_0" }, ANDY); + message = replace(message, new String[] { ">:o", ">:-o", ">:O", ">:-O", "X\\(", "X-\\(", "x\\(", + "x-\\(", ":@", "<_<" }, ANGRY); + message = replace(message, new String[] { "\\(bandit\\)", ":\\(>" }, BANDIT); + message = replace(message, new String[] { ":">", ":\\*>", ":-\\$", ":\\$" }, BLUSHING); + message = replace(message, new String[] { "B\\)", "B-\\)", "8\\)" }, COOL); + message = replace(message, new String[] { ":\'\\(", "=\'\\(" }, CRYING); + message = replace(message, new String[] { ":-d", ":d", ":-D", ":D", ":d", "=D", "=-D" }, GRIN); + message = replace(message, new String[] { "=\\)", "=-\\)" }, HAPPY); + message = replace(message, new String[] { "\\(L\\)", "\\(h\\)", "\\(H\\)" }, HEART); + message = replace(message, new String[] { ":-\\*", ":\\*" }, KISSING); + message = replace(message, new String[] { "\\(LOL\\)", "lol" }, LOL); + message = replace(message, new String[] { ":-X", ":-xX", ":x", "\\(wubya\\)", "\\(wubyou\\)", "\\(wub\\)" }, + LOVE); + message = replace(message, new String[] { "\\(:\\)", "\\(ph33r\\)", "\\(ph34r\\)" }, NINJA); + message = replace(message, new String[] { ">_<" }, PINCHED); + message = replace(message, new String[] { ":\\|", "=\\|", ":-\\|" }, POUTY); + message = replace(message, new String[] { ":\\(", "=\\(", "=-\\(", ":-\\(" }, SAD); + message = replace(message, new String[] { ":&", ":-&" }, SICK); + message = replace(message, new String[] { "=]" }, SIDEWAYS); + message = replace(message, new String[] { "\\(-.-\\)", "\\|\\)", "\\|-\\)", "I-\\)", "I-\\|" }, SLEEPING); + message = replace(message, new String[] { ":-O", ":O", ":-o", ":o", ":-0", "=-O", "=-o", "=o", "=O" }, + SURPRISED); + message = replace(message, new String[] { ":P", "=P", "=p", ":-P", ":p", ":-p", ":b" }, TONGUE); + message = replace(message, new String[] { ":-\\\\", ":-/", ":/", ":\\\\" }, UNCERTAIN); + message = replace(message, new String[] { ":s", ":-S", ":-s", ":S" }, UNSURE); + message = replace(message, new String[] { "\\(woot\\)", "\\(w00t\\)", "\\(wOOt\\)" }, W00T); + message = replace(message, new String[] { ":-"" }, WHISTLING); + message = replace(message, new String[] { ";\\)", ";-\\)", ";>" }, WINK); + message = replace(message, new String[] { "\\(wizard\\)" }, WIZARD); + message = replace(message, new String[] { ":\\?" }, WONDERING); + message = replace(message, new String[] { ":-\\)", ":\\)" }, SMILE); + return message; + } + + private static String formatEmoticons(String message) { + final Emoticons img = Emoticons.App.getInstance(); + + message = preFormatEmoticons(message); + + message = message.replaceAll(SMILE, getImgHtml(img.smile())); + message = message.replaceAll(CRYING, getImgHtml(img.crying())); + message = message.replaceAll(SURPRISED, getImgHtml(img.surprised())); + message = message.replaceAll(ANGEL, getImgHtml(img.angel())); + message = message.replaceAll(HAPPY, getImgHtml(img.happy())); + message = message.replaceAll(GRIN, getImgHtml(img.grin())); + message = message.replaceAll(JOYFUL, getImgHtml(img.joyful())); + message = message.replaceAll(UNCERTAIN, getImgHtml(img.uncertain())); + message = message.replaceAll(ANGRY, getImgHtml(img.angry())); + message = message.replaceAll(TONGUE, getImgHtml(img.tongue())); + message = message.replaceAll(LOVE, getImgHtml(img.love())); + message = message.replaceAll(SLEEPING, getImgHtml(img.sleeping())); + message = message.replaceAll(COOL, getImgHtml(img.cool())); + message = message.replaceAll(KISSING, getImgHtml(img.kissing())); + message = message.replaceAll(SAD, getImgHtml(img.sad())); + message = message.replaceAll(ALIEN, getImgHtml(img.alien())); + message = message.replaceAll(ANDY, getImgHtml(img.andy())); + message = message.replaceAll(BANDIT, getImgHtml(img.bandit())); + message = message.replaceAll(BLUSHING, getImgHtml(img.blushing())); + message = message.replaceAll(DEVIL, getImgHtml(img.devil())); + message = message.replaceAll(HEART, getImgHtml(img.heart())); + message = message.replaceAll(LOL, getImgHtml(img.lol())); + message = message.replaceAll(NINJA, getImgHtml(img.ninja())); + message = message.replaceAll(PINCHED, getImgHtml(img.pinched())); + message = message.replaceAll(POLICEMAN, getImgHtml(img.policeman())); + message = message.replaceAll(POUTY, getImgHtml(img.pouty())); + message = message.replaceAll(SICK, getImgHtml(img.sick())); + message = message.replaceAll(SIDEWAYS, getImgHtml(img.sideways())); + message = message.replaceAll(UNSURE, getImgHtml(img.unsure())); + message = message.replaceAll(W00T, getImgHtml(img.w00t())); + message = message.replaceAll(WINK, getImgHtml(img.wink())); + message = message.replaceAll(WONDERING, getImgHtml(img.wondering())); + message = message.replaceAll(WHISTLING, getImgHtml(img.whistling())); + message = message.replaceAll(WIZARD, getImgHtml(img.wizard())); + + return message; + } + + private static String getImgHtml(final AbstractImagePrototype img) { + final Image image = new Image(); + DOM.setStyleAttribute(image.getElement(), "vertical-align", "bottom"); + img.applyTo(image); + image.setStyleName("vamiddle"); + return img.getHTML(); + } + + private static String replace(String message, final String[] from, final String to) { + for (int j = 0; j < from.length; j++) { + message = message.replaceAll("(^|[\\s])" + from[j] + "([\\s]|$)", "$1" + to + "$2"); + // two times for: :) :) :) :) + message = message.replaceAll("(^|[\\s])" + from[j] + "([\\s]|$)", "$1" + to + "$2"); + } + return message; + } + + public ChatTextFormatter() { + } + +} diff --git a/src/com/anzsoft/client/utils/TextUtils.java b/src/com/anzsoft/client/utils/TextUtils.java new file mode 100644 index 0000000..42d844c --- /dev/null +++ b/src/com/anzsoft/client/utils/TextUtils.java @@ -0,0 +1,66 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.utils; + +public class TextUtils { + + // FIXME this utils are commont to kune, emiteui and emitelib + + // Original regexp from http://snippets.dzone.com/posts/show/452 + public static final String URL_REGEXP = "((ftp|http|https):\\/\\/(\\w+:{0,1}\\w*@)?(\\S+)(:[0-9]+)?(\\/|\\/([\\w#!:.?+=&%@!\\-\\/]))?)"; + + // Original regexp from http://www.regular-expressions.info/email.html + public static final String EMAIL_REGEXP = "[-!#$%&\'*+/=?_`{|}~a-z0-9^]+(\\.[-!#$%&\'*+/=?_`{|}~a-z0-9^]+)*@(localhost|([a-z0-9]([-a-z0-9]*[a-z0-9])?\\.)+[a-z0-9]([-a-z0-9]*[a-z0-9]))?"; + + /* + * This method escape only some dangerous html chars + */ + public static String escape(final String source) { + if (source == null) { + return null; + } + String result = source; + result = result.replaceAll("&", "&"); + result = result.replaceAll("\"", """); + // text = text.replaceAll("\'", "'"); + result = result.replaceAll("<", "<"); + result = result.replaceAll(">", ">"); + return result; + } + + /* + * This method unescape only some dangerous html chars for use in GWT Html + * widget for instance + */ + public static String unescape(final String source) { + if (source == null) { + return null; + } + String result = source; + result = result.replaceAll("&", "&"); + result = result.replaceAll(""", "\""); + result = result.replaceAll("'", "\'"); + result = result.replaceAll("<", "<"); + result = result.replaceAll(">", ">"); + return result; + } +} diff --git a/src/com/anzsoft/client/utils/Thumbs.db b/src/com/anzsoft/client/utils/Thumbs.db new file mode 100644 index 0000000..dec37a7 Binary files /dev/null and b/src/com/anzsoft/client/utils/Thumbs.db differ diff --git a/src/com/anzsoft/client/utils/XMLHelper.java b/src/com/anzsoft/client/utils/XMLHelper.java new file mode 100644 index 0000000..ad8952c --- /dev/null +++ b/src/com/anzsoft/client/utils/XMLHelper.java @@ -0,0 +1,61 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.utils; + +import java.util.ArrayList; + +import com.google.gwt.xml.client.Element; +import com.google.gwt.xml.client.NodeList; + +public class XMLHelper +{ + public static Element queryTag(final Element e) + { + if(e == null) + return null; + NodeList list = e.getElementsByTagName("query"); + if(list.getLength()>0) + return (Element) list.item(0); + else + return null; + } + + public static String queryNS(final Element e) + { + Element queryElement = queryTag(e); + if(queryElement != null) + return queryElement.getAttribute("xmlns"); + else + return ""; + } + + public static ArrayList getSubTagsConents(final Element e,String tagName) + { + ArrayList groups = new ArrayList(); + NodeList list = e.getElementsByTagName(tagName); + for(int index = 0;index + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.utils.emotions; + +public interface EmoticonPaletteListener { + + void onEmoticonSelected(String emoticonText); + +} diff --git a/src/com/anzsoft/client/utils/emotions/EmoticonPalettePanel.java b/src/com/anzsoft/client/utils/emotions/EmoticonPalettePanel.java new file mode 100644 index 0000000..00b97fa --- /dev/null +++ b/src/com/anzsoft/client/utils/emotions/EmoticonPalettePanel.java @@ -0,0 +1,123 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + + +package com.anzsoft.client.utils.emotions; + +import com.extjs.gxt.ui.client.widget.Popup; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.ClickListener; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Widget; + +public class EmoticonPalettePanel extends Popup { + private static final int PALETTE_ROWS = 5; + private static final int PALETTE_COLUMNS = 7; + private final Grid grid; + private int currentWidget; + + public EmoticonPalettePanel(final EmoticonPaletteListener listener) + { + setStyleName("emoticon_menu"); + //setAnimationEnabled(true); + grid = new Grid(PALETTE_ROWS, PALETTE_COLUMNS); + //final SimplePanel sp = new SimplePanel(); + //sp.add(grid); + //setWidget(grid); + add(grid); + currentWidget = 0; + //initWidget(sp); + grid.setCellSpacing(1); + grid.addStyleName("emite-MultiChatPanel-EmoticonPalette"); + final Emoticons img = Emoticons.App.getInstance(); + addNextIcon(createEmoticon(img.smile(), ":-)", listener)); + addNextIcon(createEmoticon(img.crying(), ":'(", listener)); + addNextIcon(createEmoticon(img.surprised(), ":-O", listener)); + addNextIcon(createEmoticon(img.angel(), "0:)", listener)); + addNextIcon(createEmoticon(img.happy(), "=)", listener)); + addNextIcon(createEmoticon(img.grin(), ":D", listener)); + addNextIcon(createEmoticon(img.joyful(), ":-))", listener)); + addNextIcon(createEmoticon(img.uncertain(), ":-/", listener)); + addNextIcon(createEmoticon(img.angry(), "x-(", listener)); + addNextIcon(createEmoticon(img.tongue(), ":P", listener)); + addNextIcon(createEmoticon(img.love(), ":-X", listener)); + addNextIcon(createEmoticon(img.sleeping(), "|-)", listener)); + addNextIcon(createEmoticon(img.cool(), "8)", listener)); + addNextIcon(createEmoticon(img.kissing(), ":*", listener)); + addNextIcon(createEmoticon(img.sad(), ":(", listener)); + addNextIcon(createEmoticon(img.alien(), "=:)", listener)); + addNextIcon(createEmoticon(img.andy(), "0o", listener)); + addNextIcon(createEmoticon(img.bandit(), "(bandit)", listener)); + addNextIcon(createEmoticon(img.blushing(), ":-$", listener)); + addNextIcon(createEmoticon(img.devil(), ">:)", listener)); + addNextIcon(createEmoticon(img.whistling(), ":-\"", listener)); + addNextIcon(createEmoticon(img.heart(), "(H)", listener)); + addNextIcon(createEmoticon(img.lol(), "(LOL)", listener)); + addNextIcon(createEmoticon(img.ninja(), "(:)", listener)); + addNextIcon(createEmoticon(img.pinched(), ">_<", listener)); + addNextIcon(createEmoticon(img.policeman(), "(police)", listener)); + addNextIcon(createEmoticon(img.pouty(), ":|", listener)); + addNextIcon(createEmoticon(img.wizard(), "(wizard)", listener)); + addNextIcon(createEmoticon(img.sick(), ":-&", listener)); + addNextIcon(createEmoticon(img.sideways(), "=]", listener)); + addNextIcon(createEmoticon(img.unsure(), ":-S", listener)); + addNextIcon(createEmoticon(img.w00t(), "(woot)", listener)); + addNextIcon(createEmoticon(img.wink(), ";-)", listener)); + addNextIcon(createEmoticon(img.wondering(), ":?", listener)); + /* + * addNextIcon(createEmoticon(img.bulletStar(), "ONLY FOR DEVELOPMENT + * AND TESTS: >:) O:) o:) o:-) O:-) 0:) 0:-) ^_^ " + "^-^ ^^ :)) :-)) + * (police) (cop) {):) =:) (alien) o_O o_0 O_O o_o O_o " + "0_o o0 0o oO + * Oo 0_0 >:o >:-o >:O >:-O X( X-( x( x-( :@ <_< (bandit) " + ":(> :\"> + * :*> :-$ :$ B) B-) 8) :'( ='( :-d :d :-D :D :d =D =-D =) =-) " + "(L) + * (h) (H) :-* :* (LOL) lol :-X :-xX :x (wubya) (wubyou) (wub) (:) " + + * "(ph33r) (ph34r) >_< :| =| :-| :( =( =-( :-( :& :-& =] (-.-) |) |-) " + + * "I-) I-| :-O :O :-o :o :-0 =-O =-o =o =O :P =P =p :-P :p :-p :b :-\\ " + + * ":-/ :/ :\\ :s :-S :-s :S (woot) (w00t) (wOOt) :-\" ;) ;-) ;> + * (wizard) :? :-) :)", listener)); + */ + } + + private void addNextIcon(final Image img) + { + final int row = currentWidget / PALETTE_COLUMNS; + final int col = currentWidget % PALETTE_COLUMNS; + grid.setWidget(row, col, img); + currentWidget++; + } + + private Image createEmoticon(final AbstractImagePrototype imageProto, final String emoticonText, + final EmoticonPaletteListener listener) + { + final Image img = new Image(); + imageProto.applyTo(img); + img.addClickListener(new ClickListener() + { + + public void onClick(final Widget arg0) + { + listener.onEmoticonSelected(emoticonText); + } + }); + img.setTitle(emoticonText); + return img; + } +} diff --git a/src/com/anzsoft/client/utils/emotions/Emoticons.java b/src/com/anzsoft/client/utils/emotions/Emoticons.java new file mode 100644 index 0000000..3b69111 --- /dev/null +++ b/src/com/anzsoft/client/utils/emotions/Emoticons.java @@ -0,0 +1,147 @@ +/* + iJab , The Ajax web jabber client + Copyright (c) 2006-2008 by AnzSoft + + Author:Fanglin Zhong + + Started at 2008-08-20, Beijing of China + + iJab (c) 2006-2008 by the ijab developers + + ************************************************************************* + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ************************************************************************* +*/ + +package com.anzsoft.client.utils.emotions; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.AbstractImagePrototype; +import com.google.gwt.user.client.ui.ImageBundle; + +public interface Emoticons extends ImageBundle { + + public static class App { + private static Emoticons ourInstance = null; + + public static synchronized Emoticons getInstance() { + if (ourInstance == null) { + ourInstance = (Emoticons) GWT.create(Emoticons.class); + } + return ourInstance; + } + } + + @Resource("alien.png") + AbstractImagePrototype alien(); + + @Resource("andy.png") + AbstractImagePrototype andy(); + + @Resource("angel.png") + AbstractImagePrototype angel(); + + @Resource("angry.png") + AbstractImagePrototype angry(); + + @Resource("bandit.png") + AbstractImagePrototype bandit(); + + @Resource("blushing.png") + AbstractImagePrototype blushing(); + + @Resource("bullet_black.png") + AbstractImagePrototype bulletBlack(); + + @Resource("bullet_star.png") + AbstractImagePrototype bulletStar(); + + @Resource("cool.png") + AbstractImagePrototype cool(); + + @Resource("crying.png") + AbstractImagePrototype crying(); + + @Resource("devil.png") + AbstractImagePrototype devil(); + + @Resource("grin.png") + AbstractImagePrototype grin(); + + @Resource("happy.png") + AbstractImagePrototype happy(); + + @Resource("heart.png") + AbstractImagePrototype heart(); + + @Resource("joyful.png") + AbstractImagePrototype joyful(); + + @Resource("kissing.png") + AbstractImagePrototype kissing(); + + @Resource("lol.png") + AbstractImagePrototype lol(); + + @Resource("love.png") + AbstractImagePrototype love(); + + @Resource("ninja.png") + AbstractImagePrototype ninja(); + + @Resource("pinched.png") + AbstractImagePrototype pinched(); + + @Resource("policeman.png") + AbstractImagePrototype policeman(); + + @Resource("pouty.png") + AbstractImagePrototype pouty(); + + @Resource("sad.png") + AbstractImagePrototype sad(); + + @Resource("sick.png") + AbstractImagePrototype sick(); + + @Resource("sideways.png") + AbstractImagePrototype sideways(); + + @Resource("sleeping.png") + AbstractImagePrototype sleeping(); + + @Resource("smile.png") + AbstractImagePrototype smile(); + + @Resource("surprised.png") + AbstractImagePrototype surprised(); + + @Resource("tongue.png") + AbstractImagePrototype tongue(); + + @Resource("uncertain.png") + AbstractImagePrototype uncertain(); + + @Resource("unsure.png") + AbstractImagePrototype unsure(); + + @Resource("w00t.png") + AbstractImagePrototype w00t(); + + @Resource("whistling.png") + AbstractImagePrototype whistling(); + + @Resource("wink.png") + AbstractImagePrototype wink(); + + @Resource("wizard.png") + AbstractImagePrototype wizard(); + + @Resource("wondering.png") + AbstractImagePrototype wondering(); +} diff --git a/src/com/anzsoft/client/utils/emotions/Thumbs.db b/src/com/anzsoft/client/utils/emotions/Thumbs.db new file mode 100644 index 0000000..abd64a9 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/Thumbs.db differ diff --git a/src/com/anzsoft/client/utils/emotions/alien.png b/src/com/anzsoft/client/utils/emotions/alien.png new file mode 100644 index 0000000..2334c86 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/alien.png differ diff --git a/src/com/anzsoft/client/utils/emotions/andy.png b/src/com/anzsoft/client/utils/emotions/andy.png new file mode 100644 index 0000000..dc5063d Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/andy.png differ diff --git a/src/com/anzsoft/client/utils/emotions/angel.png b/src/com/anzsoft/client/utils/emotions/angel.png new file mode 100644 index 0000000..72205bc Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/angel.png differ diff --git a/src/com/anzsoft/client/utils/emotions/angry.png b/src/com/anzsoft/client/utils/emotions/angry.png new file mode 100644 index 0000000..450f756 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/angry.png differ diff --git a/src/com/anzsoft/client/utils/emotions/bandit.png b/src/com/anzsoft/client/utils/emotions/bandit.png new file mode 100644 index 0000000..4bac65f Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/bandit.png differ diff --git a/src/com/anzsoft/client/utils/emotions/blushing.png b/src/com/anzsoft/client/utils/emotions/blushing.png new file mode 100644 index 0000000..efba6fe Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/blushing.png differ diff --git a/src/com/anzsoft/client/utils/emotions/bullet_black.png b/src/com/anzsoft/client/utils/emotions/bullet_black.png new file mode 100644 index 0000000..5761970 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/bullet_black.png differ diff --git a/src/com/anzsoft/client/utils/emotions/bullet_star.png b/src/com/anzsoft/client/utils/emotions/bullet_star.png new file mode 100644 index 0000000..fab774a Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/bullet_star.png differ diff --git a/src/com/anzsoft/client/utils/emotions/cool.png b/src/com/anzsoft/client/utils/emotions/cool.png new file mode 100644 index 0000000..43836da Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/cool.png differ diff --git a/src/com/anzsoft/client/utils/emotions/crying.png b/src/com/anzsoft/client/utils/emotions/crying.png new file mode 100644 index 0000000..f2de94f Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/crying.png differ diff --git a/src/com/anzsoft/client/utils/emotions/devil.png b/src/com/anzsoft/client/utils/emotions/devil.png new file mode 100644 index 0000000..973335e Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/devil.png differ diff --git a/src/com/anzsoft/client/utils/emotions/grin.png b/src/com/anzsoft/client/utils/emotions/grin.png new file mode 100644 index 0000000..89e896d Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/grin.png differ diff --git a/src/com/anzsoft/client/utils/emotions/happy.png b/src/com/anzsoft/client/utils/emotions/happy.png new file mode 100644 index 0000000..97e3dd0 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/happy.png differ diff --git a/src/com/anzsoft/client/utils/emotions/heart.png b/src/com/anzsoft/client/utils/emotions/heart.png new file mode 100644 index 0000000..bedbfce Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/heart.png differ diff --git a/src/com/anzsoft/client/utils/emotions/joyful.png b/src/com/anzsoft/client/utils/emotions/joyful.png new file mode 100644 index 0000000..568f35e Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/joyful.png differ diff --git a/src/com/anzsoft/client/utils/emotions/kissing.png b/src/com/anzsoft/client/utils/emotions/kissing.png new file mode 100644 index 0000000..c02dabc Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/kissing.png differ diff --git a/src/com/anzsoft/client/utils/emotions/lol.png b/src/com/anzsoft/client/utils/emotions/lol.png new file mode 100644 index 0000000..928b16f Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/lol.png differ diff --git a/src/com/anzsoft/client/utils/emotions/love.png b/src/com/anzsoft/client/utils/emotions/love.png new file mode 100644 index 0000000..45fb04b Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/love.png differ diff --git a/src/com/anzsoft/client/utils/emotions/ninja.png b/src/com/anzsoft/client/utils/emotions/ninja.png new file mode 100644 index 0000000..cb7b034 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/ninja.png differ diff --git a/src/com/anzsoft/client/utils/emotions/pinched.png b/src/com/anzsoft/client/utils/emotions/pinched.png new file mode 100644 index 0000000..f4f2aa6 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/pinched.png differ diff --git a/src/com/anzsoft/client/utils/emotions/policeman.png b/src/com/anzsoft/client/utils/emotions/policeman.png new file mode 100644 index 0000000..889c978 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/policeman.png differ diff --git a/src/com/anzsoft/client/utils/emotions/pouty.png b/src/com/anzsoft/client/utils/emotions/pouty.png new file mode 100644 index 0000000..eb791f0 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/pouty.png differ diff --git a/src/com/anzsoft/client/utils/emotions/sad.png b/src/com/anzsoft/client/utils/emotions/sad.png new file mode 100644 index 0000000..b451926 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/sad.png differ diff --git a/src/com/anzsoft/client/utils/emotions/sick.png b/src/com/anzsoft/client/utils/emotions/sick.png new file mode 100644 index 0000000..d9d4902 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/sick.png differ diff --git a/src/com/anzsoft/client/utils/emotions/sideways.png b/src/com/anzsoft/client/utils/emotions/sideways.png new file mode 100644 index 0000000..1d77eb1 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/sideways.png differ diff --git a/src/com/anzsoft/client/utils/emotions/sleeping.png b/src/com/anzsoft/client/utils/emotions/sleeping.png new file mode 100644 index 0000000..7e10006 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/sleeping.png differ diff --git a/src/com/anzsoft/client/utils/emotions/smile.png b/src/com/anzsoft/client/utils/emotions/smile.png new file mode 100644 index 0000000..cdaa5c0 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/smile.png differ diff --git a/src/com/anzsoft/client/utils/emotions/surprised.png b/src/com/anzsoft/client/utils/emotions/surprised.png new file mode 100644 index 0000000..61cb422 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/surprised.png differ diff --git a/src/com/anzsoft/client/utils/emotions/tongue.png b/src/com/anzsoft/client/utils/emotions/tongue.png new file mode 100644 index 0000000..2488c5a Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/tongue.png differ diff --git a/src/com/anzsoft/client/utils/emotions/uncertain.png b/src/com/anzsoft/client/utils/emotions/uncertain.png new file mode 100644 index 0000000..a9b7c4b Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/uncertain.png differ diff --git a/src/com/anzsoft/client/utils/emotions/unsure.png b/src/com/anzsoft/client/utils/emotions/unsure.png new file mode 100644 index 0000000..d0bf51a Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/unsure.png differ diff --git a/src/com/anzsoft/client/utils/emotions/w00t.png b/src/com/anzsoft/client/utils/emotions/w00t.png new file mode 100644 index 0000000..30d4cb8 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/w00t.png differ diff --git a/src/com/anzsoft/client/utils/emotions/whistling.png b/src/com/anzsoft/client/utils/emotions/whistling.png new file mode 100644 index 0000000..52702eb Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/whistling.png differ diff --git a/src/com/anzsoft/client/utils/emotions/wink.png b/src/com/anzsoft/client/utils/emotions/wink.png new file mode 100644 index 0000000..a13b940 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/wink.png differ diff --git a/src/com/anzsoft/client/utils/emotions/wizard.png b/src/com/anzsoft/client/utils/emotions/wizard.png new file mode 100644 index 0000000..456b81f Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/wizard.png differ diff --git a/src/com/anzsoft/client/utils/emotions/wondering.png b/src/com/anzsoft/client/utils/emotions/wondering.png new file mode 100644 index 0000000..f8814c8 Binary files /dev/null and b/src/com/anzsoft/client/utils/emotions/wondering.png differ diff --git a/src/com/anzsoft/client/utils/group-chat.png b/src/com/anzsoft/client/utils/group-chat.png new file mode 100644 index 0000000..f6e8325 Binary files /dev/null and b/src/com/anzsoft/client/utils/group-chat.png differ diff --git a/src/com/anzsoft/client/utils/icon-close.gif b/src/com/anzsoft/client/utils/icon-close.gif new file mode 100644 index 0000000..cc90527 Binary files /dev/null and b/src/com/anzsoft/client/utils/icon-close.gif differ diff --git a/src/com/anzsoft/client/utils/icon-search.gif b/src/com/anzsoft/client/utils/icon-search.gif new file mode 100644 index 0000000..d2440be Binary files /dev/null and b/src/com/anzsoft/client/utils/icon-search.gif differ diff --git a/src/com/anzsoft/client/utils/info-lamp.png b/src/com/anzsoft/client/utils/info-lamp.png new file mode 100644 index 0000000..95385df Binary files /dev/null and b/src/com/anzsoft/client/utils/info-lamp.png differ diff --git a/src/com/anzsoft/client/utils/info.png b/src/com/anzsoft/client/utils/info.png new file mode 100644 index 0000000..12cd1ae Binary files /dev/null and b/src/com/anzsoft/client/utils/info.png differ diff --git a/src/com/anzsoft/client/utils/invisible.png b/src/com/anzsoft/client/utils/invisible.png new file mode 100644 index 0000000..ea87e07 Binary files /dev/null and b/src/com/anzsoft/client/utils/invisible.png differ diff --git a/src/com/anzsoft/client/utils/message.png b/src/com/anzsoft/client/utils/message.png new file mode 100644 index 0000000..3efe8e9 Binary files /dev/null and b/src/com/anzsoft/client/utils/message.png differ diff --git a/src/com/anzsoft/client/utils/new-chat.png b/src/com/anzsoft/client/utils/new-chat.png new file mode 100644 index 0000000..cef6df5 Binary files /dev/null and b/src/com/anzsoft/client/utils/new-chat.png differ diff --git a/src/com/anzsoft/client/utils/new-email.png b/src/com/anzsoft/client/utils/new-email.png new file mode 100644 index 0000000..3efe8e9 Binary files /dev/null and b/src/com/anzsoft/client/utils/new-email.png differ diff --git a/src/com/anzsoft/client/utils/new-message.png b/src/com/anzsoft/client/utils/new-message.png new file mode 100644 index 0000000..5fe4d6b Binary files /dev/null and b/src/com/anzsoft/client/utils/new-message.png differ diff --git a/src/com/anzsoft/client/utils/not-authorized.png b/src/com/anzsoft/client/utils/not-authorized.png new file mode 100644 index 0000000..84b4ed4 Binary files /dev/null and b/src/com/anzsoft/client/utils/not-authorized.png differ diff --git a/src/com/anzsoft/client/utils/offline.png b/src/com/anzsoft/client/utils/offline.png new file mode 100644 index 0000000..55865bc Binary files /dev/null and b/src/com/anzsoft/client/utils/offline.png differ diff --git a/src/com/anzsoft/client/utils/online.png b/src/com/anzsoft/client/utils/online.png new file mode 100644 index 0000000..cbe9d83 Binary files /dev/null and b/src/com/anzsoft/client/utils/online.png differ diff --git a/src/com/anzsoft/client/utils/question.png b/src/com/anzsoft/client/utils/question.png new file mode 100644 index 0000000..0e6b0a5 Binary files /dev/null and b/src/com/anzsoft/client/utils/question.png differ diff --git a/src/com/anzsoft/client/utils/room-new-message-small.png b/src/com/anzsoft/client/utils/room-new-message-small.png new file mode 100644 index 0000000..630e90a Binary files /dev/null and b/src/com/anzsoft/client/utils/room-new-message-small.png differ diff --git a/src/com/anzsoft/client/utils/room-small.png b/src/com/anzsoft/client/utils/room-small.png new file mode 100644 index 0000000..272f547 Binary files /dev/null and b/src/com/anzsoft/client/utils/room-small.png differ diff --git a/src/com/anzsoft/client/utils/unavailable.png b/src/com/anzsoft/client/utils/unavailable.png new file mode 100644 index 0000000..74aaeb9 Binary files /dev/null and b/src/com/anzsoft/client/utils/unavailable.png differ diff --git a/src/com/anzsoft/client/utils/user_add.png b/src/com/anzsoft/client/utils/user_add.png new file mode 100644 index 0000000..deae99b Binary files /dev/null and b/src/com/anzsoft/client/utils/user_add.png differ diff --git a/src/com/anzsoft/client/utils/xa.png b/src/com/anzsoft/client/utils/xa.png new file mode 100644 index 0000000..99f9642 Binary files /dev/null and b/src/com/anzsoft/client/utils/xa.png differ diff --git a/src/com/anzsoft/iJab.gwt.xml b/src/com/anzsoft/iJab.gwt.xml new file mode 100644 index 0000000..e084ac5 --- /dev/null +++ b/src/com/anzsoft/iJab.gwt.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + '); + }, + load: function() { + var includes = + ['xmlextras', + 'jsextras', + 'crypt', + 'JSJaCConfig', + 'JSJaCConstants', + 'JSJaCCookie', + 'JSJaCJSON', + 'JSJaCJID', + 'JSJaCBuilder', + 'JSJaCPacket', + 'JSJaCError', + 'JSJaCKeys', + 'JSJaCConnection', + 'JSJaCHttpPollingConnection', + 'JSJaCHttpBindingConnection', + 'JSJaCConsoleLogger' + ]; + var scripts = document.getElementsByTagName("script"); + var path = './'; + for (var i=0; i + * The original parts of the code do have the following + * copyright and license notice:
+ * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, + * http://mir.acu lo.us)
+ * script.aculo.us is freely distributable under the terms of an + * MIT-style license.
+ * For details, see the script.aculo.us web site: + * http://script.aculo.us/
+ */ +var JSJaCBuilder = { + /** + * @private + */ + buildNode: function(doc, elementName) { + + var element, ns = arguments[4]; + + // attributes (or text) + if(arguments[2]) + if(JSJaCBuilder._isStringOrNumber(arguments[2]) || + (arguments[2] instanceof Array)) { + element = this._createElement(doc, elementName, ns); + JSJaCBuilder._children(doc, element, arguments[2]); + } else { + ns = arguments[2]['xmlns'] || ns; + element = this._createElement(doc, elementName, ns); + for(attr in arguments[2]) { + if (arguments[2].hasOwnProperty(attr) && attr != 'xmlns') + element.setAttribute(attr, arguments[2][attr]); + } + } + else + element = this._createElement(doc, elementName, ns); + // text, or array of children + if(arguments[3]) + JSJaCBuilder._children(doc, element, arguments[3], ns); + + return element; + }, + + _createElement: function(doc, elementName, ns) { + try { + if (ns) + return doc.createElementNS(ns, elementName); + } catch (ex) { } + + var el = doc.createElement(elementName); + + if (ns) + el.setAttribute("xmlns", ns); + + return el; + }, + + /** + * @private + */ + _text: function(doc, text) { + return doc.createTextNode(text); + }, + + /** + * @private + */ + _children: function(doc, element, children, ns) { + if(typeof children=='object') { // array can hold nodes and text + for (var i in children) { + if (children.hasOwnProperty(i)) { + var e = children[i]; + if (typeof e=='object') { + if (e instanceof Array) { + var node = JSJaCBuilder.buildNode(doc, e[0], e[1], e[2], ns); + element.appendChild(node); + } else { + element.appendChild(e); + } + } else { + if(JSJaCBuilder._isStringOrNumber(e)) { + element.appendChild(JSJaCBuilder._text(doc, e)); + } + } + } + } + } else { + if(JSJaCBuilder._isStringOrNumber(children)) { + element.appendChild(JSJaCBuilder._text(doc, children)); + } + } + }, + + _attributes: function(attributes) { + var attrs = []; + for(attribute in attributes) + if (attributes.hasOwnProperty(attribute)) + attrs.push(attribute + + '="' + attributes[attribute].toString().htmlEnc() + '"'); + return attrs.join(" "); + }, + + _isStringOrNumber: function(param) { + return(typeof param=='string' || typeof param=='number'); + } +}; diff --git a/src/com/anzsoft/public/dev/JSJaCConfig.js b/src/com/anzsoft/public/dev/JSJaCConfig.js new file mode 100644 index 0000000..355ab0c --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCConfig.js @@ -0,0 +1,22 @@ + +var JSJAC_HAVEKEYS = true; // whether to use keys +var JSJAC_NKEYS = 16; // number of keys to generate +var JSJAC_INACTIVITY = 300; // qnd hack to make suspend/resume work more smoothly with polling +var JSJAC_ERR_COUNT = 10; // number of retries in case of connection errors + +var JSJAC_ALLOW_PLAIN = true; // whether to allow plaintext logins + +var JSJAC_CHECKQUEUEINTERVAL = 1; // msecs to poll send queue +var JSJAC_CHECKINQUEUEINTERVAL = 1; // msecs to poll incoming queue + +// Options specific to HTTP Binding (BOSH) +var JSJACHBC_BOSH_VERSION = "1.6"; +var JSJACHBC_USE_BOSH_VER = true; + +var JSJACHBC_MAX_HOLD = 1; +var JSJACHBC_MAX_WAIT = 300; + +var JSJACHBC_MAXPAUSE = 120; + +/*** END CONFIG ***/ + diff --git a/src/com/anzsoft/public/dev/JSJaCConnection.js b/src/com/anzsoft/public/dev/JSJaCConnection.js new file mode 100644 index 0000000..7f5693a --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCConnection.js @@ -0,0 +1,1252 @@ +/** + * @fileoverview Contains all things in common for all subtypes of connections + * supported. + * @author Stefan Strigler steve@zeank.in-berlin.de + * @version $Revision: 476 $ + */ + +/** + * Creates a new Jabber connection (a connection to a jabber server) + * @class Somewhat abstract base class for jabber connections. Contains all + * of the code in common for all jabber connections + * @constructor + * @param {JSON http://www.json.org/index} oArg JSON with properties:
+ * * httpbase the http base address of the service to be used for + * connecting to jabber
+ * * oDbg (optional) a reference to a debugger interface + */ +function JSJaCConnection(oArg) { + + if (oArg && oArg.oDbg && oArg.oDbg.log) + /** + * Reference to debugger interface + *(needs to implement method log) + * @type Debugger + */ + this.oDbg = oArg.oDbg; + else { + this.oDbg = new Object(); // always initialise a debugger + this.oDbg.log = function() { }; + } + + if (oArg && oArg.httpbase) + /** + * @private + */ + this._httpbase = oArg.httpbase; + + if (oArg && oArg.allow_plain) + /** + * @private + */ + this.allow_plain = oArg.allow_plain; + else + this.allow_plain = JSJAC_ALLOW_PLAIN; + + /** + * @private + */ + this._connected = false; + /** + * @private + */ + this._events = new Array(); + /** + * @private + */ + this._keys = null; + /** + * @private + */ + this._ID = 0; + /** + * @private + */ + this._inQ = new Array(); + /** + * @private + */ + this._pQueue = new Array(); + /** + * @private + */ + this._regIDs = new Array(); + /** + * @private + */ + this._req = new Array(); + /** + * @private + */ + this._status = 'intialized'; + /** + * @private + */ + this._errcnt = 0; + /** + * @private + */ + this._inactivity = JSJAC_INACTIVITY; + /** + * @private + */ + this._sendRawCallbacks = new Array(); + + if (oArg && oArg.timerval) + this.setPollInterval(oArg.timerval); +} + +JSJaCConnection.prototype.connect = function(oArg) { + this._setStatus('connecting'); + + this.domain = oArg.domain || 'localhost'; + this.username = oArg.username; + this.resource = oArg.resource; + this.pass = oArg.pass; + this.register = oArg.register; + + this.authhost = oArg.authhost || this.domain; + this.authtype = oArg.authtype || 'sasl'; + + if (oArg.xmllang && oArg.xmllang != '') + this._xmllang = oArg.xmllang; + + this.host = oArg.host || this.domain; + this.port = oArg.port || 5222; + if (oArg.secure) + this.secure = 'true'; + else + this.secure = 'false'; + + if (oArg.wait) + this._wait = oArg.wait; + + this.jid = this.username + '@' + this.domain; + this.fulljid = this.jid + '/' + this.resource; + + this._rid = Math.round( 100000.5 + ( ( (900000.49999) - (100000.5) ) * Math.random() ) ); + + // setupRequest must be done after rid is created but before first use in reqstr + var slot = this._getFreeSlot(); + this._req[slot] = this._setupRequest(true); + + var reqstr = this._getInitialRequestString(); + + this.oDbg.log(reqstr,4); + + this._req[slot].r.onreadystatechange = + JSJaC.bind(function() { + if (this._req[slot].r.readyState == 4) { + this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); + this._handleInitialResponse(slot); // handle response + } + }, this); + + if (typeof(this._req[slot].r.onerror) != 'undefined') { + this._req[slot].r.onerror = + JSJaC.bind(function(e) { + this.oDbg.log('XmlHttpRequest error',1); + return false; + }, this); + } + + this._req[slot].r.send(reqstr); +}; + +/** + * Tells whether this connection is connected + * @return true if this connections is connected, + * false otherwise + * @type boolean + */ +JSJaCConnection.prototype.connected = function() { return this._connected; }; + +/** + * Disconnects from jabber server and terminates session (if applicable) + */ +JSJaCConnection.prototype.disconnect = function() { + this._setStatus('disconnecting'); + + if (!this.connected()) + return; + this._connected = false; + + clearInterval(this._interval); + clearInterval(this._inQto); + + if (this._timeout) + clearTimeout(this._timeout); // remove timer + + var slot = this._getFreeSlot(); + // Intentionally synchronous + this._req[slot] = this._setupRequest(false); + + request = this._getRequestString(false, true); + + this.oDbg.log("Disconnecting: " + request,4); + this._req[slot].r.send(request); + + try { + JSJaCCookie.read('JSJaC_State').erase(); + } catch (e) {} + + this.oDbg.log("Disconnected: "+this._req[slot].r.responseText,2); + this._handleEvent('ondisconnect'); +}; + +/** + * Gets current value of polling interval + * @return Polling interval in milliseconds + * @type int + */ +JSJaCConnection.prototype.getPollInterval = function() { + return this._timerval; +}; + +/** + * Registers an event handler (callback) for this connection. + + *

Note: All of the packet handlers for specific packets (like + * message_in, presence_in and iq_in) fire only if there's no + * callback associated with the id.
+ + *

Example:
+ * con.registerHandler('iq', 'query', 'jabber:iq:version', handleIqVersion); + + + * @param {String} event One of + + *

    + *
  • onConnect - connection has been established and authenticated
  • + *
  • onDisconnect - connection has been disconnected
  • + *
  • onResume - connection has been resumed
  • + + *
  • onStatusChanged - connection status has changed, current + * status as being passed argument to handler. See {@link #status}.
  • + + *
  • onError - an error has occured, error node is supplied as + * argument, like this:
    <error code='404' type='cancel'>
    + * <item-not-found xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
    + * </error>
  • + + *
  • packet_in - a packet has been received (argument: the + * packet)
  • + + *
  • packet_out - a packet is to be sent(argument: the + * packet)
  • + + *
  • message_in | message - a message has been received (argument: + * the packet)
  • + + *
  • message_out - a message packet is to be sent (argument: the + * packet)
  • + + *
  • presence_in | presence - a presence has been received + * (argument: the packet)
  • + + *
  • presence_out - a presence packet is to be sent (argument: the + * packet)
  • + + *
  • iq_in | iq - an iq has been received (argument: the packet)
  • + *
  • iq_out - an iq is to be sent (argument: the packet)
  • + *
+ + * @param {String} childName A childnode's name that must occur within a + * retrieved packet [optional] + + * @param {String} childNS A childnode's namespace that must occure within + * a retrieved packet (works only if childName is given) [optional] + + * @param {String} type The type of the packet to handle (works only if childName and chidNS are given (both may be set to '*' in order to get skipped) [optional] + + * @param {Function} handler The handler to be called when event occurs. If your handler returns 'true' it cancels bubbling of the event. No other registered handlers for this event will be fired. + */ +JSJaCConnection.prototype.registerHandler = function(event) { + event = event.toLowerCase(); // don't be case-sensitive here + var eArg = {handler: arguments[arguments.length-1], + childName: '*', + childNS: '*', + type: '*'}; + if (arguments.length > 2) + eArg.childName = arguments[1]; + if (arguments.length > 3) + eArg.childNS = arguments[2]; + if (arguments.length > 4) + eArg.type = arguments[3]; + if (!this._events[event]) + this._events[event] = new Array(eArg); + else + this._events[event] = this._events[event].concat(eArg); + + // sort events in order how specific they match criterias thus using + // wildcard patterns puts them back in queue when it comes to + // bubbling the event + this._events[event] = + this._events[event].sort(function(a,b) { + var aRank = 0; + var bRank = 0; + with (a) { + if (type == '*') + aRank++; + if (childNS == '*') + aRank++; + if (childName == '*') + aRank++; + } + with (b) { + if (type == '*') + bRank++; + if (childNS == '*') + bRank++; + if (childName == '*') + bRank++; + } + if (aRank > bRank) + return 1; + if (aRank < bRank) + return -1; + return 0; + }); + this.oDbg.log("registered handler for event '"+event+"'",2); +}; + +JSJaCConnection.prototype.unregisterHandler = function(event,handler) { + event = event.toLowerCase(); // don't be case-sensitive here + + if (!this._events[event]) + return; + + var arr = this._events[event], res = new Array(); + for (var i=0; i + *
  • 'initializing' ... well + *
  • 'connecting' if connect() was called + *
  • 'resuming' if resume() was called + *
  • 'processing' if it's about to operate as normal + *
  • 'onerror_fallback' if there was an error with the request object + *
  • 'protoerror_fallback' if there was an error at the http binding protocol flow (most likely that's where you interested in) + *
  • 'internal_server_error' in case of an internal server error + *
  • 'suspending' if suspend() is being called + *
  • 'aborted' if abort() was called + *
  • 'disconnecting' if disconnect() has been called + * + * @type String + */ +JSJaCConnection.prototype.status = function() { return this._status; }; + +/** + * Suspsends this connection (saving state for later resume) + */ +JSJaCConnection.prototype.suspend = function() { + + // remove timers + clearTimeout(this._timeout); + clearInterval(this._interval); + clearInterval(this._inQto); + + this._suspend(); + + var u = ('_connected,_keys,_ID,_inQ,_pQueue,_regIDs,_errcnt,_inactivity,domain,username,resource,jid,fulljid,_sid,_httpbase,_timerval,_is_polling').split(','); + u = u.concat(this._getSuspendVars()); + var s = new Object(); + + for (var i=0; i", + this._doSASLAuthDone); + } + this.oDbg.log("SASL ANONYMOUS requested but not supported",1); + } else { + if (this.mechs['DIGEST-MD5']) { + this.oDbg.log("SASL using mechanism 'DIGEST-MD5'",2); + return this._sendRaw("", + this._doSASLAuthDigestMd5S1); + } else if (this.allow_plain && this.mechs['PLAIN']) { + this.oDbg.log("SASL using mechanism 'PLAIN'",2); + var authStr = this.username+'@'+ + this.domain+String.fromCharCode(0)+ + this.username+String.fromCharCode(0)+ + this.pass; + this.oDbg.log("authenticating with '"+authStr+"'",2); + authStr = btoa(authStr); + return this._sendRaw(""+authStr+"", + this._doSASLAuthDone); + } + this.oDbg.log("No SASL mechanism applied",1); + this.authtype = 'nonsasl'; // fallback + } + return false; +}; + +/** + * @private + */ +JSJaCConnection.prototype._doSASLAuthDigestMd5S1 = function(el) { + if (el.nodeName != "challenge") { + this.oDbg.log("challenge missing",1); + this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); + this.disconnect(); + } else { + var challenge = atob(el.firstChild.nodeValue); + this.oDbg.log("got challenge: "+challenge,2); + this._nonce = challenge.substring(challenge.indexOf("nonce=")+7); + this._nonce = this._nonce.substring(0,this._nonce.indexOf("\"")); + this.oDbg.log("nonce: "+this._nonce,2); + if (this._nonce == '' || this._nonce.indexOf('\"') != -1) { + this.oDbg.log("nonce not valid, aborting",1); + this.disconnect(); + return; + } + + this._digest_uri = "xmpp/"; + // if (typeof(this.host) != 'undefined' && this.host != '') { + // this._digest-uri += this.host; + // if (typeof(this.port) != 'undefined' && this.port) + // this._digest-uri += ":" + this.port; + // this._digest-uri += '/'; + // } + this._digest_uri += this.domain; + + this._cnonce = cnonce(14); + + this._nc = '00000001'; + + var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+ + ':'+this._nonce+':'+this._cnonce; + + var A2 = 'AUTHENTICATE:'+this._digest_uri; + + var response = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ + this._cnonce+':auth:'+hex_md5(A2)); + + var rPlain = 'username="'+this.username+'",realm="'+this.domain+ + '",nonce="'+this._nonce+'",cnonce="'+this._cnonce+'",nc="'+this._nc+ + '",qop=auth,digest-uri="'+this._digest_uri+'",response="'+response+ + '",charset=utf-8'; + + this.oDbg.log("response: "+rPlain,2); + + this._sendRaw(""+ + binb2b64(str2binb(rPlain))+"", + this._doSASLAuthDigestMd5S2); + } +}; + +/** + * @private + */ +JSJaCConnection.prototype._doSASLAuthDigestMd5S2 = function(el) { + if (el.nodeName == 'failure') { + if (el.xml) + this.oDbg.log("auth error: "+el.xml,1); + else + this.oDbg.log("auth error",1); + this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); + this.disconnect(); + return; + } + + var response = atob(el.firstChild.nodeValue); + this.oDbg.log("response: "+response,2); + + var rspauth = response.substring(response.indexOf("rspauth=")+8); + this.oDbg.log("rspauth: "+rspauth,2); + + var A1 = str_md5(this.username+':'+this.domain+':'+this.pass)+ + ':'+this._nonce+':'+this._cnonce; + + var A2 = ':'+this._digest_uri; + + var rsptest = hex_md5(hex_md5(A1)+':'+this._nonce+':'+this._nc+':'+ + this._cnonce+':auth:'+hex_md5(A2)); + this.oDbg.log("rsptest: "+rsptest,2); + + if (rsptest != rspauth) { + this.oDbg.log("SASL Digest-MD5: server repsonse with wrong rspauth",1); + this.disconnect(); + return; + } + + if (el.nodeName == 'success') + this._reInitStream(this.domain, this._doStreamBind); + else // some extra turn + this._sendRaw("", + this._doSASLAuthDone); +}; + +/** + * @private + */ +JSJaCConnection.prototype._doSASLAuthDone = function (el) { + if (el.nodeName != 'success') { + this.oDbg.log("auth failed",1); + this._handleEvent('onerror',JSJaCError('401','auth','not-authorized')); + this.disconnect(); + } else + this._reInitStream(this.domain, this._doStreamBind); +}; + +/** + * @private + */ +JSJaCConnection.prototype._doStreamBind = function() { + var iq = new JSJaCIQ(); + iq.setIQ(this.domain,'set','bind_1'); + iq.appendNode("bind", {xmlns: "urn:ietf:params:xml:ns:xmpp-bind"}, + [["resource", this.resource]]); + this.oDbg.log(iq.xml()); + this.send(iq,this._doXMPPSess); +}; + +/** + * @private + */ +JSJaCConnection.prototype._doXMPPSess = function(iq) { + if (iq.getType() != 'result' || iq.getType() == 'error') { // failed + this.disconnect(); + if (iq.getType() == 'error') + this._handleEvent('onerror',iq.getChild('error')); + return; + } + + this.fulljid = iq.getChildVal("jid"); + this.jid = this.fulljid.substring(0,this.fulljid.lastIndexOf('/')); + + iq = new JSJaCIQ(); + iq.setIQ(this.domain,'set','sess_1'); + iq.appendNode("session", {xmlns: "urn:ietf:params:xml:ns:xmpp-session"}, + []); + this.oDbg.log(iq.xml()); + this.send(iq,this._doXMPPSessDone); +}; + +/** + * @private + */ +JSJaCConnection.prototype._doXMPPSessDone = function(iq) { + if (iq.getType() != 'result' || iq.getType() == 'error') { // failed + this.disconnect(); + if (iq.getType() == 'error') + this._handleEvent('onerror',iq.getChild('error')); + return; + } else + this._handleEvent('onconnect'); +}; + +/** + * @private + */ +JSJaCConnection.prototype._handleEvent = function(event,arg) { + event = event.toLowerCase(); // don't be case-sensitive here + this.oDbg.log("incoming event '"+event+"'",3); + if (!this._events[event]) + return; + this.oDbg.log("handling event '"+event+"'",2); + for (var i=0;i match for handler "+aEvent.handler,3); + } + if (aEvent.handler.call(this,arg)) // handled! + break; + } + else + if (aEvent.handler.call(this)) // handled! + break; + } catch (e) { this.oDbg.log(aEvent.handler+"\n>>>"+e.name+": "+ e.message,1); } + } + } +}; + +/** + * @private + */ +JSJaCConnection.prototype._handlePID = function(aJSJaCPacket) { + if (!aJSJaCPacket.getID()) + return false; + for (var i in this._regIDs) { + if (this._regIDs.hasOwnProperty(i) && + this._regIDs[i] && i == aJSJaCPacket.getID()) { + var pID = aJSJaCPacket.getID(); + this.oDbg.log("handling "+pID,3); + try { + if (this._regIDs[i].cb.call(this, aJSJaCPacket,this._regIDs[i].arg) === false) { + // don't unregister + return false; + } else { + this._unregisterPID(pID); + return true; + } + } catch (e) { + // broken handler? + this.oDbg.log(e.name+": "+ e.message); + this._unregisterPID(pID); + return true; + } + } + } + return false; +}; + +/** + * @private + */ +JSJaCConnection.prototype._handleResponse = function(req) { + var rootEl = this._parseResponse(req); + + if (!rootEl) + return; + + for (var i=0; i JSJAC_ERR_COUNT) { + // abort + this._abort(); + return false; + } + + this._setStatus('onerror_fallback'); + + // schedule next tick + setTimeout(JSJaC.bind(this._resume, this),this.getPollInterval()); + return false; + }, this); + } catch(e) { } // well ... no onerror property available, maybe we + // can catch the error somewhere else ... + + var reqstr = this._getRequestString(); + + if (typeof(this._rid) != 'undefined') // remember request id if any + this._req[slot].rid = this._rid; + + this.oDbg.log("sending: " + reqstr,4); + this._req[slot].r.send(reqstr); +}; + +/** + * @private + */ +JSJaCConnection.prototype._registerPID = function(pID,cb,arg) { + if (!pID || !cb) + return false; + this._regIDs[pID] = new Object(); + this._regIDs[pID].cb = cb; + if (arg) + this._regIDs[pID].arg = arg; + this.oDbg.log("registered "+pID,3); + return true; +}; + +/** + * send empty request + * waiting for stream id to be able to proceed with authentication + * @private + */ +JSJaCConnection.prototype._sendEmpty = function JSJaCSendEmpty() { + var slot = this._getFreeSlot(); + this._req[slot] = this._setupRequest(true); + + this._req[slot].r.onreadystatechange = + JSJaC.bind(function() { + if (this._req[slot].r.readyState == 4) { + this.oDbg.log("async recv: "+this._req[slot].r.responseText,4); + this._getStreamID(slot); // handle response + } + },this); + + if (typeof(this._req[slot].r.onerror) != 'undefined') { + this._req[slot].r.onerror = + JSJaC.bind(function(e) { + this.oDbg.log('XmlHttpRequest error',1); + return false; + }, this); + } + + var reqstr = this._getRequestString(); + this.oDbg.log("sending: " + reqstr,4); + this._req[slot].r.send(reqstr); +}; + +/** + * @private + */ +JSJaCConnection.prototype._sendRaw = function(xml,cb,arg) { + if (cb) + this._sendRawCallbacks.push({fn: cb, arg: arg}); + + this._pQueue.push(xml); + this._process(); + + return true; +}; + +/** + * @private + */ +JSJaCConnection.prototype._setStatus = function(status) { + if (!status || status == '') + return; + if (status != this._status) { // status changed! + this._status = status; + this._handleEvent('onstatuschanged', status); + this._handleEvent('status_changed', status); + } +}; + +/** + * @private + */ +JSJaCConnection.prototype._unregisterPID = function(pID) { + if (!this._regIDs[pID]) + return false; + this._regIDs[pID] = null; + this.oDbg.log("unregistered "+pID,3); + return true; +}; diff --git a/src/com/anzsoft/public/dev/JSJaCConsoleLogger.js b/src/com/anzsoft/public/dev/JSJaCConsoleLogger.js new file mode 100644 index 0000000..56eb75b --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCConsoleLogger.js @@ -0,0 +1,74 @@ +/** + * @fileoverview Contains Debugger interface for Firebug and Safari + * @class Implementation of the Debugger interface for {@link + * http://www.getfirebug.com/ Firebug} and Safari + * Creates a new debug logger to be passed to jsjac's connection + * constructor. Of course you can use it for debugging in your code + * too. + * @constructor + * @param {int} level The maximum level for debugging messages to be + * displayed. Thus you can tweak the verbosity of the logger. A value + * of 0 means very low traffic whilst a value of 4 makes logging very + * verbose about what's going on. + */ +function JSJaCConsoleLogger(level) { + /** + * @private + */ + this.level = level || 4; + + /** + * Empty function for API compatibility + */ + this.start = function() {}; + /** + * Logs a message to firebug's/safari's console + * @param {String} msg The message to be logged. + * @param {int} level The message's verbosity level. Importance is + * from 0 (very important) to 4 (not so important). A value of 1 + * denotes an error in the usual protocol flow. + */ + this.log = function(msg, level) { + level = level || 0; + if (level > this.level) + return; + if (typeof(console) == 'undefined') + return; + try { + switch (level) { + case 0: + console.warn(msg); + break; + case 1: + console.error(msg); + break; + case 2: + console.info(msg); + break; + case 4: + console.debug(msg); + break; + default: + console.log(msg); + break; + } + } catch(e) { try { console.log(msg) } catch(e) {} } + }; + + /** + * Sets verbosity level. + * @param {int} level The maximum level for debugging messages to be + * displayed. Thus you can tweak the verbosity of the logger. A + * value of 0 means very low traffic whilst a value of 4 makes + * logging very verbose about what's going on. + * @return This debug logger + * @type ConsoleLogger + */ + this.setLevel = function(level) { this.level = level; return this; }; + /** + * Gets verbosity level. + * @return The level + * @type int + */ + this.getLevel = function() { return this.level; }; +} diff --git a/src/com/anzsoft/public/dev/JSJaCConstants.js b/src/com/anzsoft/public/dev/JSJaCConstants.js new file mode 100644 index 0000000..aa4a0e1 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCConstants.js @@ -0,0 +1,97 @@ +var NS_DISCO_ITEMS = "http://jabber.org/protocol/disco#items"; +var NS_DISCO_INFO = "http://jabber.org/protocol/disco#info"; +var NS_VCARD = "vcard-temp"; +var NS_AUTH = "jabber:iq:auth"; +var NS_AUTH_ERROR = "jabber:iq:auth:error"; +var NS_REGISTER = "jabber:iq:register"; +var NS_SEARCH = "jabber:iq:search"; +var NS_ROSTER = "jabber:iq:roster"; +var NS_PRIVACY = "jabber:iq:privacy"; +var NS_PRIVATE = "jabber:iq:private"; +var NS_VERSION = "jabber:iq:version"; +var NS_TIME = "jabber:iq:time"; +var NS_LAST = "jabber:iq:last"; +var NS_XDATA = "jabber:x:data"; +var NS_IQDATA = "jabber:iq:data"; +var NS_DELAY = "jabber:x:delay"; +var NS_EXPIRE = "jabber:x:expire"; +var NS_EVENT = "jabber:x:event"; +var NS_XCONFERENCE = "jabber:x:conference"; +var NS_STATS = "http://jabber.org/protocol/stats"; +var NS_MUC = "http://jabber.org/protocol/muc"; +var NS_MUC_USER = "http://jabber.org/protocol/muc#user"; +var NS_MUC_ADMIN = "http://jabber.org/protocol/muc#admin"; +var NS_MUC_OWNER = "http://jabber.org/protocol/muc#owner"; +var NS_PUBSUB = "http://jabber.org/protocol/pubsub"; +var NS_PUBSUB_EVENT = "http://jabber.org/protocol/pubsub#event"; +var NS_PUBSUB_OWNER = "http://jabber.org/protocol/pubsub#owner"; +var NS_PUBSUB_NMI = "http://jabber.org/protocol/pubsub#node-meta-info"; +var NS_COMMANDS = "http://jabber.org/protocol/commands"; +var NS_STREAM = "http://etherx.jabber.org/streams"; + +var NS_STANZAS = "urn:ietf:params:xml:ns:xmpp-stanzas"; +var NS_STREAMS = "urn:ietf:params:xml:ns:xmpp-streams"; + +var NS_TLS = "urn:ietf:params:xml:ns:xmpp-tls"; +var NS_SASL = "urn:ietf:params:xml:ns:xmpp-sasl"; +var NS_SESSION = "urn:ietf:params:xml:ns:xmpp-session"; +var NS_BIND = "urn:ietf:params:xml:ns:xmpp-bind"; + +var NS_FEATURE_IQAUTH = "http://jabber.org/features/iq-auth"; +var NS_FEATURE_IQREGISTER = "http://jabber.org/features/iq-register"; +var NS_FEATURE_COMPRESS = "http://jabber.org/features/compress"; + +var NS_COMPRESS = "http://jabber.org/protocol/compress"; + +function STANZA_ERROR(code, type, cond) { + if (window == this) + return new STANZA_ERROR(code, type, cond); + + this.code = code; + this.type = type; + this.cond = cond; +} + +var ERR_BAD_REQUEST = + STANZA_ERROR("400", "modify", "bad-request"); +var ERR_CONFLICT = + STANZA_ERROR("409", "cancel", "conflict"); +var ERR_FEATURE_NOT_IMPLEMENTED = + STANZA_ERROR("501", "cancel", "feature-not-implemented"); +var ERR_FORBIDDEN = + STANZA_ERROR("403", "auth", "forbidden"); +var ERR_GONE = + STANZA_ERROR("302", "modify", "gone"); +var ERR_INTERNAL_SERVER_ERROR = + STANZA_ERROR("500", "wait", "internal-server-error"); +var ERR_ITEM_NOT_FOUND = + STANZA_ERROR("404", "cancel", "item-not-found"); +var ERR_JID_MALFORMED = + STANZA_ERROR("400", "modify", "jid-malformed"); +var ERR_NOT_ACCEPTABLE = + STANZA_ERROR("406", "modify", "not-acceptable"); +var ERR_NOT_ALLOWED = + STANZA_ERROR("405", "cancel", "not-allowed"); +var ERR_NOT_AUTHORIZED = + STANZA_ERROR("401", "auth", "not-authorized"); +var ERR_PAYMENT_REQUIRED = + STANZA_ERROR("402", "auth", "payment-required"); +var ERR_RECIPIENT_UNAVAILABLE = + STANZA_ERROR("404", "wait", "recipient-unavailable"); +var ERR_REDIRECT = + STANZA_ERROR("302", "modify", "redirect"); +var ERR_REGISTRATION_REQUIRED = + STANZA_ERROR("407", "auth", "registration-required"); +var ERR_REMOTE_SERVER_NOT_FOUND = + STANZA_ERROR("404", "cancel", "remote-server-not-found"); +var ERR_REMOTE_SERVER_TIMEOUT = + STANZA_ERROR("504", "wait", "remote-server-timeout"); +var ERR_RESOURCE_CONSTRAINT = + STANZA_ERROR("500", "wait", "resource-constraint"); +var ERR_SERVICE_UNAVAILABLE = + STANZA_ERROR("503", "cancel", "service-unavailable"); +var ERR_SUBSCRIPTION_REQUIRED = + STANZA_ERROR("407", "auth", "subscription-required"); +var ERR_UNEXPECTED_REQUEST = + STANZA_ERROR("400", "wait", "unexpected-request"); + diff --git a/src/com/anzsoft/public/dev/JSJaCCookie.js b/src/com/anzsoft/public/dev/JSJaCCookie.js new file mode 100644 index 0000000..78869f3 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCCookie.js @@ -0,0 +1,157 @@ +/* Copyright 2003-2006 Peter-Paul Koch + */ + +/** + * @fileoverview OO interface to handle cookies. + * Taken from {@link http://www.quirksmode.org/js/cookies.html + * http://www.quirksmode.org/js/cookies.html} + * Regarding licensing of this code the author states: + * + * "You may copy, tweak, rewrite, sell or lease any code example on + * this site, with one single exception." + * + * @author Stefan Strigler + * @version $Revision: 437 $ + */ + +/** + * Creates a new Cookie + * @class Class representing browser cookies for storing small amounts of data + * @constructor + * @param {String} name The name of the value to store + * @param {String} value The value to store + * @param {int} secs Number of seconds until cookie expires (may be empty) + */ +function JSJaCCookie(name,value,secs) +{ + if (window == this) + return new JSJaCCookie(name, value, secs); + + /** + * This cookie's name + * @type String + */ + this.name = name; + /** + * This cookie's value + * @type String + */ + this.value = value; + /** + * Time in seconds when cookie expires (thus being delete by + * browser). A value of -1 denotes a session cookie which means that + * stored data gets lost when browser is being closed. + * @type int + */ + this.expires = secs; + + /** + * Stores this cookie + */ + this.write = function() { + if (this.secs) { + var date = new Date(); + date.setTime(date.getTime()+(this.secs*1000)); + var expires = "; expires="+date.toGMTString(); + } else + var expires = ""; + document.cookie = this.getName()+"="+this.getValue()+expires+"; path=/"; + }; + /** + * Deletes this cookie + */ + this.erase = function() { + var c = new JSJaCCookie(this.getName(),"",-1); + c.write(); + }; + + /** + * Gets the name of this cookie + * @return The name + * @type String + */ + this.getName = function() { + return this.name; + }; + + /** + * Sets the name of this cookie + * @param {String} name The name for this cookie + * @return This cookie + * @type Cookie + */ + this.setName = function(name) { + this.name = name; + return this; + }; + + /** + * Gets the value of this cookie + * @return The value + * @type String + */ + this.getValue = function() { + return this.value; + }; + + /** + * Sets the value of this cookie + * @param {String} value The value for this cookie + * @return This cookie + * @type Cookie + */ + this.setValue = function(value) { + this.value = value; + return this; + }; +} + +/** + * Reads the value for given name from cookies and return new + * Cookie object + * @param {String} name The name of the cookie to read + * @return A cookie object of the given name + * @type Cookie + * @throws CookieException when cookie with given name could not be found + */ +JSJaCCookie.read = function(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for(var i=0;i < ca.length;i++) { + var c = ca[i]; + while (c.charAt(0)==' ') c = c.substring(1,c.length); + if (c.indexOf(nameEQ) == 0) return new JSJaCCookie(name, c.substring(nameEQ.length,c.length)); + } + throw new JSJaCCookieException("Cookie not found"); +}; + +/** + * Reads the value for given name from cookies and returns + * its valued new + * @param {String} name The name of the cookie to read + * @return The value of the cookie read + * @type String + * @throws CookieException when cookie with given name could not be found + */ +JSJaCCookie.get = function(name) { + return JSJaCCookie.read(name).getValue(); +}; + +/** + * Deletes cookie with given name + * @param {String} name The name of the cookie to delete + * @throws CookieException when cookie with given name could not be found + */ +JSJaCCookie.remove = function(name) { + JSJaCCookie.read(name).erase(); +}; + +/** + * Some exception denoted to dealing with cookies + * @constructor + * @param {String} msg The message to pass to the exception + */ +function JSJaCCookieException(msg) { + this.message = msg; + this.name = "CookieException"; +} diff --git a/src/com/anzsoft/public/dev/JSJaCError.js b/src/com/anzsoft/public/dev/JSJaCError.js new file mode 100644 index 0000000..f1bc6c2 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCError.js @@ -0,0 +1,15 @@ + +/** + * an error packet for internal use + * @private + * @constructor + */ +function JSJaCError(code,type,condition) { + var xmldoc = XmlDocument.create("error","jsjac"); + + xmldoc.documentElement.setAttribute('code',code); + xmldoc.documentElement.setAttribute('type',type); + xmldoc.documentElement.appendChild(xmldoc.createElement(condition)). + setAttribute('xmlns','urn:ietf:params:xml:ns:xmpp-stanzas'); + return xmldoc.documentElement; +} diff --git a/src/com/anzsoft/public/dev/JSJaCHttpBindingConnection.js b/src/com/anzsoft/public/dev/JSJaCHttpBindingConnection.js new file mode 100644 index 0000000..7e79b94 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCHttpBindingConnection.js @@ -0,0 +1,517 @@ +/** + * @fileoverview All stuff related to HTTP Binding + * @author Stefan Strigler steve@zeank.in-berlin.de + * @version $Revision: 473 $ + */ + +/** + * Instantiates an HTTP Binding session + * @class Implementation of {@link + * http://www.xmpp.org/extensions/xep-0206.html XMPP Over BOSH} + * formerly known as HTTP Binding. + * @extends JSJaCConnection + * @constructor + */ +function JSJaCHttpBindingConnection(oArg) { + /** + * @ignore + */ + this.base = JSJaCConnection; + this.base(oArg); + + // member vars + /** + * @private + */ + this._hold = JSJACHBC_MAX_HOLD; + /** + * @private + */ + this._inactivity = 0; + /** + * @private + */ + this._last_requests = new Object(); // 'hash' storing hold+1 last requests + /** + * @private + */ + this._last_rid = 0; // I know what you did last summer + /** + * @private + */ + this._min_polling = 0; + + /** + * @private + */ + this._pause = 0; + /** + * @private + */ + this._wait = JSJACHBC_MAX_WAIT; +} +JSJaCHttpBindingConnection.prototype = new JSJaCConnection(); + +/** + * Inherit an instantiated HTTP Binding session + */ +JSJaCHttpBindingConnection.prototype.inherit = function(oArg) { + this.domain = oArg.domain || 'localhost'; + this.username = oArg.username; + this.resource = oArg.resource; + this._sid = oArg.sid; + this._rid = oArg.rid; + this._min_polling = oArg.polling; + this._inactivity = oArg.inactivity; + this._setHold(oArg.requests-1); + this.setPollInterval(this._timerval); + if (oArg.wait) + this._wait = oArg.wait; // for whatever reason + + this._connected = true; + + this._handleEvent('onconnect'); + + this._interval= setInterval(JSJaC.bind(this._checkQueue, this), + JSJAC_CHECKQUEUEINTERVAL); + this._inQto = setInterval(JSJaC.bind(this._checkInQ, this), + JSJAC_CHECKINQUEUEINTERVAL); + this._timeout = setTimeout(JSJaC.bind(this._process, this), + this.getPollInterval()); +}; + +/** + * Sets poll interval + * @param {int} timerval the interval in seconds + */ +JSJaCHttpBindingConnection.prototype.setPollInterval = function(timerval) { + if (timerval && !isNaN(timerval)) { + if (!this.isPolling()) + this._timerval = 100; + else if (this._min_polling && timerval < this._min_polling*1000) + this._timerval = this._min_polling*1000; + else if (this._inactivity && timerval > this._inactivity*1000) + this._timerval = this._inactivity*1000; + else + this._timerval = timerval; + } + return this._timerval; +}; + +/** + * whether this session is in polling mode + * @type boolean + */ +JSJaCHttpBindingConnection.prototype.isPolling = function() { return (this._hold == 0) }; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._getFreeSlot = function() { + for (var i=0; i"; + } else { + reqstr += "/>"; + } + + this._last_requests[this._rid] = new Object(); + this._last_requests[this._rid].xml = reqstr; + this._last_rid = this._rid; + + for (var i in this._last_requests) + if (this._last_requests.hasOwnProperty(i) && + i < this._rid-this._hold) + delete(this._last_requests[i]); // truncate + } + + return reqstr; +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._getInitialRequestString = function() { + var reqstr = " JSJAC_ERR_COUNT) { + // abort + this._abort(); + return null; + } + this.oDbg.log("repeating ("+this._errcnt+")",1); + + this._setStatus('proto_error_fallback'); + + // schedule next tick + setTimeout(JSJaC.bind(this._resume, this), + this.getPollInterval()); + + return null; + } + } catch (e) { + this.oDbg.log("XMLHttpRequest error: status not available", 1); + this._errcnt++; + if (this._errcnt > JSJAC_ERR_COUNT) { + // abort + this._abort(); + } else { + this.oDbg.log("repeating ("+this._errcnt+")",1); + + this._setStatus('proto_error_fallback'); + + // schedule next tick + setTimeout(JSJaC.bind(this._resume, this), + this.getPollInterval()); + } + return null; + } + + var body = r.responseXML.documentElement; + if (!body || body.tagName != 'body' || + body.namespaceURI != 'http://jabber.org/protocol/httpbind') { + this.oDbg.log("invalid response:\n" + r.responseText,1); + + clearTimeout(this._timeout); // remove timer + clearInterval(this._interval); + clearInterval(this._inQto); + + this._connected = false; + this.oDbg.log("Disconnected.",1); + this._handleEvent('ondisconnect'); + + this._setStatus('internal_server_error'); + this._handleEvent('onerror', + JSJaCError('500','wait','internal-server-error')); + + return null; + } + + if (typeof(req.rid) != 'undefined' && this._last_requests[req.rid]) { + if (this._last_requests[req.rid].handled) { + this.oDbg.log("already handled "+req.rid,2); + return null; + } else + this._last_requests[req.rid].handled = true; + } + + + // Check for errors from the server + if (body.getAttribute("type") == "terminate") { + this.oDbg.log("session terminated:\n" + r.responseText,1); + + clearTimeout(this._timeout); // remove timer + clearInterval(this._interval); + clearInterval(this._inQto); + + if (body.getAttribute("condition") == "remote-stream-error") + if (body.getElementsByTagName("conflict").length > 0) + this._setStatus("session-terminate-conflict"); + this._handleEvent('onerror',JSJaCError('503','cancel',body.getAttribute('condition'))); + this._connected = false; + this.oDbg.log("Disconnected.",1); + this._handleEvent('ondisconnect'); + return null; + } + + // no error + this._errcnt = 0; + return r.responseXML.documentElement; +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._reInitStream = function(to,cb,arg) { + /* [TODO] we can't handle 'to' here as this is not (yet) supported + * by the protocol + */ + + // tell http binding to reinit stream with/before next request + this._reinit = true; + cb.call(this,arg); // proceed with next callback + + /* [TODO] make sure that we're checking for new stream features when + * 'cb' finishes + */ +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._resume = function() { + /* make sure to repeat last request as we can be sure that + * it had failed (only if we're not using the 'pause' attribute + */ + if (this._pause == 0 && this._rid >= this._last_rid) + this._rid = this._last_rid-1; + + this._process(); +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._setHold = function(hold) { + if (!hold || isNaN(hold) || hold < 0) + hold = 0; + else if (hold > JSJACHBC_MAX_HOLD) + hold = JSJACHBC_MAX_HOLD; + this._hold = hold; + return this._hold; +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._setupRequest = function(async) { + var req = new Object(); + var r = XmlHttp.create(); + try { + r.open("POST",this._httpbase,async); + r.setRequestHeader('Content-Type','text/xml; charset=utf-8'); + } catch(e) { this.oDbg.log(e,1); } + req.r = r; + this._rid++; + req.rid = this._rid; + return req; +}; + +/** + * @private + */ +JSJaCHttpBindingConnection.prototype._suspend = function() { + if (this._pause == 0) + return; // got nothing to do + + var slot = this._getFreeSlot(); + // Intentionally synchronous + this._req[slot] = this._setupRequest(false); + + var reqstr = "true if this is a polling connection, + * false otherwise. + * @type boolean + */ +JSJaCHttpPollingConnection.prototype.isPolling = function() { return true; }; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._getFreeSlot = function() { + if (typeof(this._req[0]) == 'undefined' || + typeof(this._req[0].r) == 'undefined' || + this._req[0].r.readyState == 4) + return 0; + else + return -1; +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._getInitialRequestString = function() { + var reqstr = "0"; + if (JSJAC_HAVEKEYS) { + this._keys = new JSJaCKeys(b64_sha1,this.oDbg); // generate first set of keys + key = this._keys.getKey(); + reqstr += ";"+key; + } + var streamto = this.domain; + if (this.authhost) + streamto = this.authhost; + + reqstr += ",\s*$/)) + response += ''; + + doc = XmlDocument.create("doc"); + doc.loadXML(response); + if (!this._parseStreamFeatures(doc)) + return; + } catch(e) { + this.oDbg.log("loadXML: "+e.toString(),1); + } + + this._connected = true; + + if (this.register) + this._doInBandReg(); + else + this._doAuth(); + + this._process(this._timerval); // start polling +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._getSuspendVars = function() { + return new Array(); +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._handleInitialResponse = function() { + // extract session ID + this.oDbg.log(this._req[0].r.getAllResponseHeaders(),4); + var aPList = this._req[0].r.getResponseHeader('Set-Cookie'); + aPList = aPList.split(";"); + for (var i=0;i/,""); + if (response.match(/"+response+""); + + if (!doc || doc.tagName == 'parsererror') { + this.oDbg.log("parsererror",1); + + doc = JSJaCHttpPollingConnection._parseTree(""+req.responseText); + if (doc && doc.tagName != 'parsererror') { + this.oDbg.log("stream closed",1); + + if (doc.getElementsByTagName('conflict').length > 0) + this._setStatus("session-terminate-conflict"); + + clearTimeout(this._timeout); // remove timer + clearInterval(this._interval); + clearInterval(this._inQto); + this._handleEvent('onerror',JSJaCError('503','cancel','session-terminate')); + this._connected = false; + this.oDbg.log("Disconnected.",1); + this._handleEvent('ondisconnect'); + } else + this.oDbg.log("parsererror:"+doc,1); + + return doc; + } + + return doc; + } catch (e) { + this.oDbg.log("parse error:"+e.message,1); + } + return null;; +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._reInitStream = function(to,cb,arg) { + this._sendRaw("",cb,arg); +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._resume = function() { + this._process(this._timerval); +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._setupRequest = function(async) { + var r = XmlHttp.create(); + try { + r.open("POST",this._httpbase,async); + if (r.overrideMimeType) + r.overrideMimeType('text/plain; charset=utf-8'); + r.setRequestHeader('Content-Type','application/x-www-form-urlencoded'); + } catch(e) { this.oDbg.log(e,1); } + + var req = new Object(); + req.r = r; + return req; +}; + +/** + * @private + */ +JSJaCHttpPollingConnection.prototype._suspend = function() {}; + +/*** [static] ***/ + +/** + * @private + */ +JSJaCHttpPollingConnection._parseTree = function(s) { + try { + var r = XmlDocument.create("body","foo"); + if (typeof(r.loadXML) != 'undefined') { + r.loadXML(s); + return r.documentElement; + } else if (window.DOMParser) + return (new DOMParser()).parseFromString(s, "text/xml").documentElement; + } catch (e) { } + return null; +}; diff --git a/src/com/anzsoft/public/dev/JSJaCJID.js b/src/com/anzsoft/public/dev/JSJaCJID.js new file mode 100644 index 0000000..e4e946c --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCJID.js @@ -0,0 +1,198 @@ +/** + * @fileoverview This file contains all things that make life easier when + * dealing with JIDs + * @author Stefan Strigler + * @version $Revision: 437 $ + */ + +/** + * list of forbidden chars for nodenames + * @private + */ +var JSJACJID_FORBIDDEN = ['"',' ','&','\'','/',':','<','>','@']; + +/** + * Creates a new JSJaCJID object + * @class JSJaCJID models xmpp jid objects + * @constructor + * @param {Object} jid jid may be either of type String or a JID represented + * by JSON with fields 'node', 'domain' and 'resource' + * @throws JSJaCJIDInvalidException Thrown if jid is not valid + * @return a new JSJaCJID object + */ +function JSJaCJID(jid) { + /** + *@private + */ + this._node = ''; + /** + *@private + */ + this._domain = ''; + /** + *@private + */ + this._resource = ''; + + if (typeof(jid) == 'string') { + if (jid.indexOf('@') != -1) { + this.setNode(jid.substring(0,jid.indexOf('@'))); + jid = jid.substring(jid.indexOf('@')+1); + } + if (jid.indexOf('/') != -1) { + this.setResource(jid.substring(jid.indexOf('/')+1)); + jid = jid.substring(0,jid.indexOf('/')); + } + this.setDomain(jid); + } else { + this.setNode(jid.node); + this.setDomain(jid.domain); + this.setResource(jid.resource); + } +} + + +/** + * Gets the node part of the jid + * @return A string representing the node name + * @type String + */ +JSJaCJID.prototype.getNode = function() { return this._node; }; + +/** + * Gets the domain part of the jid + * @return A string representing the domain name + * @type String + */ +JSJaCJID.prototype.getDomain = function() { return this._domain; }; + +/** + * Gets the resource part of the jid + * @return A string representing the resource + * @type String + */ +JSJaCJID.prototype.getResource = function() { return this._resource; }; + + +/** + * Sets the node part of the jid + * @param {String} node Name of the node + * @throws JSJaCJIDInvalidException Thrown if node name contains invalid chars + * @return This object + * @type JSJaCJID + */ +JSJaCJID.prototype.setNode = function(node) { + JSJaCJID._checkNodeName(node); + this._node = node || ''; + return this; +}; + +/** + * Sets the domain part of the jid + * @param {String} domain Name of the domain + * @throws JSJaCJIDInvalidException Thrown if domain name contains invalid + * chars or is empty + * @return This object + * @type JSJaCJID + */ +JSJaCJID.prototype.setDomain = function(domain) { + if (!domain || domain == '') + throw new JSJaCJIDInvalidException("domain name missing"); + // chars forbidden for a node are not allowed in domain names + // anyway, so let's check + JSJaCJID._checkNodeName(domain); + this._domain = domain; + return this; +}; + +/** + * Sets the resource part of the jid + * @param {String} resource Name of the resource + * @return This object + * @type JSJaCJID + */ +JSJaCJID.prototype.setResource = function(resource) { + this._resource = resource || ''; + return this; +}; + +/** + * The string representation of the full jid + * @return A string representing the jid + * @type String + */ +JSJaCJID.prototype.toString = function() { + var jid = ''; + if (this.getNode() && this.getNode() != '') + jid = this.getNode() + '@'; + jid += this.getDomain(); // we always have a domain + if (this.getResource() && this.getResource() != "") + jid += '/' + this.getResource(); + return jid; +}; + +/** + * Removes the resource part of the jid + * @return This object + * @type JSJaCJID + */ +JSJaCJID.prototype.removeResource = function() { + return this.setResource(); +}; + +/** + * creates a copy of this JSJaCJID object + * @return A copy of this + * @type JSJaCJID + */ +JSJaCJID.prototype.clone = function() { + return new JSJaCJID(this.toString()); +}; + +/** + * Compares two jids if they belong to the same entity (i.e. w/o resource) + * @param {String} jid a jid as string or JSJaCJID object + * @return 'true' if jid is same entity as this + * @type Boolean + */ +JSJaCJID.prototype.isEntity = function(jid) { + if (typeof jid == 'string') + jid = (new JSJaCJID(jid)); + jid.removeResource(); + return (this.clone().removeResource().toString() === jid.toString()); +}; + +/** + * Check if node name is valid + * @private + * @param {String} node A name for a node + * @throws JSJaCJIDInvalidException Thrown if name for node is not allowed + */ +JSJaCJID._checkNodeName = function(nodeprep) { + if (!nodeprep || nodeprep == '') + return; + for (var i=0; i< JSJACJID_FORBIDDEN.length; i++) { + if (nodeprep.indexOf(JSJACJID_FORBIDDEN[i]) != -1) { + throw new JSJaCJIDInvalidException("forbidden char in nodename: "+JSJACJID_FORBIDDEN[i]); + } + } +}; + +/** + * Creates a new Exception of type JSJaCJIDInvalidException + * @class Exception to indicate invalid values for a jid + * @constructor + * @param {String} message The message associated with this Exception + */ +function JSJaCJIDInvalidException(message) { + /** + * The exceptions associated message + * @type String + */ + this.message = message; + /** + * The name of the exception + * @type String + */ + this.name = "JSJaCJIDInvalidException"; +} diff --git a/src/com/anzsoft/public/dev/JSJaCJSON.js b/src/com/anzsoft/public/dev/JSJaCJSON.js new file mode 100644 index 0000000..1d4b903 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCJSON.js @@ -0,0 +1,127 @@ +/* Copyright (c) 2005-2007 Sam Stephenson + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +/* + json.js + taken from prototype.js, made static +*/ +function JSJaCJSON() {} +JSJaCJSON.toString = function (obj) { + var m = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + s = { + array: function (x) { + var a = ['['], b, f, i, l = x.length, v; + for (i = 0; i < l; i += 1) { + v = x[i]; + f = s[typeof v]; + if (f) { + v = f(v); + if (typeof v == 'string') { + if (b) { + a[a.length] = ','; + } + a[a.length] = v; + b = true; + } + } + } + a[a.length] = ']'; + return a.join(''); + }, + 'boolean': function (x) { + return String(x); + }, + 'null': function (x) { + return "null"; + }, + number: function (x) { + return isFinite(x) ? String(x) : 'null'; + }, + object: function (x) { + if (x) { + if (x instanceof Array) { + return s.array(x); + } + var a = ['{'], b, f, i, v; + for (i in x) { + if (x.hasOwnProperty(i)) { + v = x[i]; + f = s[typeof v]; + if (f) { + v = f(v); + if (typeof v == 'string') { + if (b) { + a[a.length] = ','; + } + a.push(s.string(i), ':', v); + b = true; + } + } + } + } + + a[a.length] = '}'; + return a.join(''); + } + return 'null'; + }, + string: function (x) { + if (/["\\\x00-\x1f]/.test(x)) { + x = x.replace(/([\x00-\x1f\\"])/g, function(a, b) { + var c = m[b]; + if (c) { + return c; + } + c = b.charCodeAt(); + return '\\u00' + + Math.floor(c / 16).toString(16) + + (c % 16).toString(16); + }); + } + return '"' + x + '"'; +} + }; + +switch (typeof(obj)) { + case 'object': + return s.object(obj); + case 'array': + return s.array(obj); + + } +}; + +JSJaCJSON.parse = function (str) { + try { + return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( + str.replace(/"(\\.|[^"\\])*"/g, ''))) && + eval('(' + str + ')'); + } catch (e) { + return false; + } +}; diff --git a/src/com/anzsoft/public/dev/JSJaCKeys.js b/src/com/anzsoft/public/dev/JSJaCKeys.js new file mode 100644 index 0000000..98dc4c7 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCKeys.js @@ -0,0 +1,66 @@ + +/** + * Creates a new set of hash keys + * @class Reflects a set of sha1/md5 hash keys for securing sessions + * @constructor + * @param {Function} func The hash function to be used for creating the keys + * @param {Debugger} oDbg Reference to debugger implementation [optional] + */ +function JSJaCKeys(func,oDbg) { + var seed = Math.random(); + + /** + * @private + */ + this._k = new Array(); + this._k[0] = seed.toString(); + if (oDbg) + /** + * Reference to Debugger + * @type Debugger + */ + this.oDbg = oDbg; + else { + this.oDbg = {}; + this.oDbg.log = function() {}; + } + + if (func) { + for (var i=1; itrue if there's only one key left, false otherwise + * @type boolean + */ + this.lastKey = function() { return (this._indexAt == 0); }; + /** + * Returns number of overall/initial stack size + * @return Number of keys created + * @type int + */ + this.size = function() { return this._k.length; }; + + /** + * @private + */ + this._getSuspendVars = function() { + return ('_k,_indexAt').split(','); + } +} diff --git a/src/com/anzsoft/public/dev/JSJaCPacket.js b/src/com/anzsoft/public/dev/JSJaCPacket.js new file mode 100644 index 0000000..2519b05 --- /dev/null +++ b/src/com/anzsoft/public/dev/JSJaCPacket.js @@ -0,0 +1,681 @@ +/** + * @fileoverview Contains all Jabber/XMPP packet related classes. + * @author Stefan Strigler steve@zeank.in-berlin.de + * @version $Revision: 476 $ + */ + +var JSJACPACKET_USE_XMLNS = true; + +/** + * Creates a new packet with given root tag name (for internal use) + * @class Somewhat abstract base class for all kinds of specialised packets + * @param {String} name The root tag name of the packet + * (i.e. one of 'message', 'iq' or 'presence') + */ +function JSJaCPacket(name) { + /** + * @private + */ + this.name = name; + + if (typeof(JSJACPACKET_USE_XMLNS) != 'undefined' && JSJACPACKET_USE_XMLNS) + /** + * @private + */ + this.doc = XmlDocument.create(name,'jabber:client'); + else + /** + * @private + */ + this.doc = XmlDocument.create(name,''); +} + +/** + * Gets the type (name of root element) of this packet, i.e. one of + * 'presence', 'message' or 'iq' + * @return the top level tag name + * @type String + */ +JSJaCPacket.prototype.pType = function() { return this.name; }; + +/** + * Gets the associated Document for this packet. + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#i-Document Document} + */ +JSJaCPacket.prototype.getDoc = function() { + return this.doc; +}; +/** + * Gets the root node of this packet + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} + */ +JSJaCPacket.prototype.getNode = function() { + if (this.getDoc() && this.getDoc().documentElement) + return this.getDoc().documentElement; + else + return null; +}; + +/** + * Sets the 'to' attribute of the root node of this packet + * @param {String} to + * @type JSJaCPacket + */ +JSJaCPacket.prototype.setTo = function(to) { + if (!to || to == '') + this.getNode().removeAttribute('to'); + else if (typeof(to) == 'string') + this.getNode().setAttribute('to',to); + else + this.getNode().setAttribute('to',to.toString()); + return this; +}; +/** + * Sets the 'from' attribute of the root node of this + * packet. Usually this is not needed as the server will take care + * of this automatically. + * @type JSJaCPacket + */ +JSJaCPacket.prototype.setFrom = function(from) { + if (!from || from == '') + this.getNode().removeAttribute('from'); + else if (typeof(from) == 'string') + this.getNode().setAttribute('from',from); + else + this.getNode().setAttribute('from',from.toString()); + return this; +}; +/** + * Sets 'id' attribute of the root node of this packet. + * @param {String} id The id of the packet. + * @type JSJaCPacket + */ +JSJaCPacket.prototype.setID = function(id) { + if (!id || id == '') + this.getNode().removeAttribute('id'); + else + this.getNode().setAttribute('id',id); + return this; +}; +/** + * Sets the 'type' attribute of the root node of this packet. + * @param {String} type The type of the packet. + * @type JSJaCPacket + */ +JSJaCPacket.prototype.setType = function(type) { + if (!type || type == '') + this.getNode().removeAttribute('type'); + else + this.getNode().setAttribute('type',type); + return this; +}; +/** + * Sets 'xml:lang' for this packet + * @param {String} xmllang The xml:lang of the packet. + * @type JSJaCPacket + */ +JSJaCPacket.prototype.setXMLLang = function(xmllang) { + if (!xmllang || xmllang == '') + this.getNode().removeAttribute('xml:lang'); + else + this.getNode().setAttribute('xml:lang',xmllang); + return this; +}; + +/** + * Gets the 'to' attribute of this packet + * @type String + */ +JSJaCPacket.prototype.getTo = function() { + return this.getNode().getAttribute('to'); +}; +/** + * Gets the 'from' attribute of this packet. + * @type String + */ +JSJaCPacket.prototype.getFrom = function() { + return this.getNode().getAttribute('from'); +}; +/** + * Gets the 'to' attribute of this packet as a JSJaCJID object + * @type JSJaCJID + */ +JSJaCPacket.prototype.getToJID = function() { + return new JSJaCJID(this.getTo()); +}; +/** + * Gets the 'from' attribute of this packet as a JSJaCJID object + * @type JSJaCJID + */ +JSJaCPacket.prototype.getFromJID = function() { + return new JSJaCJID(this.getFrom()); +}; +/** + * Gets the 'id' of this packet + * @type String + */ +JSJaCPacket.prototype.getID = function() { + return this.getNode().getAttribute('id'); +}; +/** + * Gets the 'type' of this packet + * @type String + */ +JSJaCPacket.prototype.getType = function() { + return this.getNode().getAttribute('type'); +}; +/** + * Gets the 'xml:lang' of this packet + * @type String + */ +JSJaCPacket.prototype.getXMLLang = function() { + return this.getNode().getAttribute('xml:lang'); +}; +/** + * Gets the 'xmlns' (xml namespace) of the root node of this packet + * @type String + */ +JSJaCPacket.prototype.getXMLNS = function() { + return this.getNode().namespaceURI; +}; + +/** + * Gets a child element of this packet. If no params given returns first child. + * @param {String} name Tagname of child to retrieve. Use '*' to match any tag. [optional] + * @param {String} ns Namespace of child. Use '*' to match any ns.[optional] + * @return The child node, null if none found + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} + */ +JSJaCPacket.prototype.getChild = function(name, ns) { + if (!this.getNode()) { + return null; + } + + name = name || '*'; + ns = ns || '*'; + + if (this.getNode().getElementsByTagNameNS) { + return this.getNode().getElementsByTagNameNS(ns, name).item(0); + } + + // fallback + var nodes = this.getNode().getElementsByTagName(name); + if (ns != '*') { + for (var i=0; i + * The original parts of the code do have the following copyright + * and license notice:
    + * Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, + * http://mir.acu lo.us)
    + * script.aculo.us is freely distributable under the terms of an + * MIT-style licen se. // For details, see the script.aculo.us web + * site: http://script.aculo.us/
    + * @author Thomas Fuchs + * @author Stefan Strigler + * @return The newly created node + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} + */ +JSJaCPacket.prototype.buildNode = function(elementName) { + return JSJaCBuilder.buildNode(this.getDoc(), + elementName, + arguments[1], + arguments[2]); +}; + +/** + * Appends node created by buildNode to this packets parent node. + * @param {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} element The node to append or + * @param {String} element A name plus an object hash with attributes (optional) plus an array of childnodes (optional) + * @see #buildNode + * @return This packet + * @type JSJaCPacket + */ +JSJaCPacket.prototype.appendNode = function(element) { + if (typeof element=='object') { // seems to be a prebuilt node + return this.getNode().appendChild(element) + } else { // build node + return this.getNode().appendChild(this.buildNode(element, + arguments[1], + arguments[2], + null, + this.getNode().namespaceURI)); + } +}; + + +/** + * A jabber/XMPP presence packet + * @class Models the XMPP notion of a 'presence' packet + * @extends JSJaCPacket + */ +function JSJaCPresence() { + /** + * @ignore + */ + this.base = JSJaCPacket; + this.base('presence'); +} +JSJaCPresence.prototype = new JSJaCPacket; + +/** + * Sets the status message for current status. Usually this is set + * to some human readable string indicating what the user is + * doing/feel like currently. + * @param {String} status A status message + * @return this + * @type JSJaCPacket + */ +JSJaCPresence.prototype.setStatus = function(status) { + this._setChildNode("status", status); + return this; +}; +/** + * Sets the online status for this presence packet. + * @param {String} show An XMPP complient status indicator. Must + * be one of 'chat', 'away', 'xa', 'dnd' + * @return this + * @type JSJaCPacket + */ +JSJaCPresence.prototype.setShow = function(show) { + if (show == 'chat' || show == 'away' || show == 'xa' || show == 'dnd') + this._setChildNode("show",show); + return this; +}; +/** + * Sets the priority of the resource bind to with this connection + * @param {int} prio The priority to set this resource to + * @return this + * @type JSJaCPacket + */ +JSJaCPresence.prototype.setPriority = function(prio) { + this._setChildNode("priority", prio); + return this; +}; +/** + * Some combined method that allowes for setting show, status and + * priority at once + * @param {String} show A status message + * @param {String} status A status indicator as defined by XMPP + * @param {int} prio A priority for this resource + * @return this + * @type JSJaCPacket + */ +JSJaCPresence.prototype.setPresence = function(show,status,prio) { + if (show) + this.setShow(show); + if (status) + this.setStatus(status); + if (prio) + this.setPriority(prio); + return this; +}; + +/** + * Gets the status message of this presence + * @return The (human readable) status message + * @type String + */ +JSJaCPresence.prototype.getStatus = function() { + return this.getChildVal('status'); +}; +/** + * Gets the status of this presence. + * Either one of 'chat', 'away', 'xa' or 'dnd' or null. + * @return The status indicator as defined by XMPP + * @type String + */ +JSJaCPresence.prototype.getShow = function() { + return this.getChildVal('show'); +}; +/** + * Gets the priority of this status message + * @return A resource priority + * @type int + */ +JSJaCPresence.prototype.getPriority = function() { + return this.getChildVal('priority'); +}; + + +/** + * A jabber/XMPP iq packet + * @class Models the XMPP notion of an 'iq' packet + * @extends JSJaCPacket + */ +function JSJaCIQ() { + /** + * @ignore + */ + this.base = JSJaCPacket; + this.base('iq'); +} +JSJaCIQ.prototype = new JSJaCPacket; + +/** + * Some combined method to set 'to', 'type' and 'id' at once + * @param {String} to the recepients JID + * @param {String} type A XMPP compliant iq type (one of 'set', 'get', 'result' and 'error' + * @param {String} id A packet ID + * @return this + * @type JSJaCIQ + */ +JSJaCIQ.prototype.setIQ = function(to,type,id) { + if (to) + this.setTo(to); + if (type) + this.setType(type); + if (id) + this.setID(id); + return this; +}; +/** + * Creates a 'query' child node with given XMLNS + * @param {String} xmlns The namespace for the 'query' node + * @return The query node + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} + */ +JSJaCIQ.prototype.setQuery = function(xmlns) { + var query; + try { + query = this.getDoc().createElementNS(xmlns,'query'); + } catch (e) { + // fallback + query = this.getDoc().createElement('query'); + } + if (query && query.getAttribute('xmlns') != xmlns) // fix opera 8.5x + query.setAttribute('xmlns',xmlns); + this.getNode().appendChild(query); + return query; +}; + +/** + * Gets the 'query' node of this packet + * @return The query node + * @type {@link http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247 Node} + */ +JSJaCIQ.prototype.getQuery = function() { + return this.getNode().getElementsByTagName('query').item(0); +}; +/** + * Gets the XMLNS of the query node contained within this packet + * @return The namespace of the query node + * @type String + */ +JSJaCIQ.prototype.getQueryXMLNS = function() { + if (this.getQuery()) + return this.getQuery().namespaceURI; + else + return null; +}; + +/** + * Creates an IQ reply with type set to 'result'. If given appends payload to first child if IQ. Payload maybe XML as string or a DOM element (or an array of such elements as well). + * @param {Element} payload A payload to be appended [optional] + * @return An IQ reply packet + * @type JSJaCIQ + */ +JSJaCIQ.prototype.reply = function(payload) { + var rIQ = this.clone(); + rIQ.setTo(this.getFrom()); + rIQ.setType('result'); + if (payload) { + if (typeof payload == 'string') + rIQ.getChild().appendChild(rIQ.getDoc().loadXML(payload)); + else if (payload.constructor == Array) { + var node = rIQ.getChild(); + for (var i=0; inull is being returned. + * @type JSJaCPacket + */ +JSJaCPacket.wrapNode = function(node) { + var aNode; + switch (node.nodeName.toLowerCase()) { + case 'presence': + aNode = new JSJaCPresence(); + break; + case 'message': + aNode = new JSJaCMessage(); + break; + case 'iq': + aNode = new JSJaCIQ(); + break; + default : // unknown + return null; + } + + aNode._replaceNode(node); + + return aNode; +}; + diff --git a/src/com/anzsoft/public/dev/Makefile b/src/com/anzsoft/public/dev/Makefile new file mode 100644 index 0000000..bb2561d --- /dev/null +++ b/src/com/anzsoft/public/dev/Makefile @@ -0,0 +1,6 @@ + +all: + @cd .. && make && cd src + +pack: + @cd .. && make pack && cd src diff --git a/src/com/anzsoft/public/dev/crypt.js b/src/com/anzsoft/public/dev/crypt.js new file mode 100644 index 0000000..08af9d8 --- /dev/null +++ b/src/com/anzsoft/public/dev/crypt.js @@ -0,0 +1,646 @@ +/* Copyright (c) 1998 - 2007, Paul Johnston & Contributors + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following + * disclaimer. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @fileoverview Collection of MD5 and SHA1 hashing and encoding + * methods. + * @author Stefan Strigler steve@zeank.in-berlin.de + * @version $Revision: 437 $ + */ + +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ +var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} +function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} +function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} +function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} +function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} +function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha1_vm_test() +{ + return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; +} + +/* + * Calculate the SHA-1 of an array of big-endian words, and a bit length + */ +function core_sha1(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << (24 - len % 32); + x[((len + 64 >> 9) << 4) + 15] = len; + + var w = Array(80); + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + var e = -1009589776; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + var olde = e; + + for(var j = 0; j < 80; j++) + { + if(j < 16) w[j] = x[i + j]; + else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); + var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), + safe_add(safe_add(e, w[j]), sha1_kt(j))); + e = d; + d = c; + c = rol(b, 30); + b = a; + a = t; + } + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + e = safe_add(e, olde); + } + return Array(a, b, c, d, e); + +} + +/* + * Perform the appropriate triplet combination function for the current + * iteration + */ +function sha1_ft(t, b, c, d) +{ + if(t < 20) return (b & c) | ((~b) & d); + if(t < 40) return b ^ c ^ d; + if(t < 60) return (b & c) | (b & d) | (c & d); + return b ^ c ^ d; +} + +/* + * Determine the appropriate additive constant for the current iteration + */ +function sha1_kt(t) +{ + return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : + (t < 60) ? -1894007588 : -899497514; +} + +/* + * Calculate the HMAC-SHA1 of a key and some data + */ +function core_hmac_sha1(key, data) +{ + var bkey = str2binb(key); + if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); + return core_sha1(opad.concat(hash), 512 + 160); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert an 8-bit or 16-bit string to an array of big-endian words + * In 8-bit function, characters >255 have their hi-byte silently ignored. + */ +function str2binb(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); + return bin; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); + return str; +} + +/* + * Convert an array of big-endian words to a hex string. + */ +function binb2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of big-endian words to a base-64 string + */ +function binb2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for more info. + */ + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +// var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +// var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ +// var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} +function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} +function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} +function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } +function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } +function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function md5_vm_test() +{ + return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; +} + +/* + * Calculate the MD5 of an array of little-endian words, and a bit length + */ +function core_md5(x, len) +{ + /* append padding */ + x[len >> 5] |= 0x80 << ((len) % 32); + x[(((len + 64) >>> 9) << 4) + 14] = len; + + var a = 1732584193; + var b = -271733879; + var c = -1732584194; + var d = 271733878; + + for(var i = 0; i < x.length; i += 16) + { + var olda = a; + var oldb = b; + var oldc = c; + var oldd = d; + + a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = md5_ff(c, d, a, b, x[i+10], 17, -42063); + b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); + a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); + c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); + b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); + b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); + c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); + b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); + b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); + a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); + a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); + d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); + c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); + b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); + b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); + b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); + c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); + a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); + c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = safe_add(a, olda); + b = safe_add(b, oldb); + c = safe_add(c, oldc); + d = safe_add(d, oldd); + } + return Array(a, b, c, d); + +} + +/* + * These functions implement the four basic operations the algorithm uses. + */ +function md5_cmn(q, a, b, x, s, t) +{ + return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); +} +function md5_ff(a, b, c, d, x, s, t) +{ + return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function md5_gg(a, b, c, d, x, s, t) +{ + return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function md5_hh(a, b, c, d, x, s, t) +{ + return md5_cmn(b ^ c ^ d, a, b, x, s, t); +} +function md5_ii(a, b, c, d, x, s, t) +{ + return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Calculate the HMAC-MD5, of a key and some data + */ +function core_hmac_md5(key, data) +{ + var bkey = str2binl(key); + if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); + return core_md5(opad.concat(hash), 512 + 128); +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function safe_add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left. + */ +function bit_rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * Convert a string to an array of little-endian words + * If chrsz is ASCII, characters >255 have their hi-byte silently ignored. + */ +function str2binl(str) +{ + var bin = Array(); + var mask = (1 << chrsz) - 1; + for(var i = 0; i < str.length * chrsz; i += chrsz) + bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); + return bin; +} + +/* + * Convert an array of little-endian words to a string + */ +function binl2str(bin) +{ + var str = ""; + var mask = (1 << chrsz) - 1; + for(var i = 0; i < bin.length * 32; i += chrsz) + str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); + return str; +} + +/* + * Convert an array of little-endian words to a hex string. + */ +function binl2hex(binarray) +{ + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i++) + { + str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + + hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); + } + return str; +} + +/* + * Convert an array of little-endian words to a base-64 string + */ +function binl2b64(binarray) +{ + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var str = ""; + for(var i = 0; i < binarray.length * 4; i += 3) + { + var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) + | (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) + | ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; + else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); + } + } + return str; +} + +/* ############################################################################# + UTF-8 Decoder and Encoder + base64 Encoder and Decoder + written by Tobias Kieslich, justdreams + Contact: tobias@justdreams.de http://www.justdreams.de/ + ############################################################################# */ + +// returns an array of byterepresenting dezimal numbers which represent the +// plaintext in an UTF-8 encoded version. Expects a string. +// This function includes an exception management for those nasty browsers like +// NN401, which returns negative decimal numbers for chars>128. I hate it!! +// This handling is unfortunately limited to the user's charset. Anyway, it works +// in most of the cases! Special signs with an unicode>256 return numbers, which +// can not be converted to the actual unicode and so not to the valid utf-8 +// representation. Anyway, this function does always return values which can not +// misinterpretd by RC4 or base64 en- or decoding, because every value is >0 and +// <255!! +// Arrays are faster and easier to handle in b64 encoding or encrypting.... +function utf8t2d(t) +{ + t = t.replace(/\r\n/g,"\n"); + var d=new Array; var test=String.fromCharCode(237); + if (test.charCodeAt(0) < 0) + for(var n=0; n0) + d[d.length]= c; + else { + d[d.length]= (((256+c)>>6)|192); + d[d.length]= (((256+c)&63)|128);} + } + else + for(var n=0; n 1byte + if (c<128) + d[d.length]= c; + // all the signs between 127 and 2047 => 2byte + else if((c>127) && (c<2048)) { + d[d.length]= ((c>>6)|192); + d[d.length]= ((c&63)|128);} + // all the signs between 2048 and 66536 => 3byte + else { + d[d.length]= ((c>>12)|224); + d[d.length]= (((c>>6)&63)|128); + d[d.length]= ((c&63)|128);} + } + return d; +} + +// returns plaintext from an array of bytesrepresenting dezimal numbers, which +// represent an UTF-8 encoded text; browser which does not understand unicode +// like NN401 will show "?"-signs instead +// expects an array of byterepresenting decimals; returns a string +function utf8d2t(d) +{ + var r=new Array; var i=0; + while(i191) && (d[i]<224)) { + r[r.length]= String.fromCharCode(((d[i]&31)<<6) | (d[i+1]&63)); i+=2;} + else { + r[r.length]= String.fromCharCode(((d[i]&15)<<12) | ((d[i+1]&63)<<6) | (d[i+2]&63)); i+=3;} + } + return r.join(""); +} + +// included in it creates two arrays which makes base64 +// en- and decoding faster +// this speed is noticeable especially when coding larger texts (>5k or so) +function b64arrays() { + var b64s='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + b64 = new Array();f64 =new Array(); + for (var i=0; i>2]; + r[r.length] = b64[((d[i]&3)<<4) | (d[i+1]>>4)]; + r[r.length] = b64[((d[i+1]&15)<<2) | (d[i+2]>>6)]; + r[r.length] = b64[d[i+2]&63]; + i+=3; + } + // this is again for the padding + if ((dl%3) == 1) + r[r.length-1] = r[r.length-2] = "="; + if ((dl%3) == 2) + r[r.length-1] = "="; + // we join the array to return a textstring + var t=r.join(""); + return t; +} + +// returns array of byterepresenting numbers created of an base64 encoded text +// it is still the slowest function in this modul; I hope I can make it faster +// expects string; returns an array +function b64t2d(t) { + var d=new Array; var i=0; + // here we fix this CRLF sequenz created by MS-OS; arrrgh!!! + t=t.replace(/\n|\r/g,""); t=t.replace(/=/g,""); + while (i>4); + d[d.length] = (((f64[t.charAt(i+1)]&15)<<4) | (f64[t.charAt(i+2)]>>2)); + d[d.length] = (((f64[t.charAt(i+2)]&3)<<6) | (f64[t.charAt(i+3)])); + i+=4; + } + if (t.length%4 == 2) + d = d.slice(0, d.length-2); + if (t.length%4 == 3) + d = d.slice(0, d.length-1); + return d; +} + +if (typeof(atob) == 'undefined' || typeof(btoa) == 'undefined') + b64arrays(); + +if (typeof(atob) == 'undefined') { + atob = function(s) { + return utf8d2t(b64t2d(s)); + } +} + +if (typeof(btoa) == 'undefined') { + btoa = function(s) { + return b64d2t(utf8t2d(s)); + } +} + +function cnonce(size) { + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var cnonce = ''; + for (var i=0; i/g,">"); + str = str.replace(/\"/g,"""); + str = str.replace(/\n/g,"
    "); + return str; +}; + +/** + * Converts from jabber timestamps to JavaScript Date objects + * @addon + * @param {String} ts A string representing a jabber datetime timestamp as + * defined by {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082} + * @return A javascript Date object corresponding to the jabber DateTime given + * @type Date + */ +Date.jab2date = function(ts) { + var date = new Date(Date.UTC(ts.substr(0,4),ts.substr(5,2)-1,ts.substr(8,2),ts.substr(11,2),ts.substr(14,2),ts.substr(17,2))); + if (ts.substr(ts.length-6,1) != 'Z') { // there's an offset + var offset = new Date(); + offset.setTime(0); + offset.setUTCHours(ts.substr(ts.length-5,2)); + offset.setUTCMinutes(ts.substr(ts.length-2,2)); + if (ts.substr(ts.length-6,1) == '+') + date.setTime(date.getTime() - offset.getTime()); + else if (ts.substr(ts.length-6,1) == '-') + date.setTime(date.getTime() + offset.getTime()); + } + return date; +}; + +/** + * Takes a timestamp in the form of 2004-08-13T12:07:04+02:00 as argument + * and converts it to some sort of humane readable format + * @addon + */ +Date.hrTime = function(ts) { + return Date.jab2date(ts).toLocaleString(); +}; + +/** + * somewhat opposit to {@link #hrTime} + * expects a javascript Date object as parameter and returns a jabber + * date string conforming to + * {@link http://www.xmpp.org/extensions/xep-0082.html XEP-0082} + * @see #hrTime + * @return The corresponding jabber DateTime string + * @type String + */ +Date.prototype.jabberDate = function() { + var padZero = function(i) { + if (i < 10) return "0" + i; + return i; + }; + + var jDate = this.getUTCFullYear() + "-"; + jDate += padZero(this.getUTCMonth()+1) + "-"; + jDate += padZero(this.getUTCDate()) + "T"; + jDate += padZero(this.getUTCHours()) + ":"; + jDate += padZero(this.getUTCMinutes()) + ":"; + jDate += padZero(this.getUTCSeconds()) + "Z"; + + return jDate; +}; + +/** + * Determines the maximum of two given numbers + * @addon + * @param {Number} A a number + * @param {Number} B another number + * @return the maximum of A and B + * @type Number + */ +Number.max = function(A, B) { + return (A > B)? A : B; +}; diff --git a/src/com/anzsoft/public/dev/xmlextras.js b/src/com/anzsoft/public/dev/xmlextras.js new file mode 100644 index 0000000..b55975d --- /dev/null +++ b/src/com/anzsoft/public/dev/xmlextras.js @@ -0,0 +1,232 @@ + +/* Copyright 2006 Erik Arvidsson + * + * Licensed 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. + */ + +/** + * @fileoverview Wrapper to make working with XmlHttpRequest and the + * DOM more convenient (cross browser compliance). + * this code is taken from + * http://webfx.eae.net/dhtml/xmlextras/xmlextras.html + * @author Stefan Strigler steve@zeank.in-berlin.de + * @version $Revision: 437 $ + */ + +/** + * XmlHttp factory + * @private + */ +function XmlHttp() {} + +/** + * creates a cross browser compliant XmlHttpRequest object + */ +XmlHttp.create = function () { + try { + if (window.XMLHttpRequest) { + var req = new XMLHttpRequest(); + + // some versions of Moz do not support the readyState property + // and the onreadystate event so we patch it! + if (req.readyState == null) { + req.readyState = 1; + req.addEventListener("load", function () { + req.readyState = 4; + if (typeof req.onreadystatechange == "function") + req.onreadystatechange(); + }, false); + } + + return req; + } + if (window.ActiveXObject) { + return new ActiveXObject(XmlHttp.getPrefix() + ".XmlHttp"); + } + } + catch (ex) {} + // fell through + throw new Error("Your browser does not support XmlHttp objects"); +}; + +/** + * used to find the Automation server name + * @private + */ +XmlHttp.getPrefix = function() { + if (XmlHttp.prefix) // I know what you did last summer + return XmlHttp.prefix; + + var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; + var o; + for (var i = 0; i < prefixes.length; i++) { + try { + // try to create the objects + o = new ActiveXObject(prefixes[i] + ".XmlHttp"); + return XmlHttp.prefix = prefixes[i]; + } + catch (ex) {}; + } + + throw new Error("Could not find an installed XML parser"); +}; + + +/** + * XmlDocument factory + * @private + */ +function XmlDocument() {} + +XmlDocument.create = function (name,ns) { + name = name || 'foo'; + ns = ns || ''; + try { + var doc; + // DOM2 + if (document.implementation && document.implementation.createDocument) { + doc = document.implementation.createDocument(ns, name, null); + // some versions of Moz do not support the readyState property + // and the onreadystate event so we patch it! + if (doc.readyState == null) { + doc.readyState = 1; + doc.addEventListener("load", function () { + doc.readyState = 4; + if (typeof doc.onreadystatechange == "function") + doc.onreadystatechange(); + }, false); + } + } else if (window.ActiveXObject) { + doc = new ActiveXObject(XmlDocument.getPrefix() + ".DomDocument"); + } + + if (!doc.documentElement || doc.documentElement.tagName != name || + (doc.documentElement.namespaceURI && + doc.documentElement.namespaceURI != ns)) { + try { + if (ns != '') + doc.appendChild(doc.createElement(name)). + setAttribute('xmlns',ns); + else + doc.appendChild(doc.createElement(name)); + } catch (dex) { + doc = document.implementation.createDocument(ns,name,null); + + if (doc.documentElement == null) + doc.appendChild(doc.createElement(name)); + + // fix buggy opera 8.5x + if (ns != '' && + doc.documentElement.getAttribute('xmlns') != ns) { + doc.documentElement.setAttribute('xmlns',ns); + } + } + } + + return doc; + } + catch (ex) { alert(ex.name+": "+ex.message); } + throw new Error("Your browser does not support XmlDocument objects"); +}; + +/** + * used to find the Automation server name + * @private + */ +XmlDocument.getPrefix = function() { + if (XmlDocument.prefix) + return XmlDocument.prefix; + + var prefixes = ["MSXML2", "Microsoft", "MSXML", "MSXML3"]; + var o; + for (var i = 0; i < prefixes.length; i++) { + try { + // try to create the objects + o = new ActiveXObject(prefixes[i] + ".DomDocument"); + return XmlDocument.prefix = prefixes[i]; + } + catch (ex) {}; + } + + throw new Error("Could not find an installed XML parser"); +}; + + +// Create the loadXML method +if (typeof(Document) != 'undefined' && window.DOMParser) { + + /** + * XMLDocument did not extend the Document interface in some + * versions of Mozilla. + * @private + */ + Document.prototype.loadXML = function (s) { + + // parse the string to a new doc + var doc2 = (new DOMParser()).parseFromString(s, "text/xml"); + + // remove all initial children + while (this.hasChildNodes()) + this.removeChild(this.lastChild); + + // insert and import nodes + for (var i = 0; i < doc2.childNodes.length; i++) { + this.appendChild(this.importNode(doc2.childNodes[i], true)); + } + }; + } + +// Create xml getter for Mozilla +if (window.XMLSerializer && + window.Node && Node.prototype && Node.prototype.__defineGetter__) { + + /** + * xml getter + * + * This serializes the DOM tree to an XML String + * + * Usage: var sXml = oNode.xml + * @deprecated + * @private + */ + // XMLDocument did not extend the Document interface in some versions + // of Mozilla. Extend both! + XMLDocument.prototype.__defineGetter__("xml", function () { + return (new XMLSerializer()).serializeToString(this); + }); + /** + * xml getter + * + * This serializes the DOM tree to an XML String + * + * Usage: var sXml = oNode.xml + * @deprecated + * @private + */ + Document.prototype.__defineGetter__("xml", function () { + return (new XMLSerializer()).serializeToString(this); + }); + + /** + * xml getter + * + * This serializes the DOM tree to an XML String + * + * Usage: var sXml = oNode.xml + * @deprecated + * @private + */ + Node.prototype.__defineGetter__("xml", function () { + return (new XMLSerializer()).serializeToString(this); + }); + } diff --git a/src/com/anzsoft/public/iJab.css b/src/com/anzsoft/public/iJab.css new file mode 100644 index 0000000..ad10a08 --- /dev/null +++ b/src/com/anzsoft/public/iJab.css @@ -0,0 +1,216 @@ +/** Add css rules here for your application. */ + +html, body { + background:#3d71b8 url(wallpapers/desktop.jpg) no-repeat left top; + font: normal 12px tahoma, arial, verdana, sans-serif; + margin: 0; + padding: 0; + border: 0 none; + overflow: hidden; + height: 100%; +} + +button { + display: block; + font-size: 16pt +} + +.widePanel { + width: 100% +} + +img { + margin-top: 3px; +} + +.icon-accordion { + background-image: url(images/icons/accordion.gif) !important; +} + +.contact-icon-online +{ + background-image: url(images/icons/status-icon/contact-icon-online.gif) !important; +} + +.contact-icon-away +{ + background-image: url(images/icons/status-icon/contact-icon-away.gif) !important; +} + +.contact-icon-busy +{ + background-image: url(images/icons/status-icon/contact-icon-busy.gif) !important; +} + +.contact-icon-offline +{ + background-image: url(images/icons/status-icon/contact-icon-offline.gif) !important; +} + +.contact-group-icon +{ + background-image:url(js/ext/resources/images/default/tree/folder-open.gif); + display:none; +} + +.search-toolbar +{ + background:transparent !important; + background-image:none !important; + border:0px 0px 0px 0px !important; +} + +.search-toolbar table +{ + width:100%; +} + + +.about-pic-bar +{ + background:transparent !important; + background-image:none !important; + border:0px 0px 0px 0px !important; + margins:0px !important; +} + +.chat-icon +{ + background-image: url(images/chat.gif) !important; +} + +.login-logo +{ + margin:5px; + float:right; +} + +.status_label +{ + background-color:transparent; + color:gray; + cursor:pointer; +} + +.indicator +{ + width: 100%; + margin-bottom: 5px; +} + +.indicator-links +{ + padding: 2px 13px 2px 0px; + background: #C3D9FF; +} + +.indicator-title { + padding: 0px 0px 0px 0px; +} + +.Status-Menu-Button +{ +} + +.Status-Menu-Button .x-btn-right +{ + background: transparent none; + height: 0px; + width:0px; +} + +.Status-Menu-Button .x-btn-left +{ + background: transparent none; + height: 0px; + width:0px; +} + +.Status-Menu-Button .x-btn-center { + background: transparent none; +} + +.message_view +{ + padding:5px !important; + border:0px !important; + border-top:0px solid #ffffff !important; + border-left:0px solid #ffffff !important; + border-right:0px solid #ffffff !important; + border-bottom:0px solid #ffffff !important; + background:#FFFFFF none repeat scroll 0% 0% !important; +} + +.message_view .x-panel-body +{ + border-style:none none none none; + overflow:auto; + padding:4px 12px 4px 4px; +} + +.emoticon_menu +{ + background-color:#FFFFFF !important; +} + +.emoticon_button +{ + background-image: url(images/smiley.gif) !important; +} + +.emoticon_button .x-btn-right +{ + background: transparent none; + height: 0px; + width:0px; +} + +.emoticon_button .x-btn-left +{ + background: transparent none; + height: 0px; + width:0px; +} + +.emoticon_button .x-btn-center { + background: transparent none; +} + + +.selected-article +{ + background:#ECF5FE url(images/post-bg.gif) repeat-x scroll 0% 0%; + border:1px solid #C3DAF9; + font-family:Trebuchet MS; + font-size:12px; + margin-bottom:4px; + overflow:inherit; + padding:2px; + width:100%; + min-height:50px; +} + +.msg-nick +{ + font-family:Trebuchet MS; + font-size:12px; +} + +.msg_header +{ + border-bottom:1px solid black !important; +} + +.roster_list +{ +} + +.roster_list .x-panel-body +{ + border:0px none !important; +} + +.roster_list .x-grid3-row +{ + border-right:0px none !important; +} \ No newline at end of file diff --git a/src/com/anzsoft/public/iJab.html b/src/com/anzsoft/public/iJab.html new file mode 100644 index 0000000..9bc9ce0 --- /dev/null +++ b/src/com/anzsoft/public/iJab.html @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + iJab + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/anzsoft/public/images/Thumbs.db b/src/com/anzsoft/public/images/Thumbs.db new file mode 100644 index 0000000..758be12 Binary files /dev/null and b/src/com/anzsoft/public/images/Thumbs.db differ diff --git a/src/com/anzsoft/public/images/about.png b/src/com/anzsoft/public/images/about.png new file mode 100644 index 0000000..175ddb4 Binary files /dev/null and b/src/com/anzsoft/public/images/about.png differ diff --git a/src/com/anzsoft/public/images/accordian.gif b/src/com/anzsoft/public/images/accordian.gif new file mode 100644 index 0000000..8846b0f Binary files /dev/null and b/src/com/anzsoft/public/images/accordian.gif differ diff --git a/src/com/anzsoft/public/images/anzim.png b/src/com/anzsoft/public/images/anzim.png new file mode 100644 index 0000000..40d7ea5 Binary files /dev/null and b/src/com/anzsoft/public/images/anzim.png differ diff --git a/src/com/anzsoft/public/images/bogus.png b/src/com/anzsoft/public/images/bogus.png new file mode 100644 index 0000000..f0945cf Binary files /dev/null and b/src/com/anzsoft/public/images/bogus.png differ diff --git a/src/com/anzsoft/public/images/chat.gif b/src/com/anzsoft/public/images/chat.gif new file mode 100644 index 0000000..145817a Binary files /dev/null and b/src/com/anzsoft/public/images/chat.gif differ diff --git a/src/com/anzsoft/public/images/default_avatar.png b/src/com/anzsoft/public/images/default_avatar.png new file mode 100644 index 0000000..0e1ed21 Binary files /dev/null and b/src/com/anzsoft/public/images/default_avatar.png differ diff --git a/src/com/anzsoft/public/images/desktop.gif b/src/com/anzsoft/public/images/desktop.gif new file mode 100644 index 0000000..f305cb6 Binary files /dev/null and b/src/com/anzsoft/public/images/desktop.gif differ diff --git a/src/com/anzsoft/public/images/desktop3.jpg b/src/com/anzsoft/public/images/desktop3.jpg new file mode 100644 index 0000000..daca8bc Binary files /dev/null and b/src/com/anzsoft/public/images/desktop3.jpg differ diff --git a/src/com/anzsoft/public/images/gears.gif b/src/com/anzsoft/public/images/gears.gif new file mode 100644 index 0000000..2bf6bd7 Binary files /dev/null and b/src/com/anzsoft/public/images/gears.gif differ diff --git a/src/com/anzsoft/public/images/gears.png b/src/com/anzsoft/public/images/gears.png new file mode 100644 index 0000000..6acdc98 Binary files /dev/null and b/src/com/anzsoft/public/images/gears.png differ diff --git a/src/com/anzsoft/public/images/grid.png b/src/com/anzsoft/public/images/grid.png new file mode 100644 index 0000000..c4da495 Binary files /dev/null and b/src/com/anzsoft/public/images/grid.png differ diff --git a/src/com/anzsoft/public/images/grid32x32.gif b/src/com/anzsoft/public/images/grid32x32.gif new file mode 100644 index 0000000..c674cc8 Binary files /dev/null and b/src/com/anzsoft/public/images/grid32x32.gif differ diff --git a/src/com/anzsoft/public/images/grid48x48.gif b/src/com/anzsoft/public/images/grid48x48.gif new file mode 100644 index 0000000..c23762f Binary files /dev/null and b/src/com/anzsoft/public/images/grid48x48.gif differ diff --git a/src/com/anzsoft/public/images/grid48x48.png b/src/com/anzsoft/public/images/grid48x48.png new file mode 100644 index 0000000..7907cbf Binary files /dev/null and b/src/com/anzsoft/public/images/grid48x48.png differ diff --git a/src/com/anzsoft/public/images/hatch.gif b/src/com/anzsoft/public/images/hatch.gif new file mode 100644 index 0000000..6a044a8 Binary files /dev/null and b/src/com/anzsoft/public/images/hatch.gif differ diff --git a/src/com/anzsoft/public/images/hd-bg.gif b/src/com/anzsoft/public/images/hd-bg.gif new file mode 100644 index 0000000..f35a53f Binary files /dev/null and b/src/com/anzsoft/public/images/hd-bg.gif differ diff --git a/src/com/anzsoft/public/images/hd-tb-bg.gif b/src/com/anzsoft/public/images/hd-tb-bg.gif new file mode 100644 index 0000000..f800edb Binary files /dev/null and b/src/com/anzsoft/public/images/hd-tb-bg.gif differ diff --git a/src/com/anzsoft/public/images/icon-down-arrow.gif b/src/com/anzsoft/public/images/icon-down-arrow.gif new file mode 100644 index 0000000..535c909 Binary files /dev/null and b/src/com/anzsoft/public/images/icon-down-arrow.gif differ diff --git a/src/com/anzsoft/public/images/icon_padlock.png b/src/com/anzsoft/public/images/icon_padlock.png new file mode 100644 index 0000000..92625ff Binary files /dev/null and b/src/com/anzsoft/public/images/icon_padlock.png differ diff --git a/src/com/anzsoft/public/images/icons-bg.png b/src/com/anzsoft/public/images/icons-bg.png new file mode 100644 index 0000000..6557cbb Binary files /dev/null and b/src/com/anzsoft/public/images/icons-bg.png differ diff --git a/src/com/anzsoft/public/images/icons/Thumbs.db b/src/com/anzsoft/public/images/icons/Thumbs.db new file mode 100644 index 0000000..500b8bb Binary files /dev/null and b/src/com/anzsoft/public/images/icons/Thumbs.db differ diff --git a/src/com/anzsoft/public/images/icons/accordion.gif b/src/com/anzsoft/public/images/icons/accordion.gif new file mode 100644 index 0000000..8846b0f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/accordion.gif differ diff --git a/src/com/anzsoft/public/images/icons/add.gif b/src/com/anzsoft/public/images/icons/add.gif new file mode 100644 index 0000000..b22cd14 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/add.gif differ diff --git a/src/com/anzsoft/public/images/icons/application.png b/src/com/anzsoft/public/images/icons/application.png new file mode 100644 index 0000000..1dee9e3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application.png differ diff --git a/src/com/anzsoft/public/images/icons/application_form.png b/src/com/anzsoft/public/images/icons/application_form.png new file mode 100644 index 0000000..807b862 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_form.png differ diff --git a/src/com/anzsoft/public/images/icons/application_form_add.png b/src/com/anzsoft/public/images/icons/application_form_add.png new file mode 100644 index 0000000..28c2175 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_form_add.png differ diff --git a/src/com/anzsoft/public/images/icons/application_form_delete.png b/src/com/anzsoft/public/images/icons/application_form_delete.png new file mode 100644 index 0000000..cd305ec Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_form_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/application_form_edit.png b/src/com/anzsoft/public/images/icons/application_form_edit.png new file mode 100644 index 0000000..af486c9 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_form_edit.png differ diff --git a/src/com/anzsoft/public/images/icons/application_form_magnify.png b/src/com/anzsoft/public/images/icons/application_form_magnify.png new file mode 100644 index 0000000..7b7fbd1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_form_magnify.png differ diff --git a/src/com/anzsoft/public/images/icons/application_home.png b/src/com/anzsoft/public/images/icons/application_home.png new file mode 100644 index 0000000..b60d0c8 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_home.png differ diff --git a/src/com/anzsoft/public/images/icons/application_put.png b/src/com/anzsoft/public/images/icons/application_put.png new file mode 100644 index 0000000..c30cf59 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_put.png differ diff --git a/src/com/anzsoft/public/images/icons/application_side_boxes.png b/src/com/anzsoft/public/images/icons/application_side_boxes.png new file mode 100644 index 0000000..efbf3c4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_side_boxes.png differ diff --git a/src/com/anzsoft/public/images/icons/application_side_contract.png b/src/com/anzsoft/public/images/icons/application_side_contract.png new file mode 100644 index 0000000..3585f94 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_side_contract.png differ diff --git a/src/com/anzsoft/public/images/icons/application_side_expand.png b/src/com/anzsoft/public/images/icons/application_side_expand.png new file mode 100644 index 0000000..030cf7c Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_side_expand.png differ diff --git a/src/com/anzsoft/public/images/icons/application_side_list.png b/src/com/anzsoft/public/images/icons/application_side_list.png new file mode 100644 index 0000000..248eaf1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_side_list.png differ diff --git a/src/com/anzsoft/public/images/icons/application_side_tree.png b/src/com/anzsoft/public/images/icons/application_side_tree.png new file mode 100644 index 0000000..f04a52b Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_side_tree.png differ diff --git a/src/com/anzsoft/public/images/icons/application_split.png b/src/com/anzsoft/public/images/icons/application_split.png new file mode 100644 index 0000000..a91c78a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_split.png differ diff --git a/src/com/anzsoft/public/images/icons/application_tile_horizontal.png b/src/com/anzsoft/public/images/icons/application_tile_horizontal.png new file mode 100644 index 0000000..8a1191c Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_tile_horizontal.png differ diff --git a/src/com/anzsoft/public/images/icons/application_tile_vertical.png b/src/com/anzsoft/public/images/icons/application_tile_vertical.png new file mode 100644 index 0000000..1d40383 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_tile_vertical.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_columns.png b/src/com/anzsoft/public/images/icons/application_view_columns.png new file mode 100644 index 0000000..dc2e9d5 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_columns.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_detail.png b/src/com/anzsoft/public/images/icons/application_view_detail.png new file mode 100644 index 0000000..aba044b Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_detail.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_gallery.png b/src/com/anzsoft/public/images/icons/application_view_gallery.png new file mode 100644 index 0000000..851950d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_gallery.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_icons.png b/src/com/anzsoft/public/images/icons/application_view_icons.png new file mode 100644 index 0000000..6a93cda Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_icons.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_list.png b/src/com/anzsoft/public/images/icons/application_view_list.png new file mode 100644 index 0000000..acc30b8 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_list.png differ diff --git a/src/com/anzsoft/public/images/icons/application_view_tile.png b/src/com/anzsoft/public/images/icons/application_view_tile.png new file mode 100644 index 0000000..3bc0bd3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_view_tile.png differ diff --git a/src/com/anzsoft/public/images/icons/application_xp.png b/src/com/anzsoft/public/images/icons/application_xp.png new file mode 100644 index 0000000..d22860a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_xp.png differ diff --git a/src/com/anzsoft/public/images/icons/application_xp_terminal.png b/src/com/anzsoft/public/images/icons/application_xp_terminal.png new file mode 100644 index 0000000..c28dd63 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/application_xp_terminal.png differ diff --git a/src/com/anzsoft/public/images/icons/book_open.png b/src/com/anzsoft/public/images/icons/book_open.png new file mode 100644 index 0000000..7d863f9 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/book_open.png differ diff --git a/src/com/anzsoft/public/images/icons/calendar.gif b/src/com/anzsoft/public/images/icons/calendar.gif new file mode 100644 index 0000000..133cf23 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/calendar.gif differ diff --git a/src/com/anzsoft/public/images/icons/chart.png b/src/com/anzsoft/public/images/icons/chart.png new file mode 100644 index 0000000..38c977a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart.png differ diff --git a/src/com/anzsoft/public/images/icons/chart_line.png b/src/com/anzsoft/public/images/icons/chart_line.png new file mode 100644 index 0000000..85020f3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart_line.png differ diff --git a/src/com/anzsoft/public/images/icons/chart_organisation.png b/src/com/anzsoft/public/images/icons/chart_organisation.png new file mode 100644 index 0000000..c32d25c Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart_organisation.png differ diff --git a/src/com/anzsoft/public/images/icons/chart_organisation_add.png b/src/com/anzsoft/public/images/icons/chart_organisation_add.png new file mode 100644 index 0000000..f0dba4a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart_organisation_add.png differ diff --git a/src/com/anzsoft/public/images/icons/chart_organisation_delete.png b/src/com/anzsoft/public/images/icons/chart_organisation_delete.png new file mode 100644 index 0000000..7dc8dca Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart_organisation_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/chart_pie.png b/src/com/anzsoft/public/images/icons/chart_pie.png new file mode 100644 index 0000000..fe00fa0 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/chart_pie.png differ diff --git a/src/com/anzsoft/public/images/icons/contact-add.png b/src/com/anzsoft/public/images/icons/contact-add.png new file mode 100644 index 0000000..2a68453 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/contact-add.png differ diff --git a/src/com/anzsoft/public/images/icons/copy.png b/src/com/anzsoft/public/images/icons/copy.png new file mode 100644 index 0000000..195dc6d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/copy.png differ diff --git a/src/com/anzsoft/public/images/icons/css.png b/src/com/anzsoft/public/images/icons/css.png new file mode 100644 index 0000000..23f3101 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/css.png differ diff --git a/src/com/anzsoft/public/images/icons/cut.png b/src/com/anzsoft/public/images/icons/cut.png new file mode 100644 index 0000000..f215d6f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/cut.png differ diff --git a/src/com/anzsoft/public/images/icons/date-add.png b/src/com/anzsoft/public/images/icons/date-add.png new file mode 100644 index 0000000..6a7ae02 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/date-add.png differ diff --git a/src/com/anzsoft/public/images/icons/date_add.png b/src/com/anzsoft/public/images/icons/date_add.png new file mode 100644 index 0000000..6a7ae02 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/date_add.png differ diff --git a/src/com/anzsoft/public/images/icons/delete.gif b/src/com/anzsoft/public/images/icons/delete.gif new file mode 100644 index 0000000..0d37c9b Binary files /dev/null and b/src/com/anzsoft/public/images/icons/delete.gif differ diff --git a/src/com/anzsoft/public/images/icons/document.gif b/src/com/anzsoft/public/images/icons/document.gif new file mode 100644 index 0000000..73ffd44 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/document.gif differ diff --git a/src/com/anzsoft/public/images/icons/document.png b/src/com/anzsoft/public/images/icons/document.png new file mode 100644 index 0000000..da793cc Binary files /dev/null and b/src/com/anzsoft/public/images/icons/document.png differ diff --git a/src/com/anzsoft/public/images/icons/email-add.png b/src/com/anzsoft/public/images/icons/email-add.png new file mode 100644 index 0000000..6c93368 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email-add.png differ diff --git a/src/com/anzsoft/public/images/icons/email.png b/src/com/anzsoft/public/images/icons/email.png new file mode 100644 index 0000000..7348aed Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email.png differ diff --git a/src/com/anzsoft/public/images/icons/email_add.gif b/src/com/anzsoft/public/images/icons/email_add.gif new file mode 100644 index 0000000..205514f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_add.gif differ diff --git a/src/com/anzsoft/public/images/icons/email_add.png b/src/com/anzsoft/public/images/icons/email_add.png new file mode 100644 index 0000000..6c93368 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_add.png differ diff --git a/src/com/anzsoft/public/images/icons/email_attach.png b/src/com/anzsoft/public/images/icons/email_attach.png new file mode 100644 index 0000000..1f99485 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_attach.png differ diff --git a/src/com/anzsoft/public/images/icons/email_delete.png b/src/com/anzsoft/public/images/icons/email_delete.png new file mode 100644 index 0000000..a9932b1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/email_edit.png b/src/com/anzsoft/public/images/icons/email_edit.png new file mode 100644 index 0000000..244f04a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_edit.png differ diff --git a/src/com/anzsoft/public/images/icons/email_go.png b/src/com/anzsoft/public/images/icons/email_go.png new file mode 100644 index 0000000..4a6c5d3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_go.png differ diff --git a/src/com/anzsoft/public/images/icons/email_link.png b/src/com/anzsoft/public/images/icons/email_link.png new file mode 100644 index 0000000..2c49f78 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_link.png differ diff --git a/src/com/anzsoft/public/images/icons/email_open.png b/src/com/anzsoft/public/images/icons/email_open.png new file mode 100644 index 0000000..7b6f981 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_open.png differ diff --git a/src/com/anzsoft/public/images/icons/email_open_image.png b/src/com/anzsoft/public/images/icons/email_open_image.png new file mode 100644 index 0000000..e588e2f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/email_open_image.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/SILK.txt b/src/com/anzsoft/public/images/icons/fam/SILK.txt new file mode 100644 index 0000000..5584ada --- /dev/null +++ b/src/com/anzsoft/public/images/icons/fam/SILK.txt @@ -0,0 +1,3 @@ +The icons in this folder are direct gif conversions of the fam fam fam silk icons. + +Please see http://www.famfamfam.com/lab/icons/silk/ for more details. \ No newline at end of file diff --git a/src/com/anzsoft/public/images/icons/fam/Thumbs.db b/src/com/anzsoft/public/images/icons/fam/Thumbs.db new file mode 100644 index 0000000..0ea0478 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/Thumbs.db differ diff --git a/src/com/anzsoft/public/images/icons/fam/add.gif b/src/com/anzsoft/public/images/icons/fam/add.gif new file mode 100644 index 0000000..9319525 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/add.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/application_go.png b/src/com/anzsoft/public/images/icons/fam/application_go.png new file mode 100644 index 0000000..5cc2b0d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/application_go.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/application_view_list.png b/src/com/anzsoft/public/images/icons/fam/application_view_list.png new file mode 100644 index 0000000..acc30b8 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/application_view_list.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/cog.png b/src/com/anzsoft/public/images/icons/fam/cog.png new file mode 100644 index 0000000..67de2c6 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/cog.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/cog_edit.png b/src/com/anzsoft/public/images/icons/fam/cog_edit.png new file mode 100644 index 0000000..47b75a4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/cog_edit.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/connect.gif b/src/com/anzsoft/public/images/icons/fam/connect.gif new file mode 100644 index 0000000..1aa16ab Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/connect.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/connect.png b/src/com/anzsoft/public/images/icons/fam/connect.png new file mode 100644 index 0000000..024138e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/connect.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/cross.gif b/src/com/anzsoft/public/images/icons/fam/cross.gif new file mode 100644 index 0000000..2eb2865 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/cross.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/delete.gif b/src/com/anzsoft/public/images/icons/fam/delete.gif new file mode 100644 index 0000000..5e2a3b1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/delete.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/feed_add.png b/src/com/anzsoft/public/images/icons/fam/feed_add.png new file mode 100644 index 0000000..e77d46e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/feed_add.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/feed_delete.png b/src/com/anzsoft/public/images/icons/fam/feed_delete.png new file mode 100644 index 0000000..5e332b4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/feed_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/feed_error.png b/src/com/anzsoft/public/images/icons/fam/feed_error.png new file mode 100644 index 0000000..c0a801c Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/feed_error.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/folder_go.png b/src/com/anzsoft/public/images/icons/fam/folder_go.png new file mode 100644 index 0000000..34a736f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/folder_go.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/folder_wrench.png b/src/com/anzsoft/public/images/icons/fam/folder_wrench.png new file mode 100644 index 0000000..ea3404e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/folder_wrench.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/grid.png b/src/com/anzsoft/public/images/icons/fam/grid.png new file mode 100644 index 0000000..c4da495 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/grid.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/plugin.gif b/src/com/anzsoft/public/images/icons/fam/plugin.gif new file mode 100644 index 0000000..209c121 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/plugin.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/plugin_add.gif b/src/com/anzsoft/public/images/icons/fam/plugin_add.gif new file mode 100644 index 0000000..5c95312 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/plugin_add.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/rss_go.png b/src/com/anzsoft/public/images/icons/fam/rss_go.png new file mode 100644 index 0000000..43a86bf Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/rss_go.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/table_refresh.png b/src/com/anzsoft/public/images/icons/fam/table_refresh.png new file mode 100644 index 0000000..ab92010 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/table_refresh.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user.gif b/src/com/anzsoft/public/images/icons/fam/user.gif new file mode 100644 index 0000000..d75bd1e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user.png b/src/com/anzsoft/public/images/icons/fam/user.png new file mode 100644 index 0000000..79f35cc Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_add.gif b/src/com/anzsoft/public/images/icons/fam/user_add.gif new file mode 100644 index 0000000..c822319 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_add.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_add.png b/src/com/anzsoft/public/images/icons/fam/user_add.png new file mode 100644 index 0000000..deae99b Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_add.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_comment.png b/src/com/anzsoft/public/images/icons/fam/user_comment.png new file mode 100644 index 0000000..e54ebeb Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_comment.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_delete.gif b/src/com/anzsoft/public/images/icons/fam/user_delete.gif new file mode 100644 index 0000000..2769aa2 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_delete.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_delete.png b/src/com/anzsoft/public/images/icons/fam/user_delete.png new file mode 100644 index 0000000..acbb563 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_edit.png b/src/com/anzsoft/public/images/icons/fam/user_edit.png new file mode 100644 index 0000000..c1974cd Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_edit.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_female.gif b/src/com/anzsoft/public/images/icons/fam/user_female.gif new file mode 100644 index 0000000..d2c913a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_female.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_female.png b/src/com/anzsoft/public/images/icons/fam/user_female.png new file mode 100644 index 0000000..7c71de0 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_female.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_gray.png b/src/com/anzsoft/public/images/icons/fam/user_gray.png new file mode 100644 index 0000000..8fd539e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_gray.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_green.gif b/src/com/anzsoft/public/images/icons/fam/user_green.gif new file mode 100644 index 0000000..6644957 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_green.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_green.png b/src/com/anzsoft/public/images/icons/fam/user_green.png new file mode 100644 index 0000000..30383c2 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_green.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_orange.png b/src/com/anzsoft/public/images/icons/fam/user_orange.png new file mode 100644 index 0000000..b818127 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_orange.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_red.png b/src/com/anzsoft/public/images/icons/fam/user_red.png new file mode 100644 index 0000000..c6f66e8 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_red.png differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_suit.gif b/src/com/anzsoft/public/images/icons/fam/user_suit.gif new file mode 100644 index 0000000..3c04d2d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_suit.gif differ diff --git a/src/com/anzsoft/public/images/icons/fam/user_suit.png b/src/com/anzsoft/public/images/icons/fam/user_suit.png new file mode 100644 index 0000000..b3454e1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/fam/user_suit.png differ diff --git a/src/com/anzsoft/public/images/icons/feed.gif b/src/com/anzsoft/public/images/icons/feed.gif new file mode 100644 index 0000000..b2d1421 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/feed.gif differ diff --git a/src/com/anzsoft/public/images/icons/feed.png b/src/com/anzsoft/public/images/icons/feed.png new file mode 100644 index 0000000..315c4f4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/feed.png differ diff --git a/src/com/anzsoft/public/images/icons/funnel.png b/src/com/anzsoft/public/images/icons/funnel.png new file mode 100644 index 0000000..149ae78 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/funnel.png differ diff --git a/src/com/anzsoft/public/images/icons/funnel_delete.png b/src/com/anzsoft/public/images/icons/funnel_delete.png new file mode 100644 index 0000000..fff04c7 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/funnel_delete.png differ diff --git a/src/com/anzsoft/public/images/icons/html.png b/src/com/anzsoft/public/images/icons/html.png new file mode 100644 index 0000000..55d1072 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/html.png differ diff --git a/src/com/anzsoft/public/images/icons/icon-close.gif b/src/com/anzsoft/public/images/icons/icon-close.gif new file mode 100644 index 0000000..cc90527 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/icon-close.gif differ diff --git a/src/com/anzsoft/public/images/icons/information-white.gif b/src/com/anzsoft/public/images/icons/information-white.gif new file mode 100644 index 0000000..b2b2fad Binary files /dev/null and b/src/com/anzsoft/public/images/icons/information-white.gif differ diff --git a/src/com/anzsoft/public/images/icons/information.png b/src/com/anzsoft/public/images/icons/information.png new file mode 100644 index 0000000..12cd1ae Binary files /dev/null and b/src/com/anzsoft/public/images/icons/information.png differ diff --git a/src/com/anzsoft/public/images/icons/layout.png b/src/com/anzsoft/public/images/icons/layout.png new file mode 100644 index 0000000..ea086b0 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/layout.png differ diff --git a/src/com/anzsoft/public/images/icons/layout_content.png b/src/com/anzsoft/public/images/icons/layout_content.png new file mode 100644 index 0000000..b4aaad9 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/layout_content.png differ diff --git a/src/com/anzsoft/public/images/icons/layout_header.png b/src/com/anzsoft/public/images/icons/layout_header.png new file mode 100644 index 0000000..c6ea7f2 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/layout_header.png differ diff --git a/src/com/anzsoft/public/images/icons/link.png b/src/com/anzsoft/public/images/icons/link.png new file mode 100644 index 0000000..25eacb7 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/link.png differ diff --git a/src/com/anzsoft/public/images/icons/list-items.gif b/src/com/anzsoft/public/images/icons/list-items.gif new file mode 100644 index 0000000..ecbdfc9 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/list-items.gif differ diff --git a/src/com/anzsoft/public/images/icons/list.gif b/src/com/anzsoft/public/images/icons/list.gif new file mode 100644 index 0000000..8490768 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/list.gif differ diff --git a/src/com/anzsoft/public/images/icons/lock.png b/src/com/anzsoft/public/images/icons/lock.png new file mode 100644 index 0000000..2ebc4f6 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/lock.png differ diff --git a/src/com/anzsoft/public/images/icons/menu-show.gif b/src/com/anzsoft/public/images/icons/menu-show.gif new file mode 100644 index 0000000..ebfefff Binary files /dev/null and b/src/com/anzsoft/public/images/icons/menu-show.gif differ diff --git a/src/com/anzsoft/public/images/icons/music.png b/src/com/anzsoft/public/images/icons/music.png new file mode 100644 index 0000000..691b95f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/music.png differ diff --git a/src/com/anzsoft/public/images/icons/page.gif b/src/com/anzsoft/public/images/icons/page.gif new file mode 100644 index 0000000..b8c27e3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page.gif differ diff --git a/src/com/anzsoft/public/images/icons/page.png b/src/com/anzsoft/public/images/icons/page.png new file mode 100644 index 0000000..03ddd79 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page.png differ diff --git a/src/com/anzsoft/public/images/icons/page_code.png b/src/com/anzsoft/public/images/icons/page_code.png new file mode 100644 index 0000000..f7ea904 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_code.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white.png b/src/com/anzsoft/public/images/icons/page_white.png new file mode 100644 index 0000000..8b8b1ca Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_acrobat.png b/src/com/anzsoft/public/images/icons/page_white_acrobat.png new file mode 100644 index 0000000..8f8095e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_acrobat.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_actionscript.png b/src/com/anzsoft/public/images/icons/page_white_actionscript.png new file mode 100644 index 0000000..159b240 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_actionscript.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_code.png b/src/com/anzsoft/public/images/icons/page_white_code.png new file mode 100644 index 0000000..0c76bd1 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_code.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_cplusplus.png b/src/com/anzsoft/public/images/icons/page_white_cplusplus.png new file mode 100644 index 0000000..a87cf84 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_cplusplus.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_csharp.png b/src/com/anzsoft/public/images/icons/page_white_csharp.png new file mode 100644 index 0000000..ffb8fc9 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_csharp.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_cup.png b/src/com/anzsoft/public/images/icons/page_white_cup.png new file mode 100644 index 0000000..0a7d6f4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_cup.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_excel.png b/src/com/anzsoft/public/images/icons/page_white_excel.png new file mode 100644 index 0000000..b977d7e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_excel.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_find.png b/src/com/anzsoft/public/images/icons/page_white_find.png new file mode 100644 index 0000000..5818436 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_find.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_flash.png b/src/com/anzsoft/public/images/icons/page_white_flash.png new file mode 100644 index 0000000..5769120 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_flash.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_freehand.png b/src/com/anzsoft/public/images/icons/page_white_freehand.png new file mode 100644 index 0000000..8d719df Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_freehand.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_office.png b/src/com/anzsoft/public/images/icons/page_white_office.png new file mode 100644 index 0000000..a65bcb3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_office.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_php.png b/src/com/anzsoft/public/images/icons/page_white_php.png new file mode 100644 index 0000000..7868a25 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_php.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_tux.png b/src/com/anzsoft/public/images/icons/page_white_tux.png new file mode 100644 index 0000000..52699bf Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_tux.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_visualstudio.png b/src/com/anzsoft/public/images/icons/page_white_visualstudio.png new file mode 100644 index 0000000..a0a433d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_visualstudio.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_word.png b/src/com/anzsoft/public/images/icons/page_white_word.png new file mode 100644 index 0000000..ae8ecbf Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_word.png differ diff --git a/src/com/anzsoft/public/images/icons/page_white_zip.png b/src/com/anzsoft/public/images/icons/page_white_zip.png new file mode 100644 index 0000000..fd4bbcc Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_white_zip.png differ diff --git a/src/com/anzsoft/public/images/icons/page_word.png b/src/com/anzsoft/public/images/icons/page_word.png new file mode 100644 index 0000000..834cdfa Binary files /dev/null and b/src/com/anzsoft/public/images/icons/page_word.png differ diff --git a/src/com/anzsoft/public/images/icons/paste.png b/src/com/anzsoft/public/images/icons/paste.png new file mode 100644 index 0000000..c0490eb Binary files /dev/null and b/src/com/anzsoft/public/images/icons/paste.png differ diff --git a/src/com/anzsoft/public/images/icons/plugin.png b/src/com/anzsoft/public/images/icons/plugin.png new file mode 100644 index 0000000..6187b15 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/plugin.png differ diff --git a/src/com/anzsoft/public/images/icons/plugin_disabled.png b/src/com/anzsoft/public/images/icons/plugin_disabled.png new file mode 100644 index 0000000..f4f6be5 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/plugin_disabled.png differ diff --git a/src/com/anzsoft/public/images/icons/printer.png b/src/com/anzsoft/public/images/icons/printer.png new file mode 100644 index 0000000..a350d18 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/printer.png differ diff --git a/src/com/anzsoft/public/images/icons/save-all.png b/src/com/anzsoft/public/images/icons/save-all.png new file mode 100644 index 0000000..fc5a52f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/save-all.png differ diff --git a/src/com/anzsoft/public/images/icons/save.png b/src/com/anzsoft/public/images/icons/save.png new file mode 100644 index 0000000..99d532e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/save.png differ diff --git a/src/com/anzsoft/public/images/icons/script.png b/src/com/anzsoft/public/images/icons/script.png new file mode 100644 index 0000000..0f9ed4d Binary files /dev/null and b/src/com/anzsoft/public/images/icons/script.png differ diff --git a/src/com/anzsoft/public/images/icons/script_code.png b/src/com/anzsoft/public/images/icons/script_code.png new file mode 100644 index 0000000..63fe6ce Binary files /dev/null and b/src/com/anzsoft/public/images/icons/script_code.png differ diff --git a/src/com/anzsoft/public/images/icons/shell.gif b/src/com/anzsoft/public/images/icons/shell.gif new file mode 100644 index 0000000..8044131 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/shell.gif differ diff --git a/src/com/anzsoft/public/images/icons/side-nav.png b/src/com/anzsoft/public/images/icons/side-nav.png new file mode 100644 index 0000000..efbf3c4 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/side-nav.png differ diff --git a/src/com/anzsoft/public/images/icons/status-icon/Thumbs.db b/src/com/anzsoft/public/images/icons/status-icon/Thumbs.db new file mode 100644 index 0000000..9460f12 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/status-icon/Thumbs.db differ diff --git a/src/com/anzsoft/public/images/icons/status-icon/contact-icon-away.gif b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-away.gif new file mode 100644 index 0000000..af37e2a Binary files /dev/null and b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-away.gif differ diff --git a/src/com/anzsoft/public/images/icons/status-icon/contact-icon-busy.gif b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-busy.gif new file mode 100644 index 0000000..76f62f2 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-busy.gif differ diff --git a/src/com/anzsoft/public/images/icons/status-icon/contact-icon-offline.gif b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-offline.gif new file mode 100644 index 0000000..654adc6 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-offline.gif differ diff --git a/src/com/anzsoft/public/images/icons/status-icon/contact-icon-online.gif b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-online.gif new file mode 100644 index 0000000..5c8613e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/status-icon/contact-icon-online.gif differ diff --git a/src/com/anzsoft/public/images/icons/table.png b/src/com/anzsoft/public/images/icons/table.png new file mode 100644 index 0000000..dc2e9d5 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/table.png differ diff --git a/src/com/anzsoft/public/images/icons/table_multiple.png b/src/com/anzsoft/public/images/icons/table_multiple.png new file mode 100644 index 0000000..d76448e Binary files /dev/null and b/src/com/anzsoft/public/images/icons/table_multiple.png differ diff --git a/src/com/anzsoft/public/images/icons/tabs.gif b/src/com/anzsoft/public/images/icons/tabs.gif new file mode 100644 index 0000000..759de0f Binary files /dev/null and b/src/com/anzsoft/public/images/icons/tabs.gif differ diff --git a/src/com/anzsoft/public/images/icons/tag.png b/src/com/anzsoft/public/images/icons/tag.png new file mode 100644 index 0000000..e093032 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/tag.png differ diff --git a/src/com/anzsoft/public/images/icons/text.gif b/src/com/anzsoft/public/images/icons/text.gif new file mode 100644 index 0000000..c549fb0 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/text.gif differ diff --git a/src/com/anzsoft/public/images/icons/text.png b/src/com/anzsoft/public/images/icons/text.png new file mode 100644 index 0000000..6300e53 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/text.png differ diff --git a/src/com/anzsoft/public/images/icons/tick.png b/src/com/anzsoft/public/images/icons/tick.png new file mode 100644 index 0000000..a9925a0 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/tick.png differ diff --git a/src/com/anzsoft/public/images/icons/vcard.png b/src/com/anzsoft/public/images/icons/vcard.png new file mode 100644 index 0000000..c02f315 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/vcard.png differ diff --git a/src/com/anzsoft/public/images/icons/vcard_add.png b/src/com/anzsoft/public/images/icons/vcard_add.png new file mode 100644 index 0000000..2a68453 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/vcard_add.png differ diff --git a/src/com/anzsoft/public/images/icons/window.png b/src/com/anzsoft/public/images/icons/window.png new file mode 100644 index 0000000..9a5ddd3 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/window.png differ diff --git a/src/com/anzsoft/public/images/icons/xhtml.png b/src/com/anzsoft/public/images/icons/xhtml.png new file mode 100644 index 0000000..da5dbf2 Binary files /dev/null and b/src/com/anzsoft/public/images/icons/xhtml.png differ diff --git a/src/com/anzsoft/public/images/im32x32.gif b/src/com/anzsoft/public/images/im32x32.gif new file mode 100644 index 0000000..2d7704f Binary files /dev/null and b/src/com/anzsoft/public/images/im32x32.gif differ diff --git a/src/com/anzsoft/public/images/im48x48.gif b/src/com/anzsoft/public/images/im48x48.gif new file mode 100644 index 0000000..ca86cc2 Binary files /dev/null and b/src/com/anzsoft/public/images/im48x48.gif differ diff --git a/src/com/anzsoft/public/images/im48x48.png b/src/com/anzsoft/public/images/im48x48.png new file mode 100644 index 0000000..3da7410 Binary files /dev/null and b/src/com/anzsoft/public/images/im48x48.png differ diff --git a/src/com/anzsoft/public/images/launcher-bg.gif b/src/com/anzsoft/public/images/launcher-bg.gif new file mode 100644 index 0000000..c7cfd83 Binary files /dev/null and b/src/com/anzsoft/public/images/launcher-bg.gif differ diff --git a/src/com/anzsoft/public/images/launcher-btn.gif b/src/com/anzsoft/public/images/launcher-btn.gif new file mode 100644 index 0000000..a9a72d7 Binary files /dev/null and b/src/com/anzsoft/public/images/launcher-btn.gif differ diff --git a/src/com/anzsoft/public/images/logout.gif b/src/com/anzsoft/public/images/logout.gif new file mode 100644 index 0000000..a4f3738 Binary files /dev/null and b/src/com/anzsoft/public/images/logout.gif differ diff --git a/src/com/anzsoft/public/images/logout.png b/src/com/anzsoft/public/images/logout.png new file mode 100644 index 0000000..1fcb386 Binary files /dev/null and b/src/com/anzsoft/public/images/logout.png differ diff --git a/src/com/anzsoft/public/images/member.gif b/src/com/anzsoft/public/images/member.gif new file mode 100644 index 0000000..216c839 Binary files /dev/null and b/src/com/anzsoft/public/images/member.gif differ diff --git a/src/com/anzsoft/public/images/member.png b/src/com/anzsoft/public/images/member.png new file mode 100644 index 0000000..0f3657f Binary files /dev/null and b/src/com/anzsoft/public/images/member.png differ diff --git a/src/com/anzsoft/public/images/post-bg.gif b/src/com/anzsoft/public/images/post-bg.gif new file mode 100644 index 0000000..362d65b Binary files /dev/null and b/src/com/anzsoft/public/images/post-bg.gif differ diff --git a/src/com/anzsoft/public/images/powered.gif b/src/com/anzsoft/public/images/powered.gif new file mode 100644 index 0000000..8ce74b8 Binary files /dev/null and b/src/com/anzsoft/public/images/powered.gif differ diff --git a/src/com/anzsoft/public/images/powered.png b/src/com/anzsoft/public/images/powered.png new file mode 100644 index 0000000..5b2a0b8 Binary files /dev/null and b/src/com/anzsoft/public/images/powered.png differ diff --git a/src/com/anzsoft/public/images/s.gif b/src/com/anzsoft/public/images/s.gif new file mode 100644 index 0000000..1d11fa9 Binary files /dev/null and b/src/com/anzsoft/public/images/s.gif differ diff --git a/src/com/anzsoft/public/images/smiley.gif b/src/com/anzsoft/public/images/smiley.gif new file mode 100644 index 0000000..53d0925 Binary files /dev/null and b/src/com/anzsoft/public/images/smiley.gif differ diff --git a/src/com/anzsoft/public/images/tabs.gif b/src/com/anzsoft/public/images/tabs.gif new file mode 100644 index 0000000..759de0f Binary files /dev/null and b/src/com/anzsoft/public/images/tabs.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/Thumbs.db b/src/com/anzsoft/public/images/taskbar/black/Thumbs.db new file mode 100644 index 0000000..5d7561e Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/Thumbs.db differ diff --git a/src/com/anzsoft/public/images/taskbar/black/item-over.gif b/src/com/anzsoft/public/images/taskbar/black/item-over.gif new file mode 100644 index 0000000..26c1fc2 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/item-over.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/scroll-left.gif b/src/com/anzsoft/public/images/taskbar/black/scroll-left.gif new file mode 100644 index 0000000..94fea48 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/scroll-left.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/scroll-right.gif b/src/com/anzsoft/public/images/taskbar/black/scroll-right.gif new file mode 100644 index 0000000..94b5669 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/scroll-right.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/start-menu-left-corners.png b/src/com/anzsoft/public/images/taskbar/black/start-menu-left-corners.png new file mode 100644 index 0000000..d6e5196 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/start-menu-left-corners.png differ diff --git a/src/com/anzsoft/public/images/taskbar/black/start-menu-left-right.png b/src/com/anzsoft/public/images/taskbar/black/start-menu-left-right.png new file mode 100644 index 0000000..a577d1b Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/start-menu-left-right.png differ diff --git a/src/com/anzsoft/public/images/taskbar/black/start-menu-right-corners.png b/src/com/anzsoft/public/images/taskbar/black/start-menu-right-corners.png new file mode 100644 index 0000000..b683301 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/start-menu-right-corners.png differ diff --git a/src/com/anzsoft/public/images/taskbar/black/start-menu-right.png b/src/com/anzsoft/public/images/taskbar/black/start-menu-right.png new file mode 100644 index 0000000..e5fa2b8 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/start-menu-right.png differ diff --git a/src/com/anzsoft/public/images/taskbar/black/start-menu-top-bottom.png b/src/com/anzsoft/public/images/taskbar/black/start-menu-top-bottom.png new file mode 100644 index 0000000..fbea3cb Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/start-menu-top-bottom.png differ diff --git a/src/com/anzsoft/public/images/taskbar/black/startbutton-icon.gif b/src/com/anzsoft/public/images/taskbar/black/startbutton-icon.gif new file mode 100644 index 0000000..8dcd2d1 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/startbutton-icon.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/startbutton.gif b/src/com/anzsoft/public/images/taskbar/black/startbutton.gif new file mode 100644 index 0000000..683313e Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/startbutton.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/taskbar-split-h.gif b/src/com/anzsoft/public/images/taskbar/black/taskbar-split-h.gif new file mode 100644 index 0000000..13564ad Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/taskbar-split-h.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/taskbar-start-panel-bg.gif b/src/com/anzsoft/public/images/taskbar/black/taskbar-start-panel-bg.gif new file mode 100644 index 0000000..9794880 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/taskbar-start-panel-bg.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/taskbutton.gif b/src/com/anzsoft/public/images/taskbar/black/taskbutton.gif new file mode 100644 index 0000000..df13974 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/taskbutton.gif differ diff --git a/src/com/anzsoft/public/images/taskbar/black/taskbuttons-panel-bg.gif b/src/com/anzsoft/public/images/taskbar/black/taskbuttons-panel-bg.gif new file mode 100644 index 0000000..0865c45 Binary files /dev/null and b/src/com/anzsoft/public/images/taskbar/black/taskbuttons-panel-bg.gif differ diff --git a/src/com/anzsoft/public/images/winbar-bg.gif b/src/com/anzsoft/public/images/winbar-bg.gif new file mode 100644 index 0000000..45295a6 Binary files /dev/null and b/src/com/anzsoft/public/images/winbar-bg.gif differ diff --git a/src/com/anzsoft/public/images/winbar-btn.gif b/src/com/anzsoft/public/images/winbar-btn.gif new file mode 100644 index 0000000..2c8c024 Binary files /dev/null and b/src/com/anzsoft/public/images/winbar-btn.gif differ diff --git a/src/com/anzsoft/public/images/windows-bg.gif b/src/com/anzsoft/public/images/windows-bg.gif new file mode 100644 index 0000000..396471e Binary files /dev/null and b/src/com/anzsoft/public/images/windows-bg.gif differ diff --git a/src/com/anzsoft/public/js/ext/adapter/ext/ext-base.js b/src/com/anzsoft/public/js/ext/adapter/ext/ext-base.js new file mode 100644 index 0000000..b68f63d --- /dev/null +++ b/src/com/anzsoft/public/js/ext/adapter/ext/ext-base.js @@ -0,0 +1,10 @@ +/* + * Ext JS Library 2.2 + * Copyright(c) 2006-2008, Ext JS, LLC. + * licensing@extjs.com + * + * http://extjs.com/license + */ + +Ext={version:"2.2"};window["undefined"]=window["undefined"];Ext.apply=function(C,D,B){if(B){Ext.apply(C,B)}if(C&&D&&typeof D=="object"){for(var A in D){C[A]=D[A]}}return C};(function(){var idSeed=0;var ua=navigator.userAgent.toLowerCase();var isStrict=document.compatMode=="CSS1Compat",isOpera=ua.indexOf("opera")>-1,isSafari=(/webkit|khtml/).test(ua),isSafari3=isSafari&&ua.indexOf("webkit/5")!=-1,isIE=!isOpera&&ua.indexOf("msie")>-1,isIE7=!isOpera&&ua.indexOf("msie 7")>-1,isGecko=!isSafari&&ua.indexOf("gecko")>-1,isGecko3=!isSafari&&ua.indexOf("rv:1.9")>-1,isBorderBox=isIE&&!isStrict,isWindows=(ua.indexOf("windows")!=-1||ua.indexOf("win32")!=-1),isMac=(ua.indexOf("macintosh")!=-1||ua.indexOf("mac os x")!=-1),isAir=(ua.indexOf("adobeair")!=-1),isLinux=(ua.indexOf("linux")!=-1),isSecure=window.location.href.toLowerCase().indexOf("https")===0;if(isIE&&!isIE7){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}Ext.apply(Ext,{isStrict:isStrict,isSecure:isSecure,isReady:false,enableGarbageCollector:true,enableListenerCollection:false,SSL_SECURE_URL:"javascript:false",BLANK_IMAGE_URL:"http:/"+"/extjs.com/s.gif",emptyFn:function(){},applyIf:function(o,c){if(o&&c){for(var p in c){if(typeof o[p]=="undefined"){o[p]=c[p]}}}return o},addBehaviors:function(o){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(o)});return }var cache={};for(var b in o){var parts=b.split("@");if(parts[1]){var s=parts[0];if(!cache[s]){cache[s]=Ext.select(s)}cache[s].on(parts[1],o[b])}}cache=null},id:function(el,prefix){prefix=prefix||"ext-gen";el=Ext.getDom(el);var id=prefix+(++idSeed);return el?(el.id?el.id:(el.id=id)):id},extend:function(){var io=function(o){for(var m in o){this[m]=o[m]}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=="object"){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments)}}var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp}sb.override=function(o){Ext.override(sb,o)};sbp.override=io;Ext.override(sb,overrides);sb.extend=function(o){Ext.extend(sb,o)};return sb}}(),override:function(origclass,overrides){if(overrides){var p=origclass.prototype;for(var method in overrides){p[method]=overrides[method]}}},namespace:function(){var a=arguments,o=null,i,j,d,rt;for(i=0;i=0){L=G[P]}if(!S||!L){return false}this.doRemove(S,O,L[this.WFN],false);delete G[P][this.WFN];delete G[P][this.FN];G.splice(P,1);return true},getTarget:function(N,M){N=N.browserEvent||N;var L=N.target||N.srcElement;return this.resolveTextNode(L)},resolveTextNode:function(L){if(Ext.isSafari&&L&&3==L.nodeType){return L.parentNode}else{return L}},getPageX:function(M){M=M.browserEvent||M;var L=M.pageX;if(!L&&0!==L){L=M.clientX||0;if(Ext.isIE){L+=this.getScroll()[1]}}return L},getPageY:function(L){L=L.browserEvent||L;var M=L.pageY;if(!M&&0!==M){M=L.clientY||0;if(Ext.isIE){M+=this.getScroll()[0]}}return M},getXY:function(L){L=L.browserEvent||L;return[this.getPageX(L),this.getPageY(L)]},getRelatedTarget:function(M){M=M.browserEvent||M;var L=M.relatedTarget;if(!L){if(M.type=="mouseout"){L=M.toElement}else{if(M.type=="mouseover"){L=M.fromElement}}}return this.resolveTextNode(L)},getTime:function(N){N=N.browserEvent||N;if(!N.time){var M=new Date().getTime();try{N.time=M}catch(L){this.lastError=L;return M}}return N.time},stopEvent:function(L){this.stopPropagation(L);this.preventDefault(L)},stopPropagation:function(L){L=L.browserEvent||L;if(L.stopPropagation){L.stopPropagation()}else{L.cancelBubble=true}},preventDefault:function(L){L=L.browserEvent||L;if(L.preventDefault){L.preventDefault()}else{L.returnValue=false}},getEvent:function(M){var L=M||window.event;if(!L){var N=this.getEvent.caller;while(N){L=N.arguments[0];if(L&&Event==L.constructor){break}N=N.caller}}return L},getCharCode:function(L){L=L.browserEvent||L;return L.charCode||L.keyCode||0},_getCacheIndex:function(Q,N,P){for(var O=0,M=G.length;O0)}var Q=[];for(var M=0,L=H.length;M0){for(var Q=0,S=T.length;Q0){O=G.length;while(O){N=O-1;M=G[N];if(M){R.removeListener(M[R.EL],M[R.TYPE],M[R.FN],N)}O=O-1}M=null;R.clearCache()}R.doRemove(window,"unload",R._unload)},getScroll:function(){var L=document.documentElement,M=document.body;if(L&&(L.scrollTop||L.scrollLeft)){return[L.scrollTop,L.scrollLeft]}else{if(M){return[M.scrollTop,M.scrollLeft]}else{return[0,0]}}},doAdd:function(){if(window.addEventListener){return function(O,M,N,L){O.addEventListener(M,N,(L))}}else{if(window.attachEvent){return function(O,M,N,L){O.attachEvent("on"+M,N)}}else{return function(){}}}}(),doRemove:function(){if(window.removeEventListener){return function(O,M,N,L){O.removeEventListener(M,N,(L))}}else{if(window.detachEvent){return function(N,L,M){N.detachEvent("on"+L,M)}}else{return function(){}}}}()}}();var D=Ext.lib.Event;D.on=D.addListener;D.un=D.removeListener;if(document&&document.body){D._load()}else{D.doAdd(window,"load",D._load)}D.doAdd(window,"unload",D._unload);D._tryPreloadAttach();Ext.lib.Ajax={request:function(K,I,E,J,F){if(F){var G=F.headers;if(G){for(var H in G){if(G.hasOwnProperty(H)){this.initHeader(H,G[H],false)}}}if(F.xmlData){if(!G||!G["Content-Type"]){this.initHeader("Content-Type","text/xml",false)}K=(K?K:(F.method?F.method:"POST"));J=F.xmlData}else{if(F.jsonData){if(!G||!G["Content-Type"]){this.initHeader("Content-Type","application/json",false)}K=(K?K:(F.method?F.method:"POST"));J=typeof F.jsonData=="object"?Ext.encode(F.jsonData):F.jsonData}}}return this.asyncRequest(K,I,E,J)},serializeForm:function(F){if(typeof F=="string"){F=(document.getElementById(F)||document.forms[F])}var G,E,H,J,K="",M=false;for(var L=0;L=200&&G<300){F=this.createResponseObject(I,J.argument);if(J.success){if(!J.scope){J.success(F)}else{J.success.apply(J.scope,[F])}}}else{switch(G){case 12002:case 12029:case 12030:case 12031:case 12152:case 13030:F=this.createExceptionObject(I.tId,J.argument,(E?E:false));if(J.failure){if(!J.scope){J.failure(F)}else{J.failure.apply(J.scope,[F])}}break;default:F=this.createResponseObject(I,J.argument);if(J.failure){if(!J.scope){J.failure(F)}else{J.failure.apply(J.scope,[F])}}}}this.releaseObject(I);F=null},createResponseObject:function(E,K){var H={};var M={};try{var G=E.conn.getAllResponseHeaders();var J=G.split("\n");for(var I=0;I=this.left&&E.right<=this.right&&E.top>=this.top&&E.bottom<=this.bottom)},getArea:function(){return((this.bottom-this.top)*(this.right-this.left))},intersect:function(I){var G=Math.max(this.top,I.top);var H=Math.min(this.right,I.right);var E=Math.min(this.bottom,I.bottom);var F=Math.max(this.left,I.left);if(E>=G&&H>=F){return new Ext.lib.Region(G,H,E,F)}else{return null}},union:function(I){var G=Math.min(this.top,I.top);var H=Math.max(this.right,I.right);var E=Math.max(this.bottom,I.bottom);var F=Math.min(this.left,I.left);return new Ext.lib.Region(G,H,E,F)},constrainTo:function(E){this.top=this.top.constrain(E.top,E.bottom);this.bottom=this.bottom.constrain(E.top,E.bottom);this.left=this.left.constrain(E.left,E.right);this.right=this.right.constrain(E.left,E.right);return this},adjust:function(G,F,E,H){this.top+=G;this.left+=F;this.right+=H;this.bottom+=E;return this}};Ext.lib.Region.getRegion=function(H){var J=Ext.lib.Dom.getXY(H);var G=J[1];var I=J[0]+H.offsetWidth;var E=J[1]+H.offsetHeight;var F=J[0];return new Ext.lib.Region(G,I,E,F)};Ext.lib.Point=function(E,F){if(Ext.isArray(E)){F=E[1];E=E[0]}this.x=this.right=this.left=this[0]=E;this.y=this.top=this.bottom=this[1]=F};Ext.lib.Point.prototype=new Ext.lib.Region();Ext.lib.Anim={scroll:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.Scroll)},motion:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.Motion)},color:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G,Ext.lib.ColorAnim)},run:function(I,F,K,L,E,H,G){G=G||Ext.lib.AnimBase;if(typeof L=="string"){L=Ext.lib.Easing[L]}var J=new G(I,F,K,L);J.animateX(function(){Ext.callback(E,H)});return J}};function C(E){if(!B){B=new Ext.Element.Flyweight()}B.dom=E;return B}if(Ext.isIE){function A(){var E=Function.prototype;delete E.createSequence;delete E.defer;delete E.createDelegate;delete E.createCallback;delete E.createInterceptor;window.detachEvent("onunload",A)}window.attachEvent("onunload",A)}Ext.lib.AnimBase=function(F,E,G,H){if(F){this.init(F,E,G,H)}};Ext.lib.AnimBase.prototype={toString:function(){var E=this.getEl();var F=E.id||E.tagName;return("Anim "+F)},patterns:{noNegatives:/width|height|opacity|padding/i,offsetAttribute:/^((width|height)|(top|left))$/,defaultUnit:/width|height|top$|bottom$|left$|right$/i,offsetUnit:/\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i},doMethod:function(E,G,F){return this.method(this.currentFrame,G,F-G,this.totalFrames)},setAttribute:function(E,G,F){if(this.patterns.noNegatives.test(E)){G=(G>0)?G:0}Ext.fly(this.getEl(),"_anim").setStyle(E,G+F)},getAttribute:function(E){var G=this.getEl();var I=C(G).getStyle(E);if(I!=="auto"&&!this.patterns.offsetUnit.test(I)){return parseFloat(I)}var F=this.patterns.offsetAttribute.exec(E)||[];var J=!!(F[3]);var H=!!(F[2]);if(H||(C(G).getStyle("position")=="absolute"&&J)){I=G["offset"+F[0].charAt(0).toUpperCase()+F[0].substr(1)]}else{I=0}return I},getDefaultUnit:function(E){if(this.patterns.defaultUnit.test(E)){return"px"}return""},animateX:function(G,E){var F=function(){this.onComplete.removeListener(F);if(typeof G=="function"){G.call(E||this,this)}};this.onComplete.addListener(F,this);this.animate()},setRuntimeAttribute:function(F){var K;var G;var H=this.attributes;this.runtimeAttributes[F]={};var J=function(L){return(typeof L!=="undefined")};if(!J(H[F]["to"])&&!J(H[F]["by"])){return false}K=(J(H[F]["from"]))?H[F]["from"]:this.getAttribute(F);if(J(H[F]["to"])){G=H[F]["to"]}else{if(J(H[F]["by"])){if(K.constructor==Array){G=[];for(var I=0,E=K.length;I0&&isFinite(O)){if(K.currentFrame+O>=N){O=N-(M+1)}K.currentFrame+=O}}};Ext.lib.Bezier=new function(){this.getPosition=function(I,H){var J=I.length;var G=[];for(var F=0;F0&&!Ext.isArray(O[0])){O=[O]}else{var N=[];for(P=0,R=O.length;P0){this.runtimeAttributes[S]=this.runtimeAttributes[S].concat(O)}this.runtimeAttributes[S][this.runtimeAttributes[S].length]=L}else{I.setRuntimeAttribute.call(this,S)}};var E=function(J,L){var K=Ext.lib.Dom.getXY(this.getEl());J=[J[0]-K[0]+L[0],J[1]-K[1]+L[1]];return J};var G=function(J){return(typeof J!=="undefined")}})();(function(){Ext.lib.Scroll=function(I,H,J,K){if(I){Ext.lib.Scroll.superclass.constructor.call(this,I,H,J,K)}};Ext.extend(Ext.lib.Scroll,Ext.lib.ColorAnim);var F=Ext.lib;var G=F.Scroll.superclass;var E=F.Scroll.prototype;E.toString=function(){var H=this.getEl();var I=H.id||H.tagName;return("Scroll "+I)};E.doMethod=function(H,K,I){var J=null;if(H=="scroll"){J=[this.method(this.currentFrame,K[0],I[0]-K[0],this.totalFrames),this.method(this.currentFrame,K[1],I[1]-K[1],this.totalFrames)]}else{J=G.doMethod.call(this,H,K,I)}return J};E.getAttribute=function(H){var J=null;var I=this.getEl();if(H=="scroll"){J=[I.scrollLeft,I.scrollTop]}else{J=G.getAttribute.call(this,H)}return J};E.setAttribute=function(H,K,J){var I=this.getEl();if(H=="scroll"){I.scrollLeft=K[0];I.scrollTop=K[1]}else{G.setAttribute.call(this,H,K,J)}}})()})(); diff --git a/src/com/anzsoft/public/js/ext/adapter/jquery/ext-jquery-adapter.js b/src/com/anzsoft/public/js/ext/adapter/jquery/ext-jquery-adapter.js new file mode 100644 index 0000000..40e3333 --- /dev/null +++ b/src/com/anzsoft/public/js/ext/adapter/jquery/ext-jquery-adapter.js @@ -0,0 +1,10 @@ +/* + * Ext JS Library 2.2 + * Copyright(c) 2006-2008, Ext JS, LLC. + * licensing@extjs.com + * + * http://extjs.com/license + */ + +Ext={version:"2.2"};window["undefined"]=window["undefined"];Ext.apply=function(C,D,B){if(B){Ext.apply(C,B)}if(C&&D&&typeof D=="object"){for(var A in D){C[A]=D[A]}}return C};(function(){var idSeed=0;var ua=navigator.userAgent.toLowerCase();var isStrict=document.compatMode=="CSS1Compat",isOpera=ua.indexOf("opera")>-1,isSafari=(/webkit|khtml/).test(ua),isSafari3=isSafari&&ua.indexOf("webkit/5")!=-1,isIE=!isOpera&&ua.indexOf("msie")>-1,isIE7=!isOpera&&ua.indexOf("msie 7")>-1,isGecko=!isSafari&&ua.indexOf("gecko")>-1,isGecko3=!isSafari&&ua.indexOf("rv:1.9")>-1,isBorderBox=isIE&&!isStrict,isWindows=(ua.indexOf("windows")!=-1||ua.indexOf("win32")!=-1),isMac=(ua.indexOf("macintosh")!=-1||ua.indexOf("mac os x")!=-1),isAir=(ua.indexOf("adobeair")!=-1),isLinux=(ua.indexOf("linux")!=-1),isSecure=window.location.href.toLowerCase().indexOf("https")===0;if(isIE&&!isIE7){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}Ext.apply(Ext,{isStrict:isStrict,isSecure:isSecure,isReady:false,enableGarbageCollector:true,enableListenerCollection:false,SSL_SECURE_URL:"javascript:false",BLANK_IMAGE_URL:"http:/"+"/extjs.com/s.gif",emptyFn:function(){},applyIf:function(o,c){if(o&&c){for(var p in c){if(typeof o[p]=="undefined"){o[p]=c[p]}}}return o},addBehaviors:function(o){if(!Ext.isReady){Ext.onReady(function(){Ext.addBehaviors(o)});return }var cache={};for(var b in o){var parts=b.split("@");if(parts[1]){var s=parts[0];if(!cache[s]){cache[s]=Ext.select(s)}cache[s].on(parts[1],o[b])}}cache=null},id:function(el,prefix){prefix=prefix||"ext-gen";el=Ext.getDom(el);var id=prefix+(++idSeed);return el?(el.id?el.id:(el.id=id)):id},extend:function(){var io=function(o){for(var m in o){this[m]=o[m]}};var oc=Object.prototype.constructor;return function(sb,sp,overrides){if(typeof sp=="object"){overrides=sp;sp=sb;sb=overrides.constructor!=oc?overrides.constructor:function(){sp.apply(this,arguments)}}var F=function(){},sbp,spp=sp.prototype;F.prototype=spp;sbp=sb.prototype=new F();sbp.constructor=sb;sb.superclass=spp;if(spp.constructor==oc){spp.constructor=sp}sb.override=function(o){Ext.override(sb,o)};sbp.override=io;Ext.override(sb,overrides);sb.extend=function(o){Ext.extend(sb,o)};return sb}}(),override:function(origclass,overrides){if(overrides){var p=origclass.prototype;for(var method in overrides){p[method]=overrides[method]}}},namespace:function(){var a=arguments,o=null,i,j,d,rt;for(i=0;i10000){clearInterval(G)}var J=document.getElementById(I);if(J){clearInterval(G);E.call(D||window,J)}};var G=setInterval(F,50)},resolveTextNode:function(D){if(D&&3==D.nodeType){return D.parentNode}else{return D}},getRelatedTarget:function(E){E=E.browserEvent||E;var D=E.relatedTarget;if(!D){if(E.type=="mouseout"){D=E.toElement}else{if(E.type=="mouseover"){D=E.fromElement}}}return this.resolveTextNode(D)}};Ext.lib.Ajax=function(){var D=function(E){return function(G,F){if((F=="error"||F=="timeout")&&E.failure){E.failure.call(E.scope||window,{responseText:G.responseText,responseXML:G.responseXML,argument:E.argument})}else{if(E.success){E.success.call(E.scope||window,{responseText:G.responseText,responseXML:G.responseXML,argument:E.argument})}}}};return{request:function(K,H,E,I,F){var J={type:K,url:H,data:I,timeout:E.timeout,complete:D(E)};if(F){var G=F.headers;if(F.xmlData){J.data=F.xmlData;J.processData=false;J.type=(K?K:(F.method?F.method:"POST"));if(!G||!G["Content-Type"]){J.contentType="text/xml"}}else{if(F.jsonData){J.data=typeof F.jsonData=="object"?Ext.encode(F.jsonData):F.jsonData;J.processData=false;J.type=(K?K:(F.method?F.method:"POST"));if(!G||!G["Content-Type"]){J.contentType="application/json"}}}if(G){J.beforeSend=function(M){for(var L in G){if(G.hasOwnProperty(L)){M.setRequestHeader(L,G[L])}}}}}jQuery.ajax(J)},formRequest:function(I,H,F,J,E,G){jQuery.ajax({type:Ext.getDom(I).method||"POST",url:H,data:jQuery(I).serialize()+(J?"&"+J:""),timeout:F.timeout,complete:D(F)})},isCallInProgress:function(E){return false},abort:function(E){return false},serializeForm:function(E){return jQuery(E.dom||E).serialize()}}}();Ext.lib.Anim=function(){var D=function(E,F){var G=true;return{stop:function(H){},isAnimated:function(){return G},proxyCallback:function(){G=false;Ext.callback(E,F)}}};return{scroll:function(H,F,J,K,E,G){var I=D(E,G);H=Ext.getDom(H);if(typeof F.scroll.to[0]=="number"){H.scrollLeft=F.scroll.to[0]}if(typeof F.scroll.to[1]=="number"){H.scrollTop=F.scroll.to[1]}I.proxyCallback();return I},motion:function(H,F,I,J,E,G){return this.run(H,F,I,J,E,G)},color:function(H,F,J,K,E,G){var I=D(E,G);I.proxyCallback();return I},run:function(F,N,I,M,G,P,O){var J=D(G,P),K=Ext.fly(F,"_animrun");var E={};for(var H in N){if(N[H].from){if(H!="points"){K.setStyle(H,N[H].from)}}switch(H){case"points":var L,R;K.position();if(L=N.points.by){var Q=K.getXY();R=K.translatePoints([Q[0]+L[0],Q[1]+L[1]])}else{R=K.translatePoints(N.points.to)}E.left=R.left;E.top=R.top;if(!parseInt(K.getStyle("left"),10)){K.setLeft(0)}if(!parseInt(K.getStyle("top"),10)){K.setTop(0)}if(N.points.from){K.setXY(N.points.from)}break;case"width":E.width=N.width.to;break;case"height":E.height=N.height.to;break;case"opacity":E.opacity=N.opacity.to;break;case"left":E.left=N.left.to;break;case"top":E.top=N.top.to;break;default:E[H]=N[H].to;break}}jQuery(F).animate(E,I*1000,undefined,J.proxyCallback);return J}}}();Ext.lib.Region=function(F,G,D,E){this.top=F;this[1]=F;this.right=G;this.bottom=D;this.left=E;this[0]=E};Ext.lib.Region.prototype={contains:function(D){return(D.left>=this.left&&D.right<=this.right&&D.top>=this.top&&D.bottom<=this.bottom)},getArea:function(){return((this.bottom-this.top)*(this.right-this.left))},intersect:function(H){var F=Math.max(this.top,H.top);var G=Math.min(this.right,H.right);var D=Math.min(this.bottom,H.bottom);var E=Math.max(this.left,H.left);if(D>=F&&G>=E){return new Ext.lib.Region(F,G,D,E)}else{return null}},union:function(H){var F=Math.min(this.top,H.top);var G=Math.max(this.right,H.right);var D=Math.max(this.bottom,H.bottom);var E=Math.min(this.left,H.left);return new Ext.lib.Region(F,G,D,E)},constrainTo:function(D){this.top=this.top.constrain(D.top,D.bottom);this.bottom=this.bottom.constrain(D.top,D.bottom);this.left=this.left.constrain(D.left,D.right);this.right=this.right.constrain(D.left,D.right);return this},adjust:function(F,E,D,G){this.top+=F;this.left+=E;this.right+=G;this.bottom+=D;return this}};Ext.lib.Region.getRegion=function(G){var I=Ext.lib.Dom.getXY(G);var F=I[1];var H=I[0]+G.offsetWidth;var D=I[1]+G.offsetHeight;var E=I[0];return new Ext.lib.Region(F,H,D,E)};Ext.lib.Point=function(D,E){if(Ext.isArray(D)){E=D[1];D=D[0]}this.x=this.right=this.left=this[0]=D;this.y=this.top=this.bottom=this[1]=E};Ext.lib.Point.prototype=new Ext.lib.Region();if(Ext.isIE){function A(){var D=Function.prototype;delete D.createSequence;delete D.defer;delete D.createDelegate;delete D.createCallback;delete D.createInterceptor;window.detachEvent("onunload",A)}window.attachEvent("onunload",A)}})(); diff --git a/src/com/anzsoft/public/js/ext/adapter/jquery/jquery.js b/src/com/anzsoft/public/js/ext/adapter/jquery/jquery.js new file mode 100644 index 0000000..2e43a82 --- /dev/null +++ b/src/com/anzsoft/public/js/ext/adapter/jquery/jquery.js @@ -0,0 +1,3408 @@ +(function(){ +/* + * jQuery 1.2.3 - New Wave Javascript + * + * Copyright (c) 2008 John Resig (jquery.com) + * Dual licensed under the MIT (MIT-LICENSE.txt) + * and GPL (GPL-LICENSE.txt) licenses. + * + * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $ + * $Rev: 4663 $ + */ + +// Map over jQuery in case of overwrite +if ( window.jQuery ) + var _jQuery = window.jQuery; + +var jQuery = window.jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.prototype.init( selector, context ); +}; + +// Map over the $ in case of overwrite +if ( window.$ ) + var _$ = window.$; + +// Map the jQuery namespace to the '$' one +window.$ = jQuery; + +// A simple way to check for HTML strings or ID strings +// (both of which we optimize for) +var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/; + +// Is it a simple selector +var isSimple = /^.[^:#\[\.]*$/; + +jQuery.fn = jQuery.prototype = { + init: function( selector, context ) { + // Make sure that a selection was provided + selector = selector || document; + + // Handle $(DOMElement) + if ( selector.nodeType ) { + this[0] = selector; + this.length = 1; + return this; + + // Handle HTML strings + } else if ( typeof selector == "string" ) { + // Are we dealing with HTML string or an ID? + var match = quickExpr.exec( selector ); + + // Verify a match, and that no context was specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) + selector = jQuery.clean( [ match[1] ], context ); + + // HANDLE: $("#id") + else { + var elem = document.getElementById( match[3] ); + + // Make sure an element was located + if ( elem ) + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id != match[3] ) + return jQuery().find( selector ); + + // Otherwise, we inject the element directly into the jQuery object + else { + this[0] = elem; + this.length = 1; + return this; + } + + else + selector = []; + } + + // HANDLE: $(expr, [context]) + // (which is just equivalent to: $(content).find(expr) + } else + return new jQuery( context ).find( selector ); + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) + return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector ); + + return this.setArray( + // HANDLE: $(array) + selector.constructor == Array && selector || + + // HANDLE: $(arraylike) + // Watch for when an array-like object, contains DOM nodes, is passed in as the selector + (selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) || + + // HANDLE: $(*) + [ selector ] ); + }, + + // The current version of jQuery being used + jquery: "1.2.3", + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + // The number of elements contained in the matched element set + length: 0, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == undefined ? + + // Return a 'clean' array + jQuery.makeArray( this ) : + + // Return just the object + this[ num ]; + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + // Build a new jQuery matched element set + var ret = jQuery( elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Force the current matched set of elements to become + // the specified array of elements (destroying the stack in the process) + // You should use pushStack() in order to do this, but maintain the stack + setArray: function( elems ) { + // Resetting the length to 0, then using the native Array push + // is a super-fast way to populate an object with array-like properties + this.length = 0; + Array.prototype.push.apply( this, elems ); + + return this; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + var ret = -1; + + // Locate the position of the desired element + this.each(function(i){ + if ( this == elem ) + ret = i; + }); + + return ret; + }, + + attr: function( name, value, type ) { + var options = name; + + // Look for the case where we're accessing a style value + if ( name.constructor == String ) + if ( value == undefined ) + return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined; + + else { + options = {}; + options[ name ] = value; + } + + // Check to see if we're setting style values + return this.each(function(i){ + // Set all the styles + for ( name in options ) + jQuery.attr( + type ? + this.style : + this, + name, jQuery.prop( this, options[ name ], type, i, name ) + ); + }); + }, + + css: function( key, value ) { + // ignore negative width and height values + if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 ) + value = undefined; + return this.attr( key, value, "curCSS" ); + }, + + text: function( text ) { + if ( typeof text != "object" && text != null ) + return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) ); + + var ret = ""; + + jQuery.each( text || this, function(){ + jQuery.each( this.childNodes, function(){ + if ( this.nodeType != 8 ) + ret += this.nodeType != 1 ? + this.nodeValue : + jQuery.fn.text( [ this ] ); + }); + }); + + return ret; + }, + + wrapAll: function( html ) { + if ( this[0] ) + // The elements to wrap the target around + jQuery( html, this[0].ownerDocument ) + .clone() + .insertBefore( this[0] ) + .map(function(){ + var elem = this; + + while ( elem.firstChild ) + elem = elem.firstChild; + + return elem; + }) + .append(this); + + return this; + }, + + wrapInner: function( html ) { + return this.each(function(){ + jQuery( this ).contents().wrapAll( html ); + }); + }, + + wrap: function( html ) { + return this.each(function(){ + jQuery( this ).wrapAll( html ); + }); + }, + + append: function() { + return this.domManip(arguments, true, false, function(elem){ + if (this.nodeType == 1) + this.appendChild( elem ); + }); + }, + + prepend: function() { + return this.domManip(arguments, true, true, function(elem){ + if (this.nodeType == 1) + this.insertBefore( elem, this.firstChild ); + }); + }, + + before: function() { + return this.domManip(arguments, false, false, function(elem){ + this.parentNode.insertBefore( elem, this ); + }); + }, + + after: function() { + return this.domManip(arguments, false, true, function(elem){ + this.parentNode.insertBefore( elem, this.nextSibling ); + }); + }, + + end: function() { + return this.prevObject || jQuery( [] ); + }, + + find: function( selector ) { + var elems = jQuery.map(this, function(elem){ + return jQuery.find( selector, elem ); + }); + + return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ? + jQuery.unique( elems ) : + elems ); + }, + + clone: function( events ) { + // Do the clone + var ret = this.map(function(){ + if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) { + // IE copies events bound via attachEvent when + // using cloneNode. Calling detachEvent on the + // clone will also remove the events from the orignal + // In order to get around this, we use innerHTML. + // Unfortunately, this means some modifications to + // attributes in IE that are actually only stored + // as properties will not be copied (such as the + // the name attribute on an input). + var clone = this.cloneNode(true), + container = document.createElement("div"); + container.appendChild(clone); + return jQuery.clean([container.innerHTML])[0]; + } else + return this.cloneNode(true); + }); + + // Need to set the expando to null on the cloned set if it exists + // removeData doesn't work here, IE removes it from the original as well + // this is primarily for IE but the data expando shouldn't be copied over in any browser + var clone = ret.find("*").andSelf().each(function(){ + if ( this[ expando ] != undefined ) + this[ expando ] = null; + }); + + // Copy the events from the original to the clone + if ( events === true ) + this.find("*").andSelf().each(function(i){ + if (this.nodeType == 3) + return; + var events = jQuery.data( this, "events" ); + + for ( var type in events ) + for ( var handler in events[ type ] ) + jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data ); + }); + + // Return the cloned set + return ret; + }, + + filter: function( selector ) { + return this.pushStack( + jQuery.isFunction( selector ) && + jQuery.grep(this, function(elem, i){ + return selector.call( elem, i ); + }) || + + jQuery.multiFilter( selector, this ) ); + }, + + not: function( selector ) { + if ( selector.constructor == String ) + // test special case where just one selector is passed in + if ( isSimple.test( selector ) ) + return this.pushStack( jQuery.multiFilter( selector, this, true ) ); + else + selector = jQuery.multiFilter( selector, this ); + + var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType; + return this.filter(function() { + return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector; + }); + }, + + add: function( selector ) { + return !selector ? this : this.pushStack( jQuery.merge( + this.get(), + selector.constructor == String ? + jQuery( selector ).get() : + selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ? + selector : [selector] ) ); + }, + + is: function( selector ) { + return selector ? + jQuery.multiFilter( selector, this ).length > 0 : + false; + }, + + hasClass: function( selector ) { + return this.is( "." + selector ); + }, + + val: function( value ) { + if ( value == undefined ) { + + if ( this.length ) { + var elem = this[0]; + + // We need to handle select boxes special + if ( jQuery.nodeName( elem, "select" ) ) { + var index = elem.selectedIndex, + values = [], + options = elem.options, + one = elem.type == "select-one"; + + // Nothing was selected + if ( index < 0 ) + return null; + + // Loop through all the selected options + for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) { + var option = options[ i ]; + + if ( option.selected ) { + // Get the specifc value for the option + value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value; + + // We don't need an array for one selects + if ( one ) + return value; + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + + // Everything else, we just grab the value + } else + return (this[0].value || "").replace(/\r/g, ""); + + } + + return undefined; + } + + return this.each(function(){ + if ( this.nodeType != 1 ) + return; + + if ( value.constructor == Array && /radio|checkbox/.test( this.type ) ) + this.checked = (jQuery.inArray(this.value, value) >= 0 || + jQuery.inArray(this.name, value) >= 0); + + else if ( jQuery.nodeName( this, "select" ) ) { + var values = value.constructor == Array ? + value : + [ value ]; + + jQuery( "option", this ).each(function(){ + this.selected = (jQuery.inArray( this.value, values ) >= 0 || + jQuery.inArray( this.text, values ) >= 0); + }); + + if ( !values.length ) + this.selectedIndex = -1; + + } else + this.value = value; + }); + }, + + html: function( value ) { + return value == undefined ? + (this.length ? + this[0].innerHTML : + null) : + this.empty().append( value ); + }, + + replaceWith: function( value ) { + return this.after( value ).remove(); + }, + + eq: function( i ) { + return this.slice( i, i + 1 ); + }, + + slice: function() { + return this.pushStack( Array.prototype.slice.apply( this, arguments ) ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function(elem, i){ + return callback.call( elem, i, elem ); + })); + }, + + andSelf: function() { + return this.add( this.prevObject ); + }, + + data: function( key, value ){ + var parts = key.split("."); + parts[1] = parts[1] ? "." + parts[1] : ""; + + if ( value == null ) { + var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]); + + if ( data == undefined && this.length ) + data = jQuery.data( this[0], key ); + + return data == null && parts[1] ? + this.data( parts[0] ) : + data; + } else + return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){ + jQuery.data( this, key, value ); + }); + }, + + removeData: function( key ){ + return this.each(function(){ + jQuery.removeData( this, key ); + }); + }, + + domManip: function( args, table, reverse, callback ) { + var clone = this.length > 1, elems; + + return this.each(function(){ + if ( !elems ) { + elems = jQuery.clean( args, this.ownerDocument ); + + if ( reverse ) + elems.reverse(); + } + + var obj = this; + + if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) ) + obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") ); + + var scripts = jQuery( [] ); + + jQuery.each(elems, function(){ + var elem = clone ? + jQuery( this ).clone( true )[0] : + this; + + // execute all scripts after the elements have been injected + if ( jQuery.nodeName( elem, "script" ) ) { + scripts = scripts.add( elem ); + } else { + // Remove any inner scripts for later evaluation + if ( elem.nodeType == 1 ) + scripts = scripts.add( jQuery( "script", elem ).remove() ); + + // Inject the elements into the document + callback.call( obj, elem ); + } + }); + + scripts.each( evalScript ); + }); + } +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.prototype.init.prototype = jQuery.prototype; + +function evalScript( i, elem ) { + if ( elem.src ) + jQuery.ajax({ + url: elem.src, + async: false, + dataType: "script" + }); + + else + jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" ); + + if ( elem.parentNode ) + elem.parentNode.removeChild( elem ); +} + +jQuery.extend = jQuery.fn.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( target.constructor == Boolean ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target != "object" && typeof target != "function" ) + target = {}; + + // extend jQuery itself if only one argument is passed + if ( length == 1 ) { + target = this; + i = 0; + } + + for ( ; i < length; i++ ) + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) + // Extend the base object + for ( var name in options ) { + // Prevent never-ending loop + if ( target === options[ name ] ) + continue; + + // Recurse if we're merging object values + if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType ) + target[ name ] = jQuery.extend( target[ name ], options[ name ] ); + + // Don't bring in undefined values + else if ( options[ name ] != undefined ) + target[ name ] = options[ name ]; + + } + + // Return the modified object + return target; +}; + +var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {}; + +// exclude the following css properties to add px +var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i; + +jQuery.extend({ + noConflict: function( deep ) { + window.$ = _$; + + if ( deep ) + window.jQuery = _jQuery; + + return jQuery; + }, + + // See test/unit/core.js for details concerning this function. + isFunction: function( fn ) { + return !!fn && typeof fn != "string" && !fn.nodeName && + fn.constructor != Array && /function/i.test( fn + "" ); + }, + + // check if an element is in a (or is an) XML document + isXMLDoc: function( elem ) { + return elem.documentElement && !elem.body || + elem.tagName && elem.ownerDocument && !elem.ownerDocument.body; + }, + + // Evalulates a script in a global context + globalEval: function( data ) { + data = jQuery.trim( data ); + + if ( data ) { + // Inspired by code by Andrea Giammarchi + // http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html + var head = document.getElementsByTagName("head")[0] || document.documentElement, + script = document.createElement("script"); + + script.type = "text/javascript"; + if ( jQuery.browser.msie ) + script.text = data; + else + script.appendChild( document.createTextNode( data ) ); + + head.appendChild( script ); + head.removeChild( script ); + } + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase(); + }, + + cache: {}, + + data: function( elem, name, data ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // Compute a unique ID for the element + if ( !id ) + id = elem[ expando ] = ++uuid; + + // Only generate the data cache if we're + // trying to access or manipulate it + if ( name && !jQuery.cache[ id ] ) + jQuery.cache[ id ] = {}; + + // Prevent overriding the named cache with undefined values + if ( data != undefined ) + jQuery.cache[ id ][ name ] = data; + + // Return the named cache data, or the ID for the element + return name ? + jQuery.cache[ id ][ name ] : + id; + }, + + removeData: function( elem, name ) { + elem = elem == window ? + windowData : + elem; + + var id = elem[ expando ]; + + // If we want to remove a specific section of the element's data + if ( name ) { + if ( jQuery.cache[ id ] ) { + // Remove the section of cache data + delete jQuery.cache[ id ][ name ]; + + // If we've removed all the data, remove the element's cache + name = ""; + + for ( name in jQuery.cache[ id ] ) + break; + + if ( !name ) + jQuery.removeData( elem ); + } + + // Otherwise, we want to remove all of the element's data + } else { + // Clean up the element expando + try { + delete elem[ expando ]; + } catch(e){ + // IE has trouble directly removing the expando + // but it's ok with using removeAttribute + if ( elem.removeAttribute ) + elem.removeAttribute( expando ); + } + + // Completely remove the data cache + delete jQuery.cache[ id ]; + } + }, + + // args is for internal usage only + each: function( object, callback, args ) { + if ( args ) { + if ( object.length == undefined ) { + for ( var name in object ) + if ( callback.apply( object[ name ], args ) === false ) + break; + } else + for ( var i = 0, length = object.length; i < length; i++ ) + if ( callback.apply( object[ i ], args ) === false ) + break; + + // A special, fast, case for the most common use of each + } else { + if ( object.length == undefined ) { + for ( var name in object ) + if ( callback.call( object[ name ], name, object[ name ] ) === false ) + break; + } else + for ( var i = 0, length = object.length, value = object[0]; + i < length && callback.call( value, i, value ) !== false; value = object[++i] ){} + } + + return object; + }, + + prop: function( elem, value, type, i, name ) { + // Handle executable functions + if ( jQuery.isFunction( value ) ) + value = value.call( elem, i ); + + // Handle passing in a number to a CSS property + return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ? + value + "px" : + value; + }, + + className: { + // internal only, use addClass("class") + add: function( elem, classNames ) { + jQuery.each((classNames || "").split(/\s+/), function(i, className){ + if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) ) + elem.className += (elem.className ? " " : "") + className; + }); + }, + + // internal only, use removeClass("class") + remove: function( elem, classNames ) { + if (elem.nodeType == 1) + elem.className = classNames != undefined ? + jQuery.grep(elem.className.split(/\s+/), function(className){ + return !jQuery.className.has( classNames, className ); + }).join(" ") : + ""; + }, + + // internal only, use is(".class") + has: function( elem, className ) { + return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1; + } + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback ) { + var old = {}; + // Remember the old values, and insert the new ones + for ( var name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + callback.call( elem ); + + // Revert the old values + for ( var name in options ) + elem.style[ name ] = old[ name ]; + }, + + css: function( elem, name, force ) { + if ( name == "width" || name == "height" ) { + var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ]; + + function getWH() { + val = name == "width" ? elem.offsetWidth : elem.offsetHeight; + var padding = 0, border = 0; + jQuery.each( which, function() { + padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0; + border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0; + }); + val -= Math.round(padding + border); + } + + if ( jQuery(elem).is(":visible") ) + getWH(); + else + jQuery.swap( elem, props, getWH ); + + return Math.max(0, val); + } + + return jQuery.curCSS( elem, name, force ); + }, + + curCSS: function( elem, name, force ) { + var ret; + + // A helper method for determining if an element's values are broken + function color( elem ) { + if ( !jQuery.browser.safari ) + return false; + + var ret = document.defaultView.getComputedStyle( elem, null ); + return !ret || ret.getPropertyValue("color") == ""; + } + + // We need to handle opacity special in IE + if ( name == "opacity" && jQuery.browser.msie ) { + ret = jQuery.attr( elem.style, "opacity" ); + + return ret == "" ? + "1" : + ret; + } + // Opera sometimes will give the wrong display answer, this fixes it, see #2037 + if ( jQuery.browser.opera && name == "display" ) { + var save = elem.style.outline; + elem.style.outline = "0 solid black"; + elem.style.outline = save; + } + + // Make sure we're using the right name for getting the float value + if ( name.match( /float/i ) ) + name = styleFloat; + + if ( !force && elem.style && elem.style[ name ] ) + ret = elem.style[ name ]; + + else if ( document.defaultView && document.defaultView.getComputedStyle ) { + + // Only "float" is needed here + if ( name.match( /float/i ) ) + name = "float"; + + name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase(); + + var getComputedStyle = document.defaultView.getComputedStyle( elem, null ); + + if ( getComputedStyle && !color( elem ) ) + ret = getComputedStyle.getPropertyValue( name ); + + // If the element isn't reporting its values properly in Safari + // then some display: none elements are involved + else { + var swap = [], stack = []; + + // Locate all of the parent display: none elements + for ( var a = elem; a && color(a); a = a.parentNode ) + stack.unshift(a); + + // Go through and make them visible, but in reverse + // (It would be better if we knew the exact display type that they had) + for ( var i = 0; i < stack.length; i++ ) + if ( color( stack[ i ] ) ) { + swap[ i ] = stack[ i ].style.display; + stack[ i ].style.display = "block"; + } + + // Since we flip the display style, we have to handle that + // one special, otherwise get the value + ret = name == "display" && swap[ stack.length - 1 ] != null ? + "none" : + ( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || ""; + + // Finally, revert the display styles back + for ( var i = 0; i < swap.length; i++ ) + if ( swap[ i ] != null ) + stack[ i ].style.display = swap[ i ]; + } + + // We should always get a number back from opacity + if ( name == "opacity" && ret == "" ) + ret = "1"; + + } else if ( elem.currentStyle ) { + var camelCase = name.replace(/\-(\w)/g, function(all, letter){ + return letter.toUpperCase(); + }); + + ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ]; + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) { + // Remember the original values + var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left; + + // Put in the new values to get a computed value out + elem.runtimeStyle.left = elem.currentStyle.left; + elem.style.left = ret || 0; + ret = elem.style.pixelLeft + "px"; + + // Revert the changed values + elem.style.left = style; + elem.runtimeStyle.left = runtimeStyle; + } + } + + return ret; + }, + + clean: function( elems, context ) { + var ret = []; + context = context || document; + // !context.createElement fails in IE with an error but returns typeof 'object' + if (typeof context.createElement == 'undefined') + context = context.ownerDocument || context[0] && context[0].ownerDocument || document; + + jQuery.each(elems, function(i, elem){ + if ( !elem ) + return; + + if ( elem.constructor == Number ) + elem = elem.toString(); + + // Convert html string into DOM nodes + if ( typeof elem == "string" ) { + // Fix "XHTML"-style tags in all browsers + elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){ + return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ? + all : + front + ">"; + }); + + // Trim whitespace, otherwise indexOf won't work as expected + var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div"); + + var wrap = + // option or optgroup + !tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + tags.match(/^<(thead|tbody|tfoot|colg|cap)/) && + [ 1, "", "
    " ] || + + !tags.indexOf("", "" ] || + + // matched above + (!tags.indexOf("", "" ] || + + !tags.indexOf("", "" ] || + + // IE can't serialize and ');},load:function(){var includes=['xmlextras','jsextras','crypt','JSJaCConfig','JSJaCConstants','JSJaCCookie','JSJaCJSON','JSJaCJID','JSJaCBuilder','JSJaCPacket','JSJaCError','JSJaCKeys','JSJaCConnection','JSJaCHttpPollingConnection','JSJaCHttpBindingConnection','JSJaCConsoleLogger'];var scripts=document.getElementsByTagName("script");var path='./';for(var i=0;i + + + + + + + + + + + + + + + iJab + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/com/anzsoft/server/JabberHTTPBind/DNSUtil.java b/src/com/anzsoft/server/JabberHTTPBind/DNSUtil.java new file mode 100644 index 0000000..297c44d --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/DNSUtil.java @@ -0,0 +1,147 @@ +/** + * $RCSfile: DNSUtil.java,v $ + * $Revision: 60 $ + * $Date: 2007-08-27 16:52:28 +0200 (lun, 27 ago 2007) $ + * + * Copyright (C) 2004-2005 Jive Software. All rights reserved. + * + * This software is published under the terms of the Apache License + */ + +package com.anzsoft.server.JabberHTTPBind; + +import javax.naming.directory.Attributes; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.DirContext; +import java.util.Hashtable; + +/** + * Utilty class to perform DNS lookups for XMPP services. + * + * @author Matt Tucker + */ +public class DNSUtil +{ + private static DirContext context; + + static + { + try + { + Hashtable env = new Hashtable(); + env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory"); + context = new InitialDirContext(env); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Returns the host name and port that the specified XMPP server can be + * reached at for communication. A DNS lookup for a SRV + * record in the form "_xmpp-server._tcp.example.com" is attempted, according + * to section 14.4 of RFC 3920. If that lookup fails, a lookup in the older form + * of "_jabber._tcp.example.com" is attempted since servers that implement an + * older version of the protocol may be listed using that notation. If that + * lookup fails as well, it's assumed that the XMPP server lives at the + * host resolved by a DNS lookup at the specified domain on the specified + * default port.

    + * + * As an example, a lookup for "example.com" may return "im.example.com:5269". + * + * @param domain the domain. + * @return a HostAddress, which encompasses the hostname and port that the XMPP + * server can be reached at for the specified domain. + */ + public static HostAddress resolveXMPPServerDomain(String domain, int defaultport) + { + if (context == null) + { + return new HostAddress(domain, defaultport); + } + String host = domain; + int port = defaultport; + + try + { + Attributes dnsLookup = context.getAttributes("_xmpp-client._tcp." + domain); + String srvRecord = (String)dnsLookup.get("SRV").get(); + String [] srvRecordEntries = srvRecord.split(" "); + port = Integer.parseInt(srvRecordEntries[srvRecordEntries.length-2]); + host = srvRecordEntries[srvRecordEntries.length-1]; + } + catch (Exception e) + { + // Attempt lookup with older "jabber" name. + try + { + Attributes dnsLookup = context.getAttributes("_jabber-client._tcp." + domain); + String srvRecord = (String)dnsLookup.get("SRV").get(); + String [] srvRecordEntries = srvRecord.split(" "); + port = Integer.parseInt(srvRecordEntries[srvRecordEntries.length-2]); + host = srvRecordEntries[srvRecordEntries.length-1]; + } + catch (Exception e2) + { } + } + // Host entries in DNS should end with a ".". + if (host.endsWith(".")) + { + host = host.substring(0, host.length()-1); + } + return new HostAddress(host, port); + } + + /** + * Encapsulates a hostname and port. + */ + public static class HostAddress + { + + private String host; + private int port; + + private HostAddress(String host, int port) + { + this.host = host; + this.port = port; + } + + /** + * Returns the hostname. + * + * @return the hostname. + */ + public String getHost() + { + return host; + } + + /** + * Returns the port. + * + * @return the port. + */ + public int getPort() + { + return port; + } + + public String toString() + { + return host + ":" + port; + } + } +} + + + + + + + + + + diff --git a/src/com/anzsoft/server/JabberHTTPBind/JHBServlet.java b/src/com/anzsoft/server/JabberHTTPBind/JHBServlet.java new file mode 100644 index 0000000..96b208c --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/JHBServlet.java @@ -0,0 +1,645 @@ +/* JabberHTTPBind - An implementation of JEP-0124 (HTTP Binding) + * Please see http://www.jabber.org/jeps/jep-0124.html for details. + * + * Copyright (c) 2005-2006 Stefan Strigler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package com.anzsoft.server.JabberHTTPBind; + +import java.io.IOException; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; + +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +/** + * An implementation of JEP-0124 (HTTP Binding). See + * http://www.jabber.org/jeps/jep-0124.html for details. + * + * @author Stefan Strigler + */ + +public final class JHBServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + public static final String APP_VERSION = "1.1"; + + public static final String APP_NAME = "Jabber HTTP Binding Servlet"; + + public static final boolean DEBUG = false; + + public static final int DEBUG_LEVEL = 2; + + private DocumentBuilder db; + + private Janitor janitor; + + public void init() throws ServletException { + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + + try { + db = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + log("failed to create DocumentBuilderFactory", e); + } + + janitor = new Janitor(); // cleans up sessions + new Thread(janitor).start(); + } + + public void destroy() { + Session.stopSessions(); + janitor.stop(); + } + + public static String hex(byte[] array) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < array.length; ++i) { + sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100) + .toLowerCase().substring(1, 3)); + } + return sb.toString(); + } + + public static String sha1(String message) { + try { + MessageDigest sha = MessageDigest.getInstance("SHA-1"); + return hex(sha.digest(message.getBytes())); + } catch (NoSuchAlgorithmException e) { + } + return null; + } + + public static void dbg(String msg) { + dbg(msg, 0); + } + + public static void dbg(String msg, int lvl) { + if (!DEBUG) + return; + if (lvl > DEBUG_LEVEL) + return; + System.err.println("[" + lvl + "] " + msg); + } + + /** + * We only need to respond to POST requests ... + * + * @param request + * The servlet request we are processing + * @param response + * The servlet response we are producing + * + * @exception IOException + * if an input/output error occurs + * @exception ServletException + * if a servlet error occurs + */ + public void doPost(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + long rid = 0; + try { + /* + * parse request + */ + Document doc; + synchronized (db) { + doc = db.parse(request.getInputStream()); + } + + Node rootNode = doc.getDocumentElement(); + if (rootNode == null || !rootNode.getNodeName().equals("body")) + // not a -tag - don't know what to do with it + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + else { + + /* + * we got a request - let's look if there something + * useful we could do with it + */ + + NamedNodeMap attribs = rootNode.getAttributes(); + + if (attribs.getNamedItem("sid") != null) { + + /*********************************************************** + * lookup existing session *** + */ + + Session sess = Session.getSession(attribs.getNamedItem( + "sid").getNodeValue()); + + if (sess != null) { + dbg("incoming request for " + sess.getSID(), 3); + + /******************************************************* + * check if request is valid + */ + // check if rid valid + if (attribs.getNamedItem("rid") == null) { + // rid missing + dbg("rid missing", 1); + response + .sendError(HttpServletResponse.SC_NOT_FOUND); + sess.terminate(); + } else { + try { + rid = Integer.parseInt(attribs.getNamedItem( + "rid").getNodeValue()); + } catch (NumberFormatException e) { + dbg("rid not a number", 1); + response + .sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + Response r = sess.getResponse(rid); + if (r != null) { // resend + dbg("resend rid " + rid, 2); + r.setAborted(true); + r.send(response); + return; + } + if (!sess.checkValidRID(rid)) { + dbg("invalid rid " + rid, 1); + response + .sendError(HttpServletResponse.SC_NOT_FOUND); + sess.terminate(); + return; + } + } + + dbg("found valid rid " + rid, 3); + + /* too many simultaneous requests? */ + if (sess.numPendingRequests() >= Session.MAX_REQUESTS) { + dbg("too many simultaneous requests: " + + sess.numPendingRequests(), 1); + response + .sendError(HttpServletResponse.SC_FORBIDDEN); + // no pardon - kick it + sess.terminate(); + return; + } + + /******************************************************* + * we got a valid request start processing it + */ + + Response jresp = new Response(db + .newDocument()); + jresp.setRID(rid); + jresp.setContentType(sess.getContent()); + sess.addResponse(jresp); + + try { + synchronized (sess.sock) { + /* wait till it's our turn */ + + /* + * NOTE: This only works when having + * MAX_REQUESTS set to 1 or 2 Otherwise we would + * fail on the condition that incoming data from + * the client has to be forwarded as soon as + * possible (the request might be pending + * waiting for others to timeout first) + */ + + /* + * wait 'till we are the lowest rid that's + * pending + */ + + long lastrid = sess.getLastDoneRID(); + while (rid != lastrid + 1) { + if (sess.isStatus(Session.SESS_TERM)) { + dbg("session terminated for " + rid, 1); + response + .sendError(HttpServletResponse.SC_NOT_FOUND); + sess.sock.notifyAll(); + return; + } + try { + dbg(rid + " waiting for " + + (lastrid + 1), 2); + sess.sock.wait(); + dbg("bell for " + rid, 2); + lastrid = sess.getLastDoneRID(); + } catch (InterruptedException e) { + } + } + + dbg("handling response " + rid, 3); + /* + * check key + */ + String key = sess.getKey(); + if (key != null) { + dbg("checking keys for " + rid, 3); + if (attribs.getNamedItem("key") == null + || !sha1( + attribs.getNamedItem("key") + .getNodeValue()) + .equals(key)) { + dbg("Key sequence error", 1); + response + .sendError(HttpServletResponse.SC_NOT_FOUND); + sess.terminate(); + return; + } + if (attribs.getNamedItem("newkey") != null) + sess.setKey(attribs.getNamedItem( + "newkey").getNodeValue()); + else + sess.setKey(attribs.getNamedItem("key") + .getNodeValue()); + dbg("key valid for " + rid, 3); + } + + if (attribs.getNamedItem("xmpp:restart") != null) { + dbg("XMPP RESTART", 2); + sess.setReinit(true); + } + + /* + * check if we got sth to forward to remote + * jabber server + */ + if (rootNode.hasChildNodes()) + sess.sendNodes(rootNode.getChildNodes()); + else { + /* + * check if polling too frequently only + * empty polls are considered harmfull + */ + long now = System.currentTimeMillis(); + if (sess.getHold() == 0 && + now - sess.getLastPoll() < Session.MIN_POLLING * 1000) { + // indeed (s)he's violating our rules + dbg("polling too frequently! [now:" + + now + ", last:" + + sess.getLastPoll() + "(" + + (now - sess.getLastPoll()) + + ")]", 1); + + response + .sendError(HttpServletResponse.SC_FORBIDDEN); + // no pardon - kick it + sess.terminate(); + return; + } + // mark last empty poll + sess.setLastPoll(); + } + + /* + * send response + */ + + /* request to terminate session? */ + if (attribs.getNamedItem("type") != null) { + String rType = attribs.getNamedItem("type") + .getNodeValue(); + if (rType.equals("terminate")) { + sess.terminate(); + jresp.send(response); + return; + } + } + + /* check incoming queue */ + NodeList nl = sess.checkInQ(rid); + // add items to response + if (nl != null) + for (int i = 0; i < nl.getLength(); i++) + jresp.addNode(nl.item(i), + "jabber:client"); + + if (sess.streamFeatures) { + jresp.setAttribute("xmlns:stream", + "http://etherx.jabber.org/streams"); + sess.streamFeatures = false; // reset + } + + /* check for streamid (digest auth!) */ + if (!sess.authidSent + && sess.getAuthid() != null) { + sess.authidSent = true; + jresp.setAttribute("authid", sess + .getAuthid()); + } + + if (sess.isStatus(Session.SESS_TERM)) { + // closed due to stream error + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", + "remote-stream-error"); + } + + /* finally send back response */ + jresp.send(response); + sess.setLastDoneRID(jresp.getRID()); + sess.sock.notifyAll(); + } + } catch (IOException ioe) { + sess.terminate(); + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", + "remote-connection-failed"); + jresp.send(response); + } + } else { + /* session not found! */ + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + } else { + + /*********************************************************** + * request to create a new session *** + */ + + if (attribs.getNamedItem("rid") == null) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } else { + try { + rid = Integer.parseInt(attribs.getNamedItem("rid") + .getNodeValue()); + } catch (NumberFormatException e) { + response + .sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + } + + Response jresp = new Response(db.newDocument(),request); + jresp.setRID(rid); + + // check 'route' attribute + String route = null; + if (attribs.getNamedItem("route") != null + && isValidRoute(attribs.getNamedItem("route") + .getNodeValue())) { + route = attribs.getNamedItem("route").getNodeValue() + .substring("xmpp:".length()); + } + + // check 'to' attribute + String to = null; + if ((attribs.getNamedItem("to") != null) + && (attribs.getNamedItem("to").getNodeValue() != "")) { + to = attribs.getNamedItem("to").getNodeValue(); + } + + if (to == null || to.equals("")) { + /* + * ERROR: 'to' attribute missing or emtpy + */ + + if (attribs.getNamedItem("content") != null) { + jresp.setContentType(attribs + .getNamedItem("content").getNodeValue()); + } else { + jresp.setContentType(Session.DEFAULT_CONTENT); + } + + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", "improper-addressing"); + + jresp.send(response); + return; + } + + /* + * really create new session + */ + try { + Session sess = new Session(to, route); + + if (attribs.getNamedItem("content") != null) + sess.setContent(attribs.getNamedItem("content") + .getNodeValue()); + + if (attribs.getNamedItem("wait") != null) + sess.setWait(Integer.parseInt(attribs.getNamedItem( + "wait").getNodeValue())); + + if (attribs.getNamedItem("hold") != null) + sess.setHold(Integer.parseInt(attribs.getNamedItem( + "hold").getNodeValue())); + + if (attribs.getNamedItem("xml:lang") != null) + sess.setXMLLang(attribs.getNamedItem("xml:lang") + .getNodeValue()); + + if (attribs.getNamedItem("newkey") != null) + sess.setKey(attribs.getNamedItem("newkey") + .getNodeValue()); + + if (attribs.getNamedItem("secure") != null + && (attribs.getNamedItem("secure") + .getNodeValue().equals("true") || attribs + .getNamedItem("secure").getNodeValue() + .equals("1"))) + sess.setSecure(true); // forces IOException + + sess.addResponse(jresp); + + /* + * send back response + */ + jresp.setContentType(sess.getContent()); + + /* check incoming queue */ + NodeList nl = sess.checkInQ(jresp.getRID()); + + // add items to response + if (nl != null) + for (int i = 0; i < nl.getLength(); i++) { + if (!nl.item(i).getNodeName() + .equals("starttls")) + jresp.addNode(nl.item(i), ""); + } + + if (sess.streamFeatures) { + jresp.setAttribute("xmlns:stream", + "http://etherx.jabber.org/streams"); + sess.streamFeatures = false; // reset + } + + jresp.setAttribute("sid", sess.getSID()); + jresp.setAttribute("wait", String.valueOf(sess + .getWait())); + jresp.setAttribute("inactivity", String + .valueOf(Session.MAX_INACTIVITY)); + jresp.setAttribute("polling", String + .valueOf(Session.MIN_POLLING)); + + jresp.setAttribute("requests", String + .valueOf(Session.MAX_REQUESTS)); + + if (sess.getAuthid() != null) { + sess.authidSent = true; + jresp.setAttribute("authid", sess.getAuthid()); + } + + if (sess.isStatus(Session.SESS_TERM)) + jresp.setAttribute("type", "terminate"); + + jresp.send(response); + sess.setLastDoneRID(jresp.getRID()); + } catch (UnknownHostException uhe) { + /* + * ERROR: remote host unknown + */ + + if (attribs.getNamedItem("content") != null) + jresp.setContentType(attribs + .getNamedItem("content").getNodeValue()); + else + jresp.setContentType(Session.DEFAULT_CONTENT); + + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", "host-unknown"); + + jresp.send(response); + } catch (IOException ioe) { + /* + * ERROR: could not connect to remote host + */ + + if (attribs.getNamedItem("content") != null) + jresp.setContentType(attribs + .getNamedItem("content").getNodeValue()); + else + jresp.setContentType(Session.DEFAULT_CONTENT); + + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", + "remote-connection-failed"); + + jresp.send(response); + } catch (NumberFormatException nfe) { + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + } + } + } catch (SAXException se) { + /* + * ERROR: Parser error + */ + dbg(se.toString(), 1); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } catch (Exception e) { + + System.err.println(e.toString()); + e.printStackTrace(); + try { + Response jresp = new Response(db.newDocument()); + jresp.setAttribute("type", "terminate"); + jresp.setAttribute("condition", "internal-server-error"); + jresp.send(response); + } catch (Exception e2) { + e2.printStackTrace(); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + } + } + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + + /* + * This one's just for convenience to inform of improper use of + * component + */ + + response.setContentType("text/html"); + PrintWriter writer = response.getWriter(); + String title = APP_NAME + " v" + APP_VERSION; + writer + .println(""); + writer.println("\n\n" + title + + "\n\n\n"); + writer.println("

    " + title + "

    "); + writer + .println("This is an implementation of JEP-0124 (HTTP-Binding). Please see http://www.jabber.org/jeps/jep-0124.html for details.

    "); + writer.println("Active sessions: "+Session.getNumSessions()); + writer.println("\n\n"); + } + + /** + * Checks if supplied parameter is a valid host value. Valid host values + * should be in the form: "xmpp:" ihost [ ":" port ] + * + * NOTE: RFC 3987 defines the form of ihost like this: ihost = IP-literal / + * IPv4address / ireg-name This function cuts corners and uses + * InetAddress.getByName() to check ihost validity. + * + * + * @see java.net.InetAddress + * @param route + * hostname that should be checked + * @return 'true' if host is in the form "xmpp:" ihost [ ":" port ] + * otherwise 'false'. + */ + private static boolean isValidRoute(String route) { + if (!route.startsWith("xmpp:")) { + return false; + } + + route = route.substring("xmpp:".length()); + + // check for port validity, if a port is given. + int port; + if ((port = route.lastIndexOf(":")) != -1) { + try { + int p = Integer.parseInt(route.substring(port + 1)); + if (p < 0 || p > 65535) { + return false; + } + } catch (NumberFormatException nfe) { + return false; + } + route = route.substring(0, port); + } + + try { + InetAddress.getByName(route); + } catch (Exception e) { + return false; + } + + return true; + } + +} diff --git a/src/com/anzsoft/server/JabberHTTPBind/Janitor.java b/src/com/anzsoft/server/JabberHTTPBind/Janitor.java new file mode 100644 index 0000000..e35d5f9 --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/Janitor.java @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2005 Stefan Strigler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package com.anzsoft.server.JabberHTTPBind; + +import java.util.Enumeration; + +/** + * @author Stefan Strigler + */ +public class Janitor implements Runnable { + public static final int SLEEPMILLIS = 1000; + + private boolean keep_running = true; + + /* + * @see java.lang.Runnable#run() + */ + public void run() { + while (this.keep_running) { + for (Enumeration e = Session.getSessions(); e.hasMoreElements();) { + Session sess = (Session) e.nextElement(); + + // stop inactive sessions + if (System.currentTimeMillis() - sess.getLastActive() > Session.MAX_INACTIVITY * 1000) { + if (JHBServlet.DEBUG) + System.err.println("Session timed out: " + sess.getSID()); + sess.terminate(); + } + } + try { + Thread.sleep(SLEEPMILLIS); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + + public void stop() { + this.keep_running = false; + } + +} \ No newline at end of file diff --git a/src/com/anzsoft/server/JabberHTTPBind/Response.java b/src/com/anzsoft/server/JabberHTTPBind/Response.java new file mode 100644 index 0000000..1c4e650 --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/Response.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2005 Stefan Strigler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ +package com.anzsoft.server.JabberHTTPBind; + +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** + * @author Stefan Strigler + */ +public class Response { + private static TransformerFactory tff = TransformerFactory.newInstance(); + public static final String STATUS_LEAVING = "leaving"; + public static final String STATUS_PENDING = "pending"; + public static final String STATUS_DONE = "done"; + + private long cDate; + private Document doc; + private Element body; + private long rid; + + private String contentType = Session.DEFAULT_CONTENT; + + private String status; + + private HttpServletRequest req; + + private boolean aborted; + + /** + * creates new high level response object specific to http binding + * responses + * + * @param response low level response object + * @param doc empty document to start with + */ + public Response(Document doc) { + this.doc = doc; + + this.body = this.doc.createElement("body"); + this.doc.appendChild(this.body); + + this.body.setAttribute("xmlns","http://jabber.org/protocol/httpbind"); + + this.cDate = System.currentTimeMillis(); + + setStatus(STATUS_PENDING); + } + + public Response(Document doc, HttpServletRequest req) { + this(doc); + this.req = req; + } + + /** + * adds an attribute to request's body element + * + * @param key attribute key + * @param val attribute value + * @return the response + */ + public Response setAttribute(String key, String val) { + this.body.setAttribute(key,val); + return this; + } + + /** + * sets content type header value of low-level response object + * + * @param type the content-type definition e.g. 'text/xml' + * @return the response + */ + public Response setContentType(String type) { + this.contentType = type; + return this; + } + + /** + * adds node as child of replies body element + * + * @param n The node to add + * @return Returns the response again + */ + public Response addNode(Node n, String ns) { + /* make sure we set proper namespace for all nodes + * which must be 'jabber:client' + */ + try { + if (!((Element) n).getAttribute("xmlns").equals(ns)) + ((Element) n).setAttribute("xmlns",ns); + } catch (ClassCastException e) { /* ? skip! */ } + this.body.appendChild(this.doc.importNode(n,true)); + return this; + } + + /** + * sends this response + */ + public synchronized void send(HttpServletResponse response) { + StringWriter strWtr = new StringWriter(); + StreamResult strResult = new StreamResult(strWtr); + try { + Transformer tf = tff.newTransformer(); + tf.setOutputProperty("omit-xml-declaration", "yes"); + tf.transform(new DOMSource(this.doc.getDocumentElement()), strResult); + response.setContentType(this.contentType); + JHBServlet.dbg("sending response ["+this.getRID()+"]: "+strResult.getWriter().toString(),2); + response.getWriter().println(strResult.getWriter().toString()); + JHBServlet.dbg("sent response for "+this.getRID(),3); + } catch (Exception e) { + JHBServlet.dbg("XML.toString(Document): " + e,1); + } + setStatus(STATUS_DONE); + } + /** + * @return Returns the status. + */ + public synchronized String getStatus() { + return status; + } + /** + * @param status The status to set. + */ + public synchronized void setStatus(String status) { + JHBServlet.dbg("response status "+status+" for "+this.getRID(),3); + this.status = status; + } + + public long getRID() { return this.rid; } + + public Response setRID(long rid) { + this.rid = rid; + return this; + } + /** + * @return Returns the cDate. + */ + public synchronized long getCDate() { + return cDate; + } + + /** + * @return the req + */ + public synchronized HttpServletRequest getReq() { + return req; + } + + /** + * @param req the req to set + */ + public synchronized void setReq(HttpServletRequest req) { + this.req = req; + } + + /** + * @return the aborted + */ + public synchronized boolean isAborted() { + return aborted; + } + + /** + * @param aborted the aborted to set + */ + public synchronized void setAborted(boolean aborted) { + this.aborted = aborted; + } +} diff --git a/src/com/anzsoft/server/JabberHTTPBind/SSLSocketReader.java b/src/com/anzsoft/server/JabberHTTPBind/SSLSocketReader.java new file mode 100644 index 0000000..b0075ff --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/SSLSocketReader.java @@ -0,0 +1,70 @@ +/* + * Created on Apr 11, 2004 + */ +package com.anzsoft.server.JabberHTTPBind; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.SocketException; +import java.net.SocketTimeoutException; + +import javax.net.ssl.SSLSocket; + +/** + * @author pau'ie + * + * This class extends BufferedReader to add expected functionality to the ready() method, + * when this class is used on an SSLSocket. An SSLSocket's inputStream will return 0 upon + * a call to available() until a read is performed. + * + * This means that if you construct a bufferedreader for an SSLSocket's inputstream, the ready() + * method will always return false. (This has something to do with just-in-time + * decryption. Might be a bug or a feature) This class overwrites ready() to force a quick read + * to see if the stream has any data available. + * + * Please send comments on whether this introduces security risks to paul@sims.berkeley.edu + */ +public class SSLSocketReader extends BufferedReader +{ + private SSLSocket sock; + + public SSLSocketReader( SSLSocket sock) throws IOException + { + super( new InputStreamReader( sock.getInputStream(), "UTF-8")); + this.sock = sock; + } + + /** + * HACK! + * This method does a quick read from the input stream, to see if data is + * actually available, then resets to the point before the read. + */ + public boolean ready() + { + int oldTimeout; + try { + oldTimeout = sock.getSoTimeout(); + sock.setSoTimeout( 10 ); + + mark(1); + + try { + read(); + } catch (SocketTimeoutException e) { + sock.setSoTimeout(oldTimeout); + return false; + } + + reset(); + sock.setSoTimeout(oldTimeout); + + return true; + + } catch (SocketException e1) { + throw new RuntimeException( "SSLSocketReader unable to set socket timeout: \n" + e1); + } catch (IOException e) { + throw new RuntimeException( "SSLSocketReader unable to access inputstream: \n" + e); + } + } +} diff --git a/src/com/anzsoft/server/JabberHTTPBind/Session.java b/src/com/anzsoft/server/JabberHTTPBind/Session.java new file mode 100644 index 0000000..b30a307 --- /dev/null +++ b/src/com/anzsoft/server/JabberHTTPBind/Session.java @@ -0,0 +1,932 @@ +/* + * Copyright (C) 2005-2006 Stefan Strigler + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +package com.anzsoft.server.JabberHTTPBind; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.StringReader; +import java.io.StringWriter; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.UnknownHostException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +/** + * this class reflects a session within http binding definition + * + * @author Stefan Strigler + */ +public class Session { + + /** + * Default HTTP Content-Type header. + */ + public static final String DEFAULT_CONTENT = "text/xml; charset=utf-8"; + + /** + * Longest allowable inactivity period (in seconds). + */ + public static final int MAX_INACTIVITY = 60; + + /** + * Maximum number of simultaneous requests allowed. + */ + public static final int MAX_REQUESTS = 2; + + /* + * ####### CONSTANTS ####### + */ + + /** + * Default value for longest time (in seconds) that the connection manager + * is allowed to wait before responding to any request during the session. + * This enables the client to prevent its TCP connection from expiring due + * to inactivity, as well as to limit the delay before it discovers any + * network failure. + */ + public static final int MAX_WAIT = 300; + + /** + * Shortest allowable polling interval (in seconds). + */ + public static final int MIN_POLLING = 2; + + /** + * Time to sleep on reading in MSEC. + */ + private static final int READ_TIMEOUT = 1; + + private static final int SOCKET_TIMEOUT = 6000; + + public static final int DEFAULT_XMPPPORT = 5222; + + protected static final String SESS_START = "starting"; + + protected static final String SESS_ACTIVE = "active"; + + protected static final String SESS_TERM = "term"; + + /* + * ####### static ####### + */ + + private static Hashtable sessions = new Hashtable(); + + private static TransformerFactory tff = TransformerFactory.newInstance(); + + private static String createSessionID(int len) { + String charlist = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; + + Random rand = new Random(); + + String str = new String(); + for (int i = 0; i < len; i++) + str += charlist.charAt(rand.nextInt(charlist.length())); + return str; + } + + public static Session getSession(String sid) { + return (Session) sessions.get(sid); + } + + public static Enumeration getSessions() { + return sessions.elements(); + } + + public static int getNumSessions() { + return sessions.size(); + } + + public static void stopSessions() { + for (Enumeration e = sessions.elements(); e.hasMoreElements();) + ((Session) e.nextElement()).terminate(); + } + + /*************************************************************************** + * END static + */ + + private String authid; // stream id given by remote jabber server + + boolean authidSent = false; + + boolean streamFeatures = false; + + private String content = DEFAULT_CONTENT; + + private DocumentBuilder db; + + private int hold = MAX_REQUESTS - 1; + + private String inQueue = ""; + + private BufferedReader br; + + private String key; + + private long lastActive; + + private long lastPoll = 0; + + // private int lastSentRid = 0; + private OutputStreamWriter osw; + + // private TreeMap outQueue; + private TreeMap responses; + + private String status = SESS_START; + + private String sid; + + public Socket sock; + + private String to; + + private DNSUtil.HostAddress host = null; + + private int wait = MAX_WAIT; + + private String xmllang = "en"; + + private boolean reinit = false; + + private boolean secure = false; + + private boolean pauseForHandshake = false; + + private Pattern streamPattern; + + private Pattern stream10Test; + + private Pattern stream10Pattern; + + /** + * Create a new session and connect to jabber server host denoted by + * route or to. + * + * @param to + * domain of the server to connect to. + * @param route + * optional hostname of the server to connect to (might be null). + * + * @throws UnknownHostException + * @throws IOException + */ + public Session(String to, String route) throws UnknownHostException, + IOException { + this.to = to; + + int port = DEFAULT_XMPPPORT; + + this.sock = new Socket(); + this.setLastActive(); + + try { + this.db = DocumentBuilderFactory.newInstance().newDocumentBuilder(); + } catch (Exception e) { + } + + // first, try connecting throught the 'route' attribute. + if (route != null && !route.equals("")) { + JHBServlet.dbg( + "Trying to use 'route' attribute to open a socket...", 3); + if (route.startsWith("xmpp:")) { + route = route.substring("xmpp:".length()); + } + + int i; + // has 'route' the optional port? + if ((i = route.lastIndexOf(":")) != -1) { + try { + int p = Integer.parseInt(route.substring(i + 1)); + if (p >= 0 && p <= 65535) { + port = p; + JHBServlet.dbg( + "...route attribute holds a valid port (" + + port + ").", 3); + } + } catch (NumberFormatException nfe) { + } + + route = route.substring(0, i); + } + + JHBServlet.dbg("Trying to open a socket to '" + route + + "', using port " + port + ".", 3); + + try { + this.sock.connect(new InetSocketAddress(route, port), + SOCKET_TIMEOUT); + } catch (Exception e) { + JHBServlet.dbg( + "Failed to open a socket using the 'route' attribute", + 3); + /* + * none of the exceptions possible should be reason to throw + * anything. If the socket isn't opened, we'll get a retry using + * the 'to' attribute anyway. + */ + } + } + + // If no socket has been opened, try connecting trough the 'to' + // attribute. + if (this.sock == null || !this.sock.isConnected()) { + JHBServlet.dbg("Trying to use 'to' attribute to open a socket...", + 3); + host = DNSUtil.resolveXMPPServerDomain(to, DEFAULT_XMPPPORT); + try { + JHBServlet.dbg("Trying to open a socket to '" + host.getHost() + + "', using port " + host.getPort() + ".", 3); + this.sock.connect(new InetSocketAddress(host.getHost(), host + .getPort()), SOCKET_TIMEOUT); + } catch (UnknownHostException uhe) { + JHBServlet.dbg( + "Failed to open a socket using the 'to' attribute", 3); + throw uhe; + } catch (IOException ioe) { + JHBServlet.dbg( + "Failed to open a socket using the 'to' attribute", 3); + throw ioe; + } + } + + // at this point, we either have a socket, or an exception has already + // been thrown. + + try { + if (this.sock.isConnected()) + JHBServlet.dbg("Succesfully connected to " + to, 2); + + this.sock.setSoTimeout(SOCKET_TIMEOUT); + // instantiate + this.osw = new OutputStreamWriter(this.sock.getOutputStream(), + "UTF-8"); + + this.osw.write(""); + this.osw.flush(); + + // create unique session id + while (sessions.get(this.sid = createSessionID(24)) != null) + ; + + JHBServlet.dbg("creating session with id " + this.sid, 2); + + // register session + sessions.put(this.sid, this); + + // create list of responses + responses = new TreeMap(); + + this.br = new BufferedReader(new InputStreamReader(this.sock + .getInputStream(), "UTF-8")); + + this.streamPattern = Pattern.compile( + ".*]*id=['|\"]([^'|^\"]+)['|\"][^>]*>.*", + Pattern.DOTALL); + + this.stream10Pattern = Pattern + .compile( + ".*]*id=['|\"]([^'|^\"]+)['|\"][^>]*>.*(]*version=['|\"]1.0['|\"][^>]*>.*", + Pattern.DOTALL); + + this.setStatus(SESS_ACTIVE); + } catch (IOException ioe) { + throw ioe; + } + } + + /** + * Adds new response to list of known responses. Truncates list to allowed + * size. + * + * @param r + * the response to add + * @return this session object + */ + public synchronized Response addResponse(Response r) { + while (this.responses.size() > 0 + && this.responses.size() >= Session.MAX_REQUESTS) + this.responses.remove(this.responses.firstKey()); + return (Response) this.responses.put(new Long(r.getRID()), r); + } + + /** + * checks InputStream from server for incoming packets blocks until request + * timeout or packets available + * + * @return nl - NodeList of incoming Nodes + */ + private int init_retry = 0; + + public NodeList checkInQ(long rid) throws IOException { + + NodeList nl = null; + + inQueue += this.readFromSocket(rid); + + JHBServlet.dbg("inQueue: " + inQueue, 2); + + if (init_retry < 1000 && (this.authid == null || this.isReinit()) + && inQueue.length() > 0) { + init_retry++; + if (stream10Test.matcher(inQueue).matches()) { + Matcher m = stream10Pattern.matcher(inQueue); + if (m.matches()) { + this.authid = m.group(1); + inQueue = m.group(2); + JHBServlet.dbg("inQueue: " + inQueue, 2); + /* + * whether there are stream features present we need to + * filter them and strip (start)tls information + */ + streamFeatures = inQueue.length() > 0; + } else { + JHBServlet.dbg("failed to get stream features", 2); + try { + Thread.sleep(5); + } catch (InterruptedException ie) { + } + return this.checkInQ(rid); // retry + } + } else { + // legacy jabber stream + Matcher m = streamPattern.matcher(inQueue); + if (m.matches()) { + this.authid = m.group(1); + } else { + JHBServlet.dbg("failed to get authid", 2); + try { + Thread.sleep(5); + } catch (InterruptedException ie) { + } + return this.checkInQ(rid); // retry + } + } + init_retry = 0; // reset + } + + // try to parse it + if (!inQueue.equals("")) { + try { + /* + * wrap inQueue with element so that multiple nodes can be + * parsed + */ + Document doc = null; + if (streamFeatures) + doc = db.parse(new InputSource(new StringReader("" + + inQueue + ""))); + else + try { + doc = db.parse(new InputSource(new StringReader( + "" + inQueue + + ""))); + } catch (SAXException sex) { + try { + // stream closed? + doc = db.parse(new InputSource(new StringReader( + "" + inQueue))); + this.terminate(); + } catch (SAXException sex2) { + } + } + if (doc != null) + nl = doc.getFirstChild().getChildNodes(); + if (streamFeatures) {// check for starttls + for (int i = 0; i < nl.item(0).getChildNodes().getLength(); i++) { + if (nl.item(0).getChildNodes().item(i).getNodeName() + .equals("starttls")) { + if (!this.isReinit()) { + JHBServlet + .dbg( + "starttls present, trying to use it", + 2); + this.osw + .write(""); + this.osw.flush(); + String response = this.readFromSocket(rid); + JHBServlet.dbg(response, 2); + + try { + SSLSocketFactory sslFact = (SSLSocketFactory) SSLSocketFactory + .getDefault(); + SSLSocket tls; + tls = (SSLSocket) sslFact.createSocket( + this.sock, this.sock + .getInetAddress() + .getHostName(), this.sock + .getPort(), false); + tls + .addHandshakeCompletedListener(new HandShakeFinished( + this)); + this.pauseForHandshake = true; + JHBServlet.dbg("initiating handshake"); + tls.startHandshake(); + try { + while (this.pauseForHandshake) { + JHBServlet.dbg("."); + Thread.sleep(5); + } + } catch (InterruptedException ire) { + } + + JHBServlet.dbg("TLS Handshake complete", 2); + + this.sock = tls; + this.sock.setSoTimeout(SOCKET_TIMEOUT); + + this.br = new SSLSocketReader( + (SSLSocket) tls); + + this.osw = new OutputStreamWriter(tls + .getOutputStream(), "UTF-8"); + + this.inQueue = ""; // reset + this.setReinit(true); + this.osw + .write(""); + this.osw.flush(); + + return this.checkInQ(rid); + } catch (Exception ssle) { + JHBServlet.dbg("STARTTLS failed: " + + ssle.toString(), 1); + this.setReinit(false); + if (this.isSecure()) { + if (!this.sock.getInetAddress() + .getHostName().equals( + "localhost") + && !this + .getResponse(rid) + .getReq() + .getServerName() + .equals( + this.sock + .getInetAddress() + .getHostName())) { + JHBServlet + .dbg( + "secure connection requested but failed", + 2); + throw new IOException(); + } else { + // we trust localhost and hostnames + // that are the same as ours + JHBServlet + .dbg( + "secure requested and we're local", + 1); + } + + } else { + JHBServlet + .dbg( + "tls failed but we don't need to be secure", + 2); + } + if (this.sock.isClosed()) { + JHBServlet.dbg("socket closed", 1); + // reconnect + Socket s = new Socket(); + s.connect(this.sock + .getRemoteSocketAddress(), + SOCKET_TIMEOUT); + this.sock = s; + this.sock.setSoTimeout(SOCKET_TIMEOUT); + this.br = new BufferedReader( + new InputStreamReader(this.sock + .getInputStream(), + "UTF-8")); + this.osw = new OutputStreamWriter( + this.sock.getOutputStream(), + "UTF-8"); + + this.inQueue = ""; // reset + this.setReinit(true); + + this.osw + .write(""); + this.osw.flush(); + + return this.checkInQ(rid); + } + } + } else + nl.item(0).removeChild( + nl.item(0).getChildNodes().item(i)); + } + } + } + inQueue = ""; // reset! + } catch (SAXException sex3) { /* skip this */ + this.setReinit(false); + JHBServlet.dbg("failed to parse inQueue: " + inQueue + "\n" + + sex3.toString(), 1); + return null; + } + } + this.setReinit(false); + this.setLastActive(); + return nl; + } + + private class HandShakeFinished implements + javax.net.ssl.HandshakeCompletedListener { + private Session sess; + + public HandShakeFinished(Session sess) { + this.sess = sess; + } + + public void handshakeCompleted( + javax.net.ssl.HandshakeCompletedEvent event) { + + JHBServlet.dbg("startTLS: Handshake is complete", 2); + + this.sess.pauseForHandshake = false; + return; + } + } + + /** + * Checks whether given request ID is valid within context of this session. + * + * @param rid + * Request ID to be checked + * @return true if rid is valid + */ + public synchronized boolean checkValidRID(long rid) { + try { + if (rid <= ((Long) this.responses.lastKey()).longValue() + + MAX_REQUESTS + && rid >= ((Long) this.responses.firstKey()).longValue()) + return true; + else { + JHBServlet.dbg("invalid request id: " + rid + " (last: " + + ((Long) this.responses.lastKey()).longValue() + ")", + 1); + return false; + } + } catch (NoSuchElementException e) { + return false; + } + } + + public String getAuthid() { + return this.authid; + } + + public String getContent() { + return this.content; + } + + public int getHold() { + return this.hold; + } + + /** + * @return Returns the key. + */ + public synchronized String getKey() { + return key; + } + + /** + * @return Returns the lastActive. + */ + public synchronized long getLastActive() { + return lastActive; + } + + /** + * @return Returns the lastPoll. + */ + public synchronized long getLastPoll() { + return lastPoll; + } + + /** + * lookup response for given request id + * + * @param rid + * Request id associated with response + * @return the response if found, null otherwise + */ + public synchronized Response getResponse(long rid) { + return (Response) this.responses.get(new Long(rid)); + } + + public String getSID() { + return this.sid; + } + + /* + * ######## getters ######### + */ + + public String getTo() { + return this.to; + } + + public int getWait() { + return this.wait; + } + + public String getXMLLang() { + return this.xmllang; + } + + public synchronized int numPendingRequests() { + int num_pending = 0; + Iterator it = this.responses.values().iterator(); + while (it.hasNext()) { + Response r = (Response) it.next(); + if (!r.getStatus().equals(Response.STATUS_DONE)) + num_pending++; + } + return num_pending; + } + + private long lastDoneRID; + + public synchronized long getLastDoneRID() { + return this.lastDoneRID; + } + + /** + * reads from socket + * + * @return string that was read + */ + private String readFromSocket(long rid) throws IOException { + String retval = ""; + char buf[] = new char[16]; + int c = 0; + + Response r = this.getResponse(rid); + + while (!this.sock.isClosed() && !this.isStatus(SESS_TERM)) { + this.setLastActive(); + try { + if (this.br.ready()) { + while (this.br.ready() + && (c = this.br.read(buf, 0, buf.length)) >= 0) + retval += new String(buf, 0, c); + break; // got sth. to send + } else { + if ((this.hold == 0 && r != null && System + .currentTimeMillis() + - r.getCDate() > 200) + || + /* + * makes polling clients feel a little bit more + * responsive + */ + (this.hold > 0 && ((r != null && System + .currentTimeMillis() + - r.getCDate() >= this.getWait() * 1000) + || this.numPendingRequests() > this + .getHold() || !retval.equals(""))) + || r.isAborted()) { + + JHBServlet.dbg("readFromSocket done for " + rid, 3); + break; // time exeeded + } + + try { + Thread.sleep(READ_TIMEOUT); // wait for incoming + // packets + } catch (InterruptedException ie) { + System.err.println(ie.toString()); + } + } + } catch (IOException e) { + System.err.println("Can't read from socket"); + this.terminate(); + } + } + + if (this.sock.isClosed()) { + throw new IOException(); + } + return retval; + } + + /** + * sends all nodes in list to remote jabber server make sure that nodes get + * sent in requested order + * + * @param nl + * list of nodes to send + * @return the session itself + */ + + public Session sendNodes(NodeList nl) { + // build a string + String out = ""; + StreamResult strResult = new StreamResult(); + + try { + Transformer tf = tff.newTransformer(); + tf.setOutputProperty("omit-xml-declaration", "yes"); + // loop list + for (int i = 0; i < nl.getLength(); i++) { + strResult.setWriter(new StringWriter()); + tf.transform(new DOMSource(nl.item(i)), strResult); + String tStr = strResult.getWriter().toString(); + out += tStr; + } + } catch (Exception e) { + JHBServlet.dbg("XML.toString(Document): " + e, 1); + } + + try { + if (this.isReinit()) { + JHBServlet.dbg("Reinitializing Stream!", 2); + this.osw.write(""); + } + this.osw.write(out); + this.osw.flush(); + } catch (IOException ioe) { + JHBServlet.dbg(this.sid + " failed to write to stream", 1); + } + + return this; + } + + public Session setContent(String content) { + this.content = content; + return this; + } + + /* + * ######## setters ######### + */ + + public Session setHold(int hold) { + if (hold < MAX_REQUESTS && hold >= 0) + this.hold = hold; + return this; + } + + /** + * @param key + * The key to set. + */ + public synchronized void setKey(String key) { + this.key = key; + } + + /** + * set lastActive to current timestamp. + */ + public synchronized void setLastActive() { + this.lastActive = System.currentTimeMillis(); + } + + public synchronized void setLastDoneRID(long rid) { + this.lastDoneRID = rid; + } + + /** + * set lastPoll to current timestamp. + */ + public synchronized void setLastPoll() { + this.lastPoll = System.currentTimeMillis(); + } + + public int setWait(int wait) { + if (wait < 0) + wait = 0; + if (wait > MAX_WAIT) + wait = MAX_WAIT; + this.wait = wait; + return wait; + } + + public Session setXMLLang(String xmllang) { + this.xmllang = xmllang; + return this; + } + + /** + * @return Returns the reinit. + */ + public synchronized boolean isReinit() { + return reinit; + } + + /** + * @return the secure + */ + public synchronized boolean isSecure() { + return secure; + } + + /** + * @param reinit + * The reinit to set. + */ + public synchronized void setReinit(boolean reinit) { + this.reinit = reinit; + } + + public synchronized void setStatus(String status) { + this.status = status; + } + + public synchronized boolean isStatus(String status) { + return (this.status == status); + } + + /** + * kill this session + * + */ + public void terminate() { + JHBServlet.dbg("terminating session " + this.getSID(), 2); + this.setStatus(SESS_TERM); + synchronized (this.sock) { + if (!this.sock.isClosed()) { + try { + this.osw.write(""); + this.osw.flush(); + this.sock.close(); + } catch (IOException ie) { + } + } + this.sock.notifyAll(); + } + sessions.remove(this.sid); + } + + /** + * @param secure + * the secure to set + */ + public synchronized void setSecure(boolean secure) { + this.secure = secure; + } + +} diff --git a/tomcat/conf/web.xml b/tomcat/conf/web.xml new file mode 100644 index 0000000..fee85f3 --- /dev/null +++ b/tomcat/conf/web.xml @@ -0,0 +1,566 @@ + + + + + + 30 + + + + abs + audio/x-mpeg + + + ai + application/postscript + + + aif + audio/x-aiff + + + aifc + audio/x-aiff + + + aiff + audio/x-aiff + + + aim + application/x-aim + + + art + image/x-jg + + + asf + video/x-ms-asf + + + asx + video/x-ms-asf + + + au + audio/basic + + + avi + video/x-msvideo + + + avx + video/x-rad-screenplay + + + bcpio + application/x-bcpio + + + bin + application/octet-stream + + + bmp + image/bmp + + + body + text/html + + + cdf + application/x-cdf + + + cer + application/x-x509-ca-cert + + + class + application/java + + + cpio + application/x-cpio + + + csh + application/x-csh + + + css + text/css + + + dib + image/bmp + + + doc + application/msword + + + dtd + text/plain + + + dv + video/x-dv + + + dvi + application/x-dvi + + + eps + application/postscript + + + etx + text/x-setext + + + exe + application/octet-stream + + + gif + image/gif + + + gtar + application/x-gtar + + + gz + application/x-gzip + + + hdf + application/x-hdf + + + hqx + application/mac-binhex40 + + + htc + text/x-component + + + htm + text/html + + + html + text/html + + + hqx + application/mac-binhex40 + + + ief + image/ief + + + jad + text/vnd.sun.j2me.app-descriptor + + + jar + application/java-archive + + + java + text/plain + + + jnlp + application/x-java-jnlp-file + + + jpe + image/jpeg + + + jpeg + image/jpeg + + + jpg + image/jpeg + + + js + text/javascript + + + jsf + text/plain + + + jspf + text/plain + + + kar + audio/x-midi + + + latex + application/x-latex + + + m3u + audio/x-mpegurl + + + mac + image/x-macpaint + + + man + application/x-troff-man + + + me + application/x-troff-me + + + mid + audio/x-midi + + + midi + audio/x-midi + + + mif + application/x-mif + + + mov + video/quicktime + + + movie + video/x-sgi-movie + + + mp1 + audio/x-mpeg + + + mp2 + audio/x-mpeg + + + mp3 + audio/x-mpeg + + + mpa + audio/x-mpeg + + + mpe + video/mpeg + + + mpeg + video/mpeg + + + mpega + audio/x-mpeg + + + mpg + video/mpeg + + + mpv2 + video/mpeg2 + + + ms + application/x-wais-source + + + nc + application/x-netcdf + + + oda + application/oda + + + pbm + image/x-portable-bitmap + + + pct + image/pict + + + pdf + application/pdf + + + pgm + image/x-portable-graymap + + + pic + image/pict + + + pict + image/pict + + + pls + audio/x-scpls + + + png + image/png + + + pnm + image/x-portable-anymap + + + pnt + image/x-macpaint + + + ppm + image/x-portable-pixmap + + + ppt + application/powerpoint + + + ps + application/postscript + + + psd + image/x-photoshop + + + qt + video/quicktime + + + qti + image/x-quicktime + + + qtif + image/x-quicktime + + + ras + image/x-cmu-raster + + + rgb + image/x-rgb + + + rm + application/vnd.rn-realmedia + + + roff + application/x-troff + + + rtf + application/rtf + + + rtx + text/richtext + + + sh + application/x-sh + + + shar + application/x-shar + + + smf + audio/x-midi + + + sit + application/x-stuffit + + + snd + audio/basic + + + src + application/x-wais-source + + + sv4cpio + application/x-sv4cpio + + + sv4crc + application/x-sv4crc + + + swf + application/x-shockwave-flash + + + t + application/x-troff + + + tar + application/x-tar + + + tcl + application/x-tcl + + + tex + application/x-tex + + + texi + application/x-texinfo + + + texinfo + application/x-texinfo + + + tif + image/tiff + + + tiff + image/tiff + + + tr + application/x-troff + + + tsv + text/tab-separated-values + + + txt + text/plain + + + ulw + audio/basic + + + ustar + application/x-ustar + + + xbm + image/x-xbitmap + + + xht + application/xhtml+xml + + + xhtml + application/xhtml+xml + + + xml + text/xml + + + xpm + image/x-xpixmap + + + xsl + text/xml + + + xwd + image/x-xwindowdump + + + wav + audio/x-wav + + + svg + image/svg+xml + + + svgz + image/svg+xml + + + vsd + application/x-visio + + + + wbmp + image/vnd.wap.wbmp + + + + wml + text/vnd.wap.wml + + + + wmlc + application/vnd.wap.wmlc + + + + wmls + text/vnd.wap.wmlscript + + + + wmlscriptc + application/vnd.wap.wmlscriptc + + + wrl + x-world/x-vrml + + + Z + application/x-compress + + + z + application/x-compress + + + zip + application/zip + + diff --git a/tomcat/webapps/ROOT/WEB-INF/web.xml b/tomcat/webapps/ROOT/WEB-INF/web.xml new file mode 100644 index 0000000..e600b2f --- /dev/null +++ b/tomcat/webapps/ROOT/WEB-INF/web.xml @@ -0,0 +1,14 @@ + + + + + shell + com.google.gwt.dev.shell.GWTShellServlet + + + + shell + /* + + + diff --git a/tomcat/work/gwt/localhost/_/SESSIONS.ser b/tomcat/work/gwt/localhost/_/SESSIONS.ser new file mode 100644 index 0000000..e555e0b Binary files /dev/null and b/tomcat/work/gwt/localhost/_/SESSIONS.ser differ diff --git a/tomcat/work/gwt/localhost/_/tldCache.ser b/tomcat/work/gwt/localhost/_/tldCache.ser new file mode 100644 index 0000000..9fa6832 Binary files /dev/null and b/tomcat/work/gwt/localhost/_/tldCache.ser differ diff --git a/www/.gwt-tmp/shell/com.anzsoft.iJab/9CB84EDB480FE0AE074E62C05EE124EB.cache.png b/www/.gwt-tmp/shell/com.anzsoft.iJab/9CB84EDB480FE0AE074E62C05EE124EB.cache.png new file mode 100644 index 0000000..1976d3f Binary files /dev/null and b/www/.gwt-tmp/shell/com.anzsoft.iJab/9CB84EDB480FE0AE074E62C05EE124EB.cache.png differ diff --git a/www/.gwt-tmp/shell/com.anzsoft.iJab/Thumbs.db b/www/.gwt-tmp/shell/com.anzsoft.iJab/Thumbs.db new file mode 100644 index 0000000..74fc0da Binary files /dev/null and b/www/.gwt-tmp/shell/com.anzsoft.iJab/Thumbs.db differ