Coverage Report - wjhk.jupload2.context.JUploadContextApplet
 
Classes in this File Line Coverage Branch Coverage Complexity
JUploadContextApplet
28 %
41/146
33 %
18/54
3,278
 
 1  
 //
 2  
 // $Id: JUploadApplet.java 750 2009-05-06 14:36:50Z etienne_sf $
 3  
 //
 4  
 // jupload - A file upload applet.
 5  
 // Copyright 2007 The JUpload Team
 6  
 //
 7  
 // Created: ?
 8  
 // Creator: William JinHua Kwong
 9  
 // Last modified: $Date: 2009-05-06 16:36:50 +0200 (mer., 06 mai 2009) $
 10  
 //
 11  
 // This program is free software; you can redistribute it and/or modify it under
 12  
 // the terms of the GNU General Public License as published by the Free Software
 13  
 // Foundation; either version 2 of the License, or (at your option) any later
 14  
 // version. This program is distributed in the hope that it will be useful, but
 15  
 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 16  
 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 17  
 // details. You should have received a copy of the GNU General Public License
 18  
 // along with this program; if not, write to the Free Software Foundation, Inc.,
 19  
 // 675 Mass Ave, Cambridge, MA 02139, USA.
 20  
 
 21  
 package wjhk.jupload2.context;
 22  
 
 23  
 import java.awt.Container;
 24  
 import java.awt.Cursor;
 25  
 import java.awt.Frame;
 26  
 import java.io.File;
 27  
 import java.io.IOException;
 28  
 import java.net.URI;
 29  
 import java.net.URISyntaxException;
 30  
 import java.net.URL;
 31  
 import java.util.Vector;
 32  
 import java.util.regex.Matcher;
 33  
 
 34  
 import javax.swing.JApplet;
 35  
 import javax.swing.JFileChooser;
 36  
 import javax.swing.JOptionPane;
 37  
 
 38  
 import netscape.javascript.JSException;
 39  
 import netscape.javascript.JSObject;
 40  
 import wjhk.jupload2.exception.JUploadException;
 41  
 import wjhk.jupload2.gui.filepanel.FilePanel.FileListViewMode;
 42  
 
 43  
 /**
 44  
  * Implementation of the Jupload Context, for an applet. One such context is created at run time.
 45  
  * 
 46  
  * @see DefaultJUploadContext
 47  
  * @author etienne_sf
 48  
  * @version $Revision: 750 $
 49  
  */
 50  
 @SuppressWarnings("restriction")
 51  
 public class JUploadContextApplet extends DefaultJUploadContext {
 52  
 
 53  
     /**
 54  
      * The current applet. All applet parameters are reading by using this attribute.
 55  
      */
 56  7
     JApplet theApplet = null;
 57  
 
 58  
     /**
 59  
      * The default constructor.
 60  
      * 
 61  
      * @param theApplet The applet is mandatory, to read the applet parameters.
 62  
      */
 63  7
     public JUploadContextApplet(JApplet theApplet) {
 64  7
         if (theApplet == null) {
 65  0
             throw new IllegalArgumentException("theApplet may not be null");
 66  
         }
 67  7
         this.theApplet = theApplet;
 68  
 
 69  
         // The applet must be signed !
 70  7
         checkAppletIsSigned();
 71  
 
 72  
         // Let's initialize the DefaultJUploadContext.
 73  7
         init(findParentFrame(theApplet), theApplet);
 74  7
     }
 75  
 
 76  
     /**
 77  
      * This method checks that the applet is signed. To do this, it just check that the current folder is readable, and
 78  
      * that the applet can create temporary files. Should be enough.<BR>
 79  
      * If anyone has a better idea ... I'll be hapy to listen to it!
 80  
      */
 81  
     void checkAppletIsSigned() {
 82  
 
 83  
         // Let's be optimistic! ;-)
 84  0
         java.lang.SecurityException ex = null;
 85  
         try {
 86  
             // I found no way to directly get the current directory (access to
 87  
             // user.xxx system properties is prohibited from within applets)
 88  0
             JFileChooser fc = new JFileChooser();
 89  0
             File currentDir = fc.getCurrentDirectory();
 90  0
             if (!currentDir.canRead()) {
 91  0
                 ex = new java.lang.SecurityException("The applet must be signed (can't write in '"
 92  0
                         + currentDir.getAbsolutePath() + "')");
 93  
             }
 94  
 
 95  
             // Let's now check that the applet may create a temporary file. May
 96  
             // be necessary for further processing, and for logging.
 97  
             try {
 98  0
                 File tmpTestFile = File.createTempFile("jupload", "test");
 99  0
                 tmpTestFile.delete();
 100  0
             } catch (IOException ioe) {
 101  0
                 String msg = ioe.getClass().getName()
 102  
                         + ": Can't create temporary file (the applet is perhaps not signed (original error message: "
 103  0
                         + ioe.getMessage() + ")";
 104  0
                 System.out.println(msg);
 105  0
                 ex = new java.lang.SecurityException(msg, ioe);
 106  0
                 ioe.printStackTrace();
 107  0
             }
 108  0
         } catch (java.lang.SecurityException e) {
 109  0
             String msg = "The applet must be signed (original error message: " + e.getMessage() + ")";
 110  0
             System.out.println(msg);
 111  0
             ex = new java.lang.SecurityException(msg, e);
 112  0
         }
 113  
 
 114  0
         if (ex != null) {
 115  0
             String msg = ex.getClass().getName() + " - " + ex.getMessage();
 116  0
             JOptionPane.showMessageDialog(null, msg, "Alert", JOptionPane.ERROR_MESSAGE);
 117  0
             System.out.println(msg);
 118  0
             ex.printStackTrace();
 119  
 
 120  0
             throw ex;
 121  
         }
 122  0
     }
 123  
 
 124  
     /**
 125  
      * Find the JFrame which contains the applet
 126  
      * 
 127  
      * @param theApplet
 128  
      * @return
 129  
      */
 130  
     private Frame findParentFrame(JApplet theApplet) {
 131  7
         Container c = theApplet;
 132  14
         while (c != null) {
 133  7
             if (c instanceof Frame)
 134  0
                 return (Frame) c;
 135  
 
 136  7
             c = c.getParent();
 137  
         }
 138  7
         return (Frame) null;
 139  
     }
 140  
 
 141  
     /** {@inheritDoc} */
 142  
     @Override
 143  
     public JApplet getApplet() {
 144  0
         return this.theApplet;
 145  
     }
 146  
 
 147  
     /** {@inheritDoc} */
 148  
     @Override
 149  
     public String getParameter(String key, String def) {
 150  2
         String paramStr = (this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : def);
 151  2
         displayDebugParameterValue(key, paramStr);
 152  2
         return paramStr;
 153  
     }
 154  
 
 155  
     /** {@inheritDoc} */
 156  
     @Override
 157  
     public int getParameter(String key, int def) {
 158  2
         String paramDef = Integer.toString(def);
 159  2
         String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : paramDef;
 160  2
         displayDebugParameterValue(key, paramStr);
 161  2
         return parseInt(paramStr, def);
 162  
     }
 163  
 
 164  
     /** {@inheritDoc} */
 165  
     @Override
 166  
     public float getParameter(String key, float def) {
 167  2
         String paramDef = Float.toString(def);
 168  2
         String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : paramDef;
 169  2
         displayDebugParameterValue(key, paramStr);
 170  2
         return parseFloat(paramStr, def);
 171  
     }
 172  
 
 173  
     /** {@inheritDoc} */
 174  
     @Override
 175  
     public long getParameter(String key, long def) {
 176  2
         String paramDef = Long.toString(def);
 177  2
         String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : paramDef;
 178  2
         displayDebugParameterValue(key, paramStr);
 179  2
         return parseLong(paramStr, def);
 180  
     }// getParameter(int)
 181  
 
 182  
     /** {@inheritDoc} */
 183  
     @Override
 184  
     public boolean getParameter(String key, boolean def) {
 185  3
         String paramDef = (def ? "true" : "false");
 186  3
         String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : paramDef;
 187  3
         displayDebugParameterValue(key, paramStr);
 188  3
         return parseBoolean(paramStr, def);
 189  
     }// getParameter(boolean)
 190  
 
 191  
     /** {@inheritDoc} */
 192  
     public FileListViewMode getParameter(String key, FileListViewMode def) {
 193  0
         String paramDef = def.toString();
 194  0
         String paramStr = this.theApplet.getParameter(key) != null ? this.theApplet.getParameter(key) : paramDef;
 195  0
         displayDebugParameterValue(key, paramStr);
 196  0
         return parseFileListViewMode(paramStr, def);
 197  
     }// getParameter(FileListViewMode)
 198  
 
 199  
     /**
 200  
      * Loads cookies, and add them to the specific headers for upload requests. {@inheritDoc}
 201  
      */
 202  
     @Override
 203  
     public void readCookieFromNavigator(Vector<String> headers) {
 204  0
         String cookie = null;
 205  
 
 206  
         try {
 207  
             // Patch given by Stani: corrects the use of JUpload for
 208  
             // Firefox on Mac.
 209  0
             cookie = (String) JSObject.getWindow(this.theApplet).eval("document.cookie");
 210  0
             uploadPolicy.displayDebug("Cookie read from the navigator: " + cookie, 80);
 211  0
         } catch (JSException e) {
 212  0
             String msg = "JSException (" + e.getClass() + ": " + e.getMessage()
 213  
                     + ") in DefaultUploadPolicy, trying default values.";
 214  0
             System.out.println(msg);
 215  0
             uploadPolicy.displayWarn(msg);
 216  
 
 217  
             // If we can't have access to the JS objects, we're in development :
 218  
             // Let's put some 'hard value', to test the juploadContext from the
 219  
             // development tool (mine is eclipse).
 220  
 
 221  
             // felfert: I need different values so let's make that
 222  
             // configurable...
 223  0
             cookie = System.getProperty("debug_cookie");
 224  
 
 225  0
             msg = "  no navigator found, reading 'debug_cookie' from system properties (" + cookie + ")";
 226  0
             System.out.println(msg);
 227  0
             uploadPolicy.displayDebug(msg, 80);
 228  
             /*
 229  
              * Example of parameter when calling the JVM: -Ddebug_cookie="Cookie:cpg146_data=
 230  
              * YTo0OntzOjI6IklEIjtzOjMyOiJhZGU3MWIxZmU4OTZjNThhZjQ5N2FiY2ZiNmFlZTUzOCI7czoyOiJhbSI7aToxO3M6NDoibGFuZyI7czo2OiJmcmVuY2giO3M6MzoibGl2IjthOjI6e2k6MDtOO2k6MTtzOjQ6IjE0ODgiO319
 231  
              * "
 232  
              */
 233  0
         }
 234  
         // The cookies and user-agent will be added to the header sent by the
 235  
         // juploadContext:
 236  0
         if (cookie != null)
 237  0
             headers.add("Cookie: " + cookie);
 238  0
     }
 239  
 
 240  
     /**
 241  
      * Loads userAgent, and add it as a header to the specific headers for upload requests. {@inheritDoc}
 242  
      */
 243  
     @Override
 244  
     public void readUserAgentFromNavigator(Vector<String> headers) {
 245  0
         String userAgent = null;
 246  
 
 247  
         try {
 248  
             // Patch given by Stani: corrects the use of JUpload for
 249  
             // Firefox on Mac.
 250  0
             userAgent = (String) JSObject.getWindow(this.theApplet).eval("navigator.userAgent");
 251  0
             uploadPolicy.displayDebug("userAgent read from the navigator: " + userAgent, 80);
 252  0
         } catch (JSException e) {
 253  0
             String msg = "JSException (" + e.getClass() + ": " + e.getMessage()
 254  
                     + ") in DefaultUploadPolicy, trying default values.";
 255  0
             System.out.println(msg);
 256  0
             uploadPolicy.displayWarn(msg);
 257  
 
 258  
             // If we can't have access to the JS objects, we're in development :
 259  
             // Let's put some 'hard value', to test the juploadContext from the
 260  
             // development tool (mine is eclipse).
 261  
 
 262  
             // felfert: I need different values so let's make that
 263  
             // configurable...
 264  0
             userAgent = System.getProperty("debug_agent");
 265  0
             msg = "  no navigator found, reading 'debug_agent' from system properties (" + userAgent + ")";
 266  0
             System.out.println(msg);
 267  0
             uploadPolicy.displayDebug(msg, 80);
 268  
             /*
 269  
              * Example of parameter when calling the JVM: -Ddebug_agent="userAgent: Mozilla/5.0 (Windows; U; Windows NT
 270  
              * 5.0; fr; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3"
 271  
              */
 272  0
         }
 273  
         // The user-agent will be added to the header sent by the
 274  
         // juploadContext:
 275  0
         if (userAgent != null)
 276  0
             headers.add("User-Agent: " + userAgent);
 277  
 
 278  0
     }
 279  
 
 280  
     /**
 281  
      * @return The current cursor
 282  
      * @see JUploadContext#setCursor(Cursor)
 283  
      */
 284  
     @Override
 285  
     public Cursor getCursor() {
 286  0
         return this.theApplet.getCursor();
 287  
     }
 288  
 
 289  
     /** @see JUploadContext#setCursor(Cursor) */
 290  
     @Override
 291  
     public Cursor setCursor(Cursor cursor) {
 292  0
         Cursor previousCursor = this.theApplet.getCursor();
 293  0
         this.theApplet.setCursor(cursor);
 294  0
         return previousCursor;
 295  
     }
 296  
 
 297  
     /** {@inheritDoc} */
 298  
     @Override
 299  
     public void showStatus(String status) {
 300  0
         this.getUploadPanel().getStatusLabel().setText(status);
 301  0
     }
 302  
 
 303  
     /**
 304  
      * @see JUploadContext#displayURL(String, boolean)
 305  
      */
 306  
     @Override
 307  
     public void displayURL(String url, boolean success) {
 308  
         try {
 309  0
             if (url.toLowerCase().startsWith("javascript:")) {
 310  
                 // A JavaScript expression was specified. Execute it.
 311  0
                 String expr = url.substring(11);
 312  
 
 313  
                 // Replacement of %msg%. Will do something only if the %msg%
 314  
                 // string exists in expr.
 315  0
                 expr = expr.replaceAll("%msg%",
 316  0
                         Matcher.quoteReplacement(jsString(getUploadPolicy().getLastResponseMessage())));
 317  
 
 318  
                 // Replacement of %body%. Will do something only if the
 319  
                 // %body% string exists in expr.
 320  0
                 expr = expr.replaceAll("%body%",
 321  0
                         Matcher.quoteReplacement(jsString(getUploadPolicy().getLastResponseBody())));
 322  
 
 323  
                 // Replacement of %success%. Will do something only if the
 324  
                 // %success% string exists in expr.
 325  0
                 expr = expr.replaceAll("%success%", Matcher.quoteReplacement((success) ? "true" : "false"));
 326  
 
 327  0
                 displayDebug("Calling javascript expression: " + expr, 80);
 328  0
                 JSObject.getWindow(this.theApplet).eval(expr);
 329  0
             } else if (success) {
 330  
                 // This is not a javascript URL: we change the current page
 331  
                 // only if no error occurred.
 332  0
                 String target = getUploadPolicy().getAfterUploadTarget();
 333  0
                 if (getUploadPolicy().getDebugLevel() >= 100) {
 334  0
                     getUploadPolicy().alertStr(
 335  
                             "No switch to getAfterUploadURL, because debug level is "
 336  0
                                     + getUploadPolicy().getDebugLevel() + " (>=100)");
 337  
                 } else {
 338  
                     // Let's change the current URL to edit names and
 339  
                     // comments, for the selected album. Ok, let's go and
 340  
                     // add names and comments to the newly updated pictures.
 341  0
                     this.theApplet.getAppletContext().showDocument(new URL(url), (null == target) ? "_self" : target);
 342  
                 }
 343  
             }
 344  0
         } catch (Exception ee) {
 345  
             // Oops, no navigator. We are probably in debug mode, within
 346  
             // eclipse for instance.
 347  
             try {
 348  0
                 getUploadPolicy().displayErr(ee);
 349  0
             } catch (JUploadException e) {
 350  
                 // Can't use standard JUpload log mode...
 351  0
                 ee.printStackTrace();
 352  0
             }
 353  0
         }
 354  0
     }
 355  
 
 356  
     /**
 357  
      * Generates a valid URL, from a String. The generation may add the documentBase of the applet.
 358  
      * 
 359  
      * @param url A url. Can be a path relative to the current one.
 360  
      * @return The normalized URL
 361  
      * @throws JUploadException
 362  
      */
 363  
     @Override
 364  
     public String normalizeURL(String url) throws JUploadException {
 365  0
         if (null == url || url.length() == 0)
 366  0
             return this.theApplet.getDocumentBase().toString();
 367  0
         URI uri = null;
 368  
         try {
 369  0
             uri = new URI(url);
 370  0
             if (null == uri.getScheme())
 371  0
                 uri = this.theApplet.getDocumentBase().toURI().resolve(url);
 372  0
             if (!uri.getScheme().equals("http") && !uri.getScheme().equals("https") && !uri.getScheme().equals("ftp")) {
 373  0
                 throw new JUploadException("URI scheme " + uri.getScheme() + " not supported.");
 374  
             }
 375  0
         } catch (URISyntaxException e) {
 376  0
             throw new JUploadException(e);
 377  0
         }
 378  0
         return uri.toString();
 379  
     }
 380  
 
 381  
     /**
 382  
      * Generate a js String, that can be written in a javascript expression. It's up to the caller to put the starting
 383  
      * and ending quotes. The double quotes are replaced by simple quotes (to let simple quotes unchanged, as it may be
 384  
      * used in common language). Thus, start and end of JS string should be with double quotes, when using the return of
 385  
      * this function.
 386  
      * 
 387  
      * @param s
 388  
      * @return The transformed string, that can be written in the output, into a javascript string. It doesn't contain
 389  
      *         the starting and ending double quotes.
 390  
      */
 391  
     public String jsString(String s) {
 392  1
         String dollarReplacement = Matcher.quoteReplacement("\\$");
 393  1
         String singleQuoteReplacement = Matcher.quoteReplacement("\\'");
 394  1
         String linefeedReplacement = Matcher.quoteReplacement("\\n");
 395  
 
 396  1
         if (s == null || s.equals("")) {
 397  0
             return "";
 398  
         } else {
 399  1
             s = s.replaceAll("\\$", dollarReplacement);
 400  1
             s = s.replaceAll("\"", "'");
 401  1
             s = s.replaceAll("'", singleQuoteReplacement);
 402  1
             s = s.replaceAll("\n", linefeedReplacement);
 403  1
             s = s.replaceAll("\r", "");
 404  1
             return s;
 405  
         }
 406  
     }
 407  
 }