// // $Id: JUploadApplet.java 750 2009-05-06 14:36:50Z etienne_sf $ // // jupload - A file upload applet. // Copyright 2007 The JUpload Team // // Created: ? // Creator: William JinHua Kwong // Last modified: $Date: 2009-05-06 16:36:50 +0200 (mer., 06 mai 2009) $ // // 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.context; import java.awt.Container; import java.awt.Cursor; import java.awt.Frame; import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.Vector; import java.util.regex.Matcher; import javax.swing.JApplet; import javax.swing.JFileChooser; import javax.swing.JOptionPane; import netscape.javascript.JSException; import netscape.javascript.JSObject; import wjhk.jupload2.exception.JUploadException; /** * Implementation of the Jupload Context, for an applet. One such context is * created at run time. * * @see DefaultJUploadContext * @author etienne_sf * @version $Revision: 750 $ */ public class JUploadContextApplet extends DefaultJUploadContext { /** * The current applet. All applet parameters are reading by using this * attribute. */ JApplet theApplet = null; /** * The default constructor. * * @param theApplet * The applet is mandatory, to read the applet parameters. */ public JUploadContextApplet(JApplet theApplet) { if (theApplet == null) { throw new IllegalArgumentException("theApplet may not be null"); } this.theApplet = theApplet; // The applet must be signed ! checkAppletIsSigned(); // Let's initialize the DefaultJUploadContext. init(findParentFrame(theApplet), theApplet); } /** * This method checks that the applet is signed. To do this, it just check * that the current folder is readable, and that the applet can create * temporary files. Should be enough.
* If anyone has a better idea ... I'll be hapy to listen to it! */ void checkAppletIsSigned() { // Let's be optimistic! ;-) java.lang.SecurityException ex = null; try { // I found no way to directly get the current directory (access to // user.xxx system properties is prohibited from within applets) JFileChooser fc = new JFileChooser(); File currentDir = fc.getCurrentDirectory(); if (!currentDir.canRead()) { ex = new java.lang.SecurityException( "The applet must be signed (can't write in '" + currentDir.getAbsolutePath() + "')"); } // Let's now check that the applet may create a temporary file. May // be necessary for further processing, and for logging. try { File tmpTestFile = File.createTempFile("jupload", "test"); tmpTestFile.delete(); } catch (IOException ioe) { String msg = ioe.getClass().getName() + ": Can't create temporary file (the applet is perhaps not signed (original error message: " + ioe.getMessage() + ")"; System.out.println(msg); ex = new java.lang.SecurityException(msg, ioe); ioe.printStackTrace(); } } catch (java.lang.SecurityException e) { String msg = "The applet must be signed (original error message: " + e.getMessage() + ")"; System.out.println(msg); ex = new java.lang.SecurityException(msg, e); } if (ex != null) { String msg = ex.getClass().getName() + " - " + ex.getMessage(); JOptionPane.showMessageDialog(null, msg, "Alert", JOptionPane.ERROR_MESSAGE); System.out.println(msg); ex.printStackTrace(); throw ex; } } /** * Find the JFrame which contains the applet * * @param theApplet * @return */ private Frame findParentFrame(JApplet theApplet) { Container c = theApplet; while (c != null) { if (c instanceof Frame) return (Frame) c; c = c.getParent(); } return (Frame) null; } /** {@inheritDoc} */ @Override public JApplet getApplet() { return this.theApplet; } /** {@inheritDoc} */ @Override public String getParameter(String key, String def) { String paramStr = (this.theApplet.getParameter(key) != null ? this.theApplet .getParameter(key) : def); displayDebugParameterValue(key, paramStr); return paramStr; } /** {@inheritDoc} */ @Override public int getParameter(String key, int def) { String paramDef = Integer.toString(def); String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet .getParameter(key) : paramDef; displayDebugParameterValue(key, paramStr); return parseInt(paramStr, def); } /** {@inheritDoc} */ @Override public float getParameter(String key, float def) { String paramDef = Float.toString(def); String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet .getParameter(key) : paramDef; displayDebugParameterValue(key, paramStr); return parseFloat(paramStr, def); } /** {@inheritDoc} */ @Override public long getParameter(String key, long def) { String paramDef = Long.toString(def); String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet .getParameter(key) : paramDef; displayDebugParameterValue(key, paramStr); return parseLong(paramStr, def); }// getParameter(int) /** {@inheritDoc} */ @Override public boolean getParameter(String key, boolean def) { String paramDef = (def ? "true" : "false"); String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet .getParameter(key) : paramDef; displayDebugParameterValue(key, paramStr); return parseBoolean(paramStr, def); }// getParameter(boolean) /** * Loads cookies, and add them to the specific headers for upload requests. * {@inheritDoc} */ @Override public void readCookieFromNavigator(Vector headers) { String cookie = null; try { // Patch given by Stani: corrects the use of JUpload for // Firefox on Mac. cookie = (String) JSObject.getWindow(this.theApplet).eval( "document.cookie"); } catch (JSException e) { System.out.println("JSException (" + e.getClass() + ": " + e.getMessage() + ") in DefaultUploadPolicy, trying default values."); // If we can't have access to the JS objects, we're in development : // Let's put some 'hard value', to test the juploadContext from the // development tool (mine is eclipse). // felfert: I need different values so let's make that // configurable... cookie = System.getProperty("debug_cookie"); System.out .println(" no navigator found, reading 'debug_cookie' from system properties (" + cookie + ")"); /* * Example of parameter when calling the JVM: * -Ddebug_cookie="Cookie:cpg146_data= * YTo0OntzOjI6IklEIjtzOjMyOiJhZGU3MWIxZmU4OTZjNThhZjQ5N2FiY2ZiNmFlZTUzOCI7czoyOiJhbSI7aToxO3M6NDoibGFuZyI7czo2OiJmcmVuY2giO3M6MzoibGl2IjthOjI6e2k6MDtOO2k6MTtzOjQ6IjE0ODgiO319 * " */ } // The cookies and user-agent will be added to the header sent by the // juploadContext: if (cookie != null) headers.add("Cookie: " + cookie); } /** * Loads userAgent, and add it as a header to the specific headers for * upload requests. {@inheritDoc} */ @Override public void readUserAgentFromNavigator(Vector headers) { String userAgent = null; try { // Patch given by Stani: corrects the use of JUpload for // Firefox on Mac. userAgent = (String) JSObject.getWindow(this.theApplet).eval( "navigator.userAgent"); } catch (JSException e) { System.out.println("JSException (" + e.getClass() + ": " + e.getMessage() + ") in DefaultUploadPolicy, trying default values."); // If we can't have access to the JS objects, we're in development : // Let's put some 'hard value', to test the juploadContext from the // development tool (mine is eclipse). // felfert: I need different values so let's make that // configurable... userAgent = System.getProperty("debug_agent"); System.out .println(" no navigator found, reading 'debug_agent' from system properties (" + userAgent + ")"); /* * Example of parameter when calling the JVM: * -Ddebug_agent="userAgent: Mozilla/5.0 (Windows; U; Windows NT * 5.0; fr; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3" */ } // The user-agent will be added to the header sent by the // juploadContext: if (userAgent != null) headers.add("User-Agent: " + userAgent); } /** * @return The current cursor * @see JUploadContext#setCursor(Cursor) */ @Override public Cursor getCursor() { return this.theApplet.getCursor(); } /** @see JUploadContext#setCursor(Cursor) */ @Override public Cursor setCursor(Cursor cursor) { Cursor previousCursor = this.theApplet.getCursor(); this.theApplet.setCursor(cursor); return previousCursor; } /** {@inheritDoc} */ @Override public void showStatus(String status) { this.getUploadPanel().getStatusLabel().setText(status); } /** * @see JUploadContext#displayURL(String, boolean) */ @Override public void displayURL(String url, boolean success) { try { if (url.toLowerCase().startsWith("javascript:")) { // A JavaScript expression was specified. Execute it. String expr = url.substring(11); // Replacement of %msg%. Will do something only if the %msg% // string exists in expr. expr = expr.replaceAll("%msg%", Matcher .quoteReplacement(jsString(getUploadPolicy() .getLastResponseMessage()))); // Replacement of %body%. Will do something only if the // %body% string exists in expr. expr = expr.replaceAll("%body%", Matcher .quoteReplacement(jsString(getUploadPolicy() .getLastResponseBody()))); // Replacement of %success%. Will do something only if the // %success% string exists in expr. expr = expr.replaceAll("%success%", Matcher .quoteReplacement((success) ? "true" : "false")); displayDebug("Calling javascript expression: " + expr, 80); JSObject.getWindow(this.theApplet).eval(expr); } else if (success) { // This is not a javascript URL: we change the current page // only if no error occurred. String target = getUploadPolicy().getAfterUploadTarget(); if (getUploadPolicy().getDebugLevel() >= 100) { getUploadPolicy().alertStr( "No switch to getAfterUploadURL, because debug level is " + getUploadPolicy().getDebugLevel() + " (>=100)"); } else { // Let's change the current URL to edit names and // comments, for the selected album. Ok, let's go and // add names and comments to the newly updated pictures. this.theApplet.getAppletContext().showDocument( new URL(url), (null == target) ? "_self" : target); } } } catch (Exception ee) { // Oops, no navigator. We are probably in debug mode, within // eclipse for instance. try { getUploadPolicy().displayErr(ee); } catch (JUploadException e) { // Can't use standard JUpload log mode... ee.printStackTrace(); } } } /** * Generates a valid URL, from a String. The generation may add the * documentBase of the applet. * * @param url * A url. Can be a path relative to the current one. * @return The normalized URL * @throws JUploadException */ @Override public String normalizeURL(String url) throws JUploadException { if (null == url || url.length() == 0) return this.theApplet.getDocumentBase().toString(); URI uri = null; try { uri = new URI(url); if (null == uri.getScheme()) uri = this.theApplet.getDocumentBase().toURI().resolve(url); if (!uri.getScheme().equals("http") && !uri.getScheme().equals("https") && !uri.getScheme().equals("ftp")) { throw new JUploadException("URI scheme " + uri.getScheme() + " not supported."); } } catch (URISyntaxException e) { throw new JUploadException(e); } return uri.toString(); } /** * Generate a js String, that can be written in a javascript expression. * It's up to the caller to put the starting and ending quotes. The double * quotes are replaced by simple quotes (to let simple quotes unchanged, as * it may be used in common language). Thus, start and end of JS string * should be with double quotes, when using the return of this function. * * @param s * @return The transformed string, that can be written in the output, into a * javascript string. It doesn't contain the starting and ending * double quotes. */ public String jsString(String s) { String dollarReplacement = Matcher.quoteReplacement("\\$"); String singleQuoteReplacement = Matcher.quoteReplacement("\\'"); String linefeedReplacement = Matcher.quoteReplacement("\\n"); if (s == null || s.equals("")) { return ""; } else { s = s.replaceAll("\\$", dollarReplacement); s = s.replaceAll("\"", "'"); s = s.replaceAll("'", singleQuoteReplacement); s = s.replaceAll("\n", linefeedReplacement); s = s.replaceAll("\r", ""); return s; } } }