DIY - HttpDump

自己做个HttpDump。

用料好简单,WinPcap + Jpcap (小心,Jpcap有两个,一个是sourceforge.net的,那个已经实现了一个capture client,而且功能齐全,但在Windows下要用cygwin或mingwin)。另需要Jakarta commoncodeclog4j,其它的可有可无。

HttpDump.java

/*
 * HttpDump.java Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without fee is hereby
 * granted provided that this copyright notice appears in all copies.
 * 
 * ALSAN WONG MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
 * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
 * NON-INFRINGEMENT. ALSAN WONG SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY
 * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES.
 * 
 * Created on 2005-5-28 Copyright 2005, alsan.home.net
 
*/
package net.alsan.httpdump;

import jpcap.
*;

import org.apache.log4j.Logger;

/**
 * 
 * @author alsan
 * @version 1.0
 
*/
public final class HttpDump implements JpcapHandler {
    
public static final Logger log = Logger.getLogger(HttpDump.class);

    
public void handlePacket(Packet packet) {
        boolean capture 
= true;
        
        
if (packet instanceof TCPPacket) {
            TCPPacket tcp 
= (TCPPacket) packet;

            
if (80 == tcp.dst_port || 80 == tcp.src_port) {
                printHost(tcp);
                printPacket(tcp);
            }
        }
    }

    
private void printPacket(TCPPacket tcp) {
        
if (0 != tcp.data.length) {
            
try {
                HttpPacket http 
= new HttpPacket(tcp.data);
                http.printInfo();
            } 
catch (Exception e) {
                log.error(
"handlePacket(Packet)", e);
            }
        }

        log.info(
"---------------------------------------------------------------");
    }

    
private void printHost(TCPPacket tcp) {
        StringBuilder sb 
= new StringBuilder();
        sb.append(tcp.src_ip.getHostAddress()).append(tcp.src_port).append(
" -> ");
        sb.append(tcp.dst_ip.getHostAddress()).append(tcp.dst_port);
        log.info(sb.toString());
    }

    
public static void main(String[] args) throws Exception {
        Jpcap jpcap 
= Jpcap.openDevice(Jpcap.getDeviceList()[1], 1000false20);
        jpcap.loopPacket(
-1new HttpDump());
    }
}


HttpPacket.java

/*
 * HttpPacket.java
 * Permission to use, copy, modify, and distribute this software
 * and its documentation for NON-COMMERCIAL purposes and without
 * fee is hereby granted provided that this copyright notice
 * appears in all copies.
 *
 * ALSAN WONG MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE
 * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING
 * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. ALSAN WONG
 * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT
 * OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
 * 
 * Created on 2005-5-30
 * Copyright 2005, alsan.home.net
 
*/
package net.alsan.httpdump;

import java.io.
*;

import net.alsan.jlib.io.BufferedInputStreamReader;

import org.apache.commons.codec.binary.Hex;
import org.apache.commons.httpclient.
*;
import org.apache.log4j.Logger;

