package com.tadpolemusic.media.http; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public class HttpParser { private static final String HEADER_PARSE_REGEX = "%s.*?:(.*)[\\r\\n | \\n]"; public static final String HACK_KEY = "hack"; public static final String HACK_REGEX = HACK_KEY + "(.*)" + HACK_KEY + "?"; public static final String META_KEY = "meta"; public static final String META_REGEX = META_KEY + "(.*)" + META_KEY + "?"; public static class Range { public int start = 0; public int end = 0; public boolean isEmpty() { return start == 0 && end == 0; } @Override public String toString() { return "{start:" + start + ", end : " + end + "}"; } } public static class RequestLine { public static final String METHOD_GET = "GET"; public String method = METHOD_GET; public String protocol = "HTTP/1.1"; public String uri = ""; @Override public String toString() { return "[protocol = " + protocol + ", uri = " + uri + ", method=" + method + "]"; } } public static class StatusLine { public static final String METHOD_GET = "GET"; public int statusCode = 400; public String protocol = "HTTP/1.1"; public String msg = "OK"; @Override public String toString() { return "[statusCode = " + statusCode + ", protocol = " + protocol + ", msg=" + msg + "]"; } } public static String hackString(String addr) { return HACK_KEY + addr + HACK_KEY; } public static String getRemoteUri(String uri) { int index = uri.indexOf(HACK_KEY); if (index >= 0) { return (String) uri.subSequence(0, index); } return null; } public static String getRemoteAddrFromHackedUri(String requestLine) { Pattern p = Pattern.compile(HACK_REGEX); Matcher m = p.matcher(requestLine); if (m.find()) { return m.group(1); } return null; } public static String metaStr(String addr) { return META_KEY + addr + META_KEY; } public static String getMetaAddr(String requestLine) { Pattern p = Pattern.compile(META_REGEX); Matcher m = p.matcher(requestLine); if (m.find()) { return m.group(1); } return null; } public static RequestLine getRequestLine(InputStream is) throws IOException { ByteArrayOutputStream bao = new ByteArrayOutputStream(); int byteRead; String statuLineRawStr = ""; while ((byteRead = is.read()) != -1) { if (byteRead == '\n') { statuLineRawStr = bao.toString(); break; } bao.write(byteRead); } return getRequestLine(statuLineRawStr); } public static RequestLine getRequestLine(String requestLineRawStr) { RequestLine statusLine = new RequestLine(); requestLineRawStr = requestLineRawStr.replace("\n", ""); String[] arr = requestLineRawStr.split(" "); if (arr.length >= 3) { statusLine.method = arr[0]; statusLine.uri = arr[1]; statusLine.protocol = arr[2]; } return statusLine; } public static StatusLine getStatusLine(InputStream is) throws IOException { ByteArrayOutputStream bao = new ByteArrayOutputStream(); int byteRead; String statuLineRawStr = ""; while ((byteRead = is.read()) != -1) { if (byteRead == '\n') { statuLineRawStr = bao.toString(); break; } bao.write(byteRead); } return getStatusLine(statuLineRawStr); } public static StatusLine getStatusLine(String statuLineRawStr) { StatusLine statusLine = new StatusLine(); int index = statuLineRawStr.indexOf("\n"); if (index >= 0) { statuLineRawStr = statuLineRawStr.substring(0, index); statuLineRawStr = statuLineRawStr.replace("\n", ""); } String[] arr = statuLineRawStr.split(" "); if (arr.length >= 3) { statusLine.protocol = arr[0]; statusLine.statusCode = Integer.valueOf(arr[1]); statusLine.msg = arr[2]; } return statusLine; } public static String getUri(String messageHeaer) { try { int indexChangeLine = messageHeaer.indexOf('\n'); String requestLine = (String) messageHeaer.subSequence(0, indexChangeLine); String[] arr = requestLine.split(" "); return arr[1].trim(); } catch (Exception e) { e.printStackTrace(); } return null; } /** * read http message header * * @param is * @return message header bytes * @throws IOException */ public static byte[] readMessageHeaderRaw(InputStream is) throws IOException { /* * http contain two part: 1 message header 2 message content * * they are split by "\r\n\r\n" */ int bytes_read; ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); ArrayList<Integer> iList = new ArrayList<Integer>(); int partIndex = 0; while ((bytes_read = is.read()) != -1) { byteArrayOutputStream.write(bytes_read); if (bytes_read == '\r' && iList.size() == 0) { iList.add(bytes_read); } else if (bytes_read == '\n' && iList.size() == 1) { iList.add(bytes_read); } else if (bytes_read == '\r' && iList.size() == 2) { iList.add(bytes_read); } else if (bytes_read == '\n' && iList.size() == 3) { iList.add(bytes_read); } else { iList.clear(); } // get message header if (iList.size() == 4 && partIndex == 0) { return byteArrayOutputStream.toByteArray(); } } return null; } public static int getContentLength(String response) { String headerRegex = String.format(HEADER_PARSE_REGEX, "Content-Length"); Pattern p = Pattern.compile(headerRegex, Pattern.CASE_INSENSITIVE); Matcher matcher = p.matcher(response); if (matcher.find() && matcher.groupCount() >= 1) { String value = matcher.group(1); return Integer.valueOf(value.trim()); } return -1; } public static String getLocation(String response) { String headerRegex = String.format(HEADER_PARSE_REGEX, "Location"); Pattern p = Pattern.compile(headerRegex, Pattern.CASE_INSENSITIVE); Matcher matcher = p.matcher(response); if (matcher.find() && matcher.groupCount() >= 1) { String value = matcher.group(1); return value; } return null; } public static String getHeader(String headerName, String bodySegment, String defaultValue) { String headerRegex = String.format(HEADER_PARSE_REGEX, headerName); Pattern p = Pattern.compile(headerRegex, Pattern.CASE_INSENSITIVE); Matcher matcher = p.matcher(bodySegment); if (matcher.find() && matcher.groupCount() >= 1) { String value = matcher.group(1); return value.trim(); } return defaultValue; } public static Range getRange(String body) { String rangeVal = getHeader("Range", body, "bytes=0-"); rangeVal = rangeVal.split("=")[1]; Range range = new Range(); String[] rangeArr = rangeVal.split("-"); range.start = Integer.valueOf(rangeArr[0].trim()); if (rangeArr.length >= 2) { range.end = Integer.valueOf(rangeArr[1].trim()); } return range; } public static String replaceStatusCode(String data, int statusCode) { String s = new String(data); Pattern p = Pattern.compile("[0-9]{3}?"); Matcher m = p.matcher(s); if (m.find()) { s = m.replaceFirst("" + statusCode + ""); } return s; } public static String addHeader(String data, String headerName, String headerValue) { int clIndex = data.indexOf('\n'); StringBuilder sb = new StringBuilder(data); sb.insert(clIndex + 1, headerName + ": " + headerValue + " \r\n"); return sb.toString(); } public static String removeHeader(String data, String headerName) { String headerRegex = String.format(HEADER_PARSE_REGEX, headerName); Pattern p = Pattern.compile(headerRegex); Matcher m = p.matcher(data); String s = data; if (m.find()) { s = m.replaceFirst(""); } return s; } public static String replaceOrAddHeader(String data, String headerName, String headerValue) { int hStartI = data.toLowerCase().indexOf(headerName.toLowerCase()); if (hStartI != -1) { hStartI += headerName.length(); StringBuilder sb = new StringBuilder(data); int hEndI = sb.indexOf("\r\n", hStartI); sb.replace(hStartI + 2, hEndI, headerValue); return sb.toString(); } else { return addHeader(data, headerName, headerValue); } } public static String addContentRange(String data, int start, int len, int total) { return HttpParser.addHeader(data, "Content-Range", "bytes " + start + "-" + (start + len - 1) + "/" + total); } public static void main(String[] args) { String bodySegment = "Location: http://www.baidu.com \r\n"; String location = getLocation(bodySegment); System.out.println("Location = " + location); String requestLineStrRaw = "GET A/B/C/CC HTTP/1.1\n"; System.out.println("requestLine = " + getRequestLine(requestLineStrRaw)); String statusLineStrRaw = "HTTP/1.1 200 OK\n"; System.out.println("statusLine = " + getStatusLine(statusLineStrRaw)); String hackedUrl = "sdfdsfs /sddddhackwww.baidu.com:80hackmetabb.commeta sdfsdfsd"; System.out.println("url = " + HttpParser.getRemoteAddrFromHackedUri(hackedUrl)); System.out.println("url = " + HttpParser.getMetaAddr(hackedUrl)); String rangeStr = "Range: bytes=0 \r\n"; String range = getHeader("Range", rangeStr, "0"); System.out.println("range = " + getRange(rangeStr)); System.out.println("changeStatusCode = " + replaceStatusCode(statusLineStrRaw, 203)); System.out.println(addHeader(statusLineStrRaw, "Content-Range", "77777")); String headerStr = replaceOrAddHeader(requestLineStrRaw + rangeStr, "Range", "dfddsdfsd"); System.out.println("headerStr = " + headerStr); headerStr = replaceOrAddHeader(requestLineStrRaw + rangeStr, "Content-Length", "10000"); System.out.println("headerStr = " + headerStr); System.out.println((byte) '\r'); URL url; try { url = new URL("http://www.baidu.com/ttt/index.html?dd=1121#121212121"); int port = url.getPort(); String host = url.getHost(); System.out.println("port = " + port); System.out.println("host = " + host); System.out.println("uri = " + url.getPath()); System.out.println("query = " + url.getQuery()); System.out.println("ref = " + url.getRef()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("uri = " + HttpGetProxy.getUriFromUrl("http://www.baidu.com/ttt/")); System.out.println("uri = " + HttpGetProxy.getUriFromUrl("http://www.baidu.com")); } }