public boolean addSubscriber(String virtualUser, String subscriberEmail) {
    Element watchedInvitation = getInvitationElementByVirtualUser(virtualUser);
    if (watchedInvitation == null) {
      return false;
    }

    Element subscriberListElem = XmlUtil.getChildByTagName(watchedInvitation, "subscriberList");
    if (subscriberListElem == null) {
      subscriberListElem = doc.createElement("subscriberList");
      watchedInvitation.appendChild(subscriberListElem);
    }

    NodeList subscriberList = subscriberListElem.getElementsByTagName("subscriber");

    if (subscriberList != null) {
      int listLength = subscriberList.getLength();
      for (int i = 0; i < listLength; i++) {
        Element subscriberElement = (Element) subscriberList.item(i);
        if (XmlUtil.getChildText(subscriberElement, "email").equals(subscriberEmail)) {
          return false;
        }
      }
    }

    Element subscriberElem = doc.createElement("subscriber");
    XmlUtil.setChildText(subscriberElem, "email", subscriberEmail);
    XmlUtil.setChildText(subscriberElem, "code", generateAccessCode());
    subscriberListElem.appendChild(subscriberElem);
    changed = true;
    return true;
  }
  protected void process() {
    if ((!isAdminUser(false)) || (!userMgr.getDocumentRoot(uid).equals("/"))) {
      Logger.getLogger(getClass())
          .warn("UNIX command line is only available for admin users with root access");
      return;
    }

    String cmdOutput = "";

    String unixCmd = req.getParameter("unixCmd");

    if (unixCmd != null) {
      unixCmd = unixCmd.trim();

      if (unixCmd.length() > 0) {
        cmdOutput = runUnixCmd(unixCmd);
      }
    }

    Element resultElement = doc.createElement("result");

    XmlUtil.setChildText(resultElement, "cmdOutput", cmdOutput);

    XmlUtil.setChildText(resultElement, "success", "true");

    doc.appendChild(resultElement);

    this.processResponse();
  }
  protected void process() {
    if (!checkWriteAccess()) {
      return;
    }

    String path = getParameter("path");

    if (!accessAllowed(path)) {
      Logger.getLogger(getClass())
          .warn("user " + uid + " tried to access folder outside of his document root: " + path);

      return;
    }

    String shortPath = CommonUtils.shortName(getHeadlinePath(path), 50);

    Element folderWatchElement = doc.createElement("folderWatch");

    doc.appendChild(folderWatchElement);

    ProcessingInstruction xslRef =
        doc.createProcessingInstruction(
            "xml-stylesheet", "type=\"text/xsl\" href=\"/doxee-internal/xsl/folderWatch.xsl\"");

    doc.insertBefore(xslRef, folderWatchElement);

    XmlUtil.setChildText(folderWatchElement, "css", userMgr.getCSS(uid), false);
    XmlUtil.setChildText(folderWatchElement, "path", path.replace('\\', '/'), false);
    XmlUtil.setChildText(folderWatchElement, "shortPath", shortPath, false);

    if (FolderWatchManager.getInstance().isListener(path, uid)) {
      XmlUtil.setChildText(folderWatchElement, "watched", "true");
    }

    addMsgResource(
        "label.readWriteStatus", getResource("label.readWriteStatus", "Read/Write status"));

    addMsgResource(
        "folderWatchStatusOn",
        getResource(
            "folderWatchStatusOn", "The content of the folder is being watched for changes."));
    addMsgResource(
        "folderWatchStatusOff",
        getResource(
            "folderWatchStatusOff", "Watch this folder for changes and get notified by e-mail."));

    addMsgResource("button.startWatch", getResource("button.startWatch", "start watch"));
    addMsgResource("button.stopWatch", getResource("button.stopWatch", "stop watch"));

    addMsgResource("button.cancel", getResource("button.cancel", "Cancel"));

    processResponse();
  }
  public void notifySubscribers(String accessCode) {
    Element invitationElem = getInvitationElement(accessCode);

    if (invitationElem == null) {
      Logger.getLogger(getClass())
          .warn("invitation for subscription notification not found: " + accessCode);
      return;
    }

    Element subscriberListElem = XmlUtil.getChildByTagName(invitationElem, "subscriberList");
    if (subscriberListElem == null) {
      return;
    }

    NodeList subscriberList = subscriberListElem.getElementsByTagName("subscriber");

    if ((subscriberList == null) || (subscriberList.getLength() == 0)) {
      return;
    }

    Element notifyElem = XmlUtil.getChildByTagName(invitationElem, "notifySubscribers");

    if (notifyElem == null) {
      notifyElem = doc.createElement("notifySubscribers");
      invitationElem.appendChild(notifyElem);
    }

    XmlUtil.setChildText(notifyElem, "changed", Long.toString(System.currentTimeMillis()));

    changed = true;
  }
  protected void process() {
    String imgFileName = getParameter("imgFile");

    if (!this.checkAccess(imgFileName)) {
      return;
    }

    Element cameraDataElement = doc.createElement("cameraData");

    doc.appendChild(cameraDataElement);

    ProcessingInstruction xslRef =
        doc.createProcessingInstruction(
            "xml-stylesheet", "type=\"text/xsl\" href=\"/webfilesys/xsl/cameraData.xsl\"");

    doc.insertBefore(xslRef, cameraDataElement);

    XmlUtil.setChildText(cameraDataElement, "css", userMgr.getCSS(uid), false);

    String shortImgName = CommonUtils.shortName(this.getHeadlinePath(imgFileName), 48);

    XmlUtil.setChildText(cameraDataElement, "shortImgName", shortImgName, false);

    addMsgResource("alt.cameradata", getResource("alt.cameradata", "Camera Data"));
    addMsgResource(
        "alert.nocameradata", getResource("alert.nocameradata", "No camera data available"));
    addMsgResource("label.picturefile", getResource("label.picturefile", "picture file"));
    addMsgResource("label.manufacturer", getResource("label.manufacturer", "camera manufacturer"));
    addMsgResource("label.cameramodel", getResource("label.cameramodel", "camera model"));
    addMsgResource("label.exposuredate", getResource("label.exposuredate", "exposure date"));
    addMsgResource("label.exposuretime", getResource("label.exposuretime", "exposure time"));
    addMsgResource("label.aperture", getResource("label.aperture", "aperture"));
    addMsgResource("label.isoValue", getResource("label.isoValue", "ISO equivalent"));
    addMsgResource("label.flashfired", getResource("label.flashfired", "flash fired"));
    addMsgResource("label.imgwidth", getResource("label.imgwidth", "image width"));
    addMsgResource("label.imgheight", getResource("label.imgheight", "image height"));
    addMsgResource("label.thumbexists", getResource("label.thumbexists", "thumbnail included"));
    addMsgResource("label.gpsLatitude", getResource("label.gpsLatitude", "GPS latitude"));
    addMsgResource("label.gpsLongitude", getResource("label.gpsLongitude", "GPS longitude"));
    addMsgResource("button.closewin", getResource("button.closewin", "Close Window"));

    CameraExifData exifData = new CameraExifData(imgFileName);

    if (exifData.hasExifData()) {
      Element exifDataElement = doc.createElement("exifData");

      cameraDataElement.appendChild(exifDataElement);

      String manufacturer = exifData.getManufacturer();

      if (manufacturer != null) {
        XmlUtil.setChildText(exifDataElement, "manufacturer", manufacturer);
      }

      String cameraModel = exifData.getCameraModel();

      if (cameraModel != null) {
        XmlUtil.setChildText(exifDataElement, "cameraModel", cameraModel);
      }

      Date exposureDate = exifData.getExposureDate();

      if (exposureDate != null) {
        SimpleDateFormat dateFormat = LanguageManager.getInstance().getDateFormat(language);

        String formattedDate = dateFormat.format(exposureDate);

        XmlUtil.setChildText(exifDataElement, "exposureDate", formattedDate);
      }

      String exposureTime = exifData.getExposureTime();

      if (exposureTime != null) {
        XmlUtil.setChildText(exifDataElement, "exposureTime", exposureTime);
      }

      String aperture = exifData.getAperture();

      if (aperture != null) {
        XmlUtil.setChildText(exifDataElement, "aperture", aperture);
      }

      String isoValue = exifData.getISOValue();

      if (isoValue != null) {
        XmlUtil.setChildText(exifDataElement, "isoValue", isoValue);
      }

      int flashFired = exifData.getFlashFired();

      if (flashFired >= 0) {
        if ((flashFired == 0) || (flashFired == 16) || (flashFired == 24) || (flashFired == 32)) {
          XmlUtil.setChildText(exifDataElement, "flashFired", getResource("label.no", "no"));
        } else {
          XmlUtil.setChildText(exifDataElement, "flashFired", getResource("label.yes", "yes"));
        }
      }

      int imageWidth = exifData.getImageWidth();

      if (imageWidth >= 0) {
        XmlUtil.setChildText(exifDataElement, "imgWidth", Integer.toString(imageWidth));
      }

      int imageHeight = exifData.getImageHeigth();

      if (imageHeight >= 0) {
        XmlUtil.setChildText(exifDataElement, "imgHeight", Integer.toString(imageHeight));
      }

      int thumbLength = exifData.getThumbnailLength();

      if (thumbLength > 0) {
        String srcFileName =
            "/webfilesys/servlet?command=exifThumb&imgFile=" + UTF8URLEncoder.encode(imgFileName);

        XmlUtil.setChildText(exifDataElement, "thumbnailPath", srcFileName);
      }

      int thumbWidth = exifData.getThumbWidth();
      int thumbHeight = exifData.getThumbHeight();

      if ((thumbWidth > 0) && (thumbHeight > 0)) {
        XmlUtil.setChildText(exifDataElement, "thumbnailWidth", Integer.toString(thumbWidth));
        XmlUtil.setChildText(exifDataElement, "thumbnailHeight", Integer.toString(thumbHeight));
      }

      float gpsLatitude = exifData.getGpsLatitude();

      if (gpsLatitude >= 0.0f) {
        XmlUtil.setChildText(
            exifDataElement,
            "gpsLatitude",
            Float.toString(gpsLatitude) + " " + exifData.getGpsLatitudeRef());
      }

      float gpsLongitude = exifData.getGpsLongitude();

      if (gpsLongitude >= 0.0f) {
        XmlUtil.setChildText(
            exifDataElement,
            "gpsLongitude",
            Float.toString(gpsLongitude) + " " + exifData.getGpsLongitudeRef());
      }

      int orientation = exifData.getOrientation();

      if (orientation != CameraExifData.ORIENTATION_UNKNOWN) {
        XmlUtil.setChildText(exifDataElement, "orientation", Integer.toString(orientation));

        addMsgResource("label.imgOrientation", getResource("label.imgOrientation", "orientation"));
        addMsgResource("orientation.landscape", getResource("orientation.landscape", "lanscape"));
        addMsgResource("orientation.portrait", getResource("orientation.portrait", "portrait"));
      }
    }

    this.processResponse("cameraData.xsl", false);
  }
  protected void process() {
    String syncSourcePath =
        (String) session.getAttribute(XmlSelectSyncFolderHandler.SESSION_ATTRIB_SYNC_SOURCE);
    String syncTargetPath =
        (String) session.getAttribute(XmlSelectSyncFolderHandler.SESSION_ATTRIB_SYNC_TARGET);

    Element syncElement = doc.createElement("synchronize");

    doc.appendChild(syncElement);

    ProcessingInstruction xslRef =
        doc.createProcessingInstruction(
            "xml-stylesheet", "type=\"text/xsl\" href=\"/webfilesys/xsl/syncCompare.xsl\"");

    doc.insertBefore(xslRef, syncElement);

    XmlUtil.setChildText(syncElement, "css", userMgr.getCSS(uid), false);
    XmlUtil.setChildText(syncElement, "syncSourcePath", getHeadlinePath(syncSourcePath), false);
    XmlUtil.setChildText(syncElement, "syncTargetPath", getHeadlinePath(syncTargetPath), false);

    addMsgResource(
        "headline.syncCompare", getResource("headline.syncCompare", "Synchronize Folders"));
    addMsgResource("label.syncSource", getResource("label.syncSource", "source folder"));
    addMsgResource("label.syncTarget", getResource("label.syncTarget", "target folder"));
    addMsgResource("button.startSync", getResource("button.startSync", "Start Synchronization"));
    addMsgResource("button.cancel", getResource("button.cancel", "Cancel"));
    addMsgResource("button.closewin", getResource("button.closewin", "close window"));

    addMsgResource(
        "diffType.missingSourceFile",
        getResource("diffType.missingSourceFile", "file missing in source folder"));
    addMsgResource(
        "diffType.missingTargetFile",
        getResource("diffType.missingTargetFile", "file missing in target folder"));
    addMsgResource(
        "diffType.missingSourceFolder",
        getResource("diffType.missingSourceFolder", "directory missing in source folder"));
    addMsgResource(
        "diffType.missingTargetFolder",
        getResource("diffType.missingTargetFolder", "directory missing in target folder"));
    addMsgResource("diffType.size", getResource("diffType.size", "size changed"));
    addMsgResource(
        "diffType.modified", getResource("diffType.modified", "last modification time changed"));
    addMsgResource(
        "diffType.sizeAndModified",
        getResource("diffType.sizeAndModified", "size and last modification time changed"));
    addMsgResource(
        "diffType.accessRights", getResource("diffType.accessRights", "access rights changed"));

    addMsgResource("sync.tableHeadPath", getResource("sync.tableHeadPath", "path"));
    addMsgResource("sync.tableHeadSource", getResource("sync.tableHeadSource", "source"));
    addMsgResource("sync.tableHeadTarget", getResource("sync.tableHeadTarget", "target"));
    addMsgResource("sync.missing", getResource("sync.missing", "missing"));

    addMsgResource("sync.bytes", getResource("sync.bytes", "bytes"));

    addMsgResource("sync.access.none", getResource("sync.access.none", "access forbidden"));
    addMsgResource("sync.access.readonly", getResource("sync.access.readonly", "read"));
    addMsgResource("sync.access.readwrite", getResource("sync.access.readwrite", "write"));

    addMsgResource(
        "sync.nothingSelected",
        getResource(
            "sync.nothingSelected", "Select at least one file/folder for synchronization!"));
    addMsgResource(
        "sync.noDifference",
        getResource("sync.noDifference", "No differences found (folders are in snyc)."));

    addMsgResource(
        "sync.action.createMissingTarget",
        getResource(
            "sync.action.createMissingTarget",
            "create missing target folders and copy missing target files"));
    addMsgResource(
        "sync.action.createMissingSource",
        getResource(
            "sync.action.createMissingSource",
            "create missing source folders and copy missing source files"));
    addMsgResource(
        "sync.action.removeExtraTarget",
        getResource(
            "sync.action.removeExtraTarget",
            "remove target folders and files that do not exist in the source folder"));
    addMsgResource(
        "sync.action.copyNewerToTarget",
        getResource(
            "sync.action.copyNewerToTarget",
            "copy newer files from source folder to target folder"));
    addMsgResource(
        "sync.action.copyNewerToSource",
        getResource(
            "sync.action.copyNewerToSource",
            "copy newer files from target folder to source folder"));
    addMsgResource(
        "sync.action.copyDateChangeToTarget",
        getResource(
            "sync.action.copyDateChangeToTarget",
            "copy all files with changed modification date from source folder to target folder"));
    addMsgResource(
        "sync.action.copySizeChangeToTarget",
        getResource(
            "sync.action.copySizeChangeToTarget",
            "copy files with changed size from source folder to target folder"));
    addMsgResource(
        "sync.action.copyAccessRights",
        getResource(
            "sync.action.copyAccessRights",
            "copy changed access rights from source folder to target folder"));

    addMsgResource(
        "sync.confirmStartSync",
        getResource(
            "sync.confirmStartSync", "Are you sure you want to start the synchronization?"));
    addMsgResource(
        "sync.confirmRemoveExtraTarget",
        getResource(
            "sync.confirmRemoveExtraTarget",
            "Synchronization might remove files and directories in the target folder. Are you sure?"));

    Element differencesElement = doc.createElement("differencesList");

    syncElement.appendChild(differencesElement);

    DirSynchronizer dirSync = new DirSynchronizer(syncSourcePath, syncTargetPath);

    ArrayList differences = dirSync.getDifferences();

    session.setAttribute(SESSION_ATTRIB_SYNCHRONIZE_ITEMS, differences);

    Element diffTypesElement = doc.createElement("diffTypes");

    syncElement.appendChild(diffTypesElement);

    if (dirSync.getMissingTargetFiles() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type1", Integer.toString(dirSync.getMissingTargetFiles()));
    }

    if (dirSync.getMissingSourceFiles() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type2", Integer.toString(dirSync.getMissingSourceFiles()));
    }

    if (dirSync.getMissingTargetFolders() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type3", Integer.toString(dirSync.getMissingTargetFolders()));
    }

    if (dirSync.getMissingSourceFolders() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type4", Integer.toString(dirSync.getMissingSourceFolders()));
    }

    if (dirSync.getModifiedSize() > 0) {
      XmlUtil.setChildText(diffTypesElement, "type5", Integer.toString(dirSync.getModifiedSize()));
    }

    if (dirSync.getModifiedTime() > 0) {
      XmlUtil.setChildText(diffTypesElement, "type6", Integer.toString(dirSync.getModifiedTime()));
    }

    if (dirSync.getModifiedSizeAndTime() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type7", Integer.toString(dirSync.getModifiedSizeAndTime()));
    }

    if (dirSync.getModifiedAccess() > 0) {
      XmlUtil.setChildText(
          diffTypesElement, "type8", Integer.toString(dirSync.getModifiedAccess()));
    }

    SimpleDateFormat dateFormat = LanguageManager.getInstance().getDateFormat(language);

    DecimalFormat numFormat = new DecimalFormat("#,###,###,###,###");

    for (int i = 0; (i < differences.size()) && (i < MAX_SHOW_DIFF_NUM); i++) {
      SyncItem syncItem = (SyncItem) differences.get(i);

      Element diffElement = doc.createElement("difference");

      XmlUtil.setChildText(diffElement, "id", Integer.toString(syncItem.getId()));

      XmlUtil.setChildText(diffElement, "diffType", Integer.toString(syncItem.getDiffType()));

      XmlUtil.setChildText(diffElement, "fileName", syncItem.getFileName());

      Element sourceElement = doc.createElement("source");

      XmlUtil.setChildText(sourceElement, "path", syncItem.getSource().getPath());
      XmlUtil.setChildText(
          sourceElement,
          "displayPath",
          getForcedLineBreakPath(getHeadlinePath(syncItem.getSource().getPath())));
      XmlUtil.setChildText(sourceElement, "size", numFormat.format(syncItem.getSource().getSize()));
      XmlUtil.setChildText(
          sourceElement,
          "modified",
          dateFormat.format(new Date(syncItem.getSource().getModificationTime())));
      XmlUtil.setChildText(sourceElement, "canRead", "" + syncItem.getSource().getCanRead());
      XmlUtil.setChildText(sourceElement, "canWrite", "" + syncItem.getSource().getCanWrite());

      diffElement.appendChild(sourceElement);

      Element targetElement = doc.createElement("target");

      XmlUtil.setChildText(targetElement, "path", syncItem.getTarget().getPath());
      XmlUtil.setChildText(
          targetElement,
          "displayPath",
          getForcedLineBreakPath(getHeadlinePath(syncItem.getTarget().getPath())));
      XmlUtil.setChildText(targetElement, "size", numFormat.format(syncItem.getTarget().getSize()));
      XmlUtil.setChildText(
          targetElement,
          "modified",
          dateFormat.format(new Date(syncItem.getTarget().getModificationTime())));
      XmlUtil.setChildText(targetElement, "canRead", "" + syncItem.getTarget().getCanRead());
      XmlUtil.setChildText(targetElement, "canWrite", "" + syncItem.getTarget().getCanWrite());

      diffElement.appendChild(targetElement);

      differencesElement.appendChild(diffElement);
    }

    if (differences.size() > MAX_SHOW_DIFF_NUM) {
      XmlUtil.setChildText(syncElement, "invisibleItems", "true", false);
      addMsgResource(
          "sync.invisibleItems",
          getResource(
              "sync.invisibleItems",
              "The number of files out of sync is rather large. Not all differences are shown here."));
    }

    this.processResponse("syncCompare.xsl", true);
  }
  protected void process() {
    if (!checkWriteAccess()) {
      return;
    }

    String relPath = null;

    String path = getParameter("path");

    if (isMobile()) {
      relPath = path;
      path = getAbsolutePath(path);
    }

    if (!checkAccess(path)) {
      return;
    }

    Element resultElement = doc.createElement("result");

    String success = null;

    String resultMsg = "";

    String lowerCaseDocRoot = userMgr.getLowerCaseDocRoot(uid);

    if (path.toLowerCase().replace('\\', '/').equals(lowerCaseDocRoot)) {
      success = "error";

      resultMsg = getResource("alert.delhomedir", "The home directory may not be deleted!");
    } else {
      File dirToBeDeleted = new File(path);

      if (!dirToBeDeleted.canWrite() || (!dirToBeDeleted.isDirectory())) {
        Logger.getLogger(getClass())
            .warn(dirToBeDeleted + " cannot be deleted (is not a writable directory)");

        success = "error";

        resultMsg = getResource("alert.delDirError", "could not be deleted!");
      } else {
        String fileList[] = dirToBeDeleted.list();

        if (fileList.length > 0) {
          if ((fileList.length > 1) || (!fileList[0].equals(MetaInfManager.METAINF_FILE))) {
            String confirmed = getParameter("confirmed");

            if ((confirmed == null) || (!confirmed.equalsIgnoreCase("true"))) {
              success = "notEmpty";

              String shortPath = null;

              if (relPath != null) {
                shortPath = CommonUtils.shortName(relPath, 35);
              } else {
                shortPath = CommonUtils.shortName(path, 35);
              }

              resultMsg =
                  shortPath
                      + "\n"
                      + getResource("confirm.forcedirdel", "is not empty.\nDelete it anyway?");
            }
          }
        }

        if (success == null) {
          File parentDir = dirToBeDeleted.getParentFile();

          if (delDirTree(path)) {
            MetaInfManager.getInstance().removePath(path);

            SubdirExistCache.getInstance().cleanupExistSubdir(path);

            FastPathManager.getInstance().removeTree(uid, path);

            success = "deleted";

            XmlUtil.setChildText(resultElement, "parentPath", parentDir.getAbsolutePath());
          } else {
            success = "error";

            resultMsg = getResource("alert.delDirError", "could not be deleted!");
          }

          // even if only a part of the tree could be deleted we have to refresh the
          // subdir status

          (new TestSubDirThread(parentDir.getAbsolutePath())).start();
        }
      }
    }

    XmlUtil.setChildText(resultElement, "success", success);

    XmlUtil.setChildText(resultElement, "message", resultMsg);

    XmlUtil.setChildText(resultElement, "path", path);

    doc.appendChild(resultElement);

    this.processResponse();
  }
  private void checkSubscriberNotifications() {
    if (Logger.getLogger(getClass()).isDebugEnabled()) {
      Logger.getLogger(getClass()).debug("checking subscriber notifications");
    }

    NodeList invitationList = invitationRoot.getElementsByTagName("invitation");

    if (invitationList == null) {
      return;
    }

    int listLength = invitationList.getLength();

    for (int i = 0; i < listLength; i++) {
      Element invitationElem = (Element) invitationList.item(i);

      Element notifyElem = XmlUtil.getChildByTagName(invitationElem, "notifySubscribers");
      if (notifyElem != null) {
        Element changedElem = XmlUtil.getChildByTagName(notifyElem, "changed");

        if (changedElem != null) {
          long lastChangeTime = 0;
          try {
            lastChangeTime = Long.parseLong(XmlUtil.getElementText(changedElem));
          } catch (NumberFormatException numEx) {
            Logger.getLogger(getClass()).error("invalid change time", numEx);
          }

          if (System.currentTimeMillis() - lastChangeTime > NOTIFIY_DELAY_AFTER_CHANGE) {
            // wait some time after blog change until subscribers are notified, in case more entries
            // will be created soon
            long lastNotified = 0;
            String lastNotificationTime = XmlUtil.getChildText(notifyElem, "lastNotified");
            if (!CommonUtils.isEmpty(lastNotificationTime)) {
              try {
                lastNotified = Long.parseLong(lastNotificationTime);
              } catch (NumberFormatException numEx) {
                Logger.getLogger(getClass())
                    .error("invalid lastNotified time: " + lastNotificationTime);
              }
            }

            if (System.currentTimeMillis() - lastNotified > MIN_SUBSCRIBER_NOTIFICATION_INTERVAL) {
              Element subscriberListElem =
                  XmlUtil.getChildByTagName(invitationElem, "subscriberList");
              if (subscriberListElem != null) {
                NodeList subscriberList = subscriberListElem.getElementsByTagName("subscriber");

                if (subscriberList != null) {
                  String blogPath = XmlUtil.getChildText(invitationElem, "path");

                  String virtualUser = XmlUtil.getChildText(invitationElem, "virtualUser");

                  String blogTitle = MetaInfManager.getInstance().getDescription(blogPath, ".");
                  if (CommonUtils.isEmpty(blogTitle)) {
                    blogTitle = virtualUser;
                  }

                  String blogAccessCode = invitationElem.getAttribute("accessCode");

                  int subscriberListLength = subscriberList.getLength();

                  for (int k = 0; k < subscriberListLength; k++) {
                    Element subscriberElement = (Element) subscriberList.item(k);
                    String email = XmlUtil.getChildText(subscriberElement, "email");
                    String code = XmlUtil.getChildText(subscriberElement, "code");
                    sendSubscriberNotification(email, code, blogTitle, virtualUser, blogAccessCode);
                  }
                }
              }

              notifyElem.removeChild(changedElem);
              XmlUtil.setChildText(
                  notifyElem, "lastNotified", Long.toString(System.currentTimeMillis()));

              changed = true;
            }
          }
        }
      }
    }
  }
  protected void process() {
    String actPath = getParameter("actpath");

    if (actPath == null) {
      actPath = getCwd();
    }

    if (!checkAccess(actPath)) {
      return;
    }

    String recurseParm = getParameter("recurse");
    String delayString = getParameter("delay");
    String autoForwardParm = getParameter("autoForward");
    String startFilePath = getParameter("startFilePath");

    boolean autoForward = ((autoForwardParm != null) && autoForwardParm.equalsIgnoreCase("true"));

    String randomizeParm = getParameter("randomize");
    boolean randomize = ((randomizeParm != null) && randomizeParm.equalsIgnoreCase("true"));

    int delay = WebFileSys.getInstance().getSlideShowDelay();
    int imageIdx = 0;
    try {
      delay = Integer.parseInt(delayString);
    } catch (NumberFormatException nfe) {
    }

    boolean recurse = false;
    if (recurseParm.equalsIgnoreCase("true")) {
      recurse = true;
    }

    if (imageIdx <= 0) {
      session.removeAttribute(SLIDESHOW_BUFFER);
      getImageTree(actPath, recurse, randomize);
      if (startFilePath == null) {
        imageIdx = 0;
      } else {
        imageIdx = getStartFileIndex(startFilePath);
      }
    } else {
      Vector imageFiles = (Vector) session.getAttribute(SLIDESHOW_BUFFER);
      if ((imageFiles == null) || (imageIdx >= imageFiles.size())) {
        session.removeAttribute(SLIDESHOW_BUFFER);
        getImageTree(actPath, recurse, randomize);
        imageIdx = 0;
      }
    }

    Vector imageFiles = (Vector) session.getAttribute(SLIDESHOW_BUFFER);
    if ((imageFiles == null) || (imageFiles.size() == 0)) {
      // todo: error handling
      return;
    }

    Element slideShowElement = doc.createElement("slideShow");

    doc.appendChild(slideShowElement);

    ProcessingInstruction xslRef =
        doc.createProcessingInstruction(
            "xml-stylesheet", "type=\"text/xsl\" href=\"/webfilesys/xsl/slideShow.xsl\"");

    doc.insertBefore(xslRef, slideShowElement);

    XmlUtil.setChildText(slideShowElement, "css", userMgr.getCSS(uid), false);

    XmlUtil.setChildText(slideShowElement, "delay", Integer.toString(delay * 1000), false);

    XmlUtil.setChildText(slideShowElement, "startIdx", Integer.toString(imageIdx), false);

    XmlUtil.setChildText(slideShowElement, "autoForward", "" + autoForward, false);

    XmlUtil.setChildText(
        slideShowElement, "numberOfImages", Integer.toString(imageFiles.size()), false);

    if (readonly) {
      XmlUtil.setChildText(slideShowElement, "readonly", "true", false);
    } else {
      XmlUtil.setChildText(slideShowElement, "readonly", "false", false);
    }

    String fadeParm = getParameter("fadeInOut");
    if ((fadeParm != null) && fadeParm.equals("true")) {
      XmlUtil.setChildText(slideShowElement, "fadeInOut", "true", false);
    }

    addMsgResource("label.slideshow", getResource("label.slideshow", "Picture Slideshow"));
    addMsgResource("alt.exitslideshow", getResource("alt.exitslideshow", "exit slideshow"));
    addMsgResource("alt.pause", getResource("alt.pause", "pause slideshow"));
    addMsgResource("alt.continue", getResource("alt.continue", "continue slideshow"));
    addMsgResource("alt.back", getResource("alt.back", "previous picture"));

    this.processResponse("slideShow.xsl", false);
  }