/**
 * 
 * @author alsan
 * @version 1.0
 
*/
public final class HttpPacket {
    
public static final Logger log = Logger.getLogger(HttpPacket.class);

    
byte[] data;
    BufferedInputStreamReader reader;
    String status, content;
    Header[] header;
    
int headerLen = 0;
    
private static int lastDecodeMethod = 0;    // 0=text, 1=bin
    
    
public HttpPacket(byte[] data) {
        
this.data = data;
        reader 
= new BufferedInputStreamReader(new ByteArrayInputStream(data));
    }
    
    
public void printInfo() throws IOException, HttpException {
        decodeData();
        printStatus();
        printHeader();
        printContent();
    }
    
    
private void printContent() {
        
if(null != content) {
            log.info(content);
        }
    }

    
private void printHeader() {
        
if(null != header) {
            
for(int i=0; i<header.length; i++) {
                StringBuilder sb 
= new StringBuilder();
                sb.append(header[i].getName()).append(
"").append(header[i].getValue());
                log.info(sb.toString());
            }
        }
    }

    
private void printStatus() {
        
if(null != status) {
            log.info(status);
        }
    }

    
private void decodeData() throws IOException, HttpException {
        
if(detectHeader()) {
            decodeHeader();

            
if (data.length > headerLen) {
                
if (isTextContent()) {
                    decodeTextContent();
                } 
else {
                    decodeBinContent();
                }
            }
        } 
else {
            
if(0 == lastDecodeMethod) {
                content 
= new String(data);
                
                
if(content.startsWith("GIF89a")) {
                    decodeBinContent();
                }
            } 
else {
                decodeBinContent();
            }
        }
    }
    
    
private void decodeBinContent() {
        lastDecodeMethod 
= 1;
        StringBuilder sb 
= new StringBuilder();

        
for (int i = 0, cnt = data.length - headerLen; i < cnt; i++) {
            sb.append(Hex.encodeHex(
new byte[] { data[i + headerLen] })).append(" ");

            
if (31 == (i % 32)) {
                sb.append(
"\n");
            } 
else if (7 == (i % 8)) {
                sb.append(
" ");
            }
        }

        content 
= sb.toString();
    }
    
    
private void decodeTextContent() throws IOException {
        lastDecodeMethod 
= 0;
        StringBuilder sb 
= new StringBuilder();
        String line;
        
        
while(null != (line = reader.readLine())) {
            sb.append(line);
        }
        
        content 
= sb.toString();
    }
    
    
private boolean isTextContent() {
        boolean textContent 
= false;
        String value 
= findHeader("Content-Type");
        
        
if(null != value && (value.startsWith("text"|| value.endsWith("x-www-form-urlencoded")) ) {
            value 
= findHeader("Content-Encoding");

            
if(null == value || -1 == value.indexOf("gzip")) {
                textContent 
= true;
            }
        }
        
        
return textContent;
    }
    
    
private boolean detectHeader() throws IOException {
        boolean exist 
= false;
        String line 
= reader.readLine();
        
        
if(-1 != line.indexOf("HTTP/1")) {
            status 
= line;
            exist 
= true;
        }
        
        
return exist;
    }
    
    
private void decodeHeader() throws IOException, HttpException {
        String[] heads 
= getHeaders();
        header 
= new Header[heads.length];
        
        
for(int i=0; i<heads.length; i++) {
            String[] parts 
= heads[i].split("");
            
            
if(2 != parts.length) {
                
throw new HttpException("Invalid HTTP header");
            }
            
            header[i] 
= new Header(parts[0], parts[1]);
        }
    }

    
private String[] getHeaders() throws IOException {
        StringBuilder sb 
= new StringBuilder();
        String line;
        
        
while(null != (line = reader.readLine()) && !line.equals("")) {
            sb.append(line).append(
"\r\n");
        }
        
        headerLen 
= status.length() + sb.length() + 4;

        
return sb.toString().split("\r\n");
    }
    
    
private String findHeader(String name) {
        String value 
= null;
        
        
for(int i=0; i<header.length; i++) {
            
if(header[i].getName().equalsIgnoreCase(name)) {
                value 
= header[i].getValue();
                
break;
            }
        }

        
return value;
    }
}

posted on 2005-06-12 15:42 毒菇求Buy 阅读(1290) 评论(6)  编辑 收藏 引用 所属分类: HTTPJAVA

评论

# re: DIY - HttpDump 2005-06-12 15:50 alsan

需要改进的地方:
1. 使用config配置filter
2. decode gzip压缩的text内容  回复  更多评论   

# re: DIY - HttpDump 2005-06-12 15:51 alsan

better dump binary data to an external file with proper extension  回复  更多评论   

# re: DIY - HttpDump 2006-11-24 07:39 bunedemek@jakarta.com

Have you ever checked this code on Firefox?
It seems wrong, cause it cannot read entity-body of an html transaction with such a code.

Check it please and make me wrong ;-)

nicely done
thanx  回复  更多评论   

# re: DIY - HttpDump 2006-11-24 08:36 毒菇求Buy

Sorry, I didn't check it under FF, it just a toy for me. I'll try to go through the problem while I have the time.  回复  更多评论   

# re: DIY - HttpDump 2007-01-08 16:06 max

請問你的
import net.alsan.jlib.io.BufferedInputStreamReader
在 socure code 並沒有這個class可否題供給我
謝謝
max@sunreap.com
  回复  更多评论   

只有注册用户登录后才能发表评论。
<2006年3月>
2627281234
567891011
12131415161718
19202122232425
2627282930311
2345678

导航

统计

常用链接

留言簿(7)

随笔分类(133)

随笔档案(111)

文章分类(65)

文章档案(53)

相册

收藏夹(30)

BLOG

Book store

Graphics Design

搜索

最新评论

阅读排行榜

评论排行榜