package com.cidat.proclets;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Hashtable;

import javax.servlet.ServletInputStream;

public class FileUploadProclet implements Proclet {
	String[] paramName;
	String[] extensionVal;
	String[] fileSavePath;
	String[] allowedExtensions;
	String[] allowedContents;
	int maxSize;
	String[] fileNameVal;

	public FileUploadProclet(String inputName, String extensionVal,
			String fileSavePathExpr, String allowedExtensions,
			String allowedContents, int maxSize, String filenameVal) {
		this.paramName = new String[] { inputName };
		this.extensionVal = new String[] { extensionVal };
		this.fileSavePath = new String[] { fileSavePathExpr };
		this.allowedExtensions = (allowedExtensions != null ? ProcletServiceData
				.valListToArr(allowedExtensions) : null);

		for (int n = 0; (this.allowedExtensions != null)
				&& (n < this.allowedExtensions.length); n++) {
			this.allowedExtensions[n] = this.allowedExtensions[n].toLowerCase();
		}
		this.allowedContents = (allowedContents != null ? ProcletServiceData
				.valListToArr(allowedContents) : null);

		for (int n = 0; (this.allowedContents != null)
				&& (n < this.allowedContents.length); n++) {
			this.allowedContents[n] = this.allowedContents[n].toLowerCase();
		}
		this.maxSize = maxSize;
		this.fileNameVal = new String[] { filenameVal };
	}

	public FileUploadProclet(String[] inputName, String[] extensionVal,
			String[] fileSavePathExpr, String allowedExtensions,
			String allowedContents, int maxSize, String[] filenameVal) {
		this.paramName = inputName;
		this.extensionVal = extensionVal;
		this.fileSavePath = fileSavePathExpr;

		this.allowedExtensions = (allowedExtensions != null ? ProcletServiceData
				.valListToArr(allowedExtensions) : null);

		for (int n = 0; (this.allowedExtensions != null)
				&& (n < this.allowedExtensions.length); n++) {
			this.allowedExtensions[n] = this.allowedExtensions[n].toLowerCase();
		}
		this.allowedContents = (allowedContents != null ? ProcletServiceData
				.valListToArr(allowedContents) : null);

		for (int n = 0; (this.allowedContents != null)
				&& (n < this.allowedContents.length); n++) {
			this.allowedContents[n] = this.allowedContents[n].toLowerCase();
		}
		this.maxSize = maxSize;
		this.fileNameVal = filenameVal;
	}

	protected static Hashtable getFileParameters(ProcletServiceData sd,
			int maxSize) throws ProcletException {
		Hashtable table = new Hashtable();

		if (!sd.req.getContentType().toLowerCase()
				.startsWith("multipart/form-data")) {
			throw new ProcletException(sd, "error",
					"Tipo de contenido incorrecto. Debe ser multipart/form-data.");
		}
		if ((maxSize != -1) && (sd.req.getContentLength() > maxSize)) {
			throw new ProcletException(sd, "error", "max_size");
		}
		int ind = sd.req.getContentType().indexOf("boundary=");
		if (ind == -1) {
			throw new ProcletException(sd, "error", "boundary no definido");
		}
		String boundary = sd.req.getContentType().substring(ind + 9);
		if (boundary == null)
			throw new ProcletException(sd, "error", "boundary no definido");
		try {
			table = parseMulti(boundary, sd.req.getInputStream());
		} catch (Exception e) {
			throw new ProcletException(sd, "error", "parseMulti : "
					+ e.getMessage());
		}
		return table;
	}

