001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: https://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: https://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.workplace.administration; 029 030import org.opencms.file.CmsResource; 031import org.opencms.jsp.CmsJspActionElement; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsIllegalArgumentException; 034import org.opencms.main.OpenCms; 035import org.opencms.util.CmsRfsException; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.workplace.CmsDialog; 038import org.opencms.workplace.CmsWorkplaceSettings; 039 040import java.io.File; 041import java.io.FileNotFoundException; 042import java.io.FileOutputStream; 043import java.io.IOException; 044import java.io.OutputStream; 045import java.util.Iterator; 046 047import org.apache.commons.fileupload2.core.DiskFileItem; 048 049import jakarta.servlet.ServletException; 050import jakarta.servlet.http.HttpServletRequest; 051import jakarta.servlet.http.HttpServletResponse; 052import jakarta.servlet.jsp.JspException; 053import jakarta.servlet.jsp.JspWriter; 054import jakarta.servlet.jsp.PageContext; 055 056/** 057 * Abstract class to upload a zip file containing VFS resources with HTTP upload.<p> 058 * 059 * @since 6.0.0 060 */ 061public abstract class A_CmsImportFromHttp extends CmsDialog { 062 063 /** The dialog type. */ 064 public static final String DIALOG_TYPE = "ImportHttp"; 065 066 /** Import file request parameter. */ 067 public static final String PARAM_IMPORTFILE = "importfile"; 068 069 /** The exception thrown if an error occurs. */ 070 private CmsException m_exception; 071 072 /** The import file name that is uploaded. */ 073 private String m_paramImportfile; 074 075 /** 076 * Public constructor with JSP action element.<p> 077 * 078 * @param jsp an initialized JSP action element 079 */ 080 public A_CmsImportFromHttp(CmsJspActionElement jsp) { 081 082 super(jsp); 083 } 084 085 /** 086 * Public constructor with JSP variables.<p> 087 * 088 * @param context the JSP page context 089 * @param req the JSP request 090 * @param res the JSP response 091 */ 092 public A_CmsImportFromHttp(PageContext context, HttpServletRequest req, HttpServletResponse res) { 093 094 this(new CmsJspActionElement(context, req, res)); 095 } 096 097 /** 098 * Performs the import operation after "OK" has been pressed.<p> 099 * 100 * @throws IOException in case of errors forwarding to the required result page 101 * @throws ServletException in case of errors forwarding to the required result page 102 */ 103 public abstract void actionCommit() throws IOException, ServletException; 104 105 /** 106 * Performs the dialog actions depending on the initialized action and displays the dialog form.<p> 107 * 108 * @throws JspException if dialog actions fail 109 * @throws IOException if writing to the JSP out fails, or in case of errors forwarding to the required result page 110 * @throws ServletException in case of errors forwarding to the required result page 111 */ 112 public void displayDialog() throws IOException, JspException, ServletException { 113 114 switch (getAction()) { 115 116 case ACTION_CANCEL: 117 // ACTION: cancel button pressed 118 actionCloseDialog(); 119 break; 120 121 case ACTION_OK: 122 // ACTION: ok button pressed 123 setParamAction(DIALOG_OK); 124 actionCommit(); 125 if (getException() == null) { 126 // file successfully copied to server 127 break; 128 } 129 130 //$FALL-THROUGH$ 131 case ACTION_DEFAULT: 132 default: 133 // ACTION: show dialog (default) 134 setParamAction(DIALOG_OK); 135 JspWriter out = getJsp().getJspContext().getOut(); 136 out.print(defaultActionHtml()); 137 } 138 } 139 140 /** 141 * Gets the return uri for this dialog.<p> 142 * 143 * @return return uri for this dialog 144 */ 145 public abstract String getDialogReturnUri(); 146 147 /** 148 * Gets the localized import message text for the input form.<p> 149 * 150 * @return localized import message text for the input form 151 */ 152 public abstract String getImportMessage(); 153 154 /** 155 * Returns the import file name that is uploaded.<p> 156 * 157 * @return the import file name that is uploaded 158 */ 159 public String getParamImportfile() { 160 161 return m_paramImportfile; 162 } 163 164 /** 165 * Gets the localized start text for the input form.<p> 166 * 167 * @return localized start text for the input form 168 */ 169 public abstract String getStarttext(); 170 171 /** 172 * Sets the import file name that is uploaded.<p> 173 * 174 * @param importfile the import file name that is uploaded 175 */ 176 public void setParamImportfile(String importfile) { 177 178 m_paramImportfile = importfile; 179 } 180 181 /** 182 * Gets a database import file from the client and copies it to the server.<p> 183 * 184 * @param destination the destination of the file on the server 185 * 186 * @return the name of the file or null if something went wrong when importing the file 187 * 188 * @throws CmsIllegalArgumentException if the specified file name is invalid 189 * @throws CmsRfsException if generating folders or files on the server fails 190 */ 191 protected String copyFileToServer(String destination) throws CmsIllegalArgumentException, CmsRfsException { 192 193 // get the file item from the multipart request 194 Iterator<DiskFileItem> i = getMultiPartFileItems().iterator(); 195 DiskFileItem fi = null; 196 while (i.hasNext()) { 197 fi = i.next(); 198 if (fi.getName() != null) { 199 // found the file object, leave iteration 200 break; 201 } else { 202 // this is no file object, check next item 203 continue; 204 } 205 } 206 207 String fileName = null; 208 209 if ((fi != null) && CmsStringUtil.isNotEmptyOrWhitespaceOnly(fi.getName())) { 210 // file name has been specified, upload the file 211 fileName = fi.getName(); 212 byte[] content = null; 213 try { 214 content = fi.get(); 215 fi.delete(); 216 } catch (IOException e) { 217 throw new CmsRfsException(Messages.get().container(Messages.ERR_FILE_NOT_WRITTEN_0, e)); 218 } 219 // get the file name without folder information 220 fileName = CmsResource.getName(fileName.replace('\\', '/')); 221 // first create the folder if it does not exist 222 File discFolder = new File( 223 OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf( 224 OpenCms.getSystemInfo().getPackagesRfsPath() + File.separator)); 225 if (!discFolder.exists()) { 226 if (!discFolder.mkdir()) { 227 throw new CmsRfsException(Messages.get().container(Messages.ERR_FOLDER_NOT_CREATED_0)); 228 } 229 } 230 // write the file into the packages folder of the OpenCms server 231 File discFile = new File( 232 OpenCms.getSystemInfo().getAbsoluteRfsPathRelativeToWebInf(destination + File.separator + fileName)); 233 try { 234 // write the new file to disk 235 OutputStream s = new FileOutputStream(discFile); 236 s.write(content); 237 s.close(); 238 } catch (FileNotFoundException e) { 239 throw new CmsRfsException(Messages.get().container(Messages.ERR_FILE_NOT_FOUND_1, fileName, e)); 240 } catch (IOException e) { 241 throw new CmsRfsException(Messages.get().container(Messages.ERR_FILE_NOT_WRITTEN_0, e)); 242 } 243 } else { 244 // no file name has been specified, throw exception 245 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_FILE_NOT_SPECIFIED_0)); 246 } 247 // set the request parameter to the name of the import file 248 setParamImportfile(fileName); 249 return fileName; 250 } 251 252 /** 253 * Creates the HTML for the error message if validation errors were found.<p> 254 * 255 * @return the HTML for the error message if validation errors were found 256 */ 257 protected String createDialogErrorMessage() { 258 259 if (getException() != null) { 260 StringBuffer result = new StringBuffer(8); 261 result.append(dialogBlockStart("")); 262 result.append("<table border=\"0\">\n"); 263 result.append("<tr><td><img src=\""); 264 result.append(getSkinUri()).append("commons/"); 265 result.append("error.png"); 266 result.append("\" border=\"0\" alt=\"\"></td><td class=\"xmlTdError maxwidth\">"); 267 Throwable t = getException(); 268 while (t != null) { 269 result.append(t.getLocalizedMessage()); 270 t = t.getCause(); 271 if (t != null) { 272 result.append("<br>"); 273 } 274 } 275 result.append("</table>\n"); 276 result.append(dialogBlockEnd()); 277 return result.toString(); 278 } 279 return ""; 280 } 281 282 /** 283 * Returns the HTML to build the input form of the upload dialog.<p> 284 * 285 * @return the HTML to build the input form of the upload dialog 286 */ 287 protected String defaultActionHtml() { 288 289 StringBuffer result = new StringBuffer(32); 290 291 result.append(htmlStart()); 292 result.append(bodyStart(null)); 293 result.append(dialogStart()); 294 result.append(dialogContentStart("")); 295 result.append("<form name=\"main\" class=\"nomargin\" action=\""); 296 result.append(getJsp().link(getDialogReturnUri())); 297 result.append("\" method=\"post\" onsubmit=\"submitAction('"); 298 result.append(DIALOG_OK); 299 result.append("', null, 'main');\" enctype=\"multipart/form-data\">\n"); 300 result.append(paramsAsHidden()); 301 if (getParamFramename() == null) { 302 result.append("<input type=\"hidden\" name=\""); 303 result.append(PARAM_FRAMENAME); 304 result.append("\" value=\"\">"); 305 } 306 result.append(createDialogErrorMessage()); 307 result.append(dialogBlockStart(getStarttext())); 308 result.append("<table border=\"0\" width=\"100%\">\n"); 309 result.append("<tr>\n\t<td style=\"white-space: nowrap;\" unselectable=\"on\">"); 310 result.append(getImportMessage()); 311 result.append(":</td>\n"); 312 result.append("\t<td class=\"maxwidth\">"); 313 result.append("<input type=\"file\" name=\""); 314 result.append(PARAM_IMPORTFILE); 315 result.append("\" class=\"maxwidth\" accept=\"application/zip\">"); 316 result.append("</td>\n</tr>"); 317 result.append(getAdditionalParameters()); 318 result.append("</table>\n"); 319 result.append(dialogBlockEnd()); 320 321 result.append(dialogContentEnd()); 322 result.append(dialogButtonsOkCancel()); 323 result.append("</form>\n"); 324 result.append(dialogEnd()); 325 result.append(bodyEnd()); 326 result.append(htmlEnd()); 327 return result.toString(); 328 } 329 330 /** 331 * Html code for the additional parameters.<p> 332 * 333 * @return html code 334 */ 335 protected String getAdditionalParameters() { 336 337 // do nothing 338 return ""; 339 } 340 341 /** 342 * Returns the dialog exception.<p> 343 * 344 * @return the dialog exception 345 */ 346 protected CmsException getException() { 347 348 return m_exception; 349 } 350 351 /** 352 * @see org.opencms.workplace.CmsWorkplace#initMessages() 353 */ 354 @Override 355 protected abstract void initMessages(); 356 357 /** 358 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, jakarta.servlet.http.HttpServletRequest) 359 */ 360 @Override 361 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 362 363 // set the dialog type 364 setParamDialogtype(getClass().getName()); 365 366 // fill the parameter values in the get/set methods 367 fillParamValues(request); 368 369 // set the action for the JSP switch 370 if (DIALOG_OK.equals(getParamAction())) { 371 // ok button pressed 372 setAction(ACTION_OK); 373 } else if (DIALOG_CANCEL.equals(getParamAction())) { 374 // cancel button pressed 375 setAction(ACTION_CANCEL); 376 } else { 377 // first dialog call, set the default action 378 setAction(ACTION_DEFAULT); 379 } 380 } 381 382 /** 383 * Sets the dialog exception.<p> 384 * 385 * @param exception the dialog exception 386 */ 387 protected void setException(CmsException exception) { 388 389 m_exception = exception; 390 } 391}