MessagePack support for GUI. Woohoo! Still backend errors though; see #5309
git-svn-id: file:///home/svn/framework3/trunk@13616 4d416f70-5f16-0410-b530-b9f4589650daunstable
parent
32eb5d05ba
commit
7a933bdf2c
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -25,10 +25,12 @@ dist.jar=${dist.dir}/msfgui.jar
|
|||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.msgpack-0.5.1-devel.jar=msgpack-0.5.1-devel.jar
|
||||
includes=**
|
||||
jar.compress=false
|
||||
javac.classpath=\
|
||||
${libs.swing-app-framework.classpath}
|
||||
${libs.swing-app-framework.classpath}:\
|
||||
${file.reference.msgpack-0.5.1-devel.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
|
|
|
@ -144,7 +144,7 @@ public class InteractWindow extends MsfFrame implements ClipboardOwner {
|
|||
time = System.currentTimeMillis() - start;
|
||||
if (!received.get("encoding").equals("base64"))
|
||||
throw new MsfException("Uhoh. Unknown encoding. Time to update?");
|
||||
byte[] decodedBytes = Base64.decode(received.get("data").toString());
|
||||
byte[] decodedBytes = RpcConnection.getData(received);
|
||||
if (decodedBytes.length > 0) {
|
||||
outputArea.append(new String(decodedBytes));
|
||||
if(decodedBytes[decodedBytes.length-1] != '\n')
|
||||
|
@ -153,8 +153,7 @@ public class InteractWindow extends MsfFrame implements ClipboardOwner {
|
|||
}
|
||||
publish(received);
|
||||
} catch (MsfException ex) {
|
||||
if(!ex.getMessage().contains("unknown session"))
|
||||
MsfguiApp.showMessage(null, ex);
|
||||
MsfguiApp.showMessage(null, ex);
|
||||
if(!ex.getMessage().contains("timed out")) // on timeout, just retry
|
||||
timerCommand.setCharAt(0, STOP_POLLING);
|
||||
}
|
||||
|
|
|
@ -224,7 +224,7 @@ public class MeterpFileBrowser extends MsfFrame {
|
|||
MsfguiApp.showMessage(null, "uhoh. encoding changed. Time to update msfgui?");
|
||||
return;
|
||||
}
|
||||
byte[] decodedBytes = Base64.decode(received.get("data").toString());
|
||||
byte[] decodedBytes = RpcConnection.getData(received);
|
||||
if (decodedBytes.length == 0)
|
||||
return;
|
||||
String[] lines = new String(decodedBytes).split("\n");
|
||||
|
|
|
@ -53,7 +53,12 @@ public abstract class ModuleInfoWindow extends MsfFrame {
|
|||
Map info = (Map) rpcConn.execute("module.info", moduleType, fullName);
|
||||
//Basic info
|
||||
setTitle(info.get("name") + " " + fullName);
|
||||
try{
|
||||
titleLabel.setText("<html><h2>"+info.get("name")+ "</h2> <b>Rank:</b> "+Rank.toString(info.get("rank"))+"</html>");
|
||||
}
|
||||
catch(Exception ex){
|
||||
System.out.println(info);
|
||||
}
|
||||
Object references = info.get("references");
|
||||
StringBuilder referenceString = new StringBuilder();
|
||||
if(references != null){
|
||||
|
|
|
@ -73,7 +73,7 @@ public class MsfguiApp extends SingleFrameApplication {
|
|||
//get saved properties file
|
||||
Map props;
|
||||
try{
|
||||
props = (Map)RpcConnection.parseVal(DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
props = (Map)XmlRpc.parseVal(DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
.parse(new FileInputStream(confFilename)).getDocumentElement());
|
||||
} catch (Exception ex) { //if anything goes wrong, make new (IOException, SAXException, ParserConfigurationException, NullPointerException
|
||||
props = new HashMap();//ensure existence
|
||||
|
@ -90,7 +90,8 @@ public class MsfguiApp extends SingleFrameApplication {
|
|||
});
|
||||
}
|
||||
public static void showMessage(java.awt.Component parent, Object message){
|
||||
if(!shuttingDown)
|
||||
String msg = message.toString();
|
||||
if(!shuttingDown && !msg.contains("unknown session"))
|
||||
JOptionPane.showMessageDialog(parent, message);
|
||||
}
|
||||
|
||||
|
@ -100,7 +101,7 @@ public class MsfguiApp extends SingleFrameApplication {
|
|||
public static void savePreferences(){
|
||||
try {
|
||||
Document docElement = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
docElement.appendChild(RpcConnection.objectToNode(docElement, propRoot));
|
||||
docElement.appendChild(XmlRpc.objectToNode(docElement, propRoot));
|
||||
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(docElement), new StreamResult(new FileOutputStream(confFilename)));
|
||||
} catch (Exception ex) {
|
||||
//fail
|
||||
|
|
|
@ -100,11 +100,9 @@ public class MsfguiLog {
|
|||
}
|
||||
//New data on existing sessions
|
||||
} else if (methodName.equals("console.read")) {
|
||||
String resString = new String(Base64.decode(((Map) result).get("data").toString()));
|
||||
logConsole("Console " + params[0], resString, false);
|
||||
logConsole("Console " + params[0], new String(RpcConnection.getData((Map)result)), false);
|
||||
} else if (methodName.startsWith("session.") && methodName.endsWith("_read")) {
|
||||
String resString = new String(Base64.decode(((Map) result).get("data").toString()));
|
||||
logConsole(params[0].toString(), resString, false);
|
||||
logConsole(params[0].toString(), new String(RpcConnection.getData((Map)result)), false);
|
||||
}
|
||||
} catch (MsfException mex) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package msfgui;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.msgpack.MessagePack;
|
||||
import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.object.*;
|
||||
|
||||
/**
|
||||
* Implements an RPC backend using the MessagePack interface
|
||||
* @author scriptjunkie
|
||||
*/
|
||||
public class MsgRpc extends RpcConnection {
|
||||
private URL u;
|
||||
private URLConnection huc; // new for each call
|
||||
protected int timeout = 5000;
|
||||
|
||||
/**
|
||||
* Creates a new URL to use as the basis of a connection.
|
||||
*/
|
||||
protected void connect() throws MalformedURLException{
|
||||
u = new URL("http",host,port,"/api");
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes a response recursively from MessagePackObject to a normal Java object
|
||||
* @param src MessagePack response
|
||||
* @return decoded object
|
||||
*/
|
||||
private static Object unMsg(Object src){
|
||||
Object out = src;
|
||||
if(src instanceof ArrayType){
|
||||
List l = ((ArrayType)src).asList();
|
||||
List outList = new ArrayList(l.size());
|
||||
out = outList;
|
||||
for(Object o : l)
|
||||
outList.add(unMsg(o));
|
||||
}else if(src instanceof BooleanType){
|
||||
out = ((BooleanType)src).asBoolean();
|
||||
}else if(src instanceof FloatType){
|
||||
out = ((FloatType)src).asFloat();
|
||||
}else if(src instanceof IntegerType){
|
||||
out = ((IntegerType)src).asInt();
|
||||
}else if(src instanceof MapType){
|
||||
Set ents = ((MapType)src).asMap().entrySet();
|
||||
out = new HashMap();
|
||||
for (Object ento : ents){
|
||||
Map.Entry ent = (Map.Entry)ento;
|
||||
((Map)out).put(unMsg(ent.getKey()), unMsg(ent.getValue()));
|
||||
}
|
||||
if(((Map)out).containsKey("error") && ((Map)out).containsKey("error_class")){
|
||||
System.out.println(((Map)out).get("error_backtrace"));
|
||||
throw new MsfException(((Map)out).get("error_message").toString());
|
||||
}
|
||||
}else if(src instanceof NilType){
|
||||
out = null;
|
||||
}else if(src instanceof RawType){
|
||||
out = ((RawType)src).asString();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Creates an XMLRPC call from the given method name and parameters and sends it */
|
||||
protected void writeCall(String methodName, Object[] args) throws Exception{
|
||||
huc = u.openConnection();
|
||||
huc.setDoOutput(true);
|
||||
huc.setDoInput(true);
|
||||
huc.setUseCaches(false);
|
||||
huc.setRequestProperty("Content-Type", "binary/message-pack");
|
||||
huc.setReadTimeout(timeout);
|
||||
OutputStream os = huc.getOutputStream();
|
||||
Packer pk = new Packer(os);
|
||||
|
||||
pk.packArray(args.length+1);
|
||||
pk.pack(methodName);
|
||||
for(Object o : args)
|
||||
pk.pack(o);
|
||||
os.close();
|
||||
}
|
||||
|
||||
/** Receives an RPC response and converts to an object */
|
||||
protected Object readResp() throws Exception{
|
||||
InputStream is = huc.getInputStream();
|
||||
MessagePackObject mpo = MessagePack.unpack(is);
|
||||
return unMsg(mpo);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
<?xml version="1.1" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<Properties>
|
||||
<Property name="defaultCloseOperation" type="int" value="2"/>
|
||||
<Property name="title" type="java.lang.String" resourceKey="Form.title"/>
|
||||
|
@ -44,7 +48,13 @@
|
|||
<Component id="hostField" alignment="0" pref="427" max="32767" attributes="0"/>
|
||||
<Component id="passwordField" alignment="0" pref="427" max="32767" attributes="0"/>
|
||||
<Component id="portField" alignment="0" pref="427" max="32767" attributes="0"/>
|
||||
<Component id="sslBox" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="sslBox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="250" max="32767" attributes="0"/>
|
||||
<Component id="xmlButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="msgpackButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
|
@ -87,14 +97,22 @@
|
|||
<Component id="portLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="sslBox" alignment="0" min="0" pref="0" max="32767" attributes="1"/>
|
||||
<Component id="sslLabel" alignment="0" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="disableDbLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="disableDbButton" alignment="3" min="-2" pref="18" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="sslBox" alignment="0" min="0" pref="0" max="32767" attributes="1"/>
|
||||
<Component id="sslLabel" alignment="0" max="32767" attributes="1"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="disableDbLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="disableDbButton" alignment="3" min="-2" pref="18" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="msgpackButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="xmlButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
|
@ -250,5 +268,24 @@
|
|||
<Property name="name" type="java.lang.String" value="disableDbButton" noResource="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="xmlButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
<Property name="selected" type="boolean" value="true"/>
|
||||
<Property name="text" type="java.lang.String" resourceKey="xmlButton.text"/>
|
||||
<Property name="name" type="java.lang.String" value="xmlButton" noResource="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="msgpackButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="buttonGroup1"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" resourceKey="msgpackButton.text"/>
|
||||
<Property name="name" type="java.lang.String" value="msgpackButton" noResource="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
|
|
@ -103,7 +103,8 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
String host = info.get("host").toString();
|
||||
int port = Integer.parseInt(info.get("port").toString());
|
||||
boolean ssl = Boolean.parseBoolean(info.get("ssl").toString());
|
||||
RpcConnection rpc = new RpcConnection(username, password.toCharArray(), host, port, ssl);
|
||||
String type = info.get("type").toString();
|
||||
RpcConnection rpc = RpcConnection.getConn(type, username, password.toCharArray(), host, port, ssl);
|
||||
if(javax.swing.JOptionPane.showConfirmDialog(null, "Connect to last remembered rpcd?") == javax.swing.JOptionPane.YES_OPTION)
|
||||
return rpc;
|
||||
rpc.execute("auth.logout");
|
||||
|
@ -118,6 +119,7 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
mainframe.statusAnimationLabel.setText("Timeout; is the SSL option correct?"
|
||||
+ " Is msfrpcd running on the right port?");
|
||||
} catch (NullPointerException nex) {//generated when attributes dont exist.
|
||||
} catch (Exception ex) { //for weird msg exceptions
|
||||
}
|
||||
//Darn. open the gui anyway
|
||||
OpenConnectionDialog diag = new OpenConnectionDialog(true, mainframe);
|
||||
|
@ -134,6 +136,7 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
titleLabel = new javax.swing.JLabel();
|
||||
usernameLabel = new javax.swing.JLabel();
|
||||
passwordLabel = new javax.swing.JLabel();
|
||||
|
@ -151,6 +154,8 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
sslLabel = new javax.swing.JLabel();
|
||||
disableDbLabel = new javax.swing.JLabel();
|
||||
disableDbButton = new javax.swing.JCheckBox();
|
||||
xmlButton = new javax.swing.JRadioButton();
|
||||
msgpackButton = new javax.swing.JRadioButton();
|
||||
|
||||
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
|
||||
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(msfgui.MsfguiApp.class).getContext().getResourceMap(OpenConnectionDialog.class);
|
||||
|
@ -250,6 +255,15 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
disableDbButton.setText(resourceMap.getString("disableDbButton.text")); // NOI18N
|
||||
disableDbButton.setName("disableDbButton"); // NOI18N
|
||||
|
||||
buttonGroup1.add(xmlButton);
|
||||
xmlButton.setSelected(true);
|
||||
xmlButton.setText(resourceMap.getString("xmlButton.text")); // NOI18N
|
||||
xmlButton.setName("xmlButton"); // NOI18N
|
||||
|
||||
buttonGroup1.add(msgpackButton);
|
||||
msgpackButton.setText(resourceMap.getString("msgpackButton.text")); // NOI18N
|
||||
msgpackButton.setName("msgpackButton"); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
|
||||
getContentPane().setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
|
@ -274,7 +288,12 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
.addComponent(hostField, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addComponent(passwordField, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addComponent(portField, javax.swing.GroupLayout.DEFAULT_SIZE, 427, Short.MAX_VALUE)
|
||||
.addComponent(sslBox)))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(sslBox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 250, Short.MAX_VALUE)
|
||||
.addComponent(xmlButton)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(msgpackButton))))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(startNewButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
|
@ -307,13 +326,18 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
.addComponent(portField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(portLabel))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(sslBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE)
|
||||
.addComponent(sslLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(disableDbLabel)
|
||||
.addComponent(disableDbButton, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(sslBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 0, Short.MAX_VALUE)
|
||||
.addComponent(sslLabel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(disableDbLabel)
|
||||
.addComponent(disableDbButton, javax.swing.GroupLayout.PREFERRED_SIZE, 18, javax.swing.GroupLayout.PREFERRED_SIZE)))
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(msgpackButton)
|
||||
.addComponent(xmlButton)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(connectButton, javax.swing.GroupLayout.DEFAULT_SIZE, 37, Short.MAX_VALUE)
|
||||
|
@ -332,8 +356,15 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
String host = hostField.getText();
|
||||
int port = Integer.parseInt(portField.getText());
|
||||
boolean ssl = checkCrypto(sslBox.isSelected());
|
||||
String type = "xml";
|
||||
if(msgpackButton.isSelected()){
|
||||
if(JOptionPane.showConfirmDialog(this, "MsgPack RPC is not currently supported. Continue anyway?",
|
||||
"Warning",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION)
|
||||
return;
|
||||
type = "msg";
|
||||
}
|
||||
try {
|
||||
rpcConn = new RpcConnection(username, password, host, port, ssl);
|
||||
rpcConn = RpcConnection.getConn(type, username, password, host, port, ssl);
|
||||
} catch (MsfException mex) {
|
||||
rpcConn = null;
|
||||
}
|
||||
|
@ -363,6 +394,14 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
|
||||
private void startNewButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startNewButtonActionPerformed
|
||||
//Setup defaults
|
||||
if(msgpackButton.isSelected()){
|
||||
if(JOptionPane.showConfirmDialog(this, "MsgPack RPC is not currently supported. Continue anyway?",
|
||||
"Warning",JOptionPane.YES_NO_CANCEL_OPTION,JOptionPane.WARNING_MESSAGE) != JOptionPane.YES_OPTION)
|
||||
return;
|
||||
RpcConnection.defaultType = "msg";
|
||||
}else{
|
||||
RpcConnection.defaultType = "xml";
|
||||
}
|
||||
RpcConnection.defaultUser = usernameField.getText();
|
||||
if(passwordField.getPassword().length > 0)
|
||||
RpcConnection.defaultPass = new String(passwordField.getPassword());
|
||||
|
@ -396,12 +435,14 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
}//GEN-LAST:event_pathButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JButton connectButton;
|
||||
private javax.swing.JCheckBox disableDbButton;
|
||||
private javax.swing.JLabel disableDbLabel;
|
||||
private javax.swing.JTextField hostField;
|
||||
private javax.swing.JLabel hostLabel;
|
||||
private javax.swing.JRadioButton msgpackButton;
|
||||
private javax.swing.JPasswordField passwordField;
|
||||
private javax.swing.JLabel passwordLabel;
|
||||
private javax.swing.JButton pathButton;
|
||||
|
@ -413,5 +454,6 @@ public class OpenConnectionDialog extends javax.swing.JDialog {
|
|||
private javax.swing.JLabel titleLabel;
|
||||
private javax.swing.JTextField usernameField;
|
||||
private javax.swing.JLabel usernameLabel;
|
||||
private javax.swing.JRadioButton xmlButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public class ProcessList extends MsfFrame {
|
|||
MsfguiApp.showMessage(null, "uhoh. encoding changed. Time to update msfgui?");
|
||||
return;
|
||||
}
|
||||
byte[] decodedBytes = Base64.decode(received.get("data").toString());
|
||||
byte[] decodedBytes = RpcConnection.getData(received);
|
||||
if (decodedBytes.length == 0)
|
||||
return; //no data
|
||||
String[] lines = new String(decodedBytes).split("\n");
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package msfgui;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -10,54 +8,78 @@ import java.net.SocketException;
|
|||
import java.security.KeyManagementException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import org.jdesktop.application.Task;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
/**
|
||||
* RpcConnection handles connection details to a msfrpcd and automatically sends
|
||||
* activity to be logged. It also caches some method calls to more quickly
|
||||
* retrieve results later.
|
||||
*
|
||||
* Implements a minimal XMLRPC client for our purposes. Reinventing the wheel is
|
||||
* usually a bad idea, but CVE/description searching takes a long time and this
|
||||
* implementation runs a CVE search twice as fast as the apache libs. It also
|
||||
* results in a more responsive console.
|
||||
*
|
||||
* Connection implementation is left to child classes, which must implemtent
|
||||
* writeCall() and readResp() and may implement connect.
|
||||
*
|
||||
* @author scriptjunkie
|
||||
*/
|
||||
public class RpcConnection {
|
||||
private String rpcToken;
|
||||
private Map callCache = new HashMap();
|
||||
public static String defaultUser = "msf",defaultPass = null, defaultHost = "127.0.0.1";
|
||||
public abstract class RpcConnection {
|
||||
public String type = "msg";
|
||||
protected String rpcToken;
|
||||
protected Map callCache = new HashMap();
|
||||
public static String defaultUser = "msf",defaultPass = null, defaultHost = "127.0.0.1", defaultType = "msg";
|
||||
public static int defaultPort = 55553;
|
||||
public static boolean defaultSsl = false;
|
||||
public static boolean disableDb = false;
|
||||
private Socket connection;
|
||||
private OutputStream sout; //socket output/input
|
||||
private InputStream sin;
|
||||
private final Object lockObject = new Object();//to synchronize one request at a time
|
||||
private String username, password, host;
|
||||
private int port;
|
||||
private boolean ssl;
|
||||
protected Socket connection;
|
||||
protected OutputStream sout; //socket output/input
|
||||
protected InputStream sin;
|
||||
protected final Object lockObject = new Object();//to synchronize one request at a time
|
||||
protected String username, password, host;
|
||||
protected int port;
|
||||
protected boolean ssl;
|
||||
|
||||
/** Constructor sets up a connection and authenticates. */
|
||||
RpcConnection(String username, char[] password, String host, int port, boolean ssl) throws MsfException {
|
||||
protected abstract void writeCall(String methname, Object[] params) throws Exception;
|
||||
protected abstract Object readResp() throws Exception;
|
||||
|
||||
/**
|
||||
* Creates an RPC connection of the appropriate type and connection details
|
||||
* @param type RPC type
|
||||
* @param username
|
||||
* @param password
|
||||
* @param host IP address or hostname of RPC server
|
||||
* @param port Port RPC server is operating on
|
||||
* @param ssl Whether SSL is to be used
|
||||
* @return A new RPC connection
|
||||
* @throws MsfException
|
||||
*/
|
||||
public static RpcConnection getConn(String type, String username, char[] password, String host, int port, boolean ssl) throws MsfException{
|
||||
RpcConnection conn;
|
||||
if(type.toLowerCase().equals("xml"))
|
||||
conn = new XmlRpc();
|
||||
else
|
||||
conn = new MsgRpc();
|
||||
conn.setup(username, password, host, port, ssl);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unencoded data returned from a something.read call
|
||||
* @param ret The return from the read call
|
||||
* @return the
|
||||
*/
|
||||
public static byte[] getData(Map received){
|
||||
if(received.get("encoding").equals("base64"))
|
||||
return Base64.decode(received.get("data").toString());
|
||||
else
|
||||
return received.get("data").toString().getBytes();
|
||||
}
|
||||
|
||||
/** Setup sets up a connection and authenticates. */
|
||||
public void setup(String username, char[] password, String host, int port, boolean ssl) throws MsfException {
|
||||
boolean haveRpcd=false;
|
||||
this.username = username;
|
||||
this.password = new String(password);
|
||||
|
@ -87,9 +109,20 @@ public class RpcConnection {
|
|||
root.put("port", port);
|
||||
root.put("ssl", ssl);
|
||||
root.put("disableDb", disableDb);
|
||||
root.put("type", type);
|
||||
MsfguiApp.savePreferences();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects this connection
|
||||
*
|
||||
* @throws SocketException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void disconnect() throws SocketException, IOException{
|
||||
connection.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disconnects then reconnects.
|
||||
*
|
||||
|
@ -98,20 +131,20 @@ public class RpcConnection {
|
|||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
private void reconnect() throws SocketException, KeyManagementException, IOException, NoSuchAlgorithmException {
|
||||
connection.close();
|
||||
protected void reconnect() throws SocketException, KeyManagementException, IOException, NoSuchAlgorithmException {
|
||||
disconnect();
|
||||
connect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Connects the TCP stream, setting up SSL if necessary.
|
||||
* Default connect method connects the TCP stream, setting up SSL if necessary.
|
||||
*
|
||||
* @throws SocketException
|
||||
* @throws KeyManagementException
|
||||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
private void connect() throws SocketException, KeyManagementException, IOException, NoSuchAlgorithmException {
|
||||
protected void connect() throws SocketException, KeyManagementException, IOException, NoSuchAlgorithmException {
|
||||
if (ssl) {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
|
@ -136,6 +169,7 @@ public class RpcConnection {
|
|||
|
||||
public String toString(){
|
||||
return "RPC connection "
|
||||
+ "\ntype: "+type
|
||||
+ "\nusername: "+username
|
||||
+ "\npassword: " + password
|
||||
+ "\nhost: " + host
|
||||
|
@ -207,174 +241,6 @@ public class RpcConnection {
|
|||
}
|
||||
}
|
||||
|
||||
/** Creates an XMLRPC call from the given method name and parameters and sends it */
|
||||
protected void writeCall(String methname, Object[] params) throws Exception{
|
||||
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
Element methodCall = doc.createElement("methodCall");
|
||||
doc.appendChild(methodCall);
|
||||
Element methodName = doc.createElement("methodName");
|
||||
methodName.appendChild(doc.createTextNode(methname));
|
||||
methodCall.appendChild(methodName);
|
||||
Element paramsEl = doc.createElement("params");
|
||||
methodCall.appendChild(paramsEl);
|
||||
//Add each parameter by type. Usually just the maps are difficult
|
||||
for(Object param : params){
|
||||
Element paramEl = doc.createElement("param");
|
||||
paramEl.appendChild(objectToNode(doc,param));
|
||||
paramsEl.appendChild(paramEl);
|
||||
}
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(bout));
|
||||
sout.write(bout.toByteArray());
|
||||
sout.write(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the object provided and recursively creates a node out of it suitable
|
||||
* for xmlrpc transmission.
|
||||
* @param doc
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
public static Node objectToNode(Document doc, Object param){
|
||||
Node valEl = doc.createElement("value");
|
||||
if(param instanceof Map){ //Reverse of the parseVal() struct-to-HashMap code
|
||||
Element structEl = doc.createElement("struct");
|
||||
for(Object entryObj : ((Map)param).entrySet()){
|
||||
Map.Entry ent = (Map.Entry)entryObj;
|
||||
Element membEl = doc.createElement("member");
|
||||
Element nameEl = doc.createElement("name");
|
||||
nameEl.appendChild(doc.createTextNode(ent.getKey().toString()));
|
||||
membEl.appendChild(nameEl);
|
||||
membEl.appendChild(objectToNode(doc,ent.getValue()));
|
||||
structEl.appendChild(membEl);
|
||||
}
|
||||
valEl.appendChild(structEl);
|
||||
}else if(param instanceof List || param instanceof Object[]){ //Reverse of the parseVal() array-to-HashMap code
|
||||
Element arrayEl = doc.createElement("array");
|
||||
Element dataEl = doc.createElement("data");
|
||||
if(param instanceof Object[])
|
||||
for(Object obj : (Object[])param)
|
||||
dataEl.appendChild(objectToNode(doc,obj));
|
||||
else
|
||||
for(Object obj : (List)param)
|
||||
dataEl.appendChild(objectToNode(doc,obj));
|
||||
arrayEl.appendChild(dataEl);
|
||||
valEl.appendChild(arrayEl);
|
||||
}else if(param instanceof Integer){ //not sure I even need this
|
||||
Element i4El = doc.createElement("i4");
|
||||
i4El.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(i4El);
|
||||
}else if(param instanceof Boolean){ //not sure I even need this
|
||||
Element boolEl = doc.createElement("boolean");
|
||||
boolEl.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(boolEl);
|
||||
}else{
|
||||
Element strEl = doc.createElement("string");
|
||||
strEl.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(strEl);
|
||||
}
|
||||
return valEl;
|
||||
}
|
||||
|
||||
/** Receives an XMLRPC response and converts to an object */
|
||||
protected Object readResp() throws Exception{
|
||||
//Will store our response
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len;
|
||||
do{
|
||||
//read bytes
|
||||
ByteArrayOutputStream cache = new ByteArrayOutputStream();
|
||||
int val;
|
||||
while((val = sin.read()) != 0){
|
||||
if(val == -1)
|
||||
throw new MsfException("Stream died.");
|
||||
cache.write(val);
|
||||
}
|
||||
//parse the response: <methodResponse><params><param><value>...
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(cache.toByteArray());
|
||||
int a = is.read();
|
||||
while(a != -1){
|
||||
if(!Character.isISOControl(a) || a == '\t')
|
||||
sb.append((char)a);
|
||||
//else
|
||||
// sb.append("&#x").append(Integer.toHexString(a)).append(';');
|
||||
a = is.read();
|
||||
}
|
||||
len = sb.length();//Check to make sure we aren't stopping on an embedded null
|
||||
} while (sb.lastIndexOf("</methodResponse>") < len - 20 || len < 30);
|
||||
Document root = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
.parse(new ByteArrayInputStream(sb.toString().getBytes()));
|
||||
|
||||
if(!root.getFirstChild().getNodeName().equals("methodResponse"))
|
||||
throw new MsfException("Error reading response: not a response.");
|
||||
Node methResp = root.getFirstChild();
|
||||
if(methResp.getFirstChild().getNodeName().equals("fault")){
|
||||
throw new MsfException(methResp.getFirstChild()//fault
|
||||
.getFirstChild() // value
|
||||
.getFirstChild() // struct
|
||||
.getLastChild() // member
|
||||
.getLastChild() // value
|
||||
.getTextContent());
|
||||
}
|
||||
Node params = methResp.getFirstChild();
|
||||
if(!params.getNodeName().equals("params"))
|
||||
throw new MsfException("Error reading response: no params.");
|
||||
Node param = params.getFirstChild();
|
||||
if(!param.getNodeName().equals("param"))
|
||||
throw new MsfException("Error reading response: no param.");
|
||||
Node value = param.getFirstChild();
|
||||
if(!value.getNodeName().equals("value"))
|
||||
throw new MsfException("Error reading response: no value.");
|
||||
return parseVal(value);
|
||||
}
|
||||
|
||||
/** Takes an XMLRPC DOM value node and creates a java object out of it recursively */
|
||||
public static Object parseVal(Node submemb) throws MsfException {
|
||||
Node type = submemb.getFirstChild();
|
||||
String typeName = type.getNodeName();
|
||||
if(typeName.equals("string")){//<struct><member><name>jobs</name><value><struct/></value></member></struct>
|
||||
return type.getTextContent(); //String returns java string
|
||||
}else if (typeName.equals("array")){ //Array returns List
|
||||
ArrayList arrgh = new ArrayList();
|
||||
Node data = type.getFirstChild();
|
||||
if(!data.getNodeName().equals("data"))
|
||||
throw new MsfException("Error reading array: no data.");
|
||||
for(Node val = data.getFirstChild(); val != null; val = val.getNextSibling())
|
||||
arrgh.add(parseVal(val));
|
||||
return arrgh;
|
||||
}else if (typeName.equals("struct")){ //Struct returns a HashMap of name->value member pairs
|
||||
HashMap structmembs = new HashMap();
|
||||
for(Node member = type.getFirstChild(); member != null; member = member.getNextSibling()){
|
||||
if(!member.getNodeName().equals("member"))
|
||||
throw new MsfException("Error reading response: non struct member.");
|
||||
Object name = null, membValue = null;
|
||||
//get each member and put into output map
|
||||
for(Node submember = member.getFirstChild(); submember != null; submember = submember.getNextSibling()){
|
||||
if(submember.getNodeName().equals("name"))
|
||||
name = submember.getTextContent();
|
||||
else if (submember.getNodeName().equals("value"))
|
||||
membValue = parseVal(submember); //Value can be arbitrarily complex
|
||||
}
|
||||
structmembs.put(name, membValue);
|
||||
}
|
||||
return structmembs;
|
||||
}else if (typeName.equals("i4")){
|
||||
return new Integer(type.getTextContent());
|
||||
}else if (typeName.equals("boolean")){
|
||||
return type.getTextContent().equals("1") || Boolean.valueOf(type.getTextContent());
|
||||
}else if (typeName.equals("dateTime.iso8601")) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
|
||||
try{
|
||||
return sdf.parse(type.getTextContent());
|
||||
}catch(ParseException pex){
|
||||
return type.getTextContent();
|
||||
}
|
||||
} else {
|
||||
throw new MsfException("Error reading val: unknown type " + typeName);
|
||||
}
|
||||
}
|
||||
|
||||
/** Attempts to start msfrpcd and connect to it.*/
|
||||
public static Task startRpcConn(final MainFrame mainFrame){
|
||||
if(mainFrame.rpcConn != null){
|
||||
|
@ -397,8 +263,11 @@ public class RpcConnection {
|
|||
}
|
||||
|
||||
// Don't fork cause we'll check if it dies
|
||||
String rpcType = "Basic";
|
||||
if(defaultType.toLowerCase().equals("msg"))
|
||||
rpcType = "Msg";
|
||||
java.util.List args = new java.util.ArrayList(java.util.Arrays.asList(new String[]{
|
||||
"msfrpcd","-f","-P",defaultPass,"-t","Basic","-U",defaultUser,"-a","127.0.0.1"}));
|
||||
"msfrpcd","-f","-P",defaultPass,"-t",rpcType,"-U",defaultUser,"-a","127.0.0.1"}));
|
||||
if(!defaultSsl)
|
||||
args.add("-S");
|
||||
if(disableDb)
|
||||
|
@ -426,7 +295,7 @@ public class RpcConnection {
|
|||
} //Nope. We're good.
|
||||
|
||||
try {
|
||||
myRpcConn = new RpcConnection(defaultUser, defaultPass.toCharArray(), "127.0.0.1", defaultPort, defaultSsl);
|
||||
myRpcConn = RpcConnection.getConn(defaultType, defaultUser, defaultPass.toCharArray(), "127.0.0.1", defaultPort, defaultSsl);
|
||||
connected = true;
|
||||
break;
|
||||
} catch (MsfException mex) {
|
||||
|
|
|
@ -0,0 +1,205 @@
|
|||
package msfgui;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
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;
|
||||
|
||||
/**
|
||||
* XMLRPC implementation of an RpcConnection.
|
||||
*
|
||||
* Implements a minimal XMLRPC client for our purposes. Reinventing the wheel is
|
||||
* usually a bad idea, but CVE/description searching takes a long time and this
|
||||
* implementation runs a CVE search twice as fast as the apache libs. It also
|
||||
* results in a more responsive console.
|
||||
*
|
||||
* @author scriptjunkie
|
||||
*/
|
||||
public class XmlRpc extends RpcConnection {
|
||||
|
||||
/**
|
||||
* We're an XML RPC
|
||||
*/
|
||||
public XmlRpc(){
|
||||
super();
|
||||
type = "XML";
|
||||
}
|
||||
/** Creates an XMLRPC call from the given method name and parameters and sends it */
|
||||
protected void writeCall(String methname, Object[] params) throws Exception{
|
||||
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
Element methodCall = doc.createElement("methodCall");
|
||||
doc.appendChild(methodCall);
|
||||
Element methodName = doc.createElement("methodName");
|
||||
methodName.appendChild(doc.createTextNode(methname));
|
||||
methodCall.appendChild(methodName);
|
||||
Element paramsEl = doc.createElement("params");
|
||||
methodCall.appendChild(paramsEl);
|
||||
//Add each parameter by type. Usually just the maps are difficult
|
||||
for(Object param : params){
|
||||
Element paramEl = doc.createElement("param");
|
||||
paramEl.appendChild(objectToNode(doc,param));
|
||||
paramsEl.appendChild(paramEl);
|
||||
}
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
TransformerFactory.newInstance().newTransformer().transform(new DOMSource(doc), new StreamResult(bout));
|
||||
sout.write(bout.toByteArray());
|
||||
sout.write(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the object provided and recursively creates a node out of it suitable
|
||||
* for xmlrpc transmission.
|
||||
* @param doc
|
||||
* @param param
|
||||
* @return
|
||||
*/
|
||||
public static Node objectToNode(Document doc, Object param){
|
||||
Node valEl = doc.createElement("value");
|
||||
if(param instanceof Map){ //Reverse of the parseVal() struct-to-HashMap code
|
||||
Element structEl = doc.createElement("struct");
|
||||
for(Object entryObj : ((Map)param).entrySet()){
|
||||
Map.Entry ent = (Map.Entry)entryObj;
|
||||
Element membEl = doc.createElement("member");
|
||||
Element nameEl = doc.createElement("name");
|
||||
nameEl.appendChild(doc.createTextNode(ent.getKey().toString()));
|
||||
membEl.appendChild(nameEl);
|
||||
membEl.appendChild(objectToNode(doc,ent.getValue()));
|
||||
structEl.appendChild(membEl);
|
||||
}
|
||||
valEl.appendChild(structEl);
|
||||
}else if(param instanceof List || param instanceof Object[]){ //Reverse of the parseVal() array-to-HashMap code
|
||||
Element arrayEl = doc.createElement("array");
|
||||
Element dataEl = doc.createElement("data");
|
||||
if(param instanceof Object[])
|
||||
for(Object obj : (Object[])param)
|
||||
dataEl.appendChild(objectToNode(doc,obj));
|
||||
else
|
||||
for(Object obj : (List)param)
|
||||
dataEl.appendChild(objectToNode(doc,obj));
|
||||
arrayEl.appendChild(dataEl);
|
||||
valEl.appendChild(arrayEl);
|
||||
}else if(param instanceof Integer){ //not sure I even need this
|
||||
Element i4El = doc.createElement("i4");
|
||||
i4El.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(i4El);
|
||||
}else if(param instanceof Boolean){ //not sure I even need this
|
||||
Element boolEl = doc.createElement("boolean");
|
||||
boolEl.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(boolEl);
|
||||
}else{
|
||||
Element strEl = doc.createElement("string");
|
||||
strEl.appendChild(doc.createTextNode(param.toString()));
|
||||
valEl.appendChild(strEl);
|
||||
}
|
||||
return valEl;
|
||||
}
|
||||
|
||||
/** Receives an XMLRPC response and converts to an object */
|
||||
protected Object readResp() throws Exception{
|
||||
//Will store our response
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int len;
|
||||
do{
|
||||
//read bytes
|
||||
ByteArrayOutputStream cache = new ByteArrayOutputStream();
|
||||
int val;
|
||||
while((val = sin.read()) != 0){
|
||||
if(val == -1)
|
||||
throw new MsfException("Stream died.");
|
||||
cache.write(val);
|
||||
}
|
||||
//parse the response: <methodResponse><params><param><value>...
|
||||
ByteArrayInputStream is = new ByteArrayInputStream(cache.toByteArray());
|
||||
int a = is.read();
|
||||
while(a != -1){
|
||||
if(!Character.isISOControl(a) || a == '\t')
|
||||
sb.append((char)a);
|
||||
//else
|
||||
// sb.append("&#x").append(Integer.toHexString(a)).append(';');
|
||||
a = is.read();
|
||||
}
|
||||
len = sb.length();//Check to make sure we aren't stopping on an embedded null
|
||||
} while (sb.lastIndexOf("</methodResponse>") < len - 20 || len < 30);
|
||||
Document root = DocumentBuilderFactory.newInstance().newDocumentBuilder()
|
||||
.parse(new ByteArrayInputStream(sb.toString().getBytes()));
|
||||
|
||||
if(!root.getFirstChild().getNodeName().equals("methodResponse"))
|
||||
throw new MsfException("Error reading response: not a response.");
|
||||
Node methResp = root.getFirstChild();
|
||||
if(methResp.getFirstChild().getNodeName().equals("fault")){
|
||||
throw new MsfException(methResp.getFirstChild()//fault
|
||||
.getFirstChild() // value
|
||||
.getFirstChild() // struct
|
||||
.getLastChild() // member
|
||||
.getLastChild() // value
|
||||
.getTextContent());
|
||||
}
|
||||
Node params = methResp.getFirstChild();
|
||||
if(!params.getNodeName().equals("params"))
|
||||
throw new MsfException("Error reading response: no params.");
|
||||
Node param = params.getFirstChild();
|
||||
if(!param.getNodeName().equals("param"))
|
||||
throw new MsfException("Error reading response: no param.");
|
||||
Node value = param.getFirstChild();
|
||||
if(!value.getNodeName().equals("value"))
|
||||
throw new MsfException("Error reading response: no value.");
|
||||
return parseVal(value);
|
||||
}
|
||||
|
||||
/** Takes an XMLRPC DOM value node and creates a java object out of it recursively */
|
||||
public static Object parseVal(Node submemb) throws MsfException {
|
||||
Node type = submemb.getFirstChild();
|
||||
String typeName = type.getNodeName();
|
||||
if(typeName.equals("string")){//<struct><member><name>jobs</name><value><struct/></value></member></struct>
|
||||
return type.getTextContent(); //String returns java string
|
||||
}else if (typeName.equals("array")){ //Array returns List
|
||||
ArrayList arrgh = new ArrayList();
|
||||
Node data = type.getFirstChild();
|
||||
if(!data.getNodeName().equals("data"))
|
||||
throw new MsfException("Error reading array: no data.");
|
||||
for(Node val = data.getFirstChild(); val != null; val = val.getNextSibling())
|
||||
arrgh.add(parseVal(val));
|
||||
return arrgh;
|
||||
}else if (typeName.equals("struct")){ //Struct returns a HashMap of name->value member pairs
|
||||
HashMap structmembs = new HashMap();
|
||||
for(Node member = type.getFirstChild(); member != null; member = member.getNextSibling()){
|
||||
if(!member.getNodeName().equals("member"))
|
||||
throw new MsfException("Error reading response: non struct member.");
|
||||
Object name = null, membValue = null;
|
||||
//get each member and put into output map
|
||||
for(Node submember = member.getFirstChild(); submember != null; submember = submember.getNextSibling()){
|
||||
if(submember.getNodeName().equals("name"))
|
||||
name = submember.getTextContent();
|
||||
else if (submember.getNodeName().equals("value"))
|
||||
membValue = parseVal(submember); //Value can be arbitrarily complex
|
||||
}
|
||||
structmembs.put(name, membValue);
|
||||
}
|
||||
return structmembs;
|
||||
}else if (typeName.equals("i4")){
|
||||
return new Integer(type.getTextContent());
|
||||
}else if (typeName.equals("boolean")){
|
||||
return type.getTextContent().equals("1") || Boolean.valueOf(type.getTextContent());
|
||||
}else if (typeName.equals("dateTime.iso8601")) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
|
||||
try{
|
||||
return sdf.parse(type.getTextContent());
|
||||
}catch(ParseException pex){
|
||||
return type.getTextContent();
|
||||
}
|
||||
} else {
|
||||
throw new MsfException("Error reading val: unknown type " + typeName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,3 +17,5 @@ sslBox.text=
|
|||
sslLabel.text=SSL
|
||||
disableDbButton.text=
|
||||
disableDbLabel.text=Disable DB
|
||||
xmlButton.text=XML
|
||||
msgpackButton.text=MsgPack
|
||||
|
|
Loading…
Reference in New Issue