//
// $Id: DefaultUploadPolicy.java 289 2007-06-19 10:04:46 +0000 (mar., 19 juin
// 2007) etienne_sf $
//
// jupload - A file upload juploadContext.
// Copyright 2007 The JUpload Team
//
// Created: 2006-05-04
// Creator: etienne_sf
// Last modified: $Date: 2010-08-18 08:23:24 -0300 (Qua, 18 Ago 2010) $
//
// This program is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free Software
// Foundation; either version 2 of the License, or (at your option) any later
// version. This program 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 General Public License for more
// details. You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation, Inc.,
// 675 Mass Ave, Cambridge, MA 02139, USA.
package wjhk.jupload2.policies;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.GridLayout;
import java.awt.SystemColor;
import java.awt.dnd.DropTargetDropEvent;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.IllegalFormatException;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.BevelBorder;
import wjhk.jupload2.context.JUploadContext;
import wjhk.jupload2.exception.JUploadException;
import wjhk.jupload2.exception.JUploadExceptionStopAddingFiles;
import wjhk.jupload2.exception.JUploadExceptionUploadFailed;
import wjhk.jupload2.exception.JUploadExceptionUploadFailedSuccessNotFound;
import wjhk.jupload2.exception.JUploadIOException;
import wjhk.jupload2.filedata.DefaultFileData;
import wjhk.jupload2.filedata.FileData;
import wjhk.jupload2.gui.JUploadFileChooser;
import wjhk.jupload2.gui.JUploadFileFilter;
import wjhk.jupload2.gui.JUploadPanel;
import wjhk.jupload2.upload.helper.ByteArrayEncoder;
import wjhk.jupload2.upload.helper.ByteArrayEncoderHTTP;
import wjhk.jupload2.upload.helper.HTTPConnectionHelper;
import wjhk.jupload2.upload.helper.HttpProtocolFinderThread;
import wjhk.jupload2.upload.helper.InteractiveTrustManager;
/**
* This class implements all {@link wjhk.jupload2.policies.UploadPolicy}
* methods. Its way of working is he same as the JUpload version 1.
* The simplest way to use this policy is given in the presentation of
* {@link UploadPolicy}. The DefaultUploadPolicy is used when no
* uploadPolicy parameter is given to the juploadContext, or this
* parameter has 'DefaultUploadPolicy' as a value.
*
* The default behavior is representated below. It can be overridden by
* adding parameters to the juploadContext. All available parameters are shown
* in the presentation of {@link UploadPolicy}.
*
*
* - Default implementation for all
* {@link wjhk.jupload2.policies.UploadPolicy} methods.
*
- Files are uploaded all in one HTTP request.
*
- No handling for particular kind of files: files are transmitted without
* any transformation.
*
- The file are transmitted to the server with the navigator cookies,
* userAgent and Protocol (see also the readCookieFromNavigator and
* serverProtocol juploadContext parameter). This make upload occurs within the
* current user session on the server. So, it allows right management and
* context during the management of uploaded files, on the server.
*
*
* @author etienne_sf
* @version $Revision: 1388 $
*/
public class DefaultUploadPolicy implements UploadPolicy {
/**
* Maximum number of characters allowed for a message that is displayed in a
* DialogBox
*/
public final static int DIALOG_MESSAGE_MAX_LINE_LENGTH = 80;
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// APPLET PARAMETERS
// ///////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////
/**
* juploadContext contains the reference of the Applet. It's useful to
* interact with it.
* It also allows access to the navigator properties, if the html tag
* MAYSCRIPT is put in the APPLET tag. This allows this class to get the
* cookie, userAgent and protocol, to upload files in the current user
* session on the server.
* Default : no default value
*/
JUploadContext juploadContext = null;
/**
* Contains the applet parameter of the same name. If a valid URL is given
* here, the navigator will get redirected to this page, after a successful
* upload.
*/
private String afterUploadURL = UploadPolicy.DEFAULT_AFTER_UPLOAD_URL;
/**
* Contains the allowedFileExtensions applet parameter.
*/
private boolean allowHttpPersistent = UploadPolicy.DEFAULT_ALLOW_HTTP_PERSISTENT;
/**
* Contains the allowedFileExtensions applet parameter.
*/
private String allowedFileExtensions = UploadPolicy.DEFAULT_ALLOWED_FILE_EXTENSIONS;
/**
* Indicate whether the log window is shown or not to the user. In all cases
* it remains in memory, and stores all debug information. This allows a log
* information, in case of an error occurs.
*
* @see #urlToSendErrorTo
*/
private String showLogWindow = UploadPolicy.DEFAULT_SHOW_LOGWINDOW;
private boolean showStatusbar = UploadPolicy.DEFAULT_SHOW_STATUSBAR;
private String specificHeaders = null;
/** Indicates the directory in which the file chooser is to be opened */
private File currentBrowsingDirectory = null;
/**
* This parameter controls whether the applet generates a debug file or not.
* If true, this file contains the full debug output, whatever the current
* debugLevel is.
*/
private boolean debugGenerateFile = true;
/**
* The current debug level. This control the details of information that is
* written in the log part of the applet.
*/
private int debugLevel = UploadPolicy.DEFAULT_DEBUG_LEVEL;
/**
* Stored value for the fileChooserIconFromFileContent applet property.
*
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
*/
private int fileChooserIconFromFileContent = UploadPolicy.DEFAULT_FILE_CHOOSER_ICON_FROM_FILE_CONTENT;
/**
* Stored value for the fileChooserIconSize applet property.
*
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
*/
private int fileChooserIconSize = UploadPolicy.DEFAULT_FILE_CHOOSER_ICON_SIZE;
/**
* Stored value for the {@link UploadPolicy#PROP_FILE_FILTER_NAME}
*/
private String fileFilterName = UploadPolicy.DEFAULT_FILE_FILTER_NAME;
/**
* This String contains the filenameEncoding parameter. All details about
* the available applet parameters are displayed in the Upload Policy javadoc page.
*/
private String filenameEncoding = UploadPolicy.DEFAULT_FILENAME_ENCODING;
/**
* Default value for the ftpCreateDirectoryStructure applet parameter
*/
private boolean ftpCreateDirectoryStructure = UploadPolicy.DEFAULT_FTP_CREATE_DIRECTORY_STRUCTURE;
/**
* Default value for the ftpCreateDirectoryStructure applet parameter
*/
private boolean ftpTransfertBinary = UploadPolicy.DEFAULT_FTP_TRANSFERT_BINARY;
/**
* Default value for the ftpCreateDirectoryStructure applet parameter
*/
private boolean ftpTransfertPassive = UploadPolicy.DEFAULT_FTP_TRANSFERT_PASSIVE;
/** Default value for the httpUploadParameterName applet parameter */
protected String httpUploadParameterName = UploadPolicy.DEFAULT_HTTP_UPLOAD_PARAMETER_NAME;
/** Default value for the httpUploadParameterType applet parameter */
protected String httpUploadParameterType = UploadPolicy.DEFAULT_HTTP_UPLOAD_PARAMETER_TYPE;
/**
* The lang parameter, given to the applet.
*/
private String lang = UploadPolicy.DEFAULT_LANG;
/**
* The current Locale. If the lang parameter is given and value, this
* supersede the default locale.
*/
private Locale locale = Locale.getDefault();
/**
* Contains the last exception that occurs in the applet.
*
* @see #displayErr(String, Exception)
*/
private JUploadException lastException = null;
/**
* The look and feel is used as a parameter of the
* UIManager.setLookAndFeel(String) method. See the parameters list on the
* {@link UploadPolicy} page.
*/
private String lookAndFeel = UploadPolicy.DEFAULT_LOOK_AND_FEEL;
/**
* The applet will do as may HTTP requests to upload all files, with the
* number as a maximum number of files for each HTTP request.
* Default : -1
*/
private int nbFilesPerRequest = UploadPolicy.DEFAULT_NB_FILES_PER_REQUEST;
/**
* Current value (or default value) of the maxChunkSize applet parameter.
* Default : Long.MAX_VALUE
*/
private long maxChunkSize = UploadPolicy.DEFAULT_MAX_CHUNK_SIZE;
/**
* Current value (or default value) of the maxFileSize applet parameter.
* Default : Long.MAX_VALUE
*/
private long maxFileSize = UploadPolicy.DEFAULT_MAX_FILE_SIZE;
/**
* The URL where files should be posted.
* Default : no default value. (mandatory)
*/
private String postURL = UploadPolicy.DEFAULT_POST_URL;
/** @see UploadPolicy#getReadCookieFromNavigator() */
private boolean readCookieFromNavigator = UploadPolicy.DEFAULT_READ_COOKIE_FROM_NAVIGATOR;
/** @see UploadPolicy#getReadUserAgentFromNavigator() */
private boolean readUserAgentFromNavigator = UploadPolicy.DEFAULT_READ_USER_AGENT_FROM_NAVIGATOR;
/** @see UploadPolicy#getRetryMaxNumberOf() */
private int retryMaxNumberOf = UploadPolicy.DEFAULT_RETRY_MAX_NUMBER_OF;
/** @see UploadPolicy#getRetryNbSecondsBetween() */
private int retryNbSecondsBetween = UploadPolicy.DEFAULT_RETRY_NB_SECONDS_BETWEEN;
/** @see UploadPolicy#getSendMD5Sum() */
private boolean sendMD5Sum = UploadPolicy.DEFAULT_SEND_MD5_SUM;
/** @see UploadPolicy#getServerProtocol() */
private String serverProtocol = UploadPolicy.DEFAULT_SERVER_PROTOCOL;
/**
* @see UploadPolicy#getStringUploadError()
*/
private String stringUploadError = UploadPolicy.DEFAULT_STRING_UPLOAD_ERROR;
/**
* @see UploadPolicy#getStringUploadSuccess()
*/
private String stringUploadSuccess = UploadPolicy.DEFAULT_STRING_UPLOAD_SUCCESS;
/**
* @see UploadPolicy#getStringUploadWarning()
*/
private String stringUploadWarning = UploadPolicy.DEFAULT_STRING_UPLOAD_WARNING;
/**
* If an error occurs during upload, and this attribute is not null, the
* applet asks the user if wants to send the debug ouput to the
* administrator. If yes, the full debug information is POSTed to this URL.
* It's a little development on the server side to send a mail to the
* webmaster, or just log this error into a log file.
*
* @see UploadPolicy#sendDebugInformation(String, Exception)
*/
private String urlToSendErrorTo = UploadPolicy.DEFAULT_URL_TO_SEND_ERROR_TO;
/**
* Optional name of a form (in the same document like the applet) which is
* used to populate POST parameters.
*/
private String formData = UploadPolicy.DEFAULT_FORMDATA;
private String afterUploadTarget = UploadPolicy.DEFAULT_AFTER_UPLOAD_TARGET;
private String lastResponseBody = null;
protected String lastResponseMessage = null;
private int sslVerifyCert = InteractiveTrustManager.NONE;
private final String CRLF = System.getProperty("line.separator");
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// INTERNAL ATTRIBUTE
// ///////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////
/**
* This Vector contains headers that will be added for each upload. It may
* contains specific cookies, for instance.
*
* @see #onAppendHeader(ByteArrayEncoder)
*/
private Vector headers = new Vector();
/**
* The resourceBundle contains all localized String (and others ??)
*/
private ResourceBundle resourceBundle = null;
/**
* This stream is used to store all information that could be useful, in
* case a problem occurs. Is content can then be sent to the webmaster.
*/
protected PrintStream debugOut = null;
/**
* The actual file, used for the debug log.
*
* @see #debugGenerateFile
*/
protected File debugFile = null;
/**
* This flag prevents endless repeats of opening the debug log, if that
* failed for some reason.
*/
protected boolean debugOk = true;
/**
* Same as {@link #patternSuccess}, but for the error message. If found,
* then the upload was accepted by the remote HTTP server, but rejected by
* the remote application. This pattern should also find the error message
* in the first matching string.
*/
protected Pattern patternError = Pattern
.compile(UploadPolicy.DEFAULT_STRING_UPLOAD_ERROR);
/**
* The regexp pattern that is used to find the success string in the HTTP
* response. If found, the upload is considered to be a success: it has been
* accepted by the remote server and the remote application.
*/
protected Pattern patternSuccess = Pattern
.compile(UploadPolicy.DEFAULT_STRING_UPLOAD_SUCCESS);
/**
* Same as {@link #patternSuccess}, but for the warning message. Each time
* it is found, a message is displayed to the user.
*/
protected Pattern patternWarning = Pattern
.compile(UploadPolicy.DEFAULT_STRING_UPLOAD_WARNING);
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// CONSTRUCTORS
// //////////////////////////////////////////////////////////////////////////////////////////////
/**
* The main constructor : use default values, and the given postURL.
*
* @param juploadContext
* The current juploadContext. As the reference to the current
* upload policy exists almost everywhere, this parameter allows
* any access to anyone on the juploadContext... including
* reading the applet parameters.
* @throws JUploadException
* If an applet parameter is invalid
*/
public DefaultUploadPolicy(JUploadContext juploadContext)
throws JUploadException {
// Call default constructor for all default initialization;.
this.juploadContext = juploadContext;
displayInfo("JUpload juploadContext started, with "
+ this.getClass().getName() + " upload policy");
// get the debug level. This control the level of debug messages that
// are written in the log window (see displayDebugMessage). In all
// cases, the full output is written in the debugBufferString (see also
// urlToSendErrorTo)
setDebugLevel(juploadContext.getParameter(PROP_DEBUG_LEVEL,
DEFAULT_DEBUG_LEVEL), false);
// Get resource file. This must be the very first parameter to be set,
// because during initialization, translations may be needed.
setLang(juploadContext.getParameter(PROP_LANG, DEFAULT_LANG));
// Force the look and feel of the current system. This must be the
// second
// first parameter to be set, because during initialization, dialogs can
// appear.
setLookAndFeel(juploadContext.getParameter(PROP_LOOK_AND_FEEL,
DEFAULT_LOOK_AND_FEEL));
// This must be set before any URL's because these might trigger an
// connection attempt.
setSslVerifyCert(juploadContext.getParameter(PROP_SSL_VERIFY_CERT,
DEFAULT_SSL_VERIFY_CERT));
// get the afterUploadURL juploadContext parameter.
setAfterUploadURL(juploadContext.getParameter(PROP_AFTER_UPLOAD_URL,
DEFAULT_AFTER_UPLOAD_URL));
// FTP: whether or not to create subfolders on the server side.
setFtpCreateDirectoryStructure(juploadContext.getParameter(
PROP_FTP_CREATE_DIRECTORY_STRUCTURE,
DEFAULT_FTP_CREATE_DIRECTORY_STRUCTURE));
// FTP transfert mode
setFtpTransfertBinary(juploadContext.getParameter(
PROP_FTP_TRANSFERT_BINARY, DEFAULT_FTP_TRANSFERT_BINARY));
// FTP connection mode
setFtpTransfertPassive(juploadContext.getParameter(
PROP_FTP_TRANSFERT_PASSIVE, DEFAULT_FTP_TRANSFERT_PASSIVE));
// get the fileChooser parameters
setAllowedFileExtensions(juploadContext.getParameter(
PROP_ALLOWED_FILE_EXTENSIONS, DEFAULT_ALLOWED_FILE_EXTENSIONS));
setFileFilterName(juploadContext.getParameter(PROP_FILE_FILTER_NAME,
DEFAULT_FILE_FILTER_NAME));
setAllowHttpPersistent(juploadContext.getParameter(
PROP_ALLOW_HTTP_PERSISTENT, DEFAULT_ALLOW_HTTP_PERSISTENT));
setShowStatusbar(juploadContext.getParameter(PROP_SHOW_STATUSBAR,
DEFAULT_SHOW_STATUSBAR));
setShowLogWindow(juploadContext.getParameter(PROP_SHOW_LOGWINDOW,
DEFAULT_SHOW_LOGWINDOW));
// set the fileChooser relative stuff.
setFileChooserIconFromFileContent(juploadContext.getParameter(
PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT,
DEFAULT_FILE_CHOOSER_ICON_FROM_FILE_CONTENT));
setFileChooserIconSize(juploadContext.getParameter(
PROP_FILE_CHOOSER_ICON_SIZE, DEFAULT_FILE_CHOOSER_ICON_SIZE));
setCurrentBrowsingDirectory(juploadContext.getParameter(
PROP_BROWSING_DIRECTORY, DEFAULT_BROWSING_DIRECTORY));
// get the filenameEncoding. If not null, it should be a valid argument
// for the URLEncoder.encode method.
// DEPRECATED.
setFilenameEncoding(juploadContext.getParameter(PROP_FILENAME_ENCODING,
DEFAULT_FILENAME_ENCODING));
// Read parameters about the HTTP upload request.
setNbFilesPerRequest(juploadContext.getParameter(
PROP_NB_FILES_PER_REQUEST, DEFAULT_NB_FILES_PER_REQUEST));
setHttpUploadParameterName(juploadContext.getParameter(
PROP_HTTP_UPLOAD_PARAMETER_NAME,
DEFAULT_HTTP_UPLOAD_PARAMETER_NAME));
setHttpUploadParameterType(juploadContext.getParameter(
PROP_HTTP_UPLOAD_PARAMETER_TYPE,
DEFAULT_HTTP_UPLOAD_PARAMETER_TYPE));
// get the maximum size of a file on one HTTP request (indicates if the
// file must be splitted before upload, see UploadPolicy comment).
setMaxChunkSize(juploadContext.getParameter(PROP_MAX_CHUNK_SIZE,
DEFAULT_MAX_CHUNK_SIZE));
// get the maximum size of an uploaded file.
setMaxFileSize(juploadContext.getParameter(PROP_MAX_FILE_SIZE,
DEFAULT_MAX_FILE_SIZE));
// retry management
setRetryMaxNumberOf(juploadContext.getParameter(
PROP_RETRY_MAX_NUMBER_OF, DEFAULT_RETRY_MAX_NUMBER_OF));
setRetryNbSecondsBetween(juploadContext
.getParameter(PROP_RETRY_NB_SECONDS_BETWEEN,
DEFAULT_RETRY_NB_SECONDS_BETWEEN));
// get the URL where files must be posted.
setPostURL(juploadContext.getParameter(PROP_POST_URL, DEFAULT_POST_URL));
// get any additional headers.
setReadCookieFromNavigator(juploadContext.getParameter(
PROP_READ_COOKIE_FROM_NAVIGATOR,
DEFAULT_READ_COOKIE_FROM_NAVIGATOR));
setReadUserAgentFromNavigator(juploadContext.getParameter(
PROP_READ_USER_AGENT_FROM_NAVIGATOR,
DEFAULT_READ_USER_AGENT_FROM_NAVIGATOR));
setSendMD5Sum(juploadContext.getParameter(PROP_SEND_MD5_SUM,
DEFAULT_SEND_MD5_SUM));
setSpecificHeaders(juploadContext.getParameter(PROP_SPECIFIC_HEADERS,
DEFAULT_SPECIFIC_HEADERS));
setStringUploadError(juploadContext.getParameter(
PROP_STRING_UPLOAD_ERROR, DEFAULT_STRING_UPLOAD_ERROR));
setStringUploadSuccess(juploadContext.getParameter(
PROP_STRING_UPLOAD_SUCCESS, DEFAULT_STRING_UPLOAD_SUCCESS));
setStringUploadWarning(juploadContext.getParameter(
PROP_STRING_UPLOAD_WARNING, DEFAULT_STRING_UPLOAD_WARNING));
// get the URL where the full debug output can be sent when an error
// occurs.
setUrlToSendErrorTo(juploadContext.getParameter(
PROP_URL_TO_SEND_ERROR_TO, DEFAULT_URL_TO_SEND_ERROR_TO));
this.formData = juploadContext.getParameter(PROP_FORMDATA,
DEFAULT_FORMDATA);
this.afterUploadTarget = juploadContext.getParameter(
PROP_AFTER_UPLOAD_TARGET, DEFAULT_AFTER_UPLOAD_TARGET);
// Let's touch the server, to test that everything is Ok. Take care,
// this is the only place where we override the default value, by null:
// the default value will be used by the HttpConnect.getProtocol()
// method.
// Also, in FTP mode, there can be no default value.
HttpProtocolFinderThread.computeServerProtocol(this, juploadContext
.getParameter(PROP_SERVER_PROTOCOL, null));
// We let the UploadPolicyFactory call the displayParameterStatus
// method, so that the initialization is finished, including for classes
// which inherit from DefaultUploadPolicy.
displayDebug(
"[DefaultUploadPolicy] end of constructor (serverProtocol has been set)",
30);
}
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// UploadPolicy methods
// //////////////////////////////////////////////////////////////////////////////////////////////
/** @see UploadPolicy#start() */
public void start() {
// The current context may add any specific headers.
if (getReadCookieFromNavigator()) {
this.juploadContext.readCookieFromNavigator(this.headers);
}
if (getReadUserAgentFromNavigator()) {
this.juploadContext.readUserAgentFromNavigator(this.headers);
}
}
// getters and setters are sorted below
/**
* @see wjhk.jupload2.policies.UploadPolicy#addHeader(java.lang.String)
*/
public void addHeader(String header) {
this.headers.add(header);
}
/**
* The default behavior (see {@link DefaultUploadPolicy}) is to check that
* the stringUploadSuccess applet parameter is present in the response from
* the server. The return is tested, in the order below: False, if
* the stringUploadError is found. An error message is then displayed.
* True, if the stringUploadSuccess is null or empty (no test at all).
* True, if the stringUploadSuccess string is present in the
* serverOutputBody. True, If previous condition is not filled, but the
* HTTP header "HTTP(.*)200OK$" is present: the test is currently non
* blocking, because I can not test all possible HTTP configurations.
* False if the previous conditions are not fullfilled.
* This method also looks for the stringUploadWarning regular expression.
* Each time it is matched, the found message is displayed to the user.
*
* @param status
* The HTTP response code
* @param msg
* The status message from the first line of the response (e.g.
* "200 OK").
* @param body
* The body of the HTTP answer.
* @return True or False, indicating if the upload is a success or not.
* @see UploadPolicy#checkUploadSuccess(int, String, String)
*/
public boolean checkUploadSuccess(int status, String msg, String body)
throws JUploadException {
boolean bReturn = false;
if (getDebugLevel() > 100) {
// Let's have a little time to check the upload messages written on
// the progress bar.
try {
Thread.sleep(300);
} catch (InterruptedException e) {
}
}
this.lastResponseBody = body;
this.lastResponseMessage = msg;
displayDebug("HTTP status: " + msg, 30);
// HTTP-100 correction, thanks to Marc Reidy
if ((status != 200) && (status != 100))
throw new JUploadExceptionUploadFailed("Received HTTP status "
+ msg);
// HTTP-100 "continue", in case we're uploading
// to an ASP.NET development server. We should
// continue sending...
if(status == 100)
return true;
// Let's analyze the body returned, line by line. The end of line
// character may be CR, LF, or CRLF. We navigate through the body, and
// replace any end of line character by a uniform CRLF.
Matcher matcherError, matcherWarning;
String line;
Pattern p = Pattern.compile("[\\r\\n]", Pattern.MULTILINE);
String[] lines = p.split(body);
StringBuffer sbBodyWithUniformCRLF = new StringBuffer(body.length());
for (int i = 0; i < lines.length; i += 1) {
line = lines[i];
sbBodyWithUniformCRLF.append(line).append("\r\n");
// FIXME some empty lines are given by the server
// Let's remove the empty line: with the p pattern, a multiline is
// generated each time a \r\n is received, that is: for each line.
if (line == null || line.equals("")) {
// An empty line. Let's go the next line.
continue;
}
// Check if this is a success
// The success string should be in the http body
if (getStringUploadSuccess() != null
&& !getStringUploadSuccess().equals("")) {
if (this.patternSuccess.matcher(line).matches()) {
// We go on. There may be some WARNING message, hereafter.
bReturn = true;
}
}
// Check if this is an error
if (getStringUploadError() != null
&& !getStringUploadError().equals("")) {
matcherError = this.patternError.matcher(line);
if (matcherError.matches()) {
String errmsg = "An error occurs during upload (but the applet couldn't find the error message)";
if (matcherError.groupCount() > 0) {
if (!matcherError.group(1).equals("")) {
// Let's do a (very simple) formatting: one line to
// 100 characters
errmsg = formatMessage(matcherError.group(1));
}
}
this.lastResponseMessage = errmsg;
throw new JUploadExceptionUploadFailed(errmsg);
}
}// getStringUploadError
// Check if this is an warning
if (getStringUploadWarning() != null
&& !getStringUploadWarning().equals("")) {
matcherWarning = this.patternWarning.matcher(line);
if (matcherWarning.matches()) {
String warnmsg = "A warning occurs during upload (but the applet couldn't find the warning message)";
if (matcherWarning.groupCount() > 0) {
if (!matcherWarning.group(1).equals("")) {
warnmsg = formatMessage(matcherWarning.group(1));
}
}
this.lastResponseMessage = warnmsg;
displayWarn(warnmsg);
alertStr(warnmsg);
}
}// getStringUploadWarning
}// while(st.hasMoreTokens())
if (bReturn) {
return true;
}
// We found no stringUploadSuccess nor stringUploadError
if (getStringUploadSuccess() == null
|| getStringUploadSuccess().equals("")) {
// No chance to check the correctness of this upload. -> Assume Ok
return true;
}
// stringUploadSuccess was defined but we did not find it.
// This is most certainly an error as http-status 200 does *not* refer
// to the correctness of the content. It merely means that the protocol
// handling was ok. -> throw an exception
throw new JUploadExceptionUploadFailedSuccessNotFound(getClass()
.getName()
+ ".checkUploadSuccess(): The regexp string \""
+ getStringUploadSuccess()
+ "\" was not found in the response body");
} // checkUploadSuccess
/**
* Generation of a formatted error message, so that it can be displayed in a
* DialogBox. That is: each line that contains more than
* {@link #DIALOG_MESSAGE_MAX_LINE_LENGTH} is truncated to
* DIALOG_MESSAGE_MAX_LINE_LENGTH.
*
* @param msg
* @return
*/
protected String formatMessage(String msg) {
StringBuffer sbMsg = new StringBuffer();
String[] lines = msg.split("\\\\n");
for (int i = 0; i < lines.length; i += 1) {
// For each line, we truncate it, if it's too long.
String line = lines[i];
for (int j = 0, remaining = line.length(); remaining > 0; remaining -= DIALOG_MESSAGE_MAX_LINE_LENGTH, j += 1) {
if (remaining <= DIALOG_MESSAGE_MAX_LINE_LENGTH) {
// It's the last loop.
sbMsg.append(line.substring(j
* DIALOG_MESSAGE_MAX_LINE_LENGTH));
} else {
sbMsg.append(line.substring(j
* DIALOG_MESSAGE_MAX_LINE_LENGTH, (j + 1)
* DIALOG_MESSAGE_MAX_LINE_LENGTH));
sbMsg.append("\n");
}
}
// End we add the EOL characters, for all lines, but the last one.
if (i < lines.length - 1) {
sbMsg.append("\n");
}
}
return sbMsg.toString();
}
/**
* @see wjhk.jupload2.policies.UploadPolicy#afterUpload(Exception, String)
*/
public void afterUpload(Exception e, String serverOutput)
throws JUploadException {
// If there was no error, and afterUploadURL is defined, let's try to go
// to this URL.
String url = getAfterUploadURL();
if (url != null) {
this.juploadContext.displayURL(url, e == null);
}
}
/** @see UploadPolicy#alertStr(String) */
public void alertStr(String str) {
String str2 = str.replaceAll("\\\\n", "\n");
JOptionPane.showMessageDialog(null, str2, "Alert",
JOptionPane.WARNING_MESSAGE);
}
/** @see UploadPolicy#confirmDialogStr(String, int) */
public int confirmDialogStr(String str, int optionTypes) {
String str2 = str.replaceAll("\\\\n", "\n");
return JOptionPane.showConfirmDialog(getContext().getUploadPanel()
.getJComponent().getParent(), str2, "Alert", optionTypes);
}
/** @see UploadPolicy#alert(String) */
public void alert(String key) {
alertStr(getLocalizedString(key));
}
/**
* The DefaultUpload accepts all file types: we just return an instance of
* FileData, without any test.
*
* @exception JUploadExceptionStopAddingFiles
* If the users choosed to stop adding. This occurs when the
* {@link #fileFilterAccept(File)} method returns false, and
* the user then choose to stop adding files.
* @see UploadPolicy#createFileData(File, File)
*/
public FileData createFileData(File file, File root)
throws JUploadExceptionStopAddingFiles {
if (!fileFilterAccept(file)) {
String msg = file.getName() + " : "
+ getLocalizedString("errForbiddenExtension");
displayWarn(msg);
if (confirmDialogStr(msg, JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION) {
// The user want to stop to add files to the list. For instance,
// when he/she added a whole directory, and it contains a lot of
// files that don't match the allowed file extension.
throw new JUploadExceptionStopAddingFiles("Stopped by the user");
}
return null;
} else if (!file.canRead()) {
displayInfo("Can't read file " + file.getName()
+ ". No DefaultFileData creation.");
return null;
} else {
return new DefaultFileData(file, root, this);
}
}
/**
* Default implementation of
* {@link wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton, JButton, JUploadPanel)}
* . IT creates a JPanel, containing the three given JButton. It creates the
* same panel as the original JUpload.
*
* @see wjhk.jupload2.policies.UploadPolicy#createTopPanel(JButton, JButton,
* JButton, JUploadPanel)
*/
public JPanel createTopPanel(JButton browse, JButton remove,
JButton removeAll, JUploadPanel jUploadPanel) {
JPanel jPanel = new JPanel();
jPanel.setLayout(new GridLayout(1, 3, 10, 5));
jPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
jPanel.add(browse);
jPanel.add(removeAll);
jPanel.add(remove);
jUploadPanel.getJComponent().setBorder(
BorderFactory.createLineBorder(SystemColor.controlDkShadow));
return jPanel;
}
/**
* @see wjhk.jupload2.policies.UploadPolicy#createProgressPanel(JProgressBar,
* JProgressBar, JButton, JButton, JUploadPanel)
*/
public JPanel createProgressPanel(JProgressBar preparationProgressBar,
JProgressBar uploadProgressBar, JButton uploadButton,
JButton stopButton, JUploadPanel mainPanel) {
// There may be two progress bar: one for preparation progress of files
// (preparation before upload) and one to follow the actual upload.
JPanel jProgressBarPanel = new JPanel();
jProgressBarPanel.setLayout(new BorderLayout(10, 1));
jProgressBarPanel.add(preparationProgressBar, BorderLayout.NORTH);
jProgressBarPanel.add(uploadProgressBar, BorderLayout.SOUTH);
JPanel jProgressPanel = new JPanel();
jProgressPanel.setLayout(new BorderLayout(10, 0));
jProgressPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
jProgressPanel.add(uploadButton, BorderLayout.LINE_START);
jProgressPanel.add(jProgressBarPanel, BorderLayout.CENTER);
jProgressPanel.add(stopButton, BorderLayout.LINE_END);
return jProgressPanel;
}
/**
* @see wjhk.jupload2.policies.UploadPolicy#createStatusBar(javax.swing.JLabel,
* JUploadPanel)
*/
public JPanel createStatusBar(JLabel content, JUploadPanel mainPanel) {
if (this.showStatusbar) {
JPanel pstatus = new JPanel();
pstatus.setLayout(new BorderLayout());
pstatus.add(content, BorderLayout.CENTER);
pstatus.setBorder(new BevelBorder(BevelBorder.LOWERED));
return pstatus;
}
return null;
}
/**
* This methods allow the upload policy to override the default disposition
* of the components on the applet.
*
* @see UploadPolicy#addComponentsToJUploadPanel(JUploadPanel)
*/
public void addComponentsToJUploadPanel(JUploadPanel jUploadPanel) {
// Set the global layout of the panel.
jUploadPanel.getJComponent().setLayout(
new BoxLayout(jUploadPanel.getJComponent(), BoxLayout.Y_AXIS));
// The top panel is the upper part of the applet: above the file
// list.
// JPanel topPanel = new JPanel();
JPanel topPanel = createTopPanel(jUploadPanel.getBrowseButton(),
jUploadPanel.getRemoveButton(), jUploadPanel
.getRemoveAllButton(), jUploadPanel);
if (topPanel != null) {
jUploadPanel.getJComponent().add(topPanel);
topPanel.addMouseListener(jUploadPanel.getMouseListener());
}
// Then, we add the file list.
jUploadPanel.getJComponent().add(
jUploadPanel.getFilePanel().getDropComponent());
// The progress panel contains the progress bar, and the upload and stop
// buttons.
JPanel progressPanel = createProgressPanel(jUploadPanel
.getPreparationProgressBar(), jUploadPanel
.getUploadProgressBar(), jUploadPanel.getUploadButton(),
jUploadPanel.getStopButton(), jUploadPanel);
jUploadPanel.getJComponent().add(progressPanel);
jUploadPanel.getJComponent().addMouseListener(
jUploadPanel.getMouseListener());
// Now, we add the log window.
jUploadPanel.showOrHideLogWindow();
jUploadPanel.getJComponent().add(jUploadPanel.getJLogWindowPane());
// And, to finish with: the status bar.
JPanel p = createStatusBar(jUploadPanel.getStatusLabel(), jUploadPanel);
if (null != p) {
jUploadPanel.getJComponent().add(p);
p.addMouseListener(jUploadPanel.getMouseListener());
}
}
/** {@inheritDoc} */
public void updateButtonState(int executionStatus) {
// First step: check the parameter.
if (executionStatus != UploadPolicy.EXEC_STATUS_READY
&& executionStatus != UploadPolicy.EXEC_STATUS_UPLOADING) {
throw new java.lang.IllegalArgumentException(
"Unknow value for executionStatus: " + executionStatus);
}
// Then ... nothing to do! This class has no specific GUI item.
}
/** @see UploadPolicy#displayErr(Exception) */
public void displayErr(Exception e) {
displayErr(e.getMessage(), e);
}
/** @see UploadPolicy#displayErr(String) */
public void displayErr(String err) {
displayErr(err, null);
}
/**
* Logs a stack trace for the given exception.
*
* @param throwable
*/
private void displayStackTrace(Throwable throwable) {
if (throwable != null) {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(bs);
throwable.printStackTrace(ps);
ps.close();
displayMsg("", bs.toString());
// If there is a cause, let's be sure its stack trace is displayed.
if (throwable.getCause() != null) {
displayMsg("", "Caused by:");
displayStackTrace(throwable.getCause());
}
}
}
/**
* This method just logs an error.
*
* @param errorText
* @param exception
*/
private void logErr(String errorText, Exception exception) {
if (exception == null) {
setLastException(new JUploadException("errorText"));
} else if (exception instanceof JUploadException) {
setLastException((JUploadException) exception);
} else {
setLastException(new JUploadException(exception));
}
// Default behavior: if debugLevel is 0, and an error occurs, we force
// the debug level to 1: this makes the log window become visible, if it
// was hidden.
if (getDebugLevel() == 0)
setDebugLevel(1);
String exceptionMsg = null;
String exceptionClassName = null;
String logMsg = errorText;
// First, we construct the exception class name.
if (exception == null) {
exceptionClassName = "";
} else if (exception instanceof JUploadException) {
exceptionClassName = "["
+ ((JUploadException) exception).getClassNameAndClause()
+ "] ";
} else {
exceptionClassName = "[" + exception.getClass().getName() + "] ";
}
// Then, the message body can be completed by the exception message.
if (exception != null) {
// Ok, we have an exception.
if (exception.getCause() != null) {
exceptionMsg = exception.getCause().getMessage();
} else {
exceptionMsg = exception.getMessage();
}
logMsg = exceptionMsg + " (" + errorText + ")";
}
// Add the message to the log window
displayMsg("[ERROR]", exceptionClassName + logMsg);
// Let's display the stack trace, if relevant.
displayStackTrace(exception);
// Then we copy the debug output to the clipboard, and say it to the
// current user.
if (this.juploadContext.getUploadPanel() != null
&& getDebugLevel() >= 99) {
// Ok, the applet has been fully built.
this.juploadContext.getUploadPanel().copyLogWindow();
alert("messageLogWindowCopiedToClipboard");
}
}
/**
* If debug is off, the log window may not be visible. We switch the debug
* to on, to be sure that some information will be displayed to the user.
* If debug is -1, the log window remains hidden.
*
* @see wjhk.jupload2.policies.UploadPolicy#displayErr(java.lang.String,
* java.lang.Exception, int)
*/
public int displayErr(String errorText, Exception exception, int optionTypes) {
// Then, we display it to the user.
String alertMsg = errorText;
// Then, the message body can be completed by the exception message.
if (exception != null && (errorText == null || errorText.equals(""))) {
// Ok, we have an exception.
if (exception.getCause() != null) {
alertMsg = exception.getCause().getMessage();
} else {
alertMsg = exception.getMessage();
}
}
// The message displayed depend on the debug level:
if (getDebugLevel() >= 30 && exception != null) {
alertMsg = exception.getClass().getName() + ": " + alertMsg;
}
// Display the message to the user. The kind of alert box depends on the
// given options:
int buttonClicked = 0;
switch (optionTypes) {
case -1:
// Standard message box.
alertStr(alertMsg);
buttonClicked = JOptionPane.OK_OPTION;
break;
case JOptionPane.OK_CANCEL_OPTION:
case JOptionPane.YES_NO_CANCEL_OPTION:
case JOptionPane.YES_NO_OPTION:
buttonClicked = confirmDialogStr(alertMsg, optionTypes);
break;
default:
// This is a problem. Let's display it to the user as a standard
// alert box.
alertStr(alertMsg);
buttonClicked = JOptionPane.OK_OPTION;
// Then, we log this new problem.
String msg = "Unknown optionType in displayErr(String, Exception, int)";
alertStr(msg);
logErr(msg, null);
}
// First, we log the error.
logErr(errorText, exception);
return buttonClicked;
}
/**
* If debug is off, the log window may not be visible. We switch the debug
* to on, to be sure that some information will be displayed to the user.
* If debug is -1, the log window remains hidden.
*
* @see wjhk.jupload2.policies.UploadPolicy#displayErr(java.lang.String,
* java.lang.Exception)
*/
public void displayErr(String errorText, Exception exception) {
displayErr(errorText, exception, -1);
}
/**
* @see UploadPolicy#displayInfo(String)
*/
public void displayInfo(String info) {
displayMsg("[INFO]", info);
}
/**
* @see UploadPolicy#displayWarn(String)
*/
public void displayWarn(String warn) {
displayMsg("[WARN]", warn);
}
/**
* @see UploadPolicy#displayDebug(String, int)
*/
public void displayDebug(String debug, int minDebugLevel) {
final String tag = "[DEBUG]";
if (this.debugLevel >= minDebugLevel) {
// displayMsg will add the message to the debugStrignBuffer.
displayMsg(tag, debug);
} else if (this.debugGenerateFile) {
// We have to write the message to the debug file, whatever the
// debugLevel is.
addMsgToDebugLog(tag + debug);
}
}
/** @see UploadPolicy#getLocalizedString(String, Object...) */
public String getLocalizedString(String key, Object... args) {
String ret = this.resourceBundle.getString(key);
try {
// We have to recreate the correct call to String.format
switch (args.length) {
case 0:
return String.format(ret);
case 1:
return String.format(ret, args[0]);
case 2:
return String.format(ret, args[0], args[1]);
case 3:
return String.format(ret, args[0], args[1], args[2]);
case 4:
return String.format(ret, args[0], args[1], args[2], args[3]);
case 5:
return String.format(ret, args[0], args[1], args[2], args[3],
args[4]);
case 6:
return String.format(ret, args[0], args[1], args[2], args[3],
args[4], args[5]);
case 7:
return String.format(ret, args[0], args[1], args[2], args[3],
args[4], args[5], args[6]);
default:
throw new IllegalArgumentException(
"DefaultUploadPolicy.getLocalizedString accepts up to 7 variable parameters ("
+ args.length
+ " values were given for the 'args' argument");
}
} catch (IllegalFormatException ife) {
displayErr(ife.getClass().getName() + " (" + ife.getMessage()
+ ")when managing this string: " + ret);
throw ife;
}
}
/**
* @see UploadPolicy#getUploadFilename(FileData, int)
*/
public String getUploadFilename(FileData fileData, int index)
throws JUploadException {
return getEncodedFilename(fileData.getFileName());
}
/**
* returns the filename and encodes it, if necessary
*
* @param filename
* the original filename
* @return filename (encoded, if necessary)
* @throws JUploadException
*/
protected final String getEncodedFilename(String filename)
throws JUploadException {
if (this.filenameEncoding == null || this.filenameEncoding.equals("")) {
return filename;
}
try {
return URLEncoder.encode(filename, this.filenameEncoding);
} catch (UnsupportedEncodingException e) {
throw new JUploadException(e);
}
}
/** @see UploadPolicy#getUploadName(FileData, int) */
public String getUploadName(FileData fileData, int index)
throws JUploadException {
if (this.httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ARRAY)) {
return this.httpUploadParameterName + "[]";
} else if (this.httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ITERATION)) {
return this.httpUploadParameterName + index;
} else if (this.httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
// Only valid if nbFilesPerRequest is 1. Let's check it.
if (getNbFilesPerRequest() == 1) {
return this.httpUploadParameterName;
} else {
throw new JUploadException(
UploadPolicy.PROP_HTTP_UPLOAD_PARAMETER_TYPE
+ " value '" + this.httpUploadParameterType
+ "' is only valid when '"
+ UploadPolicy.PROP_NB_FILES_PER_REQUEST
+ " is 1.");
}
} else {
throw new JUploadException(
UploadPolicy.PROP_HTTP_UPLOAD_PARAMETER_TYPE + " '"
+ this.httpUploadParameterType
+ "' is not implemented.");
}
}
/** @see UploadPolicy#getHttpUploadParameterName() */
public String getHttpUploadParameterName() {
return this.httpUploadParameterName;
}
/**
* Setter for the {@link #httpUploadParameterName}. This value is used by
* the {@link #getUploadName(FileData, int)} method, to generate the name of
* the upload parameter that will contain the uploaded file.
* The name must begin by a letter, then contain letter or numbers
*
* @throws JUploadException
* When the given value is invalid (null, empty string, or
* contains other characters than letters and/or numbers)
*/
protected void setHttpUploadParameterName(String httpUploadParameterName)
throws JUploadException {
// Some useful checks.
if (httpUploadParameterName == null
|| httpUploadParameterName.equals("")) {
throw new JUploadException(
"httpUploadParameterName may not be null");
}
// Control the parameter name content.
if (!httpUploadParameterName.matches("^[a-zA-Z0-9][a-zA-Z0-9_]*$")) {
throw new JUploadException(
"httpUploadParameterName may only contain letters (lowercase or uppercase) and numbers.");
}
// Ok, we're happy with the given value. Let's store it.
this.httpUploadParameterName = httpUploadParameterName;
}
/** @see UploadPolicy#getHttpUploadParameterType() */
public String getHttpUploadParameterType() {
return this.httpUploadParameterType;
}
/**
* Setter for the {@link #httpUploadParameterType}. This value is used by
* the {@link #getUploadName(FileData, int)} method, to generate the name of
* the upload parameter that will contain the uploaded file. Depending on
* this value, the parameter will be an iteration or an array.
*
* @throws JUploadException
*/
protected void setHttpUploadParameterType(String httpUploadParameterType)
throws JUploadException {
// Some useful checks.
if (httpUploadParameterType == null) {
throw new JUploadException(
"httpUploadParameterType may not be null");
}
// Check against the list of allowed values
if (!httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ARRAY)
&& !httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ITERATION)
&& !httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
throw new JUploadException("'" + httpUploadParameterType
+ "' is not an allowed value for httpUploadParameterType.");
}
// OneFile is only valid ... when we upload file per file !
if (httpUploadParameterType
.equals(UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)) {
if (getNbFilesPerRequest() != 1) {
throw new JUploadException("'" + httpUploadParameterType
+ "' is only valid when nbFilesPerRequest is 1.");
}
}
// Ok, we're happy. Let's store the value !
this.httpUploadParameterType = httpUploadParameterType;
}
/** @see wjhk.jupload2.policies.UploadPolicy#beforeUpload() */
public boolean beforeUpload() {
// Default : nothing to do before upload, so we're ready.
return true;
}
/** @see UploadPolicy#onAppendHeader(ByteArrayEncoder) */
public ByteArrayEncoder onAppendHeader(ByteArrayEncoder bae)
throws JUploadIOException {
Iterator it = this.headers.iterator();
String header;
displayDebug("[onAppendHeader] Start", 80);
while (it.hasNext()) {
header = it.next();
if (header == null || header.equals("")) {
displayWarn("[onAppendHeader] Found one empty header. Ignoring it.");
} else {
bae.append(header).append("\r\n");
displayDebug("[onAppendHeader] Header appended; " + header, 80);
}
}
displayDebug("[onAppendHeader] End", 80);
return bae;
}// appendHeader
/**
* Default implementation of the
* {@link wjhk.jupload2.policies.UploadPolicy#onFileSelected(wjhk.jupload2.filedata.FileData)}
* . Nothing's done.
*/
public void onFileSelected(FileData fileData) {
// Default implementation : no action
}
/**
* Default implementation of the
* {@link wjhk.jupload2.policies.UploadPolicy#onFileDoubleClicked(FileData)}
* . Nothing's done.
*/
public void onFileDoubleClicked(FileData fileData) {
// Default implementation : no action
}
/** @see UploadPolicy#sendDebugInformation(String, Exception) */
public void sendDebugInformation(String description, Exception exception) {
try {
if (null == getUrlToSendErrorTo()) {
displayInfo("getUrlToSendErrorTo is null. No debug information is sent.");
if (exception == null) {
displayInfo(" No exception was stored!");
} else {
displayInfo(" The exception was: "
+ exception.getClass().getName()
+ exception.getMessage());
}
} else {
displayInfo("Sending debug information to "
+ getUrlToSendErrorTo());
if (JOptionPane
.showConfirmDialog(null,
getLocalizedString("questionSendMailOnError"),
getLocalizedString("Confirm"),
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION) {
displayDebug(
"[sendDebugInformation] Within response == true",
30);
String action = null;
String line;
HTTPConnectionHelper connectionHelper = null;
boolean localDebugOk = this.debugOk;
try {
URL url = new URL(this.urlToSendErrorTo);
connectionHelper = new HTTPConnectionHelper(this);
connectionHelper.initRequest(url, "POST", false, true);
ByteArrayEncoder baeContent = new ByteArrayEncoderHTTP(
this, connectionHelper.getByteArrayEncoder()
.getBoundary(), connectionHelper
.getByteArrayEncoder().getEncoding());
// The message is written in English, as it is not sure
// that
// the webmaster speaks the same language as the current
// user.
baeContent.appendTextProperty("description",
"An error occured during upload, in JUpload.",
-1);
String exceptionClass = null;
String exceptionCause = null;
String exceptionStackTrace = null;
if (exception != null) {
exceptionClass = exception.getClass().getName();
if (exception.getCause() != null) {
exceptionCause = exception.getCause()
.getClass().getName();
}
StackTraceElement[] elements = exception
.getStackTrace();
ByteArrayEncoderHTTP baeStackTrace = new ByteArrayEncoderHTTP(
this, connectionHelper
.getByteArrayEncoder()
.getBoundary(), connectionHelper
.getByteArrayEncoder()
.getEncoding());
for (int i = 0; i < elements.length; i += 1) {
baeStackTrace.append(" at ");
baeStackTrace
.append(elements[i].getClassName());
baeStackTrace.append(".");
baeStackTrace.append(elements[i]
.getMethodName());
baeStackTrace.append("() [line ");
baeStackTrace.append(Integer
.toString(elements[i].getLineNumber()));
baeStackTrace.append("]\r\n");
}
baeStackTrace.close();
exceptionStackTrace = baeStackTrace.getString();
}
baeContent.appendTextProperty("exceptionClass",
exceptionClass, -1);
baeContent.appendTextProperty("exceptionCause",
exceptionCause, -1);
baeContent.appendTextProperty("exceptionStackTrace",
exceptionStackTrace, -1);
String baeBound = connectionHelper
.getByteArrayEncoder().getBoundary();
String baeEncoding = connectionHelper
.getByteArrayEncoder().getEncoding();
ByteArrayEncoder baeDebug = new ByteArrayEncoderHTTP(
this, baeBound, baeEncoding);
if (this.debugGenerateFile) {
// During debug output, we need to make sure that
// the debug log is not changed, so we set debugOk
// to false temporarily. -> Everything goes to
// stdout.
action = "flush (debugGenerateFile=true)";
synchronized (this) {
this.debugOut.flush();
this.debugOk = false;
// First, calculate the size of the strings we
// will
// send.
action = "read debug file (debugGenerateFile=true)";
BufferedReader debugIn = new BufferedReader(
new FileReader(this.debugFile));
while ((line = debugIn.readLine()) != null) {
baeDebug.append(line).append("\r\n");
}
debugIn.close();
// We are done with the debug log, so re-enable
// it.
this.debugOk = localDebugOk;
}// synchronized(this)
}// if (this.debugGenerateFile)
else {
action = "read debug file (debugGenerateFile=false)";
baeDebug.append(this.juploadContext.getLogWindow()
.getText());
}
action = "baeDebug.close()";
baeDebug.close();
baeContent.appendTextProperty("debugOutput", baeDebug
.getString(), -1);
baeContent.appendEndPropertyList();
// The content has been built.
baeContent.close();
// byteArrayEncoder
// .append("Content-type:
// application/x-www-form-urlencoded\r\n");
action = "send request";
connectionHelper.append(
"Content-Type: multipart/form-data; boundary=")
.append(
connectionHelper.getBoundary()
.substring(2)).append("\r\n");
connectionHelper.append("Content-length: ").append(
String.valueOf(baeContent.getEncodedLength()))
.append("\r\n");
// Let's send the headers (without baeDescription) ...
connectionHelper.sendRequest();
// Blank line (end of header)
connectionHelper.append("\r\n");
connectionHelper.append(baeContent);
action = "connectionHelper.readHttpResponse()";
int status = connectionHelper.readHttpResponse();
displayDebug(
"========================================================================================",
90);
displayDebug(
"================== sendDebugInformation [start] =================================",
90);
displayDebug(
"========================================================================================",
90);
displayDebug(
"[sendDebugInformation] Sent to server: \r\n"
+ connectionHelper
.getByteArrayEncoder()
.getString(), 90);
displayDebug(
"========================================================================================",
90);
displayDebug(
"[sendDebugInformation] Body received: \r\n"
+ connectionHelper.getResponseBody(),
90);
displayDebug(
"========================================================================================",
90);
displayDebug(
"================== sendDebugInformation [end] =================================",
90);
displayDebug(
"========================================================================================",
90);
// Is our upload a success ?
if (!checkUploadSuccess(status, connectionHelper
.getResponseMsg(), connectionHelper
.getResponseBody())) {
throw new JUploadExceptionUploadFailed(
getLocalizedString("errHttpResponse"));
}
displayInfo("debug information sent correctly");
} catch (MalformedURLException e) {
throw new JUploadIOException(
"Malformed URL Exception for "
+ this.urlToSendErrorTo, e);
} catch (Exception e) {
this.debugOk = localDebugOk;
displayErr(getLocalizedString("errDuringLogManagement")
+ " (" + action + ")", e);
} finally {
this.debugOk = localDebugOk;
}
}
}
} catch (JUploadIOException e) {
displayErr("Could not send debug information", e);
}
}// sendDebugInformation
/**
* This method manages all applet parameters. It allows javascript to update
* their value, for instance after the user chooses a value in a list ...
*
* @throws JUploadException
* @see wjhk.jupload2.policies.UploadPolicy#setProperty(java.lang.String,
* java.lang.String)
*/
public void setProperty(String prop, String value) throws JUploadException {
displayDebug("[DefaultUploadPolicy] Call of setProperty: " + prop
+ " => " + value, 30);
if (prop.equals(PROP_AFTER_UPLOAD_URL)) {
setAfterUploadURL(value);
} else if (prop.equals(PROP_ALLOW_HTTP_PERSISTENT)) {
setAllowHttpPersistent(Boolean.parseBoolean(value));
} else if (prop.equals(PROP_ALLOWED_FILE_EXTENSIONS)) {
setAllowedFileExtensions(value);
} else if (prop.equals(PROP_DEBUG_LEVEL)) {
setDebugLevel(this.juploadContext.parseInt(value, this.debugLevel));
} else if (prop.equals(PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT)) {
setFileChooserIconFromFileContent(this.juploadContext.parseInt(
value, getFileChooserIconFromFileContent()));
} else if (prop.equals(PROP_FILE_CHOOSER_ICON_SIZE)) {
setFileChooserIconSize(this.juploadContext.parseInt(value,
getFileChooserIconSize()));
} else if (prop.equals(PROP_FILE_FILTER_NAME)) {
setFileFilterName(value);
} else if (prop.equals(PROP_FILENAME_ENCODING)) {
setFilenameEncoding(value);
} else if (prop.equals(PROP_LANG)) {
setLang(value);
} else if (prop.equals(PROP_LOOK_AND_FEEL)) {
setLookAndFeel(value);
} else if (prop.equals(PROP_MAX_CHUNK_SIZE)) {
setMaxChunkSize(this.juploadContext.parseLong(value,
this.maxChunkSize));
} else if (prop.equals(PROP_MAX_FILE_SIZE)) {
setMaxFileSize(this.juploadContext.parseLong(value,
this.maxFileSize));
} else if (prop.equals(PROP_NB_FILES_PER_REQUEST)) {
setNbFilesPerRequest(this.juploadContext.parseInt(value,
this.nbFilesPerRequest));
} else if (prop.equals(PROP_POST_URL)) {
setPostURL(value);
} else if (prop.equals(PROP_SERVER_PROTOCOL)) {
HttpProtocolFinderThread.computeServerProtocol(this, value);
} else if (prop.equals(PROP_STRING_UPLOAD_SUCCESS)) {
setStringUploadSuccess(value);
} else if (prop.equals(PROP_SSL_VERIFY_CERT)) {
setSslVerifyCert(value);
} else if (prop.equals(PROP_URL_TO_SEND_ERROR_TO)) {
setUrlToSendErrorTo(value);
} else {
displayWarn("Unknown applet parameter: " + prop
+ " (in DefaultUploadPolicy.setProperty)");
}
}
/**
* This method displays the applet parameter list, according to the current
* debugLevel. It is called by the {@link #setDebugLevel(int)} method. It
* should be override by any subclasses, that should display its own
* parameters, then call super.displayParameterStatus().
*
* @see UploadPolicy#displayParameterStatus()
*/
public void displayParameterStatus() {
displayDebug(
"=======================================================================",
30);
displayDebug("======= Parameters managed by DefaultUploadPolicy", 30);
// /////////////////////////////////////////////////////////////////////////////
// Let's display some information to the user, about the received
// parameters.
displayInfo("JUpload applet, version "
+ this.juploadContext.getDetailedVersionMessage()
+ " (compiled: " + this.juploadContext.getBuildDate()
+ "), available at http://jupload.sourceforge.net/");
displayDebug("Java version: " + System.getProperty("java.version"), 30);
displayDebug("List of all applet parameters:", 30);
displayDebug(" language: "
+ this.resourceBundle.getLocale().getLanguage(), 30);
displayDebug(" country: "
+ this.resourceBundle.getLocale().getCountry(), 30);
displayDebug(PROP_AFTER_UPLOAD_URL + ": " + getAfterUploadURL(), 30);
displayDebug(PROP_ALLOW_HTTP_PERSISTENT + ": "
+ getAllowHttpPersistent(), 30);
displayDebug(PROP_ALLOWED_FILE_EXTENSIONS + ": "
+ getAllowedFileExtensions(), 30);
displayDebug(PROP_BROWSING_DIRECTORY + " (current value): "
+ getCurrentBrowsingDirectory(), 30);
displayDebug(PROP_DEBUG_LEVEL + ": " + this.debugLevel, 1);
synchronized (this) {
if (this.debugGenerateFile) {
displayDebug(" (debugfile: "
+ this.debugFile.getAbsolutePath() + ")", 1);
}
}
displayDebug(PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT + ": "
+ getFileChooserIconFromFileContent(), 30);
displayDebug(PROP_FILE_CHOOSER_ICON_SIZE + ": "
+ getFileChooserIconSize(), 30);
displayDebug(PROP_FILE_FILTER_NAME + ": " + getFileFilterName(), 30);
displayDebug(PROP_FILENAME_ENCODING + ": " + getFilenameEncoding(), 30);
displayDebug(PROP_FORMDATA + ": " + getFormdata(), 30);
displayDebug(PROP_FTP_CREATE_DIRECTORY_STRUCTURE + ": "
+ getFtpCreateDirectoryStructure(), 30);
displayDebug(
PROP_FTP_TRANSFERT_BINARY + ": " + getFtpTransfertBinary(), 30);
displayDebug(PROP_FTP_TRANSFERT_PASSIVE + ": "
+ getFtpTransfertPassive(), 30);
displayDebug(PROP_HTTP_UPLOAD_PARAMETER_NAME + ": "
+ getHttpUploadParameterName(), 30);
displayDebug(PROP_HTTP_UPLOAD_PARAMETER_TYPE + ": "
+ getHttpUploadParameterType(), 30);
displayDebug("lang: " + this.lang, 30);
displayDebug(PROP_MAX_CHUNK_SIZE + ": " + getMaxChunkSize(), 30);
if (this.maxFileSize == Long.MAX_VALUE) {
// If the maxFileSize was not given, we display its value only
// in debug mode.
displayDebug(PROP_MAX_FILE_SIZE + ": " + getMaxFileSize(), 30);
} else {
// If the maxFileSize was given, we always inform the user.
displayInfo(PROP_MAX_FILE_SIZE + ": " + getMaxFileSize());
}
displayDebug(PROP_NB_FILES_PER_REQUEST + ": " + getNbFilesPerRequest(),
30);
displayDebug(PROP_POST_URL + ": " + this.postURL, 30);
displayDebug(PROP_READ_COOKIE_FROM_NAVIGATOR + ": "
+ this.readCookieFromNavigator, 30);
displayDebug(PROP_READ_USER_AGENT_FROM_NAVIGATOR + ": "
+ this.readUserAgentFromNavigator, 30);
displayDebug(PROP_RETRY_MAX_NUMBER_OF + ": " + this.retryMaxNumberOf,
30);
displayDebug(PROP_RETRY_NB_SECONDS_BETWEEN + ": "
+ this.retryNbSecondsBetween, 30);
displayDebug(PROP_SEND_MD5_SUM + ": " + getSendMD5Sum(), 30);
displayDebug(PROP_SERVER_PROTOCOL + ": " + getServerProtocol(), 30);
displayDebug(PROP_SHOW_LOGWINDOW + ": " + getShowLogWindow(), 30);
displayDebug(PROP_SHOW_STATUSBAR + ": " + this.showStatusbar, 30);
displayDebug(PROP_SPECIFIC_HEADERS + ": " + getSpecificHeaders(), 30);
displayDebug("Headers that will be added to the POST request: ", 30);
for (Iterator it = this.headers.iterator(); it.hasNext();) {
displayDebug(it.next() + "\n", 30);
}
displayDebug(PROP_STRING_UPLOAD_ERROR + ": " + getStringUploadError(),
30);
displayDebug(PROP_STRING_UPLOAD_SUCCESS + ": "
+ getStringUploadSuccess(), 30);
displayDebug(PROP_STRING_UPLOAD_WARNING + ": "
+ getStringUploadWarning(), 30);
displayDebug(PROP_URL_TO_SEND_ERROR_TO + ": " + getUrlToSendErrorTo(),
30);
displayDebug("", 30);
}
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// getters / setters
// ///////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////////////////////////////////
/** @see UploadPolicy#getAfterUploadURL() */
public String getAfterUploadURL() {
return this.afterUploadURL;
}
/**
* Set the {@link #afterUploadURL}
*
* @param afterUploadURL
* The URL to use.
* @throws JUploadException
*/
protected void setAfterUploadURL(String afterUploadURL)
throws JUploadException {
if (null == afterUploadURL)
return;
if (afterUploadURL.toLowerCase().startsWith("javascript:")) {
this.afterUploadURL = afterUploadURL;
} else
this.afterUploadURL = this.juploadContext
.normalizeURL(afterUploadURL);
}
/**
* @see wjhk.jupload2.policies.UploadPolicy#getAllowHttpPersistent()
*/
public boolean getAllowHttpPersistent() {
return this.allowHttpPersistent;
}
/** @see UploadPolicy#getAllowedFileExtensions() */
public String getAllowedFileExtensions() {
return this.allowedFileExtensions;
}
/**
* @param allowedFileExtensions
* the allowedFileExtensions to set
*/
protected void setAllowedFileExtensions(String allowedFileExtensions) {
if (allowedFileExtensions == null || allowedFileExtensions.equals("")) {
this.allowedFileExtensions = null;
} else {
this.allowedFileExtensions = (allowedFileExtensions.startsWith("/") ? ""
: "/")
+ allowedFileExtensions.toLowerCase()
+ (allowedFileExtensions.endsWith("/") ? "" : "/");
}
}
protected void setAllowHttpPersistent(boolean value) {
this.allowHttpPersistent = value;
}
/** @see UploadPolicy#getContext() */
public JUploadContext getContext() {
return this.juploadContext;
}
/** {@inheritDoc} */
public void setCurrentBrowsingDirectory(File currentBrowsingDirectoryParam) {
try {
if (currentBrowsingDirectoryParam.isDirectory()) {
this.currentBrowsingDirectory = currentBrowsingDirectoryParam;
} else {
displayWarn("DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
+ currentBrowsingDirectoryParam + " doesn't exist.");
}
} catch (SecurityException se) {
displayWarn(se.getClass().getName()
+ " in DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
+ currentBrowsingDirectoryParam + " is ignored.");
}
}
/**
* @param currentBrowsingDirectoryParam
* The name of the directory that should be the current one.
* @see UploadPolicy#setCurrentBrowsingDirectory(String)
*/
public void setCurrentBrowsingDirectory(String currentBrowsingDirectoryParam) {
try {
if (currentBrowsingDirectoryParam == null) {
this.currentBrowsingDirectory = null;
} else {
// Apparently, Java deosn't manage path beginning by ~. folder
// is actually ... ~!
// Let's manager this.
if (currentBrowsingDirectoryParam.startsWith("~")) {
// Let's keep the part of this path that is after the ~
currentBrowsingDirectoryParam = System
.getProperty("user.home")
+ currentBrowsingDirectoryParam.substring(1);
}
this.currentBrowsingDirectory = new File(
currentBrowsingDirectoryParam);
// Let's check that we have a folder.
if (this.currentBrowsingDirectory != null
&& !this.currentBrowsingDirectory.isDirectory()) {
displayWarn("DefaultUploadPolicy.setCurrentBrowsingDirectory(): <"
+ currentBrowsingDirectoryParam
+ "> doesn't exist or is not a directory.");
this.currentBrowsingDirectory = null;
}
}
} catch (SecurityException se) {
displayWarn(se.getClass().getName()
+ " in DefaultUploadPolicy.setCurrentBrowsingDirectory(): "
+ currentBrowsingDirectoryParam + " is ignored.");
}
}
/** @see UploadPolicy#getCurrentBrowsingDirectory() */
public File getCurrentBrowsingDirectory() {
return this.currentBrowsingDirectory;
}
/** @see UploadPolicy#getDateFormat() */
public String getDateFormat() {
return UploadPolicy.DEFAULT_DATE_FORMAT;
}
/** @see UploadPolicy#getDebugLevel() */
public int getDebugLevel() {
return this.debugLevel;
}
/** @see UploadPolicy#setDebugLevel(int) */
public void setDebugLevel(int debugLevel) {
setDebugLevel(debugLevel, true);
}
/**
* Set the debug level.
*
* @param debugLevel
* The new debuglevel.
* @param displayAppletParameterList
* Flag. If set to true, the applet's parameters are shown.
*/
public synchronized void setDebugLevel(int debugLevel,
boolean displayAppletParameterList) {
// If the debugLevel was previously set, we inform the user of this
// change.
if (this.debugLevel >= 0) {
displayInfo("Debug level set to " + debugLevel);
if (this.debugGenerateFile) {
displayInfo("Current debug output file: "
+ this.debugFile.getAbsolutePath());
}
}
this.debugLevel = debugLevel;
// Let's display the current applet parameters.
if (displayAppletParameterList) {
displayParameterStatus();
}
}
/**
* Getter for fileChooserIconFromFileContent.
*
* @return Current value for fileChooserIconFromFileContent
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
*/
public int getFileChooserIconFromFileContent() {
return this.fileChooserIconFromFileContent;
}
/**
* Setter for fileChooserIconFromFileContent. Current allowed values are:
* -1, 0, 1. Default value is 0.
*
* @param fileChooserIconFromFileContent
* Value to be set. If the value is not allowed (not -1, 0 or 1),
* the current value is unchangeed.
* @exception java.lang.IllegalArgumentException
* When a value not in -1, 0 1 is given.
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_FROM_FILE_CONTENT
*/
public void setFileChooserIconFromFileContent(
int fileChooserIconFromFileContent) {
if (fileChooserIconFromFileContent != -1
&& fileChooserIconFromFileContent != 0
&& fileChooserIconFromFileContent != 1) {
throw new java.lang.IllegalArgumentException(
"fileChooserIconFromFileContent must be one of -1, 0, 1");
}
this.fileChooserIconFromFileContent = fileChooserIconFromFileContent;
}
/**
* Getter for fileChooserIconSize.
*
* @return Current value for fileChooserIconSize
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
*/
public int getFileChooserIconSize() {
return this.fileChooserIconSize;
}
/**
* Setter for fileChooserIconSize.
*
* @param fileChooserIconSize
* Value to be set.
* @exception java.lang.IllegalArgumentException
* When a negative value is given.
* @see UploadPolicy#PROP_FILE_CHOOSER_ICON_SIZE
*/
public void setFileChooserIconSize(int fileChooserIconSize) {
if (fileChooserIconSize <= 0) {
throw new java.lang.IllegalArgumentException(
"fileChooserIconSize must be more than 0");
}
this.fileChooserIconSize = fileChooserIconSize;
}
/** @see wjhk.jupload2.policies.UploadPolicy#setLang(String) */
public void setLang(String lang) {
this.lang = lang;
if (lang == null) {
displayInfo("lang = null, taking default language");
locale = Locale.getDefault();
} else {
// If we have a 5 characters lang string, then it should look like
// ll_CC, where ll is the language code
// and CC is the Country code.
if (lang.length() == 5
&& (lang.substring(2, 3).equals("_") || lang
.substring(2, 3).equals("-"))) {
String language = lang.substring(0, 2);
String country = lang.substring(3, 5);
displayDebug("setLang - language read: " + language, 50);
displayDebug("setLang - country read: " + country, 50);
locale = new Locale(language, country.toUpperCase());
} else {
locale = new Locale(lang);
displayDebug("setLang - language read (no country): " + lang,
50);
}
}
/*
* Patch given by Patrick Use of a specific class loader. The standard
* ResourceBundle checks first for a class that has the name of the
* resource bundle. Since there is no such class in the jar file, the
* AppletClassLoader makes a http request to the server, which will end
* with a 404 since there is no such class either. To avoid this
* unnecessary lookup we use a class loader that throws directly a
* ClassNotFoundException. After looking for a class (which is
* unsuccessful) ResourceBundle looks finally for a properties file.
* Therefore we delegate that lookup to the original class loader since
* this is in the jar file.
*/
this.resourceBundle = ResourceBundle.getBundle("lang.lang", locale,
// Special class loader, see description above
new ClassLoader(this.getClass().getClassLoader()) {
/** {@inheritDoc} */
@Override
public Class> loadClass(String name)
throws ClassNotFoundException {
throw new ClassNotFoundException();
}
/** {@inheritDoc} */
@Override
public InputStream getResourceAsStream(String name) {
return this.getClass().getClassLoader()
.getResourceAsStream(name);
}
});
}
/** {@inheritDoc} */
public Locale getLocale() {
return this.locale;
}
/**
*/
protected String getLookAndFeel() {
return this.lookAndFeel;
}
/**
* @param lookAndFeel
* the lookAndFeel to set
*/
protected void setLookAndFeel(String lookAndFeel) {
try {
this.lookAndFeel = lookAndFeel;
if (lookAndFeel != null && !lookAndFeel.equals("")
&& !lookAndFeel.equals("java")) {
// We try to call the UIManager.setLookAndFeel() method. We
// catch
// all possible exceptions, to prevent
// that the applet is blocked.
if (!lookAndFeel.equals("system")) {
// Correction given by Fritz. Thanks to him.
UIManager.setLookAndFeel(lookAndFeel);
} else {
UIManager.setLookAndFeel(UIManager
.getSystemLookAndFeelClassName());
}
} else {
this.lookAndFeel = "java";
UIManager
.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
}
} catch (Exception e) {
displayErr(e);
try {
this.lookAndFeel = "java";
UIManager
.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel());
} catch (UnsupportedLookAndFeelException e1) {
displayErr(e1);
// Hum, hum: we should not arrive here... We not a 'dummy' one.
this.lookAndFeel = null;
}
}
}
/** @see wjhk.jupload2.policies.UploadPolicy#getMaxChunkSize() */
public long getMaxChunkSize() {
return this.maxChunkSize;
}
/**
* If the given value is less or equals to 0, it is set back to
* Long_MAX_VALUE.
*
* @param maxChunkSize
* the maxChunkSize to set
*/
protected void setMaxChunkSize(long maxChunkSize) {
if (maxChunkSize <= 0) {
displayDebug(
"maxChunkSize<=0 which is invalid. Switched to the default value (Long.MAX_VALUE)",
1);
maxChunkSize = Long.MAX_VALUE;
}
this.maxChunkSize = maxChunkSize;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getMaxFileSize() */
public long getMaxFileSize() {
return this.maxFileSize;
}
/**
* @param maxFileSize
* the maxFileSize to set
*/
protected void setMaxFileSize(long maxFileSize) {
if (maxFileSize <= 0) {
displayDebug(
"maxFileSize<=0 which is invalid. Switched to the default value (Long.MAX_VALUE)",
1);
maxFileSize = Long.MAX_VALUE;
}
this.maxFileSize = maxFileSize;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getNbFilesPerRequest() */
public int getNbFilesPerRequest() {
return this.nbFilesPerRequest;
}
/**
* @param nbFilesPerRequest
* the nbFilesPerRequest to set
* @throws JUploadException
*/
protected void setNbFilesPerRequest(int nbFilesPerRequest)
throws JUploadException {
// If httpUploadParameterType is oneFile,
if (getHttpUploadParameterType().equals(
UploadPolicy.HTTPUPLOADPARAMETERTYPE_ONE_FILE)
&& nbFilesPerRequest != 1) {
throw new JUploadException(
"nbFilesPerRequest must be 1, when httpUploadParameterType is oneFile");
}
if (nbFilesPerRequest < 1) {
displayDebug(
"nbFilesPerRequest <1 : switched to the 'unlimited' value (Integer.MAX_VALUE)",
1);
this.nbFilesPerRequest = Integer.MAX_VALUE;
} else {
this.nbFilesPerRequest = nbFilesPerRequest;
}
}
/** @see UploadPolicy#getFilenameEncoding() */
public String getFilenameEncoding() {
return this.filenameEncoding;
}
/** @see UploadPolicy#getFileFilterName() */
public String getFileFilterName() {
return this.fileFilterName;
}
/**
* @param fileFilterName
* The new name for the fileFilter
* @see UploadPolicy#PROP_FILE_FILTER_NAME
*/
protected void setFileFilterName(String fileFilterName) {
this.fileFilterName = fileFilterName;
}
/**
* @param filenameEncoding
* the filenameEncoding to set
*/
protected void setFilenameEncoding(String filenameEncoding) {
if (filenameEncoding != null && filenameEncoding.equals("")) {
filenameEncoding = null;
}
if (filenameEncoding != null && !Charset.isSupported(filenameEncoding)) {
throw new UnsupportedCharsetException("non supported charset ("
+ filenameEncoding + ")");
}
this.filenameEncoding = filenameEncoding;
}
/** @see UploadPolicy#getFtpCreateDirectoryStructure() */
public boolean getFtpCreateDirectoryStructure() {
return this.ftpCreateDirectoryStructure;
}
/**
* @param ftpCreateDirectoryStructure
* the ftpCreateDirectoryStructure to set
*/
protected void setFtpCreateDirectoryStructure(
boolean ftpCreateDirectoryStructure) {
this.ftpCreateDirectoryStructure = ftpCreateDirectoryStructure;
}
/** @see UploadPolicy#getFtpTransfertBinary() */
public boolean getFtpTransfertBinary() {
return this.ftpTransfertBinary;
}
/**
* @param ftpTransfertBinary
* the ftpTransfertBinary to set
*/
protected void setFtpTransfertBinary(boolean ftpTransfertBinary) {
this.ftpTransfertBinary = ftpTransfertBinary;
}
/** @see UploadPolicy#getFtpTransfertPassive() */
public boolean getFtpTransfertPassive() {
return this.ftpTransfertPassive;
}
/**
* @param ftpTransfertPassive
* the ftpTransfertPassive to set
*/
protected void setFtpTransfertPassive(boolean ftpTransfertPassive) {
this.ftpTransfertPassive = ftpTransfertPassive;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getPostURL() */
public String getPostURL() {
return this.postURL;
}
/**
* @throws JUploadException
* @see wjhk.jupload2.policies.UploadPolicy#setPostURL(String)
*/
public void setPostURL(String postURL) throws JUploadException {
// Be more forgiving about postURL:
// - If none is specified, use the original DocumentBase of the
// applet.
// - If a non-absolute URI (an URI without protocol and server) is
// specified,
// prefix it with "http://servername"
// - If a relative URI is specified, prefix it with the DocumentBase's
// parent
this.postURL = this.juploadContext.normalizeURL(postURL);
}
/** @see wjhk.jupload2.policies.UploadPolicy#getReadCookieFromNavigator() */
public boolean getReadCookieFromNavigator() {
return this.readCookieFromNavigator;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getReadCookieFromNavigator() */
protected void setReadCookieFromNavigator(boolean readCookieFromNavigator) {
this.readCookieFromNavigator = readCookieFromNavigator;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getReadUserAgentFromNavigator() */
public boolean getReadUserAgentFromNavigator() {
return this.readUserAgentFromNavigator;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getReadUserAgentFromNavigator() */
protected void setReadUserAgentFromNavigator(
boolean readUserAgentFromNavigator) {
this.readUserAgentFromNavigator = readUserAgentFromNavigator;
}
/** @see UploadPolicy#getRetryMaxNumberOf() */
public int getRetryMaxNumberOf() {
return this.retryMaxNumberOf;
}
/**
* @param retryMaxNumberOf
* New value to set for the retryMaxNumberOf applet parameter
* @exception IllegalArgumentException
* If retryMaxNumberOf is less than 0.
* @see UploadPolicy#getRetryMaxNumberOf()
*/
public void setRetryMaxNumberOf(int retryMaxNumberOf) {
if (retryMaxNumberOf < 0) {
throw new IllegalArgumentException(
"retryMaxNumberOf must be 0 or more");
}
this.retryMaxNumberOf = retryMaxNumberOf;
}
/** @see UploadPolicy#getRetryNbSecondsBetween() */
public int getRetryNbSecondsBetween() {
return this.retryNbSecondsBetween;
}
/**
* @param retryNbSecondsBetween
* New value to set for the retryNbSecondsBetween applet
* parameter
* @exception IllegalArgumentException
* If retryNbSecondsBetween is less than 0.
* @see UploadPolicy#getRetryNbSecondsBetween()
*/
public void setRetryNbSecondsBetween(int retryNbSecondsBetween) {
if (retryNbSecondsBetween < 0) {
throw new IllegalArgumentException(
"retryNbSecondsBetween must be 0 or more");
}
this.retryNbSecondsBetween = retryNbSecondsBetween;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getServerProtocol() */
public String getServerProtocol() {
if (this.serverProtocol == null) {
return DEFAULT_SERVER_PROTOCOL;
} else {
return this.serverProtocol;
}
}
/** @see UploadPolicy#setServerProtocol(String) */
public void setServerProtocol(String serverProtocol) {
this.serverProtocol = serverProtocol;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getSendMD5Sum() */
public boolean getSendMD5Sum() {
return this.sendMD5Sum;
}
/** @see UploadPolicy#setSendMD5Sum(boolean) */
public void setSendMD5Sum(boolean sendMD5Sum) {
this.sendMD5Sum = sendMD5Sum;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getShowLogWindow() */
public String getShowLogWindow() {
return this.showLogWindow;
}
/** {@inheritDoc} */
public void setShowLogWindow(String showLogWindow) {
if (showLogWindow.equals(SHOWLOGWINDOW_TRUE)
|| showLogWindow.equals(SHOWLOGWINDOW_FALSE)
|| showLogWindow.equals(SHOWLOGWINDOW_ONERROR)) {
this.showLogWindow = showLogWindow;
// The log window may become visible or hidden, depending on this
// parameter.
if (this.juploadContext.getUploadPanel() != null) {
this.juploadContext.getUploadPanel().showOrHideLogWindow();
}
} else {
displayWarn("[setShowLogWindow] Unallowed value: " + showLogWindow
+ " (showLogWindow is left unchanged)");
}
}
/** @see wjhk.jupload2.policies.UploadPolicy#getSpecificHeaders() */
public String getSpecificHeaders() {
return this.specificHeaders;
}
/**
* Set all specific headers defined in the specificHeaders applet parameter.
* This string is splitted, so that each header is added to the headers
* Vector. These headers are added to the headers list during applet
* initialization. There is currently no automatic way to remove the headers
* coming from specificHeaders, after initialization.
*
* @param specificHeaders
*/
protected void setSpecificHeaders(String specificHeaders) {
this.specificHeaders = specificHeaders;
if (specificHeaders != null) {
// Let's add each header in specificHeaders to the headers list. In
// specificHeaders, each header is separated by the \n string (two
// characters: \ then n, not the \n character).
// The regexp to find the \n string (not the \n character) is: \\n
// We then double each \ character:
String[] headerArray = specificHeaders.split("\\\\n");
for (int x = 0; x < headerArray.length; x++) {
addHeader(headerArray[x]);
}
}
}
/**
* @see wjhk.jupload2.policies.UploadPolicy#getSslVerifyCert()
*/
public int getSslVerifyCert() {
return this.sslVerifyCert;
}
protected void setSslVerifyCert(String mode) throws JUploadException {
int val = -1;
if (mode.toLowerCase().equals("none"))
val = InteractiveTrustManager.NONE;
if (mode.toLowerCase().equals("server"))
val = InteractiveTrustManager.SERVER;
if (mode.toLowerCase().equals("client"))
val = InteractiveTrustManager.CLIENT;
if (mode.toLowerCase().equals("strict"))
val = InteractiveTrustManager.STRICT;
if (val == -1)
throw new JUploadException("Invalid parameter sslVerifyCert ("
+ mode + ")");
this.sslVerifyCert = val;
}
/**
* @param show
* the new showStatusbar value
*/
protected void setShowStatusbar(boolean show) {
this.showStatusbar = show;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadError() */
public String getStringUploadError() {
return this.stringUploadError;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadSuccess() */
public String getStringUploadSuccess() {
return this.stringUploadSuccess;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getStringUploadWarning() */
public String getStringUploadWarning() {
return this.stringUploadWarning;
}
/**
* @param stringUploadError
* the stringUploadError to set
* @throws JUploadException
*/
protected void setStringUploadError(String stringUploadError)
throws JUploadException {
this.stringUploadError = stringUploadError;
if (stringUploadError != null) {
try {
this.patternError = Pattern.compile(stringUploadError);
} catch (PatternSyntaxException e) {
throw new JUploadException(
"Invalid regex in parameter stringUploadError");
}
}
}
/**
* @param stringUploadSuccess
* the stringUploadSuccess to set
* @throws JUploadException
*/
protected void setStringUploadSuccess(String stringUploadSuccess)
throws JUploadException {
this.stringUploadSuccess = stringUploadSuccess;
if (stringUploadSuccess != null) {
try {
this.patternSuccess = Pattern.compile(stringUploadSuccess);
} catch (PatternSyntaxException e) {
throw new JUploadException(
"Invalid regex in parameter stringUploadSuccess");
}
}
}
/**
* @param stringUploadWarning
* the stringUploadWarning to set
* @throws JUploadException
*/
protected void setStringUploadWarning(String stringUploadWarning)
throws JUploadException {
this.stringUploadWarning = stringUploadWarning;
if (stringUploadWarning != null) {
try {
this.patternWarning = Pattern.compile(stringUploadWarning);
} catch (PatternSyntaxException e) {
throw new JUploadException(
"Invalid regex in parameter stringUploadWarning");
}
}
}
/** @see wjhk.jupload2.policies.UploadPolicy#getUrlToSendErrorTo() */
public String getUrlToSendErrorTo() {
return this.urlToSendErrorTo;
}
/** {@inheritDoc} */
public void setUrlToSendErrorTo(String urlToSendErrorTo)
throws JUploadException {
if (null == urlToSendErrorTo)
return;
String tmp = this.juploadContext.normalizeURL(urlToSendErrorTo);
if (tmp.startsWith("ftp://")) {
throw new JUploadException(
"urlToSendErrorTo: ftp scheme not supported.");
}
this.urlToSendErrorTo = tmp;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getFormdata() */
public String getFormdata() {
return this.formData;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getAfterUploadTarget() */
public String getAfterUploadTarget() {
return this.afterUploadTarget;
}
// //////////////////////////////////////////////////////////////////////////////////////////////
// /////////////////// Internal methods
// //////////////////////////////////////////////////////////////////////////////////////////////
/**
* Delete the current log. (called upon applet termination)
*/
public synchronized void deleteLog() {
if (this.debugGenerateFile) {
try {
if (null != this.debugOut) {
this.debugOut.close();
this.debugOut = null;
}
if (null != this.debugFile) {
if (!this.debugFile.delete()) {
displayWarn(this.debugFile.getName()
+ " was not correctly removed!");
}
this.debugFile = null;
}
} catch (Exception e) {
// nothing to do: we mask the exception.
displayWarn(e.getClass().getName()
+ " occured in deleteLog(). Exception ignored.");
}
}
}
/**
* This methods allows the applet to store all messages (debug, warning,
* info, errors...) into a StringBuffer. If any problem occurs, the whole
* output (displayed or not by the displayDebug, for instance) can be stored
* in a file, or sent to the webmaster. This can help to identify and
* correct problems that can occurs on the various computer configurations.
*
* @param msg
*/
protected synchronized void addMsgToDebugLog(String msg) {
// If uploading lots of chunks, the buffer gets too large, resulting in
// a OutOfMemoryError on the heap so we now use a temporary file for the
// debug log.
if (this.debugGenerateFile && this.debugOk) {
try {
if (null == this.debugOut) {
this.juploadContext.registerUnload(this, "deleteLog");
this.debugFile = File
.createTempFile("jupload_", "_log.txt");
this.debugOut = new PrintStream(new FileOutputStream(
this.debugFile));
}
boolean endsLF = msg.endsWith("\n");
msg = msg.replaceAll("\n", this.CRLF);
if (endsLF) {
this.debugOut.print(msg);
} else {
this.debugOut.println(msg);
}
} catch (IOException e) {
this.debugOk = false;
System.err.println("IO error on debuglog "
+ this.debugFile.getPath()
+ "\nFallback to standard output.");
System.out.println(msg);
}
} else {
System.out.println(msg);
}
}
/**
* Displays a message. If the logWindow panel is set, the message is
* displayed on it. If not, the System.out.println function is used.
*
* @param msg
* The message to display.
*/
private void displayMsg(String tag, String msg) {
String message;
if (this.juploadContext.getLogWindow() == null) {
message = tag + " - " + msg;
System.out.println(message);
} else {
message = this.juploadContext.getLogWindow().displayMsg(tag, msg);
}
// Let's store all text in the debug logfile
if (this.debugGenerateFile) {
addMsgToDebugLog(message);
}
}
/**
* Default reaction after a successful drop operation: no action.
*
* @see UploadPolicy#afterFileDropped(DropTargetDropEvent)
*/
public void afterFileDropped(DropTargetDropEvent dropEvent) {
// Default: no action.
}
/**
* Default implementation for {@link UploadPolicy#createFileChooser()}: just
* a creation of a {@link JUploadFileChooser}.
*
* @see UploadPolicy#createFileChooser()
*/
public JUploadFileChooser createFileChooser() {
return new JUploadFileChooser(this);
}
/**
* This method returns the response for the
* {@link JUploadFileFilter#accept(File)} which just calls this method. This
* method checks that the file extension corresponds to the
* allowedFileExtensions applet parameter.
*
* @see UploadPolicy#fileFilterAccept(File)
*/
public boolean fileFilterAccept(File file) {
if (file.isDirectory()) {
return true;
} else if (this.allowedFileExtensions == null
|| this.allowedFileExtensions.equals("")) {
return true;
} else {
// Get the file extension
String extension = DefaultFileData.getExtension(file).toLowerCase();
// allowedFileExtensions is :
// - a list of file extensions,
// - in lower case,
// - separated by slash
// - A slash has been added at the beginning in
// setAllowedFileExtensions
// - A slash has been added at the end in setAllowedFileExtensions
// So, we just look for the /ext/ string in the stored
// allowedFileExtensions.
return (this.allowedFileExtensions.indexOf("/" + extension + "/")) >= 0;
}
}
/** @see UploadPolicy#fileFilterGetDescription() */
public String fileFilterGetDescription() {
if (this.allowedFileExtensions == null
|| this.allowedFileExtensions.equals("")) {
return null;
} else if (getFileFilterName() != null) {
return getFileFilterName();
} else {
return "JUpload file filter (" + this.allowedFileExtensions + ")";
}
}
/**
* Returns null: the default icon is used.
*
* @see UploadPolicy#fileViewGetIcon(File)
*/
public Icon fileViewGetIcon(File file) {
return null;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getLastException() */
public JUploadException getLastException() {
return this.lastException;
}
/**
* Set the last exception.
*
* @param exception
* The last exception that occurs into the applet.
*/
public void setLastException(JUploadException exception) {
this.lastException = exception;
// The log window may become visible.
if (this.juploadContext.getUploadPanel() != null) {
this.juploadContext.getUploadPanel().showOrHideLogWindow();
}
}
/** @see wjhk.jupload2.policies.UploadPolicy#getLastResponseBody() */
public String getLastResponseBody() {
return this.lastResponseBody;
}
/** @see wjhk.jupload2.policies.UploadPolicy#getLastResponseMessage() */
public String getLastResponseMessage() {
return (null != this.lastResponseMessage) ? this.lastResponseMessage
: "";
}
/**
* @return The cursor that was active before setting the new one. Can be
* used to restore its previous state.
* @see UploadPolicy#setCursor(Cursor)
*/
public Cursor setCursor(Cursor cursor) {
return this.juploadContext.setCursor(cursor);
}
/**
* @return The cursor that was active before setting the new one. Can be
* used to restore its previous state.
* @see UploadPolicy#setWaitCursor()
*/
public Cursor setWaitCursor() {
return this.juploadContext.setWaitCursor();
}
}