	protected void uploadFile(ProcletServiceData sd, Hashtable aTable)
			throws ProcletException {
		String strError = "";

		for (int i = 0; i < this.paramName.length; i++) {
			Object obj = aTable.get(this.paramName[i]);

			if ((obj == null) || (!(obj instanceof Hashtable))) {
				throw new ProcletException(sd, "error", "input");
			}

			Hashtable filehash = (Hashtable) obj;
			String strNombreFichero = ((String) filehash.get("filename"))
					.toLowerCase();

			if ((this.fileNameVal != null) && (this.fileNameVal[i] != null)) {
				sd.setVal(this.fileNameVal[i], strNombreFichero);
			}
			if (strNombreFichero.equals("")) {
				if (this.extensionVal[i] != null) {
					sd.setVal(this.extensionVal[i], "");
				}
			} else {
				String strOrigExtension = "";
				if (strNombreFichero.lastIndexOf(".") > 0)
					strOrigExtension = strNombreFichero
							.substring(strNombreFichero.lastIndexOf(".") + 1);
				if (this.extensionVal[i] != null)
					sd.setVal(this.extensionVal[i], strOrigExtension);
				String strRutaGuardaFichero = sd.evalExpr(this.fileSavePath[i]);
				int nChk;
				if (this.allowedExtensions != null) {
					String extension = strOrigExtension.toLowerCase();
					for (nChk = 0; nChk < this.allowedExtensions.length; nChk++) {
						if (extension.equals(this.allowedExtensions[nChk]))
							break;
					}
					if (nChk >= this.allowedExtensions.length) {
						throw new ProcletException(sd, "error", "extension");
					}
				}

				if (this.allowedContents != null) {
					String strContenido = ((String) filehash
							.get("content-type")).toLowerCase();
					for (nChk = 0; nChk < this.allowedContents.length; nChk++) {
						if (strContenido.equals("image/"
								+ this.allowedContents[nChk]))
							break;
					}
					if (nChk >= this.allowedContents.length) {
						throw new ProcletException(sd, "error", "content");
					}
				}

				try {
					FileOutputStream of = new FileOutputStream(
							strRutaGuardaFichero);
					BufferedOutputStream fileout = new BufferedOutputStream(of);
					byte[] bytes = (byte[]) filehash.get("content");

					if (bytes.length == 0) {
						throw new ProcletException(sd, "error", "no_file");
					}
					fileout.write(bytes, 0, bytes.length);
					fileout.flush();
					fileout.close();
					of.close();
				} catch (IOException e) {
					throw new ProcletException(sd, "error", "save");
				}
			}
		}
	}

