1 // 2 // $Id: CoppermineUploadPolicy.java 143 2007-05-14 02:07:27 +0000 (lun., 14 mai 3 // 2007) felfert $ 4 // 5 // jupload - A file upload applet. 6 // Copyright 2007 The JUpload Team 7 // 8 // Created: 2006-05-07 9 // Creator: etienne_sf 10 // Last modified: $Date: 2010-07-08 13:57:30 +0200 (jeu., 08 juil. 2010) $ 11 // 12 // This program is free software; you can redistribute it and/or modify it under 13 // the terms of the GNU General Public License as published by the Free Software 14 // Foundation; either version 2 of the License, or (at your option) any later 15 // version. This program is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 17 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 18 // details. You should have received a copy of the GNU General Public License 19 // along with this program; if not, write to the Free Software Foundation, Inc., 20 // 675 Mass Ave, Cambridge, MA 02139, USA. 21 22 package wjhk.jupload2.policies; 23 24 import java.util.regex.Matcher; 25 import java.util.regex.Pattern; 26 27 import wjhk.jupload2.context.JUploadContext; 28 import wjhk.jupload2.exception.JUploadException; 29 import wjhk.jupload2.exception.JUploadExceptionUploadFailed; 30 import wjhk.jupload2.exception.JUploadExceptionUploadFailedSuccessNotFound; 31 import wjhk.jupload2.filedata.FileData; 32 import wjhk.jupload2.filedata.PictureFileData; 33 34 // TODO cookies handling: desc to be mve to UploadPolicy presentation. 35 /** 36 * Specific UploadPolicy for the coppermine picture gallery. It is based on the 37 * PictureUploadPolicy, and some specific part to add the uploaded pictures to a 38 * coppermine existing album. <BR> 39 * Specific features for this policy are: 40 * <UL> 41 * <LI>Album handling : the setProperty("albumId", n) can be called from 42 * javascript, when the user selects another album (with n is the numeric id for 43 * the selected album). This needs that the MAYSCRIPT HTML parameter is set, in 44 * the APPLET tag (see the example below). The upload can not start if the user 45 * didn't first select an album. 46 * <LI>If an error occurs, the applet asks the user if he wants to send a mail 47 * to the webmaster. If he answered yes, the full debug output is submitted to 48 * the URL pointed by urlToSendErrorTo. This URL should send a mail to the 49 * manager of the Coppermine galery. 50 * </UL> 51 * <A NAME="example1"> <H3>Call of the applet from a php script in coppermine</H3> 52 * </A> You'll find below an example of how to put the applet into a PHP page: <BR> 53 * <XMP> <?php $URL = $CONFIG['site_url'] . 'xp_publish.php'; $lang = 54 * $lang_translation_info['lang_country_code']; $max_upl_width_height = 55 * $CONFIG['max_upl_width_height']; ?> <APPLET NAME="JUpload" 56 * CODE="wjhk.jupload2.JUploadApplet" ARCHIVE="plugins/jupload/wjhk.jupload.jar" 57 * <!-- Applet display size, on the navigator page --> WIDTH="500" HEIGHT="700" 58 * <!-- The applet call some javascript function, so we must allow it : --> 59 * MAYSCRIPT > <!-- First, mandatory parameters --> <PARAM NAME="postURL" 60 * VALUE="$URL"> <PARAM NAME="uploadPolicy" VALUE="CoppermineUploadPolicy"> <!-- 61 * Then, optional parameters --> <PARAM NAME="lang" VALUE="$lang"> <PARAM 62 * NAME="maxPicHeight" VALUE="$max_upl_width_height"> <PARAM NAME="maxPicWidth" 63 * VALUE="$max_upl_width_height"> <PARAM NAME="debugLevel" VALUE="0"> Java 1.4 64 * or higher plugin required. </APPLET> </XMP> <A NAME="example1"> <H3>Example 65 * 2: albumId set by a javascript call.</H3> </A> <XMP> <script 66 * language="javascript" type="text/javascript"> function onAlbumChange() { if 67 * (document.form_album.album_id.selectedIndex >= 0) { 68 * document.applets['JUpload'].setProperty('albumId', 69 * document.form_album.album_id.value); document.form_album.album_name.value = 70 * document 71 * .form_album.album_id.options[document.form_album.album_id.selectedIndex 72 * ].text; document.form_album.album_description.value = 73 * description[document.form_album.album_id.value]; } else { 74 * document.JUpload.setProperty('albumId', ''); 75 * document.form_album.album_name.value = ''; 76 * document.form_album.album_description.value = ''; } } </script> </XMP> 77 * 78 * @author etienne_sf 79 * @version $Revision: 1367 $ 80 */ 81 public class CoppermineUploadPolicy extends PictureUploadPolicy { 82 83 /** 84 * The coppermine's album id where picture must be uploaded. 85 */ 86 private int albumId; 87 88 /** 89 * The number of pictures to download in the current upload. This number is 90 * stored in the {@link #beforeUpload()} method, which is called at the 91 * beginning of each upload. 92 */ 93 private int nbPictureInUpload = 0; 94 95 /** 96 * @param juploadContext 97 * Identifier for the current applet. It's necessary, to read 98 * information from the navigator. 99 * @throws JUploadException 100 */ 101 public CoppermineUploadPolicy(JUploadContext juploadContext) 102 throws JUploadException { 103 // Let's call our mother ! :-) 104 super(juploadContext); 105 106 // Let's read the albumId from the applet parameter. It can be unset, 107 // but the user must then choose 108 // an album before upload. 109 this.albumId = getContext().getParameter(PROP_ALBUM_ID, 110 DEFAULT_ALBUM_ID); 111 } 112 113 /** 114 * @see wjhk.jupload2.policies.UploadPolicy#onFileSelected(wjhk.jupload2.filedata.FileData) 115 */ 116 @Override 117 public void onFileSelected(FileData fileData) { 118 if (fileData != null && fileData instanceof PictureFileData) { 119 // The selected file is a picture, we let PictureUploadPolicy manage 120 // it. 121 super.onFileSelected(fileData); 122 } else { 123 // he selected file is not a picture. We simulate the fact that no 124 // more picture is selected, so that the preview picture is cleared. 125 super.onFileSelected(null); 126 } 127 } 128 129 /** 130 * This method only handles the <I>albumId</I> parameter, which is the only 131 * applet parameter that is specific to this class. The super.setProperty 132 * method is called for other properties. 133 * 134 * @see wjhk.jupload2.policies.UploadPolicy#setProperty(java.lang.String, 135 * java.lang.String) 136 */ 137 @Override 138 public void setProperty(String prop, String value) throws JUploadException { 139 displayDebug("[CoppermineUploadPolicy] Call of setProperty: " + prop 140 + " => " + value, 30); 141 142 // Check if it's a local property. 143 if (prop.equals(PROP_ALBUM_ID)) { 144 this.albumId = getContext().parseInt(value, 0); 145 displayDebug("Post URL (modified in CoppermineUploadPolicy) = " 146 + getPostURL(), 10); 147 } else { 148 // Otherwise, transmission to the mother class. 149 super.setProperty(prop, value); 150 } 151 } 152 153 /** 154 * @see wjhk.jupload2.policies.UploadPolicy#getPostURL() 155 */ 156 @Override 157 public String getPostURL() { 158 // Within the coppermine PHP script, that contains the call to this 159 // applet, the postURL given contains the full URL, without the album 160 // id. So we ask for this postURL, and just concatenate the albumId on 161 // the fly. 162 String postURL = super.getPostURL(); 163 return postURL + (postURL.contains("?") ? "&" : "?") + "album=" 164 + this.albumId; 165 } 166 167 /** 168 * This method checks that an album id has been given, and then stores the 169 * number of files that are to be uploaded, before upload, then call its 170 * superclass. This number is then used to display to the user the list of 171 * pictures he just uploaded. 172 * 173 * @see wjhk.jupload2.policies.UploadPolicy#beforeUpload() 174 */ 175 @Override 176 public boolean beforeUpload() { 177 if (this.albumId <= 0) { 178 alert("chooseAlbumFirst"); 179 return false; 180 } 181 182 // We note the number of files to upload. 183 this.nbPictureInUpload = getContext().getUploadPanel().getFilePanel() 184 .getFilesLength(); 185 186 // Default : Let's ask the mother. 187 return super.beforeUpload(); 188 } 189 190 /** @see wjhk.jupload2.policies.UploadPolicy#afterUpload(Exception, String) */ 191 @Override 192 public void afterUpload(Exception e, String serverOutput) 193 throws JUploadException { 194 int nbPictureAfterUpload = getContext().getUploadPanel().getFilePanel() 195 .getFilesLength(); 196 if (nbPictureAfterUpload > this.nbPictureInUpload) { 197 displayErr("CoppermineUploadPolicy.afterUpload: The number of uploaded files is negative! (" 198 + (this.nbPictureInUpload - nbPictureAfterUpload) + ")"); 199 } else if (nbPictureAfterUpload == this.nbPictureInUpload) { 200 displayWarn("CoppermineUploadPolicy.afterUpload: No file were uploaded! (" 201 + (nbPictureAfterUpload - this.nbPictureInUpload) + ")"); 202 } else if (getDebugLevel() >= 100) { 203 alertStr("No switch to property page, because debug level is " 204 + getDebugLevel() + " (>=100)"); 205 } else if (e == null) { 206 // Let's display an alert box, to explain what to do to the 207 // user: he will be redirected to the coppermine page that 208 // allow him to associate names and comments to the uploaded 209 // pictures. 210 alert("coppermineUploadOk"); 211 212 // Let's change the afterUploadURL value, so we can call the 213 // standard afterUpload method (DefaultUploadPolicy). 214 215 // Since JUpload 4.2.0, CPG 1.5 upload is done againts the 216 // /upload.php script, to use 217 // the Coppermine upload API ofr plugins. 218 String postURL = getPostURL(); 219 if (postURL.contains("/upload.php?")) { 220 setAfterUploadURL(postURL.substring(0, getPostURL() 221 .lastIndexOf("/upload.php?")) 222 + "/index.php?file=jupload/jupload&action=edit_uploaded_pics&album=" 223 + this.albumId 224 + "&nb_pictures=" 225 + (this.nbPictureInUpload - nbPictureAfterUpload)); 226 } else { 227 setAfterUploadURL(postURL.substring(0, getPostURL() 228 .lastIndexOf('/')) 229 + "/jupload&action=edit_uploaded_pics&album=" 230 + this.albumId 231 + "&nb_pictures=" 232 + (this.nbPictureInUpload - nbPictureAfterUpload)); 233 } // ... and call the standard behavior. 234 super.afterUpload(e, serverOutput); 235 } 236 } 237 238 /** @see DefaultUploadPolicy#checkUploadSuccess(int, String, String) */ 239 public boolean checkUploadSuccess(int status, String msg, String body) 240 throws JUploadException { 241 try { 242 return super.checkUploadSuccess(status, msg, body); 243 } catch (JUploadExceptionUploadFailedSuccessNotFound e) { 244 // We got here, if the standard return analysis did not find any 245 // error or success status. Let's try a 'Coppermine specific' 246 // analysis now. 247 Pattern patternMessage = Pattern 248 .compile(".*cpg_user_message\">(.*)</span>"); 249 Matcher matcherMessage; 250 String line; 251 Pattern pMultiline = Pattern.compile("[\\r\\n]", Pattern.MULTILINE); 252 String[] lines = pMultiline.split(body); 253 StringBuffer sbBodyWithUniformCRLF = new StringBuffer(body.length()); 254 for (int i = 0; i < lines.length; i += 1) { 255 line = lines[i]; 256 sbBodyWithUniformCRLF.append(line).append("\r\n"); 257 258 // FIXME some empty lines are given by the server 259 // Let's remove the empty line: with the p pattern, a multiline 260 // is generated each time a \r\n is received, that is: for each 261 // line. 262 if (line == null || line.equals("")) { 263 // An empty line. Let's go the next line. 264 continue; 265 } 266 267 // Is it 'message line' ? 268 matcherMessage = patternMessage.matcher(line); 269 if (matcherMessage.matches()) { 270 String errmsg = "An error occurs during upload (but the applet couldn't find the error message)"; 271 if (matcherMessage.groupCount() > 0) { 272 if (!matcherMessage.group(1).equals("")) { 273 // Let's do a (very simple) formatting: one line to 274 // 100 characters 275 errmsg = formatMessage(matcherMessage.group(1)); 276 } 277 } 278 this.lastResponseMessage = errmsg; 279 throw new JUploadExceptionUploadFailed(errmsg); 280 }// if(matcherMessage.matches()) 281 }// while(st.hasMoreTokens()) 282 283 // We didn't find any precise message. Let's transmit the default 284 // one. 285 throw e; 286 } 287 } 288 289 /** @see DefaultUploadPolicy#displayParameterStatus() */ 290 @Override 291 public void displayParameterStatus() { 292 super.displayParameterStatus(); 293 294 displayDebug("======= Parameters managed by CoppermineUploadPolicy", 30); 295 displayDebug(PROP_ALBUM_ID + " : " + this.albumId, 30); 296 displayDebug("", 30); 297 } 298 299 }