";
+ }
+ }
+
+ function dboError($errorArray, $header, $form, $instruction, $button, $target)
+ {
+ if( $errorArray[0] != "00000" || strlen($errorArray[1]) > 0 || strlen($errorArray[2]) > 0)
+ {
+ if ( $header == "header" ) { send_html_header(""); dboHeader($form, $instruction, $button, $target); }
+ echo "
";
+ exit;
+ }
+ }
+
+
+
+ //~ ====================================================================
+ //~ Database Functions
+ //~ ====================================================================
+
+
+
+ function printHeader($message, $form, $button, $target)
+ {
+ send_html_header("");
+ echo "
";
+ echo "
$message
";
+ echo "
Form [ $form ]
";
+ //~ echo "
TinyPass
";
+
+ echo "";
+ }
+
+ function printFooter()
+ {
+ echo "";
+ }
+
+
+//~ ============================================================================
+
+ function authenticateUser($user_name, $pass_word, $form, $button, $target)
+ {
+ $pdo = connectDB($form, $button, $target);
+ //~ echo "\$pdo->getAttribute(PDO::ATTR_CONNECTION_STATUS): [" . $pdo->getAttribute(PDO::ATTR_CONNECTION_STATUS) . "]\n"; // not supported attribute
+
+ $pass_hash = hash($GLOBALS["user_auth_hash_type"], "$pass_word");
+
+ $stmt = $pdo->prepare('SELECT * FROM users WHERE user_name = :user_name AND pass_hash = :pass_hash;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare1(..)", $button, $target);
+ $stmt->execute([':user_name' => $user_name, ':pass_hash' => $pass_hash]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute1(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+
+ //~ echo "\$GLOBALS[\"user_auth_hash_type\"]: ". $GLOBALS["user_auth_hash_type"] . "\n";
+ //~ echo "Password: " . $pass_word . "\n";
+ //~ echo "Login-PassHash: " . $pass_hash . "\n";
+ //~ echo "DB----PassHash: ". $object_array[0]->pass_hash . "\n";
+
+ if ( count($object_array) > 0) { return true; }
+ else { return false; }
+ }
+
+ function userExists($pdo, $user_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT * FROM users WHERE user_name = :user_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare1(..)", $button, $target);
+ $stmt->execute([':user_name' => $user_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute1(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+
+ if ( count($object_array) > 0) { return true; } else { return false; }
+ }
+
+ function insertUser($pdo, $role_id, $user_name, $pass_word, $form, $button, $target)
+ {
+ if ( userExists($pdo, $user_name, $form, $button, $target) ) { dboError(array("-","-","User: \"$user_name\" exists!"), "header", $form, "insertUser(\"$user_name\")", $button, $target); }
+
+ $hash_type = $GLOBALS["user_auth_hash_type"];
+ $pass_hash = hash($GLOBALS["user_auth_hash_type"], $pass_word);
+
+ //~ New User
+
+ $stmt = $pdo->prepare('INSERT INTO users(role_id, user_name, hash_type, pass_hash) VALUES(:role_id,:user_name,:hash_type,:pass_hash);');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $stmt->execute([':role_id' => $role_id, ':user_name' => $user_name, ':hash_type' => $hash_type, ':pass_hash' => $pass_hash]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+
+ return $pdo->lastInsertId();
+ }
+
+ function updateUser($pdo, $role_id, $user_id, $user_name, $form, $button, $target)
+ {
+ //~ Update User
+
+ //~ $stmt = $pdo->prepare('UPDATE secrets SET group_id = :group_id, secret_date = :secret_date, secret_name = :secret_name WHERE secret_id = :secret_id;');
+
+ $stmt = $pdo->prepare('
+UPDATE users SET role_id = :role_id, user_name = :user_name
+WHERE user_id = :user_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $result = $stmt->execute([':role_id' => $role_id, ':user_id' => $user_id, ':user_name' => $user_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+
+ return $result;
+ }
+
+ function updateUserCredentials($pdo, $role_id, $user_id, $user_name, $pass_word, $form, $button, $target)
+ {
+ $hash_type = $GLOBALS["user_auth_hash_type"];
+ $pass_hash = hash($GLOBALS["user_auth_hash_type"], $pass_word);
+
+ //~ Update User
+
+ //~ $stmt = $pdo->prepare('UPDATE secrets SET group_id = :group_id, secret_date = :secret_date, secret_name = :secret_name WHERE secret_id = :secret_id;');
+
+ $stmt = $pdo->prepare('
+UPDATE users SET role_id = :role_id, user_name = :user_name, hash_type = :hash_type, pass_hash = :pass_hash
+WHERE user_id = :user_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $result = $stmt->execute([':role_id' => $role_id, ':user_id' => $user_id, ':user_name' => $user_name, ':hash_type' => $hash_type, ':pass_hash' => $pass_hash]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+
+ return $result;
+ }
+
+ function userIsAdmin($user_name, $form, $button, $target)
+ {
+ $pdo = connectDB($form, $button, $target);
+
+ $role_id = getRoleIdByUserName($pdo, $user_name, $form, $button, $target);
+
+ $stmt = $pdo->prepare('
+SELECT role_name
+FROM roles
+WHERE role_id = :role_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':role_id' => $role_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+
+ if ( $object_array[0]->role_name == "Admin" ) { return true; } else { return false; }
+ }
+
+ function selectUsers($pdo, $form, $button, $target)
+ {
+ //~ user_id INTEGER PRIMARY KEY NOT NULL,
+ //~ role_id INTEGER NOT NULL,
+ //~ user_name VARCHAR (255) NOT NULL,
+ //~ hash_type VARCHAR (255) NOT NULL,
+ //~ pass_hash VARCHAR (255) NOT NULL,
+
+ $stmt = $pdo->prepare('
+SELECT *
+FROM users
+ORDER BY user_name;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute();
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function selectUserById($pdo, $user_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('
+SELECT *
+FROM users
+WHERE user_id = :user_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ //~ user_id INTEGER PRIMARY KEY NOT NULL,
+ //~ role_id INTEGER NOT NULL,
+ //~ user_name VARCHAR (255) NOT NULL,
+ //~ hash_type VARCHAR (255) NOT NULL,
+ //~ pass_hash VARCHAR (255) NOT NULL,
+
+ function searchUsersByName($pdo, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $form, $button, $target) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $stmt = $pdo->prepare("
+SELECT users.user_id, users.role_id, users.user_name, users.hash_type, users.pass_hash, COUNT(secrets.user_id) AS user_secrets
+FROM users
+LEFT JOIN secrets ON users.user_id = secrets.user_id
+WHERE users.user_name like :search_name_filter
+AND COALESCE(secrets.secret_name,'') like :search_group_filter
+GROUP BY users.user_id
+ORDER BY ${primar_column_order_fld} ${primar_column_order_dir}, ${second_column_order_fld} ${second_column_order_dir};
+ ");
+
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([
+ ':search_name_filter' => "%" . $search_name_filter . "%"
+ ,':search_group_filter' => "%" . $search_group_filter . "%"
+ ]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function getUserIdByUserName($user_name, $form, $button, $target)
+ {
+ $pdo = connectDB($form, $button, $target);
+
+ $stmt = $pdo->prepare('SELECT user_id FROM users WHERE user_name = :user_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_name' => $user_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->user_id;
+ }
+
+ function getUserNameByUserId($pdo, $user_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT user_name FROM users WHERE user_id = :user_id;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->user_name;
+ }
+
+ function getRoleIdByUserName($pdo, $user_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT role_id FROM users WHERE user_name = :user_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_name' => $user_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->role_id;
+ }
+
+ function printUsers($users)
+ {
+ echo "
";
+ echo " ";
+ echo " Users |
";
+ echo " User Id | Role Id | User Name | Pass Hash |
";
+ echo " ";
+ echo " ";
+ foreach ($users as $user)
+ {
+ echo " $user->user_id | $user->role_id | $user->user_name | $user->pass_hash |
";
+ }
+ echo " ";
+ echo "
";
+ }
+
+ function deleteUserByUserId($pdo, $user_id, $form, $button, $target)
+ {
+ $user_name = getUserNameByUserId($pdo, $user_id, $form, $button, $target);
+ if ( $user_name === "admin" || $user_name === "tiny" )
+ {
+ dboError(array("-","-","Forbidden to delete user: " . $user_name), "header", $form, "deleteUserByUserId(\"$user_name\")", "[ â—€ OK â–¶ ]","index.php");
+ }
+ else
+ {
+ deleteSecretByUserId($pdo, $user_id, $form, $button, $target);
+
+ $stmt = $pdo->prepare('DELETE FROM users WHERE user_id = :user_id;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM users..)", $button, $target);
+ $result = $stmt->execute([':user_id' => $user_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':user_id' => \$user_id])", $button, $target);
+ return $result;
+ }
+ }
+
+//~ ----------------------------------------------------------------------------
+
+
+//~ ----------------------------------------------------------------------------
+
+ function insertRole($pdo, $role_name, $form, $button, $target)
+ {
+ //~ Stop if role_name exists
+
+ $stmt = $pdo->prepare('SELECT * FROM roles WHERE role_name = :role_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare1(..)", $button, $target);
+ $stmt->execute([':role_name' => $role_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute1(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ if ( count($object_array) > 0) { dboError($err, "header", $form, "insertRole(\"$role_name\")", $button, $target); dboError(array("-","-","Roles: \"$role_name\" exists"), "header", $form, "execute1(..)", $button, $target); }
+
+ //~ New Role
+ $stmt = $pdo->prepare('INSERT INTO roles(role_name) VALUES(:role_name);');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $stmt->execute([':role_name' => $role_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+ return $pdo->lastInsertId();
+ }
+
+ function selectRoles($pdo, $role_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT * FROM roles WHERE role_name like :role_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':role_name' => "%" . $role_name . "%"]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ //~ Table roles
+ //~ role_id INTEGER PRIMARY KEY NOT NULL,
+ //~ role_name VARCHAR (255) NOT NULL
+
+ //~ Table users
+ //~ user_id INTEGER PRIMARY KEY NOT NULL,
+ //~ role_id INTEGER NOT NULL,
+ //~ user_name VARCHAR (255) NOT NULL,
+ //~ hash_type VARCHAR (255) NOT NULL,
+ //~ pass_hash VARCHAR (255) NOT NULL,
+
+ function getRoleNameByUserName($pdo, $user_name, $form, $button, $target)
+ {
+ $role_id = getRoleIdByUserName($pdo, $user_name, $form, $button, $target);
+
+ $stmt = $pdo->prepare('
+SELECT role_name
+FROM roles
+WHERE role_id = :role_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':role_id' => $role_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->role_name;
+ }
+
+ function getRoleIdByRoleName($pdo, $role_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT role_id FROM roles WHERE role_name = :role_name;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':role_name' => $role_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->role_id;
+ }
+
+ function printRoles($roles)
+ {
+ echo "
";
+ echo " ";
+ echo " Roles |
";
+ echo " Role Id | Role Name |
";
+ echo " ";
+ echo " ";
+ foreach ($roles as $role)
+ {
+ echo " $role->role_id | $role->role_name |
";
+ }
+ echo " ";
+ echo "
";
+ }
+
+ function updateRole($pdo, $fromRoleName, $toRoleName, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('UPDATE roles SET role_name = :toRoleName WHERE role_name = :fromRoleName;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $result = $stmt->execute([':fromRoleName' => $fromRoleName, ':toRoleName' => $toRoleName]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+ return $result;
+ }
+
+ function deleteRole($pdo, $role_name, $form, $button, $target)
+ {
+ $roles = selectRoles($pdo, $role_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ printHeader("Delete role: \"$role_name\"", $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ printRoles($roles);
+
+ if ( count($roles) == 0) { dboError(array("-","-","Role: \"$role_name\" not found"), "header", $form, "deleteRole(\"$role_name\")", $button, $target); }
+ else
+ {
+ $stmt = $pdo->prepare('DELETE FROM roles WHERE role_name = :role_name;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM roles..)", $button, $target);
+ $stmt->execute([':role_name' => $role_name]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':role_name' => \$role_name])", $button, $target);
+
+ $roles = selectRoles($pdo, $role_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ printHeader("Delete role: \"$role_name\"", $form, "[ â—€ OK â–¶ ]", "index.php");
+ printRoles($roles);
+ }
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ //~ $pdo->exec('CREATE TABLE IF NOT EXISTS secrets
+ //~ (
+ //~ secret_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_id INTEGER,
+ //~ secret_date INTEGER NOT NULL,
+ //~ secret_name VARCHAR (255) NOT NULL
+ //~ )');
+
+ function insertSecret($pdo, $user_id, $group_id, $secret_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('INSERT INTO secrets(user_id, group_id, secret_date, secret_name) VALUES(:user_id,:group_id,:secret_date,:secret_name);');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id, ':group_id' => $group_id, ':secret_date' => time(), ':secret_name' => $secret_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+ return $pdo->lastInsertId();
+ }
+
+ function updateSecret($pdo, $secret_id, $group_id, $secret_name, $form, $button, $target)
+ {
+ //~ Update Secret
+ $stmt = $pdo->prepare('UPDATE secrets SET group_id = :group_id, secret_date = :secret_date, secret_name = :secret_name WHERE secret_id = :secret_id;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':secret_id' => $secret_id, ':group_id' => $group_id, ':secret_date' => time(), ':secret_name' => $secret_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+ }
+
+ function deleteSecretById($pdo, $secret_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('DELETE FROM secrets WHERE secret_id = :secret_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM secrets..)", $button, $target);
+ $stmt->execute([':secret_id' => $secret_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':secret_id' => \$secret_id])", $button, $target);
+
+ $stmt = $pdo->prepare('DELETE FROM fields WHERE secret_id = :secret_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2('DELETE FROM fields..)", $button, $target);
+ $stmt->execute([':secret_id' => $secret_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2([':secret_id' => \$secret_id])", $button, $target);
+ }
+
+ function deleteSecretByUserId($pdo, $user_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('DELETE FROM secrets WHERE user_id = :user_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM secrets..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':secret_id' => \$secret_id])", $button, $target);
+
+ $stmt = $pdo->prepare('DELETE FROM fields WHERE user_id = :user_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2('DELETE FROM fields..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2([':secret_id' => \$secret_id])", $button, $target);
+ }
+
+ function selectSecretById($pdo, $secret_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('
+SELECT secrets.secret_id, secrets.secret_name, groups.group_name
+FROM secrets
+LEFT JOIN groups ON secrets.group_id = groups.group_id
+WHERE secret_id = :secret_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':secret_id' => $secret_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function selectSecretsByName($pdo, $user_name, $search_name_filter, $search_group_filter, $form, $button, $target)
+ {
+ $user_id = getUserIdByUserNameByUserName($user_name,$form, $button, $target);
+
+ //~ secret_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_id INTEGER,
+ //~ secret_date INTEGER NOT NULL,
+ //~ secret_name VARCHAR (255) NOT NULL
+
+ $stmt = $pdo->prepare("
+SELECT secrets.secret_id, secrets.secret_name, groups.group_name
+FROM secrets
+LEFT JOIN groups ON secrets.group_id = groups.group_id
+WHERE secrets.user_id = :user_id
+AND secrets.secret_name like :search_name_filter
+AND COALESCE(groups.group_name,'') like :search_group_filter;
+ ");
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id, ':search_name_filter' => "%" . $search_name_filter . "%", ':search_group_filter' => "%" . $search_group_filter . "%"]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+
+ //~ secret_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_id INTEGER,
+ //~ secret_date INTEGER NOT NULL,
+ //~ secret_name VARCHAR (255) NOT NULL,
+
+ //~ field_id INTEGER PRIMARY KEY NOT NULL,
+ //~ secret_id INTEGER NOT NULL,
+ //~ field_ordr INTEGER NOT NULL,
+ //~ field_name VARCHAR (255) NOT NULL,
+ //~ field_type INTEGER (255) NOT NULL,
+ //~ field_value VARCHAR (255) NOT NULL,
+ //~ field_hash VARCHAR (255) NOT NULL,
+
+ function searchSecretsByName($pdo, $user_name, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $form, $button, $target) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $user_id = getUserIdByUserName($user_name, $form, $button, $target);
+
+ $stmt = $pdo->prepare("
+SELECT secrets.secret_id, secrets.secret_name, groups.group_id, groups.group_name
+FROM secrets
+LEFT JOIN fields ON secrets.secret_id = fields.secret_id
+LEFT JOIN groups ON secrets.group_id = groups.group_id
+WHERE secrets.user_id = :user_id
+AND secrets.secret_name like :search_name_filter
+AND COALESCE(groups.group_name,'') like :search_group_filter
+OR secrets.user_id = :user_id
+AND fields.field_type != 'password'
+AND fields.field_value like :search_name_filter
+AND COALESCE(groups.group_name,'') like :search_group_filter
+OR secrets.user_id = :user_id
+AND fields.field_name like :search_name_filter
+AND COALESCE(groups.group_name,'') like :search_group_filter
+GROUP BY secrets.secret_id
+ORDER BY ${primar_column_order_fld} ${primar_column_order_dir}, ${second_column_order_fld} ${second_column_order_dir};
+ ");
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([
+ ':user_id' => $user_id
+ ,':search_name_filter' => "%" . $search_name_filter . "%"
+ ,':search_group_filter' => "%" . $search_group_filter . "%"
+ ]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function printSecrets($secrets)
+ {
+ echo "
";
+ echo " ";
+ echo " Secrets |
";
+ echo " Secret_Id | Folder_Id | Secret_Date Id | Secret_Name | Group_Name |
";
+ echo " ";
+ echo " ";
+ foreach ($secrets as $secret)
+ {
+ echo " $secret->secret_id | $secret->user_id | ".date("Y-m-d H:i:s",$secret->secret_date)." | $secret->secret_name | $secret->group_name |
";
+ }
+ echo " ";
+ echo "
";
+ }
+
+//~ ----------------------------------
+
+ function insertGroup($pdo, $user_id, $group_name, $form, $button, $target)
+ {
+ //~ Stop if group_name exists
+
+ //~ group_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_name VARCHAR (255) NOT NULL
+
+ $stmt = $pdo->prepare('
+SELECT *
+FROM groups
+WHERE user_id = :user_id
+AND group_name = :group_name;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare1(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id, ':group_name' => $group_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute1(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+
+ $groupId = 0;
+
+ if ( count($object_array) == 0)
+ {
+ //~ New Group
+ $stmt = $pdo->prepare('
+ INSERT INTO groups(user_id, group_name) VALUES(:user_id, :group_name);
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare2(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id, ':group_name' => $group_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute2(..)", $button, $target);
+
+ $groupId = $pdo->lastInsertId();
+ }
+ else
+ {
+ //~ dboError($err, "header", $form, "insertGroup(\"$group_name\")", $button, $target); dboError(array("-","-","Roles: \"$role_name\" exists"), "header", $form, "execute1(..)", $button, $target);
+ $groupId = getGroupId($pdo, $user_id, $group_name, $form, $button, $target);
+ }
+
+ return $groupId;
+ }
+
+ function selectGroupById($pdo, $group_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('
+SELECT *
+FROM groups
+WHERE group_id = :group_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':group_id' => $group_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function getGroupId($pdo, $user_id, $group_name, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('
+SELECT group_id
+FROM groups
+WHERE user_id = :user_id
+AND group_name = :group_name;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id, ':group_name' => $group_name]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array[0]->group_id;
+ }
+
+ function selectGroups($pdo, $user_name, $form, $button, $target)
+ {
+ $user_id = getUserIdByUserName($user_name, $form, $button, $target);
+
+ //~ group_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_name VARCHAR (255) NOT NULL
+
+ $stmt = $pdo->prepare('
+SELECT group_name
+FROM groups
+WHERE user_id = :user_id
+ORDER BY group_name;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function printGroups($groups)
+ {
+ echo "
";
+ echo " ";
+ echo " Groups |
";
+ echo " Group Id | Group Name |
";
+ echo " ";
+ echo " ";
+ foreach ($groups as $group)
+ {
+ echo " $group->group_id | $group->group_name |
";
+ }
+ echo " ";
+ echo "
";
+ }
+
+ function updateGroup($pdo, $group_id, $group_name, $form, $button, $target)
+ {
+ //~ Update Secret
+ $stmt = $pdo->prepare('
+UPDATE groups
+SET group_name = :group_name
+WHERE group_id = :group_id;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':group_name' => $group_name, ':group_id' => $group_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+ }
+
+ function deleteGroupById($pdo, $group_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('DELETE FROM groups WHERE group_id = :group_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM groups..)", $button, $target);
+ $stmt->execute([':group_id' => $group_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':group_id' => \$group_id])", $button, $target);
+ }
+
+
+//~ ============================================================================
+
+
+ //~ group_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_name VARCHAR (255) NOT NULL,
+
+ //~ secret_id INTEGER PRIMARY KEY NOT NULL,
+ //~ user_id INTEGER NOT NULL,
+ //~ group_id INTEGER,
+ //~ secret_date INTEGER NOT NULL,
+ //~ secret_name VARCHAR (255) NOT NULL,
+
+ function searchGroupsByName($pdo, $user_name,$search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $form, $button, $target) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $user_id = getUserIdByUserName($user_name, $form, $button, $target);
+
+ $stmt = $pdo->prepare("
+SELECT groups.group_id, groups.group_name, COUNT(secrets.group_id) AS group_secrets
+FROM groups
+LEFT JOIN secrets ON groups.group_id = secrets.group_id
+WHERE groups.user_id = :user_id
+AND groups.group_name like :search_name_filter
+AND COALESCE(groups.group_name,'') like :search_group_filter
+GROUP BY groups.group_id
+ORDER BY ${primar_column_order_fld} ${primar_column_order_dir}, ${second_column_order_fld} ${second_column_order_dir};
+ ");
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([
+ ':user_id' => $user_id
+ ,':search_name_filter' => "%" . $search_name_filter . "%"
+ ,':search_group_filter' => "%" . $search_group_filter . "%"
+ ]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+
+//~ ============================================================================
+
+
+ function printSecretsFields($secretsfields)
+ {
+ echo "
";
+ echo " ";
+ echo " Secrets Fields |
";
+ echo " Secret_Name | Field Name | Field Type | Field ValueName |
";
+ echo " ";
+ echo " ";
+ foreach ($secretsfields as $secretsfield)
+ {
+ echo " $secretsfield->secret_name | $secretsfield->group_name | $secretsfield->field_name | $secretsfield->field_type | $secretsfield->field_value |
";
+ }
+ echo " ";
+ echo "
";
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ //~ field_id INTEGER PRIMARY KEY NOT NULL,
+ //~ secret_id INTEGER NOT NULL,
+ //~ field_ordr INTEGER NOT NULL,
+ //~ field_name VARCHAR (255) NOT NULL,
+ //~ field_type INTEGER (255) NOT NULL,
+ //~ field_value VARCHAR (255) NOT NULL,
+ //~ field_hash VARCHAR (255) NOT NULL,
+
+ function insertField($pdo, $user_id, $secret_id, $field_ordr, $field_name, $field_type, $field_value, $field_hash, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('INSERT INTO fields(user_id,secret_id,field_ordr,field_name,field_type,field_value,field_hash) VALUES(:user_id,:secret_id,:field_ordr,:field_name,:field_type,:field_value,:field_hash);');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id,':secret_id' => $secret_id,':field_ordr' => $field_ordr,':field_name' => $field_name,':field_type' => $field_type,':field_value' => $field_value,':field_hash' => $field_hash]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+ return $pdo->lastInsertId();
+ }
+
+ function selectFieldsBySecretId($pdo, $secret_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('SELECT * FROM fields WHERE secret_id = :secret_id ORDER BY field_ordr ASC;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([':secret_id' => $secret_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function selectSecretPasswordFieldsByUserId($pdo, $user_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('
+SELECT fields.*
+FROM fields
+LEFT JOIN secrets ON secrets.secret_id = fields.secret_id
+LEFT JOIN users ON secrets.user_id = users.user_id
+WHERE secrets.user_id = :user_id
+AND secrets.secret_id = fields.secret_id
+AND fields.field_type = "password"
+ORDER BY secrets.secret_name ASC;
+ ');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "query(..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+
+ $object_array = []; while ($record = $stmt->fetchObject()) { $object_array[] = $record; }
+ return $object_array;
+ }
+
+ function updateField($pdo, $field_id, $field_ordr, $field_name, $field_value, $field_hash, $form, $button, $target)
+ {
+ //~ New Secret
+ $stmt = $pdo->prepare('UPDATE fields SET field_ordr = :field_ordr, field_name = :field_name, field_value = :field_value, field_hash = :field_hash WHERE field_id = :field_id;');
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare(..)", $button, $target);
+ $stmt->execute([':field_id' => $field_id, ':field_ordr' => $field_ordr, ':field_name' => $field_name, ':field_value' => $field_value, ':field_hash' => $field_hash ]);
+ $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute(..)", $button, $target);
+ }
+
+ function deleteField($pdo, $field_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('DELETE FROM fields WHERE field_id = :field_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM fields..)", $button, $target);
+ $stmt->execute([':field_id' => $field_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':field_id' => \$field_id])", $button, $target);
+ }
+
+ function deleteFieldsByUserId($pdo, $user_id, $form, $button, $target)
+ {
+ $stmt = $pdo->prepare('DELETE FROM fields WHERE user_id = :user_id;'); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "prepare('DELETE FROM fields..)", $button, $target);
+ $stmt->execute([':user_id' => $user_id]); $errorArray = $pdo->errorInfo(); dboError($errorArray, "header", $form, "execute([':field_id' => \$field_id])", $button, $target);
+ }
+
+
+
+//~ ============================================================================
+ //~ End External Database Functions
+//~ ============================================================================
+
+ function random_str( $length, $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
+ {
+ $str = '';
+ $max = mb_strlen($keyspace, '8bit') - 1;
+ if ($max < 1) { throw new Exception('$keyspace must be at least two characters long'); }
+ for ($i = 0; $i < $length; ++$i) { $str .= $keyspace[random_int(0, $max)]; }
+ return $str;
+ }
+
+ function create_test_secrets($user_name, $pass_word, $num)
+ {
+ $form = "create_secret";
+ //~ require("fortune/fortune.php");
+ $fortune = new Fortune;
+ $fortune_dir = "/usr/share/games/fortunes/";
+ $fortune_file = "/usr/share/games/fortunes/anarchism.dat";
+ $dict_file = "/usr/share/dict/words";
+ //~ $fortune->quoteFromDir($fortune_dir);
+ //~ $fortune->getRandomQuote($fortune_file);
+
+
+ $groups_array = array(
+ "Arthur Aardvark"
+ ,"Bugs Bunny"
+ ,"Charlie Brown"
+ ,"Donald Duck"
+ ,"Eric Cartman"
+ ,"Fred Flintstone"
+ ,"Garfield"
+ ,"Homer Simpson"
+ ,"Inspector Gadget"
+ ,"Jake the Dog"
+ ,"King Louie"
+ ,"Lola Bunny"
+ ,"Mickey Mouse"
+ ,"Nickelodeon"
+ ,"Optimus Prime"
+ ,"Pink Panther"
+ ,"Quasimodo"
+ ,"Road Runner"
+ ,"Scooby Doo"
+ ,"Tom Cat"
+ ,"Ursula"
+ ,"Velma Dinkley"
+ ,"Wall-E"
+ ,"Xavier"
+ ,"Yogi Bear"
+ ,"Zelda"
+ );
+ $words_array = explode(PHP_EOL, preg_replace("~[^a-z0-9\n\r:]~i", "", strtolower(file_get_contents($dict_file))));
+ //~ array_slice($words_array, 0, $num);
+
+ $secrets = (array) null;
+
+ //~ echo "";
+ //~ echo "";
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $user_id = getUserIdByUserName($user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ Generating Test Secret
+ for ($c = 1; $c <= $num; $c++)
+ {
+ //~ Define secret name & fields
+ $secret_name = $words_array[array_rand($words_array)] . ".com";
+ $group_name = $groups_array[array_rand($groups_array)];
+
+ //~ Insert group
+ $group_id = insertGroup($pdo, $user_id, $group_name, $form,"[ â—€ OK â–¶ ]","index.php");
+
+ //~ Insert secret name & fields
+ $lastInsertSecretId = insertSecret($pdo, $user_id, $group_id, $secret_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ Multidimensional Fields Array
+ $fields = array (
+ array("URL", "url", "https://www." . $secret_name, "" ),
+ array("Login", "email", $words_array[array_rand($words_array)] . "@" . $words_array[array_rand($words_array)] . ".com", "" ),
+ array("Pass", "password", random_str(rand(6, 12)), random_str(rand(6, 12)) ),
+ array("Text", "text", rtrim(htmlspecialchars($fortune->getRandomQuote($fortune_file), ENT_QUOTES, 'UTF-8')), "" ),
+ array("Note", "textarea", rtrim(htmlspecialchars($fortune->getRandomQuote($fortune_file), ENT_QUOTES, 'UTF-8') . $fortune->getRandomQuote($fortune_file)), "" )
+ );
+
+ for ($row = 0; $row < count($fields); $row++)
+ {
+ if ( $fields[$row][1] === "password" ) { insertField($pdo, $user_id, $lastInsertSecretId, $row, $fields[$row][0], $fields[$row][1], encrypt_password($pass_word, $fields[$row][2]), hash($GLOBALS["user_encr_hash_type"], $fields[$row][2]), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { insertField($pdo, $user_id, $lastInsertSecretId, $row, $fields[$row][0], $fields[$row][1], $fields[$row][2], "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+ }
+
+ //~ echo "";
+ //~ echo "";
+ }
+ }
+
+
+
+
+//~ ============================================================================
+//~ Web Pages
+//~ ============================================================================
+
+
+
+
+ function send_html_header($identifier)
+ {
+ echo "$identifier";
+
+ print <<< EOF
+
+
+
+
+
+
Tiny Password Manager
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+EOF;
+
+ //~ Landing (no form)
+ connectDB("landing","[ â—€ OK â–¶ ]","index.php"); // Makes sure DB gets created at first landing
+ echo "";
+ //~ echo "
";
+ } // send_html_header()
+
+//~ ----------------------------------------------------------------------------
+
+
+//~ ============================================================================
+//~ Web Menu Parser
+//~ ============================================================================
+
+
+ function logoutString($user_name, $form, $button, $target)
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+ $role = getRoleNameByUserName($pdo, $user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $admin = userIsAdmin($user_name, $form, $button, $target);
+
+ if ( $admin ) { $logout_string = "\u{1F46E} $user_name
[ exit ]"; } // \u{2B95}
+ else { $logout_string = "\u{1F465} $user_name
[ exit ]"; } // \u{2B95}
+ return $logout_string;
+ }
+
+
+//~ ----------------------------------------------------------------------------
+
+
+ function getMenuItems($user_name, $new_secret, $new_group, $new_user, $show_users, $show_groups, $show_secrets, $change_password, $logout, $form, $button, $target)
+ {
+ if ( ! empty($user_name) ) { $user_id = getUserIdByUserName($user_name, $form, "[ â—€ OK â–¶ ]","index.php"); }
+
+ $new_secret_key = "new_secret"; $new_group_key = "new_group"; $new_user_key = "new_user"; $show_users_key = "show_users"; $show_groups_key = "show_groups"; $show_secrets_key = "show_secrets";
+ $change_password_key = "change_password"; $logout_key = "logout";
+
+ if ( ! empty($user_name) ) { $admin = userIsAdmin($user_name, $form, $button, $target); }
+
+ $menu_items = array ();
+
+ if ( ! empty($user_name) )
+ {
+ if ( $new_secret === strtolower($new_secret_key)) { $menu_items[] = array("new_secret_button", "", "", "", "New Secret", ""); } elseif ( $new_secret === strtoupper($new_secret_key)) { $menu_items[] = array("new_secret_button", "", "", "", "New Secret", "selected"); }
+ if ( $new_group === strtolower($new_group_key)) { $menu_items[] = array("new_group_button", "", "", "", "New Group", ""); } elseif ( $new_group === strtoupper($new_group_key)) { $menu_items[] = array("new_group_button", "", "", "", "New Group", "selected"); }
+ if ( $admin ) { if ( $new_user === strtolower($new_user_key)) { $menu_items[] = array("new_user_button", "", "", "", "New User", ""); } elseif ( $new_user === strtoupper($new_user_key)) { $menu_items[] = array("new_user_button", "", "", "", "New User", "selected"); } }
+ if ( $admin ) { if ( $show_users === strtolower($show_users_key)) { $menu_items[] = array("show_users_button", "", "", "", "Show Users", ""); } elseif ( $show_users === strtoupper($show_users_key)) { $menu_items[] = array("show_users_button", "", "", "", "Show Users", "selected"); } }
+ if ( $show_groups === strtolower($show_groups_key)) { $menu_items[] = array("show_groups_button", "", "", "", "Show Groups", ""); } elseif ( $show_groups === strtoupper($show_groups_key)) { $menu_items[] = array("show_groups_button", "", "", "", "Show Groups", "selected"); }
+ if ( $show_secrets === strtolower($show_secrets_key)) { $menu_items[] = array("show_secrets_button", "", "", "", "Show Secrets", ""); } elseif ( $show_secrets === strtoupper($show_secrets_key)) { $menu_items[] = array("show_secrets_button", "", "", "", "Show Secrets", "selected"); }
+ if ( $change_password === strtolower($change_password_key)) { $menu_items[] = array("change_password_button", "", "", $user_id, "Change Password", ""); } elseif ( $change_password === strtoupper($change_password_key)) { $menu_items[] = array("change_password_button", "", "", $user_id, "Change Password", "selected"); }
+ if ( $logout === strtolower($logout_key)) { $menu_items[] = array("logout_button", "Logout \u{1F464} $user_name", LOGOUT_ACTION, "", logoutString($user_name, $form, $button, $target), ""); } elseif ( $logout === strtoupper($logout_key)) { $menu_items[] = array("logout_button", "Logout \u{1F464} $user_name", LOGOUT_ACTION, "", logoutString($user_name, $form, $button, $target), "selected"); }
+ }
+
+ //~ print_r($menu_items);
+ return $menu_items;
+ }
+
+
+//~ ============================================================================
+//~ Web Menu Pane
+//~ ============================================================================
+
+
+ function send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items)
+ {
+ $form = "menu_form";
+
+ $logo_bg = $GLOBALS["logo_bg"];
+ $menu_bg = $GLOBALS["menu_bg"];
+
+ foreach($menu_items as $menu_item) // Only mobile menu when logged-in
+ {
+ if ( $menu_item[0] == "logout_button")
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+ $role = getRoleNameByUserName($pdo, $tp_login_uname, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $logout_string = "Logout $role [ $tp_login_uname ]";
+ //~ $logout_string = $menu_item[2];
+ $formwidth = ( strlen($logout_string) + 2);
+ $fieldwidth = strlen($logout_string);
+ //~ $formwidth = 12; $fieldwidth = 10;
+
+ echo "
\n";
+ echo "\n";
+
+ echo "\n";
+ echo "
\n";
+ echo "
\n";
+ echo "\n";
+
+ }
+ }
+
+
+ echo "\n";
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_post_script()
+ {
+ $form = "";
+ echo "";
+ echo "";
+ echo "";
+
+ echo "";
+
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_footer()
+ {
+ print <<< EOF
+
+
+EOF;
+ }
+
+
+//~ ============================================================================
+
+
+ function send_html_login_page($delay)
+ {
+ $form = "login_form";
+
+ sleep($delay); // Slows down brute force attacks
+ $login_bg = $GLOBALS["login_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems("", "" , "", "", "", "", "", "", "", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu("", "", "", "", "", "", "", "", $menu_items);
+
+ echo "
";
+ echo "
";
+ echo "";
+ echo "
";
+ echo "";
+
+ echo "";
+ echo "";
+
+ echo "";
+ echo "
";
+ echo " ";
+ echo "
";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+//~ ============================================================================
+//~ SHOW FORMS
+//~ ============================================================================
+
+
+//~ ============================================================================
+
+ function send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $form = "show_secrets_form";
+
+ $secretCounter = 0;
+ $fieldsCounter = 0;
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "new_secret" , "", "", "show_users", "show_groups", "SHOW_SECRETS", "change_password", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ //~ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Secrets
";
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+ echo " ";
+ echo " ";
+ echo " ";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $form = "show_groups_form";
+
+ $secretCounter = 0;
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "new_group", "", "show_users", "SHOW_GROUPS", "show_secrets", "change_password", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ //~ echo "";
+
+
+ echo "
";
+ echo "
";
+ echo " Groups
";
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+ echo " ";
+ echo " ";
+ echo " ";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir) // $primar_column_order_fld = "left_column" or "right_column", $primar_column_order_dir = "ASC"or "DESC"
+ {
+ $form = "show_users_form";
+
+ $secretCounter = 0;
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "new_user", "SHOW_USERS", "show_groups", "show_secrets", "change_password", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "\n";
+
+ //~ echo "\n";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+
+
+ echo "";
+ echo "";
+ echo "";
+
+ echo " ";
+ echo " ";
+ echo " ";
+ echo " ";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+
+//~ ============================================================================
+//~ CREATE FORMS
+//~ ============================================================================
+
+
+
+ function send_html_create_secret_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "create_secret_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "", "SHOW_SECRETS", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Secrets
";
+
+ echo " ";
+
+ echo " ";
+ echo " ";
+
+ echo " ";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_create_group_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "create_group_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "SHOW_GROUPS", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Groups
";
+
+ echo " ";
+
+ echo " ";
+ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_create_user_page($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "create_user_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "SHOW_USERS", "", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo " ";
+
+ echo " ";
+ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+
+//~ ============================================================================
+//~ VIEW FORMS
+//~ ============================================================================
+
+
+
+ function send_html_view_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "view_secret_form";
+
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "", "SHOW_SECRETS", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Secrets
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $records = selectSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "view_group_form";
+
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "SHOW_GROUPS", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Groups
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $records = selectGroupById($pdo, $group_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "view_user_form";
+
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "SHOW_USERS", "", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $records = selectUserById($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+
+//~ ============================================================================
+//~ EDIT FORMS
+//~ ============================================================================
+
+
+
+ function send_html_edit_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "update_secret_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "", "SHOW_SECRETS", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Secrets
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB("update_secret_form","[ â—€ OK â–¶ ]","index.php");
+ $records = selectSecretById($pdo, $secret_id, "update_secret_form","[ â—€ OK â–¶ ]","index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_edit_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "update_group_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "SHOW_GROUPS", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Groups
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB("update_group_form","[ â—€ OK â–¶ ]","index.php");
+ $records = selectGroupById($pdo, $group_id, "update_group_form","[ â—€ OK â–¶ ]","index.php");
+ $record = $records[0];
+
+ echo "";
+ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+//~ ============================================================================
+
+
+
+//~ ----------------------------------------------------------------------------
+
+ //~ Similar to view/edit_user_form
+
+ function send_html_change_password_page($user_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "change_password_form";
+
+ $fieldsCounter = 0;
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "", "", "CHANGE_PASSWORD", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $records = selectUserById($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+
+
+
+
+
+ function send_html_edit_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "update_user_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "SHOW_USERS", "", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form,"[ â—€ OK â–¶ ]","index.php");
+ $records = selectUserById($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+ $role_name = getRoleNameByUserName($pdo, $record->user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_copy_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "copy_secret_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "", "SHOW_SECRETS", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Secrets
";
+
+ echo " ";
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+ $records = selectSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_copy_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "copy_group_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "", "SHOW_GROUPS", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Groups
";
+
+ echo " ";
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+ $records = selectGroupById($pdo, $group_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+
+ echo "";
+ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+//~ ----------------------------------------------------------------------------
+
+ function send_html_copy_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir)
+ {
+ $form = "copy_user_form";
+
+ $default_bg = $GLOBALS["default_bg"];
+
+ send_html_header("");
+
+ $menu_items = getMenuItems($tp_login_uname, "" , "", "", "SHOW_USERS", "", "", "", "logout", $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_menu($tp_login_uname, $tp_login_pword, $search_name_filter, $search_group_filter, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir, $menu_items);
+
+ //~ echo "";
+
+ echo "";
+
+ echo "
";
+ echo "
";
+ echo " Users
";
+
+ echo " ";
+
+ //~ General Form Hidden Fields for maintaining state
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+ $records = selectUserById($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $record = $records[0];
+ $role_name = getRoleNameByUserName($pdo, $record->user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ echo "";
+ //~ echo "";
+
+ echo "";
+ echo "
";
+
+ send_html_post_script();
+ send_html_footer("");
+
+ exit();
+ }
+
+ //~ Used by external callers such as Tiny Setup
+ function change_password($user_name, $old_pass_word, $new_pass_word, $webcall)
+ {
+ $form = "change_password_form";
+
+ //~ Verify Old Password
+ if ( ! authenticateUser($user_name, $old_pass_word, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ($webcall)
+ {
+ dboError(array("-","-","Old Password Incorrect"), "header", $form, "authenticateUser(\"$user_name\")", "[ â—€ OK â–¶ ]","index.php");
+ }
+ else
+ {
+ //~ echo "Tiny Pass Authentication failed for user: \"$user_name\"! Old Password \"$old_pass_word\" -> \"$new_pass_word\" Incorrect!\n";
+ echo "Authentication failed for user: \"$user_name\" ! Change password for [Tiny Pass] manually !\n";
+ }
+ }
+ else
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+
+ $user_id = getUserIdByUserName($user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ $role_id = getRoleIdByUserName($pdo, $user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ Update User
+ updateUserCredentials($pdo, $role_id, $user_id, $user_name, $new_pass_word, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ Reencrypt Password
+ $fields = selectSecretPasswordFieldsByUserId($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ foreach ($fields as $field)
+ {
+ $field_decr = decrypt_password($old_pass_word, $field->field_value);
+
+ if ( hash($GLOBALS["user_encr_hash_type"], $field_decr) == $field->field_hash )
+ {
+ $field_encr = encrypt_password($new_pass_word, $field_decr);
+ updateField($pdo, $field->field_id, $field->field_ordr, $field->field_name, $field_encr, $field->field_hash, $form, "[ â—€ OK â–¶ ]","index.php");
+ }
+ else
+ {
+ if ($webcall)
+ {
+ dboError(array("-","-","Decryption failed for fields.field_id: " . $field->field_id), "header", $form, "updateUserCredentials(\"$user_name\")", "[ â—€ OK â–¶ ]","index.php");
+ }
+ else
+ {
+ echo "Tiny Pass Decryption failed for user: \"$user_name\" ! fields.field_id: " . $field->field_id . " \n";
+ }
+ }
+ }
+ }
+ }
+
+
+//~ ============================================================================
+ //~ Begin HTTP Connection
+//~ ============================================================================
+
+ //~ foreach ($_SERVER as $key => $value) { echo $key . " = " . $value. "
\n"; } exit();
+ //~ echo "\$_SERVER\n"; print_r($_SERVER); echo "\n";
+ //~ echo "\$_POST\n"; print_r($_POST); echo "\n";
+ //~ echo "\$_FILES\n"; print_r($_FILES); echo "\n";
+
+ if (! empty($_POST) || ! empty($_FILES))
+ {
+ if ( isset($_POST['tinypass_formname']) )
+ {
+
+ $form = $_POST['tinypass_formname'];
+
+ if ( isset($_POST['tp_login_uname']) ) { $tp_login_uname = htmlspecialchars($_POST['tp_login_uname'], ENT_QUOTES, 'UTF-8'); } else { $tp_login_uname = ""; }
+ if ( isset($_POST['tp_login_pword']) ) { $tp_login_pword = htmlspecialchars($_POST['tp_login_pword'], ENT_QUOTES, 'UTF-8'); } else { $tp_login_pword = ""; }
+
+ if ( isset($_POST['search_names']) ) { $search_names = htmlspecialchars($_POST['search_names'], ENT_QUOTES, 'UTF-8'); } else { $search_names = ""; }
+ if ( isset($_POST['search_groups']) ) { $search_groups = htmlspecialchars($_POST['search_groups'], ENT_QUOTES, 'UTF-8'); } else { $search_groups = ""; }
+
+ //~ Maintain $primar_column_order_fld & $primar_column_order_dir
+ if ( isset($_POST['menu_primar_column_order_fld']) ) { $primar_column_order_fld = htmlspecialchars($_POST['menu_primar_column_order_fld'], ENT_QUOTES, 'UTF-8'); } else { $primar_column_order_fld = ""; }
+ if ( isset($_POST['menu_primar_column_order_dir']) ) { $primar_column_order_dir = htmlspecialchars($_POST['menu_primar_column_order_dir'], ENT_QUOTES, 'UTF-8'); } else { $primar_column_order_dir = ""; }
+ if ( isset($_POST['menu_second_column_order_fld']) ) { $second_column_order_fld = htmlspecialchars($_POST['menu_second_column_order_fld'], ENT_QUOTES, 'UTF-8'); } else { $second_column_order_fld = ""; }
+ if ( isset($_POST['menu_second_column_order_dir']) ) { $second_column_order_dir = htmlspecialchars($_POST['menu_second_column_order_dir'], ENT_QUOTES, 'UTF-8'); } else { $second_column_order_dir = ""; }
+
+ if ( isset($_POST['primar_column_order_fld']) ) { $primar_column_order_fld = htmlspecialchars($_POST['primar_column_order_fld'], ENT_QUOTES, 'UTF-8'); } else { $primar_column_order_fld = ""; }
+ if ( isset($_POST['primar_column_order_dir']) ) { $primar_column_order_dir = htmlspecialchars($_POST['primar_column_order_dir'], ENT_QUOTES, 'UTF-8'); } else { $primar_column_order_dir = ""; }
+ if ( isset($_POST['second_column_order_fld']) ) { $second_column_order_fld = htmlspecialchars($_POST['second_column_order_fld'], ENT_QUOTES, 'UTF-8'); } else { $second_column_order_fld = ""; }
+ if ( isset($_POST['second_column_order_dir']) ) { $second_column_order_dir = htmlspecialchars($_POST['second_column_order_dir'], ENT_QUOTES, 'UTF-8'); } else { $second_column_order_dir = ""; }
+
+ //~ Change $primar_column_order_fld & $primar_column_order_dir on input
+ if ( isset($_POST['primar_column_order_field_inp_button']) ) { $primar_column_order_field_inp = htmlspecialchars($_POST['primar_column_order_field_inp_button'], ENT_QUOTES, 'UTF-8'); } else { $primar_column_order_field_inp = ""; }
+
+ if ($form == "login_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]", "index.php") ) // User authed
+ {
+ if ( authenticateUser($tp_login_uname, $GLOBALS["user_stnd_pass_word"], $form, "[ â—€ OK â–¶ ]", "index.php") ) // User has default pass and needs pass change
+ {
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]","index.php"); send_html_change_password_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, '', '', 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ }
+ }
+ else // user not authed
+ {
+ send_html_login_page(3);
+ }
+ }
+ elseif ($form == "menu_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]", "index.php") )
+ {
+ if (isset($_POST['new_secret_button'])) { send_html_create_secret_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif (isset($_POST['new_group_button'])) { send_html_create_group_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif (isset($_POST['new_user_button'])) { send_html_create_user_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif (isset($_POST['show_secrets_button'])) { send_html_show_secrets_page($tp_login_uname, $tp_login_pword, '', '', 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC'); }
+ elseif (isset($_POST['show_groups_button'])) { send_html_show_groups_page($tp_login_uname, $tp_login_pword, '', '', 'groups.group_name', 'ASC', 'group_secrets', 'ASC'); }
+ elseif (isset($_POST['show_users_button'])) { send_html_show_users_page($tp_login_uname, $tp_login_pword, '', '', 'users.user_name', 'ASC', 'user_secrets', 'ASC'); }
+ elseif (isset($_POST['change_password_button'])) { $user_id = htmlspecialchars($_POST['change_password_button'], ENT_QUOTES, 'UTF-8'); send_html_change_password_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif (isset($_POST['logout_button'])) { send_html_login_page(0); }
+ }
+ else { send_html_login_page(3); }
+ }
+ elseif ($form == "show_secrets_form" )
+ {
+ if ( isset($_POST['primar_column_order_field_inp_button']) )
+ {
+ //~ If same fields clicked
+ if ( $primar_column_order_field_inp == "secrets.secret_id" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = $primar_column_order_field_inp;
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "secrets.secret_name" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "groups.group_name";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "groups.group_name" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "secrets.secret_name";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]","index.php");
+
+ if (isset($_POST['view_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['view_secret_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['view_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['view_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['delete_selected_secrets_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+ foreach ($_POST as $key => $value)
+ {
+ if ( preg_match('/selected/', $key, $matches))
+ {
+ //~ echo "textfieldvalue: " . $key . " value: " . $value. "
\n";
+ $secret_id="$value";
+ deleteSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ }
+ }
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['export_selected_secrets_to_tinypass_format_to_csv_file_button']))
+ {
+ //~ $secrets = [];
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+//~ ----------------------------------------------------------------------------
+//~ Build the Ouput Array
+//~ ----------------------------------------------------------------------------
+
+ //~ Add Fields Header to output array
+ $csv_records[] = array_values(EXPORT_CSV_FORMATS["TinyPass"]["field_names1"]); // 1st header record
+
+ $line_counter = 0;
+ foreach ($_POST as $key => $value)
+ {
+ if ( preg_match('/^selected/', $key, $matches))
+ {
+ //~ echo "textfieldvalue: " . $key . " value: " . $value. "
\n";
+ $secret_id="$value";
+ $secrets = selectSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php"); $secret = $secrets[0];
+
+ //~ Add Secret record to output array
+ $csv_records[] = array($secret->secret_name, $secret->group_name, "", "", "", ""); // secret record
+
+ $line_counter++;
+
+ //~ echo "secret id: ". $secret->secret_id . "
\n";
+ $fields = selectFieldsBySecretId($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ print_r($fields); echo "
\n";
+
+ //~ Add Secret Fields records to output array
+ foreach ($fields as $field)
+ {
+ //~ If it's a password field decrypt it
+ if ( $field->field_type === 'password' ) { $csv_records[] = array("", "", "", $field->field_name, $field->field_type, decrypt_password($tp_login_pword,$field->field_value)); }
+ else { $csv_records[] = array("", "", "", $field->field_name, $field->field_type, $field->field_value); }
+ }
+ }
+ }
+
+ //~ print_r($csv_records); echo "
\n";
+
+//~ ----------------------------------------------------------------------------
+//~ Write the Ouput Array
+//~ ----------------------------------------------------------------------------
+
+ if ( $line_counter > 0 )
+ {
+ //~ ob_start();
+
+ ///~ ob_get_contents — Return the contents of the output buffer
+ ///~ ob_flush — Flush (send) the return value of the active output handler
+ ///~ ob_end_flush — Flush (send) the return value of the active output handler and turn the active output buffer off
+ ///~ ob_end_clean — Clean (erase) the contents of the active output buffer and turn it off
+
+ header('Content-Type: text/csv; charset=utf-8');
+ header("Content-Disposition: attachment; filename=". $GLOBALS['tiny_pass_export_file'] . "_server_". TINY_PASS_HOST . "_user_${tp_login_uname}" . "_search_names_${search_names}_". "search_groups_${search_groups}.csv");
+ //~ header('Pragma: no-cache'); // May not be longer support by browsers
+ //~ header('Expires: 0');
+
+ ///~ Writing records to output
+
+ if ( ($output_file_handle = fopen( 'php://output', 'w' )) !== FALSE ) { foreach( $csv_records as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } } fclose( $output_file_handle );
+
+ //~ ob_end_clean();
+
+ exit(); //~ Don't parse any non file export related HTML code inside this codeblock as it's addded to the filehandle corrupting export data so force exit
+ }
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ elseif (isset($_POST['export_selected_secrets_to_non_tiny_pass_csv_format_button']))
+ {
+ //~ $secrets = [];
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+//~ ----------------------------------------------------------------------------
+//~ Build the Ouput Array
+//~ ----------------------------------------------------------------------------
+
+ //~ Add Field Headers to the output arrays
+
+ $csv_records_edge_2[] = array_values(EXPORT_CSV_FORMATS["Edge_2"]["field_names1"]); // 4
+ $csv_records_1password_2[] = array_values(EXPORT_CSV_FORMATS["1Password_2"]["field_names1"]); // 4
+ $csv_records_chrome_2[] = array_values(EXPORT_CSV_FORMATS["Chrome_2"]["field_names1"]); // 5
+ $csv_records_keepass_2[] = array_values(EXPORT_CSV_FORMATS["KeePass_2"]["field_names1"]); // 5
+ $csv_records_dashlane_2[] = array_values(EXPORT_CSV_FORMATS["Dashlane_2"]["field_names1"]); // 7
+ $csv_records_firefox_2[] = array_values(EXPORT_CSV_FORMATS["Firefox_2"]["field_names1"]); // 9
+ $csv_records_1password2_2[] = array_values(EXPORT_CSV_FORMATS["1Password2_2"]["field_names1"]); // 9
+ $csv_records_bitwarden_2[] = array_values(EXPORT_CSV_FORMATS["Bitwarden_2"]["field_names1"]); // 11
+ $csv_records_teampass_2[] = array_values(EXPORT_CSV_FORMATS["TeamPass_2"]["field_names1"]); // 12
+ $csv_records_nordpass_2[] = array_values(EXPORT_CSV_FORMATS["NordPass_2"]["field_names1"]); // 19
+
+ $line_counter = 0;
+ $format_found = false;
+ $select_secrets_found = false;
+
+ foreach ($_POST as $key => $value)
+ {
+ if ( preg_match('/^selected/', $key, $matches))
+ {
+ $select_secrets_found = true;
+
+ //~ echo "textfieldvalue: " . $key . " value: " . $value. "
\n";
+ $secret_id="$value";
+ $secrets = selectSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php"); $secret = $secrets[0];
+
+ //~ Add Secret record to output array
+
+ $line_counter++;
+
+ //~ echo "secret id: ". $secret->secret_id . "
\n";
+ $fields = selectFieldsBySecretId($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ print_r($fields); echo "
\n";
+
+ $field_names = array_column($fields, 'field_name');
+ $field_types = array_column($fields, 'field_type');
+ $field_values = array_column($fields, 'field_value');
+
+ $counted_num_of_fields = count($field_names);
+
+ //~ print_r(array_values($field_names)); echo "
\n"; exit;
+
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["1Password_2"] || $std_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["Edge_2"] ) // 4
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["Edge_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_edge_2[] = $values_record;
+ }
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["1Password_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_1password_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["Chrome_2"] || $std_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["KeePass_2"] ) // 5
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["Chrome_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_chrome_2[] = $values_record;
+ }
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["KeePass_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_keepass_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["Dashlane_2"] ) // 12
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["Dashlane_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_dashlane_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["Firefox_2"] || $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["1Password2_2"] ) // 9
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["Firefox_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_firefox_2[] = $values_record;
+ }
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["1Password2_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_1password2_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["Bitwarden_2"] ) // 12
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["Bitwarden_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_bitwarden_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["TeamPass_2"] ) // 12
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["TeamPass_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_teampass_2[] = $values_record;
+ }
+ }
+ if ( $counted_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS["NordPass_2"] ) //19
+ {
+ if ( count(array_diff(array_map('strtolower', $field_names), array_map('strtolower', array_values(EXPORT_CSV_FORMATS["NordPass_2"]["field_names1"])) )) == 0 )
+ {
+ $format_found = true; $values_record = array();
+ for ($row = 0; $row < count(array_values($field_names)); $row++)
+ {
+ if ( array_values($field_types)[$row] === 'password' ) { array_push($values_record,decrypt_password($tp_login_pword,array_values($field_values)[$row])); }
+ else { array_push($values_record, array_values($field_values)[$row]); }
+ } $csv_records_nordpass_2[] = $values_record;
+ }
+ }
+ }
+ }
+
+//~ ----------------------------------------------------------------------------
+//~ Write the Ouput Arrays
+//~ ----------------------------------------------------------------------------
+
+ if ( $select_secrets_found )
+ {
+ $section = "--------------------------------------------------------------------------------" . PHP_EOL;
+ if ( ! $format_found )
+ {
+ echo "No NON Tiny Pass fields (for supported formats) amongs the selected records found !\n
";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ if ( ($output_file_handle = fopen( 'php://output', 'w' )) !== FALSE )
+ {
+ header('Content-Type: text/csv; charset=utf-8');
+ header("Content-Disposition: attachment; filename=". $GLOBALS['non_tiny_pass_export_file'] . "_server_". TINY_PASS_HOST . "_user_${tp_login_uname}" . "_search_names_${search_names}_". "search_groups_${search_groups}.csv");
+
+ fwrite($output_file_handle, "Please remove all non field lines (such as these comments) and empty lines !" . PHP_EOL);
+ fwrite($output_file_handle, "Copy each below [ Format Export Section ] (only the lines in between \"--------\")" . PHP_EOL . "into a seperate file before it can be imported by the related Password Manager." . PHP_EOL . PHP_EOL);
+ if ( count($csv_records_edge_2) > 1 ) { fwrite($output_file_handle, "[ Edge Export Section ]" . PHP_EOL . $section); foreach( $csv_records_edge_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_1password_2) > 1 ) { fwrite($output_file_handle, "[ 1Password Export Section ]" . PHP_EOL . $section); foreach( $csv_records_1password_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_chrome_2) > 1 ) { fwrite($output_file_handle, "[ Chrome Export Section ]" . PHP_EOL . $section); foreach( $csv_records_chrome_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_keepass_2) > 1 ) { fwrite($output_file_handle, "[ KeePass Export Section ]" . PHP_EOL . $section); foreach( $csv_records_keepass_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_dashlane_2) > 1 ) { fwrite($output_file_handle, "[ Dashlane Export Section ]" . PHP_EOL . $section); foreach( $csv_records_dashlane_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_firefox_2) > 1 ) { fwrite($output_file_handle, "[ Firefox Export Section ]" . PHP_EOL . $section); foreach( $csv_records_firefox_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_1password2_2) > 1 ) { fwrite($output_file_handle, "[ 1Password2 Export Section ]" . PHP_EOL . $section); foreach( $csv_records_1password2_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_bitwarden_2) > 1 ) { fwrite($output_file_handle, "[ Bitwarden Export Section ]" . PHP_EOL . $section); foreach( $csv_records_bitwarden_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_teampass_2) > 1 ) { fwrite($output_file_handle, "[ TeamPass Export Section ]" . PHP_EOL . $section); foreach( $csv_records_teampass_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+ if ( count($csv_records_nordpass_2) > 1 ) { fwrite($output_file_handle, "[ NordPass Export Section ]" . PHP_EOL . $section); foreach( $csv_records_nordpass_2 as $csv_record ) { fputcsv( $output_file_handle,$csv_record,",","\"" ); } fwrite($output_file_handle, $section . PHP_EOL); }
+
+ fclose( $output_file_handle );
+ exit(); //~ Don't parse any non file export related HTML code inside this codeblock as it's addded to the filehandle corrupting export data so force exit
+ }
+ }
+ }
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+ ///~ print_r($csv_records); echo "
\n";
+
+ }
+ elseif ( isset($_FILES['import_exported_secrets_in_limited_format_from_csv_file_button']) || isset($_FILES['import_exported_secrets_in_original_format_from_csv_file_button']) )
+ {
+ $filesArray1 = $_FILES['import_exported_secrets_in_limited_format_from_csv_file_button'];
+ $filesArray2 = $_FILES['import_exported_secrets_in_original_format_from_csv_file_button'];
+
+ if ( $filesArray1['error'] == UPLOAD_ERR_OK ) { $filesArray = $filesArray1; $limited_format_requested = true; } else { $limited_format_requested = false; }
+ if ( $filesArray2['error'] == UPLOAD_ERR_OK ) { $filesArray = $filesArray2; $original_format_requested = true; } else { $original_format_requested = false; }
+
+ if ( $filesArray['error'] !== UPLOAD_ERR_OK )
+ {
+ $uploadErrors = array(
+ 0 => 'There is no error, the file uploaded with success',
+ 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
+ 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
+ 3 => 'The uploaded file was only partially uploaded',
+ 4 => 'No file was uploaded',
+ 6 => 'Missing a temporary folder',
+ 7 => 'Failed to write file to disk.',
+ 8 => 'A PHP extension stopped the file upload.',
+ );
+ echo "Import Upload Error: " . $uploadErrors[$filesArray['error']] . "
\n";
+ }
+ else
+ {
+ $file_name = $filesArray["name"];
+ $file_type = $filesArray["type"];
+ $file_size = $filesArray["size"];
+ $tmp_name = $filesArray["tmp_name"];
+
+ //~ $file_name = $_FILES["import_secrets_in_original_format_from_csv_file_button"]["name"];
+ //~ $file_type = $_FILES["import_secrets_in_original_format_from_csv_file_button"]["type"];
+ //~ $file_size = $_FILES["import_secrets_in_original_format_from_csv_file_button"]["size"];
+ //~ $tmp_name = $_FILES["import_secrets_in_original_format_from_csv_file_button"]["tmp_name"];
+
+ ///~ echo "Upload: " . $file_name . "
";
+ ///~ echo "Type: " . $file_type . "
";
+ ///~ echo "Size: " . ($file_size) . " Bytes
";
+ ///~ echo "Stored in: " . $tmp_name . "
";
+
+ //~ It must be a CSV
+
+ if ( $file_type !== EXPORT_FILE_TYPE )
+ {
+ echo "Imported file: \"$file_name\" not of type \"". EXPORT_FILE_TYPE . "\"
";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+
+ //~ There must be data in it
+
+ if ( $file_size == 0 )
+ {
+ echo "Imported file: \"$file_name\" empty
";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ $records = [];
+
+ //~ After upload open the tmp file
+ if (($input_file_handle = fopen($tmp_name, "r")) !== FALSE)
+ {
+//~ ----------------------------------------------------------------------------
+//~ Header Quantity Validation
+//~ ----------------------------------------------------------------------------
+
+ //~ Row & Field Validation
+
+ $line_counter = 0; $std_num_of_fields = 0; $lowest_counted_num_of_fields = 0; $highest_counted_num_of_fields = 0;
+
+ while (($record = fgetcsv($input_file_handle,0,",",'"')) !== FALSE) // Old Way
+ {
+ $line_counter++;
+ $counted_num_of_fields = count($record);
+
+ //~ 1st row sets the standard number of rows that may not be defiated from
+
+ if ( $line_counter == 1 )
+ {
+ $lowest_counted_num_of_fields = $counted_num_of_fields; $highest_counted_num_of_fields = $counted_num_of_fields;
+
+ //~ Check if the Number of fields match the the known CSV Formats
+
+ if (! in_array($counted_num_of_fields, array_values(EXPORT_CSV_FORMATS_FIELD_LENGTHS)))
+ {
+ echo "Error in file: \"$file_name\" at row: $line_counter: Unsupported number of header fields: [
$counted_num_of_fields]/[
". EXPORT_CSV_FORMATS_FIELD_DESC . "]\n
";
+ echo "Invalid 1st Input Record Header: [". ($line_counter + 1) . "]: "; foreach ($record as $field) { echo trim($field) . ", "; } echo "\n
";
+ fclose($input_file_handle);
+
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else { $std_num_of_fields = $counted_num_of_fields; }
+ }
+ else // validate forbidden field number variations
+ {
+ //~ Check if the number of fields in the remaining rows are equal to the 1st row
+
+ if ( $counted_num_of_fields < $lowest_counted_num_of_fields ) { $lowest_counted_num_of_fields = $counted_num_of_fields; }
+ if ( $counted_num_of_fields > $highest_counted_num_of_fields ) { $highest_counted_num_of_fields = $counted_num_of_fields; }
+
+ if ( $lowest_counted_num_of_fields != $highest_counted_num_of_fields || $counted_num_of_fields != $std_num_of_fields )
+ {
+ echo "Error in file: \"$file_name\" at line: $line_counter: ";
+ //~ for ($c=0; $c < $counted_num_of_fields; $c++) { echo "[" . ($c + 1) . "]=\"$record[$c]\" "; }
+ echo "wrong num of fields: [
$counted_num_of_fields]/[
$std_num_of_fields] Corruption at line: $line_counter ?\n
";
+
+ fclose($input_file_handle);
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ //~ echo "line_counter $line_counter | std_num_of_fields $std_num_of_fields | lowest_counted_num_of_fields $lowest_counted_num_of_fields | highest_counted_num_of_fields $highest_counted_num_of_fields\n
";
+ }
+
+//~ ----------------------------------------------------------------------------
+//~ Header Quality Validation
+//~ ----------------------------------------------------------------------------
+
+ rewind($input_file_handle);
+
+ //~ Format num of standard fields (supported format) Validation
+
+
+
+ if (($record = fgetcsv($input_file_handle,0,",",'"')) !== FALSE) //~ Delete unicode BOM
+ {
+ $record[0] = ltrim($record[0]); // The PHP file handle inserts 4 extra spaces at the very start of the file (affecting header field 1 causing header match failures) which needs to be trimmed / removed at import
+ foreach (array_keys(EXPORT_CSV_FORMATS) as $key)
+ {
+ if ( ! preg_match('/^.+_2$/', $key, $matches))
+ {
+ //~ echo "$key\n
";
+ if ( $std_num_of_fields == EXPORT_CSV_FORMATS_FIELD_LENGTHS[$key] )
+ {
+ $line_counter = 0;
+ $format_found = false;
+
+ if ( count(array_diff(array_map('strtolower', $record), array_map('strtolower', array_values(EXPORT_CSV_FORMATS[$key]["field_names1"])) )) == 0 ) { $format_found = true; if ( $limited_format_requested ) { $format = $key; } else { if ( ${key} == "TinyPass" ) { $format = $key; } else { $format = $key . "_2"; } } break; }
+ }
+ }
+ }
+ }
+ else
+ {
+ echo "Error: no lines found in file: \"$file_name\"\n
";
+ fclose($input_file_handle);
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+ if (! format_found)
+ {
+ echo "Error in file: \"$file_name\"\n
";
+ fclose($input_file_handle);
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+
+//~ ----------------------------------------------------------------------------
+//~ Records Processing
+//~ ----------------------------------------------------------------------------
+
+
+ if ( $format_found && $format != "TinyPass" ) // Non Header Rows
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ ///~ echo "Processing General Record: [". ($line_counter + 1) . "]: "; foreach ($record as $field) { echo trim($field) . ", "; } echo "\n
";
+
+ while (($record = fgetcsv($input_file_handle,0,",",'"')) !== FALSE) //~ Delete unicode BOM
+ {
+ $field_counter = 0;
+
+ ///~ echo "Inserting Secret Record: [". ($line_counter + 1) . "]: $record[EXPORT_CSV_FORMATS[$format][\"group_name\"]] | $format | | | | \n
";
+ if ( EXPORT_CSV_FORMATS[$format]["secret_group"] > -1 ) { $group_id = insertGroup($pdo, $user_id, $record[EXPORT_CSV_FORMATS[$format]["secret_group"]], $form, "[ â—€ OK â–¶ ]", "index.php"); } //~ Insert group (gets ignored when it exists)
+ else { $group_id = insertGroup($pdo, $user_id, $format, $form, "[ â—€ OK â–¶ ]", "index.php"); } //~ Insert group (gets ignored when it exists)
+
+ $lastInsertSecretId = insertSecret($pdo, $user_id, $group_id, $record[EXPORT_CSV_FORMATS[$format]["secret_name"]], $form, "[ â—€ OK â–¶ ]", "index.php");
+ ///~ echo "
\ninsertSecret(" . $user_id . ", " . $group_id . ", " . record[EXPORT_CSV_FORMATS[$format][\"secret_name\"]] . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+ $fieldOrderCounter = 0;
+
+ foreach($record as $field)
+ {
+ //~ "secret_name" => 0,
+ //~ "secret_group" => -1,
+ //~ "field_names1" => [ "Name", "URL", "Username", "Password" ],
+ //~ "field_types" => [ "name", "url", "text", "password" ], // URL, Email, Pass, Text, Textarea
+ //~ "field_orders" => [ -1, 0, 1, 2 ], // -1, nr (-1 = ignore field)
+
+ //~ Non Ignored Field
+
+ if ( EXPORT_CSV_FORMATS[$format]["field_orders"][$field_counter] > -1 )
+ {
+ ///~ other -> field_name + field_type + field_value
+ $field_order_fld = EXPORT_CSV_FORMATS[$format]["field_orders"][$field_counter]; $field_name_fld = EXPORT_CSV_FORMATS[$format]["field_names2"][$field_counter]; $field_type_fld = EXPORT_CSV_FORMATS[$format]["field_types"][$field_counter]; $field_value_fld = $field;
+ ///~ echo "Inserting Field Record: [". ($line_counter + 1) . "]: | | $field_order_fld | $field_name_fld | $field_type_fld | $field_value_fld\n
";
+ if ( $field_type_fld == "password" ) { insertField($pdo, $user_id, $lastInsertSecretId, $field_order_fld, $field_name_fld, $field_type_fld, encrypt_password($tp_login_pword,$field_value_fld), hash($GLOBALS["user_encr_hash_type"], $field_value_fld), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { insertField($pdo, $user_id, $lastInsertSecretId, $field_order_fld, $field_name_fld, $field_type_fld, $field_value_fld, "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+ }
+
+ $field_counter++;
+ $fieldOrderCounter++;
+ }
+ $line_counter++;
+ }
+
+ fclose($input_file_handle);
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif ( $format_found && $format == "TinyPass" ) // Non Header Rows
+ {
+ //~ "secret_name" => 0,
+ //~ "secret_group" => -1,
+ //~ "field_names1" => [ "Name", "URL", "Username", "Password" ],
+ //~ "field_types" => [ "name", "url", "text", "password" ], // URL, Email, Pass, Text, Textarea
+ //~ "field_orders" => [ -1, 0, 1, 2 ], // -1, nr (-1 = ignore field)
+ //~ EXPORT_CSV_FORMATS[$format]["field_names1"][$field_counter]
+
+ $line_counter = 0;
+ $tinypass_format = false;
+
+ while (($record = fgetcsv($input_file_handle, 0, ",", '"')) !== FALSE)
+ {
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]", "index.php");
+
+ ///~ echo "Processing General Record: [". ($line_counter + 1) . "]: "; foreach ($record as $field) { echo trim($field) . ", "; } echo "\n
";
+
+ //~ "SecretName","GroupName","FieldOrder","FieldName","FieldType","FieldValue"
+
+ if ( ! empty($record[0]))
+ {
+ //~ echo "Inserting Secret Record: [". ($line_counter + 1) . "]: $record[0] | $record[1] | $record[2] | $record[3] | $record[4] | $record[5]\n
";
+ ///~ Insert group (gets ignored when it exists)
+ $group_id = insertGroup($pdo, $user_id, $record[1], $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $lastInsertSecretId = insertSecret($pdo, $user_id, $group_id, $record[0], $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ echo "
\ninsertSecret(" . $user_id . ", " . $group_id . ", " . $record[0] . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+
+ $fieldOrderCounter = 0;
+ }
+ elseif ( ! empty($record[3]) )
+ {
+ if ( ! empty($record[2]) ) { $fieldOrderCounter = $record[2]; } else { $record[2] = $fieldOrderCounter; }
+
+ //~ echo "Inserting Field Record: [". ($line_counter + 1) . "]: $record[0] | $record[1] | $record[2] | $record[3] | $record[4] | $record[5]\n
";
+ if ( $record[4] === "password" ) { insertField($pdo, $user_id, $lastInsertSecretId, $record[2], $record[3], $record[4], encrypt_password($tp_login_pword,$record[5]), hash($GLOBALS["user_encr_hash_type"], $record[5]), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { insertField($pdo, $user_id, $lastInsertSecretId, $record[2], $record[3], $record[4], $record[5], "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+ $fieldOrderCounter++;
+ }
+
+ $line_counter++;
+ } // while lines in tmp file
+
+ fclose($input_file_handle);
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else // unsupported num of fields
+ {
+ echo "Error in file: \"$file_name\" at row: $line_counter: ";
+ echo "Unsupported Header Format: [". ($line_counter + 1) . "]: "; foreach ($record as $field) { echo $field . ", "; } echo "\n
";
+ fclose($input_file_handle);
+
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ echo "Import Open Error: could not open uploaded file \"$tmp_name\"
";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ } // uploaded file empty
+ } // not a csv file
+ } // upload not okay
+ } // unknown button pressed
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "show_groups_form" )
+ {
+ if ( isset($_POST['primar_column_order_field_inp_button']) )
+ {
+ //~ If same fields clicked
+ if ( $primar_column_order_field_inp == "groups.group_id" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = $primar_column_order_field_inp;
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "groups.group_name" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "group_secrets";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "group_secrets" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "groups.group_name";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+ //~ if ( isset($_POST['primar_column_order_field_inp_button']) )
+ //~ {
+ //~ if ( $primar_column_order_field_inp == $primar_column_order_fld ) { if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; } else { $primar_column_order_dir = "ASC"; } }
+ //~ elseif ( $primar_column_order_field_inp != $primar_column_order_fld ) { $primar_column_order_fld = $primar_column_order_field_inp; $primar_column_order_dir = "ASC"; }
+ //~ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ }
+
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if (isset($_POST['view_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['view_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['show_secrets_button']))
+ {
+ $search_groups = htmlspecialchars($_POST['show_secrets_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ //~ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['delete_selected_groups_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+ foreach ($_POST as $key => $value)
+ {
+ if ( preg_match('/selected/', $key, $matches))
+ {
+ //~ echo "textfieldvalue: " . $key . " value: " . $value. "
\n";
+ $group_id="$value";
+ deleteGroupById($pdo, $group_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ }
+ }
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "show_users_form" )
+ {
+ if ( isset($_POST['primar_column_order_field_inp_button']) )
+ {
+ //~ If same fields clicked
+ if ( $primar_column_order_field_inp == "users.user_id" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = $primar_column_order_field_inp;
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "users.user_name" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "user_secrets";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ elseif ( $primar_column_order_field_inp == "user_secrets" )
+ {
+ $primar_column_order_fld = $primar_column_order_field_inp;
+ $second_column_order_fld = "users.user_name";
+ if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; $second_column_order_dir = "ASC"; } else { $primar_column_order_dir = "ASC"; $second_column_order_dir = "ASC"; }
+ }
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+
+ //~ if ( isset($_POST['primar_column_order_field_inp_button']) )
+ //~ {
+ //~ if ( $primar_column_order_field_inp == $primar_column_order_fld ) { if ( $primar_column_order_dir == "ASC" ) { $primar_column_order_dir = "DESC"; } else { $primar_column_order_dir = "ASC"; } }
+ //~ elseif ( $primar_column_order_field_inp != $primar_column_order_fld ) { $primar_column_order_fld = $primar_column_order_field_inp; $primar_column_order_dir = "ASC"; }
+ //~ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ }
+
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if (isset($_POST['view_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['view_user_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['show_secrets_button']))
+ {
+ $tp_login_uname = htmlspecialchars($_POST['show_secrets_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ }
+ elseif (isset($_POST['delete_selected_users_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+ foreach ($_POST as $key => $value)
+ {
+ if ( preg_match('/selected/', $key, $matches))
+ {
+ //~ echo "textfieldvalue: " . $key . " value: " . $value. "
\n";
+ $user_id="$value";
+ deleteUserByUserId($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ }
+ }
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "view_secret_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if (isset($_POST['edit_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['edit_secret_button'], ENT_QUOTES, 'UTF-8');
+ send_html_edit_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['copy_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['copy_secret_button'], ENT_QUOTES, 'UTF-8');
+ send_html_copy_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['delete_secret_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ $secret_id = htmlspecialchars($_POST['delete_secret_button'], ENT_QUOTES, 'UTF-8');
+ deleteSecretById($pdo, $secret_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['cancel_secret_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "view_group_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if (isset($_POST['edit_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['edit_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_edit_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['copy_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['copy_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_copy_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['delete_group_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ $group_id = htmlspecialchars($_POST['delete_group_button'], ENT_QUOTES, 'UTF-8');
+ deleteGroupById($pdo, $group_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['cancel_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "view_user_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if (isset($_POST['edit_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['edit_user_button'], ENT_QUOTES, 'UTF-8');
+ send_html_edit_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['copy_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['copy_user_button'], ENT_QUOTES, 'UTF-8');
+ send_html_copy_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['delete_user_button']))
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ $user_id = htmlspecialchars($_POST['delete_user_button'], ENT_QUOTES, 'UTF-8');
+ deleteUserByUserId($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['cancel_user_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "create_secret_form" || $form == "copy_secret_form")
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_secret_button']) && isset($_POST['secret_name']) && isset($_POST['group_name']) )
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ $secret_name = $_POST['secret_name'];
+ $group_name = $_POST['group_name'];
+
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ Insert group (gets ignored when it exists)
+ $group_id = insertGroup($pdo, $user_id, $group_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ $lastInsertSecretId = insertSecret($pdo, $user_id, $group_id, $secret_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ echo "
\ninsertSecret(" . $user_id . ", " . $group_id . ", " . $secret_name . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+
+ $fieldOrderCounter = 0;
+
+ foreach ($_POST as $key => $value)
+ {
+ //~ echo "key: " . $key . " value: " . $value . "
\n";
+ if ( preg_match('/textfieldname/', $key, $matches))
+ {
+ $field_name="$value";
+ //~ echo "textfieldname: " . $key . "
\n";
+ }
+
+ if ( preg_match('/textfieldtype/', $key, $matches))
+ {
+ $field_type="$value";
+ //~ echo "textfieldtype: " . $key . "
\n";
+ }
+
+ if ( preg_match('/textfieldvalu/', $key, $matches))
+ {
+ $field_value="$value";
+ $field_hash="$value";
+ //~ echo "textfieldvalue: " . $key . "
\n";
+
+ if ( $field_type === "password" ) { insertField($pdo, $user_id, $lastInsertSecretId, $fieldOrderCounter, $field_name, $field_type, encrypt_password($tp_login_pword,$field_value), hash($GLOBALS["user_encr_hash_type"], $field_value), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { insertField($pdo, $user_id, $lastInsertSecretId, $fieldOrderCounter, $field_name, $field_type, $field_value, "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+
+ $fieldOrderCounter++;
+ }
+ }
+
+ send_html_view_secret_page($lastInsertSecretId, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['cancel_secret_button'], ENT_QUOTES, 'UTF-8');
+ //~ echo "Cancel secret id: ". $secret_id . "
\n";
+
+ if ($form == "create_secret_form") { send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif ($form == "copy_secret_form") { send_html_view_secret_page($secret_id, $tp_login_uname,$tp_login_pword,$search_names,$search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ else { send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "create_group_form" || $form == "copy_group_form")
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_group_button']) && isset($_POST['group_name']) )
+ {
+ $group_name = $_POST['group_name'];
+
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]","index.php");
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ //~ Insert group (gets ignored when it exists)
+ $group_id = insertGroup($pdo, $user_id, $group_name, "create_group","[ â—€ OK â–¶ ]","index.php");
+
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['cancel_group_button'], ENT_QUOTES, 'UTF-8');
+ //~ echo "Cancel group id: ". $group_id . "
\n";
+
+ if ($form == "create_group_form") { send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif ($form == "copy_group_form") { send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ else { send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "create_user_form" || $form == "copy_user_form")
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_user_button']) && isset($_POST['role_name']) && isset($_POST['user_name']) && isset($_POST['pass_word']) )
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ $role_name = $_POST['role_name'];
+ $role_id = getRoleIdByRoleName($pdo, $role_name, $form, "[ â—€ OK â–¶ ]","index.php");
+
+ $user_name = $_POST['user_name'];
+ $pass_word = $_POST['pass_word'];
+
+ //~ insertUser($pdo, $role_id, $user_name, $pass_word, $form, $button, $target);
+ $user_id = insertUser($pdo, $role_id, $user_name, $pass_word, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ create_test_secrets($user_name, $pass_word, 11);
+
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['cancel_user_button'], ENT_QUOTES, 'UTF-8');
+
+ if ($form == "create_user_form") { send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ elseif ($form == "copy_user_form") { send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ else { send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "update_secret_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_secret_button']) && isset($_POST['secret_name']) && isset($_POST['group_name']) )
+ {
+ $secret_id = $_POST['save_secret_button'];
+ $secret_name = $_POST['secret_name'];
+ $group_name = $_POST['group_name'];
+
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]","index.php");
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ //~ Insert group (gets ignored when it exists)
+ $group_id = insertGroup($pdo, $user_id, $group_name, "create_secret","[ â—€ OK â–¶ ]","index.php");
+
+ updateSecret($pdo, $secret_id, $group_id, $secret_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ echo "
\nupdateSecret(" . $secret_id . ", " . $group_id . ", " . $secret_name . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+
+ $fieldOrderCounter = 0;
+
+ foreach ($_POST as $key => $value)
+ {
+ //~ echo "key: " . $key . " value: " . $value . "
\n";
+
+ if ( preg_match('/textfieldfunc/', $key, $matches))
+ {
+ $field_func="$value";
+ //~ echo "textfieldfunc: " . $key . "
\n";
+ }
+
+ if ( preg_match('/textfieldfdid/', $key, $matches))
+ {
+ $field_fdid = "$value";
+ //~ echo "textfieldfdid: " . $key . "
\n";
+ if ( $field_func == "DELETE" )
+ {
+ deleteField($pdo, $field_fdid, $form, "[ â—€ OK â–¶ ]","index.php");
+ //~ echo "deleteField(" . $field_fdid . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+ }
+ }
+
+ if ( preg_match('/textfieldname/', $key, $matches))
+ {
+ $field_name = "$value";
+ //~ echo "textfieldname: " . $key . "
\n";
+ }
+
+ if ( preg_match('/textfieldtype/', $key, $matches))
+ {
+ $field_type = "$value";
+ //~ echo "textfieldtype: " . $key . "
\n";
+ }
+
+ if ( preg_match('/textfieldvalu/', $key, $matches))
+ {
+ $field_value = "$value";
+ $field_hash = "$value";
+ //~ echo "textfieldvalue: " . $key . "
\n";
+
+ if ( $field_func == "UPDATE" )
+ {
+ if ( $field_type === "password" ) { updateField($pdo, $field_fdid, $fieldOrderCounter, $field_name, encrypt_password($tp_login_pword,$field_value), hash($GLOBALS["user_encr_hash_type"], $field_value), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { updateField($pdo, $field_fdid, $fieldOrderCounter, $field_name, $field_value, "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+
+ //~ updateField($pdo, $field_fdid, $fieldOrderCounter, $field_name, $field_value, "", $form, "[ â—€ OK â–¶ ]","index.php");
+ //~ echo "updateField(" . $field_fdid . ", " . $field_ordr . ", " . $field_name . ", " . $field_value .", " . $field_hash . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+ $fieldOrderCounter++;
+ }
+ elseif ( $field_func == "DELETE" )
+ {
+ deleteField($pdo, $field_fdid, $form, "[ â—€ OK â–¶ ]","index.php");
+ //~ echo "deleteField(" . $field_fdid . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+ }
+ elseif ( $field_func == "INSERT" )
+ {
+ if ( $field_type === "password" ) { insertField($pdo, $user_id, $secret_id, $fieldOrderCounter, $field_name, $field_type, encrypt_password($tp_login_pword,$field_value), hash($GLOBALS["user_encr_hash_type"], $field_value), $form, "[ â—€ OK â–¶ ]","index.php"); }
+ else { insertField($pdo, $user_id, $secret_id, $fieldOrderCounter, $field_name, $field_type, $field_value, "", $form, "[ â—€ OK â–¶ ]","index.php"); }
+
+
+ //~ insertField($pdo, $user_id, $secret_id, $fieldOrderCounter, $field_name, $field_type, $field_value, "", $form, "[ â—€ OK â–¶ ]","index.php");
+ //~ echo "insertField(" . $user_id . ", " . $secret_id . ", " . $field_ordr . ", " . $field_name . ", " . $field_type . ", " . $field_value .", " . $field_hash . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+ $fieldOrderCounter++;
+ }
+ else
+ {
+ $message = "Error form field_func: " . $field_func . " parameter invalid! (can only be: UPDATE, DELETE or INSERT)";
+ $instruction = "
Please report this incident to Tiny Server Support!
";
+ message($message, $form, $instruction, $button, $target);
+ }
+ }
+ }
+
+ send_html_view_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_secret_button']))
+ {
+ $secret_id = htmlspecialchars($_POST['cancel_secret_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_secret_page($secret_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ //~ echo "Not Authenticated
\n";
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "update_group_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_group_button']) && isset($_POST['group_name']) )
+ {
+ $group_id = $_POST['save_group_button'];
+ $group_name = $_POST['group_name'];
+
+ $user_id = getUserIdByUserName($tp_login_uname, $form, "[ â—€ OK â–¶ ]","index.php");
+
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+
+ updateGroup($pdo, $group_id, $group_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ echo "
\nupdateSecret(" . $group_id . ", " . $group_name . ", " . $form . ", \"[ â—€ OK â–¶ ]\",\"index.php\");
\n";
+
+ send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ //~ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ elseif (isset($_POST['cancel_group_button']))
+ {
+ $group_id = htmlspecialchars($_POST['cancel_group_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_group_page($group_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_groups_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ //~ echo "Not Authenticated
\n";
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "update_user_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ //~ if ( isset($_POST['save_user_button']) && isset($_POST['role_name']) && isset($_POST['user_name']) && isset($_POST['old_pass_word']) && isset($_POST['new_pass_word']) )
+ if ( isset($_POST['save_user_button']) && isset($_POST['role_name']) && isset($_POST['user_name']) )
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+ $user_id = $_POST['save_user_button'];
+ $role_name = $_POST['role_name'];
+ $role_id = getRoleIdByRoleName($pdo, $role_name, $form, "[ â—€ OK â–¶ ]","index.php");
+ $user_name = $_POST['user_name'];
+ //~ $old_pass_word = $_POST['old_pass_word'];
+ //~ $new_pass_word = $_POST['new_pass_word'];
+
+ ///~ Verify Old Password
+ if ( ! authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ dboError(array("-","-","Old Password Incorrect"), "header", $form, "authenticateUser(\"$user_name\")", "[ â—€ OK â–¶ ]","index.php");
+ send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ if ( $user_name === "admin" || $user_name === "tiny" )
+ {
+ send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ // Update User
+
+ echo "updateUser(\$pdo, $role_id, $user_id, $user_name, $form, \"[ â—€ OK â–¶ ]\", \"index.php\");";
+
+ updateUser($pdo, $role_id, $user_id, $user_name, $form, "[ â—€ OK â–¶ ]", "index.php");
+
+ //~ // Reencrypt Password
+
+ //~ $fields = selectSecretPasswordFieldsByUserId($pdo, $user_id, $form, "[ â—€ OK â–¶ ]", "index.php");
+ //~ foreach ($fields as $field)
+ //~ {
+ //~ $field_decr = decrypt_password($old_pass_word, $field->field_value);
+
+ //~ if ( hash($GLOBALS["user_encr_hash_type"], $field_decr) == $field->field_hash )
+ //~ {
+ //~ $field_encr = encrypt_password($new_pass_word, $field_decr);
+ //~ updateField($pdo, $field->field_id, $field->field_ordr, $field->field_name, $field_encr, $field->field_hash, $form, "[ â—€ OK â–¶ ]","index.php");
+ //~ }
+ //~ else { dboError(array("-","-","Decryption failed for fields.field_id: " . $field->field_id), "header", $form, "updateUser(\"$user_name\")", "[ â—€ OK â–¶ ]","index.php"); }
+ //~ }
+ //~ if ( $user_name == $tp_login_uname ) { send_html_view_user_page($user_id, $tp_login_uname, $new_pass_word, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ //~ else { send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+
+ // View User
+
+ if ( $user_name == $tp_login_uname ) { send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ else { send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir); }
+ } // valid new username
+ } // not authenticated
+
+ }
+ elseif (isset($_POST['cancel_user_button']))
+ {
+ $user_id = htmlspecialchars($_POST['cancel_user_button'], ENT_QUOTES, 'UTF-8');
+ send_html_view_user_page($user_id, $tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_users_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ }
+ else
+ {
+ //~ echo "Not Authenticated
\n";
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ elseif ($form == "change_password_form" )
+ {
+ if ( authenticateUser($tp_login_uname, $tp_login_pword, $form, "[ â—€ OK â–¶ ]","index.php") )
+ {
+ if ( isset($_POST['save_password_button']) && isset($_POST['role_name']) && isset($_POST['user_name']) && isset($_POST['old_pass_word']) && isset($_POST['new_pass_word']) )
+ {
+ $pdo = connectDB($form, "[ â—€ OK â–¶ ]","index.php");
+ $user_id = $_POST['save_password_button'];
+ $role_name = $_POST['role_name'];
+ $role_id = getRoleIdByRoleName($pdo, $role_name, $form, "[ â—€ OK â–¶ ]","index.php");
+ $user_name = $_POST['user_name'];
+ $old_pass_word = $_POST['old_pass_word'];
+ $new_pass_word = $_POST['new_pass_word'];
+
+ change_password($user_name, $old_pass_word, $new_pass_word, true);
+
+ if ( authenticateUser("tiny", $GLOBALS["user_stnd_pass_word"], $form, "[ â—€ OK â–¶ ]", "index.php") ) // User has default pass and needs pass change
+ {
+ $user_id = getUserIdByUserName("tiny", $form, "[ â—€ OK â–¶ ]","index.php"); send_html_change_password_page($user_id, "tiny", $GLOBALS["user_stnd_pass_word"], $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ send_html_login_page(0);
+ }
+ else
+ {
+ if ( $old_pass_word == $GLOBALS["user_stnd_pass_word"] )
+ {
+ send_html_login_page(0);
+ }
+ else
+ {
+ send_html_show_secrets_page($tp_login_uname, $new_pass_word, $search_names, $search_groups, 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ }
+ }
+ }
+ elseif (isset($_POST['cancel_password_button']))
+ {
+ //~ $user_id = htmlspecialchars($_POST['cancel_password_button'], ENT_QUOTES, 'UTF-8');
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ }
+ else
+ {
+ //~ echo "Pressed Other Button
\n";
+ send_html_show_secrets_page($tp_login_uname, $tp_login_pword, $search_names, $search_groups, 'secrets.secret_name', 'ASC', 'groups.group_name', 'ASC');
+ }
+ }
+ else
+ {
+ //~ echo "Not Authenticated
\n";
+ send_html_login_page(3);
+ }
+ exit();
+ }
+ else
+ {
+ send_html_header("");
+ while (@ ob_end_flush());
+ echo "
";
+ echo '
';
+
+ echo "T E R M I N A L
";
+
+ echo "[ Invalid Form ]
*** Invalid Form Submitted ***
";
+ echo "
Please report this incident to Tiny Server Support!
";
+
+ echo '';
+ $button = "[ â—€ OK â–¶ ]"; $target = "index.php#createlicense"; echo "
";
+ exit();
+ }
+ }
+ }
+ elseif (PHP_SAPI === 'cli' || empty($_SERVER['REMOTE_ADDR'])) // from command line
+ {
+ //~ echo "SERVER\n";
+ //~ foreach ($_SERVER as $key => $value) { echo $key . " = " . $value. "
\n"; }
+ //~ echo "\n";
+ //~ exit();
+
+ $options = getopt(null, array("call_func:","user_name:","old_pass_word:","new_pass_word:"));
+
+ if ( count($options) > 0 )
+ {
+ if ( isset($options['call_func']) )
+ {
+ $call_func = rtrim("$options[call_func]");
+
+ if ( $call_func === "change_password" )
+ {
+ if ( isset($options['user_name']) ) { $user_name = rtrim("$options[user_name]"); } else { usage("Warning: Shell -> PHP Function: \"$call_func\" --user_name=\"user\" missing !"); }
+ if ( isset($options['old_pass_word']) ) { $old_pass_word = rtrim("$options[old_pass_word]"); } else { usage("Warning: Shell -> PHP Function: \"$call_func\" --old_pass_word=\"old_password\" missing !"); }
+ if ( isset($options['new_pass_word']) ) { $new_pass_word = rtrim("$options[new_pass_word]"); } else { usage("Warning: Shell -> PHP Function: \"$call_func\" --new_pass_word=\"new_password\" missing !"); }
+
+ if ( $old_pass_word === $new_pass_word ) { usage("Warning: Shell -> PHP Function: \"$call_func\" --old_pass_word=\"$old_pass_word\" --new_pass_word=\"$new_pass_word\" are equal ! Aborting !"); }
+
+ //~ Test Shell -> PHP Function
+ //~ php "/home/tiny/Services/by-name/apache2/apps/tinypass/www/index.php" --call_func="change_password" --user_name="admin" --old_pass_word="old_pass_word" --new_pass_word="new_pass_word";
+
+ //~ echo "\ncall_func: $call_func\nuser_name: $user_name\nold_sys_pass: $old_pass_word\nnew_sys_pass: $new_pass_word\n\n";
+ change_password($user_name, $old_pass_word, $new_pass_word, false);
+ }
+ else
+ {
+ usage("Warning: Shell -> PHP Function: \"--call_func=\"$call_func\" unknown !");
+ }
+ }
+ else
+ {
+ usage("Warning: Shell -> PHP Option: \"--call_func=\"php_function\" not set !");
+ }
+ }
+ else
+ {
+ usage("Warning: Shell -> No PHP Options !");
+ }
+ }
+ else // Defaults to web interface landing
+ {
+ if ( authenticateUser("admin", $GLOBALS["user_stnd_pass_word"], $form, "[ â—€ OK â–¶ ]", "index.php") ) // User has default pass and needs pass change
+ {
+ $user_id = getUserIdByUserName("admin", $form, "[ â—€ OK â–¶ ]","index.php"); send_html_change_password_page($user_id, "admin", $GLOBALS["user_stnd_pass_word"], $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else if ( authenticateUser("tiny", $GLOBALS["user_stnd_pass_word"], $form, "[ â—€ OK â–¶ ]", "index.php") ) // User has default pass and needs pass change
+ {
+ $user_id = getUserIdByUserName("tiny", $form, "[ â—€ OK â–¶ ]","index.php"); send_html_change_password_page($user_id, "tiny", $GLOBALS["user_stnd_pass_word"], $search_names, $search_groups, $primar_column_order_fld, $primar_column_order_dir, $second_column_order_fld, $second_column_order_dir);
+ }
+ else
+ {
+ send_html_login_page(0);
+ }
+ }
+
+ function usage($message)
+ {
+ //~ echo "\$_SERVER\n"; print_r($_SERVER); echo "\n";
+ //~ echo "\$_POST\n"; print_r($_POST); echo "\n";
+ //~ echo "\$_FILES\n"; print_r($_FILES); echo "\n";
+
+ echo "\n";
+ echo basename($_SERVER['SCRIPT_FILENAME']) . " <--call_func=\"function\" [--param1=\"value1\"] [--param2=\"value2\"] ..\n";
+ echo "\n";
+ echo "Options\n";
+ echo "\n";
+ echo " --call_func=\"change_password\" --user_name=\"user\" --old_pass_word=\"current_password\" --new_pass_word=\"new_password\"\n";
+ echo "\n";
+ echo "Example\n";
+ echo "\n";
+ echo "php \"". $_SERVER['SCRIPT_FILENAME']. "\" --call_func=\"change_password\" --user_name=\"user\" --old_pass_word=\"oldpass\" --new_pass_word=\"newpass\";\n";
+ echo "\n";
+ if ( ! empty($message) )
+ {
+ echo "$message\n\n";
+ }
+ exit(1);
+ }
+ ?>
diff --git a/js/main.js b/js/main.js
new file mode 100755
index 0000000..00e22f6
--- /dev/null
+++ b/js/main.js
@@ -0,0 +1,83 @@
+
+(function ($) {
+ "use strict";
+
+ /*==================================================================
+ [ Validate ]*/
+ var input = $('.validate-input .input100');
+
+ $('.validate-form').on('submit',function(){
+ var check = true;
+
+ for(var i=0; i
= itemSlide.length) {nowSlide = 0;} */
+
+ setInterval(function()
+ {
+ slide('up');
+ //~ $(itemSlide).fadeOut(speed);
+ //~ $(itemSlide[nowSlide]).fadeIn(speed);
+ //~ nowSlide = Math.floor(Math.random() * itemSlide.length);
+ /* if(nowSlide >= itemSlide.length) {nowSlide = 0;} */
+ },delay);
+ });
+
+
+})(jQuery);
diff --git a/js/plugins.js b/js/plugins.js
new file mode 100755
index 0000000..7612e71
--- /dev/null
+++ b/js/plugins.js
@@ -0,0 +1,6749 @@
+/*
+ _ _ _ _
+ ___| (_) ___| | __ (_)___
+/ __| | |/ __| |/ / | / __|
+\__ \ | | (__| < _ | \__ \
+|___/_|_|\___|_|\_(_)/ |___/
+ |__/
+
+ Version: 1.8.0
+ Author: Ken Wheeler
+ Website: http://kenwheeler.github.io
+ Docs: http://kenwheeler.github.io/slick
+ Repo: http://github.com/kenwheeler/slick
+ Issues: http://github.com/kenwheeler/slick/issues
+
+ */
+/* global window, document, define, jQuery, setInterval, clearInterval */
+(function(factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ define(['jquery'], factory);
+ } else if (typeof exports !== 'undefined') {
+ module.exports = factory(require('jquery'));
+ } else {
+ factory(jQuery);
+ }
+
+}(function($) {
+ 'use strict';
+ var Slick = window.Slick || {};
+
+ Slick = (function() {
+
+ var instanceUid = 0;
+
+ function Slick(element, settings) {
+
+ var _ = this, dataSettings;
+
+ _.defaults = {
+ accessibility: true,
+ adaptiveHeight: false,
+ appendArrows: $(element),
+ appendDots: $(element),
+ arrows: true,
+ asNavFor: null,
+ prevArrow: '',
+ nextArrow: '',
+ autoplay: false,
+ autoplaySpeed: 3000,
+ centerMode: false,
+ centerPadding: '50px',
+ cssEase: 'ease',
+ customPaging: function(slider, i) {
+ return $('').text(i + 1);
+ },
+ dots: false,
+ dotsClass: 'slick-dots',
+ draggable: true,
+ easing: 'linear',
+ edgeFriction: 0.35,
+ fade: false,
+ focusOnSelect: false,
+ infinite: true,
+ initialSlide: 0,
+ lazyLoad: 'ondemand',
+ mobileFirst: false,
+ pauseOnHover: true,
+ pauseOnFocus: true,
+ pauseOnDotsHover: false,
+ respondTo: 'window',
+ responsive: null,
+ rows: 1,
+ rtl: false,
+ slide: '',
+ slidesPerRow: 1,
+ slidesToShow: 1,
+ slidesToScroll: 1,
+ speed: 500,
+ swipe: true,
+ swipeToSlide: false,
+ touchMove: true,
+ touchThreshold: 5,
+ useCSS: true,
+ useTransform: true,
+ variableWidth: false,
+ vertical: false,
+ verticalSwiping: false,
+ waitForAnimate: true,
+ zIndex: 1000
+ };
+
+ _.initials = {
+ animating: false,
+ dragging: false,
+ autoPlayTimer: null,
+ currentDirection: 0,
+ currentLeft: null,
+ currentSlide: 0,
+ direction: 1,
+ $dots: null,
+ listWidth: null,
+ listHeight: null,
+ loadIndex: 0,
+ $nextArrow: null,
+ $prevArrow: null,
+ slideCount: null,
+ slideWidth: null,
+ $slideTrack: null,
+ $slides: null,
+ sliding: false,
+ slideOffset: 0,
+ swipeLeft: null,
+ $list: null,
+ touchObject: {},
+ transformsEnabled: false,
+ unslicked: false
+ };
+
+ $.extend(_, _.initials);
+
+ _.activeBreakpoint = null;
+ _.animType = null;
+ _.animProp = null;
+ _.breakpoints = [];
+ _.breakpointSettings = [];
+ _.cssTransitions = false;
+ _.focussed = false;
+ _.interrupted = false;
+ _.hidden = 'hidden';
+ _.paused = true;
+ _.positionProp = null;
+ _.respondTo = null;
+ _.rowCount = 1;
+ _.shouldClick = true;
+ _.$slider = $(element);
+ _.$slidesCache = null;
+ _.transformType = null;
+ _.transitionType = null;
+ _.visibilityChange = 'visibilitychange';
+ _.windowWidth = 0;
+ _.windowTimer = null;
+
+ dataSettings = $(element).data('slick') || {};
+
+ _.options = $.extend({}, _.defaults, settings, dataSettings);
+
+ _.currentSlide = _.options.initialSlide;
+
+ _.originalSettings = _.options;
+
+ if (typeof document.mozHidden !== 'undefined') {
+ _.hidden = 'mozHidden';
+ _.visibilityChange = 'mozvisibilitychange';
+ } else if (typeof document.webkitHidden !== 'undefined') {
+ _.hidden = 'webkitHidden';
+ _.visibilityChange = 'webkitvisibilitychange';
+ }
+
+ _.autoPlay = $.proxy(_.autoPlay, _);
+ _.autoPlayClear = $.proxy(_.autoPlayClear, _);
+ _.autoPlayIterator = $.proxy(_.autoPlayIterator, _);
+ _.changeSlide = $.proxy(_.changeSlide, _);
+ _.clickHandler = $.proxy(_.clickHandler, _);
+ _.selectHandler = $.proxy(_.selectHandler, _);
+ _.setPosition = $.proxy(_.setPosition, _);
+ _.swipeHandler = $.proxy(_.swipeHandler, _);
+ _.dragHandler = $.proxy(_.dragHandler, _);
+ _.keyHandler = $.proxy(_.keyHandler, _);
+
+ _.instanceUid = instanceUid++;
+
+ // A simple way to check for HTML strings
+ // Strict HTML recognition (must start with <)
+ // Extracted from jQuery v1.11 source
+ _.htmlExpr = /^(?:\s*(<[\w\W]+>)[^>]*)$/;
+
+
+ _.registerBreakpoints();
+ _.init(true);
+
+ }
+
+ return Slick;
+
+ }());
+
+ Slick.prototype.activateADA = function() {
+ var _ = this;
+
+ _.$slideTrack.find('.slick-active').attr({
+ 'aria-hidden': 'false'
+ }).find('a, input, button, select').attr({
+ 'tabindex': '0'
+ });
+
+ };
+
+ Slick.prototype.addSlide = Slick.prototype.slickAdd = function(markup, index, addBefore) {
+
+ var _ = this;
+
+ if (typeof(index) === 'boolean') {
+ addBefore = index;
+ index = null;
+ } else if (index < 0 || (index >= _.slideCount)) {
+ return false;
+ }
+
+ _.unload();
+
+ if (typeof(index) === 'number') {
+ if (index === 0 && _.$slides.length === 0) {
+ $(markup).appendTo(_.$slideTrack);
+ } else if (addBefore) {
+ $(markup).insertBefore(_.$slides.eq(index));
+ } else {
+ $(markup).insertAfter(_.$slides.eq(index));
+ }
+ } else {
+ if (addBefore === true) {
+ $(markup).prependTo(_.$slideTrack);
+ } else {
+ $(markup).appendTo(_.$slideTrack);
+ }
+ }
+
+ _.$slides = _.$slideTrack.children(this.options.slide);
+
+ _.$slideTrack.children(this.options.slide).detach();
+
+ _.$slideTrack.append(_.$slides);
+
+ _.$slides.each(function(index, element) {
+ $(element).attr('data-slick-index', index);
+ });
+
+ _.$slidesCache = _.$slides;
+
+ _.reinit();
+
+ };
+
+ Slick.prototype.animateHeight = function() {
+ var _ = this;
+ if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
+ var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
+ _.$list.animate({
+ height: targetHeight
+ }, _.options.speed);
+ }
+ };
+
+ Slick.prototype.animateSlide = function(targetLeft, callback) {
+
+ var animProps = {},
+ _ = this;
+
+ _.animateHeight();
+
+ if (_.options.rtl === true && _.options.vertical === false) {
+ targetLeft = -targetLeft;
+ }
+ if (_.transformsEnabled === false) {
+ if (_.options.vertical === false) {
+ _.$slideTrack.animate({
+ left: targetLeft
+ }, _.options.speed, _.options.easing, callback);
+ } else {
+ _.$slideTrack.animate({
+ top: targetLeft
+ }, _.options.speed, _.options.easing, callback);
+ }
+
+ } else {
+
+ if (_.cssTransitions === false) {
+ if (_.options.rtl === true) {
+ _.currentLeft = -(_.currentLeft);
+ }
+ $({
+ animStart: _.currentLeft
+ }).animate({
+ animStart: targetLeft
+ }, {
+ duration: _.options.speed,
+ easing: _.options.easing,
+ step: function(now) {
+ now = Math.ceil(now);
+ if (_.options.vertical === false) {
+ animProps[_.animType] = 'translate(' +
+ now + 'px, 0px)';
+ _.$slideTrack.css(animProps);
+ } else {
+ animProps[_.animType] = 'translate(0px,' +
+ now + 'px)';
+ _.$slideTrack.css(animProps);
+ }
+ },
+ complete: function() {
+ if (callback) {
+ callback.call();
+ }
+ }
+ });
+
+ } else {
+
+ _.applyTransition();
+ targetLeft = Math.ceil(targetLeft);
+
+ if (_.options.vertical === false) {
+ animProps[_.animType] = 'translate3d(' + targetLeft + 'px, 0px, 0px)';
+ } else {
+ animProps[_.animType] = 'translate3d(0px,' + targetLeft + 'px, 0px)';
+ }
+ _.$slideTrack.css(animProps);
+
+ if (callback) {
+ setTimeout(function() {
+
+ _.disableTransition();
+
+ callback.call();
+ }, _.options.speed);
+ }
+
+ }
+
+ }
+
+ };
+
+ Slick.prototype.getNavTarget = function() {
+
+ var _ = this,
+ asNavFor = _.options.asNavFor;
+
+ if ( asNavFor && asNavFor !== null ) {
+ asNavFor = $(asNavFor).not(_.$slider);
+ }
+
+ return asNavFor;
+
+ };
+
+ Slick.prototype.asNavFor = function(index) {
+
+ var _ = this,
+ asNavFor = _.getNavTarget();
+
+ if ( asNavFor !== null && typeof asNavFor === 'object' ) {
+ asNavFor.each(function() {
+ var target = $(this).slick('getSlick');
+ if(!target.unslicked) {
+ target.slideHandler(index, true);
+ }
+ });
+ }
+
+ };
+
+ Slick.prototype.applyTransition = function(slide) {
+
+ var _ = this,
+ transition = {};
+
+ if (_.options.fade === false) {
+ transition[_.transitionType] = _.transformType + ' ' + _.options.speed + 'ms ' + _.options.cssEase;
+ } else {
+ transition[_.transitionType] = 'opacity ' + _.options.speed + 'ms ' + _.options.cssEase;
+ }
+
+ if (_.options.fade === false) {
+ _.$slideTrack.css(transition);
+ } else {
+ _.$slides.eq(slide).css(transition);
+ }
+
+ };
+
+ Slick.prototype.autoPlay = function() {
+
+ var _ = this;
+
+ _.autoPlayClear();
+
+ if ( _.slideCount > _.options.slidesToShow ) {
+ _.autoPlayTimer = setInterval( _.autoPlayIterator, _.options.autoplaySpeed );
+ }
+
+ };
+
+ Slick.prototype.autoPlayClear = function() {
+
+ var _ = this;
+
+ if (_.autoPlayTimer) {
+ clearInterval(_.autoPlayTimer);
+ }
+
+ };
+
+ Slick.prototype.autoPlayIterator = function() {
+
+ var _ = this,
+ slideTo = _.currentSlide + _.options.slidesToScroll;
+
+ if ( !_.paused && !_.interrupted && !_.focussed ) {
+
+ if ( _.options.infinite === false ) {
+
+ if ( _.direction === 1 && ( _.currentSlide + 1 ) === ( _.slideCount - 1 )) {
+ _.direction = 0;
+ }
+
+ else if ( _.direction === 0 ) {
+
+ slideTo = _.currentSlide - _.options.slidesToScroll;
+
+ if ( _.currentSlide - 1 === 0 ) {
+ _.direction = 1;
+ }
+
+ }
+
+ }
+
+ _.slideHandler( slideTo );
+
+ }
+
+ };
+
+ Slick.prototype.buildArrows = function() {
+
+ var _ = this;
+
+ if (_.options.arrows === true ) {
+
+ _.$prevArrow = $(_.options.prevArrow).addClass('slick-arrow');
+ _.$nextArrow = $(_.options.nextArrow).addClass('slick-arrow');
+
+ if( _.slideCount > _.options.slidesToShow ) {
+
+ _.$prevArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
+ _.$nextArrow.removeClass('slick-hidden').removeAttr('aria-hidden tabindex');
+
+ if (_.htmlExpr.test(_.options.prevArrow)) {
+ _.$prevArrow.prependTo(_.options.appendArrows);
+ }
+
+ if (_.htmlExpr.test(_.options.nextArrow)) {
+ _.$nextArrow.appendTo(_.options.appendArrows);
+ }
+
+ if (_.options.infinite !== true) {
+ _.$prevArrow
+ .addClass('slick-disabled')
+ .attr('aria-disabled', 'true');
+ }
+
+ } else {
+
+ _.$prevArrow.add( _.$nextArrow )
+
+ .addClass('slick-hidden')
+ .attr({
+ 'aria-disabled': 'true',
+ 'tabindex': '-1'
+ });
+
+ }
+
+ }
+
+ };
+
+ Slick.prototype.buildDots = function() {
+
+ var _ = this,
+ i, dot;
+
+ if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
+
+ _.$slider.addClass('slick-dotted');
+
+ dot = $('').addClass(_.options.dotsClass);
+
+ for (i = 0; i <= _.getDotCount(); i += 1) {
+ dot.append($('').append(_.options.customPaging.call(this, _, i)));
+ }
+
+ _.$dots = dot.appendTo(_.options.appendDots);
+
+ _.$dots.find('li').first().addClass('slick-active').attr('aria-hidden', 'false');
+
+ }
+
+ };
+
+ Slick.prototype.buildOut = function() {
+
+ var _ = this;
+
+ _.$slides =
+ _.$slider
+ .children( _.options.slide + ':not(.slick-cloned)')
+ .addClass('slick-slide');
+
+ _.slideCount = _.$slides.length;
+
+ _.$slides.each(function(index, element) {
+ $(element)
+ .attr('data-slick-index', index)
+ .data('originalStyling', $(element).attr('style') || '');
+ });
+
+ _.$slider.addClass('slick-slider');
+
+ _.$slideTrack = (_.slideCount === 0) ?
+ $('').appendTo(_.$slider) :
+ _.$slides.wrapAll('').parent();
+
+ _.$list = _.$slideTrack.wrap(
+ '').parent();
+ _.$slideTrack.css('opacity', 0);
+
+ if (_.options.centerMode === true || _.options.swipeToSlide === true) {
+ _.options.slidesToScroll = 1;
+ }
+
+ $('img[data-lazy]', _.$slider).not('[src]').addClass('slick-loading');
+
+ _.setupInfinite();
+
+ _.buildArrows();
+
+ _.buildDots();
+
+ _.updateDots();
+
+
+ _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);
+
+ if (_.options.draggable === true) {
+ _.$list.addClass('draggable');
+ }
+
+ };
+
+ Slick.prototype.buildRows = function() {
+
+ var _ = this, a, b, c, newSlides, numOfSlides, originalSlides,slidesPerSection;
+
+ newSlides = document.createDocumentFragment();
+ originalSlides = _.$slider.children();
+
+ if(_.options.rows > 1) {
+
+ slidesPerSection = _.options.slidesPerRow * _.options.rows;
+ numOfSlides = Math.ceil(
+ originalSlides.length / slidesPerSection
+ );
+
+ for(a = 0; a < numOfSlides; a++){
+ var slide = document.createElement('div');
+ for(b = 0; b < _.options.rows; b++) {
+ var row = document.createElement('div');
+ for(c = 0; c < _.options.slidesPerRow; c++) {
+ var target = (a * slidesPerSection + ((b * _.options.slidesPerRow) + c));
+ if (originalSlides.get(target)) {
+ row.appendChild(originalSlides.get(target));
+ }
+ }
+ slide.appendChild(row);
+ }
+ newSlides.appendChild(slide);
+ }
+
+ _.$slider.empty().append(newSlides);
+ _.$slider.children().children().children()
+ .css({
+ 'width':(100 / _.options.slidesPerRow) + '%',
+ 'display': 'inline-block'
+ });
+
+ }
+
+ };
+
+ Slick.prototype.checkResponsive = function(initial, forceUpdate) {
+
+ var _ = this,
+ breakpoint, targetBreakpoint, respondToWidth, triggerBreakpoint = false;
+ var sliderWidth = _.$slider.width();
+ var windowWidth = window.innerWidth || $(window).width();
+
+ if (_.respondTo === 'window') {
+ respondToWidth = windowWidth;
+ } else if (_.respondTo === 'slider') {
+ respondToWidth = sliderWidth;
+ } else if (_.respondTo === 'min') {
+ respondToWidth = Math.min(windowWidth, sliderWidth);
+ }
+
+ if ( _.options.responsive &&
+ _.options.responsive.length &&
+ _.options.responsive !== null) {
+
+ targetBreakpoint = null;
+
+ for (breakpoint in _.breakpoints) {
+ if (_.breakpoints.hasOwnProperty(breakpoint)) {
+ if (_.originalSettings.mobileFirst === false) {
+ if (respondToWidth < _.breakpoints[breakpoint]) {
+ targetBreakpoint = _.breakpoints[breakpoint];
+ }
+ } else {
+ if (respondToWidth > _.breakpoints[breakpoint]) {
+ targetBreakpoint = _.breakpoints[breakpoint];
+ }
+ }
+ }
+ }
+
+ if (targetBreakpoint !== null) {
+ if (_.activeBreakpoint !== null) {
+ if (targetBreakpoint !== _.activeBreakpoint || forceUpdate) {
+ _.activeBreakpoint =
+ targetBreakpoint;
+ if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
+ _.unslick(targetBreakpoint);
+ } else {
+ _.options = $.extend({}, _.originalSettings,
+ _.breakpointSettings[
+ targetBreakpoint]);
+ if (initial === true) {
+ _.currentSlide = _.options.initialSlide;
+ }
+ _.refresh(initial);
+ }
+ triggerBreakpoint = targetBreakpoint;
+ }
+ } else {
+ _.activeBreakpoint = targetBreakpoint;
+ if (_.breakpointSettings[targetBreakpoint] === 'unslick') {
+ _.unslick(targetBreakpoint);
+ } else {
+ _.options = $.extend({}, _.originalSettings,
+ _.breakpointSettings[
+ targetBreakpoint]);
+ if (initial === true) {
+ _.currentSlide = _.options.initialSlide;
+ }
+ _.refresh(initial);
+ }
+ triggerBreakpoint = targetBreakpoint;
+ }
+ } else {
+ if (_.activeBreakpoint !== null) {
+ _.activeBreakpoint = null;
+ _.options = _.originalSettings;
+ if (initial === true) {
+ _.currentSlide = _.options.initialSlide;
+ }
+ _.refresh(initial);
+ triggerBreakpoint = targetBreakpoint;
+ }
+ }
+
+ // only trigger breakpoints during an actual break. not on initialize.
+ if( !initial && triggerBreakpoint !== false ) {
+ _.$slider.trigger('breakpoint', [_, triggerBreakpoint]);
+ }
+ }
+
+ };
+
+ Slick.prototype.changeSlide = function(event, dontAnimate) {
+
+ var _ = this,
+ $target = $(event.currentTarget),
+ indexOffset, slideOffset, unevenOffset;
+
+ // If target is a link, prevent default action.
+ if($target.is('a')) {
+ event.preventDefault();
+ }
+
+ // If target is not the element (ie: a child), find the .
+ if(!$target.is('li')) {
+ $target = $target.closest('li');
+ }
+
+ unevenOffset = (_.slideCount % _.options.slidesToScroll !== 0);
+ indexOffset = unevenOffset ? 0 : (_.slideCount - _.currentSlide) % _.options.slidesToScroll;
+
+ switch (event.data.message) {
+
+ case 'previous':
+ slideOffset = indexOffset === 0 ? _.options.slidesToScroll : _.options.slidesToShow - indexOffset;
+ if (_.slideCount > _.options.slidesToShow) {
+ _.slideHandler(_.currentSlide - slideOffset, false, dontAnimate);
+ }
+ break;
+
+ case 'next':
+ slideOffset = indexOffset === 0 ? _.options.slidesToScroll : indexOffset;
+ if (_.slideCount > _.options.slidesToShow) {
+ _.slideHandler(_.currentSlide + slideOffset, false, dontAnimate);
+ }
+ break;
+
+ case 'index':
+ var index = event.data.index === 0 ? 0 :
+ event.data.index || $target.index() * _.options.slidesToScroll;
+
+ _.slideHandler(_.checkNavigable(index), false, dontAnimate);
+ $target.children().trigger('focus');
+ break;
+
+ default:
+ return;
+ }
+
+ };
+
+ Slick.prototype.checkNavigable = function(index) {
+
+ var _ = this,
+ navigables, prevNavigable;
+
+ navigables = _.getNavigableIndexes();
+ prevNavigable = 0;
+ if (index > navigables[navigables.length - 1]) {
+ index = navigables[navigables.length - 1];
+ } else {
+ for (var n in navigables) {
+ if (index < navigables[n]) {
+ index = prevNavigable;
+ break;
+ }
+ prevNavigable = navigables[n];
+ }
+ }
+
+ return index;
+ };
+
+ Slick.prototype.cleanUpEvents = function() {
+
+ var _ = this;
+
+ if (_.options.dots && _.$dots !== null) {
+
+ $('li', _.$dots)
+ .off('click.slick', _.changeSlide)
+ .off('mouseenter.slick', $.proxy(_.interrupt, _, true))
+ .off('mouseleave.slick', $.proxy(_.interrupt, _, false));
+
+ }
+
+ _.$slider.off('focus.slick blur.slick');
+
+ if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
+ _.$prevArrow && _.$prevArrow.off('click.slick', _.changeSlide);
+ _.$nextArrow && _.$nextArrow.off('click.slick', _.changeSlide);
+ }
+
+ _.$list.off('touchstart.slick mousedown.slick', _.swipeHandler);
+ _.$list.off('touchmove.slick mousemove.slick', _.swipeHandler);
+ _.$list.off('touchend.slick mouseup.slick', _.swipeHandler);
+ _.$list.off('touchcancel.slick mouseleave.slick', _.swipeHandler);
+
+ _.$list.off('click.slick', _.clickHandler);
+
+ $(document).off(_.visibilityChange, _.visibility);
+
+ _.cleanUpSlideEvents();
+
+ if (_.options.accessibility === true) {
+ _.$list.off('keydown.slick', _.keyHandler);
+ }
+
+ if (_.options.focusOnSelect === true) {
+ $(_.$slideTrack).children().off('click.slick', _.selectHandler);
+ }
+
+ $(window).off('orientationchange.slick.slick-' + _.instanceUid, _.orientationChange);
+
+ $(window).off('resize.slick.slick-' + _.instanceUid, _.resize);
+
+ $('[draggable!=true]', _.$slideTrack).off('dragstart', _.preventDefault);
+
+ $(window).off('load.slick.slick-' + _.instanceUid, _.setPosition);
+ $(document).off('ready.slick.slick-' + _.instanceUid, _.setPosition);
+
+ };
+
+ Slick.prototype.cleanUpSlideEvents = function() {
+
+ var _ = this;
+
+ _.$list.off('mouseenter.slick', $.proxy(_.interrupt, _, true));
+ _.$list.off('mouseleave.slick', $.proxy(_.interrupt, _, false));
+
+ };
+
+ Slick.prototype.cleanUpRows = function() {
+
+ var _ = this, originalSlides;
+
+ if(_.options.rows > 1) {
+ originalSlides = _.$slides.children().children();
+ originalSlides.removeAttr('style');
+ _.$slider.empty().append(originalSlides);
+ }
+
+ };
+
+ Slick.prototype.clickHandler = function(event) {
+
+ var _ = this;
+
+ if (_.shouldClick === false) {
+ event.stopImmediatePropagation();
+ event.stopPropagation();
+ event.preventDefault();
+ }
+
+ };
+
+ Slick.prototype.destroy = function(refresh) {
+
+ var _ = this;
+
+ _.autoPlayClear();
+
+ _.touchObject = {};
+
+ _.cleanUpEvents();
+
+ $('.slick-cloned', _.$slider).detach();
+
+ if (_.$dots) {
+ _.$dots.remove();
+ }
+
+
+ if ( _.$prevArrow && _.$prevArrow.length ) {
+
+ _.$prevArrow
+ .removeClass('slick-disabled slick-arrow slick-hidden')
+ .removeAttr('aria-hidden aria-disabled tabindex')
+ .css('display','');
+
+ if ( _.htmlExpr.test( _.options.prevArrow )) {
+ _.$prevArrow.remove();
+ }
+ }
+
+ if ( _.$nextArrow && _.$nextArrow.length ) {
+
+ _.$nextArrow
+ .removeClass('slick-disabled slick-arrow slick-hidden')
+ .removeAttr('aria-hidden aria-disabled tabindex')
+ .css('display','');
+
+ if ( _.htmlExpr.test( _.options.nextArrow )) {
+ _.$nextArrow.remove();
+ }
+
+ }
+
+
+ if (_.$slides) {
+
+ _.$slides
+ .removeClass('slick-slide slick-active slick-center slick-visible slick-current')
+ .removeAttr('aria-hidden')
+ .removeAttr('data-slick-index')
+ .each(function(){
+ $(this).attr('style', $(this).data('originalStyling'));
+ });
+
+ _.$slideTrack.children(this.options.slide).detach();
+
+ _.$slideTrack.detach();
+
+ _.$list.detach();
+
+ _.$slider.append(_.$slides);
+ }
+
+ _.cleanUpRows();
+
+ _.$slider.removeClass('slick-slider');
+ _.$slider.removeClass('slick-initialized');
+ _.$slider.removeClass('slick-dotted');
+
+ _.unslicked = true;
+
+ if(!refresh) {
+ _.$slider.trigger('destroy', [_]);
+ }
+
+ };
+
+ Slick.prototype.disableTransition = function(slide) {
+
+ var _ = this,
+ transition = {};
+
+ transition[_.transitionType] = '';
+
+ if (_.options.fade === false) {
+ _.$slideTrack.css(transition);
+ } else {
+ _.$slides.eq(slide).css(transition);
+ }
+
+ };
+
+ Slick.prototype.fadeSlide = function(slideIndex, callback) {
+
+ var _ = this;
+
+ if (_.cssTransitions === false) {
+
+ _.$slides.eq(slideIndex).css({
+ zIndex: _.options.zIndex
+ });
+
+ _.$slides.eq(slideIndex).animate({
+ opacity: 1
+ }, _.options.speed, _.options.easing, callback);
+
+ } else {
+
+ _.applyTransition(slideIndex);
+
+ _.$slides.eq(slideIndex).css({
+ opacity: 1,
+ zIndex: _.options.zIndex
+ });
+
+ if (callback) {
+ setTimeout(function() {
+
+ _.disableTransition(slideIndex);
+
+ callback.call();
+ }, _.options.speed);
+ }
+
+ }
+
+ };
+
+ Slick.prototype.fadeSlideOut = function(slideIndex) {
+
+ var _ = this;
+
+ if (_.cssTransitions === false) {
+
+ _.$slides.eq(slideIndex).animate({
+ opacity: 0,
+ zIndex: _.options.zIndex - 2
+ }, _.options.speed, _.options.easing);
+
+ } else {
+
+ _.applyTransition(slideIndex);
+
+ _.$slides.eq(slideIndex).css({
+ opacity: 0,
+ zIndex: _.options.zIndex - 2
+ });
+
+ }
+
+ };
+
+ Slick.prototype.filterSlides = Slick.prototype.slickFilter = function(filter) {
+
+ var _ = this;
+
+ if (filter !== null) {
+
+ _.$slidesCache = _.$slides;
+
+ _.unload();
+
+ _.$slideTrack.children(this.options.slide).detach();
+
+ _.$slidesCache.filter(filter).appendTo(_.$slideTrack);
+
+ _.reinit();
+
+ }
+
+ };
+
+ Slick.prototype.focusHandler = function() {
+
+ var _ = this;
+
+ _.$slider
+ .off('focus.slick blur.slick')
+ .on('focus.slick blur.slick',
+ '*:not(.slick-arrow)', function(event) {
+
+ event.stopImmediatePropagation();
+ var $sf = $(this);
+
+ setTimeout(function() {
+
+ if( _.options.pauseOnFocus ) {
+ _.focussed = $sf.is(':focus');
+ _.autoPlay();
+ }
+
+ }, 0);
+
+ });
+ };
+
+ Slick.prototype.getCurrent = Slick.prototype.slickCurrentSlide = function() {
+
+ var _ = this;
+ return _.currentSlide;
+
+ };
+
+ Slick.prototype.getDotCount = function() {
+
+ var _ = this;
+
+ var breakPoint = 0;
+ var counter = 0;
+ var pagerQty = 0;
+
+ if (_.options.infinite === true) {
+ while (breakPoint < _.slideCount) {
+ ++pagerQty;
+ breakPoint = counter + _.options.slidesToScroll;
+ counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
+ }
+ } else if (_.options.centerMode === true) {
+ pagerQty = _.slideCount;
+ } else if(!_.options.asNavFor) {
+ pagerQty = 1 + Math.ceil((_.slideCount - _.options.slidesToShow) / _.options.slidesToScroll);
+ }else {
+ while (breakPoint < _.slideCount) {
+ ++pagerQty;
+ breakPoint = counter + _.options.slidesToScroll;
+ counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
+ }
+ }
+
+ return pagerQty - 1;
+
+ };
+
+ Slick.prototype.getLeft = function(slideIndex) {
+
+ var _ = this,
+ targetLeft,
+ verticalHeight,
+ verticalOffset = 0,
+ targetSlide;
+
+ _.slideOffset = 0;
+ verticalHeight = _.$slides.first().outerHeight(true);
+
+ if (_.options.infinite === true) {
+ if (_.slideCount > _.options.slidesToShow) {
+ _.slideOffset = (_.slideWidth * _.options.slidesToShow) * -1;
+ verticalOffset = (verticalHeight * _.options.slidesToShow) * -1;
+ }
+ if (_.slideCount % _.options.slidesToScroll !== 0) {
+ if (slideIndex + _.options.slidesToScroll > _.slideCount && _.slideCount > _.options.slidesToShow) {
+ if (slideIndex > _.slideCount) {
+ _.slideOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * _.slideWidth) * -1;
+ verticalOffset = ((_.options.slidesToShow - (slideIndex - _.slideCount)) * verticalHeight) * -1;
+ } else {
+ _.slideOffset = ((_.slideCount % _.options.slidesToScroll) * _.slideWidth) * -1;
+ verticalOffset = ((_.slideCount % _.options.slidesToScroll) * verticalHeight) * -1;
+ }
+ }
+ }
+ } else {
+ if (slideIndex + _.options.slidesToShow > _.slideCount) {
+ _.slideOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * _.slideWidth;
+ verticalOffset = ((slideIndex + _.options.slidesToShow) - _.slideCount) * verticalHeight;
+ }
+ }
+
+ if (_.slideCount <= _.options.slidesToShow) {
+ _.slideOffset = 0;
+ verticalOffset = 0;
+ }
+
+ if (_.options.centerMode === true && _.options.infinite === true) {
+ _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2) - _.slideWidth;
+ } else if (_.options.centerMode === true) {
+ _.slideOffset = 0;
+ _.slideOffset += _.slideWidth * Math.floor(_.options.slidesToShow / 2);
+ }
+
+ if (_.options.vertical === false) {
+ targetLeft = ((slideIndex * _.slideWidth) * -1) + _.slideOffset;
+ } else {
+ targetLeft = ((slideIndex * verticalHeight) * -1) + verticalOffset;
+ }
+
+ if (_.options.variableWidth === true) {
+
+ if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
+ targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
+ } else {
+ targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow);
+ }
+
+ if (_.options.rtl === true) {
+ if (targetSlide[0]) {
+ targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
+ } else {
+ targetLeft = 0;
+ }
+ } else {
+ targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
+ }
+
+ if (_.options.centerMode === true) {
+ if (_.slideCount <= _.options.slidesToShow || _.options.infinite === false) {
+ targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex);
+ } else {
+ targetSlide = _.$slideTrack.children('.slick-slide').eq(slideIndex + _.options.slidesToShow + 1);
+ }
+
+ if (_.options.rtl === true) {
+ if (targetSlide[0]) {
+ targetLeft = (_.$slideTrack.width() - targetSlide[0].offsetLeft - targetSlide.width()) * -1;
+ } else {
+ targetLeft = 0;
+ }
+ } else {
+ targetLeft = targetSlide[0] ? targetSlide[0].offsetLeft * -1 : 0;
+ }
+
+ targetLeft += (_.$list.width() - targetSlide.outerWidth()) / 2;
+ }
+ }
+
+ return targetLeft;
+
+ };
+
+ Slick.prototype.getOption = Slick.prototype.slickGetOption = function(option) {
+
+ var _ = this;
+
+ return _.options[option];
+
+ };
+
+ Slick.prototype.getNavigableIndexes = function() {
+
+ var _ = this,
+ breakPoint = 0,
+ counter = 0,
+ indexes = [],
+ max;
+
+ if (_.options.infinite === false) {
+ max = _.slideCount;
+ } else {
+ breakPoint = _.options.slidesToScroll * -1;
+ counter = _.options.slidesToScroll * -1;
+ max = _.slideCount * 2;
+ }
+
+ while (breakPoint < max) {
+ indexes.push(breakPoint);
+ breakPoint = counter + _.options.slidesToScroll;
+ counter += _.options.slidesToScroll <= _.options.slidesToShow ? _.options.slidesToScroll : _.options.slidesToShow;
+ }
+
+ return indexes;
+
+ };
+
+ Slick.prototype.getSlick = function() {
+
+ return this;
+
+ };
+
+ Slick.prototype.getSlideCount = function() {
+
+ var _ = this,
+ slidesTraversed, swipedSlide, centerOffset;
+
+ centerOffset = _.options.centerMode === true ? _.slideWidth * Math.floor(_.options.slidesToShow / 2) : 0;
+
+ if (_.options.swipeToSlide === true) {
+ _.$slideTrack.find('.slick-slide').each(function(index, slide) {
+ if (slide.offsetLeft - centerOffset + ($(slide).outerWidth() / 2) > (_.swipeLeft * -1)) {
+ swipedSlide = slide;
+ return false;
+ }
+ });
+
+ slidesTraversed = Math.abs($(swipedSlide).attr('data-slick-index') - _.currentSlide) || 1;
+
+ return slidesTraversed;
+
+ } else {
+ return _.options.slidesToScroll;
+ }
+
+ };
+
+ Slick.prototype.goTo = Slick.prototype.slickGoTo = function(slide, dontAnimate) {
+
+ var _ = this;
+
+ _.changeSlide({
+ data: {
+ message: 'index',
+ index: parseInt(slide)
+ }
+ }, dontAnimate);
+
+ };
+
+ Slick.prototype.init = function(creation) {
+
+ var _ = this;
+
+ if (!$(_.$slider).hasClass('slick-initialized')) {
+
+ $(_.$slider).addClass('slick-initialized');
+
+ _.buildRows();
+ _.buildOut();
+ _.setProps();
+ _.startLoad();
+ _.loadSlider();
+ _.initializeEvents();
+ _.updateArrows();
+ _.updateDots();
+ _.checkResponsive(true);
+ _.focusHandler();
+
+ }
+
+ if (creation) {
+ _.$slider.trigger('init', [_]);
+ }
+
+ if (_.options.accessibility === true) {
+ _.initADA();
+ }
+
+ if ( _.options.autoplay ) {
+
+ _.paused = false;
+ _.autoPlay();
+
+ }
+
+ };
+
+ Slick.prototype.initADA = function() {
+ var _ = this;
+ _.$slides.add(_.$slideTrack.find('.slick-cloned')).attr({
+ 'aria-hidden': 'true',
+ 'tabindex': '-1'
+ }).find('a, input, button, select').attr({
+ 'tabindex': '-1'
+ });
+
+ _.$slideTrack.attr('role', 'listbox');
+
+ _.$slides.not(_.$slideTrack.find('.slick-cloned')).each(function(i) {
+ $(this).attr({
+ 'role': 'option',
+ 'aria-describedby': 'slick-slide' + _.instanceUid + i + ''
+ });
+ });
+
+ if (_.$dots !== null) {
+ _.$dots.attr('role', 'tablist').find('li').each(function(i) {
+ $(this).attr({
+ 'role': 'presentation',
+ 'aria-selected': 'false',
+ 'aria-controls': 'navigation' + _.instanceUid + i + '',
+ 'id': 'slick-slide' + _.instanceUid + i + ''
+ });
+ })
+ .first().attr('aria-selected', 'true').end()
+ .find('button').attr('role', 'button').end()
+ .closest('div').attr('role', 'toolbar');
+ }
+ _.activateADA();
+
+ };
+
+ Slick.prototype.initArrowEvents = function() {
+
+ var _ = this;
+
+ if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
+ _.$prevArrow
+ .off('click.slick')
+ .on('click.slick', {
+ message: 'previous'
+ }, _.changeSlide);
+ _.$nextArrow
+ .off('click.slick')
+ .on('click.slick', {
+ message: 'next'
+ }, _.changeSlide);
+ }
+
+ };
+
+ Slick.prototype.initDotEvents = function() {
+
+ var _ = this;
+
+ if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
+ $('li', _.$dots).on('click.slick', {
+ message: 'index'
+ }, _.changeSlide);
+ }
+
+ if ( _.options.dots === true && _.options.pauseOnDotsHover === true ) {
+
+ $('li', _.$dots)
+ .on('mouseenter.slick', $.proxy(_.interrupt, _, true))
+ .on('mouseleave.slick', $.proxy(_.interrupt, _, false));
+
+ }
+
+ };
+
+ Slick.prototype.initSlideEvents = function() {
+
+ var _ = this;
+
+ if ( _.options.pauseOnHover ) {
+
+ _.$list.on('mouseenter.slick', $.proxy(_.interrupt, _, true));
+ _.$list.on('mouseleave.slick', $.proxy(_.interrupt, _, false));
+
+ }
+
+ };
+
+ Slick.prototype.initializeEvents = function() {
+
+ var _ = this;
+
+ _.initArrowEvents();
+
+ _.initDotEvents();
+ _.initSlideEvents();
+
+ _.$list.on('touchstart.slick mousedown.slick', {
+ action: 'start'
+ }, _.swipeHandler);
+ _.$list.on('touchmove.slick mousemove.slick', {
+ action: 'move'
+ }, _.swipeHandler);
+ _.$list.on('touchend.slick mouseup.slick', {
+ action: 'end'
+ }, _.swipeHandler);
+ _.$list.on('touchcancel.slick mouseleave.slick', {
+ action: 'end'
+ }, _.swipeHandler);
+
+ _.$list.on('click.slick', _.clickHandler);
+
+ $(document).on(_.visibilityChange, $.proxy(_.visibility, _));
+
+ if (_.options.accessibility === true) {
+ _.$list.on('keydown.slick', _.keyHandler);
+ }
+
+ if (_.options.focusOnSelect === true) {
+ $(_.$slideTrack).children().on('click.slick', _.selectHandler);
+ }
+
+ $(window).on('orientationchange.slick.slick-' + _.instanceUid, $.proxy(_.orientationChange, _));
+
+ $(window).on('resize.slick.slick-' + _.instanceUid, $.proxy(_.resize, _));
+
+ $('[draggable!=true]', _.$slideTrack).on('dragstart', _.preventDefault);
+
+ $(window).on('load.slick.slick-' + _.instanceUid, _.setPosition);
+ $(document).on('ready.slick.slick-' + _.instanceUid, _.setPosition);
+
+ };
+
+ Slick.prototype.initUI = function() {
+
+ var _ = this;
+
+ if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
+
+ _.$prevArrow.show();
+ _.$nextArrow.show();
+
+ }
+
+ if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
+
+ _.$dots.show();
+
+ }
+
+ };
+
+ Slick.prototype.keyHandler = function(event) {
+
+ var _ = this;
+ //Dont slide if the cursor is inside the form fields and arrow keys are pressed
+ if(!event.target.tagName.match('TEXTAREA|INPUT|SELECT')) {
+ if (event.keyCode === 37 && _.options.accessibility === true) {
+ _.changeSlide({
+ data: {
+ message: _.options.rtl === true ? 'next' : 'previous'
+ }
+ });
+ } else if (event.keyCode === 39 && _.options.accessibility === true) {
+ _.changeSlide({
+ data: {
+ message: _.options.rtl === true ? 'previous' : 'next'
+ }
+ });
+ }
+ }
+
+ };
+
+ Slick.prototype.lazyLoad = function() {
+
+ var _ = this,
+ loadRange, cloneRange, rangeStart, rangeEnd;
+
+ function loadImages(imagesScope) {
+
+ $('img[data-lazy]', imagesScope).each(function() {
+
+ var image = $(this),
+ imageSource = $(this).attr('data-lazy'),
+ imageToLoad = document.createElement('img');
+
+ imageToLoad.onload = function() {
+
+ image
+ .animate({ opacity: 0 }, 100, function() {
+ image
+ .attr('src', imageSource)
+ .animate({ opacity: 1 }, 200, function() {
+ image
+ .removeAttr('data-lazy')
+ .removeClass('slick-loading');
+ });
+ _.$slider.trigger('lazyLoaded', [_, image, imageSource]);
+ });
+
+ };
+
+ imageToLoad.onerror = function() {
+
+ image
+ .removeAttr( 'data-lazy' )
+ .removeClass( 'slick-loading' )
+ .addClass( 'slick-lazyload-error' );
+
+ _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);
+
+ };
+
+ imageToLoad.src = imageSource;
+
+ });
+
+ }
+
+ if (_.options.centerMode === true) {
+ if (_.options.infinite === true) {
+ rangeStart = _.currentSlide + (_.options.slidesToShow / 2 + 1);
+ rangeEnd = rangeStart + _.options.slidesToShow + 2;
+ } else {
+ rangeStart = Math.max(0, _.currentSlide - (_.options.slidesToShow / 2 + 1));
+ rangeEnd = 2 + (_.options.slidesToShow / 2 + 1) + _.currentSlide;
+ }
+ } else {
+ rangeStart = _.options.infinite ? _.options.slidesToShow + _.currentSlide : _.currentSlide;
+ rangeEnd = Math.ceil(rangeStart + _.options.slidesToShow);
+ if (_.options.fade === true) {
+ if (rangeStart > 0) rangeStart--;
+ if (rangeEnd <= _.slideCount) rangeEnd++;
+ }
+ }
+
+ loadRange = _.$slider.find('.slick-slide').slice(rangeStart, rangeEnd);
+ loadImages(loadRange);
+
+ if (_.slideCount <= _.options.slidesToShow) {
+ cloneRange = _.$slider.find('.slick-slide');
+ loadImages(cloneRange);
+ } else
+ if (_.currentSlide >= _.slideCount - _.options.slidesToShow) {
+ cloneRange = _.$slider.find('.slick-cloned').slice(0, _.options.slidesToShow);
+ loadImages(cloneRange);
+ } else if (_.currentSlide === 0) {
+ cloneRange = _.$slider.find('.slick-cloned').slice(_.options.slidesToShow * -1);
+ loadImages(cloneRange);
+ }
+
+ };
+
+ Slick.prototype.loadSlider = function() {
+
+ var _ = this;
+
+ _.setPosition();
+
+ _.$slideTrack.css({
+ opacity: 1
+ });
+
+ _.$slider.removeClass('slick-loading');
+
+ _.initUI();
+
+ if (_.options.lazyLoad === 'progressive') {
+ _.progressiveLazyLoad();
+ }
+
+ };
+
+ Slick.prototype.next = Slick.prototype.slickNext = function() {
+
+ var _ = this;
+
+ _.changeSlide({
+ data: {
+ message: 'next'
+ }
+ });
+
+ };
+
+ Slick.prototype.orientationChange = function() {
+
+ var _ = this;
+
+ _.checkResponsive();
+ _.setPosition();
+
+ };
+
+ Slick.prototype.pause = Slick.prototype.slickPause = function() {
+
+ var _ = this;
+
+ _.autoPlayClear();
+ _.paused = true;
+
+ };
+
+ Slick.prototype.play = Slick.prototype.slickPlay = function() {
+
+ var _ = this;
+
+ _.autoPlay();
+ _.options.autoplay = true;
+ _.paused = false;
+ _.focussed = false;
+ _.interrupted = false;
+
+ };
+
+ Slick.prototype.postSlide = function(index) {
+
+ var _ = this;
+
+ if( !_.unslicked ) {
+
+ _.$slider.trigger('afterChange', [_, index]);
+
+ _.animating = false;
+
+ _.setPosition();
+
+ _.swipeLeft = null;
+
+ if ( _.options.autoplay ) {
+ _.autoPlay();
+ }
+
+ if (_.options.accessibility === true) {
+ _.initADA();
+ }
+
+ }
+
+ };
+
+ Slick.prototype.prev = Slick.prototype.slickPrev = function() {
+
+ var _ = this;
+
+ _.changeSlide({
+ data: {
+ message: 'previous'
+ }
+ });
+
+ };
+
+ Slick.prototype.preventDefault = function(event) {
+
+ event.preventDefault();
+
+ };
+
+ Slick.prototype.progressiveLazyLoad = function( tryCount ) {
+
+ tryCount = tryCount || 1;
+
+ var _ = this,
+ $imgsToLoad = $( 'img[data-lazy]', _.$slider ),
+ image,
+ imageSource,
+ imageToLoad;
+
+ if ( $imgsToLoad.length ) {
+
+ image = $imgsToLoad.first();
+ imageSource = image.attr('data-lazy');
+ imageToLoad = document.createElement('img');
+
+ imageToLoad.onload = function() {
+
+ image
+ .attr( 'src', imageSource )
+ .removeAttr('data-lazy')
+ .removeClass('slick-loading');
+
+ if ( _.options.adaptiveHeight === true ) {
+ _.setPosition();
+ }
+
+ _.$slider.trigger('lazyLoaded', [ _, image, imageSource ]);
+ _.progressiveLazyLoad();
+
+ };
+
+ imageToLoad.onerror = function() {
+
+ if ( tryCount < 3 ) {
+
+ /**
+ * try to load the image 3 times,
+ * leave a slight delay so we don't get
+ * servers blocking the request.
+ */
+ setTimeout( function() {
+ _.progressiveLazyLoad( tryCount + 1 );
+ }, 500 );
+
+ } else {
+
+ image
+ .removeAttr( 'data-lazy' )
+ .removeClass( 'slick-loading' )
+ .addClass( 'slick-lazyload-error' );
+
+ _.$slider.trigger('lazyLoadError', [ _, image, imageSource ]);
+
+ _.progressiveLazyLoad();
+
+ }
+
+ };
+
+ imageToLoad.src = imageSource;
+
+ } else {
+
+ _.$slider.trigger('allImagesLoaded', [ _ ]);
+
+ }
+
+ };
+
+ Slick.prototype.refresh = function( initializing ) {
+
+ var _ = this, currentSlide, lastVisibleIndex;
+
+ lastVisibleIndex = _.slideCount - _.options.slidesToShow;
+
+ // in non-infinite sliders, we don't want to go past the
+ // last visible index.
+ if( !_.options.infinite && ( _.currentSlide > lastVisibleIndex )) {
+ _.currentSlide = lastVisibleIndex;
+ }
+
+ // if less slides than to show, go to start.
+ if ( _.slideCount <= _.options.slidesToShow ) {
+ _.currentSlide = 0;
+
+ }
+
+ currentSlide = _.currentSlide;
+
+ _.destroy(true);
+
+ $.extend(_, _.initials, { currentSlide: currentSlide });
+
+ _.init();
+
+ if( !initializing ) {
+
+ _.changeSlide({
+ data: {
+ message: 'index',
+ index: currentSlide
+ }
+ }, false);
+
+ }
+
+ };
+
+ Slick.prototype.registerBreakpoints = function() {
+
+ var _ = this, breakpoint, currentBreakpoint, l,
+ responsiveSettings = _.options.responsive || null;
+
+ if ( $.type(responsiveSettings) === 'array' && responsiveSettings.length ) {
+
+ _.respondTo = _.options.respondTo || 'window';
+
+ for ( breakpoint in responsiveSettings ) {
+
+ l = _.breakpoints.length-1;
+ currentBreakpoint = responsiveSettings[breakpoint].breakpoint;
+
+ if (responsiveSettings.hasOwnProperty(breakpoint)) {
+
+ // loop through the breakpoints and cut out any existing
+ // ones with the same breakpoint number, we don't want dupes.
+ while( l >= 0 ) {
+ if( _.breakpoints[l] && _.breakpoints[l] === currentBreakpoint ) {
+ _.breakpoints.splice(l,1);
+ }
+ l--;
+ }
+
+ _.breakpoints.push(currentBreakpoint);
+ _.breakpointSettings[currentBreakpoint] = responsiveSettings[breakpoint].settings;
+
+ }
+
+ }
+
+ _.breakpoints.sort(function(a, b) {
+ return ( _.options.mobileFirst ) ? a-b : b-a;
+ });
+
+ }
+
+ };
+
+ Slick.prototype.reinit = function() {
+
+ var _ = this;
+
+ _.$slides =
+ _.$slideTrack
+ .children(_.options.slide)
+ .addClass('slick-slide');
+
+ _.slideCount = _.$slides.length;
+
+ if (_.currentSlide >= _.slideCount && _.currentSlide !== 0) {
+ _.currentSlide = _.currentSlide - _.options.slidesToScroll;
+ }
+
+ if (_.slideCount <= _.options.slidesToShow) {
+ _.currentSlide = 0;
+ }
+
+ _.registerBreakpoints();
+
+ _.setProps();
+ _.setupInfinite();
+ _.buildArrows();
+ _.updateArrows();
+ _.initArrowEvents();
+ _.buildDots();
+ _.updateDots();
+ _.initDotEvents();
+ _.cleanUpSlideEvents();
+ _.initSlideEvents();
+
+ _.checkResponsive(false, true);
+
+ if (_.options.focusOnSelect === true) {
+ $(_.$slideTrack).children().on('click.slick', _.selectHandler);
+ }
+
+ _.setSlideClasses(typeof _.currentSlide === 'number' ? _.currentSlide : 0);
+
+ _.setPosition();
+ _.focusHandler();
+
+ _.paused = !_.options.autoplay;
+ _.autoPlay();
+
+ _.$slider.trigger('reInit', [_]);
+
+ };
+
+ Slick.prototype.resize = function() {
+
+ var _ = this;
+
+ if ($(window).width() !== _.windowWidth) {
+ clearTimeout(_.windowDelay);
+ _.windowDelay = window.setTimeout(function() {
+ _.windowWidth = $(window).width();
+ _.checkResponsive();
+ if( !_.unslicked ) { _.setPosition(); }
+ }, 50);
+ }
+ };
+
+ Slick.prototype.removeSlide = Slick.prototype.slickRemove = function(index, removeBefore, removeAll) {
+
+ var _ = this;
+
+ if (typeof(index) === 'boolean') {
+ removeBefore = index;
+ index = removeBefore === true ? 0 : _.slideCount - 1;
+ } else {
+ index = removeBefore === true ? --index : index;
+ }
+
+ if (_.slideCount < 1 || index < 0 || index > _.slideCount - 1) {
+ return false;
+ }
+
+ _.unload();
+
+ if (removeAll === true) {
+ _.$slideTrack.children().remove();
+ } else {
+ _.$slideTrack.children(this.options.slide).eq(index).remove();
+ }
+
+ _.$slides = _.$slideTrack.children(this.options.slide);
+
+ _.$slideTrack.children(this.options.slide).detach();
+
+ _.$slideTrack.append(_.$slides);
+
+ _.$slidesCache = _.$slides;
+
+ _.reinit();
+
+ };
+
+ Slick.prototype.setCSS = function(position) {
+
+ var _ = this,
+ positionProps = {},
+ x, y;
+
+ if (_.options.rtl === true) {
+ position = -position;
+ }
+ x = _.positionProp == 'left' ? Math.ceil(position) + 'px' : '0px';
+ y = _.positionProp == 'top' ? Math.ceil(position) + 'px' : '0px';
+
+ positionProps[_.positionProp] = position;
+
+ if (_.transformsEnabled === false) {
+ _.$slideTrack.css(positionProps);
+ } else {
+ positionProps = {};
+ if (_.cssTransitions === false) {
+ positionProps[_.animType] = 'translate(' + x + ', ' + y + ')';
+ _.$slideTrack.css(positionProps);
+ } else {
+ positionProps[_.animType] = 'translate3d(' + x + ', ' + y + ', 0px)';
+ _.$slideTrack.css(positionProps);
+ }
+ }
+
+ };
+
+ Slick.prototype.setDimensions = function() {
+
+ var _ = this;
+
+ if (_.options.vertical === false) {
+ if (_.options.centerMode === true) {
+ _.$list.css({
+ padding: ('0px ' + _.options.centerPadding)
+ });
+ }
+ } else {
+ _.$list.height(_.$slides.first().outerHeight(true) * _.options.slidesToShow);
+ if (_.options.centerMode === true) {
+ _.$list.css({
+ padding: (_.options.centerPadding + ' 0px')
+ });
+ }
+ }
+
+ _.listWidth = _.$list.width();
+ _.listHeight = _.$list.height();
+
+
+ if (_.options.vertical === false && _.options.variableWidth === false) {
+ _.slideWidth = Math.ceil(_.listWidth / _.options.slidesToShow);
+ _.$slideTrack.width(Math.ceil((_.slideWidth * _.$slideTrack.children('.slick-slide').length)));
+
+ } else if (_.options.variableWidth === true) {
+ _.$slideTrack.width(5000 * _.slideCount);
+ } else {
+ _.slideWidth = Math.ceil(_.listWidth);
+ _.$slideTrack.height(Math.ceil((_.$slides.first().outerHeight(true) * _.$slideTrack.children('.slick-slide').length)));
+ }
+
+ var offset = _.$slides.first().outerWidth(true) - _.$slides.first().width();
+ if (_.options.variableWidth === false) _.$slideTrack.children('.slick-slide').width(_.slideWidth - offset);
+
+ };
+
+ Slick.prototype.setFade = function() {
+
+ var _ = this,
+ targetLeft;
+
+ _.$slides.each(function(index, element) {
+ targetLeft = (_.slideWidth * index) * -1;
+ if (_.options.rtl === true) {
+ $(element).css({
+ position: 'relative',
+ right: targetLeft,
+ top: 0,
+ zIndex: _.options.zIndex - 2,
+ opacity: 0
+ });
+ } else {
+ $(element).css({
+ position: 'relative',
+ left: targetLeft,
+ top: 0,
+ zIndex: _.options.zIndex - 2,
+ opacity: 0
+ });
+ }
+ });
+
+ _.$slides.eq(_.currentSlide).css({
+ zIndex: _.options.zIndex - 1,
+ opacity: 1
+ });
+
+ };
+
+ Slick.prototype.setHeight = function() {
+
+ var _ = this;
+
+ if (_.options.slidesToShow === 1 && _.options.adaptiveHeight === true && _.options.vertical === false) {
+ var targetHeight = _.$slides.eq(_.currentSlide).outerHeight(true);
+ _.$list.css('height', targetHeight);
+ }
+
+ };
+
+ Slick.prototype.setOption =
+ Slick.prototype.slickSetOption = function() {
+
+ /**
+ * accepts arguments in format of:
+ *
+ * - for changing a single option's value:
+ * .slick("setOption", option, value, refresh )
+ *
+ * - for changing a set of responsive options:
+ * .slick("setOption", 'responsive', [{}, ...], refresh )
+ *
+ * - for updating multiple values at once (not responsive)
+ * .slick("setOption", { 'option': value, ... }, refresh )
+ */
+
+ var _ = this, l, item, option, value, refresh = false, type;
+
+ if( $.type( arguments[0] ) === 'object' ) {
+
+ option = arguments[0];
+ refresh = arguments[1];
+ type = 'multiple';
+
+ } else if ( $.type( arguments[0] ) === 'string' ) {
+
+ option = arguments[0];
+ value = arguments[1];
+ refresh = arguments[2];
+
+ if ( arguments[0] === 'responsive' && $.type( arguments[1] ) === 'array' ) {
+
+ type = 'responsive';
+
+ } else if ( typeof arguments[1] !== 'undefined' ) {
+
+ type = 'single';
+
+ }
+
+ }
+
+ if ( type === 'single' ) {
+
+ _.options[option] = value;
+
+
+ } else if ( type === 'multiple' ) {
+
+ $.each( option , function( opt, val ) {
+
+ _.options[opt] = val;
+
+ });
+
+
+ } else if ( type === 'responsive' ) {
+
+ for ( item in value ) {
+
+ if( $.type( _.options.responsive ) !== 'array' ) {
+
+ _.options.responsive = [ value[item] ];
+
+ } else {
+
+ l = _.options.responsive.length-1;
+
+ // loop through the responsive object and splice out duplicates.
+ while( l >= 0 ) {
+
+ if( _.options.responsive[l].breakpoint === value[item].breakpoint ) {
+
+ _.options.responsive.splice(l,1);
+
+ }
+
+ l--;
+
+ }
+
+ _.options.responsive.push( value[item] );
+
+ }
+
+ }
+
+ }
+
+ if ( refresh ) {
+
+ _.unload();
+ _.reinit();
+
+ }
+
+ };
+
+ Slick.prototype.setPosition = function() {
+
+ var _ = this;
+
+ _.setDimensions();
+
+ _.setHeight();
+
+ if (_.options.fade === false) {
+ _.setCSS(_.getLeft(_.currentSlide));
+ } else {
+ _.setFade();
+ }
+
+ _.$slider.trigger('setPosition', [_]);
+
+ };
+
+ Slick.prototype.setProps = function() {
+
+ var _ = this,
+ bodyStyle = document.body.style;
+
+ _.positionProp = _.options.vertical === true ? 'top' : 'left';
+
+ if (_.positionProp === 'top') {
+ _.$slider.addClass('slick-vertical');
+ } else {
+ _.$slider.removeClass('slick-vertical');
+ }
+
+ if (bodyStyle.WebkitTransition !== undefined ||
+ bodyStyle.MozTransition !== undefined ||
+ bodyStyle.msTransition !== undefined) {
+ if (_.options.useCSS === true) {
+ _.cssTransitions = true;
+ }
+ }
+
+ if ( _.options.fade ) {
+ if ( typeof _.options.zIndex === 'number' ) {
+ if( _.options.zIndex < 3 ) {
+ _.options.zIndex = 3;
+ }
+ } else {
+ _.options.zIndex = _.defaults.zIndex;
+ }
+ }
+
+ if (bodyStyle.OTransform !== undefined) {
+ _.animType = 'OTransform';
+ _.transformType = '-o-transform';
+ _.transitionType = 'OTransition';
+ if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
+ }
+ if (bodyStyle.MozTransform !== undefined) {
+ _.animType = 'MozTransform';
+ _.transformType = '-moz-transform';
+ _.transitionType = 'MozTransition';
+ if (bodyStyle.perspectiveProperty === undefined && bodyStyle.MozPerspective === undefined) _.animType = false;
+ }
+ if (bodyStyle.webkitTransform !== undefined) {
+ _.animType = 'webkitTransform';
+ _.transformType = '-webkit-transform';
+ _.transitionType = 'webkitTransition';
+ if (bodyStyle.perspectiveProperty === undefined && bodyStyle.webkitPerspective === undefined) _.animType = false;
+ }
+ if (bodyStyle.msTransform !== undefined) {
+ _.animType = 'msTransform';
+ _.transformType = '-ms-transform';
+ _.transitionType = 'msTransition';
+ if (bodyStyle.msTransform === undefined) _.animType = false;
+ }
+ if (bodyStyle.transform !== undefined && _.animType !== false) {
+ _.animType = 'transform';
+ _.transformType = 'transform';
+ _.transitionType = 'transition';
+ }
+ _.transformsEnabled = _.options.useTransform && (_.animType !== null && _.animType !== false);
+ };
+
+
+ Slick.prototype.setSlideClasses = function(index) {
+
+ var _ = this,
+ centerOffset, allSlides, indexOffset, remainder;
+
+ allSlides = _.$slider
+ .find('.slick-slide')
+ .removeClass('slick-active slick-center slick-current')
+ .attr('aria-hidden', 'true');
+
+ _.$slides
+ .eq(index)
+ .addClass('slick-current');
+
+ if (_.options.centerMode === true) {
+
+ centerOffset = Math.floor(_.options.slidesToShow / 2);
+
+ if (_.options.infinite === true) {
+
+ if (index >= centerOffset && index <= (_.slideCount - 1) - centerOffset) {
+
+ _.$slides
+ .slice(index - centerOffset, index + centerOffset + 1)
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ } else {
+
+ indexOffset = _.options.slidesToShow + index;
+ allSlides
+ .slice(indexOffset - centerOffset + 1, indexOffset + centerOffset + 2)
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ }
+
+ if (index === 0) {
+
+ allSlides
+ .eq(allSlides.length - 1 - _.options.slidesToShow)
+ .addClass('slick-center');
+
+ } else if (index === _.slideCount - 1) {
+
+ allSlides
+ .eq(_.options.slidesToShow)
+ .addClass('slick-center');
+
+ }
+
+ }
+
+ _.$slides
+ .eq(index)
+ .addClass('slick-center');
+
+ } else {
+
+ if (index >= 0 && index <= (_.slideCount - _.options.slidesToShow)) {
+
+ _.$slides
+ .slice(index, index + _.options.slidesToShow)
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ } else if (allSlides.length <= _.options.slidesToShow) {
+
+ allSlides
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ } else {
+
+ remainder = _.slideCount % _.options.slidesToShow;
+ indexOffset = _.options.infinite === true ? _.options.slidesToShow + index : index;
+
+ if (_.options.slidesToShow == _.options.slidesToScroll && (_.slideCount - index) < _.options.slidesToShow) {
+
+ allSlides
+ .slice(indexOffset - (_.options.slidesToShow - remainder), indexOffset + remainder)
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ } else {
+
+ allSlides
+ .slice(indexOffset, indexOffset + _.options.slidesToShow)
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ }
+
+ }
+
+ }
+
+ if (_.options.lazyLoad === 'ondemand') {
+ _.lazyLoad();
+ }
+
+ };
+
+ Slick.prototype.setupInfinite = function() {
+
+ var _ = this,
+ i, slideIndex, infiniteCount;
+
+ if (_.options.fade === true) {
+ _.options.centerMode = false;
+ }
+
+ if (_.options.infinite === true && _.options.fade === false) {
+
+ slideIndex = null;
+
+ if (_.slideCount > _.options.slidesToShow) {
+
+ if (_.options.centerMode === true) {
+ infiniteCount = _.options.slidesToShow + 1;
+ } else {
+ infiniteCount = _.options.slidesToShow;
+ }
+
+ for (i = _.slideCount; i > (_.slideCount -
+ infiniteCount); i -= 1) {
+ slideIndex = i - 1;
+ $(_.$slides[slideIndex]).clone(true).attr('id', '')
+ .attr('data-slick-index', slideIndex - _.slideCount)
+ .prependTo(_.$slideTrack).addClass('slick-cloned');
+ }
+ for (i = 0; i < infiniteCount; i += 1) {
+ slideIndex = i;
+ $(_.$slides[slideIndex]).clone(true).attr('id', '')
+ .attr('data-slick-index', slideIndex + _.slideCount)
+ .appendTo(_.$slideTrack).addClass('slick-cloned');
+ }
+ _.$slideTrack.find('.slick-cloned').find('[id]').each(function() {
+ $(this).attr('id', '');
+ });
+
+ }
+
+ }
+
+ };
+
+ Slick.prototype.interrupt = function( toggle ) {
+
+ var _ = this;
+
+ if( !toggle ) {
+ _.autoPlay();
+ }
+ _.interrupted = toggle;
+
+ };
+
+ Slick.prototype.selectHandler = function(event) {
+
+ var _ = this;
+
+ var targetElement =
+ $(event.target).is('.slick-slide') ?
+ $(event.target) :
+ $(event.target).parents('.slick-slide');
+
+ var index = parseInt(targetElement.attr('data-slick-index'));
+
+ if (!index) index = 0;
+
+ if (_.slideCount <= _.options.slidesToShow) {
+
+ _.setSlideClasses(index);
+ _.asNavFor(index);
+ return;
+
+ }
+
+ _.slideHandler(index);
+
+ };
+
+ Slick.prototype.slideHandler = function(index, sync, dontAnimate) {
+
+ var targetSlide, animSlide, oldSlide, slideLeft, targetLeft = null,
+ _ = this, navTarget;
+
+ sync = sync || false;
+
+ if (_.animating === true && _.options.waitForAnimate === true) {
+ return;
+ }
+
+ if (_.options.fade === true && _.currentSlide === index) {
+ return;
+ }
+
+ if (_.slideCount <= _.options.slidesToShow) {
+ return;
+ }
+
+ if (sync === false) {
+ _.asNavFor(index);
+ }
+
+ targetSlide = index;
+ targetLeft = _.getLeft(targetSlide);
+ slideLeft = _.getLeft(_.currentSlide);
+
+ _.currentLeft = _.swipeLeft === null ? slideLeft : _.swipeLeft;
+
+ if (_.options.infinite === false && _.options.centerMode === false && (index < 0 || index > _.getDotCount() * _.options.slidesToScroll)) {
+ if (_.options.fade === false) {
+ targetSlide = _.currentSlide;
+ if (dontAnimate !== true) {
+ _.animateSlide(slideLeft, function() {
+ _.postSlide(targetSlide);
+ });
+ } else {
+ _.postSlide(targetSlide);
+ }
+ }
+ return;
+ } else if (_.options.infinite === false && _.options.centerMode === true && (index < 0 || index > (_.slideCount - _.options.slidesToScroll))) {
+ if (_.options.fade === false) {
+ targetSlide = _.currentSlide;
+ if (dontAnimate !== true) {
+ _.animateSlide(slideLeft, function() {
+ _.postSlide(targetSlide);
+ });
+ } else {
+ _.postSlide(targetSlide);
+ }
+ }
+ return;
+ }
+
+ if ( _.options.autoplay ) {
+ clearInterval(_.autoPlayTimer);
+ }
+
+ if (targetSlide < 0) {
+ if (_.slideCount % _.options.slidesToScroll !== 0) {
+ animSlide = _.slideCount - (_.slideCount % _.options.slidesToScroll);
+ } else {
+ animSlide = _.slideCount + targetSlide;
+ }
+ } else if (targetSlide >= _.slideCount) {
+ if (_.slideCount % _.options.slidesToScroll !== 0) {
+ animSlide = 0;
+ } else {
+ animSlide = targetSlide - _.slideCount;
+ }
+ } else {
+ animSlide = targetSlide;
+ }
+
+ _.animating = true;
+
+ _.$slider.trigger('beforeChange', [_, _.currentSlide, animSlide]);
+
+ oldSlide = _.currentSlide;
+ _.currentSlide = animSlide;
+
+ _.setSlideClasses(_.currentSlide);
+
+ if ( _.options.asNavFor ) {
+
+ navTarget = _.getNavTarget();
+ navTarget = navTarget.slick('getSlick');
+
+ if ( navTarget.slideCount <= navTarget.options.slidesToShow ) {
+ navTarget.setSlideClasses(_.currentSlide);
+ }
+
+ }
+
+ _.updateDots();
+ _.updateArrows();
+
+ if (_.options.fade === true) {
+ if (dontAnimate !== true) {
+
+ _.fadeSlideOut(oldSlide);
+
+ _.fadeSlide(animSlide, function() {
+ _.postSlide(animSlide);
+ });
+
+ } else {
+ _.postSlide(animSlide);
+ }
+ _.animateHeight();
+ return;
+ }
+
+ if (dontAnimate !== true) {
+ _.animateSlide(targetLeft, function() {
+ _.postSlide(animSlide);
+ });
+ } else {
+ _.postSlide(animSlide);
+ }
+
+ };
+
+ Slick.prototype.startLoad = function() {
+
+ var _ = this;
+
+ if (_.options.arrows === true && _.slideCount > _.options.slidesToShow) {
+
+ _.$prevArrow.hide();
+ _.$nextArrow.hide();
+
+ }
+
+ if (_.options.dots === true && _.slideCount > _.options.slidesToShow) {
+
+ _.$dots.hide();
+
+ }
+
+ _.$slider.addClass('slick-loading');
+
+ };
+
+ Slick.prototype.swipeDirection = function() {
+
+ var xDist, yDist, r, swipeAngle, _ = this;
+
+ xDist = _.touchObject.startX - _.touchObject.curX;
+ yDist = _.touchObject.startY - _.touchObject.curY;
+ r = Math.atan2(yDist, xDist);
+
+ swipeAngle = Math.round(r * 180 / Math.PI);
+ if (swipeAngle < 0) {
+ swipeAngle = 360 - Math.abs(swipeAngle);
+ }
+
+ if ((swipeAngle <= 45) && (swipeAngle >= 0)) {
+ return (_.options.rtl === false ? 'left' : 'right');
+ }
+ if ((swipeAngle <= 360) && (swipeAngle >= 315)) {
+ return (_.options.rtl === false ? 'left' : 'right');
+ }
+ if ((swipeAngle >= 135) && (swipeAngle <= 225)) {
+ return (_.options.rtl === false ? 'right' : 'left');
+ }
+ if (_.options.verticalSwiping === true) {
+ if ((swipeAngle >= 35) && (swipeAngle <= 135)) {
+ return 'down';
+ } else {
+ return 'up';
+ }
+ }
+
+ return 'vertical';
+
+ };
+
+ Slick.prototype.swipeEnd = function(event) {
+
+ var _ = this,
+ slideCount,
+ direction;
+
+ _.dragging = false;
+ _.interrupted = false;
+ _.shouldClick = ( _.touchObject.swipeLength > 10 ) ? false : true;
+
+ if ( _.touchObject.curX === undefined ) {
+ return false;
+ }
+
+ if ( _.touchObject.edgeHit === true ) {
+ _.$slider.trigger('edge', [_, _.swipeDirection() ]);
+ }
+
+ if ( _.touchObject.swipeLength >= _.touchObject.minSwipe ) {
+
+ direction = _.swipeDirection();
+
+ switch ( direction ) {
+
+ case 'left':
+ case 'down':
+
+ slideCount =
+ _.options.swipeToSlide ?
+ _.checkNavigable( _.currentSlide + _.getSlideCount() ) :
+ _.currentSlide + _.getSlideCount();
+
+ _.currentDirection = 0;
+
+ break;
+
+ case 'right':
+ case 'up':
+
+ slideCount =
+ _.options.swipeToSlide ?
+ _.checkNavigable( _.currentSlide - _.getSlideCount() ) :
+ _.currentSlide - _.getSlideCount();
+
+ _.currentDirection = 1;
+
+ break;
+
+ default:
+
+
+ }
+
+ if( direction != 'vertical' ) {
+
+ _.slideHandler( slideCount );
+ _.touchObject = {};
+ _.$slider.trigger('swipe', [_, direction ]);
+
+ }
+
+ } else {
+
+ if ( _.touchObject.startX !== _.touchObject.curX ) {
+
+ _.slideHandler( _.currentSlide );
+ _.touchObject = {};
+
+ }
+
+ }
+
+ };
+
+ Slick.prototype.swipeHandler = function(event) {
+
+ var _ = this;
+
+ if ((_.options.swipe === false) || ('ontouchend' in document && _.options.swipe === false)) {
+ return;
+ } else if (_.options.draggable === false && event.type.indexOf('mouse') !== -1) {
+ return;
+ }
+
+ _.touchObject.fingerCount = event.originalEvent && event.originalEvent.touches !== undefined ?
+ event.originalEvent.touches.length : 1;
+
+ _.touchObject.minSwipe = _.listWidth / _.options
+ .touchThreshold;
+
+ if (_.options.verticalSwiping === true) {
+ _.touchObject.minSwipe = _.listHeight / _.options
+ .touchThreshold;
+ }
+
+ switch (event.data.action) {
+
+ case 'start':
+ _.swipeStart(event);
+ break;
+
+ case 'move':
+ _.swipeMove(event);
+ break;
+
+ case 'end':
+ _.swipeEnd(event);
+ break;
+
+ }
+
+ };
+
+ Slick.prototype.swipeMove = function(event) {
+
+ var _ = this,
+ edgeWasHit = false,
+ curLeft, swipeDirection, swipeLength, positionOffset, touches;
+
+ touches = event.originalEvent !== undefined ? event.originalEvent.touches : null;
+
+ if (!_.dragging || touches && touches.length !== 1) {
+ return false;
+ }
+
+ curLeft = _.getLeft(_.currentSlide);
+
+ _.touchObject.curX = touches !== undefined ? touches[0].pageX : event.clientX;
+ _.touchObject.curY = touches !== undefined ? touches[0].pageY : event.clientY;
+
+ _.touchObject.swipeLength = Math.round(Math.sqrt(
+ Math.pow(_.touchObject.curX - _.touchObject.startX, 2)));
+
+ if (_.options.verticalSwiping === true) {
+ _.touchObject.swipeLength = Math.round(Math.sqrt(
+ Math.pow(_.touchObject.curY - _.touchObject.startY, 2)));
+ }
+
+ swipeDirection = _.swipeDirection();
+
+ if (swipeDirection === 'vertical') {
+ return;
+ }
+
+ if (event.originalEvent !== undefined && _.touchObject.swipeLength > 4) {
+ event.preventDefault();
+ }
+
+ positionOffset = (_.options.rtl === false ? 1 : -1) * (_.touchObject.curX > _.touchObject.startX ? 1 : -1);
+ if (_.options.verticalSwiping === true) {
+ positionOffset = _.touchObject.curY > _.touchObject.startY ? 1 : -1;
+ }
+
+
+ swipeLength = _.touchObject.swipeLength;
+
+ _.touchObject.edgeHit = false;
+
+ if (_.options.infinite === false) {
+ if ((_.currentSlide === 0 && swipeDirection === 'right') || (_.currentSlide >= _.getDotCount() && swipeDirection === 'left')) {
+ swipeLength = _.touchObject.swipeLength * _.options.edgeFriction;
+ _.touchObject.edgeHit = true;
+ }
+ }
+
+ if (_.options.vertical === false) {
+ _.swipeLeft = curLeft + swipeLength * positionOffset;
+ } else {
+ _.swipeLeft = curLeft + (swipeLength * (_.$list.height() / _.listWidth)) * positionOffset;
+ }
+ if (_.options.verticalSwiping === true) {
+ _.swipeLeft = curLeft + swipeLength * positionOffset;
+ }
+
+ if (_.options.fade === true || _.options.touchMove === false) {
+ return false;
+ }
+
+ if (_.animating === true) {
+ _.swipeLeft = null;
+ return false;
+ }
+
+ _.setCSS(_.swipeLeft);
+
+ };
+
+ Slick.prototype.swipeStart = function(event) {
+
+ var _ = this,
+ touches;
+
+ _.interrupted = true;
+
+ if (_.touchObject.fingerCount !== 1 || _.slideCount <= _.options.slidesToShow) {
+ _.touchObject = {};
+ return false;
+ }
+
+ if (event.originalEvent !== undefined && event.originalEvent.touches !== undefined) {
+ touches = event.originalEvent.touches[0];
+ }
+
+ _.touchObject.startX = _.touchObject.curX = touches !== undefined ? touches.pageX : event.clientX;
+ _.touchObject.startY = _.touchObject.curY = touches !== undefined ? touches.pageY : event.clientY;
+
+ _.dragging = true;
+
+ };
+
+ Slick.prototype.unfilterSlides = Slick.prototype.slickUnfilter = function() {
+
+ var _ = this;
+
+ if (_.$slidesCache !== null) {
+
+ _.unload();
+
+ _.$slideTrack.children(this.options.slide).detach();
+
+ _.$slidesCache.appendTo(_.$slideTrack);
+
+ _.reinit();
+
+ }
+
+ };
+
+ Slick.prototype.unload = function() {
+
+ var _ = this;
+
+ $('.slick-cloned', _.$slider).remove();
+
+ if (_.$dots) {
+ _.$dots.remove();
+ }
+
+ if (_.$prevArrow && _.htmlExpr.test(_.options.prevArrow)) {
+ _.$prevArrow.remove();
+ }
+
+ if (_.$nextArrow && _.htmlExpr.test(_.options.nextArrow)) {
+ _.$nextArrow.remove();
+ }
+
+ _.$slides
+ .removeClass('slick-slide slick-active slick-visible slick-current')
+ .attr('aria-hidden', 'true')
+ .css('width', '');
+
+ };
+
+ Slick.prototype.unslick = function(fromBreakpoint) {
+
+ var _ = this;
+ _.$slider.trigger('unslick', [_, fromBreakpoint]);
+ _.destroy();
+
+ };
+
+ Slick.prototype.updateArrows = function() {
+
+ var _ = this,
+ centerOffset;
+
+ centerOffset = Math.floor(_.options.slidesToShow / 2);
+
+ if ( _.options.arrows === true &&
+ _.slideCount > _.options.slidesToShow &&
+ !_.options.infinite ) {
+
+ _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
+ _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
+
+ if (_.currentSlide === 0) {
+
+ _.$prevArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
+ _.$nextArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
+
+ } else if (_.currentSlide >= _.slideCount - _.options.slidesToShow && _.options.centerMode === false) {
+
+ _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
+ _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
+
+ } else if (_.currentSlide >= _.slideCount - 1 && _.options.centerMode === true) {
+
+ _.$nextArrow.addClass('slick-disabled').attr('aria-disabled', 'true');
+ _.$prevArrow.removeClass('slick-disabled').attr('aria-disabled', 'false');
+
+ }
+
+ }
+
+ };
+
+ Slick.prototype.updateDots = function() {
+
+ var _ = this;
+
+ if (_.$dots !== null) {
+
+ _.$dots
+ .find('li')
+ .removeClass('slick-active')
+ .attr('aria-hidden', 'true');
+
+ _.$dots
+ .find('li')
+ .eq(Math.floor(_.currentSlide / _.options.slidesToScroll))
+ .addClass('slick-active')
+ .attr('aria-hidden', 'false');
+
+ }
+
+ };
+
+ Slick.prototype.visibility = function() {
+
+ var _ = this;
+
+ if ( _.options.autoplay ) {
+
+ if ( document[_.hidden] ) {
+
+ _.interrupted = true;
+
+ } else {
+
+ _.interrupted = false;
+
+ }
+
+ }
+
+ };
+
+ $.fn.slick = function() {
+ var _ = this,
+ opt = arguments[0],
+ args = Array.prototype.slice.call(arguments, 1),
+ l = _.length,
+ i,
+ ret;
+ for (i = 0; i < l; i++) {
+ if (typeof opt == 'object' || typeof opt == 'undefined')
+ _[i].slick = new Slick(_[i], opt);
+ else
+ ret = _[i].slick[opt].apply(_[i].slick, args);
+ if (typeof ret != 'undefined') return ret;
+ }
+ return _;
+ };
+
+}));
+/*!
+ * Lightbox v2.10.0
+ * by Lokesh Dhakar
+ *
+ * More info:
+ * http://lokeshdhakar.com/projects/lightbox2/
+ *
+ * Copyright 2007, 2018 Lokesh Dhakar
+ * Released under the MIT license
+ * https://github.com/lokesh/lightbox2/blob/master/LICENSE
+ *
+ * @preserve
+ */
+
+// Uses Node, AMD or browser globals to create a module.
+(function (root, factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like environments that support module.exports,
+ // like Node.
+ module.exports = factory(require('jquery'));
+ } else {
+ // Browser globals (root is window)
+ root.lightbox = factory(root.jQuery);
+ }
+}(this, function ($) {
+
+ function Lightbox(options) {
+ this.album = [];
+ this.currentImageIndex = void 0;
+ this.init();
+
+ // options
+ this.options = $.extend({}, this.constructor.defaults);
+ this.option(options);
+ }
+
+ // Descriptions of all options available on the demo site:
+ // http://lokeshdhakar.com/projects/lightbox2/index.html#options
+ Lightbox.defaults = {
+ albumLabel: 'Image %1 of %2',
+ alwaysShowNavOnTouchDevices: false,
+ fadeDuration: 600,
+ fitImagesInViewport: true,
+ imageFadeDuration: 600,
+ // maxWidth: 800,
+ // maxHeight: 600,
+ positionFromTop: 50,
+ resizeDuration: 700,
+ showImageNumberLabel: true,
+ wrapAround: false,
+ disableScrolling: false,
+ /*
+ Sanitize Title
+ If the caption data is trusted, for example you are hardcoding it in, then leave this to false.
+ This will free you to add html tags, such as links, in the caption.
+
+ If the caption data is user submitted or from some other untrusted source, then set this to true
+ to prevent xss and other injection attacks.
+ */
+ sanitizeTitle: false
+ };
+
+ Lightbox.prototype.option = function(options) {
+ $.extend(this.options, options);
+ };
+
+ Lightbox.prototype.imageCountLabel = function(currentImageNum, totalImages) {
+ return this.options.albumLabel.replace(/%1/g, currentImageNum).replace(/%2/g, totalImages);
+ };
+
+ Lightbox.prototype.init = function() {
+ var self = this;
+ // Both enable and build methods require the body tag to be in the DOM.
+ $(document).ready(function() {
+ self.enable();
+ self.build();
+ });
+ };
+
+ // Loop through anchors and areamaps looking for either data-lightbox attributes or rel attributes
+ // that contain 'lightbox'. When these are clicked, start lightbox.
+ Lightbox.prototype.enable = function() {
+ var self = this;
+ $('body').on('click', 'a[rel^=lightbox], area[rel^=lightbox], a[data-lightbox], area[data-lightbox]', function(event) {
+ self.start($(event.currentTarget));
+ return false;
+ });
+ };
+
+ // Build html for the lightbox and the overlay.
+ // Attach event handlers to the new DOM elements. click click click
+ Lightbox.prototype.build = function() {
+ if ($('#lightbox').length > 0) {
+ return;
+ }
+
+ var self = this;
+ $('').appendTo($('body'));
+
+ // Cache jQuery objects
+ this.$lightbox = $('#lightbox');
+ this.$overlay = $('#lightboxOverlay');
+ this.$outerContainer = this.$lightbox.find('.lb-outerContainer');
+ this.$container = this.$lightbox.find('.lb-container');
+ this.$image = this.$lightbox.find('.lb-image');
+ this.$nav = this.$lightbox.find('.lb-nav');
+
+ // Store css values for future lookup
+ this.containerPadding = {
+ top: parseInt(this.$container.css('padding-top'), 10),
+ right: parseInt(this.$container.css('padding-right'), 10),
+ bottom: parseInt(this.$container.css('padding-bottom'), 10),
+ left: parseInt(this.$container.css('padding-left'), 10)
+ };
+
+ this.imageBorderWidth = {
+ top: parseInt(this.$image.css('border-top-width'), 10),
+ right: parseInt(this.$image.css('border-right-width'), 10),
+ bottom: parseInt(this.$image.css('border-bottom-width'), 10),
+ left: parseInt(this.$image.css('border-left-width'), 10)
+ };
+
+ // Attach event handlers to the newly minted DOM elements
+ this.$overlay.hide().on('click', function() {
+ self.end();
+ return false;
+ });
+
+ this.$lightbox.hide().on('click', function(event) {
+ if ($(event.target).attr('id') === 'lightbox') {
+ self.end();
+ }
+ return false;
+ });
+
+ this.$outerContainer.on('click', function(event) {
+ if ($(event.target).attr('id') === 'lightbox') {
+ self.end();
+ }
+ return false;
+ });
+
+ this.$lightbox.find('.lb-prev').on('click', function() {
+ if (self.currentImageIndex === 0) {
+ self.changeImage(self.album.length - 1);
+ } else {
+ self.changeImage(self.currentImageIndex - 1);
+ }
+ return false;
+ });
+
+ this.$lightbox.find('.lb-next').on('click', function() {
+ if (self.currentImageIndex === self.album.length - 1) {
+ self.changeImage(0);
+ } else {
+ self.changeImage(self.currentImageIndex + 1);
+ }
+ return false;
+ });
+
+ /*
+ Show context menu for image on right-click
+
+ There is a div containing the navigation that spans the entire image and lives above of it. If
+ you right-click, you are right clicking this div and not the image. This prevents users from
+ saving the image or using other context menu actions with the image.
+
+ To fix this, when we detect the right mouse button is pressed down, but not yet clicked, we
+ set pointer-events to none on the nav div. This is so that the upcoming right-click event on
+ the next mouseup will bubble down to the image. Once the right-click/contextmenu event occurs
+ we set the pointer events back to auto for the nav div so it can capture hover and left-click
+ events as usual.
+ */
+ this.$nav.on('mousedown', function(event) {
+ if (event.which === 3) {
+ self.$nav.css('pointer-events', 'none');
+
+ self.$lightbox.one('contextmenu', function() {
+ setTimeout(function() {
+ this.$nav.css('pointer-events', 'auto');
+ }.bind(self), 0);
+ });
+ }
+ });
+
+
+ this.$lightbox.find('.lb-loader, .lb-close').on('click', function() {
+ self.end();
+ return false;
+ });
+ };
+
+ // Show overlay and lightbox. If the image is part of a set, add siblings to album array.
+ Lightbox.prototype.start = function($link) {
+ var self = this;
+ var $window = $(window);
+
+ $window.on('resize', $.proxy(this.sizeOverlay, this));
+
+ $('select, object, embed').css({
+ visibility: 'hidden'
+ });
+
+ this.sizeOverlay();
+
+ this.album = [];
+ var imageNumber = 0;
+
+ function addToAlbum($link) {
+ self.album.push({
+ alt: $link.attr('data-alt'),
+ link: $link.attr('href'),
+ title: $link.attr('data-title') || $link.attr('title')
+ });
+ }
+
+ // Support both data-lightbox attribute and rel attribute implementations
+ var dataLightboxValue = $link.attr('data-lightbox');
+ var $links;
+
+ if (dataLightboxValue) {
+ $links = $($link.prop('tagName') + '[data-lightbox="' + dataLightboxValue + '"]');
+ for (var i = 0; i < $links.length; i = ++i) {
+ addToAlbum($($links[i]));
+ if ($links[i] === $link[0]) {
+ imageNumber = i;
+ }
+ }
+ } else {
+ if ($link.attr('rel') === 'lightbox') {
+ // If image is not part of a set
+ addToAlbum($link);
+ } else {
+ // If image is part of a set
+ $links = $($link.prop('tagName') + '[rel="' + $link.attr('rel') + '"]');
+ for (var j = 0; j < $links.length; j = ++j) {
+ addToAlbum($($links[j]));
+ if ($links[j] === $link[0]) {
+ imageNumber = j;
+ }
+ }
+ }
+ }
+
+ // Position Lightbox
+ var top = $window.scrollTop() + this.options.positionFromTop;
+ var left = $window.scrollLeft();
+ this.$lightbox.css({
+ top: top + 'px',
+ left: left + 'px'
+ }).fadeIn(this.options.fadeDuration);
+
+ // Disable scrolling of the page while open
+ if (this.options.disableScrolling) {
+ $('html').addClass('lb-disable-scrolling');
+ }
+
+ this.changeImage(imageNumber);
+ };
+
+ // Hide most UI elements in preparation for the animated resizing of the lightbox.
+ Lightbox.prototype.changeImage = function(imageNumber) {
+ var self = this;
+
+ this.disableKeyboardNav();
+ var $image = this.$lightbox.find('.lb-image');
+
+ this.$overlay.fadeIn(this.options.fadeDuration);
+
+ $('.lb-loader').fadeIn('slow');
+ this.$lightbox.find('.lb-image, .lb-nav, .lb-prev, .lb-next, .lb-dataContainer, .lb-numbers, .lb-caption').hide();
+
+ this.$outerContainer.addClass('animating');
+
+ // When image to show is preloaded, we send the width and height to sizeContainer()
+ var preloader = new Image();
+ preloader.onload = function() {
+ var $preloader;
+ var imageHeight;
+ var imageWidth;
+ var maxImageHeight;
+ var maxImageWidth;
+ var windowHeight;
+ var windowWidth;
+
+ $image.attr({
+ 'alt': self.album[imageNumber].alt,
+ 'src': self.album[imageNumber].link
+ });
+
+ $preloader = $(preloader);
+
+ $image.width(preloader.width);
+ $image.height(preloader.height);
+
+ if (self.options.fitImagesInViewport) {
+ // Fit image inside the viewport.
+ // Take into account the border around the image and an additional 10px gutter on each side.
+
+ windowWidth = $(window).width();
+ windowHeight = $(window).height();
+ maxImageWidth = windowWidth - self.containerPadding.left - self.containerPadding.right - self.imageBorderWidth.left - self.imageBorderWidth.right - 20;
+ maxImageHeight = windowHeight - self.containerPadding.top - self.containerPadding.bottom - self.imageBorderWidth.top - self.imageBorderWidth.bottom - 120;
+
+ // Check if image size is larger then maxWidth|maxHeight in settings
+ if (self.options.maxWidth && self.options.maxWidth < maxImageWidth) {
+ maxImageWidth = self.options.maxWidth;
+ }
+ if (self.options.maxHeight && self.options.maxHeight < maxImageWidth) {
+ maxImageHeight = self.options.maxHeight;
+ }
+
+ // Is the current image's width or height is greater than the maxImageWidth or maxImageHeight
+ // option than we need to size down while maintaining the aspect ratio.
+ if ((preloader.width > maxImageWidth) || (preloader.height > maxImageHeight)) {
+ if ((preloader.width / maxImageWidth) > (preloader.height / maxImageHeight)) {
+ imageWidth = maxImageWidth;
+ imageHeight = parseInt(preloader.height / (preloader.width / imageWidth), 10);
+ $image.width(imageWidth);
+ $image.height(imageHeight);
+ } else {
+ imageHeight = maxImageHeight;
+ imageWidth = parseInt(preloader.width / (preloader.height / imageHeight), 10);
+ $image.width(imageWidth);
+ $image.height(imageHeight);
+ }
+ }
+ }
+ self.sizeContainer($image.width(), $image.height());
+ };
+
+ preloader.src = this.album[imageNumber].link;
+ this.currentImageIndex = imageNumber;
+ };
+
+ // Stretch overlay to fit the viewport
+ Lightbox.prototype.sizeOverlay = function() {
+ this.$overlay
+ .width($(document).width())
+ .height($(document).height());
+ };
+
+ // Animate the size of the lightbox to fit the image we are showing
+ Lightbox.prototype.sizeContainer = function(imageWidth, imageHeight) {
+ var self = this;
+
+ var oldWidth = this.$outerContainer.outerWidth();
+ var oldHeight = this.$outerContainer.outerHeight();
+ var newWidth = imageWidth + this.containerPadding.left + this.containerPadding.right + this.imageBorderWidth.left + this.imageBorderWidth.right;
+ var newHeight = imageHeight + this.containerPadding.top + this.containerPadding.bottom + this.imageBorderWidth.top + this.imageBorderWidth.bottom;
+
+ function postResize() {
+ self.$lightbox.find('.lb-dataContainer').width(newWidth);
+ self.$lightbox.find('.lb-prevLink').height(newHeight);
+ self.$lightbox.find('.lb-nextLink').height(newHeight);
+ self.showImage();
+ }
+
+ if (oldWidth !== newWidth || oldHeight !== newHeight) {
+ this.$outerContainer.animate({
+ width: newWidth,
+ height: newHeight
+ }, this.options.resizeDuration, 'swing', function() {
+ postResize();
+ });
+ } else {
+ postResize();
+ }
+ };
+
+ // Display the image and its details and begin preload neighboring images.
+ Lightbox.prototype.showImage = function() {
+ this.$lightbox.find('.lb-loader').stop(true).hide();
+ this.$lightbox.find('.lb-image').fadeIn(this.options.imageFadeDuration);
+
+ this.updateNav();
+ this.updateDetails();
+ this.preloadNeighboringImages();
+ this.enableKeyboardNav();
+ };
+
+ // Display previous and next navigation if appropriate.
+ Lightbox.prototype.updateNav = function() {
+ // Check to see if the browser supports touch events. If so, we take the conservative approach
+ // and assume that mouse hover events are not supported and always show prev/next navigation
+ // arrows in image sets.
+ var alwaysShowNav = false;
+ try {
+ document.createEvent('TouchEvent');
+ alwaysShowNav = (this.options.alwaysShowNavOnTouchDevices) ? true : false;
+ } catch (e) {}
+
+ this.$lightbox.find('.lb-nav').show();
+
+ if (this.album.length > 1) {
+ if (this.options.wrapAround) {
+ if (alwaysShowNav) {
+ this.$lightbox.find('.lb-prev, .lb-next').css('opacity', '1');
+ }
+ this.$lightbox.find('.lb-prev, .lb-next').show();
+ } else {
+ if (this.currentImageIndex > 0) {
+ this.$lightbox.find('.lb-prev').show();
+ if (alwaysShowNav) {
+ this.$lightbox.find('.lb-prev').css('opacity', '1');
+ }
+ }
+ if (this.currentImageIndex < this.album.length - 1) {
+ this.$lightbox.find('.lb-next').show();
+ if (alwaysShowNav) {
+ this.$lightbox.find('.lb-next').css('opacity', '1');
+ }
+ }
+ }
+ }
+ };
+
+ // Display caption, image number, and closing button.
+ Lightbox.prototype.updateDetails = function() {
+ var self = this;
+
+ // Enable anchor clicks in the injected caption html.
+ // Thanks Nate Wright for the fix. @https://github.com/NateWr
+ if (typeof this.album[this.currentImageIndex].title !== 'undefined' &&
+ this.album[this.currentImageIndex].title !== '') {
+ var $caption = this.$lightbox.find('.lb-caption');
+ if (this.options.sanitizeTitle) {
+ $caption.text(this.album[this.currentImageIndex].title);
+ } else {
+ $caption.html(this.album[this.currentImageIndex].title);
+ }
+ $caption.fadeIn('fast')
+ .find('a').on('click', function(event) {
+ if ($(this).attr('target') !== undefined) {
+ window.open($(this).attr('href'), $(this).attr('target'));
+ } else {
+ location.href = $(this).attr('href');
+ }
+ });
+ }
+
+ if (this.album.length > 1 && this.options.showImageNumberLabel) {
+ var labelText = this.imageCountLabel(this.currentImageIndex + 1, this.album.length);
+ this.$lightbox.find('.lb-number').text(labelText).fadeIn('fast');
+ } else {
+ this.$lightbox.find('.lb-number').hide();
+ }
+
+ this.$outerContainer.removeClass('animating');
+
+ this.$lightbox.find('.lb-dataContainer').fadeIn(this.options.resizeDuration, function() {
+ return self.sizeOverlay();
+ });
+ };
+
+ // Preload previous and next images in set.
+ Lightbox.prototype.preloadNeighboringImages = function() {
+ if (this.album.length > this.currentImageIndex + 1) {
+ var preloadNext = new Image();
+ preloadNext.src = this.album[this.currentImageIndex + 1].link;
+ }
+ if (this.currentImageIndex > 0) {
+ var preloadPrev = new Image();
+ preloadPrev.src = this.album[this.currentImageIndex - 1].link;
+ }
+ };
+
+ Lightbox.prototype.enableKeyboardNav = function() {
+ $(document).on('keyup.keyboard', $.proxy(this.keyboardAction, this));
+ };
+
+ Lightbox.prototype.disableKeyboardNav = function() {
+ $(document).off('.keyboard');
+ };
+
+ Lightbox.prototype.keyboardAction = function(event) {
+ var KEYCODE_ESC = 27;
+ var KEYCODE_LEFTARROW = 37;
+ var KEYCODE_RIGHTARROW = 39;
+
+ var keycode = event.keyCode;
+ var key = String.fromCharCode(keycode).toLowerCase();
+ if (keycode === KEYCODE_ESC || key.match(/x|o|c/)) {
+ this.end();
+ } else if (key === 'p' || keycode === KEYCODE_LEFTARROW) {
+ if (this.currentImageIndex !== 0) {
+ this.changeImage(this.currentImageIndex - 1);
+ } else if (this.options.wrapAround && this.album.length > 1) {
+ this.changeImage(this.album.length - 1);
+ }
+ } else if (key === 'n' || keycode === KEYCODE_RIGHTARROW) {
+ if (this.currentImageIndex !== this.album.length - 1) {
+ this.changeImage(this.currentImageIndex + 1);
+ } else if (this.options.wrapAround && this.album.length > 1) {
+ this.changeImage(0);
+ }
+ }
+ };
+
+ // Closing time. :-(
+ Lightbox.prototype.end = function() {
+ this.disableKeyboardNav();
+ $(window).off('resize', this.sizeOverlay);
+ this.$lightbox.fadeOut(this.options.fadeDuration);
+ this.$overlay.fadeOut(this.options.fadeDuration);
+ $('select, object, embed').css({
+ visibility: 'visible'
+ });
+ if (this.options.disableScrolling) {
+ $('html').removeClass('lb-disable-scrolling');
+ }
+ };
+
+ return new Lightbox();
+}));
+
+
+/**
+ * Owl Carousel v2.3.1
+ * Copyright 2013-2018 David Deutsch
+ * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
+ */
+/**
+ * Owl carousel
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ * @todo Lazy Load Icon
+ * @todo prevent animationend bubling
+ * @todo itemsScaleUp
+ * @todo Test Zepto
+ * @todo stagePadding calculate wrong active classes
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates a carousel.
+ * @class The Owl Carousel.
+ * @public
+ * @param {HTMLElement|jQuery} element - The element to create the carousel for.
+ * @param {Object} [options] - The options
+ */
+ function Owl(element, options) {
+
+ /**
+ * Current settings for the carousel.
+ * @public
+ */
+ this.settings = null;
+
+ /**
+ * Current options set by the caller including defaults.
+ * @public
+ */
+ this.options = $.extend({}, Owl.Defaults, options);
+
+ /**
+ * Plugin element.
+ * @public
+ */
+ this.$element = $(element);
+
+ /**
+ * Proxied event handlers.
+ * @protected
+ */
+ this._handlers = {};
+
+ /**
+ * References to the running plugins of this carousel.
+ * @protected
+ */
+ this._plugins = {};
+
+ /**
+ * Currently suppressed events to prevent them from being retriggered.
+ * @protected
+ */
+ this._supress = {};
+
+ /**
+ * Absolute current position.
+ * @protected
+ */
+ this._current = null;
+
+ /**
+ * Animation speed in milliseconds.
+ * @protected
+ */
+ this._speed = null;
+
+ /**
+ * Coordinates of all items in pixel.
+ * @todo The name of this member is missleading.
+ * @protected
+ */
+ this._coordinates = [];
+
+ /**
+ * Current breakpoint.
+ * @todo Real media queries would be nice.
+ * @protected
+ */
+ this._breakpoint = null;
+
+ /**
+ * Current width of the plugin element.
+ */
+ this._width = null;
+
+ /**
+ * All real items.
+ * @protected
+ */
+ this._items = [];
+
+ /**
+ * All cloned items.
+ * @protected
+ */
+ this._clones = [];
+
+ /**
+ * Merge values of all items.
+ * @todo Maybe this could be part of a plugin.
+ * @protected
+ */
+ this._mergers = [];
+
+ /**
+ * Widths of all items.
+ */
+ this._widths = [];
+
+ /**
+ * Invalidated parts within the update process.
+ * @protected
+ */
+ this._invalidated = {};
+
+ /**
+ * Ordered list of workers for the update process.
+ * @protected
+ */
+ this._pipe = [];
+
+ /**
+ * Current state information for the drag operation.
+ * @todo #261
+ * @protected
+ */
+ this._drag = {
+ time: null,
+ target: null,
+ pointer: null,
+ stage: {
+ start: null,
+ current: null
+ },
+ direction: null
+ };
+
+ /**
+ * Current state information and their tags.
+ * @type {Object}
+ * @protected
+ */
+ this._states = {
+ current: {},
+ tags: {
+ 'initializing': [ 'busy' ],
+ 'animating': [ 'busy' ],
+ 'dragging': [ 'interacting' ]
+ }
+ };
+
+ $.each([ 'onResize', 'onThrottledResize' ], $.proxy(function(i, handler) {
+ this._handlers[handler] = $.proxy(this[handler], this);
+ }, this));
+
+ $.each(Owl.Plugins, $.proxy(function(key, plugin) {
+ this._plugins[key.charAt(0).toLowerCase() + key.slice(1)]
+ = new plugin(this);
+ }, this));
+
+ $.each(Owl.Workers, $.proxy(function(priority, worker) {
+ this._pipe.push({
+ 'filter': worker.filter,
+ 'run': $.proxy(worker.run, this)
+ });
+ }, this));
+
+ this.setup();
+ this.initialize();
+ }
+
+ /**
+ * Default options for the carousel.
+ * @public
+ */
+ Owl.Defaults = {
+ items: 3,
+ loop: false,
+ center: false,
+ rewind: false,
+
+ mouseDrag: true,
+ touchDrag: true,
+ pullDrag: true,
+ freeDrag: false,
+
+ margin: 0,
+ stagePadding: 0,
+
+ merge: false,
+ mergeFit: true,
+ autoWidth: false,
+
+ startPosition: 0,
+ rtl: false,
+
+ smartSpeed: 250,
+ fluidSpeed: false,
+ dragEndSpeed: false,
+
+ responsive: {},
+ responsiveRefreshRate: 200,
+ responsiveBaseElement: window,
+
+ fallbackEasing: 'swing',
+
+ info: false,
+
+ nestedItemSelector: false,
+ itemElement: 'div',
+ stageElement: 'div',
+
+ refreshClass: 'owl-refresh',
+ loadedClass: 'owl-loaded',
+ loadingClass: 'owl-loading',
+ rtlClass: 'owl-rtl',
+ responsiveClass: 'owl-responsive',
+ dragClass: 'owl-drag',
+ itemClass: 'owl-item',
+ stageClass: 'owl-stage',
+ stageOuterClass: 'owl-stage-outer',
+ grabClass: 'owl-grab'
+ };
+
+ /**
+ * Enumeration for width.
+ * @public
+ * @readonly
+ * @enum {String}
+ */
+ Owl.Width = {
+ Default: 'default',
+ Inner: 'inner',
+ Outer: 'outer'
+ };
+
+ /**
+ * Enumeration for types.
+ * @public
+ * @readonly
+ * @enum {String}
+ */
+ Owl.Type = {
+ Event: 'event',
+ State: 'state'
+ };
+
+ /**
+ * Contains all registered plugins.
+ * @public
+ */
+ Owl.Plugins = {};
+
+ /**
+ * List of workers involved in the update process.
+ */
+ Owl.Workers = [ {
+ filter: [ 'width', 'settings' ],
+ run: function() {
+ this._width = this.$element.width();
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function(cache) {
+ cache.current = this._items && this._items[this.relative(this._current)];
+ }
+ }, {
+ filter: [ 'items', 'settings' ],
+ run: function() {
+ this.$stage.children('.cloned').remove();
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function(cache) {
+ var margin = this.settings.margin || '',
+ grid = !this.settings.autoWidth,
+ rtl = this.settings.rtl,
+ css = {
+ 'width': 'auto',
+ 'margin-left': rtl ? margin : '',
+ 'margin-right': rtl ? '' : margin
+ };
+
+ !grid && this.$stage.children().css(css);
+
+ cache.css = css;
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function(cache) {
+ var width = (this.width() / this.settings.items).toFixed(3) - this.settings.margin,
+ merge = null,
+ iterator = this._items.length,
+ grid = !this.settings.autoWidth,
+ widths = [];
+
+ cache.items = {
+ merge: false,
+ width: width
+ };
+
+ while (iterator--) {
+ merge = this._mergers[iterator];
+ merge = this.settings.mergeFit && Math.min(merge, this.settings.items) || merge;
+
+ cache.items.merge = merge > 1 || cache.items.merge;
+
+ widths[iterator] = !grid ? this._items[iterator].width() : width * merge;
+ }
+
+ this._widths = widths;
+ }
+ }, {
+ filter: [ 'items', 'settings' ],
+ run: function() {
+ var clones = [],
+ items = this._items,
+ settings = this.settings,
+ // TODO: Should be computed from number of min width items in stage
+ view = Math.max(settings.items * 2, 4),
+ size = Math.ceil(items.length / 2) * 2,
+ repeat = settings.loop && items.length ? settings.rewind ? view : Math.max(view, size) : 0,
+ append = '',
+ prepend = '';
+
+ repeat /= 2;
+
+ while (repeat > 0) {
+ // Switch to only using appended clones
+ clones.push(this.normalize(clones.length / 2, true));
+ append = append + items[clones[clones.length - 1]][0].outerHTML;
+ clones.push(this.normalize(items.length - 1 - (clones.length - 1) / 2, true));
+ prepend = items[clones[clones.length - 1]][0].outerHTML + prepend;
+ repeat -= 1;
+ }
+
+ this._clones = clones;
+
+ $(append).addClass('cloned').appendTo(this.$stage);
+ $(prepend).addClass('cloned').prependTo(this.$stage);
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function() {
+ var rtl = this.settings.rtl ? 1 : -1,
+ size = this._clones.length + this._items.length,
+ iterator = -1,
+ previous = 0,
+ current = 0,
+ coordinates = [];
+
+ while (++iterator < size) {
+ previous = coordinates[iterator - 1] || 0;
+ current = this._widths[this.relative(iterator)] + this.settings.margin;
+ coordinates.push(previous + current * rtl);
+ }
+
+ this._coordinates = coordinates;
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function() {
+ var padding = this.settings.stagePadding,
+ coordinates = this._coordinates,
+ css = {
+ 'width': Math.ceil(Math.abs(coordinates[coordinates.length - 1])) + padding * 2,
+ 'padding-left': padding || '',
+ 'padding-right': padding || ''
+ };
+
+ this.$stage.css(css);
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function(cache) {
+ var iterator = this._coordinates.length,
+ grid = !this.settings.autoWidth,
+ items = this.$stage.children();
+
+ if (grid && cache.items.merge) {
+ while (iterator--) {
+ cache.css.width = this._widths[this.relative(iterator)];
+ items.eq(iterator).css(cache.css);
+ }
+ } else if (grid) {
+ cache.css.width = cache.items.width;
+ items.css(cache.css);
+ }
+ }
+ }, {
+ filter: [ 'items' ],
+ run: function() {
+ this._coordinates.length < 1 && this.$stage.removeAttr('style');
+ }
+ }, {
+ filter: [ 'width', 'items', 'settings' ],
+ run: function(cache) {
+ cache.current = cache.current ? this.$stage.children().index(cache.current) : 0;
+ cache.current = Math.max(this.minimum(), Math.min(this.maximum(), cache.current));
+ this.reset(cache.current);
+ }
+ }, {
+ filter: [ 'position' ],
+ run: function() {
+ this.animate(this.coordinates(this._current));
+ }
+ }, {
+ filter: [ 'width', 'position', 'items', 'settings' ],
+ run: function() {
+ var rtl = this.settings.rtl ? 1 : -1,
+ padding = this.settings.stagePadding * 2,
+ begin = this.coordinates(this.current()) + padding,
+ end = begin + this.width() * rtl,
+ inner, outer, matches = [], i, n;
+
+ for (i = 0, n = this._coordinates.length; i < n; i++) {
+ inner = this._coordinates[i - 1] || 0;
+ outer = Math.abs(this._coordinates[i]) + padding * rtl;
+
+ if ((this.op(inner, '<=', begin) && (this.op(inner, '>', end)))
+ || (this.op(outer, '<', begin) && this.op(outer, '>', end))) {
+ matches.push(i);
+ }
+ }
+
+ this.$stage.children('.active').removeClass('active');
+ this.$stage.children(':eq(' + matches.join('), :eq(') + ')').addClass('active');
+
+ this.$stage.children('.center').removeClass('center');
+ if (this.settings.center) {
+ this.$stage.children().eq(this.current()).addClass('center');
+ }
+ }
+ } ];
+
+ /**
+ * Initializes the carousel.
+ * @protected
+ */
+ Owl.prototype.initialize = function() {
+ this.enter('initializing');
+ this.trigger('initialize');
+
+ this.$element.toggleClass(this.settings.rtlClass, this.settings.rtl);
+
+ if (this.settings.autoWidth && !this.is('pre-loading')) {
+ var imgs, nestedSelector, width;
+ imgs = this.$element.find('img');
+ nestedSelector = this.settings.nestedItemSelector ? '.' + this.settings.nestedItemSelector : undefined;
+ width = this.$element.children(nestedSelector).width();
+
+ if (imgs.length && width <= 0) {
+ this.preloadAutoWidthImages(imgs);
+ }
+ }
+
+ this.$element.addClass(this.options.loadingClass);
+
+ // create stage
+ this.$stage = $('<' + this.settings.stageElement + ' class="' + this.settings.stageClass + '"/>')
+ .wrap('');
+
+ // append stage
+ this.$element.append(this.$stage.parent());
+
+ // append content
+ this.replace(this.$element.children().not(this.$stage.parent()));
+
+ // check visibility
+ if (this.$element.is(':visible')) {
+ // update view
+ this.refresh();
+ } else {
+ // invalidate width
+ this.invalidate('width');
+ }
+
+ this.$element
+ .removeClass(this.options.loadingClass)
+ .addClass(this.options.loadedClass);
+
+ // register event handlers
+ this.registerEventHandlers();
+
+ this.leave('initializing');
+ this.trigger('initialized');
+ };
+
+ /**
+ * Setups the current settings.
+ * @todo Remove responsive classes. Why should adaptive designs be brought into IE8?
+ * @todo Support for media queries by using `matchMedia` would be nice.
+ * @public
+ */
+ Owl.prototype.setup = function() {
+ var viewport = this.viewport(),
+ overwrites = this.options.responsive,
+ match = -1,
+ settings = null;
+
+ if (!overwrites) {
+ settings = $.extend({}, this.options);
+ } else {
+ $.each(overwrites, function(breakpoint) {
+ if (breakpoint <= viewport && breakpoint > match) {
+ match = Number(breakpoint);
+ }
+ });
+
+ settings = $.extend({}, this.options, overwrites[match]);
+ if (typeof settings.stagePadding === 'function') {
+ settings.stagePadding = settings.stagePadding();
+ }
+ delete settings.responsive;
+
+ // responsive class
+ if (settings.responsiveClass) {
+ this.$element.attr('class',
+ this.$element.attr('class').replace(new RegExp('(' + this.options.responsiveClass + '-)\\S+\\s', 'g'), '$1' + match)
+ );
+ }
+ }
+
+ this.trigger('change', { property: { name: 'settings', value: settings } });
+ this._breakpoint = match;
+ this.settings = settings;
+ this.invalidate('settings');
+ this.trigger('changed', { property: { name: 'settings', value: this.settings } });
+ };
+
+ /**
+ * Updates option logic if necessery.
+ * @protected
+ */
+ Owl.prototype.optionsLogic = function() {
+ if (this.settings.autoWidth) {
+ this.settings.stagePadding = false;
+ this.settings.merge = false;
+ }
+ };
+
+ /**
+ * Prepares an item before add.
+ * @todo Rename event parameter `content` to `item`.
+ * @protected
+ * @returns {jQuery|HTMLElement} - The item container.
+ */
+ Owl.prototype.prepare = function(item) {
+ var event = this.trigger('prepare', { content: item });
+
+ if (!event.data) {
+ event.data = $('<' + this.settings.itemElement + '/>')
+ .addClass(this.options.itemClass).append(item)
+ }
+
+ this.trigger('prepared', { content: event.data });
+
+ return event.data;
+ };
+
+ /**
+ * Updates the view.
+ * @public
+ */
+ Owl.prototype.update = function() {
+ var i = 0,
+ n = this._pipe.length,
+ filter = $.proxy(function(p) { return this[p] }, this._invalidated),
+ cache = {};
+
+ while (i < n) {
+ if (this._invalidated.all || $.grep(this._pipe[i].filter, filter).length > 0) {
+ this._pipe[i].run(cache);
+ }
+ i++;
+ }
+
+ this._invalidated = {};
+
+ !this.is('valid') && this.enter('valid');
+ };
+
+ /**
+ * Gets the width of the view.
+ * @public
+ * @param {Owl.Width} [dimension=Owl.Width.Default] - The dimension to return.
+ * @returns {Number} - The width of the view in pixel.
+ */
+ Owl.prototype.width = function(dimension) {
+ dimension = dimension || Owl.Width.Default;
+ switch (dimension) {
+ case Owl.Width.Inner:
+ case Owl.Width.Outer:
+ return this._width;
+ default:
+ return this._width - this.settings.stagePadding * 2 + this.settings.margin;
+ }
+ };
+
+ /**
+ * Refreshes the carousel primarily for adaptive purposes.
+ * @public
+ */
+ Owl.prototype.refresh = function() {
+ this.enter('refreshing');
+ this.trigger('refresh');
+
+ this.setup();
+
+ this.optionsLogic();
+
+ this.$element.addClass(this.options.refreshClass);
+
+ this.update();
+
+ this.$element.removeClass(this.options.refreshClass);
+
+ this.leave('refreshing');
+ this.trigger('refreshed');
+ };
+
+ /**
+ * Checks window `resize` event.
+ * @protected
+ */
+ Owl.prototype.onThrottledResize = function() {
+ window.clearTimeout(this.resizeTimer);
+ this.resizeTimer = window.setTimeout(this._handlers.onResize, this.settings.responsiveRefreshRate);
+ };
+
+ /**
+ * Checks window `resize` event.
+ * @protected
+ */
+ Owl.prototype.onResize = function() {
+ if (!this._items.length) {
+ return false;
+ }
+
+ if (this._width === this.$element.width()) {
+ return false;
+ }
+
+ if (!this.$element.is(':visible')) {
+ return false;
+ }
+
+ this.enter('resizing');
+
+ if (this.trigger('resize').isDefaultPrevented()) {
+ this.leave('resizing');
+ return false;
+ }
+
+ this.invalidate('width');
+
+ this.refresh();
+
+ this.leave('resizing');
+ this.trigger('resized');
+ };
+
+ /**
+ * Registers event handlers.
+ * @todo Check `msPointerEnabled`
+ * @todo #261
+ * @protected
+ */
+ Owl.prototype.registerEventHandlers = function() {
+ if ($.support.transition) {
+ this.$stage.on($.support.transition.end + '.owl.core', $.proxy(this.onTransitionEnd, this));
+ }
+
+ if (this.settings.responsive !== false) {
+ this.on(window, 'resize', this._handlers.onThrottledResize);
+ }
+
+ if (this.settings.mouseDrag) {
+ this.$element.addClass(this.options.dragClass);
+ this.$stage.on('mousedown.owl.core', $.proxy(this.onDragStart, this));
+ this.$stage.on('dragstart.owl.core selectstart.owl.core', function() { return false });
+ }
+
+ if (this.settings.touchDrag){
+ this.$stage.on('touchstart.owl.core', $.proxy(this.onDragStart, this));
+ this.$stage.on('touchcancel.owl.core', $.proxy(this.onDragEnd, this));
+ }
+ };
+
+ /**
+ * Handles `touchstart` and `mousedown` events.
+ * @todo Horizontal swipe threshold as option
+ * @todo #261
+ * @protected
+ * @param {Event} event - The event arguments.
+ */
+ Owl.prototype.onDragStart = function(event) {
+ var stage = null;
+
+ if (event.which === 3) {
+ return;
+ }
+
+ if ($.support.transform) {
+ stage = this.$stage.css('transform').replace(/.*\(|\)| /g, '').split(',');
+ stage = {
+ x: stage[stage.length === 16 ? 12 : 4],
+ y: stage[stage.length === 16 ? 13 : 5]
+ };
+ } else {
+ stage = this.$stage.position();
+ stage = {
+ x: this.settings.rtl ?
+ stage.left + this.$stage.width() - this.width() + this.settings.margin :
+ stage.left,
+ y: stage.top
+ };
+ }
+
+ if (this.is('animating')) {
+ $.support.transform ? this.animate(stage.x) : this.$stage.stop()
+ this.invalidate('position');
+ }
+
+ this.$element.toggleClass(this.options.grabClass, event.type === 'mousedown');
+
+ this.speed(0);
+
+ this._drag.time = new Date().getTime();
+ this._drag.target = $(event.target);
+ this._drag.stage.start = stage;
+ this._drag.stage.current = stage;
+ this._drag.pointer = this.pointer(event);
+
+ $(document).on('mouseup.owl.core touchend.owl.core', $.proxy(this.onDragEnd, this));
+
+ $(document).one('mousemove.owl.core touchmove.owl.core', $.proxy(function(event) {
+ var delta = this.difference(this._drag.pointer, this.pointer(event));
+
+ $(document).on('mousemove.owl.core touchmove.owl.core', $.proxy(this.onDragMove, this));
+
+ if (Math.abs(delta.x) < Math.abs(delta.y) && this.is('valid')) {
+ return;
+ }
+
+ event.preventDefault();
+
+ this.enter('dragging');
+ this.trigger('drag');
+ }, this));
+ };
+
+ /**
+ * Handles the `touchmove` and `mousemove` events.
+ * @todo #261
+ * @protected
+ * @param {Event} event - The event arguments.
+ */
+ Owl.prototype.onDragMove = function(event) {
+ var minimum = null,
+ maximum = null,
+ pull = null,
+ delta = this.difference(this._drag.pointer, this.pointer(event)),
+ stage = this.difference(this._drag.stage.start, delta);
+
+ if (!this.is('dragging')) {
+ return;
+ }
+
+ event.preventDefault();
+
+ if (this.settings.loop) {
+ minimum = this.coordinates(this.minimum());
+ maximum = this.coordinates(this.maximum() + 1) - minimum;
+ stage.x = (((stage.x - minimum) % maximum + maximum) % maximum) + minimum;
+ } else {
+ minimum = this.settings.rtl ? this.coordinates(this.maximum()) : this.coordinates(this.minimum());
+ maximum = this.settings.rtl ? this.coordinates(this.minimum()) : this.coordinates(this.maximum());
+ pull = this.settings.pullDrag ? -1 * delta.x / 5 : 0;
+ stage.x = Math.max(Math.min(stage.x, minimum + pull), maximum + pull);
+ }
+
+ this._drag.stage.current = stage;
+
+ this.animate(stage.x);
+ };
+
+ /**
+ * Handles the `touchend` and `mouseup` events.
+ * @todo #261
+ * @todo Threshold for click event
+ * @protected
+ * @param {Event} event - The event arguments.
+ */
+ Owl.prototype.onDragEnd = function(event) {
+ var delta = this.difference(this._drag.pointer, this.pointer(event)),
+ stage = this._drag.stage.current,
+ direction = delta.x > 0 ^ this.settings.rtl ? 'left' : 'right';
+
+ $(document).off('.owl.core');
+
+ this.$element.removeClass(this.options.grabClass);
+
+ if (delta.x !== 0 && this.is('dragging') || !this.is('valid')) {
+ this.speed(this.settings.dragEndSpeed || this.settings.smartSpeed);
+ this.current(this.closest(stage.x, delta.x !== 0 ? direction : this._drag.direction));
+ this.invalidate('position');
+ this.update();
+
+ this._drag.direction = direction;
+
+ if (Math.abs(delta.x) > 3 || new Date().getTime() - this._drag.time > 300) {
+ this._drag.target.one('click.owl.core', function() { return false; });
+ }
+ }
+
+ if (!this.is('dragging')) {
+ return;
+ }
+
+ this.leave('dragging');
+ this.trigger('dragged');
+ };
+
+ /**
+ * Gets absolute position of the closest item for a coordinate.
+ * @todo Setting `freeDrag` makes `closest` not reusable. See #165.
+ * @protected
+ * @param {Number} coordinate - The coordinate in pixel.
+ * @param {String} direction - The direction to check for the closest item. Ether `left` or `right`.
+ * @return {Number} - The absolute position of the closest item.
+ */
+ Owl.prototype.closest = function(coordinate, direction) {
+ var position = -1,
+ pull = 30,
+ width = this.width(),
+ coordinates = this.coordinates();
+
+ if (!this.settings.freeDrag) {
+ // check closest item
+ $.each(coordinates, $.proxy(function(index, value) {
+ // on a left pull, check on current index
+ if (direction === 'left' && coordinate > value - pull && coordinate < value + pull) {
+ position = index;
+ // on a right pull, check on previous index
+ // to do so, subtract width from value and set position = index + 1
+ } else if (direction === 'right' && coordinate > value - width - pull && coordinate < value - width + pull) {
+ position = index + 1;
+ } else if (this.op(coordinate, '<', value)
+ && this.op(coordinate, '>', coordinates[index + 1] || value - width)) {
+ position = direction === 'left' ? index + 1 : index;
+ }
+ return position === -1;
+ }, this));
+ }
+
+ if (!this.settings.loop) {
+ // non loop boundries
+ if (this.op(coordinate, '>', coordinates[this.minimum()])) {
+ position = coordinate = this.minimum();
+ } else if (this.op(coordinate, '<', coordinates[this.maximum()])) {
+ position = coordinate = this.maximum();
+ }
+ }
+
+ return position;
+ };
+
+ /**
+ * Animates the stage.
+ * @todo #270
+ * @public
+ * @param {Number} coordinate - The coordinate in pixels.
+ */
+ Owl.prototype.animate = function(coordinate) {
+ var animate = this.speed() > 0;
+
+ this.is('animating') && this.onTransitionEnd();
+
+ if (animate) {
+ this.enter('animating');
+ this.trigger('translate');
+ }
+
+ if ($.support.transform3d && $.support.transition) {
+ this.$stage.css({
+ transform: 'translate3d(' + coordinate + 'px,0px,0px)',
+ transition: (this.speed() / 1000) + 's'
+ });
+ } else if (animate) {
+ this.$stage.animate({
+ left: coordinate + 'px'
+ }, this.speed(), this.settings.fallbackEasing, $.proxy(this.onTransitionEnd, this));
+ } else {
+ this.$stage.css({
+ left: coordinate + 'px'
+ });
+ }
+ };
+
+ /**
+ * Checks whether the carousel is in a specific state or not.
+ * @param {String} state - The state to check.
+ * @returns {Boolean} - The flag which indicates if the carousel is busy.
+ */
+ Owl.prototype.is = function(state) {
+ return this._states.current[state] && this._states.current[state] > 0;
+ };
+
+ /**
+ * Sets the absolute position of the current item.
+ * @public
+ * @param {Number} [position] - The new absolute position or nothing to leave it unchanged.
+ * @returns {Number} - The absolute position of the current item.
+ */
+ Owl.prototype.current = function(position) {
+ if (position === undefined) {
+ return this._current;
+ }
+
+ if (this._items.length === 0) {
+ return undefined;
+ }
+
+ position = this.normalize(position);
+
+ if (this._current !== position) {
+ var event = this.trigger('change', { property: { name: 'position', value: position } });
+
+ if (event.data !== undefined) {
+ position = this.normalize(event.data);
+ }
+
+ this._current = position;
+
+ this.invalidate('position');
+
+ this.trigger('changed', { property: { name: 'position', value: this._current } });
+ }
+
+ return this._current;
+ };
+
+ /**
+ * Invalidates the given part of the update routine.
+ * @param {String} [part] - The part to invalidate.
+ * @returns {Array.} - The invalidated parts.
+ */
+ Owl.prototype.invalidate = function(part) {
+ if ($.type(part) === 'string') {
+ this._invalidated[part] = true;
+ this.is('valid') && this.leave('valid');
+ }
+ return $.map(this._invalidated, function(v, i) { return i });
+ };
+
+ /**
+ * Resets the absolute position of the current item.
+ * @public
+ * @param {Number} position - The absolute position of the new item.
+ */
+ Owl.prototype.reset = function(position) {
+ position = this.normalize(position);
+
+ if (position === undefined) {
+ return;
+ }
+
+ this._speed = 0;
+ this._current = position;
+
+ this.suppress([ 'translate', 'translated' ]);
+
+ this.animate(this.coordinates(position));
+
+ this.release([ 'translate', 'translated' ]);
+ };
+
+ /**
+ * Normalizes an absolute or a relative position of an item.
+ * @public
+ * @param {Number} position - The absolute or relative position to normalize.
+ * @param {Boolean} [relative=false] - Whether the given position is relative or not.
+ * @returns {Number} - The normalized position.
+ */
+ Owl.prototype.normalize = function(position, relative) {
+ var n = this._items.length,
+ m = relative ? 0 : this._clones.length;
+
+ if (!this.isNumeric(position) || n < 1) {
+ position = undefined;
+ } else if (position < 0 || position >= n + m) {
+ position = ((position - m / 2) % n + n) % n + m / 2;
+ }
+
+ return position;
+ };
+
+ /**
+ * Converts an absolute position of an item into a relative one.
+ * @public
+ * @param {Number} position - The absolute position to convert.
+ * @returns {Number} - The converted position.
+ */
+ Owl.prototype.relative = function(position) {
+ position -= this._clones.length / 2;
+ return this.normalize(position, true);
+ };
+
+ /**
+ * Gets the maximum position for the current item.
+ * @public
+ * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
+ * @returns {Number}
+ */
+ Owl.prototype.maximum = function(relative) {
+ var settings = this.settings,
+ maximum = this._coordinates.length,
+ iterator,
+ reciprocalItemsWidth,
+ elementWidth;
+
+ if (settings.loop) {
+ maximum = this._clones.length / 2 + this._items.length - 1;
+ } else if (settings.autoWidth || settings.merge) {
+ iterator = this._items.length;
+ if (iterator) {
+ reciprocalItemsWidth = this._items[--iterator].width();
+ elementWidth = this.$element.width();
+ while (iterator--) {
+ reciprocalItemsWidth += this._items[iterator].width() + this.settings.margin;
+ if (reciprocalItemsWidth > elementWidth) {
+ break;
+ }
+ }
+ }
+ maximum = iterator + 1;
+ } else if (settings.center) {
+ maximum = this._items.length - 1;
+ } else {
+ maximum = this._items.length - settings.items;
+ }
+
+ if (relative) {
+ maximum -= this._clones.length / 2;
+ }
+
+ return Math.max(maximum, 0);
+ };
+
+ /**
+ * Gets the minimum position for the current item.
+ * @public
+ * @param {Boolean} [relative=false] - Whether to return an absolute position or a relative position.
+ * @returns {Number}
+ */
+ Owl.prototype.minimum = function(relative) {
+ return relative ? 0 : this._clones.length / 2;
+ };
+
+ /**
+ * Gets an item at the specified relative position.
+ * @public
+ * @param {Number} [position] - The relative position of the item.
+ * @return {jQuery|Array.} - The item at the given position or all items if no position was given.
+ */
+ Owl.prototype.items = function(position) {
+ if (position === undefined) {
+ return this._items.slice();
+ }
+
+ position = this.normalize(position, true);
+ return this._items[position];
+ };
+
+ /**
+ * Gets an item at the specified relative position.
+ * @public
+ * @param {Number} [position] - The relative position of the item.
+ * @return {jQuery|Array.} - The item at the given position or all items if no position was given.
+ */
+ Owl.prototype.mergers = function(position) {
+ if (position === undefined) {
+ return this._mergers.slice();
+ }
+
+ position = this.normalize(position, true);
+ return this._mergers[position];
+ };
+
+ /**
+ * Gets the absolute positions of clones for an item.
+ * @public
+ * @param {Number} [position] - The relative position of the item.
+ * @returns {Array.} - The absolute positions of clones for the item or all if no position was given.
+ */
+ Owl.prototype.clones = function(position) {
+ var odd = this._clones.length / 2,
+ even = odd + this._items.length,
+ map = function(index) { return index % 2 === 0 ? even + index / 2 : odd - (index + 1) / 2 };
+
+ if (position === undefined) {
+ return $.map(this._clones, function(v, i) { return map(i) });
+ }
+
+ return $.map(this._clones, function(v, i) { return v === position ? map(i) : null });
+ };
+
+ /**
+ * Sets the current animation speed.
+ * @public
+ * @param {Number} [speed] - The animation speed in milliseconds or nothing to leave it unchanged.
+ * @returns {Number} - The current animation speed in milliseconds.
+ */
+ Owl.prototype.speed = function(speed) {
+ if (speed !== undefined) {
+ this._speed = speed;
+ }
+
+ return this._speed;
+ };
+
+ /**
+ * Gets the coordinate of an item.
+ * @todo The name of this method is missleanding.
+ * @public
+ * @param {Number} position - The absolute position of the item within `minimum()` and `maximum()`.
+ * @returns {Number|Array.} - The coordinate of the item in pixel or all coordinates.
+ */
+ Owl.prototype.coordinates = function(position) {
+ var multiplier = 1,
+ newPosition = position - 1,
+ coordinate;
+
+ if (position === undefined) {
+ return $.map(this._coordinates, $.proxy(function(coordinate, index) {
+ return this.coordinates(index);
+ }, this));
+ }
+
+ if (this.settings.center) {
+ if (this.settings.rtl) {
+ multiplier = -1;
+ newPosition = position + 1;
+ }
+
+ coordinate = this._coordinates[position];
+ coordinate += (this.width() - coordinate + (this._coordinates[newPosition] || 0)) / 2 * multiplier;
+ } else {
+ coordinate = this._coordinates[newPosition] || 0;
+ }
+
+ coordinate = Math.ceil(coordinate);
+
+ return coordinate;
+ };
+
+ /**
+ * Calculates the speed for a translation.
+ * @protected
+ * @param {Number} from - The absolute position of the start item.
+ * @param {Number} to - The absolute position of the target item.
+ * @param {Number} [factor=undefined] - The time factor in milliseconds.
+ * @returns {Number} - The time in milliseconds for the translation.
+ */
+ Owl.prototype.duration = function(from, to, factor) {
+ if (factor === 0) {
+ return 0;
+ }
+
+ return Math.min(Math.max(Math.abs(to - from), 1), 6) * Math.abs((factor || this.settings.smartSpeed));
+ };
+
+ /**
+ * Slides to the specified item.
+ * @public
+ * @param {Number} position - The position of the item.
+ * @param {Number} [speed] - The time in milliseconds for the transition.
+ */
+ Owl.prototype.to = function(position, speed) {
+ var current = this.current(),
+ revert = null,
+ distance = position - this.relative(current),
+ direction = (distance > 0) - (distance < 0),
+ items = this._items.length,
+ minimum = this.minimum(),
+ maximum = this.maximum();
+
+ if (this.settings.loop) {
+ if (!this.settings.rewind && Math.abs(distance) > items / 2) {
+ distance += direction * -1 * items;
+ }
+
+ position = current + distance;
+ revert = ((position - minimum) % items + items) % items + minimum;
+
+ if (revert !== position && revert - distance <= maximum && revert - distance > 0) {
+ current = revert - distance;
+ position = revert;
+ this.reset(current);
+ }
+ } else if (this.settings.rewind) {
+ maximum += 1;
+ position = (position % maximum + maximum) % maximum;
+ } else {
+ position = Math.max(minimum, Math.min(maximum, position));
+ }
+
+ this.speed(this.duration(current, position, speed));
+ this.current(position);
+
+ if (this.$element.is(':visible')) {
+ this.update();
+ }
+ };
+
+ /**
+ * Slides to the next item.
+ * @public
+ * @param {Number} [speed] - The time in milliseconds for the transition.
+ */
+ Owl.prototype.next = function(speed) {
+ speed = speed || false;
+ this.to(this.relative(this.current()) + 1, speed);
+ };
+
+ /**
+ * Slides to the previous item.
+ * @public
+ * @param {Number} [speed] - The time in milliseconds for the transition.
+ */
+ Owl.prototype.prev = function(speed) {
+ speed = speed || false;
+ this.to(this.relative(this.current()) - 1, speed);
+ };
+
+ /**
+ * Handles the end of an animation.
+ * @protected
+ * @param {Event} event - The event arguments.
+ */
+ Owl.prototype.onTransitionEnd = function(event) {
+
+ // if css2 animation then event object is undefined
+ if (event !== undefined) {
+ event.stopPropagation();
+
+ // Catch only owl-stage transitionEnd event
+ if ((event.target || event.srcElement || event.originalTarget) !== this.$stage.get(0)) {
+ return false;
+ }
+ }
+
+ this.leave('animating');
+ this.trigger('translated');
+ };
+
+ /**
+ * Gets viewport width.
+ * @protected
+ * @return {Number} - The width in pixel.
+ */
+ Owl.prototype.viewport = function() {
+ var width;
+ if (this.options.responsiveBaseElement !== window) {
+ width = $(this.options.responsiveBaseElement).width();
+ } else if (window.innerWidth) {
+ width = window.innerWidth;
+ } else if (document.documentElement && document.documentElement.clientWidth) {
+ width = document.documentElement.clientWidth;
+ } else {
+ console.warn('Can not detect viewport width.');
+ }
+ return width;
+ };
+
+ /**
+ * Replaces the current content.
+ * @public
+ * @param {HTMLElement|jQuery|String} content - The new content.
+ */
+ Owl.prototype.replace = function(content) {
+ this.$stage.empty();
+ this._items = [];
+
+ if (content) {
+ content = (content instanceof jQuery) ? content : $(content);
+ }
+
+ if (this.settings.nestedItemSelector) {
+ content = content.find('.' + this.settings.nestedItemSelector);
+ }
+
+ content.filter(function() {
+ return this.nodeType === 1;
+ }).each($.proxy(function(index, item) {
+ item = this.prepare(item);
+ this.$stage.append(item);
+ this._items.push(item);
+ this._mergers.push(item.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
+ }, this));
+
+ this.reset(this.isNumeric(this.settings.startPosition) ? this.settings.startPosition : 0);
+
+ this.invalidate('items');
+ };
+
+ /**
+ * Adds an item.
+ * @todo Use `item` instead of `content` for the event arguments.
+ * @public
+ * @param {HTMLElement|jQuery|String} content - The item content to add.
+ * @param {Number} [position] - The relative position at which to insert the item otherwise the item will be added to the end.
+ */
+ Owl.prototype.add = function(content, position) {
+ var current = this.relative(this._current);
+
+ position = position === undefined ? this._items.length : this.normalize(position, true);
+ content = content instanceof jQuery ? content : $(content);
+
+ this.trigger('add', { content: content, position: position });
+
+ content = this.prepare(content);
+
+ if (this._items.length === 0 || position === this._items.length) {
+ this._items.length === 0 && this.$stage.append(content);
+ this._items.length !== 0 && this._items[position - 1].after(content);
+ this._items.push(content);
+ this._mergers.push(content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
+ } else {
+ this._items[position].before(content);
+ this._items.splice(position, 0, content);
+ this._mergers.splice(position, 0, content.find('[data-merge]').addBack('[data-merge]').attr('data-merge') * 1 || 1);
+ }
+
+ this._items[current] && this.reset(this._items[current].index());
+
+ this.invalidate('items');
+
+ this.trigger('added', { content: content, position: position });
+ };
+
+ /**
+ * Removes an item by its position.
+ * @todo Use `item` instead of `content` for the event arguments.
+ * @public
+ * @param {Number} position - The relative position of the item to remove.
+ */
+ Owl.prototype.remove = function(position) {
+ position = this.normalize(position, true);
+
+ if (position === undefined) {
+ return;
+ }
+
+ this.trigger('remove', { content: this._items[position], position: position });
+
+ this._items[position].remove();
+ this._items.splice(position, 1);
+ this._mergers.splice(position, 1);
+
+ this.invalidate('items');
+
+ this.trigger('removed', { content: null, position: position });
+ };
+
+ /**
+ * Preloads images with auto width.
+ * @todo Replace by a more generic approach
+ * @protected
+ */
+ Owl.prototype.preloadAutoWidthImages = function(images) {
+ images.each($.proxy(function(i, element) {
+ this.enter('pre-loading');
+ element = $(element);
+ $(new Image()).one('load', $.proxy(function(e) {
+ element.attr('src', e.target.src);
+ element.css('opacity', 1);
+ this.leave('pre-loading');
+ !this.is('pre-loading') && !this.is('initializing') && this.refresh();
+ }, this)).attr('src', element.attr('src') || element.attr('data-src') || element.attr('data-src-retina'));
+ }, this));
+ };
+
+ /**
+ * Destroys the carousel.
+ * @public
+ */
+ Owl.prototype.destroy = function() {
+
+ this.$element.off('.owl.core');
+ this.$stage.off('.owl.core');
+ $(document).off('.owl.core');
+
+ if (this.settings.responsive !== false) {
+ window.clearTimeout(this.resizeTimer);
+ this.off(window, 'resize', this._handlers.onThrottledResize);
+ }
+
+ for (var i in this._plugins) {
+ this._plugins[i].destroy();
+ }
+
+ this.$stage.children('.cloned').remove();
+
+ this.$stage.unwrap();
+ this.$stage.children().contents().unwrap();
+ this.$stage.children().unwrap();
+ this.$stage.remove();
+ this.$element
+ .removeClass(this.options.refreshClass)
+ .removeClass(this.options.loadingClass)
+ .removeClass(this.options.loadedClass)
+ .removeClass(this.options.rtlClass)
+ .removeClass(this.options.dragClass)
+ .removeClass(this.options.grabClass)
+ .attr('class', this.$element.attr('class').replace(new RegExp(this.options.responsiveClass + '-\\S+\\s', 'g'), ''))
+ .removeData('owl.carousel');
+ };
+
+ /**
+ * Operators to calculate right-to-left and left-to-right.
+ * @protected
+ * @param {Number} [a] - The left side operand.
+ * @param {String} [o] - The operator.
+ * @param {Number} [b] - The right side operand.
+ */
+ Owl.prototype.op = function(a, o, b) {
+ var rtl = this.settings.rtl;
+ switch (o) {
+ case '<':
+ return rtl ? a > b : a < b;
+ case '>':
+ return rtl ? a < b : a > b;
+ case '>=':
+ return rtl ? a <= b : a >= b;
+ case '<=':
+ return rtl ? a >= b : a <= b;
+ default:
+ break;
+ }
+ };
+
+ /**
+ * Attaches to an internal event.
+ * @protected
+ * @param {HTMLElement} element - The event source.
+ * @param {String} event - The event name.
+ * @param {Function} listener - The event handler to attach.
+ * @param {Boolean} capture - Wether the event should be handled at the capturing phase or not.
+ */
+ Owl.prototype.on = function(element, event, listener, capture) {
+ if (element.addEventListener) {
+ element.addEventListener(event, listener, capture);
+ } else if (element.attachEvent) {
+ element.attachEvent('on' + event, listener);
+ }
+ };
+
+ /**
+ * Detaches from an internal event.
+ * @protected
+ * @param {HTMLElement} element - The event source.
+ * @param {String} event - The event name.
+ * @param {Function} listener - The attached event handler to detach.
+ * @param {Boolean} capture - Wether the attached event handler was registered as a capturing listener or not.
+ */
+ Owl.prototype.off = function(element, event, listener, capture) {
+ if (element.removeEventListener) {
+ element.removeEventListener(event, listener, capture);
+ } else if (element.detachEvent) {
+ element.detachEvent('on' + event, listener);
+ }
+ };
+
+ /**
+ * Triggers a public event.
+ * @todo Remove `status`, `relatedTarget` should be used instead.
+ * @protected
+ * @param {String} name - The event name.
+ * @param {*} [data=null] - The event data.
+ * @param {String} [namespace=carousel] - The event namespace.
+ * @param {String} [state] - The state which is associated with the event.
+ * @param {Boolean} [enter=false] - Indicates if the call enters the specified state or not.
+ * @returns {Event} - The event arguments.
+ */
+ Owl.prototype.trigger = function(name, data, namespace, state, enter) {
+ var status = {
+ item: { count: this._items.length, index: this.current() }
+ }, handler = $.camelCase(
+ $.grep([ 'on', name, namespace ], function(v) { return v })
+ .join('-').toLowerCase()
+ ), event = $.Event(
+ [ name, 'owl', namespace || 'carousel' ].join('.').toLowerCase(),
+ $.extend({ relatedTarget: this }, status, data)
+ );
+
+ if (!this._supress[name]) {
+ $.each(this._plugins, function(name, plugin) {
+ if (plugin.onTrigger) {
+ plugin.onTrigger(event);
+ }
+ });
+
+ this.register({ type: Owl.Type.Event, name: name });
+ this.$element.trigger(event);
+
+ if (this.settings && typeof this.settings[handler] === 'function') {
+ this.settings[handler].call(this, event);
+ }
+ }
+
+ return event;
+ };
+
+ /**
+ * Enters a state.
+ * @param name - The state name.
+ */
+ Owl.prototype.enter = function(name) {
+ $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
+ if (this._states.current[name] === undefined) {
+ this._states.current[name] = 0;
+ }
+
+ this._states.current[name]++;
+ }, this));
+ };
+
+ /**
+ * Leaves a state.
+ * @param name - The state name.
+ */
+ Owl.prototype.leave = function(name) {
+ $.each([ name ].concat(this._states.tags[name] || []), $.proxy(function(i, name) {
+ this._states.current[name]--;
+ }, this));
+ };
+
+ /**
+ * Registers an event or state.
+ * @public
+ * @param {Object} object - The event or state to register.
+ */
+ Owl.prototype.register = function(object) {
+ if (object.type === Owl.Type.Event) {
+ if (!$.event.special[object.name]) {
+ $.event.special[object.name] = {};
+ }
+
+ if (!$.event.special[object.name].owl) {
+ var _default = $.event.special[object.name]._default;
+ $.event.special[object.name]._default = function(e) {
+ if (_default && _default.apply && (!e.namespace || e.namespace.indexOf('owl') === -1)) {
+ return _default.apply(this, arguments);
+ }
+ return e.namespace && e.namespace.indexOf('owl') > -1;
+ };
+ $.event.special[object.name].owl = true;
+ }
+ } else if (object.type === Owl.Type.State) {
+ if (!this._states.tags[object.name]) {
+ this._states.tags[object.name] = object.tags;
+ } else {
+ this._states.tags[object.name] = this._states.tags[object.name].concat(object.tags);
+ }
+
+ this._states.tags[object.name] = $.grep(this._states.tags[object.name], $.proxy(function(tag, i) {
+ return $.inArray(tag, this._states.tags[object.name]) === i;
+ }, this));
+ }
+ };
+
+ /**
+ * Suppresses events.
+ * @protected
+ * @param {Array.} events - The events to suppress.
+ */
+ Owl.prototype.suppress = function(events) {
+ $.each(events, $.proxy(function(index, event) {
+ this._supress[event] = true;
+ }, this));
+ };
+
+ /**
+ * Releases suppressed events.
+ * @protected
+ * @param {Array.} events - The events to release.
+ */
+ Owl.prototype.release = function(events) {
+ $.each(events, $.proxy(function(index, event) {
+ delete this._supress[event];
+ }, this));
+ };
+
+ /**
+ * Gets unified pointer coordinates from event.
+ * @todo #261
+ * @protected
+ * @param {Event} - The `mousedown` or `touchstart` event.
+ * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
+ */
+ Owl.prototype.pointer = function(event) {
+ var result = { x: null, y: null };
+
+ event = event.originalEvent || event || window.event;
+
+ event = event.touches && event.touches.length ?
+ event.touches[0] : event.changedTouches && event.changedTouches.length ?
+ event.changedTouches[0] : event;
+
+ if (event.pageX) {
+ result.x = event.pageX;
+ result.y = event.pageY;
+ } else {
+ result.x = event.clientX;
+ result.y = event.clientY;
+ }
+
+ return result;
+ };
+
+ /**
+ * Determines if the input is a Number or something that can be coerced to a Number
+ * @protected
+ * @param {Number|String|Object|Array|Boolean|RegExp|Function|Symbol} - The input to be tested
+ * @returns {Boolean} - An indication if the input is a Number or can be coerced to a Number
+ */
+ Owl.prototype.isNumeric = function(number) {
+ return !isNaN(parseFloat(number));
+ };
+
+ /**
+ * Gets the difference of two vectors.
+ * @todo #261
+ * @protected
+ * @param {Object} - The first vector.
+ * @param {Object} - The second vector.
+ * @returns {Object} - The difference.
+ */
+ Owl.prototype.difference = function(first, second) {
+ return {
+ x: first.x - second.x,
+ y: first.y - second.y
+ };
+ };
+
+ /**
+ * The jQuery Plugin for the Owl Carousel
+ * @todo Navigation plugin `next` and `prev`
+ * @public
+ */
+ $.fn.owlCarousel = function(option) {
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ return this.each(function() {
+ var $this = $(this),
+ data = $this.data('owl.carousel');
+
+ if (!data) {
+ data = new Owl(this, typeof option == 'object' && option);
+ $this.data('owl.carousel', data);
+
+ $.each([
+ 'next', 'prev', 'to', 'destroy', 'refresh', 'replace', 'add', 'remove'
+ ], function(i, event) {
+ data.register({ type: Owl.Type.Event, name: event });
+ data.$element.on(event + '.owl.carousel.core', $.proxy(function(e) {
+ if (e.namespace && e.relatedTarget !== this) {
+ this.suppress([ event ]);
+ data[event].apply(this, [].slice.call(arguments, 1));
+ this.release([ event ]);
+ }
+ }, data));
+ });
+ }
+
+ if (typeof option == 'string' && option.charAt(0) !== '_') {
+ data[option].apply(data, args);
+ }
+ });
+ };
+
+ /**
+ * The constructor for the jQuery Plugin
+ * @public
+ */
+ $.fn.owlCarousel.Constructor = Owl;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * AutoRefresh Plugin
+ * @version 2.3.1
+ * @author Artus Kolanowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the auto refresh plugin.
+ * @class The Auto Refresh Plugin
+ * @param {Owl} carousel - The Owl Carousel
+ */
+ var AutoRefresh = function(carousel) {
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * Refresh interval.
+ * @protected
+ * @type {number}
+ */
+ this._interval = null;
+
+ /**
+ * Whether the element is currently visible or not.
+ * @protected
+ * @type {Boolean}
+ */
+ this._visible = null;
+
+ /**
+ * All event handlers.
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'initialized.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.autoRefresh) {
+ this.watch();
+ }
+ }, this)
+ };
+
+ // set default options
+ this._core.options = $.extend({}, AutoRefresh.Defaults, this._core.options);
+
+ // register event handlers
+ this._core.$element.on(this._handlers);
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ AutoRefresh.Defaults = {
+ autoRefresh: true,
+ autoRefreshInterval: 500
+ };
+
+ /**
+ * Watches the element.
+ */
+ AutoRefresh.prototype.watch = function() {
+ if (this._interval) {
+ return;
+ }
+
+ this._visible = this._core.$element.is(':visible');
+ this._interval = window.setInterval($.proxy(this.refresh, this), this._core.settings.autoRefreshInterval);
+ };
+
+ /**
+ * Refreshes the element.
+ */
+ AutoRefresh.prototype.refresh = function() {
+ if (this._core.$element.is(':visible') === this._visible) {
+ return;
+ }
+
+ this._visible = !this._visible;
+
+ this._core.$element.toggleClass('owl-hidden', !this._visible);
+
+ this._visible && (this._core.invalidate('width') && this._core.refresh());
+ };
+
+ /**
+ * Destroys the plugin.
+ */
+ AutoRefresh.prototype.destroy = function() {
+ var handler, property;
+
+ window.clearInterval(this._interval);
+
+ for (handler in this._handlers) {
+ this._core.$element.off(handler, this._handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.AutoRefresh = AutoRefresh;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * Lazy Plugin
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the lazy plugin.
+ * @class The Lazy Plugin
+ * @param {Owl} carousel - The Owl Carousel
+ */
+ var Lazy = function(carousel) {
+
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * Already loaded items.
+ * @protected
+ * @type {Array.}
+ */
+ this._loaded = [];
+
+ /**
+ * Event handlers.
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'initialized.owl.carousel change.owl.carousel resized.owl.carousel': $.proxy(function(e) {
+ if (!e.namespace) {
+ return;
+ }
+
+ if (!this._core.settings || !this._core.settings.lazyLoad) {
+ return;
+ }
+
+ if ((e.property && e.property.name == 'position') || e.type == 'initialized') {
+ var settings = this._core.settings,
+ n = (settings.center && Math.ceil(settings.items / 2) || settings.items),
+ i = ((settings.center && n * -1) || 0),
+ position = (e.property && e.property.value !== undefined ? e.property.value : this._core.current()) + i,
+ clones = this._core.clones().length,
+ load = $.proxy(function(i, v) { this.load(v) }, this);
+
+ while (i++ < n) {
+ this.load(clones / 2 + this._core.relative(position));
+ clones && $.each(this._core.clones(this._core.relative(position)), load);
+ position++;
+ }
+ }
+ }, this)
+ };
+
+ // set the default options
+ this._core.options = $.extend({}, Lazy.Defaults, this._core.options);
+
+ // register event handler
+ this._core.$element.on(this._handlers);
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ Lazy.Defaults = {
+ lazyLoad: false
+ };
+
+ /**
+ * Loads all resources of an item at the specified position.
+ * @param {Number} position - The absolute position of the item.
+ * @protected
+ */
+ Lazy.prototype.load = function(position) {
+ var $item = this._core.$stage.children().eq(position),
+ $elements = $item && $item.find('.owl-lazy');
+
+ if (!$elements || $.inArray($item.get(0), this._loaded) > -1) {
+ return;
+ }
+
+ $elements.each($.proxy(function(index, element) {
+ var $element = $(element), image,
+ url = (window.devicePixelRatio > 1 && $element.attr('data-src-retina')) || $element.attr('data-src');
+
+ this._core.trigger('load', { element: $element, url: url }, 'lazy');
+
+ if ($element.is('img')) {
+ $element.one('load.owl.lazy', $.proxy(function() {
+ $element.css('opacity', 1);
+ this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
+ }, this)).attr('src', url);
+ } else {
+ image = new Image();
+ image.onload = $.proxy(function() {
+ $element.css({
+ 'background-image': 'url("' + url + '")',
+ 'opacity': '1'
+ });
+ this._core.trigger('loaded', { element: $element, url: url }, 'lazy');
+ }, this);
+ image.src = url;
+ }
+ }, this));
+
+ this._loaded.push($item.get(0));
+ };
+
+ /**
+ * Destroys the plugin.
+ * @public
+ */
+ Lazy.prototype.destroy = function() {
+ var handler, property;
+
+ for (handler in this.handlers) {
+ this._core.$element.off(handler, this.handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.Lazy = Lazy;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * AutoHeight Plugin
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the auto height plugin.
+ * @class The Auto Height Plugin
+ * @param {Owl} carousel - The Owl Carousel
+ */
+ var AutoHeight = function(carousel) {
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * All event handlers.
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'initialized.owl.carousel refreshed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.autoHeight) {
+ this.update();
+ }
+ }, this),
+ 'changed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.autoHeight && e.property.name == 'position'){
+ this.update();
+ }
+ }, this),
+ 'loaded.owl.lazy': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.autoHeight
+ && e.element.closest('.' + this._core.settings.itemClass).index() === this._core.current()) {
+ this.update();
+ }
+ }, this)
+ };
+
+ // set default options
+ this._core.options = $.extend({}, AutoHeight.Defaults, this._core.options);
+
+ // register event handlers
+ this._core.$element.on(this._handlers);
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ AutoHeight.Defaults = {
+ autoHeight: false,
+ autoHeightClass: 'owl-height'
+ };
+
+ /**
+ * Updates the view.
+ */
+ AutoHeight.prototype.update = function() {
+ var start = this._core._current,
+ end = start + this._core.settings.items,
+ visible = this._core.$stage.children().toArray().slice(start, end),
+ heights = [],
+ maxheight = 0;
+
+ $.each(visible, function(index, item) {
+ heights.push($(item).height());
+ });
+
+ maxheight = Math.max.apply(null, heights);
+
+ this._core.$stage.parent()
+ .height(maxheight)
+ .addClass(this._core.settings.autoHeightClass);
+ };
+
+ AutoHeight.prototype.destroy = function() {
+ var handler, property;
+
+ for (handler in this._handlers) {
+ this._core.$element.off(handler, this._handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.AutoHeight = AutoHeight;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * Video Plugin
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the video plugin.
+ * @class The Video Plugin
+ * @param {Owl} carousel - The Owl Carousel
+ */
+ var Video = function(carousel) {
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * Cache all video URLs.
+ * @protected
+ * @type {Object}
+ */
+ this._videos = {};
+
+ /**
+ * Current playing item.
+ * @protected
+ * @type {jQuery}
+ */
+ this._playing = null;
+
+ /**
+ * All event handlers.
+ * @todo The cloned content removale is too late
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'initialized.owl.carousel': $.proxy(function(e) {
+ if (e.namespace) {
+ this._core.register({ type: 'state', name: 'playing', tags: [ 'interacting' ] });
+ }
+ }, this),
+ 'resize.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.video && this.isInFullScreen()) {
+ e.preventDefault();
+ }
+ }, this),
+ 'refreshed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.is('resizing')) {
+ this._core.$stage.find('.cloned .owl-video-frame').remove();
+ }
+ }, this),
+ 'changed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && e.property.name === 'position' && this._playing) {
+ this.stop();
+ }
+ }, this),
+ 'prepared.owl.carousel': $.proxy(function(e) {
+ if (!e.namespace) {
+ return;
+ }
+
+ var $element = $(e.content).find('.owl-video');
+
+ if ($element.length) {
+ $element.css('display', 'none');
+ this.fetch($element, $(e.content));
+ }
+ }, this)
+ };
+
+ // set default options
+ this._core.options = $.extend({}, Video.Defaults, this._core.options);
+
+ // register event handlers
+ this._core.$element.on(this._handlers);
+
+ this._core.$element.on('click.owl.video', '.owl-video-play-icon', $.proxy(function(e) {
+ this.play(e);
+ }, this));
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ Video.Defaults = {
+ video: false,
+ videoHeight: false,
+ videoWidth: false
+ };
+
+ /**
+ * Gets the video ID and the type (YouTube/Vimeo/vzaar only).
+ * @protected
+ * @param {jQuery} target - The target containing the video data.
+ * @param {jQuery} item - The item containing the video.
+ */
+ Video.prototype.fetch = function(target, item) {
+ var type = (function() {
+ if (target.attr('data-vimeo-id')) {
+ return 'vimeo';
+ } else if (target.attr('data-vzaar-id')) {
+ return 'vzaar'
+ } else {
+ return 'youtube';
+ }
+ })(),
+ id = target.attr('data-vimeo-id') || target.attr('data-youtube-id') || target.attr('data-vzaar-id'),
+ width = target.attr('data-width') || this._core.settings.videoWidth,
+ height = target.attr('data-height') || this._core.settings.videoHeight,
+ url = target.attr('href');
+
+ if (url) {
+
+ /*
+ Parses the id's out of the following urls (and probably more):
+ https://www.youtube.com/watch?v=:id
+ https://youtu.be/:id
+ https://vimeo.com/:id
+ https://vimeo.com/channels/:channel/:id
+ https://vimeo.com/groups/:group/videos/:id
+ https://app.vzaar.com/videos/:id
+
+ Visual example: https://regexper.com/#(http%3A%7Chttps%3A%7C)%5C%2F%5C%2F(player.%7Cwww.%7Capp.)%3F(vimeo%5C.com%7Cyoutu(be%5C.com%7C%5C.be%7Cbe%5C.googleapis%5C.com)%7Cvzaar%5C.com)%5C%2F(video%5C%2F%7Cvideos%5C%2F%7Cembed%5C%2F%7Cchannels%5C%2F.%2B%5C%2F%7Cgroups%5C%2F.%2B%5C%2F%7Cwatch%5C%3Fv%3D%7Cv%5C%2F)%3F(%5BA-Za-z0-9._%25-%5D*)(%5C%26%5CS%2B)%3F
+ */
+
+ id = url.match(/(http:|https:|)\/\/(player.|www.|app.)?(vimeo\.com|youtu(be\.com|\.be|be\.googleapis\.com)|vzaar\.com)\/(video\/|videos\/|embed\/|channels\/.+\/|groups\/.+\/|watch\?v=|v\/)?([A-Za-z0-9._%-]*)(\&\S+)?/);
+
+ if (id[3].indexOf('youtu') > -1) {
+ type = 'youtube';
+ } else if (id[3].indexOf('vimeo') > -1) {
+ type = 'vimeo';
+ } else if (id[3].indexOf('vzaar') > -1) {
+ type = 'vzaar';
+ } else {
+ throw new Error('Video URL not supported.');
+ }
+ id = id[6];
+ } else {
+ throw new Error('Missing video URL.');
+ }
+
+ this._videos[url] = {
+ type: type,
+ id: id,
+ width: width,
+ height: height
+ };
+
+ item.attr('data-video', url);
+
+ this.thumbnail(target, this._videos[url]);
+ };
+
+ /**
+ * Creates video thumbnail.
+ * @protected
+ * @param {jQuery} target - The target containing the video data.
+ * @param {Object} info - The video info object.
+ * @see `fetch`
+ */
+ Video.prototype.thumbnail = function(target, video) {
+ var tnLink,
+ icon,
+ path,
+ dimensions = video.width && video.height ? 'style="width:' + video.width + 'px;height:' + video.height + 'px;"' : '',
+ customTn = target.find('img'),
+ srcType = 'src',
+ lazyClass = '',
+ settings = this._core.settings,
+ create = function(path) {
+ icon = '';
+
+ if (settings.lazyLoad) {
+ tnLink = '';
+ } else {
+ tnLink = '';
+ }
+ target.after(tnLink);
+ target.after(icon);
+ };
+
+ // wrap video content into owl-video-wrapper div
+ target.wrap('');
+
+ if (this._core.settings.lazyLoad) {
+ srcType = 'data-src';
+ lazyClass = 'owl-lazy';
+ }
+
+ // custom thumbnail
+ if (customTn.length) {
+ create(customTn.attr(srcType));
+ customTn.remove();
+ return false;
+ }
+
+ if (video.type === 'youtube') {
+ path = "//img.youtube.com/vi/" + video.id + "/hqdefault.jpg";
+ create(path);
+ } else if (video.type === 'vimeo') {
+ $.ajax({
+ type: 'GET',
+ url: '//vimeo.com/api/v2/video/' + video.id + '.json',
+ jsonp: 'callback',
+ dataType: 'jsonp',
+ success: function(data) {
+ path = data[0].thumbnail_large;
+ create(path);
+ }
+ });
+ } else if (video.type === 'vzaar') {
+ $.ajax({
+ type: 'GET',
+ url: '//vzaar.com/api/videos/' + video.id + '.json',
+ jsonp: 'callback',
+ dataType: 'jsonp',
+ success: function(data) {
+ path = data.framegrab_url;
+ create(path);
+ }
+ });
+ }
+ };
+
+ /**
+ * Stops the current video.
+ * @public
+ */
+ Video.prototype.stop = function() {
+ this._core.trigger('stop', null, 'video');
+ this._playing.find('.owl-video-frame').remove();
+ this._playing.removeClass('owl-video-playing');
+ this._playing = null;
+ this._core.leave('playing');
+ this._core.trigger('stopped', null, 'video');
+ };
+
+ /**
+ * Starts the current video.
+ * @public
+ * @param {Event} event - The event arguments.
+ */
+ Video.prototype.play = function(event) {
+ var target = $(event.target),
+ item = target.closest('.' + this._core.settings.itemClass),
+ video = this._videos[item.attr('data-video')],
+ width = video.width || '100%',
+ height = video.height || this._core.$stage.height(),
+ html;
+
+ if (this._playing) {
+ return;
+ }
+
+ this._core.enter('playing');
+ this._core.trigger('play', null, 'video');
+
+ item = this._core.items(this._core.relative(item.index()));
+
+ this._core.reset(item.index());
+
+ if (video.type === 'youtube') {
+ html = '';
+ } else if (video.type === 'vimeo') {
+ html = '';
+ } else if (video.type === 'vzaar') {
+ html = '';
+ }
+
+ $('' + html + '
').insertAfter(item.find('.owl-video'));
+
+ this._playing = item.addClass('owl-video-playing');
+ };
+
+ /**
+ * Checks whether an video is currently in full screen mode or not.
+ * @todo Bad style because looks like a readonly method but changes members.
+ * @protected
+ * @returns {Boolean}
+ */
+ Video.prototype.isInFullScreen = function() {
+ var element = document.fullscreenElement || document.mozFullScreenElement ||
+ document.webkitFullscreenElement;
+
+ return element && $(element).parent().hasClass('owl-video-frame');
+ };
+
+ /**
+ * Destroys the plugin.
+ */
+ Video.prototype.destroy = function() {
+ var handler, property;
+
+ this._core.$element.off('click.owl.video');
+
+ for (handler in this._handlers) {
+ this._core.$element.off(handler, this._handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.Video = Video;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * Animate Plugin
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the animate plugin.
+ * @class The Navigation Plugin
+ * @param {Owl} scope - The Owl Carousel
+ */
+ var Animate = function(scope) {
+ this.core = scope;
+ this.core.options = $.extend({}, Animate.Defaults, this.core.options);
+ this.swapping = true;
+ this.previous = undefined;
+ this.next = undefined;
+
+ this.handlers = {
+ 'change.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && e.property.name == 'position') {
+ this.previous = this.core.current();
+ this.next = e.property.value;
+ }
+ }, this),
+ 'drag.owl.carousel dragged.owl.carousel translated.owl.carousel': $.proxy(function(e) {
+ if (e.namespace) {
+ this.swapping = e.type == 'translated';
+ }
+ }, this),
+ 'translate.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this.swapping && (this.core.options.animateOut || this.core.options.animateIn)) {
+ this.swap();
+ }
+ }, this)
+ };
+
+ this.core.$element.on(this.handlers);
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ Animate.Defaults = {
+ animateOut: false,
+ animateIn: false
+ };
+
+ /**
+ * Toggles the animation classes whenever an translations starts.
+ * @protected
+ * @returns {Boolean|undefined}
+ */
+ Animate.prototype.swap = function() {
+
+ if (this.core.settings.items !== 1) {
+ return;
+ }
+
+ if (!$.support.animation || !$.support.transition) {
+ return;
+ }
+
+ this.core.speed(0);
+
+ var left,
+ clear = $.proxy(this.clear, this),
+ previous = this.core.$stage.children().eq(this.previous),
+ next = this.core.$stage.children().eq(this.next),
+ incoming = this.core.settings.animateIn,
+ outgoing = this.core.settings.animateOut;
+
+ if (this.core.current() === this.previous) {
+ return;
+ }
+
+ if (outgoing) {
+ left = this.core.coordinates(this.previous) - this.core.coordinates(this.next);
+ previous.one($.support.animation.end, clear)
+ .css( { 'left': left + 'px' } )
+ .addClass('animated owl-animated-out')
+ .addClass(outgoing);
+ }
+
+ if (incoming) {
+ next.one($.support.animation.end, clear)
+ .addClass('animated owl-animated-in')
+ .addClass(incoming);
+ }
+ };
+
+ Animate.prototype.clear = function(e) {
+ $(e.target).css( { 'left': '' } )
+ .removeClass('animated owl-animated-out owl-animated-in')
+ .removeClass(this.core.settings.animateIn)
+ .removeClass(this.core.settings.animateOut);
+ this.core.onTransitionEnd();
+ };
+
+ /**
+ * Destroys the plugin.
+ * @public
+ */
+ Animate.prototype.destroy = function() {
+ var handler, property;
+
+ for (handler in this.handlers) {
+ this.core.$element.off(handler, this.handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.Animate = Animate;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * Autoplay Plugin
+ * @version 2.3.1
+ * @author Bartosz Wojciechowski
+ * @author Artus Kolanowski
+ * @author David Deutsch
+ * @author Tom De Caluwé
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+
+ /**
+ * Creates the autoplay plugin.
+ * @class The Autoplay Plugin
+ * @param {Owl} scope - The Owl Carousel
+ */
+ var Autoplay = function(carousel) {
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * The autoplay timeout id.
+ * @type {Number}
+ */
+ this._call = null;
+
+ /**
+ * Depending on the state of the plugin, this variable contains either
+ * the start time of the timer or the current timer value if it's
+ * paused. Since we start in a paused state we initialize the timer
+ * value.
+ * @type {Number}
+ */
+ this._time = 0;
+
+ /**
+ * Stores the timeout currently used.
+ * @type {Number}
+ */
+ this._timeout = 0;
+
+ /**
+ * Indicates whenever the autoplay is paused.
+ * @type {Boolean}
+ */
+ this._paused = true;
+
+ /**
+ * All event handlers.
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'changed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && e.property.name === 'settings') {
+ if (this._core.settings.autoplay) {
+ this.play();
+ } else {
+ this.stop();
+ }
+ } else if (e.namespace && e.property.name === 'position' && this._paused) {
+ // Reset the timer. This code is triggered when the position
+ // of the carousel was changed through user interaction.
+ this._time = 0;
+ }
+ }, this),
+ 'initialized.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.autoplay) {
+ this.play();
+ }
+ }, this),
+ 'play.owl.autoplay': $.proxy(function(e, t, s) {
+ if (e.namespace) {
+ this.play(t, s);
+ }
+ }, this),
+ 'stop.owl.autoplay': $.proxy(function(e) {
+ if (e.namespace) {
+ this.stop();
+ }
+ }, this),
+ 'mouseover.owl.autoplay': $.proxy(function() {
+ if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
+ this.pause();
+ }
+ }, this),
+ 'mouseleave.owl.autoplay': $.proxy(function() {
+ if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
+ this.play();
+ }
+ }, this),
+ 'touchstart.owl.core': $.proxy(function() {
+ if (this._core.settings.autoplayHoverPause && this._core.is('rotating')) {
+ this.pause();
+ }
+ }, this),
+ 'touchend.owl.core': $.proxy(function() {
+ if (this._core.settings.autoplayHoverPause) {
+ this.play();
+ }
+ }, this)
+ };
+
+ // register event handlers
+ this._core.$element.on(this._handlers);
+
+ // set default options
+ this._core.options = $.extend({}, Autoplay.Defaults, this._core.options);
+ };
+
+ /**
+ * Default options.
+ * @public
+ */
+ Autoplay.Defaults = {
+ autoplay: false,
+ autoplayTimeout: 5000,
+ autoplayHoverPause: false,
+ autoplaySpeed: false
+ };
+
+ /**
+ * Transition to the next slide and set a timeout for the next transition.
+ * @private
+ * @param {Number} [speed] - The animation speed for the animations.
+ */
+ Autoplay.prototype._next = function(speed) {
+ this._call = window.setTimeout(
+ $.proxy(this._next, this, speed),
+ this._timeout * (Math.round(this.read() / this._timeout) + 1) - this.read()
+ );
+
+ if (this._core.is('busy') || this._core.is('interacting') || document.hidden) {
+ return;
+ }
+ this._core.next(speed || this._core.settings.autoplaySpeed);
+ }
+
+ /**
+ * Reads the current timer value when the timer is playing.
+ * @public
+ */
+ Autoplay.prototype.read = function() {
+ return new Date().getTime() - this._time;
+ };
+
+ /**
+ * Starts the autoplay.
+ * @public
+ * @param {Number} [timeout] - The interval before the next animation starts.
+ * @param {Number} [speed] - The animation speed for the animations.
+ */
+ Autoplay.prototype.play = function(timeout, speed) {
+ var elapsed;
+
+ if (!this._core.is('rotating')) {
+ this._core.enter('rotating');
+ }
+
+ timeout = timeout || this._core.settings.autoplayTimeout;
+
+ // Calculate the elapsed time since the last transition. If the carousel
+ // wasn't playing this calculation will yield zero.
+ elapsed = Math.min(this._time % (this._timeout || timeout), timeout);
+
+ if (this._paused) {
+ // Start the clock.
+ this._time = this.read();
+ this._paused = false;
+ } else {
+ // Clear the active timeout to allow replacement.
+ window.clearTimeout(this._call);
+ }
+
+ // Adjust the origin of the timer to match the new timeout value.
+ this._time += this.read() % timeout - elapsed;
+
+ this._timeout = timeout;
+ this._call = window.setTimeout($.proxy(this._next, this, speed), timeout - elapsed);
+ };
+
+ /**
+ * Stops the autoplay.
+ * @public
+ */
+ Autoplay.prototype.stop = function() {
+ if (this._core.is('rotating')) {
+ // Reset the clock.
+ this._time = 0;
+ this._paused = true;
+
+ window.clearTimeout(this._call);
+ this._core.leave('rotating');
+ }
+ };
+
+ /**
+ * Pauses the autoplay.
+ * @public
+ */
+ Autoplay.prototype.pause = function() {
+ if (this._core.is('rotating') && !this._paused) {
+ // Pause the clock.
+ this._time = this.read();
+ this._paused = true;
+
+ window.clearTimeout(this._call);
+ }
+ };
+
+ /**
+ * Destroys the plugin.
+ */
+ Autoplay.prototype.destroy = function() {
+ var handler, property;
+
+ this.stop();
+
+ for (handler in this._handlers) {
+ this._core.$element.off(handler, this._handlers[handler]);
+ }
+ for (property in Object.getOwnPropertyNames(this)) {
+ typeof this[property] != 'function' && (this[property] = null);
+ }
+ };
+
+ $.fn.owlCarousel.Constructor.Plugins.autoplay = Autoplay;
+
+})(window.Zepto || window.jQuery, window, document);
+
+/**
+ * Navigation Plugin
+ * @version 2.3.1
+ * @author Artus Kolanowski
+ * @author David Deutsch
+ * @license The MIT License (MIT)
+ */
+;(function($, window, document, undefined) {
+ 'use strict';
+
+ /**
+ * Creates the navigation plugin.
+ * @class The Navigation Plugin
+ * @param {Owl} carousel - The Owl Carousel.
+ */
+ var Navigation = function(carousel) {
+ /**
+ * Reference to the core.
+ * @protected
+ * @type {Owl}
+ */
+ this._core = carousel;
+
+ /**
+ * Indicates whether the plugin is initialized or not.
+ * @protected
+ * @type {Boolean}
+ */
+ this._initialized = false;
+
+ /**
+ * The current paging indexes.
+ * @protected
+ * @type {Array}
+ */
+ this._pages = [];
+
+ /**
+ * All DOM elements of the user interface.
+ * @protected
+ * @type {Object}
+ */
+ this._controls = {};
+
+ /**
+ * Markup for an indicator.
+ * @protected
+ * @type {Array.}
+ */
+ this._templates = [];
+
+ /**
+ * The carousel element.
+ * @type {jQuery}
+ */
+ this.$element = this._core.$element;
+
+ /**
+ * Overridden methods of the carousel.
+ * @protected
+ * @type {Object}
+ */
+ this._overrides = {
+ next: this._core.next,
+ prev: this._core.prev,
+ to: this._core.to
+ };
+
+ /**
+ * All event handlers.
+ * @protected
+ * @type {Object}
+ */
+ this._handlers = {
+ 'prepared.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.dotsData) {
+ this._templates.push('' +
+ $(e.content).find('[data-dot]').addBack('[data-dot]').attr('data-dot') + '
');
+ }
+ }, this),
+ 'added.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.dotsData) {
+ this._templates.splice(e.position, 0, this._templates.pop());
+ }
+ }, this),
+ 'remove.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._core.settings.dotsData) {
+ this._templates.splice(e.position, 1);
+ }
+ }, this),
+ 'changed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && e.property.name == 'position') {
+ this.draw();
+ }
+ }, this),
+ 'initialized.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && !this._initialized) {
+ this._core.trigger('initialize', null, 'navigation');
+ this.initialize();
+ this.update();
+ this.draw();
+ this._initialized = true;
+ this._core.trigger('initialized', null, 'navigation');
+ }
+ }, this),
+ 'refreshed.owl.carousel': $.proxy(function(e) {
+ if (e.namespace && this._initialized) {
+ this._core.trigger('refresh', null, 'navigation');
+ this.update();
+ this.draw();
+ this._core.trigger('refreshed', null, 'navigation');
+ }
+ }, this)
+ };
+
+ // set default options
+ this._core.options = $.extend({}, Navigation.Defaults, this._core.options);
+
+ // register event handlers
+ this.$element.on(this._handlers);
+ };
+
+ /**
+ * Default options.
+ * @public
+ * @todo Rename `slideBy` to `navBy`
+ */
+ Navigation.Defaults = {
+ nav: false,
+ navText: [
+ '‹',
+ '›'
+ ],
+ navSpeed: false,
+ navElement: 'button role="presentation"',
+ navContainer: false,
+ navContainerClass: 'owl-nav',
+ navClass: [
+ 'owl-prev',
+ 'owl-next'
+ ],
+ slideBy: 1,
+ dotClass: 'owl-dot',
+ dotsClass: 'owl-dots',
+ dots: true,
+ dotsEach: false,
+ dotsData: false,
+ dotsSpeed: false,
+ dotsContainer: false
+ };
+
+ /**
+ * Initializes the layout of the plugin and extends the carousel.
+ * @protected
+ */
+ Navigation.prototype.initialize = function() {
+ var override,
+ settings = this._core.settings;
+
+ // create DOM structure for relative navigation
+ this._controls.$relative = (settings.navContainer ? $(settings.navContainer)
+ : $('').addClass(settings.navContainerClass).appendTo(this.$element)).addClass('disabled');
+
+ this._controls.$previous = $('<' + settings.navElement + '>')
+ .addClass(settings.navClass[0])
+ .html(settings.navText[0])
+ .prependTo(this._controls.$relative)
+ .on('click', $.proxy(function(e) {
+ this.prev(settings.navSpeed);
+ }, this));
+ this._controls.$next = $('<' + settings.navElement + '>')
+ .addClass(settings.navClass[1])
+ .html(settings.navText[1])
+ .appendTo(this._controls.$relative)
+ .on('click', $.proxy(function(e) {
+ this.next(settings.navSpeed);
+ }, this));
+
+ // create DOM structure for absolute navigation
+ if (!settings.dotsData) {
+ this._templates = [ $('