dims        02/02/27 12:21:23

  Modified:    src/webapp/WEB-INF web.xml
  Added:       src/java/org/apache/cocoon/components/request
                        MultipartRequestFactoryImpl.java
               src/java/org/apache/cocoon/components/request/multipart
                        FilePart.java FilePartArray.java FilePartFile.java
                        MultipartException.java MultipartParser.java
                        MultipartRequestWrapper.java TokenStream.java
  Log:
  "Replacement for maybeupload" from "Jeroen ter Voorde" <[EMAIL PROTECTED]>
  
  Revision  Changes    Path
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/MultipartRequestFactoryImpl.java
  
  Index: MultipartRequestFactoryImpl.java
  ===================================================================
  /*
   *
   * ============================================================================
   *                  The Apache Software License, Version 1.1
   * ============================================================================
   *
   * Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without modifica-
   * tion, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of  source code must  retain the above copyright  notice,
   *   this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   *   this list of conditions and the following disclaimer in the documentation
   *   and/or other materials provided with the distribution.
   *
   * 3. The end-user documentation included with the redistribution, if any, must
   *   include  the following  acknowledgment:  "This product includes  software
   *   developed  by the  Apache Software Foundation  (http://www.apache.org/)."
   *   Alternately, this  acknowledgment may  appear in the software itself,  if
   *   and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
   *   used to  endorse or promote  products derived from  this software without
   *   prior written permission. For written permission, please contact
   *   [EMAIL PROTECTED]
   *
   * 5. Products  derived from this software may not  be called "Apache", nor may
   *   "Apache" appear  in their name,  without prior written permission  of the
   *   Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   * FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   * APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   * INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   * DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   * ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   * (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software  consists of voluntary contributions made  by many individuals
   * on  behalf of the Apache Software  Foundation and was  originally created by
   * Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   * Software Foundation, please see <http://www.apache.org/>.
   *
   */
  package org.apache.cocoon.components.request;
  
  import org.apache.cocoon.components.request.multipart.MultipartRequestWrapper;
  
  import javax.servlet.http.HttpServletRequest;
  import java.io.File;
  import java.util.Vector;
  
  /**
   *
   * Extends the {@link RequestFactory} class
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Davanum Srinivas</a>
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: MultipartRequestFactoryImpl.java,v 1.1 2002/02/27 20:21:22 dims 
Exp $
   */
  public final class MultipartRequestFactoryImpl extends RequestFactory {
  
      /**
       * Return a wrapped request object
       *
       * @param request
       * @param saveUploadedFilesToDisk
       * @param uploadDirectory
       * @param allowOverwrite
       * @param silentlyRename
       * @param maxUploadSize
       *
       * @return
       */
      public HttpServletRequest getServletRequest(HttpServletRequest request,
                                                  boolean saveUploadedFilesToDisk,
                                                  File uploadDirectory,
                                                  boolean allowOverwrite,
                                                  boolean silentlyRename,
                                                  int maxUploadSize) {
  
          HttpServletRequest req         = request;
          String             contentType = req.getContentType();
  
          if (contentType == null) {
              contentType = "application/x-www-form-urlencoded";
          }
          if (contentType.startsWith("multipart/form-data")) {
              try {
                  req = new MultipartRequestWrapper(request,
                                                      saveUploadedFilesToDisk,
                                                      uploadDirectory,
                                                      allowOverwrite,
                                                      silentlyRename,
                                                      maxUploadSize);
              } catch (Exception e) {
                  req = request;
              }
          }
          return req;
      }
  
      /**
       * Implementation of the get method
       *
       * @param request
       * @param name
       *
       * @return
       */
      public Object get(HttpServletRequest request, String name) {
          // FIXME We should get rid of this instanceof test
          if (request instanceof MultipartRequestWrapper) {
              return ((MultipartRequestWrapper) request).get(name);
          } else {
              String[] values = request.getParameterValues(name);
              if (values == null) {
                  return null;
              }
              if (values.length == 1) {
                  return values[0];
              }
              if (values.length > 1) {
                  Vector vect = new Vector(values.length);
                  for (int i = 0; i < values.length; i++) {
                      vect.add(values[i]);
                  }
                  return vect;
              }
          }
          return null;
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/FilePart.java
  
  Index: FilePart.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import java.io.InputStream;
  import java.util.Map;
  
  /**
   * This (abstract) class represents a file part parsed from a http post stream.
   * It is subclassed by FilePartFile (which is a file allready written to disk) and
   * FilePartArray (which is a file in memory)
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: FilePart.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  public abstract class FilePart {
  
      /** Field headers           */
      private Map headers;
  
      /**
       * Returns the part headers
       *
       * @return
       */
      public Map getHeaders() {
          return headers;
      }
  
      /**
       * Returns the filename
       *
       * @return
       */
      public abstract String getFileName();
  
      /**
       * Returns the filepath
       *
       * @return
       */
      public String getFilePath() {
          return (String) headers.get("filename");
      }
  
      /**
       * Returns the mime type (or null if unknown)
       *
       * @return
       */
      public String getMimeType() {
          return (String) headers.get("content-type");
      }
  
      /**
       * Returns an InputStream containing the file data
       *
       * @return
       *
       * @throws Exception
       */
      public abstract InputStream getInputStream() throws Exception;
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/FilePartArray.java
  
  Index: FilePartArray.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import java.io.File;
  import java.io.InputStream;
  import java.util.Map;
  
  /**
   * This class represents a file part parsed from a http post stream.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: FilePartArray.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  public class FilePartArray extends FilePart {
  
      /** Field in           */
      private InputStream in = null;
  
      /** Field headers           */
      private Map headers;
  
      /**
       * Constructor FilePartArray
       *
       * @param headers
       * @param in
       */
      protected FilePartArray(Map headers, InputStream in) {
          this.headers = headers;
          this.in = in;
      }
  
      /**
       * Returns the filename
       *
       * @return
       */
      public String getFileName() {
  
          File f = new File((String) headers.get("filename"));
  
          return f.getName();
      }
  
      /**
       * Returns a (ByteArray)InputStream containing the file data
       *
       * @return
       *
       * @throws Exception
       */
      public InputStream getInputStream() throws Exception {
          return in;
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/FilePartFile.java
  
  Index: FilePartFile.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.InputStream;
  import java.util.Map;
  
  /**
   * This class represents a file part parsed from a http post stream.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: FilePartFile.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  public class FilePartFile extends FilePart {
  
      /** Field file           */
      private File file = null;
  
      /** Field headers           */
      private Map headers;
  
      /**
       * Constructor FilePartFile
       *
       * @param headers
       * @param file
       */
      protected FilePartFile(Map headers, File file) {
          this.headers = headers;
          this.file = file;
      }
  
      /**
       * Returns the filename
       *
       * @return
       */
      public String getFileName() {
          return file.getName();
      }
  
      /**
       * Returns the file
       *
       * @return
       */
      public File getFile() {
          return file;
      }
  
      /**
       * Returns a (ByteArray)InputStream containing the file data
       *
       * @return
       *
       * @throws Exception
       */
      public InputStream getInputStream() throws Exception {
          return new FileInputStream(file);
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/MultipartException.java
  
  Index: MultipartException.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  /**
   * Exception thrown when on a parse error such as
   * a malformed stream.
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: MultipartException.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  public class MultipartException extends Exception {
  
      /**
       * Constructor MultipartException
       */
      public MultipartException() {
          super();
      }
  
      /**
       * Constructor MultipartException
       *
       * @param text
       */
      public MultipartException(String text) {
          super(text);
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/MultipartParser.java
  
  Index: MultipartParser.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import javax.servlet.http.HttpServletRequest;
  import java.io.BufferedInputStream;
  import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.File;
  import java.io.FileOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.io.PushbackInputStream;
  import java.util.Hashtable;
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  /**
   * This class is used to implement a multipart request wrapper.
   * It will parse the http post stream and and fill it's hashtable with values.
   *
   * The hashtable will contain:
   * Vector: inline part values
   * FilePart: file part
   *
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: MultipartParser.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  public class MultipartParser extends Hashtable {
  
      /** Field FILE_BUFFER_SIZE           */
      private final static int FILE_BUFFER_SIZE = 4096;
  
      /** Field INLINE_BUFFER_SIZE           */
      private final static int INLINE_BUFFER_SIZE = 256;
  
      /** Field MAX_BOUNDARY_SIZE           */
      private static final int MAX_BOUNDARY_SIZE = 128;
  
      /** Field saveUploadedFilesToDisk           */
      private boolean saveUploadedFilesToDisk;
  
      /** Field uploadDirectory           */
      private File uploadDirectory = null;
  
      /** Field allowOverwrite           */
      private boolean allowOverwrite;
  
      /** Field silentlyRename           */
      private boolean silentlyRename;
  
      /** Field maxUploadSize           */
      private int maxUploadSize;
  
      /**
       * Constructor, parses given request
       *
       * @param request The servlet request.
       * @param saveUploadFilesToDisk Write fileparts to the uploadDirectory. If true 
the corresponding object
       *              in the hashtable will contain a FilePartFile, if false a 
FilePartArray
       * @param File uploadDirectory The directory to write to if 
saveUploadedFilesToDisk is true.
       * @param saveUploadedFilesToDisk
       * @param uploadDirectory
       * @param allowOverwrite Allow existing files to be overwritten.
       * @param silentlyRename If file exists rename file (using filename+number).
       * @param maxUploadSize The maximum content length accepted.
       *
       * @throws IOException
       * @throws MultipartException
       */
      public MultipartParser(
              HttpServletRequest request, boolean saveUploadedFilesToDisk, File 
uploadDirectory, boolean allowOverwrite, boolean silentlyRename, int maxUploadSize)
              throws IOException, MultipartException {
  
          this.saveUploadedFilesToDisk = saveUploadedFilesToDisk;
          this.uploadDirectory = uploadDirectory;
          this.allowOverwrite = allowOverwrite;
          this.silentlyRename = silentlyRename;
          this.maxUploadSize = maxUploadSize;
  
          if (request.getContentLength() > maxUploadSize) {
              throw new IOException("Content length exceeds maximum upload size");
          }
  
          parseMultiPart(
                  new TokenStream(
                          new PushbackInputStream(
                                  new BufferedInputStream(request.getInputStream()),
                                  MAX_BOUNDARY_SIZE)), 
getBoundary(request.getContentType()));
      }
  
      /**
       * Parse a multipart block
       *
       * @param ts
       * @param boundary
       *
       * @throws IOException
       * @throws MultipartException
       */
      private void parseMultiPart(TokenStream ts, String boundary)
              throws IOException, MultipartException {
  
          ts.setBoundary(boundary.getBytes());
          ts.read();    // read first boundary away
          ts.setBoundary(("\r\n" + boundary).getBytes());
  
          while (ts.getState() == TokenStream.STATE_NEXTPART) {
              ts.nextPart();
              parsePart(ts);
          }
  
          if (ts.getState() != TokenStream.STATE_ENDMULTIPART) {    // sanity check
              throw new MultipartException("Malformed stream");
          }
      }
  
      /**
       * Parse a single part
       *
       * @param ts
       *
       * @throws IOException
       * @throws MultipartException
       */
      private void parsePart(TokenStream ts)
              throws IOException, MultipartException {
  
          Hashtable headers = new Hashtable();
  
          headers = readHeaders(ts);
  
          try {
              if (headers.containsKey("filename")) {
                  parseFilePart(ts, headers);
              } else if (((String) headers.get("content-disposition"))
                      .toLowerCase().equals("form-data")) {
                  parseInlinePart(ts, headers);
              }
  
              // FIXME: multipart/mixed parts are untested.
              else if (((String) headers.get("content-disposition")).toLowerCase()
                      .indexOf("multipart") > -1) {
                  parseMultiPart(new TokenStream(ts, MAX_BOUNDARY_SIZE),
                          "--" + (String) headers.get("boundary"));
                  ts.read();    // read past boundary
              } else {
                  throw new MultipartException("Unknown part type");
              }
          } catch (IOException e) {
              throw new MultipartException("Malformed stream: " + e.getMessage());
          } catch (NullPointerException e) {
              throw new MultipartException("Malformed header");
          }
      }
  
      /**
       * Parse a file part
       *
       * @param in
       * @param headers
       *
       * @throws IOException
       * @throws MultipartException
       */
      private void parseFilePart(TokenStream in, Hashtable headers)
              throws IOException, MultipartException {
  
          byte[] buf = new byte[FILE_BUFFER_SIZE];
          OutputStream out = null;
          File file = null;
  
          if (!saveUploadedFilesToDisk) {
              out = new ByteArrayOutputStream();
          } else {
              String filePath = uploadDirectory.getPath() + File.separator;
              String fileName =
                      new File((String) headers.get("filename")).getName();
  
              file = new File(filePath + fileName);
  
              if (file.exists()) {
                  if (!allowOverwrite) {
                      if (silentlyRename) {
                          int c = 0;
  
                          do {
                              file = new File(filePath + c++ + "_" + fileName);
                          } while (file.exists());
                      } else {
                          throw new MultipartException("Duplicate file "
                                  + file.getName() + ".");
                      }
                  }
              }
  
              out = new FileOutputStream(file);
          }
  
          int read = 0;
  
          while (in.getState() == TokenStream.STATE_READING) {    // read data
              read = in.read(buf);
  
              out.write(buf, 0, read);
          }
  
          out.close();
  
          if (file == null) {
              byte[] bytes = ((ByteArrayOutputStream) out).toByteArray();
  
              put(headers.get("name"),
                      new FilePartArray(headers, new ByteArrayInputStream(bytes)));
          } else {
              put(headers.get("name"), new FilePartFile(headers, file));
          }
      }
  
      /**
       * Parse an inline part
       *
       * @param in
       * @param headers
       *
       * @throws IOException
       */
      private void parseInlinePart(TokenStream in, Hashtable headers)
              throws IOException {
  
          byte[] buf = new byte[INLINE_BUFFER_SIZE];
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          StringBuffer value = new StringBuffer();
  
          while (in.getState() == TokenStream.STATE_READING) {
              int read = in.read(buf);
  
              value.append(new String(buf, 0, read));
          }
  
          String field = (String) headers.get("name");
          Vector v = (Vector) get(field);
  
          if (v == null) {
              v = new Vector();
  
              put(field, v);
          }
  
          v.add(value.toString());
      }
  
      /**
       * Read part headers
       *
       * @param in
       *
       * @return
       *
       * @throws IOException
       */
      private Hashtable readHeaders(TokenStream in) throws IOException {
  
          Hashtable headers = new Hashtable();
          String hdrline = readln(in);
  
          while (!"".equals(hdrline)) {
              StringTokenizer tokenizer = new StringTokenizer(hdrline);
  
              headers.put(tokenizer.nextToken(" :").toLowerCase(),
                      tokenizer.nextToken(" :;"));
  
              while (tokenizer.hasMoreTokens()) {
                  headers.put(tokenizer.nextToken(" ;=\""),
                          tokenizer.nextToken("=\""));
              }
  
              hdrline = readln(in);
          }
  
          return headers;
      }
  
      /**
       * Get boundary from contentheader
       *
       * @param hdr
       *
       * @return
       */
      private String getBoundary(String hdr) {
  
          int start = hdr.toLowerCase().indexOf("boundary=");
  
          if (start > -1) {
              return "--" + hdr.substring(start + 9);
          } else {
              return null;
          }
      }
  
      /**
       * Read string until newline or end of stream
       *
       * @param in
       *
       * @return
       *
       * @throws IOException
       */
      private String readln(TokenStream in) throws IOException {
  
          StringBuffer out = new StringBuffer();
          int b = in.read();
  
          while ((b != -1) && (b != '\r')) {
              out.append((char) b);
  
              b = in.read();
          }
  
          if (b == '\r') {
              in.read();    // read '\n'
          }
  
          return out.toString();
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/MultipartRequestWrapper.java
  
  Index: MultipartRequestWrapper.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import javax.servlet.RequestDispatcher;
  import javax.servlet.ServletInputStream;
  import javax.servlet.ServletRequest;
  import javax.servlet.http.Cookie;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpSession;
  import java.io.BufferedReader;
  import java.io.File;
  import java.io.IOException;
  import java.security.Principal;
  import java.util.Enumeration;
  import java.util.Locale;
  import java.util.Map;
  import java.util.Vector;
  
  /**
   * Servlet request wrapper for multipart parser.
   *
   * @author Jeroen ter Voorde
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: MultipartRequestWrapper.java,v 1.1 2002/02/27 20:21:22 dims Exp 
$
   */
  public class MultipartRequestWrapper
          implements ServletRequest, HttpServletRequest {
  
      /** Field CONTENTHEADER           */
      private final String CONTENTHEADER = "multipart/form-data";
  
      /** Field request           */
      private HttpServletRequest request = null;
  
      /** Field values           */
      private MultipartParser values = null;
  
      /**
       * Constructor MultipartRequestWrapper
       *
       * @param request
       * @param saveUploadedFilesToDisk
       * @param uploadDirectory
       * @param allowOverwrite
       * @param silentlyRename
       * @param maxUploadSize
       *
       * @throws IOException
       * @throws MultipartException
       */
      public MultipartRequestWrapper(
              HttpServletRequest request, boolean saveUploadedFilesToDisk, File 
uploadDirectory, boolean allowOverwrite, boolean silentlyRename, int maxUploadSize)
              throws IOException, MultipartException {
  
          this.request = request;
  
          String contentType = request.getContentType();
  
          if ((contentType != null)
                  && (contentType.toLowerCase().indexOf(CONTENTHEADER) > -1)) {
              values = new MultipartParser(request, saveUploadedFilesToDisk,
                      uploadDirectory, allowOverwrite,
                      silentlyRename, maxUploadSize);
          }
      }
  
      /**
       * Method get
       *
       * @param name
       *
       * @return
       */
      public Object get(String name) {
  
          Object result = null;
  
          if (values != null) {
              result = values.get(name);
  
              if (result instanceof Vector) {
                  if (((Vector) result).size() == 1) {
                      return ((Vector) result).elementAt(0);
                  } else {
                      return result;
                  }
              }
          } else {
              String[] array = request.getParameterValues(name);
              Vector vec = new Vector();
  
              if (array != null) {
                  for (int i = 0; i < array.length; i++) {
                      vec.addElement(array[i]);
                  }
  
                  if (vec.size() == 1) {
                      result = vec.elementAt(0);
                  } else {
                      result = vec;
                  }
              }
          }
  
          return result;
      }
  
      /**
       * Method getParameterNames
       *
       * @return
       */
      public Enumeration getParameterNames() {
  
          if (values != null) {
              return values.keys();
          } else {
              return request.getParameterNames();
          }
      }
  
      /**
       * Method getParameter
       *
       * @param name
       *
       * @return
       */
      public String getParameter(String name) {
  
          Object value = get(name);
          String result = null;
  
          if (value != null) {
              if (value instanceof Vector) {
                  value = ((Vector) value).elementAt(0);
              }
  
              result = value.toString();
          }
  
          return result;
      }
  
      /**
       * Method getParameterValues
       *
       * @param name
       *
       * @return
       */
      public String[] getParameterValues(String name) {
  
          if (values != null) {
              Object value = get(name);
  
              if (value != null) {
                  if (value instanceof Vector) {
                      return (String[]) ((Vector) value).toArray();
                  } else {
                      return new String[]{value.toString()};
                  }
              }
  
              return null;
          } else {
              return request.getParameterValues(name);
          }
      }
  
      /**
       * Method getRequest
       *
       * @return
       */
      public HttpServletRequest getRequest() {
          return request;
      }
  
      /**
       * Method getAttribute
       *
       * @param name
       *
       * @return
       */
      public Object getAttribute(String name) {
          return request.getAttribute(name);
      }
  
      /**
       * Method getAttributeNames
       *
       * @return
       */
      public Enumeration getAttributeNames() {
          return request.getAttributeNames();
      }
  
      /**
       * Method getCharacterEncoding
       *
       * @return
       */
      public String getCharacterEncoding() {
          return request.getCharacterEncoding();
      }
  
      /**
       * Method getContentLength
       *
       * @return
       */
      public int getContentLength() {
          return request.getContentLength();
      }
  
      /**
       * Method getContentType
       *
       * @return
       */
      public String getContentType() {
          return request.getContentType();
      }
  
      /**
       * Method getInputStream
       *
       * @return
       *
       * @throws IOException
       */
      public ServletInputStream getInputStream() throws IOException {
          return request.getInputStream();
      }
  
      /**
       * Method getProtocol
       *
       * @return
       */
      public String getProtocol() {
          return request.getProtocol();
      }
  
      /**
       * Method getScheme
       *
       * @return
       */
      public String getScheme() {
          return request.getScheme();
      }
  
      /**
       * Method getServerName
       *
       * @return
       */
      public String getServerName() {
          return request.getServerName();
      }
  
      /**
       * Method getServerPort
       *
       * @return
       */
      public int getServerPort() {
          return request.getServerPort();
      }
  
      /**
       * Method getReader
       *
       * @return
       *
       * @throws IOException
       */
      public BufferedReader getReader() throws IOException {
          return request.getReader();
      }
  
      /**
       * Method getRemoteAddr
       *
       * @return
       */
      public String getRemoteAddr() {
          return request.getRemoteAddr();
      }
  
      /**
       * Method getRemoteHost
       *
       * @return
       */
      public String getRemoteHost() {
          return request.getRemoteHost();
      }
  
      /**
       * Method setAttribute
       *
       * @param name
       * @param o
       */
      public void setAttribute(String name, Object o) {
          request.setAttribute(name, o);
      }
  
      /**
       * Method removeAttribute
       *
       * @param name
       */
      public void removeAttribute(String name) {
          request.removeAttribute(name);
      }
  
      /**
       * Method getLocale
       *
       * @return
       */
      public Locale getLocale() {
          return request.getLocale();
      }
  
      /**
       * Method getLocales
       *
       * @return
       */
      public Enumeration getLocales() {
          return request.getLocales();
      }
  
      /**
       * Method isSecure
       *
       * @return
       */
      public boolean isSecure() {
          return request.isSecure();
      }
  
      /**
       * Method getRequestDispatcher
       *
       * @param path
       *
       * @return
       */
      public RequestDispatcher getRequestDispatcher(String path) {
          return request.getRequestDispatcher(path);
      }
  
      /**
       * Method getRealPath
       *
       * @param path
       *
       * @return
       */
      public String getRealPath(String path) {
          return request.getRealPath(path);
      }
  
      /**
       * Method getAuthType
       *
       * @return
       */
      public String getAuthType() {
          return request.getAuthType();
      }
  
      /**
       * Method getCookies
       *
       * @return
       */
      public Cookie[] getCookies() {
          return request.getCookies();
      }
  
      /**
       * Method getDateHeader
       *
       * @param name
       *
       * @return
       */
      public long getDateHeader(String name) {
          return request.getDateHeader(name);
      }
  
      /**
       * Method getHeader
       *
       * @param name
       *
       * @return
       */
      public String getHeader(String name) {
          return request.getHeader(name);
      }
  
      /**
       * Method getHeaders
       *
       * @param name
       *
       * @return
       */
      public Enumeration getHeaders(String name) {
          return request.getHeaders(name);
      }
  
      /**
       * Method getHeaderNames
       *
       * @return
       */
      public Enumeration getHeaderNames() {
          return request.getHeaderNames();
      }
  
      /**
       * Method getIntHeader
       *
       * @param name
       *
       * @return
       */
      public int getIntHeader(String name) {
          return request.getIntHeader(name);
      }
  
      /**
       * Method getMethod
       *
       * @return
       */
      public String getMethod() {
          return request.getMethod();
      }
  
      /**
       * Method getPathInfo
       *
       * @return
       */
      public String getPathInfo() {
          return request.getPathInfo();
      }
  
      /**
       * Method getPathTranslated
       *
       * @return
       */
      public String getPathTranslated() {
          return request.getPathTranslated();
      }
  
      /**
       * Method getContextPath
       *
       * @return
       */
      public String getContextPath() {
          return request.getContextPath();
      }
  
      /**
       * Method getQueryString
       *
       * @return
       */
      public String getQueryString() {
          return request.getQueryString();
      }
  
      /**
       * Method getRemoteUser
       *
       * @return
       */
      public String getRemoteUser() {
          return request.getRemoteUser();
      }
  
      /**
       * Method isUserInRole
       *
       * @param role
       *
       * @return
       */
      public boolean isUserInRole(String role) {
          return request.isUserInRole(role);
      }
  
      /**
       * Method getUserPrincipal
       *
       * @return
       */
      public Principal getUserPrincipal() {
          return request.getUserPrincipal();
      }
  
      /**
       * Method getRequestedSessionId
       *
       * @return
       */
      public String getRequestedSessionId() {
          return request.getRequestedSessionId();
      }
  
      /**
       * Method getRequestURI
       *
       * @return
       */
      public String getRequestURI() {
          return request.getRequestURI();
      }
  
      /**
       * Method getServletPath
       *
       * @return
       */
      public String getServletPath() {
          return request.getServletPath();
      }
  
      /**
       * Method getSession
       *
       * @param create
       *
       * @return
       */
      public HttpSession getSession(boolean create) {
          return request.getSession(create);
      }
  
      /**
       * Method getSession
       *
       * @return
       */
      public HttpSession getSession() {
          return request.getSession();
      }
  
      /**
       * Method isRequestedSessionIdValid
       *
       * @return
       */
      public boolean isRequestedSessionIdValid() {
          return request.isRequestedSessionIdValid();
      }
  
      /**
       * Method isRequestedSessionIdFromCookie
       *
       * @return
       */
      public boolean isRequestedSessionIdFromCookie() {
          return request.isRequestedSessionIdFromCookie();
      }
  
      /**
       * Method isRequestedSessionIdFromURL
       *
       * @return
       */
      public boolean isRequestedSessionIdFromURL() {
          return request.isRequestedSessionIdFromURL();
      }
  
      /**
       * Method isRequestedSessionIdFromUrl
       *
       * @return
       */
      public boolean isRequestedSessionIdFromUrl() {
          return request.isRequestedSessionIdFromURL();
      }
  
      /**
       * Method getParameterMap
       *
       * @return
       */
      public Map getParameterMap() {
          // FIXME:
          return null;
      }
  
      /**
       * Method setCharacterEncoding
       *
       * @param s
       */
      public void setCharacterEncoding(String s) {
          // FIXME:
      }
  
      /**
       * Method getRequestURL
       *
       * @return
       */
      public StringBuffer getRequestURL() {
          // FIXME:
          return null;
      }
  }
  
  
  
  1.1                  
xml-cocoon2/src/java/org/apache/cocoon/components/request/multipart/TokenStream.java
  
  Index: TokenStream.java
  ===================================================================
  /*
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
  
   Copyright (C) 1999-2002 The Apache Software Foundation. All rights reserved.
  
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
  
   1. Redistributions of  source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
  
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
  
   3. The end-user documentation included with the redistribution, if any, must
      include  the following  acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
  
   4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not  be
      used to  endorse or promote  products derived from  this software without
      prior written permission. For written permission, please contact
      [EMAIL PROTECTED]
  
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
  
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software  consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software  Foundation and was  originally created by
   Stefano Mazzocchi  <[EMAIL PROTECTED]>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
  */
  package org.apache.cocoon.components.request.multipart;
  
  import java.io.IOException;
  import java.io.PushbackInputStream;
  
  /**
   * Utility class for MultipartParser. Divides the inputstream into parts
   * separated by a given boundary.
   *
   * A newline is espected after each boundary and is parsed away.
   * @author <a href="mailto:[EMAIL PROTECTED]";>Jeroen ter Voorde</a>
   * @version CVS $Id: TokenStream.java,v 1.1 2002/02/27 20:21:22 dims Exp $
   */
  class TokenStream extends PushbackInputStream {
  
      /**
       * Initial state, no boundary has been set.
       */
      public static final int STATE_NOBOUNDARY = -1;
  
      /**
       * Fully read a part, now at the beginning of a new part
       */
      public static final int STATE_NEXTPART = -2;
  
      /**
       * Read last boundary, end of multipart block
       */
      public static final int STATE_ENDMULTIPART = -3;
  
      /**
       * End of stream, this should not happen
       */
      public static final int STATE_ENDOFSTREAM = -4;
  
      /**
       * Currently reading a part
       */
      public static final int STATE_READING = -5;
  
      /** Field in           */
      private PushbackInputStream in = null;
  
      /** Field boundary           */
      private byte[] boundary = null;
  
      /** Field state           */
      private int state = STATE_NOBOUNDARY;
  
      /**
       * Creates a new pushback token stream from in.
       *
       * @param in The input stream
       * @param pushbackSize Size (in bytes) of the pushback buffer
       */
      public TokenStream(PushbackInputStream in, int pushbackSize) {
          super(in, pushbackSize);
          this.in = in;
      }
  
      /**
       * Creates a new pushback token stream from in with pushback buffer size 1.
       *
       * @param in The input stream
       */
      public TokenStream(PushbackInputStream in) {
          this(in, 1);
      }
  
      /**
       * Sets the boundary to scan for
       *
       * @param boundary A byte array containg the boundary
       *
       * @throws MultipartException
       */
      public void setBoundary(byte[] boundary) throws MultipartException {
          this.boundary = boundary;
          if (state == STATE_NOBOUNDARY) {
              state = STATE_READING;
          }
      }
  
      /**
       * Start reading the next part in the stream. This method may only be called
       * if state is STATE_NEXTPART. It will throw a MultipartException if not.
       *
       * @throws MultipartException
       */
      public void nextPart() throws MultipartException {
          if (state != STATE_NEXTPART) {
              throw new MultipartException("Illegal state");
          }
          state = STATE_READING;
      }
  
      /**
       * Return the stream state
       *
       * @return
       */
      public int getState() {
          return state;
      }
  
      /**
       * Fill the ouput buffer until either it's full, the boundary has been reached or
       * the end of the inputstream has been reached.
       * When a boundary is reached it is entirely read away including trailing \r's 
and \n's.
       * It will not be written to the output buffer.
       * The stream state is updated after each call.
       *
       * @param out The output buffer
       *
       * @return
       *
       * @throws IOException
       */
      private int readToBoundary(byte[] out) throws IOException {
          if (state != STATE_READING) {
              return 0;
          }
          int boundaryIndex = 0;
          int read = 0;
          int written = 0;
          int b = in.read();
  
          while (true) {
              while ((byte) b != boundary[0]) {
                  if (b == -1) {
                      state = STATE_ENDOFSTREAM;
                      return written;
                  }
                  out[written++] = (byte) b;
  
                  if (written == out.length) {
                      return written;
                  }
                  b = in.read();
              }
              boundaryIndex = 0;                         // we know the first byte 
matched
              // check for boundary
              while ((boundaryIndex < boundary.length)
                      && ((byte) b == boundary[boundaryIndex])) {
                  b = in.read();
                  boundaryIndex++;
              }
  
              if (boundaryIndex == boundary.length) {    // matched boundary
                  if (b != -1) {
                      if (b == '\r') {                   // newline, another part 
follows
                          state = STATE_NEXTPART;
                          in.read();
                      } else if (b == '-') {             // hyphen, end of multipart
                          state = STATE_ENDMULTIPART;
                          in.read();                     // read next hyphen
                          in.read();                     // read \r
                          in.read();                     // read \n
                      } else {                           // something else, error
                          throw new IOException(
                                  "Unexpected character after boundary");
                      }
                  } else {    // nothing after boundary, this shouldn't happen either
                      state = STATE_ENDOFSTREAM;
                  }
                  return written;
              } else {                                   // did not match boundary
                  // bytes skipped, write first skipped byte, push back the rest
                  if (b != -1) {                         // b may be -1
                      in.unread(b);                      // the non-matching byte
                  }
                  in.unread(boundary, 1,
                          boundaryIndex - 1);          // unread skipped boundary data
                  out[written++] = boundary[0];
                  if (written == out.length) {
                      return written;
                  }
              }
              b = in.read();
          }
      }
  
      /**
       * @see java.io.InputStream#read(byte[])
       *
       * @param out
       *
       * @return
       *
       * @throws IOException
       */
      public int read(byte[] out) throws IOException {
          if (state != STATE_READING) {
              return 0;
          }
          return readToBoundary(out);
      }
  
      /**
       * @see java.io.InputStream#read(byte[],int,int)
       *
       * @param out
       * @param off
       * @param len
       *
       * @return
       *
       * @throws IOException
       */
      public int read(byte[] out, int off, int len) throws IOException {
          if ((off < 0) || (off >= out.length)) {
              throw new IOException("Buffer offset outside buffer");
          }
          if (off + len >= out.length) {
              throw new IOException("Buffer end outside buffer");
          }
          if (len < 0) {
              throw new IOException("Length must be a positive integer");
          }
          byte[] buf = new byte[len];
          int read = read(buf);
          if (read > 0) {
              System.arraycopy(buf, 0, out, off, read);
          }
          return read;
      }
  
      /**
       * @see java.io.InputStream#read()
       *
       * @return
       *
       * @throws IOException
       */
      public int read() throws IOException {
          byte[] buf = new byte[1];
          int read = read(buf);
  
          if (read == 0) {
              return -1;
          } else {
              return (int) buf[0];
          }
      }
  }
  
  
  
  1.5       +4 -2      xml-cocoon2/src/webapp/WEB-INF/web.xml
  
  Index: web.xml
  ===================================================================
  RCS file: /home/cvs/xml-cocoon2/src/webapp/WEB-INF/web.xml,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- web.xml   24 Feb 2002 11:10:58 -0000      1.4
  +++ web.xml   27 Feb 2002 20:21:23 -0000      1.5
  @@ -194,11 +194,13 @@
       -->
   
       <!--
  -      This parameter allows you to select the request factory.
  +      This parameter allows you to select the request factory. Possible choices are 
as follows:
  +          - org.apache.cocoon.components.request.MultipartRequestFactoryImpl
  +          - org.apache.cocoon.components.request.MaybeUploadRequestFactoryImpl
       -->
       <init-param>
         <param-name>request-factory</param-name>
  -      
<param-value>org.apache.cocoon.components.request.MaybeUploadRequestFactoryImpl</param-value>
  +      
<param-value>org.apache.cocoon.components.request.MultipartRequestFactoryImpl</param-value>
       </init-param>
   
       <!--
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to