+
+ // Return status
+ return $return;
+}
+
+// Confirms a user account
+function doConfirmUserAccount ($hash) {
+ // Init content
+ $content = array(
+ 'message' => '{--GUEST_CONFIRMED_FAILED--}',
+ 'userid' => 0,
+ );
+
+ // Initialize the user id
+ $userid = NULL;
+
+ // Search for an unconfirmed or confirmed account
+ $result = sqlQueryEscaped("SELECT `userid`, `refid` FROM `{?_MYSQL_PREFIX?}_user_data` WHERE `user_hash`='%s' AND (`status`='UNCONFIRMED' OR `status`='CONFIRMED') LIMIT 1",
+ array($hash), __FILE__, __LINE__);
+
+ // One result should be found
+ if (ifSqlHasZeroNumRows($result)) {
+ // Nothing found or tried to confirm twice?
+ displayMessage('{--GUEST_CONFIRMED_TWICE--}');
+ return;
+ } // END - if
+
+ // Okay, the user want's to confirm now so we load some data
+ list($userid, $refid) = sqlFetchRow($result);
+
+ // Fetch user data
+ if (!fetchUserData($userid)) {
+ // Not found, should not happen
+ reportBug(__FILE__, __LINE__, 'User account ' . $userid . ' not found.');
+ } // END - if
+
+ // Load all data and add points
+ $content = merge_array($content, getUserDataArray());
+
+ // Is 'user' updated?
+ if (isExtensionInstalledAndNewer('user', '0.6.3')) {
+ // Unlock his account (but only when it is on UNCONFIRMED!)
+ sqlQueryEscaped("UPDATE
+ `{?_MYSQL_PREFIX?}_user_data`
+SET
+ `status`='CONFIRMED',
+ `user_hash`=NULL,
+ `confirmed_timestamp`=NOW(),
+ `confirmed_ip_address`='%s'
+WHERE
+ `user_hash`='%s' AND
+ `status`='UNCONFIRMED'
+LIMIT 1",
+ array(
+ determineRealRemoteAddress(),
+ $hash
+ ), __FILE__, __LINE__
+ );
+ } else {
+ // Unlock his account (but only when it is on UNCONFIRMED!)
+ sqlQueryEscaped("UPDATE
+ `{?_MYSQL_PREFIX?}_user_data`
+SET
+ `status`='CONFIRMED',
+ `user_hash`=NULL
+WHERE
+ `user_hash`='%s' AND
+ `status`='UNCONFIRMED'
+LIMIT 1",
+ array(
+ $hash
+ ), __FILE__, __LINE__
+ );
+ }
+
+ // Was it updated?
+ if (ifSqlHasZeroAffectedRows()) {
+ // Nobody was found unter this hash key... or our new member want's to confirm twice?
+ displayMessage('{--GUEST_CONFIRMED_TWICE--}');
+ return;
+ } // END - if
+
+ // Load email template
+ $message = loadEmailTemplate('guest_user_confirmed', $content, bigintval($userid));
+
+ // And send him right away the confirmation mail
+ sendEmail($userid, '{--GUEST_THANX_CONFIRM--}', $message);
+
+ // Maybe he got "referraled"?
+ if ((isValidId($refid)) && ($refid != $userid)) {
+ // Select the referral userid
+ if (fetchUserData($refid)) {
+ // Update ref counter...
+ updateReferralCounter($refid);
+
+ // If version matches add ref bonus to refid's account
+ if ((isExtensionInstalledAndNewer('bonus', '0.4.4')) && (isBonusRallyeActive())) {
+ // Add points (directly only!)
+ sqlQueryEscaped("UPDATE `{?_MYSQL_PREFIX?}_user_data` SET `bonus_ref`=`bonus_ref`+{?bonus_ref?} WHERE `userid`=%s LIMIT 1",
+ array(bigintval($refid)), __FILE__, __LINE__);
+
+ // Subtract points from system
+ handleBonusPoints(getBonusRef(), $refid);
+ } // END - if
+
+ // Add one-time referral bonus over referral system or directly
+ initReferralSystem();
+ addPointsThroughReferralSystem('referral_bonus', $refid, getPointsRef(), bigintval($userid));
+ } // END - if
+ } // END - if
+
+ // @TODO Rewrite this to 2 filters as a possible redirect must always come last
+ if (isExtensionActive('rallye')) {
+ // Add user to rallye (or not?)
+ addUserToReferralRallye(bigintval($userid));
+ } // END - if
+
+ // Account confirmed!
+ if (isExtensionActive('lead')) {
+ // Set special lead cookie
+ setSession('lead_userid', bigintval($userid));
+
+ // Lead-Code mode enabled
+ redirectToUrl('lead-confirm.php');
+ } else {
+ // Regular confirmation
+ $content['message'] = '{--GUEST_CONFIRMED_DONE--}';
+ $content['userid'] = bigintval($userid);
+ }
+
+ // Load template
+ displayMessage($content['message']);
+}
+
+// Does resend the user's confirmation link for given email address
+function doResendUserConfirmationLink ($email) {
+ // Email address not registered is default message
+ $message = '{--EMAIL_404--}';
+
+ // Confirmation link requested
+ if (fetchUserData($email, 'email')) {
+ // Email address found
+ $content = getUserDataArray();
+
+ // Is the account unconfirmed?
+ if ($content['status'] == 'UNCONFIRMED') {
+ // Load email template
+ $message = loadEmailTemplate('guest_request_confirm', array(), $content['userid']);
+
+ // Send email
+ sendEmail($content['userid'], '{--GUEST_REQUEST_CONFIRM_LINK_SUBJECT--}', $message);
+ } // END - if
+
+ // Create message based on the status
+ $message = getConfirmationMessageFromUserStatus($content['status']);
+ } // END - if
+
+ // Output message
+ displayMessage($message);
+}
+
+// Get a message (somewhat translation) from user status for confirmation link.
+// This is different to translateUserStatus() in text messages.
+function getConfirmationMessageFromUserStatus ($status) {
+ // Default is 'UNKNOWN'
+ $message = '{%message,GUEST_LOGIN_ID_UNKNOWN_STATUS=' . $status . '%}';
+
+ // Which status is it?
+ switch ($status) {
+ case 'UNCONFIRMED': // Account is unconfirmed
+ // And set message
+ $message = '{--GUEST_CONFIRM_LINK_SENT--}';
+ break;
+
+ case 'CONFIRMED': // Account already confirmed
+ $message = '{--GUEST_LOGIN_ID_CONFIRMED--}';
+ break;
+
+ case 'LOCKED': // Account is locked
+ $message = '{--GUEST_LOGIN_ID_LOCKED--}';
+ break;
+
+ default: // This should not happen
+ reportBug(__FUNCTION__, __LINE__, 'Unknown user status ' . $status . ' detected.');
+ break;
+ } // END - switch
+
+ // Return message
+ return $message;
+}
+
+// "Getter" for total tester accounts
+function getTotalTesterUsers () {
+ // Is there cache?
+ if (!isset($GLOBALS[__FUNCTION__])) {
+ // Determine it
+ $GLOBALS[__FUNCTION__] = countSumTotalData('', 'user_data', 'userid', '', TRUE, runFilterChain('user_inclusion_sql'));
+ } // END - if
+
+ // Return cache
+ return $GLOBALS[__FUNCTION__];
+}
+
+// Checks whether the admin is allowed to create more tester accounts
+function isNewUserTesterAllowed () {
+ // By default only admins are allowed
+ if (!isAdmin()) {
+ // This should not happen and must be fixed
+ reportBug(__FUNCTION__, __LINE__, 'isAdmin()=false - Not allowed.');
+ } // END - if
+
+ // Are more tester accounts allowed?
+ $isAllowed = (getTotalTesterUsers() < bigintval(getTesterUserMaximum() + 1));
+
+ // Return result
+ return $isAllowed;
+}
+
+// "Getter" for next free tester account number
+function getNextFreeTesterUserNumber () {
+ // Get current total amount because we start with zero
+ $nextTester = getTotalTesterUsers();
+
+ // Prepend zeros
+ $nextTester = padLeftZero($nextTester, 6);
+
+ // Return it
+ return $nextTester;
+}
+
+// Wrapper function to return a selection box for tester user default referral id
+function addTesterUserDefaultRefidSelectionBox ($fieldName = 'tester_user_default_refid') {
+ // Return it
+ return addMemberSelectionBox(getConfig('tester_user_default_refid'), FALSE, TRUE, TRUE, $fieldName, " WHERE `surname` LIKE '{?tester_user_surname_prefix?}%'");
+}
+
+// Checks whether given surname is a test user name
+function isTesterUserName ($surname) {
+ // Determine it
+ return (substr($surname, 0, strlen(getTesterUserSurnamePrefix())) == getTesterUserSurnamePrefix());
+}
+
+// Creates a tester account from given POST data
+function createTesterUserAccount () {
+ // Add generated surname
+ setPostRequestElement('surname', (getTesterUserSurnamePrefix() . getNextFreeTesterUserNumber()));
+
+ // Is the registration data complete?
+ if (!isRegistrationDataComplete()) {
+ // Then abort here
+ //* DEBUG: */ logDebugMessage(__FUNCTION__, __LINE__, 'isRegistrationDataComplete()=false, please check if you e.g. have selected the required minimum of categories.');
+ return FALSE;
+ } // END - if
+
+ // Do registration
+ $isCreated = doUserRegistration();
+
+ // Remove cache to force recalculation of total tester accounts
+ unset($GLOBALS['getTotalTesterUsers']);
+
+ // Return status
+ return $isCreated;
+}
+
+// Checks whether the given sub id is fused by current member
+function isMemberSubIdFree ($subId) {
+ // Only do this for logged-in members
+ assert(isMember());
+
+ // Check it
+ $isFree = (countSumTotalData(getMemberId(), 'user_subids', 'id', 'userid', TRUE, sprintf(" AND `subid`='%s'", $subId)) == 0);
+
+ // Return result
+ return $isFree;
+}
+
+// Checks whether the sub id is valid
+function isValidSubId ($subId) {
+ // First convert any spaces/dashes to underscores
+ $subId = str_replace(' ', '_', str_replace('-', '_', $subId));
+
+ // Then filter out any unwanted characters
+ $subIdTest = preg_replace('/([^a-zA-Z0-9_])/', '', $subId);
+
+ // Is it valid?
+ return ($subId == $subIdTest);
+} // END - if
+
+// Prepares found sub id for updating in database
+function prepareFoundSubId ($subId) {
+ // Then check if it is valid and available
+ if ((!isValidSubId($subId)) || (isMemberSubIdFree($subId))) {
+ // Is not free or invalid
+ $subId = FALSE;
+ } // END - if
+
+ // Return prepared sub id
+ return $subId;
+}
+
+// Validates sub id and returns FALSE if not valid
+function validateSubId ($subId) {
+ // Then check if it is valid and available
+ if (!isValidSubId($subId)) {
+ // Is not free or invalid
+ $subId = FALSE;
+ } // END - if
+
+ // Return prepared sub id
+ return $subId;
+}
+
+// Prepares given sub id for inserting into database
+function prepareSubId ($subId) {
+ // Then check if it is valid and available
+ if ((!isValidSubId($subId)) || (!isMemberSubIdFree($subId))) {
+ // Is not free or invalid
+ $subId = FALSE;
+ } // END - if
+
+ // Return prepared sub id
+ return $subId;
+}
+
+// Check whether given sub *id* is assigned to current member
+function isUserSubIdAssignedToMember ($subId, $userid = NULL) {
+ // Is there cache?
+ if (!isset($GLOBALS[__FUNCTION__][$subId][$userid])) {
+ // Determine it
+ $GLOBALS[__FUNCTION__][$subId][$userid] = (
+ (
+ // Is a userid set or current set?
+ (isValidId($userid)) || (isMember())
+ ) && (
+ // .. and it assigned with subid's id?
+ countSumTotalData(
+ (isValidId($userid) ? $userid : getMemberId()),
+ 'user_subids',
+ 'id',
+ 'userid',
+ TRUE,
+ sprintf(' AND `id`=%s', bigintval($subId))
+ ) == 1
+ )
+ );
+ } // END - if
+
+ // Return cache
+ return $GLOBALS[__FUNCTION__][$subId][$userid];
+}
+
+// Getter for subid from given id number
+function getSubId ($id) {
+ // Is there cache?
+ if (!isset($GLOBALS[__FUNCTION__][$id])) {
+ // Check database for record
+ $result = sqlQueryEscaped("SELECT `subid` FROM `{?_MYSQL_PREFIX?}_user_subids` WHERE `id`=%s LIMIT 1",
+ array(bigintval($id)), __FUNCTION__, __LINE__);
+
+ // Is there an entry?
+ if (sqlNumRows($result) == 1) {
+ // Load it
+ list($GLOBALS[__FUNCTION__][$id]) = sqlFetchRow($result);
+ } // END - if
+
+ // Free result
+ sqlFreeResult($result);
+ } // END - if
+
+ // Return cache
+ return $GLOBALS[__FUNCTION__][$id];
+}
+
+// "Getter for total count of current user's sub ids
+function getTotalMemberSubIds () {
+ // Only do this for logged-in members
+ assert(isMember());
+
+ // Is there cache?
+ if (!isset($GLOBALS[__FUNCTION__])) {
+ // Determine it
+ $GLOBALS[__FUNCTION__] = countSumTotalData(getMemberId(), 'user_subids', 'id', 'userid', TRUE);
+ } // END - if
+
+ // Return cache
+ return $GLOBALS[__FUNCTION__];
+}
+
+// Displays generic user registration form
+function doDisplayGenericUserRegistrationForm () {
+ // Do this only if form is sent
+ if (isFormSent()) {
+ if (postRequestElement('agree') == '!') {
+ registerOutputFailedMessage('HAVE_TO_AGREE');
+ } // END - if
+
+ if (postRequestElement('email') == '!') {
+ registerOutputFailedMessage('ENTER_EMAIL');
+ setPostRequestElement('email', '');
+ } elseif (postRequestElement('email') == '?') {
+ registerOutputFailedMessage('GUEST_EMAIL_IS_ALREADY_REGISTERED');
+ setPostRequestElement('email', '');
+ }
+
+ if (postRequestElement('surname') == '!') {
+ registerOutputFailedMessage('ENTER_SURNAME');
+ setPostRequestElement('surname', '');
+ } // END - if
+
+ if (postRequestElement('family') == '!') {
+ registerOutputFailedMessage('ENTER_FAMILY');
+ setPostRequestElement('family', '');
+ } // END - if
+
+ if ((postRequestElement('password1') == '!') && (postRequestElement('password2') == '!')) {
+ registerOutputFailedMessage('ENTER_BOTH_PASSWORDS');
+ } elseif (postRequestElement('password1') == '!') {
+ registerOutputFailedMessage('ENTER_PASSWORD1');
+ } elseif (postRequestElement('password2') == '!') {
+ registerOutputFailedMessage('ENTER_PASSWORD2');
+ }
+
+ if ((isset($GLOBALS['registration_weak_password'])) && ($GLOBALS['registration_weak_password'] === TRUE)) {
+ registerOutputFailedMessage('GUEST_WEAK_PASSWORD');
+ } // END - if
+
+ if ((isset($GLOBALS['registration_ip_timeout'])) && ($GLOBALS['registration_ip_timeout'] === TRUE)) {
+ registerOutputFailedMessage('REMOTE_ADDR_TIMEOUT');
+ } // END - if
+
+ if ((!empty($GLOBALS['registration_selected_cats'])) && ($GLOBALS['registration_selected_cats'] < getLeastCats())) {
+ registerOutputFailedMessage('', '{--CHOOSE_MORE_CATEGORIES--}');
+ } // END - if
+ } // END - if
+
+ // Generate birthday selection
+ $content['birthday_selection'] = generateDayMonthYearSelectionBox(postRequestElement('day'),postRequestElement('month'),postRequestElement('year'));
+
+ // ZIP codes are numerical values
+ $content['zip'] = '';
+ if ((isPostRequestElementSet('zip')) && (isValidNumber(postRequestElement('zip')))) {
+ $content['zip'] = bigintval(postRequestElement('zip'));
+ } // END - if
+
+ // Other values
+ foreach (array('gender', 'surname', 'family', 'street_nr', 'city', 'email') as $entry) {
+ $content[$entry] = sqlEscapeString(postRequestElement($entry));
+ } // END - foreach
+
+ // Set must-fillout fields
+ $content = runFilterChain('register_must_fillout', $content);
+
+ // Display registration form
+ loadTemplate('guest_register', FALSE, $content);