package de.uni_passau.fim.pkjab.model.xmpp; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.io.OutputStreamWriter; import de.uni_passau.fim.pkjab.model.messages.Message; import de.uni_passau.fim.pkjab.util.Base64; import de.uni_passau.fim.pkjab.util.UserState; public class XMPPWriter { private static final String CLOSE_EMPTY_TAG = "/>"; private static final String CONNECTION_INIT = "<?xml version='1.0' ?><stream:stream to='%s' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>"; private static final String CONNECTION_CLOSE = "</stream:stream>"; private static final String AUTH_START = "<auth mechanism='%s' xmlns='urn:ietf:params:xml:ns:xmpp-sasl'"; private static final String AUTH_RESPONSE = "<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'"; private static final String BIND = "<bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'"; private static final String BIND_RESOURCE = "><resource>%s</resource></bind>"; private static final String SESSION_INIT = "<session xmlns='urn:ietf:params:xml:ns:xmpp-session'/>"; private static final String PRESENCE = "<presence"; private static final String PRESENCE_TYPE = PRESENCE + " type='%s'"; private static final String PRESENCE_SHOW = PRESENCE + "><show>%s</show"; private static final String PRESENCE_STATUS = "><status>%s</status"; private static final String PRESENCE_CLOSE = "></presence>"; private final BufferedWriter writer; private int myId = 0; public XMPPWriter(OutputStream outputStream) throws IllegalArgumentException, IOException { if (outputStream == null) { throw new IllegalArgumentException("Socket required."); } writer = new BufferedWriter(new OutputStreamWriter(outputStream)); } public synchronized void sendInit(String domain) throws IOException { writer.write(String.format(CONNECTION_INIT, domain)); writer.flush(); } public synchronized void sendAuthInit(String mechanism, byte[] initialResponse) throws IOException { writer.write(String.format(AUTH_START, mechanism)); if (initialResponse == null) { writer.write(CLOSE_EMPTY_TAG); } else { writer.write(">"); writer.write(Base64.encodeBytes(initialResponse)); writer.write("</auth>"); } writer.flush(); } public synchronized void sendAuthResponse(byte[] response) throws IOException { writer.write(AUTH_RESPONSE); if (response == null) { writer.write(CLOSE_EMPTY_TAG); } else { writer.write(">"); writer.write(Base64.encodeBytes(response)); writer.write("</response>"); } writer.flush(); } public synchronized void sendBind(String resource) throws IOException { if (resource == null || resource.equals("")) { sendIq("set", BIND + CLOSE_EMPTY_TAG, null, null, null); } else { sendIq("set", BIND + String.format(BIND_RESOURCE, resource), null, null, null); } } public synchronized void sendSessionInit() throws IOException { sendIq("set", SESSION_INIT, null, null, null); } public synchronized void getRoster() throws IOException { sendIqQuery("get", "jabber:iq:roster", "", null, null, null); } public synchronized void sendPresence(UserState state, String text) throws IOException { if (state == UserState.OFFLINE) { writer.write(String.format(PRESENCE_TYPE, state.toXML())); } else if (state == UserState.ONLINE) { writer.write(PRESENCE); } else { writer.write(String.format(PRESENCE_SHOW, state.toXML())); } if (text != null) { writer.write(String.format(PRESENCE_STATUS, text)); } writer.write(PRESENCE_CLOSE); writer.flush(); } public synchronized void sendQuit() throws IOException { // close tags, send quit writer.write(CONNECTION_CLOSE); writer.flush(); } public synchronized void writeRaw(String text) throws IOException { writer.write(text); writer.flush(); } public synchronized void sendIq(String type, String content, String id, String to, String from) throws IOException { StringBuffer sb = new StringBuffer("<iq id='"); if (id == null) sb.append(myId++); else sb.append(id); sb.append("'"); if (to != null) { sb.append(" to='"); sb.append(to); sb.append('\''); } if (from != null) { sb.append(" from='"); sb.append(from); sb.append('\''); } sb.append(" type='"); sb.append(type); sb.append("'>"); sb.append(content); sb.append("</iq>"); writer.write(sb.toString()); writer.flush(); } public synchronized void sendMessage(Message msg) throws IOException { writer.write(msg.toXML()); writer.flush(); } public synchronized void sendIqQuery(String type, String namespace, String content, String id, String to, String from) throws IOException { sendIq(type, String.format("<query xmlns='%s'>%s</query>", namespace, content), id, to, from); } }