Solved

How do I get my HTTP request handler to accept file uploads?

Posted on 2007-04-10
6
665 Views
Last Modified: 2008-01-09
Hello,
I have written a small HTTP server in Java, its for me to toy around with and use as a basis for other projects. I am having some issues now with receiving HTTP uploads. Initially I had left this ability out of the spec of my http server, but it appears now I need the functionality, so I have gone back and recoded my request object to support it, but whenever I use it (in an upload scenario - everything else works fine) I get a connection reset error.
            I was hoping someone could tell me how to fix my code so that it works properly. Here's what its supposed to do: first it reads all the http header information passed, and stores it in a hashtable for easy reference. After the header is collected if it is a post command, it collects the additional data and stores it in the hashtable as well, finally, if it finds the content type to be multi-part form data, it reads in the remaining bytes, and should process them into another hashtable stored value (for later processing, or writing to disk).

A working fix to this is worth 500 points. The function in question is called processRequest.

Thanks,
Rick


Here is the code:

/*
 * Request.java
 *
 * Created on January 13, 2007, 1:25 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */


import java.util.*;
import java.io.*;
import java.net.*;

/**
 *
 * @author Rick
 */
public class Request
{    
    /** Creates a new instance of Request */
    Socket client;
    Hashtable requestHeaders;
    config cfg;
    int errorLevel = 0;
   
    public Request(Socket client, config cfg)
    {
        this.client = client;
        this.cfg = cfg;
        requestHeaders = new Hashtable();
    }
   
    public boolean requestValueExists(String value)
    {
        return (requestHeaders.get(value) != null);
    }
   
    public void processRequest()
    {
        //grabs the whole header and sets the request hashtable up
        try
        {
            //get the request
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream(),"8859_1"));
            String req_in = "";
            int line = 0;
            requestHeaders.put("local_ip",client.getLocalAddress().getHostAddress());
           
            while ((req_in=in.readLine()).length() > 0)
            {
                //System.out.println(req_in);
                if (line == 0)
                {
                    //it is the page requested break it apart into query string, requested page, request type, and protocol, also set the requesting ip, and hostname
                   String reqs[] = req_in.split(" ");
                   
                   //set up the request type
                   requestHeaders.put("request_method",reqs[0].replace('/',' ').trim());
                   
                   //first split the requested file by ?
                   String tw[] = reqs[1].split("\\?");
                   
                   requestHeaders.put("page_requested",tw[0]);
                     
                   if (tw.length == 2)
                        requestHeaders.put("query_string",tw[1]);
                   
                   //set up the protocol
                   requestHeaders.put("remote_protocol",reqs[2]);
       
                   //get the hostname and ip of the requester
                   String hostnameIP = client.getInetAddress().toString();      
                   String clientInfo[] = hostnameIP.split("/");
           
                   //set up the remote hostname
                   requestHeaders.put("remote_hostname",clientInfo[0]);
                   
                   //set up the remote ip
                   requestHeaders.put("remote_ip",clientInfo[0]);  
                   
                   line=1;
                }
                else
                {
                    //split the string by :
                    String reqs[] = req_in.split(":");
                   
                    if (reqs.length == 2)
                        requestHeaders.put(reqs[0].toLowerCase().trim(),reqs[1].trim());
                    else
                        requestHeaders.put(reqs[0].toLowerCase().trim(),reqs[1].trim() + ":" + reqs[2].trim());
                }
            }   /* end of get request headers */
           