	static Hashtable parseMulti(String boundary, ServletInputStream in)
			throws IOException {
		int buffSize = 1024;
		Hashtable hash = new Hashtable();

		String boundaryStr = "--" + boundary;

		byte[] b = new byte[buffSize];

		int result = in.readLine(b, 0, b.length);

		if (result == -1)
			throw new IllegalArgumentException("InputStream truncated");
		String line = new String(b, 0, result);

		if (!line.startsWith(boundaryStr))
			throw new IllegalArgumentException("MIME boundary missing: " + line);
		while (true) {
			String filename = null;
			String contentType = null;
			ByteArrayOutputStream content = new ByteArrayOutputStream();
			String name = null;

			result = in.readLine(b, 0, b.length);

			if (result == -1)
				return hash;
			line = new String(b, 0, result - 2);
			String lowerline = line.toLowerCase();
			if (!lowerline.startsWith("content-disposition")) {
				continue;
			}
			int ind = lowerline.indexOf("content-disposition: ");
			int ind2 = lowerline.indexOf(";");
			if ((ind == -1) || (ind2 == -1))
				throw new IllegalArgumentException(
						"Content Disposition line misformatted: " + line);
			String disposition = lowerline.substring(ind + 21, ind2);
			if (!disposition.equals("form-data")) {
				throw new IllegalArgumentException("Content Disposition "
						+ disposition + " no esta soportada");
			}

			int ind3 = lowerline.indexOf("name=\"", ind2);
			int ind4 = lowerline.indexOf("\"", ind3 + 7);
			if ((ind3 == -1) || (ind4 == -1))
				throw new IllegalArgumentException(
						"Content Disposition line misformatted: " + line);
			name = line.substring(ind3 + 6, ind4);

			int ind5 = lowerline.indexOf("filename=\"", ind4 + 2);
			int ind6 = lowerline.indexOf("\"", ind5 + 10);
			if ((ind5 != -1) && (ind6 != -1)) {
				filename = line.substring(ind5 + 10, ind6);
			}

			result = in.readLine(b, 0, b.length);
			if (result == -1)
				return hash;
			line = new String(b, 0, result - 2);
			lowerline = line.toLowerCase();
			if (lowerline.startsWith("content-type")) {
				int ind7 = lowerline.indexOf(" ");
				if (ind7 == -1)
					throw new IllegalArgumentException(
							"Content-Type line misformatted: " + line);
				contentType = lowerline.substring(ind7 + 1);

				result = in.readLine(b, 0, b.length);
				if (result == -1)
					return hash;
				line = new String(b, 0, result - 2);
				if (line.length() != 0) {
					throw new IllegalArgumentException(
							"Linea inesperada en la cabecera MIMEpart : "
									+ line);
				}
			} else if (line.length() != 0) {
				throw new IllegalArgumentException(
						"Misformatted line following disposition: " + line);
			}

			boolean readingContent = true;
			boolean firstLine = true;
			byte[] buffbytes = new byte[buffSize];
			int buffnum = 0;

			result = in.readLine(b, 0, b.length);
			if (result == -1)
				return hash;
			line = new String(b, 0, result);
			if (!line.startsWith(boundaryStr)) {
				System.arraycopy(b, 0, buffbytes, 0, result);
				buffnum = result;
				result = in.readLine(b, 0, b.length);
				if (result == -1)
					return hash;
				line = new String(b, 0, result);
				firstLine = false;
				if (line.startsWith(boundaryStr))
					readingContent = false;
			} else {
				readingContent = false;
			}

			while (readingContent) {
				content.write(buffbytes, 0, buffnum);
				System.arraycopy(b, 0, buffbytes, 0, result);
				buffnum = result;
				result = in.readLine(b, 0, b.length);
				if (result == -1)
					return hash;
				line = new String(b, 0, result);
				if (!line.startsWith(boundaryStr))
					continue;
				readingContent = false;
			}
			if (!firstLine) {
				if (buffnum > 2) {
					content.write(buffbytes, 0, buffnum - 2);
				}
			}

			if (filename == null) {
				if (hash.get(name) == null) {
					String[] values = new String[1];
					values[0] = content.toString();
					hash.put(name, values);
				} else {
					Object prevobj = hash.get(name);
					if ((prevobj instanceof String[])) {
						String[] prev = (String[]) prevobj;
						String[] newStr = new String[prev.length + 1];
						System.arraycopy(prev, 0, newStr, 0, prev.length);
						newStr[prev.length] = content.toString();
						hash.put(name, newStr);
					} else {
						throw new IllegalArgumentException(
								"Fallo en codigo de creacion de hashtable en parseMulti");
					}
				}
			} else {
				Hashtable filehash = new Hashtable(4);
				filehash.put("name", name);
				filehash.put("filename", filename);
				if (contentType == null)
					contentType = "application/octet-stream";
				filehash.put("content-type", contentType);
				filehash.put("content", content.toByteArray());
				hash.put(name, filehash);
			}
		}
	}

	public void process(ProcletServiceData sd) throws ProcletException {
		if ((sd.servletSrv == 1) || (sd.servletSrv == 3)
				|| (sd.servletSrv == 4) || (sd.servletSrv == 5)
				|| (sd.servletSrv == 6)) {
			if (sd.multiPartEncParams == null) {
				sd.setVal("com.cidat.proclets.error",
						"Tipo de contenido incorrecto. Debe ser multipart/form-data.");
				throw new ProcletException(sd);
			}

			if ((this.maxSize != -1)
					&& (sd.req.getContentLength() > this.maxSize)) {
				throw new ProcletException(sd, "error", "max_size");
			}

			uploadFile(sd, sd.multiPartEncParams);

			for (int n = 0; n < this.paramName.length; n++) {
				sd.multiPartEncParams.put(this.paramName[n], "null");
			}

		} else {
			Hashtable table = getFileParameters(sd, this.maxSize);

			sd.canForwardJsp = false;

			uploadFile(sd, table);
		}
	}
}

/*
 * Location:
 * D:\svn\ejie\q53.trunk\codigo\q53\q53ItourbaskWar\WebContent\WEB-INF\
 * lib\proclets_wl81.jar Qualified Name: com.cidat.proclets.FileUploadProclet
 * JD-Core Version: 0.6.0
 */