All Downloads are FREE. Search and download functionalities are using the official Maven repository.

w3c.css.util.Codecs Maven / Gradle / Ivy

There is a newer version: 1.0.8
Show newest version
//
// $Id$
// From Philippe Le Hegaret ([email protected])
//
// (c) COPYRIGHT MIT and INRIA, 1997.
// Please first read the full copyright statement in file COPYRIGHT.html
/*
 * Be Careful this version is not the original version.
 * I modified some sources.          Philippe Le Hegaret
 *
 * @(#)Codecs.java					0.2-2 23/03/1997
 *
 *  This file is part of the HTTPClient package
 *  Copyright (C) 1996,1997  Ronald Tschalaer
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public
 *  License along with this library; if not, write to the Free
 *  Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 *  MA 02111-1307, USA
 *
 *  For questions, suggestions, bug-reports, enhancement-requests etc.
 *  I may be contacted at:
 *
 *  [email protected]
 *  [email protected]
 *
 */

package org.w3c.css.util;

import java.io.IOException;

/**
 * This class collects various encoders and decoders.
 *
 * @author Ronald Tschalär
 * @version 0.2 (bug fix 2)  23/03/1997
 */

public class Codecs {

    /**
     * I have problems with multipart/form-data so I integrated auto-debug here
     */
    private static boolean debugMode = false;

    // Constructors

    /**
     * This class isn't meant to be instantiated.
     */
    private Codecs() {
    }


    // Methods

