package org.appwork.utils.net.httpconnection; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.nio.ByteBuffer; import org.appwork.utils.Regex; import org.appwork.utils.StringUtils; import org.appwork.utils.encoding.Base64; import org.appwork.utils.logging.Log; public class HTTPConnectionUtils { private static byte R = (byte) 13; private static byte N = (byte) 10; public static String getFileNameFromDispositionHeader(String header) { // http://greenbytes.de/tech/tc2231/ if (StringUtils.isEmpty(header)) { return null; } final String orgheader = header; String contentdisposition = header; String filename = null; for (int i = 0; i < 2; i++) { if (contentdisposition.contains("filename*")) { /* Codierung default */ /* * Content-Disposition: attachment;filename==?UTF-8?B? * RGF2aWQgR3VldHRhIC0gSnVzdCBBIExpdHRsZSBNb3JlIExvdmUgW2FMYnlsb3ZlciBYLUNsdXNpdiBSZW1peF0uTVAz * ?= */ /* remove fallback, in case RFC 2231/5987 appear */ contentdisposition = contentdisposition.replaceAll("filename=.*?;", ""); contentdisposition = contentdisposition.replaceAll("filename\\*", "filename"); final String format = new Regex(contentdisposition, ".*?=[ \"']*(.+)''").getMatch(0); if (format == null) { Log.L.severe("Content-Disposition: invalid format: " + header); filename = null; return filename; } contentdisposition = contentdisposition.replaceAll(format + "''", ""); filename = new Regex(contentdisposition, "filename.*?=[ ]*\"(.+)\"").getMatch(0); if (filename == null) { filename = new Regex(contentdisposition, "filename.*?=[ ]*'(.+)'").getMatch(0); } if (filename == null) { header = header.replaceAll("=", "=\"") + "\""; header = header.replaceAll(";\"", "\""); contentdisposition = header; } else { try { filename = URLDecoder.decode(filename, format); } catch (final Exception e) { Log.L.severe("Content-Disposition: could not decode filename: " + header); filename = null; return filename; } } } else if (new Regex(contentdisposition, "=\\?.*?\\?.*?\\?.*?\\?=").matches()) { /* * Codierung Encoded Words, TODO: Q-Encoding und mehrfach * tokens, aber noch nicht in freier Wildbahn gesehen */ final String tokens[][] = new Regex(contentdisposition, "=\\?(.*?)\\?(.*?)\\?(.*?)\\?=").getMatches(); if (tokens.length == 1 && tokens[0].length == 3 && tokens[0][1].trim().equalsIgnoreCase("B")) { /* Base64 Encoded */ try { filename = URLDecoder.decode(new String(Base64.decode(tokens[0][2].trim()), tokens[0][0].trim()), tokens[0][0].trim()); } catch (final Exception e) { Log.L.severe("Content-Disposition: could not decode filename: " + header); filename = null; return filename; } } } else if (new Regex(contentdisposition, "=\\?.*?\\?.*?\\?=").matches()) { /* Unicode Format wie es 4Shared nutzt */ final String tokens[][] = new Regex(contentdisposition, "=\\?(.*?)\\?(.*?)\\?=").getMatches(); if (tokens.length == 1 && tokens[0].length == 2) { try { contentdisposition = new String(tokens[0][1].trim().getBytes("ISO-8859-1"), tokens[0][0].trim()); continue; } catch (final Exception e) { Log.L.severe("Content-Disposition: could not decode filename: " + header); filename = null; return filename; } } } else { /* ohne Codierung */ filename = new Regex(contentdisposition, "filename.*?=[ ]*\"(.+)\"").getMatch(0); if (filename == null) { filename = new Regex(contentdisposition, "filename.*?=[ ]*'(.+)'").getMatch(0); } if (filename == null) { header = header.replaceAll("=", "=\"") + "\""; header = header.replaceAll(";\"", "\""); contentdisposition = header; } } if (filename != null) { break; } } if (filename != null) { filename = filename.trim(); if (filename.startsWith("\"")) { Log.L.info("Using Workaround for broken filename header!"); filename = filename.substring(1); } } if (filename == null) { Log.L.severe("Content-Disposition: could not parse header: " + orgheader); } return filename; } public static ByteBuffer readheader(final InputStream in, final boolean readSingleLine) throws IOException { ByteBuffer bigbuffer = ByteBuffer.wrap(new byte[4096]); final byte[] minibuffer = new byte[1]; int position; int c; boolean complete = false; while ((c = in.read(minibuffer)) >= 0) { if (bigbuffer.remaining() < 1) { final ByteBuffer newbuffer = ByteBuffer.wrap(new byte[bigbuffer.capacity() * 2]); bigbuffer.flip(); newbuffer.put(bigbuffer); bigbuffer = newbuffer; } if (c > 0) { bigbuffer.put(minibuffer); } if (readSingleLine) { if (bigbuffer.position() >= 1) { /* * \n only line termination, for fucking buggy non rfc * servers */ position = bigbuffer.position(); if (bigbuffer.get(position - 1) == HTTPConnectionUtils.N) { break; } } if (bigbuffer.position() >= 2) { /* \r\n, correct line termination */ position = bigbuffer.position(); if (bigbuffer.get(position - 2) == HTTPConnectionUtils.R && bigbuffer.get(position - 1) == HTTPConnectionUtils.N) { break; } } } else { if (bigbuffer.position() >= 4) { /* RNRN for header<->content divider */ position = bigbuffer.position(); complete = bigbuffer.get(position - 4) == HTTPConnectionUtils.R; complete &= bigbuffer.get(position - 3) == HTTPConnectionUtils.N; complete &= bigbuffer.get(position - 2) == HTTPConnectionUtils.R; complete &= bigbuffer.get(position - 1) == HTTPConnectionUtils.N; if (complete) { break; } } } } bigbuffer.flip(); return bigbuffer; } }