&$entry) { if ($now - $limit_time > $entry['time']) { // Delete entries that are older than $limit_time unset($ips[$key]); } else if ($entry['ip'] === $ip) { // IP matches, and entry under $limit_time $ip_unknown = FALSE; if ($entry['hits'] >= $limit_hits) { // Try limit exceeded, iterate and set abort variable $entry['hits'] = $entry['hits'] + 1; $limit_exceeded = TRUE; if ($entry['hits'] > $limit_spam) { // IP exceeds spam limit if (! file_exists($spamdb)) { touch($spamdb); } $realip = $_SERVER['REMOTE_ADDR']; $spammer = file_get_contents($spamdb); $pattern = preg_quote($realip); if (! preg_match("/$pattern/", $spammer, $match)) { file_put_contents($spamdb, $realip . "\n", FILE_APPEND | LOCK_EX); } } } else { // Try limit not exceeded, just iterate $entry['hits'] = $entry['hits'] + 1; } } } // Extend IP database if this IP was unknown if ($ip_unknown) { $ips[] = array("time" => $now, "ip" => $ip, "hits" => 1); } // Write IP database back to file file_put_contents($ipdb, json_encode($ips, JSON_PRETTY_PRINT), LOCK_EX); unset($ips); // Abort if IP limit is exceeded if ($limit_exceeded) { $output .= "Too many submits with your IP. Please try again in a few minutes."; show_page($output, 1); } /////////////////////// /// FORM EVALUATION /// /////////////////////// // Get basic info from form if ($_SERVER['REQUEST_METHOD'] === 'POST') { $action = isset($_POST['action']) ? $_POST['action'] : false; } else { $action = isset($_GET['action']) ? $_GET['action'] : false; } // Continue only if action = sign/confirmation // Depending on action, get important variables if(empty($action)) { $output .= "No action defined."; show_page($output, 1); } else if ($action === "sign") { // sign $name = isset($_POST['name']) ? $_POST['name'] : false; $email = isset($_POST['email']) ? $_POST['email'] : false; $country = isset($_POST['country']) ? $_POST['country'] : false; $zip = isset($_POST['zip']) ? $_POST['zip'] : false; $comment = isset($_POST['comment']) ? $_POST['comment'] : false; $permPriv = isset($_POST['permissionPriv']) ? $_POST['permissionPriv'] : false; $permNews = isset($_POST['permissionNews']) ? $_POST['permissionNews'] : false; $permPub = isset($_POST['permissionPub']) ? $_POST['permissionPub'] : false; // Check for missing required fields if(empty($name) || empty($email) || empty($permPriv)) { $output .= "At least one required variable is empty."; show_page($output, 1); } } else if ($action === "confirm") { // confirm $confirmcode = isset($_GET['code']) ? $_GET['code'] : false; $confirmid = isset($_GET['id']) ? $_GET['id'] : false; // Check for missing required fields if(empty($confirmcode) || empty($confirmid)) { $output .= "Confirmation code or ID is missing."; show_page($output, 1); } } else { // invalid $output .= "Invalid action."; show_page($output, 1); } // Validate input //TODO /////////////// /// SIGNING /// /////////////// if ($action === "sign") { read_db($db); // Test whether email is a duplicate $total = count($data); for ($row = 0; $row < $total; $row++) { if ($email === $data[$row]['email']) { $output .= "We already received a signature with this email address."; show_page($output, 1); } } // Take sequential ID $id = $total; // Create a random string for email verification $code = rand(1000000000,9999999999) . uniqid(); $codeid = $id + $codemod; // this is to obfuscate the real ID of the user if we don't want to publish this number // Append new signature to array $data[] = array("id" => $id, "name" => $name, "email" => $email, "country" => $country, "zip" => $zip, "comment" => $comment, "permPriv" => $permPriv, "permNews" => $permNews, "permPub" => $permPub, "code" => $code, "confirmed" => "no"); // Encode to JSON again and write to file $allsig = json_encode($data, JSON_PRETTY_PRINT); file_put_contents($db, $allsig, LOCK_EX); unset($allsig); $mail = new PHPMailer; $mail->isSMTP(); $mail->Host = "mail.fsfe.org"; $mail->setFrom('noreply@fsfe.org', 'Public Money, Public Code'); // Send email asking for confirmation $mail->addAddress($email); $mail->Subject = "One step left to sign the \"Public Money - Public Code\" letter"; $mail->Body = "Dear $name, \r\n\r\n" . "Thank you for signing the open \"Public Money - Public Code\" letter! \r\n\r\n" . "In order to confirm your signature, please visit following link:\r\n" . "$selfurl?action=confirm&id=$codeid&code=$code \r\n\r\n" . "If your confirmation succeeds, your signature will appear on the website within the next few hours."; $mail->Send(); $output .= "Thank you for signing our open letter!

"; $output .= "We just sent an email to your address ($email) for you to confirm your signature."; show_page($output, 0); } else if ($action === "confirm") { //////////////////// /// CONFIRMATION /// //////////////////// $id = $confirmid - $codemod; // substract the obfuscation number from the given ID if ($id < 0) { // $confirmid is less than $codemod $output .= "Invalid signature ID."; show_page($output, 1); } read_db($db); if (empty($data[$id])) { // there is no array element with this ID $output .= "The signature ID does not exist."; show_page($output, 1); } $email = $data[$id]['email']; // Get the user's email in case we need it $code = $data[$id]['code']; // The confirmation code according to the DB $confirmed = $data[$id]['confirmed']; // The current confirmation status // Check whether the confirmation code is what we saved in the DB if ($confirmed === "no") { if ($confirmcode === $code) { // Set the user's confirmation key to "yes" $data[$id]['confirmed'] = "yes"; // Encode to JSON again and write to file $allsig = json_encode($data, JSON_PRETTY_PRINT); // TODO: JSON_PRETTY_PRINT could be turned off to make file smaller file_put_contents($db, $allsig, LOCK_EX); unset($allsig); $output .= "Your email address has been confirmed.

"; $output .= "Thank you for signing the open letter! Your signature will appear in the signature list within the next hours."; show_page($output, 0); } else { $output .= "The provided confirmation code is incorrect."; show_page($output, 1); } } else if ($confirmed === "yes") { $output .= "This email address is already confirmed. It can take a few hours until your signature appears in the signature list."; show_page($output, 1); } else { $output .= "This signature ID does not exist or the confirmation status is broken."; show_page($output, 1); } } // END confirm //////////////// // FUNCTIONS /// //////////////// // Read signatures database (should only be called if really needed) function read_db($db) { global $data; // declare $data a global variable to access it outside this function if (! file_exists($db)) { touch($db); } $file = file_get_contents($db, true); $data = json_decode($file, true); unset($file); } // Read IP database function read_ips($ipdb) { global $ips; // declare $data a global variable to access it outside this function if (! file_exists($ipdb)) { touch($ipdb); } $file = file_get_contents($ipdb, true); $ips = json_decode($file, true); unset($file); } // Replace a given placeholder in a template HTML page with given content function replace_page($template, $placeholder, $content){ $vars = array($placeholder=>$content); return str_replace(array_keys($vars), $vars, $template); } // Show the filled template page, depending on exit code function show_page($output, $exit) { if ($exit === 0) { $headline = "Success"; $notice = ""; } else if ($exit === 1) { $headline = "Error"; $notice = "

This error could have happened because one or more fields contained invalid information. Please try again. If you think that you see this error by mistake, please contact us.

"; } else { $headline = "Thank you"; } $template = file_get_contents('../template/index.html', true); $page = replace_page($template, ':HEADLINE:', $headline); $page = replace_page($page, ':BODY1:', $output); $page = replace_page($page, ':BODY2:', $notice); echo $page; unset($data); // PHP execution time tracking global $timer_start; echo "\n"; exit($exit); } ?>