Example #1
0
 // After all that, we start the page body and write-out the HTML for
 // the form.
 //
 // If the user is authenticated then some of the fields will be
 // already-filled-in (sender name and email).
 //
 //if ( $_POST['Action'] == "verify" ) {
 //  // We wouldn't be here if they hadn't failed
 //  $smarty->assign('verifyFailed', TRUE);
 //}
 //$smarty->assign('senderName', ($theDropbox->authorizedUser() ? $theDropbox->authorizedUserData("displayName") : htmlentities(stripslashes($_POST['senderName']))));
 //$smarty->assign('senderOrg', ($theDropbox->authorizedUser() ? $theDropbox->authorizedUserData("organization") : htmlentities(stripslashes($_POST['senderOrganization']))));
 //$smarty->assign('senderEmail', ($theDropbox->authorizedUser() ? strtolower($theDropbox->authorizedUserData("mail")) : htmlentities(stripslashes($_POST['senderEmail']))));
 $smarty->assign('senderName', $theDropbox->authorizedUser() ? $theDropbox->authorizedUserData("displayName") : (isset($_POST['senderName']) ? htmlentities(paramPrepare($_POST['senderName'])) : NULL));
 $smarty->assign('senderOrg', $theDropbox->authorizedUser() ? $theDropbox->authorizedUserData("organization") : (isset($_POST['senderOrganization']) ? htmlentities(paramPrepare($_POST['senderOrganization'])) : NULL));
 $smarty->assign('senderEmail', $theDropbox->authorizedUser() ? strtolower($theDropbox->authorizedUserData("mail")) : (isset($_POST['senderEmail']) ? htmlentities(paramPrepare($_POST['senderEmail'])) : NULL));
 if (!$theDropbox->authorizedUser()) {
     $captcha = $theDropbox->captcha();
     if ($captcha === 'areyouahuman') {
         $smarty->assign('recaptchaHTML', $ayah->getPublisherHTML());
         $smarty->assign('recaptchaDisabled', FALSE);
     } elseif ($captcha === 'google' || $captcha === '') {
         // Using Google or an old version without this set
         $reCaptchaPublicKey = $theDropbox->recaptchaPublicKey();
         if ($reCaptchaPublicKey === 'disabled') {
             $smarty->assign('recaptchaDisabled', TRUE);
         } else {
             $smarty->assign('recaptchaHTML', recaptcha_get_html($reCaptchaPublicKey));
             $smarty->assign('recaptchaDisabled', FALSE);
         }
     } else {
Example #2
0
// configuration!
//
require "../config/preferences.php";
require_once NSSDROPBOX_LIB_DIR . "Smartyconf.php";
require_once NSSDROPBOX_LIB_DIR . "NSSDropbox.php";
if ($theDropbox = new NSSDropbox($NSSDROPBOX_PREFS)) {
    $theDropbox->SetupPage();
    if ($theDropbox->authorizedUser() && $theDropbox->authorizedUserData('grantAdminPriv')) {
        if ($_POST['action'] == 'unlock') {
            // Unlock the ticked users
            $output = array();
            for ($i = 0; $i <= $_POST['unlockMax']; $i++) {
                $user = $_POST['unlocktick_' . $i];
                if ($user) {
                    // Unlock the user
                    $theDropbox->database->DBDeleteLoginlog(htmlentities(paramPrepare($user)));
                    $output[] = $user;
                }
            }
            if ($output) {
                NSSError("Unlocked " . implode(', ', $output) . ".");
            }
        }
        // Build the list of locked users
        $all = $theDropbox->database->DBLoginlogAll(time() - $theDropbox->loginFailTime());
        $failures = array();
        $lockedout = array();
        $names = array();
        $unlockMax = 0;
        $max = $theDropbox->loginFailMax();
        foreach ($all as $rec) {
Example #3
0
 public function DBAddFile2($d, $dropoffID, $tmpname, $filename, $contentLen, $mimeType, $description, $claimID)
 {
     if (!$this->DBStartTran()) {
         $d->writeToLog("failed to BEGIN transaction block while adding {$filename} to dropoff {$claimID}");
         return false;
     }
     $query = sprintf("INSERT INTO file (dID,tmpname,basename,lengthInBytes,mimeType,description) VALUES (%d,'%s','%s',%.0f,'%s','%s')", $dropoffID, $this->database->real_escape_string(basename($tmpname)), $this->database->real_escape_string(paramPrepare($filename)), $contentLen, $this->database->real_escape_string($mimeType), $this->database->real_escape_string(paramPrepare($description)));
     if (!$this->database->query($query)) {
         //  Exit gracefully -- dump database changes and remove the dropoff
         //  directory:
         $d->writeToLog("error while adding {$filename} to dropoff {$claimID}");
         if (!$this->DBRollbackTran()) {
             $d->writeToLog("failed to ROLLBACK after botched addition of {$filename} to dropoff {$claimID}");
         }
         return false;
     }
     return $this->DBCommitTran();
 }
Example #4
0
 private function userFromAuthentication()
 {
     $result = FALSE;
     if (($usernameRegex = $this->usernameRegexp()) == NULL) {
         $usernameRegex = '/^([a-zA-Z0-9][a-zA-Z0-9\\_\\.\\-\\@\\\\]*)$/';
     }
     if ($this->_authenticator && isset($_POST['uname']) && preg_match($usernameRegex, $_POST['uname']) && isset($_POST['password']) && $_POST['password']) {
         $password = $_POST['password'];
         // JKF Don't unquote the password as it might break passwords with backslashes in them. stripslashes($_POST['password']);
         $uname = paramPrepare(strtolower($_POST['uname']));
         if ($result = $this->_authenticator->authenticate($uname, $password, $this->_authorizedUserData)) {
             // They have been authenticated, yay!
             if ($this->database->DBLoginlogLength($uname, time() - $this->_loginFailTime) >= $this->_loginFailMax) {
                 // There have been too many failure attempts.
                 $this->_authorizationFailed = TRUE;
                 $this->writeToLog("authorization attempt for locked-out user {$uname}");
                 // Add a new failure record
                 $this->database->DBAddLoginlog($uname);
                 $this->_authorizedUserData = NULL;
                 $this->_authorizedUser = '';
                 $result = FALSE;
             } else {
                 // Successful login attempt with no lockout! :-)
                 $this->_authorizedUser = $uname;
                 $this->_authorizationFailed = FALSE;
                 $this->writeToLog("authorization succeeded for " . $uname);
                 // Reset their login log
                 $this->database->DBDeleteLoginlog($uname);
                 $result = TRUE;
             }
         } else {
             $this->_authorizationFailed = TRUE;
             $this->writeToLog("authorization failed for " . $uname);
             // Add a new failure record
             $this->database->DBAddLoginlog($uname);
             $result = FALSE;
         }
     } else {
         // Login attempt failed, check for bad usernames and report them.
         // But only if there is a username and a password, or else this will
         // false alarm on any page that displays the login box.
         if (isset($_POST['uname']) && $_POST['uname'] != "" && !preg_match($usernameRegex, $_POST['uname'])) {
             $this->writeToLog("Illegal username \"" . paramPrepare($_POST['uname']) . "\" attempted to login");
             $this->_authorizationFailed = TRUE;
             $this->_authorizedUserData = NULL;
             $this->_authorizedUser = '';
             $result = FALSE;
         }
     }
     return $result;
 }
Example #5
0
 public function sendVerifyEmail()
 {
     global $smarty;
     global $NSSDROPBOX_URL;
     if ($this->_dropbox->authorizedUser()) {
         // They are an authenticated user so try to get their name and email
         // from the authentication system.
         $senderName = $this->_dropbox->authorizedUserData("displayName");
         if (!$senderName) {
             $senderName = paramPrepare($_POST['senderName']);
         }
         $senderEmail = strtolower($this->_dropbox->authorizedUserData("mail"));
         if (!$senderEmail) {
             $senderEmail = paramPrepare($_POST['senderEmail']);
         }
     } else {
         // They are not an authenticated user so get their name and email
         // from the form.
         $senderName = paramPrepare($_POST['senderName']);
         $senderEmail = paramPrepare(strtolower($_POST['senderEmail']));
     }
     $senderOrganization = paramPrepare($_POST['senderOrganization']);
     // Sanitise the data
     // Still needs doing to save us from nasty crap in email!
     $senderName = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\,\\$ ]/', '', $senderName);
     $senderEmail = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\,\\$ ]/', '', $senderEmail);
     $senderOrganization = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\,\\$ ]/', '', $senderOrganization);
     if (!$senderName) {
         return FALSE;
     }
     if (!$senderEmail) {
         return FALSE;
     }
     if (!preg_match($this->_dropbox->validEmailRegexp(), $senderEmail, $emailParts)) {
         return FALSE;
     }
     // $senderEmail = $emailParts[1]."@".$emailParts[2];
     //  Insert into database:
     $auth = $this->_dropbox->WriteAuthData($senderName, $senderEmail, $senderOrganization);
     if ($auth == '') {
         NSSError("Database failure writing authentication key. Please contact your system administrator.");
         return FALSE;
     }
     $this->_senderName = $senderName;
     $this->_senderOrganization = $senderOrganization;
     $this->_senderEmail = $senderEmail;
     // If they are authenticated user, then generate a form containing
     // the data and auto-post it.
     if ($this->_dropbox->authorizedUser()) {
         Header("HTTP/1.1 302 Moved Temporarily");
         Header("Location: " . $NSSDROPBOX_URL . "dropoff.php?auth=" . $auth);
         $this->_dropbox->writeToLog(sprintf("auto-verification for logged in user %s", $senderEmail));
     } else {
         //  Construct the email notification and deliver:
         $smarty->assign('senderName', $senderName);
         $smarty->assign('senderOrg', $senderOrganization);
         $smarty->assign('senderEmail', $senderEmail);
         $smarty->assign('URL', $NSSDROPBOX_URL . "dropoff.php?auth={$auth}");
         $emailSubject = $smarty->getConfigVariable('VerifyEmailSubject');
         $success = $this->_dropbox->deliverEmail($senderEmail, $smarty->getConfigVariable('EmailSenderAddress'), $emailSubject, $smarty->fetch('verify_email.tpl'));
         if ($success) {
             $this->_dropbox->writeToLog(sprintf("address verification email delivered successfully to %s", $senderEmail));
         } else {
             $this->_dropbox->writeToLog(sprintf("address verification email not delivered successfully to %s", $senderEmail));
             return FALSE;
         }
     }
     // Everything worked and the mail was sent!
     return TRUE;
 }
Example #6
0
 private function initWithFormData($recipEmail)
 {
     global $NSSDROPBOX_URL;
     // They are an authenticated user so try to get their name and email
     // from the authentication system.
     $senderName = $this->_dropbox->authorizedUserData("displayName");
     if (!$senderName) {
         $senderName = paramPrepare($_POST['senderName']);
     }
     $senderEmail = strtolower($this->_dropbox->authorizedUserData("mail"));
     if (!$senderEmail) {
         $senderEmail = paramPrepare($_POST['senderEmail']);
     }
     $senderOrganization = paramPrepare($_POST['senderOrganization']);
     $recipName = paramPrepare($_POST['recipName']);
     # This is now read from a parameter passed to us
     #$recipEmail = stripslashes(strtolower($_POST['recipEmail']));
     // SLASH $note = stripslashes($_POST['note']);
     $note = $_POST['note'];
     $subject = paramPrepare($_POST['subject']);
     // Sanitise the data
     $senderName = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\, ]/', '', $senderName);
     $senderEmail = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\, ]/', '', $senderEmail);
     $senderOrganization = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\, ]/', '', $senderOrganization);
     $recipName = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\, ]/', '', $recipName);
     $recipEmail = preg_replace('/[^a-zA-Z0-9\\.\\-\\_\\+\\"\'\\@\\/\\:\\&\\, ]/', '', $recipEmail);
     if (!$senderName) {
         return "You must specify your name in the form.  Use the back button in your browser to go back and fix this omission before trying again.";
     }
     if (!$senderEmail) {
         return "You must specify your own email address in the form.  Use the back button in your browser to go back and fix this omission before trying again.";
     }
     if (!$recipName) {
         return "You must specify the recipient's name in the form. Use the back button in your browser to go back and fix this omission before trying again.";
     }
     if (!$recipEmail) {
         return "You must specify the recipient's email address in the form. Use the back button in your browser to go back and fix this omission before trying again.";
     }
     if (!preg_match($this->_dropbox->validEmailRegexp(), $senderEmail, $emailParts)) {
         return "Your email address you entered was invalid.  Use the back button in your browser to go back and fix this omission before trying again.";
     }
     $senderEmail = $emailParts[1] . "@" . $emailParts[2];
     if (!preg_match($this->_dropbox->validEmailRegexp(), $recipEmail, $emailParts)) {
         return "The recipient's email address you entered was invalid.  Use the back button in your browser to go back and fix this omission before trying again.";
     }
     $recipEmail = $emailParts[1] . "@" . $emailParts[2];
     // Check the length of the subject.
     $subjectlength = strlen($subject);
     $maxlen = $this->_dropbox->maxsubjectlength();
     if ($subjectlength > $maxlen) {
         return sprintf($smarty->getConfigVariable('ErrorSubjectTooLong'), $subjectlength, $maxlen);
     }
     // The subject line of the files will be a "Re: +subject"
     $reSubject = trim($subject);
     if (!preg_match('/^Re:/i', $reSubject)) {
         $reSubject = 'Re: ' . $reSubject;
     }
     //  Insert into database:
     $words = $this->_dropbox->WriteReqData($senderName, $senderEmail, $senderOrganization, $recipName, $recipEmail, $note, $reSubject);
     if ($words == '') {
         return "Database failure writing request information. Please contact your system administrator.";
     } else {
         $this->_words = $words;
         $this->_auth = preg_replace('/[^a-zA-Z0-9]/', '', $words);
         $this->_senderName = $senderName;
         $this->_senderEmail = $senderEmail;
         $this->_senderOrg = $senderOrg;
         $this->_recipName = $recipName;
         $this->_recipEmail = $recipEmail;
         $this->_note = $note;
         $this->_subject = $subject;
     }
     return "";
 }
