001: /*
002: * PushHandler.java
003: *
004: * Brazil project web application Framework,
005: * export version: 1.1
006: * Copyright (c) 1999-2000 Sun Microsystems, Inc.
007: *
008: * Sun Public License Notice
009: *
010: * The contents of this file are subject to the Sun Public License Version
011: * 1.0 (the "License"). You may not use this file except in compliance with
012: * the License. A copy of the License is included as the file "license.terms",
013: * and also available at http://www.sun.com/
014: *
015: * The Original Code is from:
016: * Brazil project web application Framework release 1.1.
017: * The Initial Developer of the Original Code is: suhler.
018: * Portions created by suhler are Copyright (C) Sun Microsystems, Inc.
019: * All Rights Reserved.
020: *
021: * Contributor(s): cstevens, suhler.
022: *
023: * Version: 1.9
024: * Created by suhler on 99/08/04
025: * Last modified by suhler on 00/12/11 13:28:16
026: */
027:
028: package sunlabs.brazil.handler;
029:
030: import java.io.IOException;
031: import sunlabs.brazil.server.Handler;
032: import sunlabs.brazil.server.Request;
033: import sunlabs.brazil.server.Server;
034:
035: /**
036: * Skeleton Handler for uploading files using multipart/form-data.
037: * Application specific functionallity is added by overriding
038: * {@link #processData}.
039: * <p>
040: * Properties:
041: * <dl class=props>
042: * <dt>prefix <dd> The URL prefix required for all documents
043: * </dl>
044: *
045: * @author Stephen Uhler
046: * @version 1.9, 00/12/11
047: */
048:
049: public class PushHandler implements Handler {
050: public String urlPrefix; // The url prefix that triggers this handler
051:
052: /**
053: * Handler configuration property <b>prefix</b>.
054: * Only URL's that begin with this string are considered by this handler.
055: * The default is (/).
056: */
057: static final String PREFIX = "prefix"; // URL prefix for proxy
058:
059: public boolean init(Server server, String prefix) {
060: urlPrefix = server.props.getProperty(prefix + PREFIX, "/");
061: return true;
062: }
063:
064: /**
065: * Make sure this is one of our requests.
066: * IF OK, save file to proper spot.
067: */
068:
069: public boolean respond(Request request) throws IOException {
070:
071: String type = (String) request.headers.get("content-type");
072: if (!request.url.startsWith(urlPrefix)
073: || !type.startsWith("multipart/form-data")) {
074: return false;
075: }
076:
077: /*
078: * screen out bad requests
079: */
080:
081: if (request.postData == null) {
082: request.sendError(400, "No content to put");
083: return true;
084: }
085:
086: if (request.headers.get("Content-Range") != null) {
087: request.sendError(501, "Can't handle partial puts");
088: return true;
089: }
090: return processData(request);
091: }
092:
093: /**
094: * process the data - this doesn't currently do anything useful.
095: */
096:
097: public boolean processData(Request request) {
098: Split s = new Split(request.postData);
099: while (s.nextPart()) {
100: System.out.println(s.name() + ": {" + s.content() + "}");
101: }
102: return false;
103: }
104:
105: /**
106: * Split multipart data into its constituent pieces. Use byte[] so we can
107: * handle (potentially) large amounts of binary data.
108: * This acts as an iterator, stepping through the parts, extracting the appropriate
109: * info for eacxh part.
110: */
111:
112: public static class Split {
113: byte[] bytes;
114: int bndryEnd; // end of the initial boundary line
115: int partStart; // start index of this part
116: int partEnd; // index to the end of this part
117: int contentStart; // start of the content
118:
119: /**
120: * create a new multipart form thingy
121: */
122:
123: public Split(byte[] bytes) {
124: partEnd = 0;
125: this .bytes = bytes;
126: bndryEnd = indexOf(bytes, 0, bytes.length, "\r\n");
127: partStart = 0;
128: contentStart = 0;
129: }
130:
131: /**
132: * Return true if there is a next part
133: */
134:
135: public boolean nextPart() {
136: partStart = partEnd + bndryEnd + 2;
137: if (partStart >= bytes.length) {
138: return false;
139: }
140: partEnd = indexOf(bytes, partStart, bytes.length, bytes, 0,
141: bndryEnd);
142: if (partEnd < 0) {
143: return false;
144: }
145: partEnd -= 2; // back over \r\n
146: contentStart = indexOf(bytes, partStart, bytes.length,
147: "\r\n\r\n") + 4;
148: return true;
149: }
150:
151: /**
152: * Get the content as a string
153: */
154:
155: public String content() {
156: return new String(bytes, contentStart, partEnd
157: - contentStart);
158: }
159:
160: /**
161: * Return the content length
162: */
163:
164: public int length() {
165: return partEnd - contentStart;
166: }
167:
168: /**
169: * return the index into the start of the data for this part
170: */
171:
172: public int start() {
173: return contentStart;
174: }
175:
176: /**
177: * Return the header as a string
178: */
179:
180: public String header() {
181: return (new String(bytes, partStart, contentStart
182: - partStart));
183: }
184:
185: /**
186: * get the part name
187: */
188:
189: public String name() {
190: int start = indexOf(bytes, partStart, contentStart,
191: "name=\"") + 6;
192: int end = indexOf(bytes, start, contentStart, "\"");
193: if (start >= 6 && end >= 0) {
194: return (new String(bytes, start, end - start));
195: } else {
196: return null;
197: }
198: }
199: }
200:
201: /**
202: * Find the index of dst in src or -1 if not found >
203: * This is the byte array equivalent to string.indexOf()
204: */
205:
206: public static int indexOf(byte[] src, int srcStart, int srcEnd,
207: byte[] dst, int dstStart, int dstEnd) {
208: int len = dstEnd - dstStart; // len of to look for
209: srcEnd -= len;
210: for (; srcStart < srcEnd; srcStart++) {
211: boolean ok = true;
212: for (int i = 0; ok && i < len; i++) {
213: if (dst[i + dstStart] != src[srcStart + i]) {
214: ok = false;
215: }
216: }
217: if (ok) {
218: return srcStart;
219: }
220: }
221: return -1;
222: }
223:
224: public static int indexOf(byte[] src, int srcStart, int srcEnd,
225: String dst) {
226: return (indexOf(src, srcStart, srcEnd, dst.getBytes(), 0, dst
227: .length()));
228: }
229: }
|