001: /*
002: * JFolder, Copyright 2001-2006 Gary Steinmetz
003: *
004: * Distributable under LGPL license.
005: * See terms of license at gnu.org.
006: */
007:
008: package org.jfolder.common.utils.web;
009:
010: //base classes
011: import java.io.ByteArrayInputStream;
012: import java.io.ByteArrayOutputStream;
013: import java.io.File;
014: import java.io.FileInputStream;
015: import java.io.FileOutputStream;
016: import java.io.IOException;
017: import java.io.InputStream;
018: import java.io.OutputStream;
019: import java.io.UnsupportedEncodingException;
020: import java.util.Enumeration;
021: import java.util.List;
022: import java.util.StringTokenizer;
023: import java.util.zip.ZipEntry;
024: import java.util.zip.ZipInputStream;
025: import java.util.zip.ZipOutputStream;
026: import javax.servlet.ServletInputStream;
027: import javax.servlet.http.HttpServletRequest;
028:
029: //project specific classes
030: import org.jfolder.common.ImmutableByteArray;
031: import org.jfolder.common.UnexpectedSystemException;
032: import org.jfolder.common.utils.misc.MiscHelper;
033:
034: //other classes
035: import org.apache.commons.fileupload.FileItem;
036: import org.apache.commons.fileupload.FileUpload;
037: import org.apache.commons.fileupload.FileUploadException;
038: import org.apache.commons.fileupload.disk.DiskFileItemFactory;
039:
040: public class ParameterHelper {
041:
042: private ParameterHelper() {
043: }
044:
045: public final static void zipDirectory(File inDirName,
046: OutputStream inOs) throws IOException {
047:
048: ZipOutputStream zos = new ZipOutputStream(inOs);
049: zipDirectory(inDirName, inDirName, zos);
050: zos.flush();
051: zos.close();
052: }
053:
054: private final static void zipDirectory(File inBaseDir,
055: File inCurrentDir, ZipOutputStream inZos)
056: throws IOException {
057:
058: File dirContents[] = inCurrentDir.listFiles();
059:
060: byte buffer[] = new byte[1024];
061:
062: for (int i = 0; i < dirContents.length; i++) {
063:
064: File nextFile = dirContents[i];
065:
066: if (nextFile.isFile()) {
067:
068: FileInputStream fis = new FileInputStream(nextFile);
069:
070: String entryName = nextFile
071: .getAbsolutePath()
072: .substring(
073: inBaseDir.getAbsolutePath().length() + 1);
074:
075: entryName = entryName.replace(File.separatorChar, '/');
076:
077: inZos.putNextEntry(new ZipEntry(entryName));
078:
079: int len = 0;
080:
081: while ((len = fis.read(buffer, 0, buffer.length)) != -1) {
082: inZos.write(buffer, 0, len);
083: }
084:
085: inZos.closeEntry();
086: fis.close();
087: } else {
088: zipDirectory(inBaseDir, nextFile, inZos);
089: }
090: }
091: }
092:
093: private final static void createDir(File inDir) {
094: if (!inDir.exists()) {
095: createDir(inDir.getParentFile());
096: inDir.mkdir();
097: }
098: }
099:
100: public final static void parseZipInfo(InputStream inIs,
101: File inBaseDir) throws IOException {
102:
103: ZipInputStream zis = new ZipInputStream(inIs);
104:
105: ZipEntry nextEntry = null;
106:
107: while ((nextEntry = zis.getNextEntry()) != null) {
108: String nextEntryName = nextEntry.getName();
109: nextEntryName = nextEntryName.replace('/',
110: File.separatorChar);
111: File nextEntryFile = new File(inBaseDir, nextEntryName);
112: if (nextEntry.isDirectory()) {
113: createDir(nextEntryFile);
114: } else {
115: createDir(nextEntryFile.getParentFile());
116: FileOutputStream fos = new FileOutputStream(
117: nextEntryFile);
118:
119: byte buffer[] = new byte[1024];
120: int len = 0;
121: while ((len = zis.read(buffer, 0, buffer.length)) != -1) {
122: fos.write(buffer, 0, len);
123: }
124:
125: fos.flush();
126: fos.close();
127: }
128: //MiscHelper.println(nextEntry.getName());
129: zis.closeEntry();
130: }
131:
132: zis.close();
133: }
134:
135: //parseHttpParameters
136: //
137: public final static ParameterSet getParameterSet(
138: HttpServletRequest inRequest) throws IOException {
139:
140: try {
141: ParameterSet outValue = new ParameterSet();
142:
143: ByteArrayOutputStream baos = new ByteArrayOutputStream();
144: InputStream servletIs = inRequest.getInputStream();
145: byte servletBuffer[] = new byte[1024 * 4];
146: int servletRead = 0;
147: while ((servletRead = servletIs.read(servletBuffer, 0,
148: servletBuffer.length)) != -1) {
149: baos.write(servletBuffer, 0, servletRead);
150: }
151: byte content[] = baos.toByteArray();
152: ImmutableByteArray iba = ImmutableByteArray.newInstance(
153: content, false);
154: outValue.addContent(iba);
155: ByteArrayInputStream bais = new ByteArrayInputStream(
156: content);
157:
158: ParameterRequestContext prc = ParameterRequestContext
159: .newInstance(bais, inRequest.getContentType(),
160: inRequest.getContentLength(), inRequest
161: .getCharacterEncoding());
162:
163: int s = 1024 * 1024 * 16;
164: DiskFileItemFactory dfif = new DiskFileItemFactory(s,
165: new File("./"));
166: FileUpload fu = new FileUpload(dfif);
167: fu.setSizeMax(s);
168: if (fu.isMultipartContent(prc)) {
169: String encoding = fu.getHeaderEncoding();
170: outValue.setEncoding(encoding);
171: //
172: List params = fu.parseRequest(prc);
173: for (int i = 0; i < params.size(); i++) {
174: ParameterHolder ph = new ParameterHolder();
175: FileItem nextItem = (FileItem) params.get(i);
176: if (nextItem.isFormField()) {
177: ph.setName(nextItem.getFieldName());
178: if (encoding != null) {
179: ph.setValue(nextItem.getString(encoding));
180: } else {
181: ph.setValue(nextItem.getString());
182: }
183: } else {
184: ph.setName(nextItem.getFieldName());
185: ph.setValue(nextItem.get());
186: ph.setFileName(nextItem.getName());
187: //MiscHelper.println(
188: // "ParamHelp name = " + nextItem.getName());
189: //MiscHelper.println(
190: // "ParamHelp name = " + nextItem.getName());
191: //MiscHelper.println(
192: // "ParamHelp name = " + nextItem.getName());
193: }
194: outValue.addParameterHolder(ph);
195: }
196: } else {
197: Enumeration params = inRequest.getParameterNames();
198: while (params.hasMoreElements()) {
199: String nextParam = (String) params.nextElement();
200: String nextParamValues[] = inRequest
201: .getParameterValues(nextParam);
202: for (int i = 0; i < nextParamValues.length; i++) {
203: ParameterHolder ph = new ParameterHolder();
204: ph.setName(nextParam);
205: ph.setValue(nextParamValues[i]);
206: outValue.addParameterHolder(ph);
207: }
208:
209: }
210: }
211:
212: return outValue;
213: } catch (FileUploadException fue) {
214: throw new UnexpectedSystemException(fue);
215: }
216: }
217:
218: private final static ParameterSet getParameterSet2(
219: HttpServletRequest inRequest) throws IOException {
220:
221: ParameterSet outValue = new ParameterSet();
222:
223: //begin seperation
224:
225: boolean isMultiPart = isRequestMultipartFormData(inRequest);
226: //TO DO: how will multiple values for a parameter behave below??
227:
228: if (isMultiPart) {
229:
230: ServletInputStream sis = inRequest.getInputStream();
231:
232: String boundary = "--"
233: + getBoundary(inRequest.getContentType());
234: String endBoundary = boundary + "--";
235:
236: scrollToFirstPart(sis, boundary, endBoundary);
237:
238: boolean endBoundaryReached = false;
239: boolean boundaryReached = false;
240:
241: //beginning of function
242: do {
243: ParameterHolder ph = new ParameterHolder();
244:
245: boundaryReached = false;
246: boolean addCRLF = false;
247:
248: readHeaderPart(sis, ph);
249: ByteArrayOutputStream baos = new ByteArrayOutputStream();
250:
251: //beginning of function
252: do {
253: byte nextLine[] = getNextLine(sis);
254:
255: boundaryReached = isLineBoundary(nextLine, boundary);
256: endBoundaryReached = isLineEndBoundary(nextLine,
257: endBoundary);
258: //if (boundaryReached) {
259: // MiscHelper.println("boundryReached");
260: //}
261: //if (endBoundaryReached) {
262: // MiscHelper.println("endBoundryReached");
263: //}
264:
265: if (!(boundaryReached || endBoundaryReached)) {
266: if (addCRLF) {
267: baos.write(((byte) '\r'));
268: baos.write(((byte) '\n'));
269: }
270:
271: baos.write(nextLine);
272: addCRLF = true;
273: }
274: } while (!(boundaryReached || endBoundaryReached));
275: //end of function
276:
277: byte partContent[] = baos.toByteArray();
278: ph.setValue(partContent);
279:
280: outValue.addParameterHolder(ph);
281: } while (!endBoundaryReached);
282: //end of function
283:
284: sis.close();
285: //end seperation
286: } else {
287: Enumeration paramEnum = inRequest.getParameterNames();
288: while (paramEnum.hasMoreElements()) {
289: String nextParam = (String) paramEnum.nextElement();
290: String nextParamValues[] = inRequest
291: .getParameterValues(nextParam);
292: for (int i = 0; i < nextParamValues.length; i++) {
293: ParameterHolder ph = new ParameterHolder();
294: ph.setName(nextParam);
295: ph.setValue(nextParamValues[i]);
296: outValue.addParameterHolder(ph);
297: }
298:
299: }
300: }
301:
302: return outValue;
303: }
304:
305: //FILE UPLOAD FUNCTIONS
306: //TO DO: consider making this private after making ParameterSet for all call
307: private final static boolean isRequestMultipartFormData(
308: HttpServletRequest inRequest) {
309:
310: boolean outValue = false;
311:
312: String method = inRequest.getMethod();
313: String contentType = inRequest.getContentType();
314:
315: if (method.equalsIgnoreCase("POST")
316: && contentType.toLowerCase().indexOf(
317: "multipart/form-data") > -1) {
318: outValue = true;
319: }
320:
321: return outValue;
322: }
323:
324: private final static void readHeaderPart(ServletInputStream inSis,
325: ParameterHolder inPh) throws IOException {
326:
327: byte bArray[] = null;
328: final String CONTENT_DISPOSITION = "content-disposition:";
329:
330: while ((bArray = getNextLine(inSis)).length > 0) {
331: String nextLine = new String(bArray, "ISO-8859-1");
332: //MiscHelper.println("HLine = " + nextLine);
333: if (nextLine.toLowerCase().startsWith(CONTENT_DISPOSITION)) {
334: String contentMetaData = nextLine
335: .substring(CONTENT_DISPOSITION.length());
336:
337: StringTokenizer st = new StringTokenizer(
338: contentMetaData, ";");
339: while (st.hasMoreTokens()) {
340: String token = st.nextToken().trim();
341: if (token.trim().length() > 0
342: && !token.toLowerCase().equals("form-data")) {
343: int equalIndex = token.indexOf('=');
344: String type = token.substring(0, equalIndex);
345: String value = token.substring(equalIndex + 1);
346: if (value.startsWith("\"")) {
347: value = value.substring(1,
348: value.length() - 1);
349: }
350:
351: if (type.toLowerCase().equals("filename")) {
352: inPh.setFileName(value);
353: } else if (type.toLowerCase().equals("name")) {
354: inPh.setName(value);
355: }
356:
357: }
358: }
359: }
360: }
361: }
362:
363: private final static void scrollToFirstPart(
364: ServletInputStream inSis, String boundary,
365: String endBoundary) throws IOException {
366:
367: byte nextLine[] = null;
368:
369: do {
370:
371: nextLine = getNextLine(inSis);
372: //MiscHelper.println("NextLine = " + new String(nextLine));
373: } while (!(isLineBoundary(nextLine, boundary) || isLineEndBoundary(
374: nextLine, endBoundary)));
375: }
376:
377: private final static boolean isLineBoundary(byte inLine[],
378: String inBoundary) throws UnsupportedEncodingException {
379:
380: boolean returnValue = false;
381:
382: if (inLine.length == inBoundary.length()) {
383: String testString = new String(inLine, "ISO-8859-1");
384:
385: returnValue = testString.equals(inBoundary);
386: }
387:
388: return returnValue;
389: }
390:
391: private final static boolean isLineEndBoundary(byte inLine[],
392: String inEndBoundary) throws UnsupportedEncodingException {
393:
394: boolean returnValue = false;
395:
396: if (inLine.length == inEndBoundary.length()) {
397: String testString = new String(inLine, "ISO-8859-1");
398:
399: returnValue = testString.equals(inEndBoundary);
400: }
401:
402: return returnValue;
403: }
404:
405: //strip carriage return, line feed
406: private final static byte[] getNextLine(ServletInputStream inSis)
407: throws IOException {
408:
409: byte returnValue[] = null;
410:
411: ByteArrayOutputStream baos = new ByteArrayOutputStream();
412:
413: byte buffer[] = new byte[1024 * 8];
414: boolean reserveCarriageReturn = false;
415: boolean noContent = true;
416:
417: while (true) {
418:
419: int bytesRead = inSis.readLine(buffer, 0, buffer.length);
420:
421: if (bytesRead > 0) {
422: noContent = false;
423: }
424:
425: if (bytesRead == -1) {
426:
427: if (reserveCarriageReturn) {
428: baos.write(((byte) '\r'));
429: }
430:
431: break;
432: } else if (bytesRead == 0) {
433: //do nothing, continue
434: } else if (bytesRead == 1) {
435: if (reserveCarriageReturn) {
436: if (buffer[0] == '\n') {
437: break;
438: } else {
439: baos.write(((byte) '\r'));
440: }
441: }
442:
443: if (buffer[0] == '\r') {
444: reserveCarriageReturn = true;
445: } else {
446: reserveCarriageReturn = false;
447: baos.write(buffer[0]);
448: }
449: } else if (bytesRead >= 2) {
450: if (reserveCarriageReturn) {
451: baos.write(((byte) '\r'));
452: }
453:
454: if (buffer[bytesRead - 1] == '\r') {
455: reserveCarriageReturn = true;
456: baos.write(buffer, 0, bytesRead - 1);
457: } else if ((buffer[bytesRead - 2] == '\r')
458: && (buffer[bytesRead - 1] == '\n')) {
459: baos.write(buffer, 0, bytesRead - 2);
460: break;
461: } else {
462: reserveCarriageReturn = false;
463: baos.write(buffer, 0, bytesRead);
464: }
465: }
466: }
467:
468: baos.flush();
469:
470: if (!noContent) {
471: returnValue = baos.toByteArray();
472: }
473:
474: //MiscHelper.print(new String(returnValue, "ISO-8859-1"));
475:
476: return returnValue;
477: }
478:
479: private final static String getBoundary(String inContentType) {
480:
481: String returnValue = null;
482:
483: String lcContentType = inContentType.toLowerCase();
484:
485: if (lcContentType.startsWith("multipart/form-data")) {
486: String boundaryString = "boundary=";
487: int boundaryIndex = lcContentType.indexOf(boundaryString);
488:
489: boundaryIndex = boundaryIndex + boundaryString.length();
490:
491: if (inContentType.charAt(boundaryIndex) == '"') {
492: boundaryIndex++;
493: int quoteIndex = inContentType.indexOf('"',
494: boundaryIndex);
495: returnValue = inContentType.substring(boundaryIndex,
496: quoteIndex);
497: } else {
498: int semiIndex = inContentType.indexOf(';',
499: boundaryIndex);
500: if (semiIndex != -1) {
501: returnValue = inContentType.substring(
502: boundaryIndex, semiIndex);
503: } else {
504: returnValue = inContentType
505: .substring(boundaryIndex);
506: }
507: }
508: }
509:
510: return returnValue;
511: }
512:
513: private final static boolean endsWithLineFeed(byte inBa[],
514: int inLength) {
515:
516: boolean returnValue = false;
517:
518: if (inLength >= 1) {
519: if (inBa[inLength - 1] == '\n') {
520: returnValue = true;
521: }
522: }
523:
524: return returnValue;
525: }
526:
527: private final static boolean endsWithCarriageReturnLineFeed(
528: byte inBa[], int inLength) {
529:
530: boolean returnValue = false;
531:
532: if (inLength >= 2) {
533: if (inBa[inLength - 1] == '\n'
534: && inBa[inLength - 2] == '\r') {
535: returnValue = true;
536: }
537: }
538:
539: return returnValue;
540: }
541: }
|