    /**
     * This method decodes a multipart/form-data encoded string. The boundary
     * is parsed from the cont_type parameter, which must be of the
     * form 'multipart/form-data; boundary=...'.
     * 
Any encoded files are created in the directory specified by * dir using the encoded filename. *
Note: Does not handle nested encodings (yet). *
Example: *
     * NVPair[] opts = Codecs.mpFormDataDecode(resp.getData(),
     * resp.getHeader("Content-length"),
     * ".");
     * 
* Assuming the data received looked something like: *
     * -----------------------------114975832116442893661388290519
     * Content-Disposition: form-data; name="option"
     *  
     * doit
     * -----------------------------114975832116442893661388290519
     * Content-Disposition: form-data; name="comment"; filename="comment.txt"
     *  
     * Gnus and Gnats are not Gnomes.
     * -----------------------------114975832116442893661388290519--
     * 
* you would get one file called comment.txt in the current * directory, and opts would contain two elements: {"option", "doit"} * and {"comment", "comment.txt"} * * @param data the form-data to decode. * @param cont_type the content type header (must contain the * boundary string). * @return an array of name/value pairs, one for each part; * the name is the 'name' attribute given in the * Content-Disposition header; the value is either * the name of the file if a filename attribute was * found, or the contents of the part. * @throws IOException If any file operation fails. */ public final static synchronized NVPair[] mpFormDataDecode(byte[] data, String cont_type) throws IOException { // Find and extract boundary string String bndstr = getParameter("boundary", cont_type); if (bndstr == null) { throw new IOException("\'boundary\' parameter " + "not found in Content-type: " + cont_type); } byte[] srtbndry = new byte[bndstr.length() + 4], boundary = new byte[bndstr.length() + 6], endbndry = new byte[bndstr.length() + 6]; srtbndry = ("--" + bndstr + "\n").getBytes(); boundary = ("\n--" + bndstr + "\n").getBytes(); endbndry = ("\n--" + bndstr + "--").getBytes(); if (debugMode) { System.err.println("[START OF DATA]"); printData(data); System.err.println("[END OF DATA]"); System.err.print("boundary : "); printData(srtbndry); System.err.println(); printData(boundary); System.err.println(); printData(endbndry); System.err.println(); } // slurp // setup search routines int[] bs = Util.compile_search(srtbndry); int[] bc = Util.compile_search(boundary); int[] be = Util.compile_search(endbndry); // let's start parsing the actual data int start = Util.findStr(srtbndry, bs, data, 0, data.length); if (start == -1) { // didn't even find the start if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; throw new IOException("Starting boundary not found: " + new String(srtbndry)); } } start += srtbndry.length; NVPair[] res = new NVPair[10]; boolean done = false; int idx; for (idx = 0; !done; idx++) { // find end of this part int end = Util.findStr(boundary, bc, data, start, data.length); if (end == -1) { // must be the last part end = Util.findStr(endbndry, be, data, start, data.length); if (end == -1) { /* if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; System.err.println( "[Ending boundary not found in]" ); printData(data, start); System.err.println( "[END DATA BOUNDARY SEARCH]"); throw new IOException("Ending boundary not found: " + new String(endbndry)); */ end = data.length - 1; while (end >= 0 && (data[end] == '\n' || data[end] == ' ')) { end--; } end++; /* } */ } done = true; } // parse header(s) String hdr, lchdr, name = null, filename = null, cont_disp = null, mimeType = null; Object value; while (true) { int next = findEOL(data, start) + 1; if (next - 1 <= start) break; // empty line -> end of headers hdr = new String(data, start, next - 1 - start); if (debugMode) { System.err.println(" start = " + start + " end = " + next); } // handle line continuation byte ch; while (next < data.length - 1 && ((ch = data[next]) == ' ' || ch == '\t')) { next = findEOL(data, start) + 1; String result = new String(data, start, next - 1 - start); hdr += result; start = next; } start = next; if (debugMode) { System.err.println("hdr=" + hdr); System.err.println("(New) start = " + start + " end = " + next); } lchdr = hdr.toLowerCase(); if (lchdr.startsWith("content-type")) { mimeType = lchdr.substring("content-type: ".length()); continue; } else if (!lchdr.startsWith("content-disposition")) continue; int off = lchdr.indexOf("form-data", 20); if (off == -1) { if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; throw new IOException("Expected \'Content-Disposition: form-data\' in line: " + hdr); } } name = getParameter("name", hdr); if (debugMode) { System.err.println("[ADD name is " + name + ']'); } if (name == null) { if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; throw new IOException("\'name\' parameter not found in header: " + hdr); } } filename = getParameter("filename", hdr); if (debugMode) { System.err.println("[ADD filename is " + filename + ']'); } cont_disp = hdr; } start += 1; if (debugMode) { System.err.println("(End) start = " + start + " end = " + end); } if (start > end) { if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; throw new IOException("End of header not found at offset " + end); } } if (cont_disp == null) { if (!debugMode) { debugMode = true; mpFormDataDecode(data, cont_type); return null; } else { debugMode = false; throw new IOException("Missing \'Content-Disposition\' header at offset " + start); } } // handle data for this part if (filename != null) { // It's a file FakeFile file = new FakeFile(filename); file.write(data, start, end - start); file.setContentType(mimeType); value = file; } else { // It's simple data value = new String(data, start, end - start); } if (idx >= res.length) { res = Util.resizeArray(res, idx + 10); } res[idx] = new NVPair(name, value); if (debugMode) { System.err.println("[ADD " + name + ',' + value + ',' + value.getClass() + ']'); } start = end + boundary.length; } return Util.resizeArray(res, idx); } /** * retrieves the value associated with the parameter param in * a given header string. This is used especially in headers like * 'Content-type' and 'Content-Disposition'. Here is the syntax it * expects:
* ";" param "=" ( token | quoted-string ) * * @param param the parameter name * @param hdr the header value * @return the value for this parameter, or null if not found. */ public final static String getParameter(String param, String hdr) { int pbeg, // parameter name begin pend, // parameter name end vbeg, // parameter value begin vend = -1, // parameter value end len = hdr.length(); param = param.trim(); while (true) { // mark parameter name if (debugMode) { System.err.println("[DEBUG] looks for " + param + " in "); System.err.println("[" + hdr.substring(vend + 1) + ']'); } if (vend == -1) { pbeg = hdr.indexOf(';', vend + 1); // get ';' if (pbeg == -1) return null; } else { pbeg = vend + 1; } while (pbeg < len - 1 && (Util.isWhiteSpace(hdr.charAt(pbeg)) || (hdr.charAt(pbeg) == ';'))) { pbeg++; } if (pbeg == len - 1) return null; pend = hdr.indexOf('=', pbeg + 1); // get '=' if (pend == -1) return null; vbeg = pend + 1; while (Util.isWhiteSpace(hdr.charAt(--pend))) ; pend++; if (debugMode) { System.err.println("[DEBUG] p is [" + hdr.substring(pbeg, pend) + "]"); } // mark parameter value while (vbeg < len && Util.isWhiteSpace(hdr.charAt(vbeg))) vbeg++; if (vbeg == len) return null; vend = vbeg; if (hdr.charAt(vbeg) == '\"') { // is a quoted-string vbeg++; vend = hdr.indexOf('\"', vbeg); if (vend == -1) return null; } else { // is a simple token vend = hdr.indexOf(';', vbeg); if (vend == -1) vend = hdr.length(); while (Util.isWhiteSpace(hdr.charAt(--vend))) ; vend++; } if (hdr.regionMatches(true, pbeg, param, 0, pend - pbeg)) { break; // found it } } return hdr.substring(vbeg, vend); } private static void printData(byte[] data) { printData(data, 0); } private static void printData(byte[] data, int offset) { for (int i = offset; i < data.length; i++) { if (data[i] == '\n' || data[i] == '\r') { System.err.print("&" + ((int) data[i])); System.err.println(); } else { System.err.print((char) data[i]); } } } /** * Searches for the next LF in an array. * * @param arr the byte array to search. * @param off the offset at which to start the search. * @return the position of the CR or (arr.length-2) if not found */ private final static int findEOL(byte[] arr, int off) { while (off < arr.length - 1 && !(arr[off++] == '\n')) ; return off - 1; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy