mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-31 08:25:22 +00:00
Add helper class for formatting multipart mime
This commit is contained in:
parent
62a1ca46bc
commit
30b2c1ea3f
@ -50,6 +50,8 @@ public abstract class AbstractId {
|
||||
return binary;
|
||||
}
|
||||
|
||||
public abstract String getMimeType();
|
||||
|
||||
public AbstractId(String hex) throws InvalidHexException {
|
||||
if (hex==null)
|
||||
throw new InvalidHexException(this, "null is not a invalid hex value");
|
||||
|
@ -36,4 +36,8 @@ public class BundleId extends SigningKey {
|
||||
super(binary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,11 @@ public class BundleKey extends AbstractId {
|
||||
return 32;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return null; //TODO?
|
||||
}
|
||||
|
||||
public BundleKey(String hex) throws InvalidHexException {
|
||||
super(hex);
|
||||
}
|
||||
|
@ -41,4 +41,8 @@ public class BundleSecret extends AbstractId {
|
||||
super(binary);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return "rhizome/bundle-secret";
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ public class FileHash extends AbstractId {
|
||||
return BINARY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public FileHash(String hex) throws InvalidHexException {
|
||||
super(hex);
|
||||
}
|
||||
|
97
java/org/servalproject/servaldna/PostHelper.java
Normal file
97
java/org/servalproject/servaldna/PostHelper.java
Normal file
@ -0,0 +1,97 @@
|
||||
package org.servalproject.servaldna;
|
||||
|
||||
import org.servalproject.servaldna.rhizome.RhizomeIncompleteManifest;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.HttpURLConnection;
|
||||
|
||||
/**
|
||||
* Created by jeremy on 5/10/16.
|
||||
*/
|
||||
public class PostHelper {
|
||||
private HttpURLConnection conn;
|
||||
private String boundary;
|
||||
private OutputStream output;
|
||||
private PrintStream writer;
|
||||
|
||||
public PostHelper(HttpURLConnection conn) {
|
||||
this.conn = conn;
|
||||
boundary = Long.toHexString(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public void connect() throws IOException {
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
conn.connect();
|
||||
output = conn.getOutputStream();
|
||||
writer = new PrintStream(output, false, "UTF-8");
|
||||
}
|
||||
|
||||
private void quoteString(StringBuilder sb, String unquoted)
|
||||
{
|
||||
if (unquoted == null) {
|
||||
sb.append("null");
|
||||
return;
|
||||
}
|
||||
sb.append('"');
|
||||
for (int i = 0; i < unquoted.length(); ++i) {
|
||||
char c = unquoted.charAt(i);
|
||||
if (c == '"' || c == '\\')
|
||||
sb.append('\\');
|
||||
sb.append(c);
|
||||
}
|
||||
sb.append('"');
|
||||
}
|
||||
|
||||
public void writeHeading(String name, String filename, String type, String encoding)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("\r\n--").append(boundary).append("\r\n");
|
||||
sb.append("Content-Disposition: form-data; name=");
|
||||
quoteString(sb, name);
|
||||
if (filename!=null) {
|
||||
sb.append("; filename=");
|
||||
quoteString(sb, filename);
|
||||
}
|
||||
sb.append("\r\n");
|
||||
sb.append("Content-Type: ").append(type).append("\r\n");
|
||||
if (encoding!=null)
|
||||
sb.append("Content-Transfer-Encoding: ").append(encoding).append("\r\n");
|
||||
sb.append("\r\n");
|
||||
writer.print(sb.toString());
|
||||
}
|
||||
|
||||
public void writeField(String name, String value){
|
||||
writeHeading(name, null, "text/plain; charset=utf-8", null);
|
||||
writer.print(value);
|
||||
}
|
||||
|
||||
public void writeField(String name, AbstractId value){
|
||||
writeHeading(name, null, value.getMimeType(), "hex");
|
||||
writer.print(value.toHex());
|
||||
}
|
||||
|
||||
public void writeField(String name, String filename, InputStream stream) throws IOException {
|
||||
writeHeading(name, filename, "application/octet-stream", "binary");
|
||||
writer.flush();
|
||||
byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while ((n = stream.read(buffer)) > 0)
|
||||
output.write(buffer, 0, n);
|
||||
}
|
||||
|
||||
public void writeField(String name, RhizomeIncompleteManifest manifest) throws IOException {
|
||||
writeHeading(name, null, "rhizome/manifest; format=\"text+binarysig\"", "binary");
|
||||
manifest.toTextFormat(writer);
|
||||
}
|
||||
|
||||
public void close(){
|
||||
writer.print("\r\n--" + boundary + "--\r\n");
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
@ -24,4 +24,9 @@ public class SigningKey extends AbstractId {
|
||||
public int getBinarySize() {
|
||||
return BINARY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return "serval-mesh/id";
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,11 @@ public class SubscriberId extends AbstractId {
|
||||
return BINARY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMimeType() {
|
||||
return "serval-mesh/sid";
|
||||
}
|
||||
|
||||
public SubscriberId(String hex) throws InvalidHexException {
|
||||
super(hex);
|
||||
}
|
||||
|
@ -22,14 +22,13 @@ package org.servalproject.servaldna.meshms;
|
||||
|
||||
import org.servalproject.json.JSONInputException;
|
||||
import org.servalproject.json.JSONTokeniser;
|
||||
import org.servalproject.servaldna.PostHelper;
|
||||
import org.servalproject.servaldna.ServalDFailureException;
|
||||
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
|
||||
@ -122,20 +121,10 @@ public class MeshMSCommon
|
||||
public static MeshMSStatus sendMessage(ServalDHttpConnectionFactory connector, SubscriberId sid1, SubscriberId sid2, String text) throws IOException, ServalDInterfaceException, MeshMSException
|
||||
{
|
||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/meshms/" + sid1.toHex() + "/" + sid2.toHex() + "/sendmessage");
|
||||
String boundary = Long.toHexString(System.currentTimeMillis());
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
conn.connect();
|
||||
OutputStream ost = conn.getOutputStream();
|
||||
PrintStream wr = new PrintStream(ost, false, "UTF-8");
|
||||
wr.print("--" + boundary + "\r\n");
|
||||
wr.print("Content-Disposition: form-data; name=\"message\"\r\n");
|
||||
wr.print("Content-Type: text/plain; charset=utf-8\r\n");
|
||||
wr.print("\r\n");
|
||||
wr.print(text);
|
||||
wr.print("\r\n--" + boundary + "--\r\n");
|
||||
wr.close();
|
||||
PostHelper helper = new PostHelper(conn);
|
||||
helper.connect();
|
||||
helper.writeField("message", text);
|
||||
helper.close();
|
||||
JSONTokeniser json = MeshMSCommon.receiveRestfulResponse(conn, HttpURLConnection.HTTP_CREATED);
|
||||
Status status = decodeRestfulStatus(json);
|
||||
throwRestfulResponseExceptions(status, conn.getURL());
|
||||
|
@ -26,6 +26,7 @@ import org.servalproject.servaldna.BundleId;
|
||||
import org.servalproject.servaldna.BundleKey;
|
||||
import org.servalproject.servaldna.BundleSecret;
|
||||
import org.servalproject.servaldna.FileHash;
|
||||
import org.servalproject.servaldna.PostHelper;
|
||||
import org.servalproject.servaldna.ServalDFailureException;
|
||||
import org.servalproject.servaldna.ServalDHttpConnectionFactory;
|
||||
import org.servalproject.servaldna.ServalDInterfaceException;
|
||||
@ -34,7 +35,6 @@ import org.servalproject.servaldna.SubscriberId;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
@ -384,56 +384,17 @@ public class RhizomeCommon
|
||||
RhizomeEncryptionException
|
||||
{
|
||||
HttpURLConnection conn = connector.newServalDHttpConnection("/restful/rhizome/insert");
|
||||
String boundary = Long.toHexString(System.currentTimeMillis());
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setDoOutput(true);
|
||||
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
|
||||
conn.connect();
|
||||
OutputStream ost = conn.getOutputStream();
|
||||
PrintStream wr = new PrintStream(ost, false, "UTF-8");
|
||||
wr.print(new Object(){}.getClass().getEnclosingClass().getName());
|
||||
if (author != null) {
|
||||
wr.print("\r\n--" + boundary + "\r\n");
|
||||
wr.print("Content-Disposition: form-data; name=\"bundle-author\"\r\n");
|
||||
wr.print("Content-Type: serval-mesh/sid\r\n");
|
||||
wr.print("Content-Transfer-Encoding: hex\r\n");
|
||||
wr.print("\r\n");
|
||||
wr.print(author.toHex());
|
||||
}
|
||||
if (secret != null) {
|
||||
wr.print("\r\n--" + boundary + "\r\n");
|
||||
wr.print("Content-Disposition: form-data; name=\"bundle-secret\"\r\n");
|
||||
wr.print("Content-Type: rhizome/bundle-secret\r\n");
|
||||
wr.print("Content-Transfer-Encoding: hex\r\n");
|
||||
wr.print("\r\n");
|
||||
wr.print(secret.toHex());
|
||||
}
|
||||
wr.print("\r\n--" + boundary + "\r\n");
|
||||
wr.print("Content-Disposition: form-data; name=\"manifest\"\r\n");
|
||||
wr.print("Content-Type: rhizome/manifest; format=\"text+binarysig\"\r\n");
|
||||
wr.print("Content-Transfer-Encoding: binary\r\n");
|
||||
wr.print("\r\n");
|
||||
wr.flush();
|
||||
manifest.toTextFormat(ost);
|
||||
if (payloadStream != null) {
|
||||
wr.print("\r\n--" + boundary + "\r\n");
|
||||
wr.print("Content-Disposition: form-data; name=\"payload\"");
|
||||
if (fileName != null) {
|
||||
wr.print("; filename=");
|
||||
wr.print(quoteString(fileName));
|
||||
}
|
||||
wr.print("\r\n");
|
||||
wr.print("Content-Type: application/octet-stream\r\n");
|
||||
wr.print("Content-Transfer-Encoding: binary\r\n");
|
||||
wr.print("\r\n");
|
||||
wr.flush();
|
||||
byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while ((n = payloadStream.read(buffer)) > 0)
|
||||
ost.write(buffer, 0, n);
|
||||
}
|
||||
wr.print("\r\n--" + boundary + "--\r\n");
|
||||
wr.close();
|
||||
PostHelper helper = new PostHelper(conn);
|
||||
helper.connect();
|
||||
if (author != null)
|
||||
helper.writeField("bundle-author", author);
|
||||
if (secret != null)
|
||||
helper.writeField("bundle-secret", secret);
|
||||
helper.writeField("manifest", manifest);
|
||||
if (payloadStream != null)
|
||||
helper.writeField("payload", fileName, payloadStream);
|
||||
helper.close();
|
||||
|
||||
int[] expected_response_codes = { HttpURLConnection.HTTP_OK, HttpURLConnection.HTTP_CREATED };
|
||||
Status status = RhizomeCommon.receiveResponse(conn, expected_response_codes);
|
||||
try {
|
||||
|
@ -20,22 +20,21 @@
|
||||
|
||||
package org.servalproject.servaldna.rhizome;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import org.servalproject.servaldna.AbstractId;
|
||||
import org.servalproject.servaldna.BundleId;
|
||||
import org.servalproject.servaldna.BundleKey;
|
||||
import org.servalproject.servaldna.FileHash;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import org.servalproject.servaldna.AbstractId;
|
||||
import org.servalproject.servaldna.SubscriberId;
|
||||
import org.servalproject.servaldna.BundleId;
|
||||
import org.servalproject.servaldna.FileHash;
|
||||
import org.servalproject.servaldna.BundleKey;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class RhizomeIncompleteManifest {
|
||||
|
||||
@ -80,36 +79,40 @@ public class RhizomeIncompleteManifest {
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
public void toTextFormat(PrintStream writer){
|
||||
if (id != null)
|
||||
writer.print("id=" + id.toHex() + "\n");
|
||||
if (version != null)
|
||||
writer.print("version=" + version + "\n");
|
||||
if (filesize != null)
|
||||
writer.print("filesize=" + filesize + "\n");
|
||||
if (filehash != null)
|
||||
writer.print("filehash=" + filehash.toHex() + "\n");
|
||||
if (sender != null)
|
||||
writer.print("sender=" + sender.toHex() + "\n");
|
||||
if (recipient != null)
|
||||
writer.print("recipient=" + recipient.toHex() + "\n");
|
||||
if (BK != null)
|
||||
writer.print("BK=" + BK.toHex() + "\n");
|
||||
if (crypt != null)
|
||||
writer.print("crypt=" + crypt + "\n");
|
||||
if (tail != null)
|
||||
writer.print("tail=" + tail + "\n");
|
||||
if (date != null)
|
||||
writer.print("date=" + date + "\n");
|
||||
if (service != null)
|
||||
writer.print("service=" + service + "\n");
|
||||
if (name != null)
|
||||
writer.print("name=" + name + "\n");
|
||||
for (Map.Entry<String,String> e: extraFields.entrySet())
|
||||
writer.print(e.getKey() + "=" + e.getValue() + "\n");
|
||||
}
|
||||
|
||||
public void toTextFormat(OutputStream os) throws IOException
|
||||
{
|
||||
OutputStreamWriter osw = new OutputStreamWriter(os, "UTF-8");
|
||||
if (id != null)
|
||||
osw.write("id=" + id.toHex() + "\n");
|
||||
if (version != null)
|
||||
osw.write("version=" + version + "\n");
|
||||
if (filesize != null)
|
||||
osw.write("filesize=" + filesize + "\n");
|
||||
if (filehash != null)
|
||||
osw.write("filehash=" + filehash.toHex() + "\n");
|
||||
if (sender != null)
|
||||
osw.write("sender=" + sender.toHex() + "\n");
|
||||
if (recipient != null)
|
||||
osw.write("recipient=" + recipient.toHex() + "\n");
|
||||
if (BK != null)
|
||||
osw.write("BK=" + BK.toHex() + "\n");
|
||||
if (crypt != null)
|
||||
osw.write("crypt=" + crypt + "\n");
|
||||
if (tail != null)
|
||||
osw.write("tail=" + tail + "\n");
|
||||
if (date != null)
|
||||
osw.write("date=" + date + "\n");
|
||||
if (service != null)
|
||||
osw.write("service=" + service + "\n");
|
||||
if (name != null)
|
||||
osw.write("name=" + name + "\n");
|
||||
for (Map.Entry<String,String> e: extraFields.entrySet())
|
||||
osw.write(e.getKey() + "=" + e.getValue() + "\n");
|
||||
osw.flush();
|
||||
PrintStream wr = new PrintStream(os, false, "UTF-8");
|
||||
toTextFormat(wr);
|
||||
wr.flush();
|
||||
}
|
||||
|
||||
/** Construct a Rhizome manifest from its text format representation.
|
||||
|
Loading…
x
Reference in New Issue
Block a user