Example #7
0
     exit;
 }
 // They are either trying to submit or display the "New Request" form,
 // so they must be logged in.
 if (!$theDropbox->authorizedUser()) {
     $theDropbox->SetupPage();
     NSSError($smarty->getConfigVariable('ErrorNotLoggedIn'), "Access Denied");
     $smarty->display('error.tpl');
     exit;
 }
 if ($_POST['Action'] == "send") {
     // Read the contents of the form, and send the email of it all
     // Loop through all the email addresses we were given, creating a new
     // Req object for each one. Then piece together the bits of the output
     // we need to make the resulting web page look pretty.
     $emailAddrs = preg_split('/[;, ]+/', paramPrepare(strtolower($_POST['recipEmail'])), NULL, PREG_SPLIT_NO_EMPTY);
     $wordList = array();
     $emailList = array();
     // This is the output list, separate for safety
     foreach ($emailAddrs as $re) {
         $req = new Req($theDropbox, $re);
         if ($req->formInitError() != "") {
             $theDropbox->SetupPage();
             NSSError($req->formInitError(), "Request error");
             $smarty->display('error.tpl');
             exit;
         }
         if (!$req->sendReqEmail()) {
             $theDropbox->SetupPage();
             NSSError("Sending the request email failed.", "Email error");
             $smarty->display('error.tpl');
Example #8
0
 private function initWithFormData()
 {
     global $NSSDROPBOX_URL;
     global $smarty;
     // Start off with the data from the form posting, overwriting it with
     // stored data as necessary.
     $senderName = paramPrepare($_POST['senderName']);
     $senderEmail = paramPrepare(strtolower($_POST['senderEmail']));
     $senderOrganization = paramPrepare($_POST['senderOrganization']);
     // SLASH $note = stripslashes($_POST['note']);
     $note = $_POST['note'];
     $expiry = 0;
     // If they have a valid req key, then they don't need to be verified
     // or logged in.
     $reqSubject = '';
     $req = '';
     if ($_POST['req'] != '') {
         $dummy = '';
         $recipName = '';
         // Never actually use this
         $recipEmail = '';
         // Never actually use this
         $req = preg_replace('/[^a-zA-Z0-9]/', '', $_POST['req']);
         if ($this->_dropbox->ReadReqData($req, $recipName, $recipEmail, $senderOrganization, $senderName, $senderEmail, $dummy, $reqSubject, $expiry)) {
             if ($expiry < time()) {
                 $this->_dropbox->DeleteReqData($req);
                 return $smarty->getConfigVariable('ErrorReadAuth');
             }
             // It was a valid req key, so leave $req alone (and true).
             $reqSubject = trim($reqSubject);
             $this->_subject = $reqSubject;
         } else {
             // Invalid request code, so ignore them
             $req = FALSE;
             $reqSubject = '';
         }
     }
     // It is not a request, or not a valid request
     if ($req == '') {
         // So now they must be authorized as it's not a request
         if (!$this->_dropbox->authorizedUser()) {
             $auth = $_POST['auth'];
             // JKF Get the above from the auth database
             // JKF Fail if it doesn't exist or it's a pickup auth not a dropoff
             $authdatares = $this->_dropbox->ReadAuthData($auth, $senderName, $senderEmail, $senderOrganization, $expiry);
             if (!$authdatares) {
                 return $smarty->getConfigVariable('ErrorReadAuth');
             }
             // If the email is blank (and name has no spaces) then it's a pickup.
             // In a pickup, the name is used as the sender's IP address.
             if (!preg_match('/ /', $senderName) && $senderEmail == '') {
                 return $smarty->getConfigVariable('ErrorReadAuth');
             }
             if ($expiry < time()) {
                 $this->_dropbox->DeleteAuthData($auth);
                 return $smarty->getConfigVariable('ErrorReadAuth');
             }
         } else {
             // Logged-in user so just read their data
             $senderName = $this->_dropbox->authorizedUserData("displayName");
             $senderOrganization = paramPrepare($_POST['senderOrganization']);
             $senderEmail = trim($this->_dropbox->authorizedUserData("mail"));
         }
     }
     // Erase the note if it is just white space.
     if (preg_match('/^\\s*$/', $note)) {
         $note = "";
     }
     // Check the length of the note.
     $notelength = strlen($note);
     $maxlen = $this->_dropbox->maxnotelength();
     if ($notelength > $maxlen) {
         return sprintf($smarty->getConfigVariable('ErrorNoteTooLong'), $notelength, $maxlen);
     }
     $confirmDelivery = $_POST['confirmDelivery'] ? TRUE : FALSE;
     $informRecipients = $_POST['informRecipients'] ? TRUE : FALSE;
     $recipients = array();
     $recipIndex = -1;
     // <0 => no recipients found
     $arraykeys = array_keys($_POST);
     foreach ($arraykeys as $arraykey) {
         $matches = array();
         if (preg_match('/^recipient_(\\d+)/', $arraykey, $matches)) {
             $recipIndex = $matches[1];
             //while ( array_key_exists('recipient_'.$recipIndex,$_POST) ) {
             $recipName = paramPrepare($_POST['recipName_' . $recipIndex]);
             $recipEmail = paramPrepare($_POST['recipEmail_' . $recipIndex]);
             if ($recipName || $recipEmail) {
                 //  Take the email to purely lowercase for simplicity:
                 $recipEmail = strtolower($recipEmail);
                 //  Just a username?  We add an implicit "@domain.com" for these and validate them!
                 $emailParts[1] = NULL;
                 $emailParts[2] = NULL;
                 if (preg_match('/\\@/', $recipEmail)) {
                     // Has an @ sign so is an email address. Must be valid!
                     if (!preg_match($this->_dropbox->validEmailRegexp(), $recipEmail, $emailParts)) {
                         return sprintf($smarty->getConfigVariable('ErrorBadRecipient'), $recipEmail);
                     }
                 } else {
                     // No @ sign so just stick default domain in right hand side
                     $emailParts[1] = $recipEmail;
                     $emailParts[2] = $this->_dropbox->defaultEmailDomain();
                 }
                 $recipEmailDomain = $emailParts[2];
                 // Don't think this line is needed any more, but harmless
                 $recipEmail = $emailParts[1] . "@" . $emailParts[2];
                 //  Look at the recipient's email domain; un-authenticated users can only deliver
                 //  to the dropbox's domain:
                 // JKF Changed checkRecipientDomain to return true if it's a local user
                 if (!$this->_dropbox->authorizedUser() && !$this->_dropbox->checkRecipientDomain($recipEmail)) {
                     return $smarty->getConfigVariable('ErrorWillNotSend');
                 }
                 $recipients[] = array($recipName ? $recipName : "", $recipEmail);
             } else {
                 if ($recipName && !$recipEmail) {
                     return $smarty->getConfigVariable('ErrorNoEmail');
                 }
             }
             //$recipIndex++;
         }
     }
     // No recipients found?
     if ($recipIndex < 0) {
         return $smarty->getConfigVariable('ErrorNoEmail');
     }
     //
     //  Check for an uploaded CSV/TXT file containing addresses:
     //
     if ($_FILES['recipient_csv']['tmp_name']) {
         if ($_FILES['recipient_csv']['error'] != UPLOAD_ERR_OK) {
             $error = sprintf($smarty->getConfigVariable('ErrorWhileUploading'), $_FILES['recipient_csv']['name']);
             switch ($_FILES['recipient_csv']['error']) {
                 case UPLOAD_ERR_INI_SIZE:
                     $error .= $smarty->getConfigVariable('ErrorRecipientsTooBigForPHP');
                     break;
                 case UPLOAD_ERR_FORM_SIZE:
                     $error .= sprintf($smarty->getConfigVariable('ErrorRecipientsFileTooBig'), $this->_dropbox->maxBytesForFile());
                     break;
                 case UPLOAD_ERR_PARTIAL:
                     $error .= $smarty->getConfigVariable('ErrorRecipientsPartialUpload');
                     break;
                 case UPLOAD_ERR_NO_FILE:
                     $error .= $smarty->getConfigVariable('ErrorNoRecipientsFile');
                     break;
                 case UPLOAD_ERR_NO_TMP_DIR:
                     $error .= $smarty->getConfigVariable('ErrorNoTemp');
                     break;
                 case UPLOAD_ERR_CANT_WRITE:
                     $error .= $smarty->getConfigVariable('ErrorBadTemp');
                     break;
             }
             return $error;
         }
         //  Parse the CSV/TXT file:
         if ($csv = fopen($_FILES['recipient_csv']['tmp_name'], 'r')) {
             while ($fields = fgetcsv($csv)) {
                 if ($fields[0] !== NULL) {
                     //  Got one; figure out which field is an email address:
                     foreach ($fields as $recipEmail) {
                         //  Take the email to purely lowercase for simplicity:
                         $recipEmail = strtolower($recipEmail);
                         // JKF Don't allow just usernames in CSV file!
                         if (!preg_match($this->_dropbox->validEmailRegexp(), $recipEmail, $emailParts)) {
                             continue;
                         }
                         $recipEmailDomain = $emailParts[2];
                         $recipEmail = $emailParts[1] . "@" . $emailParts[2];
                         //  Look at the recipient's email domain;
                         //  un-authenticated users can only deliver to the dropbox's
                         //  domain:
                         if (!$this->_dropbox->authorizedUser() && !$this->_dropbox->checkRecipientDomain($recipEmail)) {
                             return $smarty->getConfigVariable('ErrorWillNotSend');
                         }
                         // $recipients[] = array(( $recipName ? $recipName : "" ),$recipEmail);
                         $recipients[] = array("", $recipEmail);
                     }
                 }
             }
             fclose($csv);
         } else {
             return $smarty->getConfigVariable('ErrorBadRecipientsFile');
         }
         //$fileCount = count( array_keys($_FILES) ) - 1;
         //} else {
         //  //$fileCount = count( array_keys($_FILES) );
         //  $fileCount = numberOfFiles();
     }
     // If it's in response to a request, and the recipient override
     // is set, then zap the first recipient and replace with ours.
     $reqRecipient = $this->_dropbox->reqRecipient();
     if ($req != '' && $reqRecipient != '') {
         $recipients[0][1] = $reqRecipient;
     }
     // Reduce the list of recipients to those with unique email addresses
     uniqueifyRecipients($recipients);
     //  Confirm that all fields are present and accounted for:
     $fileCount = $this->numberOfFiles();
     if ($fileCount == 0) {
         return $smarty->getConfigVariable('ErrorNoFiles');
     }
     //  Now make sure each file was uploaded successfully, isn't too large,
     //  and that the total size of the upload isn't over capacity:
     $i = 1;
     $totalBytes = 0.0;
     $totalFiles = 0;
     // while ( $i <= $fileCount ) {
     while ($i <= $this->maxFilesKey) {
         $key = "file_" . $i;
         if (array_key_exists('file_select_' . $i, $_POST) && $_POST['file_select_' . $i] != "-1") {
             $totalFiles++;
         } elseif ($_FILES[$key]['name']) {
             if ($_FILES[$key]['error'] != UPLOAD_ERR_OK) {
                 $error = sprintf($smarty->getConfigVariable('ErrorWhileUploading'), $_FILES[$key]['name']);
                 switch ($_FILES[$key]['error']) {
                     case UPLOAD_ERR_INI_SIZE:
                         $error .= $smarty->getConfigVariable('ErrorTooBigForPHP');
                         break;
                     case UPLOAD_ERR_FORM_SIZE:
                         $error .= sprintf($smarty->getConfigVariable('ErrorFileTooBig'), $this->_dropbox->maxBytesForFile());
                         break;
                     case UPLOAD_ERR_PARTIAL:
                         $error .= $smarty->getConfigVariable('ErrorPartialUpload');
                         break;
                     case UPLOAD_ERR_NO_FILE:
                         $error .= $smarty->getConfigVariable('ErrorNoFile');
                         break;
                     case UPLOAD_ERR_NO_TMP_DIR:
                         $error .= $smarty->getConfigVariable('ErrorNoTemp');
                         break;
                     case UPLOAD_ERR_CANT_WRITE:
                         $error .= $smarty->getConfigVariable('ErrorBadTemp');
                         break;
                 }
                 return $error;
             }
             if (($bytes = $_FILES[$key]['size']) < 0) {
                 //  Grrr...stupid 32-bit nonsense.  Convert to the positive
                 //  value float-wise:
                 $bytes = ($bytes & 0x7fffffff) + 2147483648.0;
             }
             if ($bytes > $this->_dropbox->maxBytesForFile()) {
                 return sprintf($smarty->getConfigVariable('ErrorNamedFileTooBig'), $_FILES[$key]['name'], NSSFormattedMemSize($this->_dropbox->maxBytesForFile()));
             }
             if (($totalBytes += $bytes) > $this->_dropbox->maxBytesForDropoff()) {
                 return sprintf($smarty->getConfigVariable('ErrorDropoffTooBig'), $_FILES[$key]['name'], NSSFormattedMemSize($this->_dropbox->maxBytesForDropoff()));
             }
             // MyZendTo: If they don't have enough quota left, disallow it
             if (preg_match('/^[yYtT1]/', MYZENDTO)) {
                 $QuotaLeft = $this->_dropbox->database->DBRemainingQuota($this->_dropbox->authorizedUser());
                 if ($totalBytes > $QuotaLeft) {
                     return sprintf($smarty->getConfigVariable('ErrorDropoffQuota'), NSSFormattedMemSize($totalBytes - $QuotaLeft));
                 }
             }
             $totalFiles++;
         }
         $i++;
     }
     //if ( $totalBytes == 0 ) {
     if ($totalFiles == 0) {
         return $smarty->getConfigVariable('ErrorNoFiles');
     }
     // JKF Start
     //
     // Call clamdscan on all the files, fail if they are infected
     // If the name of the scanner is set to '' or 'DISABLED' then skip this.
     $clamdscancmd = $this->_dropbox->clamdscan();
     if ($clamdscancmd != 'DISABLED') {
         $ccfilecount = 1;
         $ccfilelist = '';
         $foundsometoscan = FALSE;
         while ($ccfilecount <= $this->maxFilesKey) {
             // For every possible file, we only add it to the list of clamd
             // targets if it's not a library file (assumed clean), but it is
             // an uploaded file, and that file-slot in the form was used.
             $filekey = "file_" . $ccfilecount;
             $selectkey = "file_select_" . $ccfilecount;
             if (!(array_key_exists($selectkey, $_POST) && $_POST[$selectkey] != "-1") && array_key_exists($filekey, $_FILES) && array_key_exists('tmp_name', $_FILES[$filekey]) && $_FILES[$filekey]['tmp_name'] !== '') {
                 // and is not blank
                 $ccfilelist .= ' ' . $_FILES[$filekey]['tmp_name'];
                 $foundsometoscan = TRUE;
             }
             $ccfilecount++;
         }
         if ($foundsometoscan) {
             // Don't do any of this if they uploaded nothing
             exec("/bin/chmod go+r " . $ccfilelist);
             // Need clamd to read them!
             $clamdinfected = 0;
             $clamdoutput = array();
             $clamcmd = exec($clamdscancmd . $ccfilelist, $clamdoutput, $clamdinfected);
             if ($clamdinfected == 1) {
                 return $smarty->getConfigVariable('ErrorVirusFound');
             }
             if ($clamdinfected == 2) {
                 return $smarty->getConfigVariable('ErrorVirusFailed');
             }
         }
     }
     //
     // JKF End
     if (!$senderName) {
         return $smarty->getConfigVariable('ErrorSenderName');
     }
     if (!$senderEmail) {
         return $smarty->getConfigVariable('ErrorSenderEmail');
     }
     if (!preg_match($this->_dropbox->validEmailRegexp(), $senderEmail, $emailParts)) {
         return $smarty->getConfigVariable('ErrorSenderBadEmail');
     }
     $senderEmail = $emailParts[1] . "@" . $emailParts[2];
     //  Invent a passcode and claim ID:
     $claimPasscode = NSSGenerateCode();
     $claimID = NULL;
     $claimDir = NULL;
     if (!$this->_dropbox->directoryForDropoff($claimID, $claimDir)) {
         return $smarty->getConfigVariable('ErrorUniqueDir');
     }
     //  Insert into database:
     if ($this->_dropbox->database->DBStartTran()) {
         if ($dropoffID = $this->_dropbox->database->DBAddDropoff($claimID, $claimPasscode, $this->_dropbox->authorizedUser(), $senderName, $senderOrganization, $senderEmail, $_SERVER['REMOTE_ADDR'], $confirmDelivery, timestampForTime(time()), $note)) {
             //  Add recipients:
             if (!$this->_dropbox->database->DBAddRecipients($recipients, $dropoffID)) {
                 $this->_dropbox->database->DBRollbackTran();
                 return $smarty->getConfigVariable('ErrorStoreRecipients');
             }
             //  Process the files:
             $i = 1;
             $realFileCount = 0;
             $tplFiles = array();
             // These are the file hashes we process in tpl.
             //while ( $i <= $fileCount ) {
             while ($i <= $this->maxFilesKey) {
                 $key = "file_" . $i;
                 $selectkey = 'file_select_' . $i;
                 if (array_key_exists($selectkey, $_POST) && $_POST[$selectkey] != "-1") {
                     // It's a library file.
                     // Get the name of the library file they want (safely)
                     // by removing all "../" elements and things like it
                     $libraryfile = preg_replace('/\\.\\.[:\\/\\\\]/', '', $_POST[$selectkey]);
                     $libraryfile = paramPrepare($libraryfile);
                     // Generate a random filename (collisions are very unlikely)
                     $tmpname = mt_rand(10000000, 99999999);
                     // Link in the library file
                     symlink($this->_dropbox->libraryDirectory() . '/' . $libraryfile, $claimDir . '/' . $tmpname);
                     // Now strip off the possible subdirectory name as we only
                     // want it in the symlink and not after that.
                     $libraryfilesize = filesize($this->_dropbox->libraryDirectory() . '/' . $libraryfile);
                     $libraryfile = trim(preg_replace('/^.*\\//', '', $libraryfile));
                     // We use this a few times
                     $librarydesc = paramPrepare(trim($_POST["desc_" . $i]));
                     //  Add to database:
                     if (!$this->_dropbox->database->DBAddFile1($dropoffID, $tmpname, $libraryfile, $libraryfilesize, "application/octet-stream", $librarydesc)) {
                         //  Exit gracefully -- dump database changes and remove the dropoff
                         //  directory:
                         $this->_dropbox->writeToLog("error while adding dropoff library file to database for {$claimID}");
                         if (!rmdir_r($claimDir)) {
                             $this->_dropbox->writeToLog("unable to remove {$claimDir} -- orphaned!!");
                         }
                         if (!$this->_dropbox->database->DBRollbackTran()) {
                             $this->_dropbox->writeToLog("failed to ROLLBACK after botched dropoff:  {$claimID}");
                             $this->_dropbox->writeToLog("there may be orphans");
                         }
                         return sprintf($smarty->getConfigVariable('ErrorNamedStore'), $libraryfile);
                     }
                     //  That's right, one more file!
                     $tplFiles[$realFileCount] = array();
                     $tplFiles[$realFileCount]['name'] = $libraryfile;
                     $tplFiles[$realFileCount]['type'] = 'Library';
                     $tplFiles[$realFileCount]['size'] = NSSFormattedMemSize($libraryfilesize);
                     $tplFiles[$realFileCount]['description'] = $librarydesc;
                     $realFileCount++;
                     // Update the description in the library index
                     $this->_dropbox->database()->DBUpdateLibraryDescription($libraryfile, $librarydesc);
                 } elseif ($_FILES[$key]['name']) {
                     // It's an uploaded file
                     $tmpname = basename($_FILES[$key]['tmp_name']);
                     // Get file size from local copy, not what browser told us
                     $bytes = filesize($_FILES[$key]['tmp_name']);
                     if (!move_uploaded_file($_FILES[$key]['tmp_name'], $claimDir . "/" . $tmpname)) {
                         //  Exit gracefully -- dump database changes and remove the dropoff
                         //  directory:
                         $this->_dropbox->writeToLog("error while storing dropoff files for {$claimID}");
                         if (!rmdir_r($claimDir)) {
                             $this->_dropbox->writeToLog("unable to remove {$claimDir} -- orphaned!!");
                         }
                         if (!$this->_dropbox->database->DBRollbackTran()) {
                             $this->_dropbox->writeToLog("failed to ROLLBACK after botched dropoff:  {$claimID}");
                             $this->_dropbox->writeToLog("there may be orphans");
                         }
                         return sprintf($smarty->getConfigVariable('ErrorNamedDrop'), $_FILES[$key]['name']);
                     }
                     //if ( ($bytes = $_FILES[$key]['size']) < 0 ) {
                     //  //  Grrr...stupid 32-bit nonsense.  Convert to the positive
                     //  //  value float-wise:
                     //  $bytes = ($bytes & 0x7FFFFFFF) + 2147483648.0;
                     //}
                     //  Add to database:
                     if (!$this->_dropbox->database->DBAddFile1($dropoffID, $tmpname, paramPrepare($_FILES[$key]['name']), $bytes, $_FILES[$key]['type'] ? $_FILES[$key]['type'] : "application/octet-stream", paramPrepare($_POST["desc_" . $i]))) {
                         //  Exit gracefully -- dump database changes and remove the dropoff
                         //  directory:
                         $this->_dropbox->writeToLog("error while adding dropoff file to database for {$claimID}");
                         if (!rmdir_r($claimDir)) {
                             $this->_dropbox->writeToLog("unable to remove {$claimDir} -- orphaned!!");
                         }
                         if (!$this->_dropbox->database->DBRollbackTran()) {
                             $this->_dropbox->writeToLog("failed to ROLLBACK after botched dropoff:  {$claimID}");
                             $this->_dropbox->writeToLog("there may be orphans");
                         }
                         return sprintf($smarty->getConfigVariable('ErrorNamedStore'), $_FILES[$key]['name']);
                     }
                     //  That's right, one more file!
                     $tplFiles[$realFileCount] = array();
                     $tplFiles[$realFileCount]['name'] = paramPrepare($_FILES[$key]['name']);
                     $tplFiles[$realFileCount]['type'] = $_FILES[$key]['type'];
                     // Get filesize from local copy, not browser $tplFiles[$i]['size'] = NSSFormattedMemSize($_FILES[$key]['size']);
                     $tplFiles[$realFileCount]['size'] = NSSFormattedMemSize($bytes);
                     $tplFiles[$realFileCount]['description'] = paramPrepare($_POST["desc_" . $i]);
                     $realFileCount++;
                 }
                 $i++;
             }
             //  Once we get here, it's time to commit the stuff to the database:
             $this->_dropbox->database->DBCommitTran();
             $this->_dropoffID = $dropoffID;
             //  At long last, fill-in the fields:
             $this->_claimID = $claimID;
             $this->_claimPasscode = $claimPasscode;
             $this->_claimDir = $claimDir;
             $this->_authorizedUser = $this->_dropbox->authorizedUser();
             $this->_note = $note;
             $this->_senderName = $senderName;
             $this->_senderOrganization = $senderOrganization;
             $this->_senderEmail = $senderEmail;
             $this->_senderIP = $_SERVER['REMOTE_ADDR'];
             $senderIP = $_SERVER['REMOTE_ADDR'];
             $senderHost = gethostbyaddr($_SERVER['REMOTE_ADDR']);
             if ($senderHost != '') {
                 $senderHost = '(' . $senderHost . ')';
             }
             $this->_confirmDelivery = $confirmDelivery;
             $this->_informRecipients = $informRecipients;
             $this->_created = getdate();
             $this->_recipients = $recipients;
             // This Drop-off request has been fulfilled, so kill the keys
             // to stop playback attacks.
             if ($req) {
                 $this->_dropbox->DeleteReqData($req);
             }
             if ($auth) {
                 $this->_dropbox->DeleteAuthData($auth);
             }
             // Work out the real email subject line.
             if ($reqSubject != '') {
                 $emailSubject = $reqSubject;
             } else {
                 if ($realFileCount == 1) {
                     $emailSubject = sprintf($smarty->getConfigVariable('DropoffEmailSubject1'), $senderName);
                 } else {
                     $emailSubject = sprintf($smarty->getConfigVariable('DropoffEmailSubject2'), $senderName);
                 }
             }
             //  Construct the email notification and deliver:
             $smarty->assign('senderName', $senderName);
             $smarty->assign('senderOrg', $senderOrganization);
             $smarty->assign('senderEmail', $senderEmail);
             $smarty->assign('senderIP', $senderIP);
             $smarty->assign('senderHost', $senderHost);
             $smarty->assign('note', trim($note));
             $smarty->assign('subject', $emailSubject);
             $smarty->assign('now', timestampForTime(time()));
             $smarty->assign('claimID', $claimID);
             $smarty->assign('claimPasscode', $claimPasscode);
             $smarty->assign('fileCount', $realFileCount);
             $smarty->assign('retainDays', $this->_dropbox->retainDays());
             $smarty->assignByRef('files', $tplFiles);
             $emailTemplate = $smarty->fetch('dropoff_email.tpl');
             // Update the address book entries for this user
             $this->_dropbox->updateAddressbook($recipients);
             // Inform all the recipients by email if they want me to
             if ($informRecipients) {
                 // Do we want to Bcc the sender as well?
                 $emailBcc = '';
                 if ($this->_dropbox->bccSender()) {
                     // and don't forget to encode it if there are intl chars in it
                     if (preg_match('/[^\\x00-\\x7f]/', $senderEmail)) {
                         $emailBcc = "Bcc: =?UTF-8?B?" . base64_encode(html_entity_decode($senderEmail)) . "?=" . PHP_EOL;
                     } else {
                         $emailBcc = "Bcc: {$senderEmail}" . PHP_EOL;
                     }
                 }
                 // Make the mail come from the sender, not ZendTo
                 foreach ($recipients as $recipient) {
                     // In MyZendTo, don't send email to myself
                     if (preg_match('/^[yYtT1]/', MYZENDTO) && $senderEmail != $recipient[1] || preg_match('/^[^yYtT1]/', MYZENDTO)) {
                         $emailContent = preg_replace('/__EMAILADDR__/', urlencode($recipient[1]), $emailTemplate);
                         $success = $this->_dropbox->deliverEmail($recipient[1], $senderEmail, $emailSubject, $emailContent, $emailBcc);
                         $emailBcc = '';
                         // Only Bcc the sender on the first email out
                         if (!$success) {
                             $this->_dropbox->writeToLog(sprintf("notification email not delivered successfully to %s for claimID {$claimID}", $recipient[1]));
                         } else {
                             $this->_dropbox->writeToLog(sprintf("notification email delivered successfully to %s for claimID {$claimID}", $recipient[1]));
                         }
                     }
                 }
             }
             //  Log our success:
             $this->_dropbox->writeToLog(sprintf("{$senderName} <{$senderEmail}> => {$claimID} [%s]", $realFileCount == 1 ? "1 file" : "{$realFileCount} files"));
         } else {
             return $smarty->getConfigVariable('ErrorAddDropoff');
         }
     } else {
         return $smarty->getConfigVariable('ErrorBeginTransaction');
     }
     return NULL;
 }