            //now check to see if there is any POST data to collect
            if ((requestHeaders.get("request_method").toString().compareTo("POST") == 0) && (requestHeaders.containsKey("content-length")) && (requestHeaders.containsKey("content-type")))
            {
                //it is a post method and there is data to collect so collect it
                //first get the total content length
                int contentLength = new Integer(requestHeaders.get("content-length").toString()).intValue();
               
                char[] postdata = new char[contentLength];
               
                //read in til the length is hit
                in.read(postdata,0,contentLength);
               
                String post_data = new String(postdata);
               
                //determine if it is a normal form submit or a multi-part form submit
                if (requestHeaders.get("content-type").toString().indexOf("multipart/form-data; boundary=") > -1)
                {
                    //get the data boundary
                    String boundary = "--" + requestHeaders.get("content-type").toString().replaceAll("multipart/form-data; boundary=","");
                   
                    //split the post_data apart by the boundary leaving data parts + 1
                    String formdata[] = post_data.split(boundary);
                   
                    System.out.println("Data Parts: " + formdata.length);
                    System.out.println("------------------");
                   
                    //process each of the data parts
                    for (int i=0; i < formdata.length; i++)
                    {
                        //System.out.println("DataPart " + i);
                       
                        //first find the Content-Disposition
                        int start = formdata[i].toLowerCase().indexOf("content-disposition: form-data; name=");
                        int end = formdata[i].toLowerCase().indexOf("\r\n",start+1);
                       
                        //System.out.println("Start:" + start);
                        //System.out.println("End:" + end);
                       
                        if ((start > -1) && (start < end))
                        {
                            String disposition = formdata[i].substring(start,end);
                       
                            //now determine if the disposution type is formdata or a file upload
                            if (disposition.toLowerCase().indexOf("filename") > -1)
                            {
                                //it is a file upload so lets start by collecting the variable name and value
                               
                                //first split the disposition by ;
                                String uploaddata[] = disposition.split(";");
                               
                                String key = uploaddata[1].toLowerCase().replaceAll("name=","").replaceAll("\"","");
                                String value = uploaddata[2].toLowerCase().replaceAll("filename=","").replaceAll("\"","");
                               
                                requestHeaders.put(key.trim(),value.trim());
                               
                                //ok lets pull the disposition line out of the data
                                String data = formdata[i].replaceAll(disposition,"");
                               
                                //ok now we have to grab the content type of the file
                                start = formdata[i].toLowerCase().indexOf("content-type");
                                end = formdata[i].toLowerCase().indexOf("\r\n",start);
                               
                                String content_type = formdata[i].substring(start,end);
                               
                                requestHeaders.put("file-content-type",content_type.split(":")[1].trim());
                               
                                //remove the content_type
                                System.out.println(data.replaceAll(content_type,"").trim().getBytes().length);
                                requestHeaders.put(value.trim(),data.replaceAll(content_type,"").trim().getBytes());                                
                            }
                            else
                            {
                                if (disposition.split("=")[1].length() > 0)
                                //it is a normal data variable so get the key / value pair and insert it into the request hash
                                requestHeaders.put(disposition.split("=")[1].replaceAll("\"",""),formdata[i].replaceAll(disposition,"").replaceAll("\r\n",""));
                            }
                        }
                        //System.out.println("--------------------");
                    }
                }
                else
                {
               
                    //convert it to a string
                    String pdata[] = post_data.split("&");
               
                    //loop over the results and split by the = sign
                    for (int i = 0; i < pdata.length; i++)
                    {
                        String data[] = pdata[i].split("=");
                        if(data.length == 2)
                            requestHeaders.put(data[0],URLDecoder.decode(data[1]));
                        else
                            requestHeaders.put(data[0],"");
                    }
                }
            }    
        }
        catch(Exception e)
        {
            cfg.writeLog("HTTP Request: Client Connection Error. (" + e.toString() + ").");
            e.printStackTrace();
            errorLevel = 1;
        }
    } // end of processRequest()
   
    public Enumeration getKeyList()
    {
        //return an enumeration of all the key values in the requestHeader hash
        return requestHeaders.keys();
    }
   
    public String getRequestValue(String value)
    {
        //return the requested value from the requestHeader hash
        return requestHeaders.get(value).toString();
    }
   
   
}
0
Comment
Question by:richardsimnett
  • 4
6 Comments
 
LVL 26

Expert Comment

by:ksivananth
ID: 18887535
can you post the exception stack too?
0
 

Author Comment

by:richardsimnett
ID: 18887692
It doesnt throw an exception at all. Instead the browser simply stops, and displays a message connection reset. It only does this on files larger than 1k, and that are binary. Small text files (<1k) go through fine.

Thanks,
Rick
0
 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 18888052
u can't use a Reader to read binary data, need to use an InputStream
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:richardsimnett
ID: 18909020
objects,
is it possible to use a combination of BufferedReader and InputStream? Basically use a buffered reader to read the HTTP header, and then an InputStream to read in the post data?

Thanks,
Rick
0
 

Author Comment

by:richardsimnett
ID: 18909254
nevermind that last question. I proved it cant be done. Im re-coding the entire thing to use inputstream. I will post my results.

Thanks,
Rick
0
 

Author Comment

by:richardsimnett
ID: 18909574
Objects,
Got it works well with InputStream.

Thanks!
Rick
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

For customizing the look of your lightweight component and making it look lucid like it was made of glass. Or: how to make your component more Apple-ish ;) This tip assumes your component to be of rectangular shape and completely opaque. (COD…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now