From 4cf3d9c1a2766bee5f2ad96b300b99bfb75ea59e Mon Sep 17 00:00:00 2001
From: jrandom <jrandom>
Date: Thu, 25 Aug 2005 21:00:09 +0000
Subject: [PATCH] HTTP file upload (rfc 1867) helper

---
 core/java/src/net/i2p/util/EepPost.java | 189 ++++++++++++++++++++++++
 1 file changed, 189 insertions(+)
 create mode 100644 core/java/src/net/i2p/util/EepPost.java

diff --git a/core/java/src/net/i2p/util/EepPost.java b/core/java/src/net/i2p/util/EepPost.java
new file mode 100644
index 0000000000..e938493419
--- /dev/null
+++ b/core/java/src/net/i2p/util/EepPost.java
@@ -0,0 +1,189 @@
+package net.i2p.util;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import net.i2p.I2PAppContext;
+
+/**
+ * Simple helper for uploading files and such via HTTP POST (rfc 1867)
+ *
+ */
+public class EepPost {
+    public static void main(String args[]) {
+        EepPost e = new EepPost();
+        Map fields = new HashMap();
+        fields.put("key", "value");
+        fields.put("key1", "value1");
+        fields.put("key2", "value2");
+        fields.put("blogpost0", new File("/home/i2p/1.snd"));
+        fields.put("blogpost1", new File("/home/i2p/2.snd"));
+        fields.put("blogpost2", new File("/home/i2p/2.snd"));
+        fields.put("blogpost3", new File("/home/i2p/2.snd"));
+        fields.put("blogpost4", new File("/home/i2p/2.snd"));
+        fields.put("blogpost5", new File("/home/i2p/2.snd"));
+        e.postFiles("http://localhost:7653/import.jsp", null, -1, fields, null);
+        //e.postFiles("http://localhost/cgi-bin/read.pl", null, -1, fields, null);
+        //e.postFiles("http://localhost:2001/import.jsp", null, -1, fields, null);
+    }
+    /**
+     * Submit an HTTP POST to the given URL (using the proxy if specified),
+     * uploading the given fields.  If the field's value is a File object, then
+     * that file is uploaded, and if the field's value is a String object, the
+     * value is posted for that particular field.  Multiple values for one 
+     * field name is not currently supported.
+     *
+     */
+    public void postFiles(String url, String proxyHost, int proxyPort, Map fields, Runnable onCompletion) {
+        I2PThread postThread = new I2PThread(new Runner(url, proxyHost, proxyPort, fields, onCompletion));
+        postThread.start();
+    }
+    
+    private class Runner implements Runnable {
+        private String _url;
+        private String _proxyHost;
+        private int _proxyPort;
+        private Map _fields;
+        private Runnable _onCompletion;
+        public Runner(String url, String proxy, int port, Map fields, Runnable onCompletion) {
+            _url = url;
+            _proxyHost = proxy;
+            _proxyPort = port;
+            _fields = fields;
+            _onCompletion = onCompletion;
+        }
+        public void run() {
+            try {
+                URL u = new URL(_url);
+                String h = u.getHost();
+                int p = u.getPort();
+                if (p <= 0)
+                    p = 80;
+                String path = u.getPath();
+
+                boolean isProxy = true;
+                if ( (_proxyHost == null) || (_proxyPort <= 0) ) {
+                    isProxy = false;
+                    _proxyHost = h;
+                    _proxyPort = p;
+                }
+
+                Socket s = new Socket(_proxyHost, _proxyPort);
+                OutputStream out = s.getOutputStream();
+                String sep = getSeparator();
+                long length = calcContentLength(sep, _fields);
+                String header = getHeader(isProxy, path, h, p, sep, length);
+                System.out.println("Header: \n" + header);
+                out.write(header.getBytes());
+                out.flush();
+                if (false) {
+                    out.write(("--" + sep + "\ncontent-disposition: form-data; name=\"field1\"\n\nStuff goes here\n--" + sep + "--\n").getBytes()); 
+                } else {
+                    sendFields(out, sep, _fields);
+                }
+                out.flush();
+                BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
+                String line = null;
+                while ( (line = in.readLine()) != null)
+                    System.out.println("recv: [" + line + "]");
+                out.close();
+            } catch (Exception e) {
+                e.printStackTrace();
+            } finally {
+                if (_onCompletion != null)
+                    _onCompletion.run();
+            }
+        }
+    }
+    
+    private long calcContentLength(String sep, Map fields) {
+        long len = 0;
+        for (Iterator iter = fields.keySet().iterator(); iter.hasNext(); ) {
+            String key = (String)iter.next();
+            Object val = fields.get(key);
+            if (val instanceof File) {
+                File f = (File)val;
+                len += ("--" + sep + "\nContent-Disposition: form-data; name=\"" + key + "\"; filename=\"" + f.getName() + "\"\n").length();
+                //len += ("Content-length: " + f.length() + "\n").length();
+                len += ("Content-Type: application/octet-stream\n\n").length();
+                len += f.length();
+                len += 1; // nl
+            } else {
+                len += ("--" + sep + "\nContent-Disposition: form-data; name=\"" + key + "\"\n\n").length();
+                len += val.toString().length();
+                len += 1; // nl
+            }
+        }
+        len += 2 + sep.length() + 2;
+        //len += 2;
+        return len;
+    }
+    private void sendFields(OutputStream out, String separator, Map fields) throws IOException {
+        for (Iterator iter = fields.keySet().iterator(); iter.hasNext(); ) {
+            String field = (String)iter.next();
+            Object val = fields.get(field);
+            if (val instanceof File)
+                sendFile(out, separator, field, (File)val);
+            else
+                sendField(out, separator, field, val.toString());
+        }
+        out.write(("--" + separator + "--\n").getBytes());
+    }
+    
+    private void sendFile(OutputStream out, String separator, String field, File file) throws IOException {
+        long len = file.length();
+        out.write(("--" + separator + "\n").getBytes());
+        out.write(("Content-Disposition: form-data; name=\"" + field + "\"; filename=\"" + file.getName() + "\"\n").getBytes());
+        //out.write(("Content-length: " + len + "\n").getBytes());
+        out.write(("Content-Type: application/octet-stream\n\n").getBytes());
+        FileInputStream in = new FileInputStream(file);
+        byte buf[] = new byte[1024];
+        int read = -1;
+        while ( (read = in.read(buf)) != -1)
+            out.write(buf, 0, read);
+        out.write("\n".getBytes());
+        in.close();
+    }
+    
+    private void sendField(OutputStream out, String separator, String field, String val) throws IOException {
+        out.write(("--" + separator + "\n").getBytes());
+        out.write(("Content-Disposition: form-data; name=\"" + field + "\"\n\n").getBytes());
+        out.write(val.getBytes());
+        out.write("\n".getBytes());
+    }
+    
+    private String getHeader(boolean isProxy, String path, String host, int port, String separator, long length) {
+        StringBuffer buf = new StringBuffer(512);
+        buf.append("POST ");
+        if (isProxy) {
+            buf.append("http://").append(host);
+            if (port != 80)
+                buf.append(":").append(port);
+        }
+        buf.append(path);
+        buf.append(" HTTP/1.1\n");
+        buf.append("Host: ").append(host);
+        if (port != 80)
+            buf.append(":").append(port);
+        buf.append("\n");
+        buf.append("Connection: close\n");
+        buf.append("Content-length: ").append(length).append("\n");
+        buf.append("Content-type: multipart/form-data, boundary=").append(separator);
+        buf.append("\n");
+        buf.append("\n");
+        return buf.toString();
+    }
+    
+    private String getSeparator() {
+        if (false)
+            return "ABCDEFG"; 
+        if (false)
+            return "------------------------" + new java.util.Random().nextLong();
+        byte separator[] = new byte[32];  // 2^-128 chance of this being a problem
+        I2PAppContext.getGlobalContext().random().nextBytes(separator);
+        StringBuffer sep = new StringBuffer(48);
+        for (int i = 0; i < separator.length; i++)
+            sep.append((char)((int)'a' + (int)(separator[i]&0x0F))).append((char)((int)'a' + (int)((separator[i] >>> 4) & 0x0F)));
+        return sep.toString();
+    }
+}
-- 
GitLab