mschachter    01/10/11 09:28:17

  Modified:    src/share/org/apache/struts/upload
                        BufferedMultipartInputStream.java
                        MultipartIterator.java
  Log:
   - port from 1.0 branch to address bugs #3702, #3828, and #2683
  
  Revision  Changes    Path
  1.6       +7 -4      
jakarta-struts/src/share/org/apache/struts/upload/BufferedMultipartInputStream.java
  
  Index: BufferedMultipartInputStream.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-struts/src/share/org/apache/struts/upload/BufferedMultipartInputStream.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- BufferedMultipartInputStream.java 2001/09/24 16:41:37     1.5
  +++ BufferedMultipartInputStream.java 2001/10/11 16:28:17     1.6
  @@ -218,13 +218,16 @@
   
           int read = read();
           ByteArrayOutputStream baos = new ByteArrayOutputStream();
  -        while (read != -1) {
  -            if (read == '\n') {
  -                return baos.toByteArray();
  -            }
  +
  +         // return null if there are no more bytes to read
  +        if( -1 == read )
  +            return null;
  +
  +        while ((read != -1) && (read != '\n')) {
               baos.write(read);
               read = read();
           }
  +
           return baos.toByteArray();
       }
   
  
  
  
  1.18      +95 -90    
jakarta-struts/src/share/org/apache/struts/upload/MultipartIterator.java
  
  Index: MultipartIterator.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-struts/src/share/org/apache/struts/upload/MultipartIterator.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- MultipartIterator.java    2001/09/24 16:41:37     1.17
  +++ MultipartIterator.java    2001/10/11 16:28:17     1.18
  @@ -21,7 +21,7 @@
    * <pre>
    *      MultipartIterator iterator = new MultipartIterator(request);
    *      MultipartElement element;
  - * 
  + *
    *      while ((element = iterator.getNextElement()) != null) {
    *           //do something with element
    *      }
  @@ -31,64 +31,64 @@
    * @author Mike Schachter
    */
   public class MultipartIterator {
  -    
  +
       /**
        * The maximum size in bytes of the buffer used to read lines [4K]
        */
       public static int MAX_LINE_SIZE = 4096;
  -    
  +
       /**
        * The request instance for this class
        */
       protected HttpServletRequest request;
  -    
  +
       /**
        * The input stream instance for this class
        */
       protected BufferedMultipartInputStream inputStream;
  -    
  +
       /**
        * The boundary for this multipart request
        */
       protected String boundary;
  -    
  +
       /**
        * The byte array representing the boundary for this multipart request
        */
       protected byte[] boundaryBytes;
  -    
  +
       /**
        * Whether or not the input stream is finished
        */
       protected boolean contentRead = false;
  -    
  +
       /**
        * The maximum file size in bytes allowed. Ignored if -1
        */
       protected long maxSize = -1;
  -    
  +
       /**
        * The total bytes read from this request
        */
       protected long totalLength = 0;
  -    
  +
       /**
        * The content length of this request
        */
       protected int contentLength;
  -    
  +
       /**
        * The size in bytes written to the filesystem at a time [20K]
        */
       protected int diskBufferSize = 2 * 10240;
  -    
  +
       /**
        * The amount of data read from a request at a time.
        * This also represents the maximum size in bytes of
        * a line read from the request [4KB]
        */
       protected int bufferSize = 4096;
  -    
  +
       /**
        * The temporary directory to store files
        */
  @@ -97,13 +97,13 @@
       /**
        * Constructs a MultipartIterator with a default buffer size and no file size
        * limit
  -     * 
  +     *
        * @param request The multipart request to iterate
        */
       public MultipartIterator(HttpServletRequest request) throws ServletException{
           this(request, -1);
       }
  -    
  +
       /**
        * Constructs a MultipartIterator with the specified buffer size and
        * no file size limit
  @@ -112,10 +112,10 @@
        * @param bufferSize The size in bytes that should be read from the input
        *                   stream at a times
        */
  -    public MultipartIterator(HttpServletRequest request, int bufferSize) throws 
ServletException {        
  +    public MultipartIterator(HttpServletRequest request, int bufferSize) throws 
ServletException {
          this (request, bufferSize, -1);
       }
  -    
  +
       /**
        * Constructs a MultipartIterator with the specified buffer size and
        * the specified file size limit in bytes
  @@ -125,18 +125,18 @@
        *                   stream at a times
        * @param maxSize The maximum size in bytes allowed for a multipart element's 
data
        */
  -    public MultipartIterator(HttpServletRequest request, int bufferSize, long 
maxSize) 
  +    public MultipartIterator(HttpServletRequest request, int bufferSize, long 
maxSize)
                                                                    throws 
ServletException {
  -                         
  -        this(request, bufferSize, maxSize, null);                                   
                              
  -        
  +
  +        this(request, bufferSize, maxSize, null);
  +
       }
  -    
  +
       public MultipartIterator(HttpServletRequest request,
                                int bufferSize,
                                long maxSize,
                                String tempDir) throws ServletException {
  -                                 
  +
           this.request = request;
           this.maxSize = maxSize;
           if (bufferSize > -1) {
  @@ -151,7 +151,7 @@
           }
           parseRequest();
       }
  -    
  +
       /**
        * Retrieves the next element in the iterator if one exists.
        *
  @@ -166,18 +166,18 @@
           //retrieve the "Content-Disposition" header
           //and parse
           String disposition = readLine();
  -        
  -        
  +
  +
           if ((disposition != null) && 
(disposition.startsWith("Content-Disposition"))) {
               String name = parseDispositionName(disposition);
               String filename = parseDispositionFilename(disposition);
  -                                   
  +
               String contentType = null;
               boolean isFile = (filename != null);
  -            
  +
               if (isFile) {
                   filename = new File(filename).getName();
  -                
  +
                   //check for windows filenames,
                   //from linux jdk's the entire filepath
                   //isn't parsed correctly from File.getName()
  @@ -187,29 +187,29 @@
                       colonIndex = filename.indexOf("\\\\");
                   }
                   int slashIndex = filename.lastIndexOf("\\");
  -                
  +
                   if ((colonIndex > -1) && (slashIndex > -1)) {
                       //then consider this filename to be a full
                       //windows filepath, and parse it accordingly
                       //to retrieve just the file name
                       filename = filename.substring(slashIndex+1, filename.length());
                   }
  -            
  +
                   //get the content type
                   contentType = readLine();
                   contentType = parseContentType(contentType);
               }
  -            
  -           
  -            
  +
  +
  +
               //ignore next line (whitespace) (unless it's a file
               //without content-type)
            if (! ((isFile) && contentType == null)) {
                readLine();
               }
  -            
  +
               MultipartElement element = null;
  -            
  +
               //process a file element
               if (isFile) {
                   try {
  @@ -218,6 +218,7 @@
   
                       element = new MultipartElement(name, filename, contentType, 
elementFile);
                   } catch (IOException ioe) {
  +                    ioe.printStackTrace(System.err);
                       throw new ServletException("IOException while reading file 
element: " + ioe.getMessage(), ioe);
                   }
               }
  @@ -240,13 +241,13 @@
                           textData.setLength(textData.length()-1);
                       }
                   }
  -                
  +
                   //create the element
                   element = new MultipartElement(name, textData.toString());
               }
               return element;
  -        }       
  -        
  +        }
  +
           //reset stream
           if (inputStream.markSupported()) {
               try {
  @@ -257,9 +258,9 @@
                       ioe.getMessage());
               }
           }
  -        return null;       
  +        return null;
       }
  -    
  +
       /**
        * Set the maximum amount of bytes read from a line at one time
        *
  @@ -268,7 +269,7 @@
       public void setBufferSize(int bufferSize) {
           this.bufferSize = bufferSize;
       }
  -    
  +
       /**
        * Get the maximum amount of bytes read from a line at one time
        *
  @@ -277,7 +278,7 @@
       public int getBufferSize() {
           return bufferSize;
       }
  -    
  +
       /**
        * Set the maximum post data size allowed for a multipart request
        * @param maxSize The maximum post data size in bytes, set to <code>-1</code>
  @@ -286,26 +287,26 @@
       public void setMaxSize(long maxSize) {
           this.maxSize = maxSize;
       }
  -    
  -    /** 
  +
  +    /**
        * Get the maximum post data size allowed for a multipart request
        * @return The maximum post data size in bytes
        */
       public long getMaxSize() {
           return maxSize;
       }
  -    
  +
       /**
        * Handles retrieving the boundary and setting the input stream
        */
       protected void parseRequest() throws ServletException {
  -             
  +
           contentLength = request.getContentLength();
  -        
  +
           //set boundary
           boundary = parseBoundary(request.getContentType());
           boundaryBytes = boundary.getBytes();
  -        
  +
           try {
               //set the input stream
               inputStream = new BufferedMultipartInputStream(request.getInputStream(),
  @@ -316,23 +317,23 @@
               if (inputStream.markSupported()) {
                   inputStream.mark(contentLength+1);
               }
  -                
  +
           }
           catch (IOException ioe) {
  -            throw new ServletException("Problem while reading request: " + 
  +            throw new ServletException("Problem while reading request: " +
                   ioe.getMessage(), ioe);
           }
  -       
  +
           if ((boundary == null) || (boundary.length() < 1)) {
               //try retrieving the header through more "normal" means
               boundary = parseBoundary(request.getHeader("Content-type"));
           }
  -        
  +
           if ((boundary == null) || (boundary.length() < 1)) {
               throw new ServletException("MultipartIterator: cannot retrieve boundary 
" +
                                          "for multipart request");
           }
  -        
  +
           //read first line
           try {
            String firstLine = readLine();
  @@ -350,37 +351,39 @@
               throw new ServletException("MultipartIterator: encoding \"ISO-8859-1\" 
not supported");
           }
       }
  -      
  +
       /**
  -     * Parses a content-type String for the boundary.  Appends a 
  +     * Parses a content-type String for the boundary.  Appends a
        * "--" to the beginning of the boundary, because thats the
        * real boundary as opposed to the shortened one in the
        * content type.
        */
       public static String parseBoundary(String contentType) {
           if (contentType.lastIndexOf("boundary=") != -1) {
  -            String _boundary = "--" + 
  +            String _boundary = "--" +
                                  
contentType.substring(contentType.lastIndexOf("boundary=")+9);
               if (_boundary.endsWith("\n")) {
                   //strip it off
                   return _boundary.substring(0, _boundary.length()-1);
               }
  -            return _boundary; 
  +            return _boundary;
           }
  -        return null;      
  +        return null;
       }
  -    
  +
       /**
        * Parses the "Content-Type" line of a multipart form for a content type
        *
  -     * @param contentTypeString A String reprsenting the Content-Type line, 
  +     * @param contentTypeString A String reprsenting the Content-Type line,
        *        with a trailing "\n"
        * @return The content type specified, or <code>null</code> if one can't be
        *         found.
        */
       public static String parseContentType(String contentTypeString) {
           int nameIndex = contentTypeString.indexOf("Content-Type: ");
  -        
  +        if (nameIndex == -1)
  +            nameIndex = contentTypeString.indexOf("\n");
  +
           if (nameIndex != -1) {
               int endLineIndex = contentTypeString.indexOf("\n");
               if (endLineIndex == -1) {
  @@ -390,10 +393,10 @@
           }
           return null;
       }
  -    
  +
       /**
        * Retrieves the "name" attribute from a content disposition line
  -     * 
  +     *
        * @param dispositionString The entire "Content-disposition" string
        * @return <code>null</code> if no name could be found, otherwise,
        *         returns the name
  @@ -402,8 +405,8 @@
       public static String parseDispositionName(String dispositionString) {
           return parseForAttribute("name", dispositionString);
       }
  -    
  -    /** 
  +
  +    /**
        * Retrieves the "filename" attribute from a content disposition line
        *
        * @param dispositionString The entire "Content-disposition" string
  @@ -414,8 +417,8 @@
       public static String parseDispositionFilename(String dispositionString) {
           return parseForAttribute("filename", dispositionString);
       }
  -        
  -    
  +
  +
       /**
        * Parses a string looking for a attribute-value pair, and returns the value.
        * For example:
  @@ -424,7 +427,7 @@
        *      MultipartIterator.parseForAttribute(parseString, "name");
        * </pre>
        * That will return "bob".
  -     * 
  +     *
        * @param attribute The name of the attribute you're trying to get
        * @param parseString The string to retrieve the value from
        * @return The value of the attribute, or <code>null</code> if none could be 
found
  @@ -432,17 +435,17 @@
       public static String parseForAttribute(String attribute, String parseString) {
           int nameIndex = parseString.indexOf(attribute + "=\"");
           if (nameIndex != -1) {
  -            
  +
               int endQuoteIndex = parseString.indexOf("\"", 
nameIndex+attribute.length()+3);
  -            
  +
               if (endQuoteIndex != -1) {
                   return parseString.substring(nameIndex+attribute.length()+2, 
endQuoteIndex);
               }
               return "";
  -        }        
  +        }
           return null;
       }
  -    
  +
       /**
        * Reads the input stream until it reaches a new line
        */
  @@ -450,42 +453,44 @@
   
           byte[] bufferByte;
           int bytesRead;
  -        
  +
           if (totalLength >= contentLength) {
               return null;
           }
  -        
  +
           try {
               bufferByte = inputStream.readLine();
  +            if (bufferByte == null)
  +                return null;
               bytesRead  = bufferByte.length;
           }
           catch (IOException ioe) {
  -            throw new ServletException("IOException while reading multipart 
request: " + 
  +            throw new ServletException("IOException while reading multipart 
request: " +
                                       ioe.getMessage());
           }
           if (bytesRead == -1) {
               return null;
           }
  -        
  +
           totalLength += bytesRead;
           return new String(bufferByte, 0, bytesRead, "ISO-8859-1");
       }
  -    
  +
       /**
        * Creates a file on disk from the current mulitpart element
        * @param fileName the name of the multipart file
        */
       protected File createLocalFile() throws IOException {
  -        
  +
           File tempFile = File.createTempFile("strts", null, new File(tempDir));
           BufferedOutputStream fos = new BufferedOutputStream(new 
FileOutputStream(tempFile),
                                                               diskBufferSize);
           byte[] lineBuffer = inputStream.readLine();
            int bytesRead = lineBuffer.length;
  -        
  +
           boolean cutCarriage = false;
           boolean cutNewline = false;
  -        
  +
           try {
               while ((bytesRead != -1) && (!equals(lineBuffer, 0, 
boundaryBytes.length,
                       boundaryBytes))) {
  @@ -514,12 +519,12 @@
               tempFile.delete();
               throw ioe;
           }
  -        
  -        fos.flush(); 
  +
  +        fos.flush();
           fos.close();
           return tempFile;
       }
  -    
  +
      /**
       * Checks bytes for equality.  Two byte arrays are equal if
       * each of their elements are the same.  This method checks
  @@ -528,21 +533,21 @@
       * @param comp The byte to compare to <code>source</code>
       * @param offset The offset to start at in <code>comp</code>
       * @param length The length of <code>comp</code> to compare to
  -    * @param source The reference byte to test for equality
  +    * @param source The reference byte array to test for equality
       */
      public static boolean equals(byte[] comp, int offset, int length,
                                   byte[] source) {
  -    
  -       if (length != source.length) {
  -         return false;
  +
  +       if ((length != source.length) || (comp.length - offset < length)) {
  +            return false;
          }
  -    
  +
          for (int i = 0; i < length; i++) {
              if (comp[offset+i] != source[i]) {
                  return false;
              }
          }
  -       return true;    
  +       return true;
      }
   
   }
  
  
  


Reply via email to