/** * Logs this member into the session given username and password * @var $eml = The email address * @var $pwd = The plaintext password (will be salted and hashed) * @return If successful, the Member object. Otherwise null. */ public static function Login($eml, $pwd) { // Sanitize input $eml = DB::Safe($eml); // First, we need to obtain this member's unique salt $r = DB::Run("SELECT Salt FROM Credentials WHERE Email='{$eml}' AND MemberID > 0 LIMIT 1"); if (mysql_num_rows($r) == 0) { return null; } $salt = mysql_result($r, 0); // Now hash input according to our hashing algorithm and user's salt $pwd = hashPwd($pwd, $salt); // See if the email/password combination are correct $try = DB::Run("SELECT MemberID FROM Credentials WHERE Email='{$eml}' AND Password='******' AND MemberID > 0 LIMIT 1"); if (mysql_num_rows($try) == 0) { return null; } // At this point, valid credentials were entered. Proceed... $memberID = mysql_result($try, 0); $member = Member::Load($memberID); // Update LastActivity $member->UpdateLastActivity(); // Since they've logged in, no more need for existing // password reset tokens. Delete any strays for security. $q = "DELETE FROM PwdResetTokens WHERE CredentialsID={$member->CredentialsID()}"; DB::Run($q); // Save the session. This is the actual "logging in" part. session_regenerate_id(); // Helps prevent session hijacking $_SESSION["userID"] = $memberID; $_SESSION["timestamp"] = time(); $_SESSION["ipaddress"] = $_SERVER['REMOTE_ADDR']; return $member; }
public function Save() { // Can we have multiple answer options of the exact // same value for the same question? // Right now... NO. // Make safe the answer value before our preliminary query (including stripping HTML tags) $safeAns = DB::Safe($this->AnswerValue); $q = "SELECT 1 FROM SurveyAnswerOptions WHERE QuestionID='{$this->QuestionID}' AND AnswerValue='{$safeAns}' LIMIT 1"; if (mysql_num_rows(DB::Run($q)) > 0) { fail("Hmmm, this answer option ({$this->AnswerValue}) already exists for this question. Are you sure you didn't mean something else?"); } $q = DB::BuildSaveQuery($this, get_object_vars($this)); $r = DB::Run($q); if (!$this->ID) { $this->ID = mysql_insert_id(); } return $r ? true : false; }
public function Save() { // Should we be able to save multiple answers to the // same question for the same member? No. // Make safe the user's input, then let's prevent duplication. if (is_array($this->AnswerValue)) { $this->AnswerArrayToString(); } $safeAns = DB::Safe($this->AnswerValue); // Strips HTML tags, just be aware of that. $q = "SELECT 1 FROM SurveyAnswers WHERE AnswerValue='{$safeAns}' AND QuestionID='{$this->QuestionID}' AND MemberID='{$this->MemberID}' AND ID!='{$this->ID}' LIMIT 1"; if (mysql_num_rows(DB::Run($q)) > 0) { fail("Oops. Could not save this answer; this user has already answered that question, but instead of changing the existing answer we tried adding a new one. Huh."); } $q = DB::BuildSaveQuery($this, get_object_vars($this)); $r = DB::Run($q); if (!$this->ID) { $this->ID = mysql_insert_id(); } return $r ? true : false; }
public function Save() { if (!$this->Name || !$this->WardID) { return false; } if (!$this->ID) { $this->ID = 0; } $this->Name = trim($this->Name); // Sanitize the name before we use it in our query below... $safeName = DB::Safe($this->Name); // Make sure the calling title is unique $q = "SELECT 1 FROM Callings WHERE Name='{$safeName}' AND WardID='{$this->WardID}' AND ID!='{$this->ID}' LIMIT 1"; if (mysql_num_rows(DB::Run($q)) > 0) { fail("Oops. Could not save Calling information; the name of the calling already exists in this ward."); } $q = DB::BuildSaveQuery($this, get_object_vars($this)); $r = DB::Run($q); if (!$this->ID) { $this->ID = mysql_insert_id(); } return $r ? true : false; }
public function Save() { if (!$this->GroupName || !$this->WardID) { return false; } if (!$this->ID) { $this->ID = 0; } // Pascal-case the FHE group name for consistency $this->GroupName = ucwords(strtolower(trim($this->GroupName))); // Sanitize the name before we use it in our query below... $safeName = DB::Safe($this->GroupName); // Make sure the group title is unique $q = "SELECT 1 FROM FheGroups WHERE GroupName='{$safeName}' AND ID!='{$this->ID}' LIMIT 1"; if (mysql_num_rows(DB::Run($q)) > 0) { fail("Oops. Could not save the FHE group; the name is already the name of another group, and they must be unique."); } $q = DB::BuildSaveQuery($this, get_object_vars($this)); $r = DB::Run($q); if (!$this->ID) { $this->ID = mysql_insert_id(); } return $r ? true : false; }
<?php require_once "lib/init.php"; if ($MEMBER || $LEADER) { // If logged in... just go to directory. header("Location: /directory.php"); } if (!isset($_GET['key'])) { die("Oops! Couldn't find any password reset token. Make sure you clicked on the link in the email or copied the entire link... "); } // Valid key? $key = ''; $credID = 0; if (isset($_GET['key'])) { $key = DB::Safe($_GET['key']); $q = "SELECT * FROM PwdResetTokens WHERE Token='{$key}' LIMIT 1"; $r = DB::Run($q); if (mysql_num_rows($r) == 0) { die("ERROR > Sorry, that is not a valid password reset token. Please go back to your email and try again?"); } // Get the associated credentials ID... $row = mysql_fetch_array($r); $credID = $row['CredentialsID']; if (!$credID) { die("ERROR > That token doesn't seem associated with any account..."); } // Make sure it hasn't expired; delete it if it has $tokenID = $row['ID']; $tooLate = strtotime("+48 hours", strtotime($row['Timestamp'])); if (time() > $tooLate) { DB::Run("DELETE FROM PwdResetTokens WHERE ID='{$tokenID}' LIMIT 1");
public function Save() { if (!$this->Name || !$this->StakeID || !$this->Password) { return false; } if (!$this->ID) { $this->ID = 0; } $this->Name = trim(strip_tags(str_ireplace("ward", "", $this->Name))); // Sanitize the name before we use it in our query below... (and strip tags) $safeName = DB::Safe($this->Name); // Make sure the ward name is unique $q = "SELECT 1 FROM Wards WHERE Name='{$safeName}' AND StakeID='{$this->StakeID}' AND ID!='{$this->ID}' LIMIT 1"; if (mysql_num_rows(DB::Run($q)) > 0) { fail("Oops. Could not save Ward information; the name of the ward already exists in its stake."); } $q = DB::BuildSaveQuery($this, get_object_vars($this)); $r = DB::Run($q); if (!$this->ID) { $this->ID = mysql_insert_id(); } return $r ? true : false; }
public function Delete($sure = false) { if ($sure !== true) { fail("Could not delete this question; pass in boolean true to be sure."); } if (!$this->ID) { fail("Could not delete this question, because no valid ID was associated with it."); } // "Make safe the harbor!" ... or ... "Make safe the city!" (pick your movie; I prefer the latter) $safeID = DB::Safe($this->ID); // Delete all SurveyAnswerOptions to it $this->DeleteAllAnswerOptions(true); // Delete all permissions for it $q = "DELETE FROM Permissions WHERE QuestionID='{$safeID}'"; if (!DB::Run($q)) { fail("Could not delete permissions for this question with ID {$this->ID}, reason: " . mysql_error()); } // Delete all answers to this question foreach ($this->Answers() as $ans) { $ans->Delete(); } // Delete the question, at last. $q = "DELETE FROM SurveyQuestions WHERE ID='{$safeID}' LIMIT 1"; if (!DB::Run($q)) { fail("Could not delete question with ID {$this->ID} from database (but answers, answer options, and permissions for it were all deleted), reason: " . mysql_error()); } return true; }
<?php require_once "../lib/init.php"; if ($MEMBER || $LEADER) { Response::Send(403, "You're already logged in!"); } @($eml = $_POST['eml']); if (!$eml) { Response::Send(400, "Please type your email address."); } $eml = DB::Safe($eml); // Verify input, send email, etc. $q = "SELECT ID FROM Credentials WHERE Email='{$eml}' LIMIT 1"; $r = DB::Run($q); if (mysql_num_rows($r) == 0) { Response::Send(400, "That email address {$eml} doesn't match any on file."); } // Get credential ID $credID = mysql_result($r, 0); // Make sure they haven't requested a reset in the last 15 minutes. $q = "SELECT `Timestamp` FROM `PwdResetTokens` WHERE `CredentialsID`='{$credID}' ORDER BY `ID` DESC LIMIT 1"; // Find most recent $result = mysql_fetch_array(DB::Run($q)); $tooSoon = strtotime("+15 minutes", strtotime($result['Timestamp'])); if (time() < $tooSoon) { Response::Send(403, "Please wait at least 15 minutes before requesting another email to be sent."); } // Generate reset token $token = urlencode(randomString(15, false)); // Prepare the email $subj = "Reset your ward website password";
<?php require_once "../../lib/init.php"; protectPage(11); @($mID = DB::Safe($_GET['mID'])); @($cID = DB::Safe($_GET['cID'])); if (!$mID || !$cID) { fail("Problem... missing member ID or calling ID or both."); } $m = Member::Load($mID); if (!$m) { fail("Could not load member with ID {$mID}. aborting."); } if (!$m->RemoveCalling($cID)) { fail("Could not remove calling from member."); } Response::Send(200);
public function NameUnique() { $name = DB::Safe($this->Name); $q = DB::Run("SELECT 1 FROM Residences WHERE Name='{$name}' AND WardID='{$this->WardID}' AND ID!='{$this->ID}' LIMIT 1"); return mysql_num_rows($q) == 0; }
<?php require_once "../lib/init.php"; protectPage(0, true); // Get the ward ID. "$WARD" is defined in init.php for convenience. $wardID = DB::Safe($WARD->ID()); // Load a list of the members in order of apartment or address $members = array(); $q = DB::Run("SELECT\n\tMembers.ID,\n\tTRIM(CONCAT_WS(\" \", Residences.Address, Residences.City, Residences.State)) AS FullAddr,\n\tTRIM(CONCAT_WS(\" \", Residences.Name, Members.Apartment)) AS RegularAddr\nFROM Members\nLEFT JOIN Residences\nON Members.ResidenceID = Residences.ID\nWHERE Members.WardID='{$WARD->ID()}'\nORDER BY RegularAddr, FullAddr, FirstName, LastName ASC;"); $lastApt = ""; // The apartment/address string of the last member in the loop $i = 0; // New line (float clearing) counter $j = 0; // Incremented for each apartment group we encounter ?> <html> <head> <title><?php echo $WARD->Name; ?> Ward Directory — <?php echo SITE_NAME; ?> </title> <?php include "../includes/head.php"; ?> <style> html,
/** * Since Credentials are stored in a separate table but loaded inline into the same object, * here we extract the Credentials information so BuildSaveQuery (above) can save the object * without hassle. That function shouldn't encounter a member field that isn't in the table. * @var $obj = The Member or StakeLeader for which to save credentials * @var &$vars = A reference to the object's member variables, so they can be altered directly **/ public static function BuildCredentialsSaveQuery($obj, &$vars) { $className = get_class($obj); $fields = ""; $values = ""; $update = ""; if ($className != "Member" && $className != "StakeLeader") { return false; } @($recordID = $vars['ID'] ? $vars['ID'] : 0); @($credID = $vars['CredentialsID'] ? $vars['CredentialsID'] : 0); @($email = $vars['Email']); @($password = $vars['Password']); @($salt = $vars['Salt']); $credID = DB::Safe($credID); $recordID = DB::Safe($recordID); $email = DB::Safe($email); $password = DB::Safe($password); $salt = DB::Safe($salt); unset($vars['Email']); // Unset these here because they don't go in the Member/StakeLeader tables! unset($vars['Password']); unset($vars['Salt']); return "INSERT INTO Credentials (`ID`, `Email`, `Password`, `Salt`, `{$className}ID`) VALUES ('{$credID}', '{$email}', '{$password}', '{$salt}', '{$recordID}') ON DUPLICATE KEY UPDATE Email='{$email}', Password='******', Salt='{$salt}', `{$className}ID`='{$recordID}'"; }
<?php require_once "../../lib/init.php"; protectPage(9); @($id = DB::Safe($_GET['id'])); // Verify... if (!$id) { fail("Could not delete permission; please specify a valid ID."); } // Load the permission and make sure it belongs in the ward $p = Permission::Load($id); if (!$p->InWard($MEMBER->WardID)) { fail("That permission is not within your own ward..."); } // Delete this permission. $p->Delete(true); Response::Send(200);
public static function UnfinishedJobExistsWithLeaderID($id, $max = 1) { $id = DB::Safe($id); $r = DB::Run("SELECT ID FROM EmailJobs WHERE StakeLeaderID='{$id}' AND Ended = 0 LIMIT {$max}"); return mysql_num_rows($r) >= $max; }
public function Permissions($removeOverlap = true) { $permissions = array(); $wardID = DB::Safe($_SESSION['wardID']); $questionQuery = DB::Run("SELECT ID FROM SurveyQuestions WHERE WardID='{$wardID}'"); while ($questionRow = mysql_fetch_array($questionQuery)) { $per = new Permission(); // Ad-hoc part. We're not looking up permissions by calling or name. $per->QuestionID($questionRow['ID']); $permissions[] = $per; } return $permissions; }
header("Location: /newpwd?key={$token}"); } if (!$token) { Response::Send(400, "Token value disappeared. That shouldn't happen. Please report this so it can get fixed."); } // Make sure both passswords match if ($pwd1 != $pwd2) { Response::Send(400, "Your passwords don't match. Make sure they match."); } // Check length if (strlen($pwd1) < 8) { Response::Send(400, "Your password is too short. Please make it at least 8 characters."); } // Verify that the credentials ID matches the token $credID = DB::Safe($credID); $token = DB::Safe($token); $r = DB::Run("SELECT 1 FROM `PwdResetTokens` WHERE `CredentialsID`='{$credID}' AND `Token`='{$token}' LIMIT 1"); if (mysql_num_rows($r) == 0) { Response::Send(400, "Account ID and token do not appear to match. Maybe try again from the link in your email?"); } // Get account object (Member or Leader) -- first we have to determine which type it is $q2 = DB::Run("SELECT * FROM Credentials WHERE ID='{$credID}' LIMIT 1"); $r = mysql_fetch_array($q2); $memberID = $r['MemberID']; $leaderID = $r['StakeLeaderID']; $user = null; if ($memberID && !$leaderID) { $user = @Member::Load($memberID); } else { if ($leaderID && !$memberID) { $user = @StakeLeader::Load($leaderID);