1 64 65 package com.jcorporate.expresso.ext.controller; 66 67 import com.jcorporate.expresso.core.controller.Block; 68 import com.jcorporate.expresso.core.controller.ControllerException; 69 import com.jcorporate.expresso.core.controller.ControllerRequest; 70 import com.jcorporate.expresso.core.controller.ControllerResponse; 71 import com.jcorporate.expresso.core.controller.DBController; 72 import com.jcorporate.expresso.core.controller.Output; 73 import com.jcorporate.expresso.core.controller.ServletControllerRequest; 74 import com.jcorporate.expresso.core.controller.State; 75 import com.jcorporate.expresso.core.controller.Transition; 76 import com.jcorporate.expresso.core.db.DBException; 77 import com.jcorporate.expresso.core.dbobj.SecuredDBObject; 78 import com.jcorporate.expresso.core.misc.DateTime; 79 import com.jcorporate.expresso.core.misc.EventHandler; 80 import com.jcorporate.expresso.core.misc.FileUtil; 81 import com.jcorporate.expresso.core.misc.RecordPaginator; 82 import com.jcorporate.expresso.core.misc.StringUtil; 83 import com.jcorporate.expresso.core.security.User; 84 import com.jcorporate.expresso.ext.dbobj.DownloadFiles; 85 import com.jcorporate.expresso.ext.dbobj.DownloadLog; 86 import com.jcorporate.expresso.ext.dbobj.RestrictedCountries; 87 import com.jcorporate.expresso.ext.dbobj.RestrictedOverrides; 88 import com.jcorporate.expresso.services.dbobj.MimeTypes; 89 import org.apache.log4j.Logger; 90 91 import javax.servlet.http.HttpServletRequest ; 92 import javax.servlet.http.HttpServletResponse ; 93 import java.io.File ; 94 import java.io.FileInputStream ; 95 import java.io.FileNotFoundException ; 96 import java.io.IOException ; 97 import java.io.OutputStream ; 98 import java.util.ArrayList ; 99 import java.util.Enumeration ; 100 import java.util.Iterator ; 101 import java.util.StringTokenizer ; 102 import java.util.Vector ; 103 104 105 124 public class Download 125 extends DBController { 126 private static Logger log = Logger.getLogger(Download.class); 127 128 public Download() { 129 super(); 130 131 State prompt = new State("list", this.getString("List_Downloadable")); 132 prompt.addOptionalParameter("project"); 133 prompt.addOptionalParameter("file"); addState(prompt); 136 137 State begin = new State("begin", this.getString("Begin_Downloading_A")); 138 begin.addRequiredParameter("file"); 139 addState(begin); 140 141 142 State download = new State("download", 143 this.getString("Download_A_File")); 144 download.addRequiredParameter("file"); 145 addState(download); 146 setInitialState("list"); 147 148 State s = new State("viewNotes", "View_Notes"); 149 s.addRequiredParameter("file"); 150 this.addState(s); 151 152 this.setSchema(com.jcorporate.expresso.core.ExpressoSchema.class); 153 } 154 155 165 protected DownloadFiles getThisDownloadFile(ControllerRequest request, User u) 166 throws ControllerException { 167 try { 168 DownloadFiles thisFile = new DownloadFiles(SecuredDBObject.SYSTEM_ACCOUNT); 169 thisFile.setDataContext(request.getDataContext()); 170 thisFile.setField("FileNumber", request.getParameter("file")); 171 172 if (!thisFile.find()) { 173 logInvalidFileRequest(request, u); 174 throw new ControllerException("Invalid File Number Request"); 175 } 176 177 return thisFile; 178 } catch (DBException ex) { 179 throw new ControllerException("Database communication error", ex); 180 } 181 } 182 183 194 protected ControllerResponse runBeginState(ControllerRequest request, 195 ControllerResponse response) 196 throws ControllerException { 197 try { 198 User myUser = User.getUserFromId(request.getUid(), request.getDataContext()); 199 DownloadFiles thisFile = getThisDownloadFile(request, myUser); 200 String fileName = thisFile.getField("FilePathName"); 201 202 checkIsAllowed(request, myUser, thisFile); 206 207 File checkFile = new File (fileName); 208 if (checkFile == null || !checkFile.exists()) { 209 logInvalidFileRequest(request, myUser); 210 } 211 212 213 long fileLength = checkFile.length(); 214 215 if (fileLength > 0) { 216 response.addOutput(new Output("fileLength", 217 Long.toString(fileLength) + " bytes")); 218 response.addOutput(new Output("downloadTime", 219 getDownloadTime(response, 220 fileLength))); 221 } else { 222 response.addOutput(new Output("fileLength", "unknown")); 223 response.addOutput(new Output("downloadTime", "unknown")); 224 } 225 226 response.addOutput(new Output("fileName", 227 getFriendlyName(thisFile))); 228 229 String downloadURL = StringUtil.notNull(thisFile.getField("FileURL")); 235 236 if (downloadURL.length() > 0) { 237 response.addOutput(new Output("downloadURL", downloadURL)); 238 response.addOutput(new Output("downloadLabel", 239 response.getString("Click_Here_If"))); 240 241 if (!(request instanceof ServletControllerRequest)) { 242 throw new ControllerException("runDownloadState(): Request must be" + 243 " of class ServletControllerRequest"); 244 } 245 246 ServletControllerRequest req = (ServletControllerRequest) request; 247 HttpServletRequest hreq = (HttpServletRequest ) req.getServletRequest(); 248 String eventString = ("User '" + request.getUser() + 249 "' (" + myUser.getDisplayName() + 250 "), at " + myUser.getEmail() + 251 " has just downloaded file '" + 252 fileName + "' (" + 253 thisFile.getField("Descrip") + 254 ")"); 255 256 EventHandler.Event(request.getDataContext(), "DOWNLOAD", 257 eventString, true); 258 259 DownloadLog dll = new DownloadLog(SecuredDBObject.SYSTEM_ACCOUNT); 260 dll.setDataContext(request.getDataContext()); 261 dll.setField("ExpUid", request.getUid()); 262 dll.setField("FileNumber", thisFile.getField("FileNumber")); 263 dll.setField("FilePathName", thisFile.getField("FilePathName")); 264 dll.setField("Downloaded", DateTime.getDateTimeForDB(request.getDataContext())); 265 dll.setField("IPNumber", hreq.getRemoteAddr()); 266 dll.add(); 267 } else { 268 Transition t = new Transition("download", this); 269 t.addParam("file", request.getParameter("file")); 270 t.setLabel(response.getString("Click_Here_If")); 271 response.addTransition(t); 272 } 273 } catch (DBException dbe) { 274 log.error("DBException in runBeginState", dbe); 275 throw new ControllerException(dbe); 276 } 277 278 return response; 279 } 280 281 294 protected ControllerResponse runListState(ControllerRequest request, 295 ControllerResponse response) 296 throws ControllerException { 297 String fileNumParam = StringUtil.notNull(request.getParameter("file")); 303 304 if (fileNumParam.length() > 0) { 305 return runBeginState(request, response); 306 } 307 try { 308 response.addOutput(new Output("Heading", 309 response.getString("Files_Available_For"))); 310 311 DownloadFiles dl = new DownloadFiles(request); 312 dl.setField("IsActive", "Y"); 313 314 DownloadFiles oneDownloadFile = null; 315 String project = StringUtil.notNull(request.getParameter("project")); 316 317 if (!project.equals("")) { 318 dl.setField("Project", project); 319 } 320 321 User myUser = User.getUserFromId(request.getUid(), 322 request.getDataContext()); 323 324 RecordPaginator paginator = new RecordPaginator(); 325 paginator.setCountRecords(true); 326 paginator.setPageNumber(request); 327 328 ArrayList retrieveList = paginator.searchAndRetrieve(dl, 329 DownloadFiles.FLD_LAST_UPDATED + " desc"); 330 331 if (retrieveList.size() == 0) { 332 response.addOutput(new Output("NoFiles", 333 response.getString("No_Files_Are"))); 334 335 return response; 336 } 337 338 339 Block matrix = new Block("downloadMatrix"); 340 matrix.setAttribute("table", "Y"); 341 matrix.setAttribute("header-row", 342 response.getString("FileNumber_File")); 343 response.addBlock(matrix); 344 345 if (paginator.isMoreRecords()) { 347 Transition t = new Transition("list", this); 348 t.setName("nextBtn"); 349 t.setOwnerController(this.getClass().getName()); 350 351 if (project != null && project.length() > 0) { 352 t.addParam("project", project); 353 } 354 355 t.setLabel(response.getString("List_Next_Page_Of")); 356 t.addParam("page", 357 Integer.toString((paginator.getPageNumber() + 1))); 358 response.add(t); 359 } 360 if (paginator.isPreviousRecords()) { 362 Transition t = new Transition("list", this); 363 t.setOwnerController(this.getClass().getName()); 364 t.setName("prevBtn"); 365 366 if (project != null && project.length() > 0) { 367 t.addParam("project", project); 368 } 369 370 t.addParam("page", 371 Integer.toString((paginator.getPageNumber() - 1))); 372 t.setLabel(response.getString("List_Previous_Page_Of")); 373 response.add(t); 374 } 375 376 for (Iterator i = retrieveList.iterator(); i.hasNext();) { 377 oneDownloadFile = (DownloadFiles) i.next(); 378 379 if (isAllowed(request, oneDownloadFile, myUser)) { 380 Block oneRow = new Block("oneRow"); 381 String value = null; 382 oneRow.setAttribute("row", "Y"); 383 384 String fileNumber = StringUtil.notNull(oneDownloadFile.getField("FileNumber")); 385 386 if (fileNumber.length() == 0) { 387 throw new ControllerException(response.getString("Retrieved_an_invalid")); 388 } 389 390 String label = getFriendlyName(oneDownloadFile); 391 String pathName = StringUtil.notNull(oneDownloadFile.getField("FilePathName")); 392 String urlName = StringUtil.notNull(oneDownloadFile.getField("FileURL")); 393 394 if (label.length() == 0) { 395 if (pathName.length() > 0) { 396 label = FileUtil.getBase(pathName); 397 } else if (urlName.length() > 0) { 398 label = FileUtil.getBase(urlName); 399 } else { 400 throw new ControllerException("Error, must have either a " + 401 "file path or a file URL in the database"); 402 } 403 } 404 405 Transition t = new Transition("begin", this); 406 t.addParam("file", fileNumber); 407 t.setLabel(label); 408 t.setName("downloadLink"); 409 t.setOwnerController(this.getClass().getName()); 410 oneRow.add(t); 411 value = oneDownloadFile.getField("Descrip"); 412 413 if (value != null && value.length() > 0) { 414 oneRow.add(new Output("Descrip", value)); 415 } 416 417 value = oneDownloadFile.getField(DownloadFiles.FLD_DL_NOTES); 418 419 if (value != null && value.length() > 0) { 420 Transition viewNotes = new Transition("viewNotes", this); 421 viewNotes.addParam("file", fileNumber); 422 oneRow.add(viewNotes); 423 } 424 425 value = oneDownloadFile.getField(DownloadFiles.FLD_DL_NOTES); 426 427 if (value != null && value.length() > 0) { 428 oneRow.add(new Output("Notes", value)); 429 } 430 431 oneRow.add(new Output("LastUpdated", 432 oneDownloadFile.getField("LastUpdated"))); 433 434 File checkFile = new File (oneDownloadFile.getField("FilePathName")); 435 int tempLength = (int) checkFile.length(); 436 437 if (tempLength > 0) { 440 oneRow.add(new Output("FileLength", 441 Integer.toString(tempLength) + " bytes")); 442 } else { 443 oneRow.add(new Output("FileLength", "unknown")); 444 } 445 446 MimeTypes mimeType = new MimeTypes(request); 447 mimeType.setField("MimeNumber", 448 oneDownloadFile.getField("MimeNumber")); 449 450 if (mimeType.find()) { 451 oneRow.add(new Output("IconURL", mimeType.getIconURL())); 452 } 453 454 matrix.add(oneRow); 455 } 456 457 } 458 459 } catch (DBException de) { 460 throw new ControllerException("Download.runListState()", de); 461 } 462 463 return response; 464 } 465 466 477 protected ControllerResponse runDownloadState(ControllerRequest controllerRequest, 478 ControllerResponse controllerResponse) 479 throws ControllerException { 480 String fileName = ("no name"); 481 controllerResponse.setCustomResponse(true); 482 483 if (!(controllerRequest instanceof ServletControllerRequest)) { 484 throw new ControllerException("runDownloadState(): Request must be" + 485 " of class ServletControllerRequest"); 486 } 487 488 ServletControllerRequest req = (ServletControllerRequest) controllerRequest; 489 HttpServletRequest request = (HttpServletRequest ) req.getServletRequest(); 490 HttpServletResponse response = (HttpServletResponse ) req.getServletResponse(); 491 492 response.reset(); 493 OutputStream toClient = null; 494 495 try { 496 String fileNumber = StringUtil.notNull(controllerRequest.getParameter("file")); 497 User myUser = User.getUserFromId(controllerRequest.getUid(), controllerRequest.getDataContext()); 498 499 if (log.isInfoEnabled()) { 500 log.info("User '" + controllerRequest.getUser() + "' (" + 501 myUser.getLoginName() + 502 ") requesting download of file number '" + fileNumber + 503 "'"); 504 } 505 506 DownloadFiles thisFile = this.getThisDownloadFile(controllerRequest, myUser); 507 508 509 fileName = thisFile.getField(DownloadFiles.FLD_FILE_PATH_NAME); 510 511 checkIsAllowed(controllerRequest, myUser, thisFile); 512 513 514 File checkFile = new File (fileName); 515 516 if (!checkFile.exists()) { 517 logInvalidFileRequest(controllerRequest, myUser); 518 } 519 520 521 StringTokenizer stfn = new StringTokenizer (fileName, "/"); 522 String baseName = null; 523 524 while (stfn.hasMoreTokens()) { 525 baseName = stfn.nextToken(); 526 } 527 528 response.setHeader("Content-Disposition", 529 "inline;filename=" + baseName); 530 531 String eventString = ("User '" + 532 controllerRequest.getUser() + 533 "' (" + myUser.getDisplayName() + 534 "), at " + myUser.getEmail() + 535 " has just downloaded file '" + 536 fileName + "' (" + 537 thisFile.getField("Descrip") + 538 ")"); 539 540 EventHandler.Event(controllerRequest.getDataContext(), "DOWNLOAD", 541 eventString, true); 542 543 DownloadLog dll = new DownloadLog(SecuredDBObject.SYSTEM_ACCOUNT); 544 dll.setDataContext(controllerRequest.getDataContext()); 545 dll.setField("ExpUid", controllerRequest.getUid()); 546 dll.setField("FileNumber", fileNumber); 547 dll.setField("FilePathName", fileName); 548 dll.setField("Downloaded", DateTime.getDateTimeForDB(controllerRequest.getDataContext())); 549 dll.setField("IPNumber", request.getRemoteAddr()); 550 dll.add(); 551 552 String mimeNumber = thisFile.getField("MimeNumber"); 553 554 if (mimeNumber == null) { 555 response.setHeader("Content-Type", "application/x-unknown"); 556 } else { 557 try { 558 MimeTypes contentType = new MimeTypes(SecuredDBObject.SYSTEM_ACCOUNT); 559 contentType.setField("MimeNumber", mimeNumber); 560 contentType.retrieve(); 561 response.setHeader("Content-Type", contentType.getField("MimeType")); 563 } catch (DBException ex) { 564 response.setHeader("Content-Type", "application/x-unknown"); 565 } 567 } 568 569 int tempLength = (int) checkFile.length(); 570 571 if (tempLength > 0) { 574 response.setContentLength(tempLength); 575 } 576 577 toClient = response.getOutputStream(); 578 returnFile(fileName, toClient); 579 } catch (DBException dbe) { 581 throw new ControllerException("DownloadController.runDownloadState", 582 dbe); 583 } catch (Exception de) { 584 if (de instanceof IOException ) { 585 log.error("Download IO Exception:", de); 586 } else { 587 throw new ControllerException("DownloadController.runDownloadState", 588 de); 589 } 590 } finally { 591 592 593 if (toClient != null) { 594 try { 595 toClient.flush(); 596 } catch (java.io.IOException ioe) { 597 log.debug("Error flushing client stream", ioe); 598 } 599 } 600 } 601 602 return controllerResponse; 603 } 604 605 613 protected void returnFile(String filename, OutputStream out) 614 throws FileNotFoundException , IOException { 615 616 FileInputStream fis = null; 618 619 try { 620 fis = new FileInputStream (filename); 621 FileUtil.copyStream(fis, out); 622 623 } finally { 630 if (fis != null) { 631 fis.close(); 632 } 633 } 634 635 } 636 637 638 647 protected boolean isAllowed(ControllerRequest request, 648 DownloadFiles oneFile, User myUser) 649 throws DBException { 650 boolean foundGroupName = false; 651 Vector groupList = myUser.getGroups(); 652 String allowedGroup = oneFile.getField("GroupName"); 653 654 if (allowedGroup == null || allowedGroup.length() == 0) { 655 throw new DBException("No allowed download groups for this file"); 656 } 657 658 for (Enumeration e = groupList.elements(); e.hasMoreElements();) { 659 String oneGroup = (String ) e.nextElement(); 660 661 if (oneGroup.equalsIgnoreCase(oneFile.getField("GroupName"))) { 662 foundGroupName = true; 663 } 664 } 665 666 if (foundGroupName == true) { 667 668 boolean isRestricted = oneFile.getFieldBoolean("IsRestricted"); 673 if (isRestricted) { 674 String remoteIP = ((ServletControllerRequest) request).getServletRequest().getRemoteAddr(); 675 676 if (remoteIP.equals("127.0.0.1")) { 677 log.warn("Got a restricted download request from localhost." + 678 " Please make sure that remote connection ip addresses" + 679 " are getting through the servlet connector properly"); 680 681 return true; 682 } else { 683 684 RestrictedOverrides overRides = new RestrictedOverrides(request); 688 int overRideValue = overRides.isAllowed(myUser); 689 690 switch (overRideValue) { 691 case RestrictedOverrides.OVERRIDE_ALLOWED: 692 return true; 693 694 case RestrictedOverrides.OVERRIDE_DENIED: 695 return false; 696 697 case RestrictedOverrides.OVERRIDE_NOT_FOUND: 698 699 break; 701 702 default: 703 throw new DBException("RestrictedOverrides." + 704 "isAllowed() returned unknown integer value: " + 705 overRideValue); 706 } 707 708 RestrictedCountries rc = new RestrictedCountries(request); 709 710 if (!rc.isRestricted(((ServletControllerRequest) request).getServletRequest().getRemoteAddr())) { 711 return true; 712 } 713 } 714 } else { 715 return true; 716 } 717 } 718 719 return false; 720 } 721 722 730 protected void logInvalidFileRequest(ControllerRequest request, 731 User myUser) 732 throws ControllerException { 733 String eventString = null; 734 735 try { 736 eventString = ("User '" + request.getUser() + "' (" + 737 myUser.getDisplayName() + 738 ") attempted to downloaded file number'" + 739 request.getParameter("file") + "', but " + 740 "the record did not exist."); 741 EventHandler.Event(request.getDataContext(), "DOWNLOAD", eventString, 742 false); 743 throw new ControllerException("There is no download file number '" + 744 request.getParameter("file") + "'"); 745 } catch (DBException de) { 746 log.error("Could not trigger event:" + 747 StringUtil.notNull(eventString) + ":", de); 748 } 749 } 750 751 761 protected String getFriendlyName(DownloadFiles oneDownloadFile) 762 throws ControllerException, DBException { 763 String label = StringUtil.notNull(oneDownloadFile.getField("DisplayName")); 764 String pathName = StringUtil.notNull(oneDownloadFile.getField("FilePathName")); 765 String urlName = StringUtil.notNull(oneDownloadFile.getField("FileURL")); 766 767 if (label.length() == 0) { 768 if (pathName.length() > 0) { 769 label = FileUtil.getBase(pathName); 770 } else if (urlName.length() > 0) { 771 label = FileUtil.getBase(urlName); 772 } else { 773 throw new ControllerException("Error, must have either a " + 774 "file path or a file URL in the database"); 775 } 776 } 777 778 return label; 779 } 780 781 792 protected String getDownloadTime(ControllerResponse response, 793 long fileLength) 794 throws ControllerException { 795 long downloadSeconds = fileLength / 3333; 796 797 if (downloadSeconds >= 120) { 798 return (Long.toString(downloadSeconds / 60) + 799 response.getString("Minutes")); 800 } else { 801 return (Long.toString(downloadSeconds) + 802 response.getString("Seconds")); 803 } 804 } 805 806 816 protected void checkIsAllowed(ControllerRequest request, 817 User u, DownloadFiles file) 818 throws ControllerException { 819 try { 820 if (!isAllowed(request, file, u)) { 824 String fileName = file.getField(DownloadFiles.FLD_DISPLAY_NAME); 825 String eventString = ("User '" + 826 request.getUser() + 827 "' (" + u.getDisplayName() + 828 ") attempted to downloaded file '" + 829 fileName + "' (" + 830 file.getField("Descrip") + 831 "), but " + 832 "did not have permission to do so."); 833 834 EventHandler.Event(request.getDataContext(), 835 "DOWNLOAD", eventString, false); 836 throw new ControllerException("You do not have " + 837 " permission to download '" + 838 fileName + "'"); 839 } 840 } catch (DBException ex) { 841 throw new ControllerException("Database communication error.", ex); 842 } 843 844 } 845 846 851 public String getTitle() { 852 return "Download Controller"; 853 } 854 855 863 protected void runViewNotesState(ControllerRequest request, 864 ControllerResponse response) throws ControllerException { 865 866 try { 867 User u = User.getUserFromId(request.getUid(), request.getDataContext()); 868 DownloadFiles df = getThisDownloadFile(request, u); 869 checkIsAllowed(request, u, df); 870 871 response.addOutput(new Output("notes", df.getField(DownloadFiles.FLD_DL_NOTES))); 872 } catch (DBException ex) { 873 throw new ControllerException("Database Access Error", ex); 874 } 875 } 876 } | Popular Tags |