<?php

	/*
	*	Gekko - Open Source Web Development Framework
	*	------------------------------------------------------------------------
	*	Copyright (C) 2004-2005, J. Carlos Nieto <xiam@users.sourceforge.net>
	*	This program is Free Software.
	*
	*	@package	Gekko
	*	@license	http://www.gnu.org/copyleft/gpl.html GNU/GPL License 2.0
	*	@author		J. Carlos Nieto <xiam@users.sf.net>
	*	@version	CVS: $Id:$
	*	@link		http://www.gekkoware.org
	*/

	define ("IN-GEKKO", true);

	require_once "../../conf.php";
	require_once GEKKO_ROOT."lib/core.lib.php";
	require_once GEKKO_ROOT."modules/users/main.lib.php";
	require_once GEKKO_ROOT."modules/groups/main.lib.php";
	require_once GEKKO_ROOT."lib/template.lib.php";
	require_once GEKKO_ROOT."lib/network.lib.php";

	db_init();

	require_once GEKKO_ROOT."lib/auth.inc.php";

	gpGet("action", 1);
	gpGet("id", 1);

	gpGlobalize("return");

	// setting access rules
	$login_protection = $AccessTable->set_generic_rule("user", "auth");

	switch ($action) {
		case "delete":
			// admin only action
			(is_Admin()) ? execWithEach($id, "deleteUser") : accessDenied(true);
		break;
		case "enable":
			// admin only action
			(is_Admin()) ? userSetStatus($id, 1) : accessDenied(true);
		break;
		case "confirm":

			gpGlobalize("username, password, confirmation");

			requireVars($username, $password, $confirmation);

			$username = strtolower($username);

			$hash = md5($username.$password);

			if (strlen($confirmation) == 16 && conf::getKey("users", "account.require_confirmation")) {

				$db->query ("
				UPDATE ".db_table("user")." SET
					authKey = '',
					Status = '1'
				WHERE Username = '{$username}' AND Password='{$hash}' AND AuthKey = '{$confirmation}'",
				__FILE__, __LINE__);

				$aff = $db->affected_rows();

				$return = "../../index.php/users/".($aff ? "login": "confirm");

				if ($aff)
					slog("users: confirmed account for user '$username'", "actions", 2);
			}

		break;
		case "resetpasswd":

			if (!conf::getKey("users", "account.enable_password_reset"))
				abort(accessDenied(true, __FILE__, __LINE__));

			gpGlobalize("username, email, confirmation, password1, password2");

			requireVars($username, $email);

			$username = strtolower($username);

			if ($confirmation) {
				if ((strlen($password1) >= conf::getKey("users", "password.min_length")) && ($password1 == $password2)) {
					$db->query("
						UPDATE ".db_table("user")." SET
							Password = '".md5($username.$password1)."'
						WHERE Username = '{$username}' AND ResetCookie = '{$confirmation}'
					");
					if ($db->affected_rows()) {
						slog("users: password reset for '$username'", "actions", 4);
						$return = "../../index.php/users/login?user=$username";
					} else {
						abort(_l("E_WRONG_KEY"));
					}
				} else {
					abort(_l("E_PASSWORD_MISMATCH"));
				}
			} else {

				// Creating access rule
				$AccessTable->set_rule (
					"users-register",
					conf::getKey("users", "resetpw.interval", 600, "i"),
					conf::getKey("users", "resetpw.requests", 2, "i"),
					true
				);

				// Using rule for preventing bruteforce attacks
				$AccessTable->load_rule ("users-register", "L_RESETPASSWD_WAIT");

				$confirmation = genkey(64);

				$db->query("
				UPDATE ".db_table("user")." SET
					ResetCookie = '{$confirmation}'
				WHERE Username = '{$username}' AND Email = '{$email}'
				", __FILE__, __LINE__);

				if ($db->affected_rows()) {
					sendMail($email, _l("L_RESET_PASSWORD"),
						mkLetter("users/resetpasswd",
							Array (
								"USERNAME" => $username,
								"EMAIL" => $email,
								"CONFIRMATION_CODE" => $confirmation
							)
						)
					);
					$return = "../../index.php/users/resetpasswd?sent=1";
				} else {
					abort(_l("E_DATABASE_MISMATCH"));
				}
			}

		break;
		case "login":

			// Creating access rule
			$AccessTable->set_rule (
				"users-login",
				conf::getKey("users", "login.interval", 800, "i"),
				conf::getKey("users", "login.requests", 10, "i"),
				true
			);

			// Using rule for preventing bruteforce attacks
			$AccessTable->load_rule ("users-login", "E_TOO_MANY_FAILED_LOGIN_ATTEMPTS");

			gpGlobalize("username, password");

			requireVars($username, $password);
			$username = strtolower($username);

			// autentication hash
			$hash = md5($username.$password);

			$db->query ("
				SELECT ID, Status, AuthKey, SesLen
				FROM ".db_table("user")."
				WHERE Username = '{$username}' AND Password = '{$hash}'
			", __FILE__, __LINE__);

			if ($db->num_rows()) {

				$row = $db->fetch_row();

				if ($row["Status"] || (!conf::getKey("users", "account.require_confirmation"))) {
					// generating a ramdom authentication key, this will avoid username from being saved in a cookie

					$AuthKey = "";
					if (!conf::getKey("users", "login.multi_session") || (conf::getKey("users", "login.multi_session") && !$row["AuthKey"]))
						$AuthKey = genkey(32);

					$db->query("
						UPDATE ".db_table("user")." SET
							".(($AuthKey) ? "AuthKey = '{$AuthKey}'," : "")."
							LastLogin = '".time()."'
						WHERE ID = '".$row["ID"]."'
					", __FILE__, __LINE__);

					// setting cookie
					gcookie("auth", mkauth($hash, $AuthKey ? $AuthKey : $row["AuthKey"]), ($row["SesLen"]*60));

					slog("users: '$username' logged in", "actions", 5);

				} elseif (strlen($row["AuthKey"]) == 16) {
					// this user has not confirmed him account, and it is required to login.
					header("Location: ../../index.php/users/confirm");
					db_exit();
					abort();
				} else {
					// inactive account
					abort(_l("E_INACTIVE_ACCOUNT"));
				}
			} else {

				slog("Failed login attempt for: $username.", "warning", 4);

				$AccessTable->GateKeeper("users", "login");

				abort(_l("E_LOGIN_INCORRECT"));
			}

		break;
		case "register":

			// Creating access rule
			$AccessTable->set_rule (
				"users-register",
				conf::getKey("users", "register.interval", 86400, "i"),
				conf::getKey("users", "register.requests", 3, "i"),
				false
			);

			/*
				This action is valid for both Administrators and Simple Users.
				Check those permissions!!
			*/
 			if (is_admin()) {

				// some features are allowed only for admin
				gpGlobalize("username, password, email, realname,
				seslen, status, groups");

			} else {

				if (!conf::getKey("users", "account.enable_self_registration")) {
					// this means the user cannot register himself
					abort(accessDenied(true, __FILE__, __LINE__));
				}
				gpGlobalize("username, password, email, realname, confirm");
			}

			requireVars($username, $password, $email);

			$username = strtolower($username);

			// some security checks....
			if (strlen($password) < conf::getKey("users", "password.min_length")) {
				abort(_l("E_PASSWORD_LEN"));
			}

			if ((!is_Admin() || isset($confirm)) && ($confirm != $password)) {
				// admin doesn't need to confirm the password
				abort(_l("E_PASSWORD_MISMATCH"));
			}

			if (preg_match("/[^a-zA-Z0-9\-_.]/", $username)) {
				abort(_l("E_USERNAME_MUST_CONTAIN"));
			}

			// checking for duplicated entries
			$db->query("SELECT ID FROM ".db_table("user")."
				WHERE Username = '{$username}'");
			if ($db->num_rows())
				abort(_l("E_DUPLICATED_USERNAME"));

			$db->query("SELECT ID FROM ".db_table("user")." WHERE Email = '{$email}'");
			if ($db->num_rows())
				abort(_l("E_DUPLICATED_EMAIL"));

			// groups for the user
			$groups = (is_Admin() && isset($groups) && is_array($groups)) ? implode(",", $groups) : "";

			if (!is_Admin())
				$AccessTable->load_rule("users-register", "E_TOO_MANY_REGISTRATIONS");

			$db->query ("
			INSERT INTO ".db_table("user")."
				(
					ID,
					Username,
					Realname,
					Password,
					Email,
					SesLen,
					RegTime,
					Status,
					Groups
				)
					VALUES
				(
					'".($id = $db->free_id("user"))."',
					'".$username."',
					'".$realname."',
					'".md5($username.$password)."',
					'".$email."',
					'".(is_Admin() ? $seslen : "")."',
					'".time()."',
					'".(is_Admin() ? $status : 1)."',
					'".($groups ? $groups : "500")."'
				)
			", __FILE__, __LINE__);

			$require_confirmation = conf::getKey("users", "account.require_confirmation");
			$welcome_email = conf::getKey("users", "account.send_welcome_letter");

			if (!is_Admin() && ($require_confirmation || $welcome_email)) {

				$code = "";
				if ($require_confirmation) {
					$code = genkey(16);
					$db->query("
						UPDATE ".db_table("user")." SET
							Status = '0',
							AuthKey = '$code'
						WHERE ID = '{$id}'
					", __FILE__, __LINE__);
				}

				sendMail($email, _l("L_WELCOME"),
					mkLetter("users/welcome",
						Array (
							"REALNAME" => $realname,
							"USERNAME" => $username,
							"PASSWORD" => $password,
							"CONFIRMATION_CODE" => $code ? $code : _l("L_NOT_NECESSARY")
						)
					)
				);

			}

			slog("users: registered -- '$username'", "actions", 1);

		break;
		case "edit":
			if (is_Admin()) {

				gpGlobalize("id, username, password, email, realname,
				seslen, status, groups");

				requireVars($id, $username, $email);

				$db->query("SELECT Username FROM ".db_table("user")." WHERE ID = '$id'", __FILE__, __LINE__);
				$row = $db->fetch_row();
				$username = strtolower($row["Username"]);

				if ($password)
					$password = md5($username.$password);

				// checking for duplicated data
				$db->query("SELECT ID FROM ".db_table("user")." WHERE Email = '$email' AND ID != '$id'");
				if ($db->num_rows()) abort(_l("E_DUPLICATED_EMAIL"));

				$groups = (isset($groups) && is_array($groups)) ? implode(",", $groups) : "";

				$db->query("
					UPDATE ".db_table("user")." SET
						Realname = '$realname',
						".($password ? "Password = '$password'," : "")."
						Email = '$email',
						SesLen = '$seslen',
						Status = '$status',
						Groups = '$groups'
					WHERE ID = '$id'
				", __FILE__, __LINE__);

				slog("users: updated account information for user: $username", "actions", 5);
				if ($password) {
					slog("users: password changed for user: $username.", "actions", 4);
				}
			} else {
				abort(accessDenied());
			}
		break;
		case "account":
			# allow only authenticated users
			if (gauth("$")) {

				gpGlobalize("id, realname, email, password, seslen, new_password,
				confirm_password");

				requireVars($id, $realname, $email, $password);

				$db->query("SELECT Username, Password FROM ".db_table("user")."
				WHERE ID = '".$id."'");
				$row = $db->fetch_row();
				$username = strtolower($row["Username"]);

				if (md5($username.$password) != $row["Password"]) {
					abort(_l("E_ACCESS_DENIED"));
				}

				if ($new_password || $confirm_password) {
					if ($new_password == $confirm_password) {
						$new_password = md5($username.$new_password);
					} else {
						abort(_l("E_PASSWORDS_MISMATCH"));
					}
				}

				$db->query("SELECT ID FROM ".db_table("user")." WHERE Email = '$email' AND ID != '$id'");
				if ($db->num_rows()) abort(_l("E_DUPLICATED_EMAIL"));

				$db->query("
					UPDATE ".db_table("user")." SET
						Realname = '$realname',
						".($new_password ? "Password = '$new_password'," : "")."
						Email = '$email',
						SesLen = '$seslen'
					WHERE ID='$id' AND Password = '".md5($username.$password)."'
				", __FILE__, __LINE__);
			} else {
				abort(accessDenied());
			}

		break;
		case "profile":

			if ((gauth("$") && $User["ID"] == $id) || is_Admin()) {

				gpGlobalize("id, nickname, publicemail, website, location, gender,
				birthdate, avatar, aboutme, signature, immsn, imyim, imicq");

				requireVars($id, $nickname);

				$db->query("SELECT ID FROM ".db_table("user")." WHERE Username = '$nickname' AND ID != '$id'", __FILE__, __LINE__);
				if ($db->num_rows()) abort(_l("L_TAKEN_NICKNAME"));

				$db->query("SELECT ID FROM ".db_table("user")." WHERE Email = '$publicemail' AND ID != '$id'", __FILE__, __LINE__);
				if ($db->num_rows()) abort(_l("L_USED_NICKNAME"));

				$db->query("SELECT ID FROM ".db_table("user_profile")." WHERE Nickname = '$nickname' AND ID != '$id'", __FILE__, __LINE__);
				if ($db->num_rows()) abort(_l("L_TAKEN_NICKNAME"));

				$db->query("SELECT ID FROM ".db_table("user_profile")." WHERE ID = '$id'");

				/*
					converting date to mysql timestamp
					yyyymmddhhmmss
				*/

				$birthdate = date2mysqltime($birthdate);

				if ($db->num_rows()) {
					$db->query("
						UPDATE ".db_table("user_profile")." SET
							Nickname = '$nickname',
							PublicEmail = '$publicemail',
							BirthDate = '$birthdate',
							WebSite = '$website',
							Avatar = '$avatar',
							AboutMe = '$aboutme',
							Signature = '$signature',
							Location = '$location',
							Gender = '$gender',
							imMSN = '$immsn',
							imYIM = '$imyim',
							imICQ = '$imicq'
						WHERE ID = '$id'
					", __FILE__, __LINE__);
				} else {
					$db->query("
						INSERT INTO ".db_table("user_profile")." (
							ID,
							Nickname,
							PublicEmail,
							BirthDate,
							WebSite,
							Avatar,
							AboutMe,
							Signature,
							Location,
							Gender,
							imMSN,
							imYIM,
							imICQ
						) VALUES (
							'{$id}',
							'{$nickname}',
							'{$publicemail}',
							'{$birthdate}',
							'{$website}',
							'{$avatar}',
							'{$aboutme}',
							'{$signature}',
							'{$location}',
							'{$gender}',
							'{$immsn}',
							'{$imyim}',
							'{$imicq}'
						)
					", __FILE__, __LINE__);
				}
			} else {
				abort(accessDenied());
			}

		break;
		default:
			abort(_l("L_UNDEFINED_ACTION"));
		break;
	}

	ssl_normal_redirect($return);

	redirect($return ? $return : $_SERVER["HTTP_REFERER"]);

	db_exit();
?>