package com.jeztek.imok; import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.security.GeneralSecurityException; import java.util.HashMap; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import android.util.Log; public class HttpPost { private static final String DEBUG_ID = "IMOk.HttpPost"; public String BOUNDARY = "--------multipart_formdata_boundary$--------"; public String CRLF = "\r\n"; private String url = null; private Map<String,String> vars = null; private Map<String,File> files = null; public HttpPost() { } public HttpPost(String url) { this.url = url; } public HttpPost(String url, Map<String,String> vars, Map<String,File> files) { this.url = url; this.vars = vars; this.files = files; } public String post() { if (this.url == null || this.vars == null || this.files == null) return null; return post(this.url, this.vars, this.files); } public String post(Map<String,String> vars, Map<String,File> files) { if (this.url == null) return null; return post(this.url, vars, files); } public String post(String url, Map<String,String> vars, Map<String,File> files) { try { HttpURLConnection conn = (HttpURLConnection)(new URL(url)).openConnection(); conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); DataOutputStream out = new DataOutputStream(conn.getOutputStream()); assembleMultipart(out, vars, files); InputStream in = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { sb.append(line); } return sb.toString(); } catch (UnsupportedEncodingException e) { return "Encoding exception: " + e; } catch (IOException e) { return "IOException: " + e; } catch (IllegalStateException e) { return "IllegalState: " + e; } } public void assembleMultipart(DataOutputStream out, Map<String,String> vars, Map<String,File> files) throws IOException { for (String key : vars.keySet()) { out.writeBytes("--" + BOUNDARY + CRLF); out.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + CRLF); out.writeBytes(CRLF); out.writeBytes(vars.get(key) + CRLF); } for (String key : files.keySet()) { File f = files.get(key); out.writeBytes("--" + BOUNDARY + CRLF); out.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"; filename=\"" + f.getName() + "\"" + CRLF); out.writeBytes("Content-Type: application/octet-stream" + CRLF); out.writeBytes(CRLF); // write file int maxBufferSize = 1024; FileInputStream fin = new FileInputStream(f); int bytesAvailable = fin.available(); int bufferSize = Math.min(maxBufferSize, bytesAvailable); byte[] buffer = new byte[bufferSize]; int bytesRead = fin.read(buffer, 0, bufferSize); while (bytesRead > 0) { out.write(buffer, 0, bufferSize); bytesAvailable = fin.available(); bufferSize = Math.min(maxBufferSize, bytesAvailable); bytesRead = fin.read(buffer, 0, bufferSize); } } out.writeBytes(CRLF); out.writeBytes("--" + BOUNDARY + "--" + CRLF); out.writeBytes(CRLF); } // --------------------------------------------------------------------------------------- public void assembleMultipart(DataOutputStream out, Map<String,String> vars, String fileKey, String fileName, InputStream istream) throws IOException { for (String key : vars.keySet()) { out.writeBytes("--" + BOUNDARY + CRLF); out.writeBytes("Content-Disposition: form-data; name=\"" + key + "\"" + CRLF); out.writeBytes(CRLF); out.writeBytes(vars.get(key) + CRLF); } if (fileName != null) { out.writeBytes("--" + BOUNDARY + CRLF); out.writeBytes("Content-Disposition: form-data; name=\"" + fileKey + "\"; filename=\"" + fileName + "\"" + CRLF); out.writeBytes("Content-Type: application/octet-stream" + CRLF); out.writeBytes(CRLF); // write stream //http://getablogger.blogspot.com/2008/01/android-how-to-post-file-to-php-server.html int maxBufferSize = 1024; int bytesAvailable = istream.available(); int bufferSize = Math.min(maxBufferSize, bytesAvailable); byte[] buffer = new byte[bufferSize]; int bytesRead = istream.read(buffer, 0, bufferSize); while (bytesRead > 0) { out.write(buffer, 0, bufferSize); out.flush(); bytesAvailable = istream.available(); bufferSize = Math.min(maxBufferSize, bytesAvailable); bytesRead = istream.read(buffer, 0, bufferSize); } } out.writeBytes(CRLF); out.writeBytes("--" + BOUNDARY + "--" + CRLF); out.writeBytes(CRLF); } public Map<String,String> post(String url, boolean useSSL, Map<String,String> vars, String fileKey, String fileName, InputStream istream) throws IOException { HttpURLConnection conn; try { if (useSSL) { DisableSSLCertificateCheckUtil.disableChecks(); conn = (HttpsURLConnection)(new URL(url)).openConnection(); } else { conn = (HttpURLConnection)(new URL(url)).openConnection(); } } catch (IOException e) { throw new IOException("HttpPost - IOException: " + e); } catch (GeneralSecurityException e) { throw new IOException("HttpPost - disable ssl: " + e); } try { conn.setDoInput(true); conn.setDoOutput(true); conn.setUseCaches(false); conn.setAllowUserInteraction(true); conn.setRequestMethod("POST"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); DataOutputStream out = new DataOutputStream(conn.getOutputStream()); assembleMultipart(out, vars, fileKey, fileName, istream); if(istream != null) { istream.close(); } out.flush(); InputStream in = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); StringBuilder sb = new StringBuilder(); // Set postedSuccess to true if there is a line in the HTTP response in // the form "GEOCAM_SHARE_POSTED <file>" where <file> equals fileName. // Our old success condition was just checking for HTTP return code 200; turns // out that sometimes gives false positives. Boolean postedSuccess = false; for (String line = reader.readLine(); line != null; line = reader.readLine()) { sb.append(line); if (!postedSuccess && line.startsWith("GEOCAM_SHARE_POSTED")) { String[] vals = line.trim().split("\\s+"); String filePosted = vals[1]; if (filePosted.equals(fileName)) { Log.d(DEBUG_ID, line); postedSuccess = true; } } } out.close(); HashMap<String,String> retVal = new HashMap<String,String>(); retVal.put("code", Integer.toString(conn.getResponseCode())); retVal.put("response", sb.toString()); return retVal; } catch (UnsupportedEncodingException e) { throw new IOException("HttpPost - Encoding exception: " + e); } // ??? when would this ever be thrown? catch (IllegalStateException e) { throw new IOException("HttpPost - IllegalState: " + e); } catch (IOException e) { try { HashMap<String,String> retVal = new HashMap<String,String>(); retVal.put("code", Integer.toString(conn.getResponseCode())); return retVal; } catch(IOException f) { throw new IOException("HttpPost - IOException: " + e); } } } }