Compare commits

...

32 Commits

Author SHA1 Message Date
e36a2cbd77 Changed the ID of the input element 2023-06-25 15:22:22 -05:00
1392c62d31 Fixed bugs in PHP database code 2023-06-25 15:21:43 -05:00
e37bf086dd Added code to regex for password 2023-06-25 15:21:10 -05:00
67228048e1 Fixed JS errors with validation 2023-06-25 15:20:39 -05:00
de1a7f0687 Modified CSS for inputs 2023-06-25 15:20:08 -05:00
1c74b82f6e Removed database initialization code and instead used the function defined in db.inc.php 2023-06-25 14:09:30 -05:00
df131d2fb5 Added code to include Tailwind CSS file with this file 2023-06-25 14:08:56 -05:00
4d10b191c7 Created directory for fonts 2023-06-25 14:08:32 -05:00
071113592b Added Tailwind CSS file 2023-06-25 14:08:15 -05:00
b5283110d2 Created PHP file for database-related functions 2023-06-25 14:08:03 -05:00
3914190175 Created PHP file to sign up the user 2023-06-25 14:07:19 -05:00
0022e0d7c2 Created HTML file for sign up 2023-06-25 14:06:58 -05:00
0f8b0154f8 Added code to process the user's login information 2023-06-25 14:06:40 -05:00
e3e3b45c65 Added HTML and Javascript files for a login page 2023-06-25 14:06:26 -05:00
cd1261418a Added code to redirect the user if they are permitted to access the GLink, and show an error JS alert if they are not 2023-06-19 01:14:18 -05:00
96abdd9852 Added code to check if the user is within the radius for the GLink 2023-06-19 01:13:31 -05:00
22c85234da Sent the requested glink to reqloc.html as a GET variable, so that the Glink can be sent to the PHP file 2023-06-17 13:56:02 -05:00
4bba4f9410 NOT FINISHED: Created a file to process the user's location 2023-06-17 13:55:05 -05:00
d928ad2ce3 Created file to request the user's location to determine if they are allowed to acces the glink 2023-06-17 13:54:31 -05:00
63050a8065 Changed variable names to match HTML document 2023-06-17 13:54:09 -05:00
0b08c1ce9c Added code to hide radius drop-down menu if geo-restriction checkbox was not selected 2023-06-17 13:53:51 -05:00
b7a8602e34 Added code to wait for location to be retrieved before allowing user to submit, and hid the radius drop-down if geo-location wasn't checked 2023-06-15 23:00:21 -05:00
42eff5e0fa Added code to redirect the user to a different page if the GLink they requested is geo-restricted 2023-06-15 18:49:31 -05:00
3d36c2704a Added code to retrieve the user's location and store it in the database 2023-06-15 18:48:36 -05:00
ae036686b8 Added code to fetch the user's location, and send it as a GET/POST variable 2023-06-12 15:29:24 -05:00
70f91c7586 Fixed bug where I accessed the database without opening a session 2023-06-12 15:28:30 -05:00
913d53b757 Added form field to allow user to georestrict the link 2023-06-12 15:28:02 -05:00
8b68547644 Added code to generate a random GLink if the user doesn't submit one 2023-06-09 20:03:30 -05:00
0f85fcf021 Made the Glink field optional 2023-06-09 20:03:01 -05:00
1d4606db27 Added code to redirect the user if the database query returns a URL 2023-06-08 21:36:33 -05:00
116bbe5218 Started working on redirect when user enters a GLink 2023-06-08 10:46:59 -05:00
1b52864952 Added server-side checks to input 2023-06-08 10:46:41 -05:00
15 changed files with 2598 additions and 122 deletions

75
checkloc.php Normal file
View File

@@ -0,0 +1,75 @@
<?php
session_start();
require_once 'db.inc.php';
if (isset($_SESSION['glink']) && !empty($_SESSION['glink'])) {
session_unset();
session_destroy();
} else {
http_response_code(403);
die('Forbidden.');
}
// FUNCTION TO CALCULATE HAVERSINE DISTANCE GIVEN COORDINATES OF
// TWO POINTS, AND RADIUS (IN KM)
function haversine_distance($lat1, $long1, $lat2, $long2, $radius) {
$term_1 = $lat2 - $lat1;
$term_1 = $term_1 / 2;
$term_1 = sin($term_1);
$term_1 = pow($term_1, 2);
$term_2 = $long2 - $long1;
$term_2 = $term_2 / 2;
$term_2 = sin($term_2);
$term_2 = pow($term_2, 2);
$term_2 = $term_2 * cos($lat1);
$term_2 = $term_2 * cos($lat2);
$distance = $term_1 + $term_2;
$distance = sqrt($distance);
$distance = asin($distance);
$distance = $distance * 2;
$distance = $distance * $radius;
return $distance;
}
function km_to_miles($distance) {
return $distance * 0.62137119;
}
$user_lat = $_GET["latitude"];
$user_lat = $user_lat * (M_PI / 180);
$user_long = $_GET["longitude"];
$user_long = $user_long * (M_PI / 180);
$glink = $_GET["glink"];
$session = init_cass_db();
$statement = $session->prepare('SELECT latitude,longitude,radius,url FROM data WHERE shortlink=? ALLOW FILTERING;');
$result = $session->execute($statement,array('arguments' => array($glink)));
$link_lat = floatval($result[0]['latitude']);
$link_lat = $link_lat * (M_PI / 180);
$link_long = floatval($result[0]['longitude']);
$link_long = $link_long * (M_PI / 180);
$target_radius = intval($result[0]['radius']);
$url = $result[0]['url'];
$distance = haversine_distance($link_lat, $link_long, $user_lat, $user_long, 6371.009);
$distance = km_to_miles($distance);
if ($distance <= $target_radius) {
printf("%s",$url);
} else {
printf("B");
}
// Check the database to see if user is allowed to access the URL. If they are, respond 'Yes' (for the time being), if they are not, respond 'No' (for the time being).
// To check if the user is allowed to access the URL, check if the distance between their location and the location in the database is less than the radius. To compute the
// distance, use something like Haversine Forumla.
?>

9
db.inc.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
function init_cass_db() {
$cluster = Cassandra::cluster()->withPersistentSessions(true)->build();
$keyspace = 'glink';
$session = $cluster->connect($keyspace);
return $session;
}
?>

Binary file not shown.

View File

@@ -1,31 +1,66 @@
<html> <html>
<head> <head>
<title>GLink</title> <title>GLink</title>
<link rel="stylesheet" href="index.css"> <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="output.css">
</head> </head>
<body> <body class="bg-gray-50">
<h1 class="ml-4 text-5xl font-narrow">Link Shortener</h1>
<p class="ml-4 font-fingerpaint">Hello There!</p>
<div id="root"> <div id="root">
<h1>Link Shortener</h1>
<form id="form" method="GET" action="result.php" onsubmit="return validate()"> <form id="form" method="GET" action="result.php" onsubmit="return validate()">
<!-- <form id="form"> --> <div class="flex flex-wrap">
<label for="url">URL:</label><span class="mandatory">*</span> <label for="URL" class="text-2xl ml-4 font-rubik self-center">URL</label>
<input type="text" name="url" id="URL" value="https://example.com" required><br><br> <span class="mandatory font-rubik self-center text-2xl">*</span>
<span class="font-rubik self-center m-1 text-2xl">:</span>
<div class="p-0.5 m-4 rounded-lg max-w-sm bg-gradient-to-r from-cyan-500 to-cyan-500 focus-within:from-rose-400 focus-within:via-fuchsia-500 focus-within:to-indigo-500 focus-within:caret-gray-600 focus-within:p-[3.2px]">
<input type="text" name="url" id="URL" placeholder="https://example.com" required class="p-2 w-full rounded-lg focus:outline-none focus:shadow-lg focus:focus:shadow-black/50 text-center text-lg text-black font-bold">
</div>
</div>
<label for="labels">GLink:</label><span class="mandatory">*</span> <div class="flex flex-wrap">
<label for="GLink" id="labels" class="glink">glink.zip/</label><input type="text" name="glink" id="GLink" class="glink" value="exampleWebsite" required> <label for="labels" class="text-2xl ml-4 font-rubik self-center">GLink</label>
<span class="mandatory font-rubik text-2xl self-center">*</span>
<span class="font-rubik self-center m-1 text-2xl">:</span>
<label for="GLink" id="labels" class=" ml-2 glink text-center text-xl self-center">glink.zip/</label>
<div class="p-0.5 ml-2 mr-4 my-4 rounded-lg max-w-sm bg-gradient-to-r from-cyan-500 to-cyan-500 focus-within:from-rose-400 focus-within:via-fuchsia-500 focus-within:to-indigo-500 focus-within:caret-gray-600 focus-within:p-[3.2px]">
<input type="text" name="glink" id="GLink" class="glink p-2 w-full rounded-lg focus:outline-none focus:shadow-lg focus:focus:shadow-black/50 text-center text-lg text-black font-bold" placeholder="exampleWebsite">
</div>
</div>
<span role="alert" id="error" aria-hidden="true">Invalid URL</span> <label for="restricted" class="ml-4 self-center text-2xl font-rubik lg:invisible">Geo-restricted? : </label><input type="checkbox" name="restricted" id="restricted" class="ml-2 mr-4 my-4 text-center font-rubik ease-soft rounded-1.4 w-6 h-6 cursor-pointer checked:accent-blue-700 shadow-lg shadow-black/50 peer"><span id="loadingText" class="font-rubik self-center text-center text-xl" style="position: relative; left: 20px;"></span>
<span class="flex flex-wrap invisible peer-checked:visible" id="js-enabled">
<label for="radiusSelect" id="radius_label" class="ml-4 font-rubik text-2xl self-center">Radius</label><span id="mandatory-radius" class="mandatory font-rubik text-2xl self-center">*</span><span class="font-rubik self-center m-1 text-2xl">:</span>
<div class="p-0.5 ml-2 mr-4 my-4 rounded-lg max-w-sm bg-gradient-to-r from-cyan-500 to-cyan-500 focus-within:from-rose-400 focus-within:via-fuchsia-500 focus-within:to-indigo-500 focus-within:p-[3.2px]">
<select name="radius" id="radius" class="cursor-pointer text-lg p-2 w-full rounded-lg focus:outline-none invalid:text-gray-400 font-bold">
<option value="" selected disabled hidden>Choose a radius for your geo link</option>
<option value="5">5 mi</option>
<option value="10">10 mi</option>
<option value="15">15 mi</option>
<option value="20">20 mi</option>
</select>
</div>
</span>
<noscript>
<style>
#js-enabled {display: none;}
</style>
</noscript>
<span role="alert" class="m-4 font-rubik" id="error" aria-hidden="true">Invalid entry</span>
<input type="submit" id="button" value="Zip It!" class="scale-125 brightness-125 ml-20 font-rubik bg-gradient-to-r from-cyan-500 to-blue-500 hover:from-cyan-400 hover:to-blue-400 hover:shadow-lg hover:shadow-black/50 transition hover:-translate-y-1 hover:scale-150 duration-600 ease-in-out rounded-full cursor-pointer">
<input type="hidden" name="latitude" id="latitude">
<input type="hidden" name="longitude" id="longitude">
<br><br>
<input type="submit" id="button" value="Zip It!">
</form> </form>
<hr> <hr>
<div> <img src="./cat.gif">
<img src="cat.gif"> <p id="footer" class="object-none object-bottom">Insert Footer Here</p>
</div> <script src="./index.js"></script>
<script src="index.js"></script>
</div> </div>
</body> </body>
</html> </html>

141
index.js
View File

@@ -1,21 +1,101 @@
//const submit = document.getElementById("button"); // const submit = document.getElementById("button");
//submit.addEventListener('click', validate); mycheckbox = document.getElementById("restricted");
function validate() { mycheckbox.addEventListener('change',checkboxCallback);
// e.preventDefault(); window.onload = function() {
if (mycheckbox.checked) {
document.getElementById("radius_label").hidden = false;
document.getElementById("mandatory-radius").hidden = false;
var radiusSelect = document.getElementById("radius");
radiusSelect.hidden = false;
radiusSelect.required = true;
}
}
var lat = document.getElementById("latitude");
lat.setValue = function(newValue) {
this.value = newValue;
valueReceived();
}
function valueReceived() {
let load = document.getElementById("loadingText");
load.innerHTML = "Location retrieved";
load.style.color = "green";
}
function valueRequested() {
let load = document.getElementById("loadingText");
load.innerHTML = "Location requested. Please wait...";
load.style.color = "red";
}
function checkboxCallback(event) {
const radiusLabel = document.getElementById("radius_label");
const radiusSelect = document.getElementById("radius");
const mandatoryRadius = document.getElementById("mandatory-radius");
if (event.currentTarget.checked) {
radiusLabel.hidden = false;
mandatoryRadius.hidden = false;
radiusSelect.hidden = false;
radiusSelect.required = true;
valueRequested();
getLocation();
} else {
radiusLabel.hidden = true;
mandatoryRadius.hidden = true;
radiusSelect.hidden = true;
radiusSelect.required = false;
}
}
function getLocation() {
console.log("GeoLocation");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
} else {
console.log("Your browser does not support geolocation.");
}
}
function showPosition(position) {
console.log("Gotten positions");
console.log(position.coords.latitude);
console.log(position.coords.longitude);
document.getElementById("latitude").setValue(position.coords.latitude);
document.getElementById("longitude").value = position.coords.longitude;
console.log("done");
}
// submit.addEventListener('click', validate);
function validate() {
//e.preventDefault();
const checked = document.getElementById("restricted");
if (checked.checked) {
const lat = document.getElementById("latitude");
const long = document.getElementById("longitude");
if (lat.value === "" || long.value === "") {
/* wait */
return false
}
}
const url = document.getElementById("URL"); const url = document.getElementById("URL");
const glink = document.getElementById("GLink"); let glink = document.getElementById("GLink");
const error = document.getElementById("error");
// if (!url) { // if (!url) {
// /* Flag */ // /* Flag */
// } // }
let valid = true; let valid = true;
const domainExp = new RegExp("http(s)*:\\/\\/[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)+"); const domainExp = new RegExp("^http(s)*:\\/\\/[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)+$");
const filepathExp = new RegExp("[a-zA-Z]+"); const filepathExp = new RegExp("^[a-zA-Z]+$");
const glinkExp = new RegExp("^[a-zA-Z]*$");
let glinkStr = glink.value;
let count = 0; let count = 0;
let index = -1; let index = -1;
let domain = ""; let domain = "";
let filepath = ""; let filepath = "";
for (let i=0; i < url.value.length; i++) { for (let i = 0; i < url.value.length; i++) {
if (url.value.charAt(i) == '/') { if (url.value.charAt(i) == '/') {
count++; count++;
} }
@@ -36,8 +116,16 @@ function validate() {
domain = url.value; domain = url.value;
} }
console.log(domain); console.log(domain);
if (domain.match(domainExp)) /** and is available? */{
const error = document.getElementById("error"); if (glinkStr === "") {
var result = window.confirm("You have left the glink field blank. A random one will be generated for you.");
if (result === false) {
return false;
}
}
if (domain.match(domainExp) && glinkStr.match(glinkExp))/** and is available? */{
if (error.classList.contains("visible")) { if (error.classList.contains("visible")) {
error.classList.remove("visible"); error.classList.remove("visible");
} }
@@ -45,30 +133,43 @@ function validate() {
url.classList.remove("invalid"); url.classList.remove("invalid");
} }
url.classList.add("valid"); url.classList.add("valid");
if (glink.classList.contains("invalid")) {
glink.classList.remove("invalid");
}
glink.classList.add("valid");
error.setAttribute('aria-hidden', true); error.setAttribute('aria-hidden', true);
error.setAttribute('aria-invalid', false); error.setAttribute('aria-invalid', false);
console.log("Valid"); console.log("Valid with url= " +url.value+ " glink=" +glink);
return valid; return valid;
/* var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET','result.php',true);
xmlhttp.send();
console.log(xmlhttp.responseText);*/
} else { } else {
/*flag*/ /*flag*/
const error = document.getElementById("error");
error.classList.add("visible"); error.classList.add("visible");
//error.classList.add("hidden"); //error.classList.add("hidden");
if (!domain.match(domainExp)) {
if (url.classList.contains("valid")) { if (url.classList.contains("valid")) {
url.classList.remove("valid"); url.classList.remove("valid");
} }
url.classList.add("invalid"); url.classList.add("invalid");
} else {
if (url.classList.contains("invalid")) {
url.classList.remove("invalid");
}
url.classList.add("valid");
}
if (!glinkStr.match(glinkExp)) {
if (glink.classList.contains("valid")) {
glink.classList.remove("valid");
}
glink.classList.add("invalid");
} else {
if (glink.classList.contains("invalid")) {
glink.classList.remove("invalid");
}
glink.classList.add("valid");
}
error.setAttribute('aria-hidden', false); error.setAttribute('aria-hidden', false);
error.setAttribute('aria-invalid', true); error.setAttribute('aria-invalid', true);
return false; return false;
} }
} }

84
login.html Normal file
View File

@@ -0,0 +1,84 @@
<!DOCTYPE html>
<html lang="en" class="h-full bg-white">
<head>
<link rel="stylesheet" href="output.css">
<title>Title</title>
</head>
<body class="h-full">
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<img class="mx-auto h-10 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600" alt="Your Company">
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">Log in to your account</h2>
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form class="space-y-6" action="login.php" method="GET"> <!--Change to php-->
<div>
<label for="email" class="block text-sm font-medium leading-6 text-gray-900">Email address</label>
<div class="mt-2">
<input id="email" name="email" type="email" autocomplete="email" required class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
<div id="email-error" class="hidden mt-2 text-red-800 text-xs">
invalid Email
</div>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<label for="password" class="block text-sm font-medium leading-6 text-gray-900">Password</label>
<div class="text-sm">
<a href="#" class="font-semibold text-indigo-600 hover:text-indigo-500">Forgot password?</a>
</div>
</div>
<div class="mt-2 relative block">
<input id="password" name="password" type="password" autocomplete="off" required class="block w-11/12 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
<span id="pswd-invisible" class="absolute inset-y-0 right-0 flex items-center px-1 rounded-r-md">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" color="black"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z">
</path>
</svg>
</span>
<span id="pswd-visible" class="absolute inset-y-0 right-0 flex items-center px-1 hidden">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21">
</path>
</svg>
</span>
</div>
<p id="domain" class="hidden text-red-800 text-xs">
<b>Invalid characters entered</b>
</p>
<p id="letter" class="hidden text-red-800 text-xs">
A <b>lowercase</b> letter
</p>
<p id="capital" class="hidden text-red-800 text-xs">
A <b>capital (uppercase)</b> letter
</p>
<p id="number" class="hidden text-red-800 text-xs">
A <b>number</b>
</p>
<p id="symbol" class="hidden text-red-800 text-xs">
A <b>symbol</b>
</p>
<p id="length" class="hidden text-red-800 text-xs">
Minimum <b>10 characters</b>
</p>
<p id="auth" class="hidden text-red-800 text-xs">
Incorrect Email or password
</p>
</div>
<div>
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Log in</button>
</div>
</form>
</div>
</div>
<script src="login.js"></script>
</body>
</html>

168
login.js Normal file
View File

@@ -0,0 +1,168 @@
let email = document.getElementById("email");
let password = document.getElementById("password");
let pswd_visible = document.getElementById("pswd-visible");
let pswd_invisible = document.getElementById("pswd-invisible");
console.log(window.location.pathname);
pswd_visible.addEventListener('click', () => {
pswd_visible.classList.add("hidden");
pswd_invisible.classList.remove("hidden");
password.type = "password";
});
pswd_invisible.addEventListener('click', () => {
pswd_invisible.classList.add("hidden");
pswd_visible.classList.remove("hidden");
password.type = "text";
});
if (window.location.pathname === '/signup.html') {
let check_pswd_visible = document.getElementById("check-pswd-visible");
let check_pswd_invisible = document.getElementById("check-pswd-invisible");
let check_password = document.getElementById("verify");
check_pswd_visible.addEventListener('click', () => {
check_pswd_visible.classList.add("hidden");
check_pswd_invisible.classList.remove("hidden");
check_password.type = "password";
});
check_pswd_invisible.addEventListener('click', () => {
check_pswd_invisible.classList.add("hidden");
check_pswd_visible.classList.remove("hidden");
check_password.type = "text";
});
}
let emailRX = new RegExp("^[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z]+)+$");
let domainError = document.getElementById("domain");
let domainRX = new RegExp("^[a-zA-Z0-9!@#$%^&*]*$");
let emailError = document.getElementById("email-error");
let capsRX = new RegExp(".*[A-Z]+");
let capsError = document.getElementById("capital");
let lowRX = new RegExp(".*[a-z]+");
let lowError = document.getElementById("letter");
let numRX = new RegExp(".*[0-9]+");
let numError = document.getElementById("number");
let symbolRX = new RegExp(".*[!@#$%^&*]+");
let symbolError = document.getElementById("symbol");
let MIN_LENGTH = 10;
let lenError = document.getElementById("length");
if (window.location.pathname === '/login.html') {
let auth_error = document.getElementById("auth");
let query = window.location.search;
const urlParams = new URLSearchParams(query);
const errorType = urlParams.get('error');
console.log(window.location.pathname);
if (errorType === 'auth') {
auth_error.classList.add('block');
auth_error.classList.remove('hidden');
} else {
auth_error.classList.remove('block');
auth_error.classList.add('hidden');
}
}
email.addEventListener('keyup', function(event) {
if (emailRX.test(email.value)) {
console.log("email valid");
email.classList.add("ring-green-400");
email.classList.add("focus:ring-green-400");
email.classList.remove("ring-red-400");
email.classList.remove("focus:ring-red-400");
emailError.classList.add("hidden");
emailError.classList.remove("block");
return true;
} else {
console.log("email invalid");
email.classList.add("ring-red-400");
email.classList.add("focus:ring-red-400");
email.classList.remove("ring-green-400");
email.classList.remove("focus:ring-green-400");
emailError.classList.remove("hidden");
emailError.classList.add("block");
return false;
}
});
password.addEventListener('keyup', () => {
if (document.location.pathname === '/login.html') {
if (document.getElementById('auth').classList.contains('block')) {
document.getElementById('auth').classList.remove('block');
document.getElementById('auth').classList.add('hidden');
}
} else {
let pswd = password.value;
if (!capsRX.test(pswd)) {
capsError.classList.remove("hidden");
capsError.classList.add("block");
} else {
capsError.classList.add("hidden");
capsError.classList.remove("block");
}
if (!lowRX.test(pswd)) {
lowError.classList.remove("hidden");
lowError.classList.add("block");
} else {
lowError.classList.add("hidden");
lowError.classList.remove("block");
}
if (!numRX.test(pswd)) {
numError.classList.remove("hidden");
numError.classList.add("block");
} else {
numError.classList.add("hidden");
numError.classList.remove("block");
}
if (!symbolRX.test(pswd)) {
symbolError.classList.remove("hidden");
symbolError.classList.add("block");
} else {
symbolError.classList.add("hidden");
symbolError.classList.remove("block");
}
if (!domainRX.test(pswd)) {
domainError.classList.remove("hidden");
domainError.classList.add("block");
} else {
domainError.classList.add("hidden");
domainError.classList.remove("block");
}
if (pswd.length < MIN_LENGTH) {
lenError.classList.remove("hidden");
lenError.classList.add("block");
} else {
lenError.classList.add("hidden");
lenError.classList.remove("block");
}
if (capsError.classList.contains("block") || lowError.classList.contains("block") || numError.classList.contains("block") || symbolError.classList.contains("block") || lenError.classList.contains("block")) {
password.classList.remove("ring-green-400");
password.classList.remove("focus:ring-green-400");
password.classList.add("ring-red-400");
password.classList.add("focus:ring-red-400");
} else {
password.classList.add("ring-green-400");
password.classList.add("focus:ring-green-400");
password.classList.remove("ring-red-400");
password.classList.remove("focus:ring-red-400");
}
}
});
if (window.location.pathname === '/signup.html') {
let check_password = document.getElementById("verify");
let check_password_error = document.getElementById("check-password-error");
check_password.addEventListener("keyup", () => {
let check = check_password.value;
if (check !== password.value) {
check_password_error.classList.remove("hidden");
check_password_error.classList.add("block");
} else {
check_password_error.classList.add("hidden");
check_password_error.classList.remove("block")
}
if (check_password_error.classList.contains("block")) {
check_password.classList.remove("ring-green-400");
check_password.classList.remove("focus:ring-green-400");
check_password.classList.add("ring-red-400");
check_password.classList.add("focus:ring-red-400");
} else {
check_password.classList.add("ring-green-400");
check_password.classList.add("focus:ring-green-400");
check_password.classList.remove("ring-red-400");
check_password.classList.remove("focus:ring-red-400");
}
});
}

29
login.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
require_once 'db.inc.php';
$email = $_GET['email'];
$password = $_GET['password'];
$session = init_cass_db();
$statement = $session->prepare('SELECT password_hash FROM users WHERE email=? ALLOW FILTERING;');
$result = $session->execute($statement,array('arguments' => array($email)));
if ($result->count() <= 0) {
echo('Invalid email address or password.');
exit();
} else {
$hash = $result[0]['password_hash'];
if (password_verify($password,$hash) != true) {
echo('Invalid email address or password.');
exit();
} else {
session_start();
$_SESSION['user'] = $email;
header('Location: https://glink.zip?res=success');
}
}
?>

1672
output.css Normal file

File diff suppressed because it is too large Load Diff

44
redirect.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
require_once 'db.inc.php';
ini_set("session.cookie_secure",1);
session_start();
use Cassandra;
$uri = $_SERVER['REQUEST_URI'];
$uri = substr($uri,1);
$matches_uri = preg_match('/^[a-zA-Z]+$/',$uri);
if (($matches_uri == 0) || ($matches_uri == false)) {
header("Location: https://glink.zip/");
exit;
} else {
$session = init_cass_db();
$statement = $session->prepare('SELECT url,is_geo FROM data WHERE shortlink=? ALLOW FILTERING;');
$result = $session->execute($statement,array('arguments' => array($uri)));
if ($result->count() == 0) {
printf('The given GLink was invalid, and doesn\'t point to a specific web page.');
exit;
}
foreach($result as $row) {
if (is_null($row)) {
printf('The given GLink was invalid, and doesn\'t point to a specific web page.');
exit;
} else {
if ($row['is_geo'] == true) {
$_SESSION['glink'] = $uri;
header("Location: https://glink.zip/reqloc.html?glink=" . $uri);
exit;
} else {
header("Location: " . $row['url']);
exit;
}
}
}
}
?>

59
reqloc.html Normal file
View File

@@ -0,0 +1,59 @@
<html>
<head>
<title>Location needed</title>
</head>
<body onload="get_location()">
This link is geo-restricted. Your location is needed to verify that you are authorized to access this link.
<script>
var params = new URLSearchParams(window.location.search);
var glink = params.get("glink");
var lat;
var long;
var method = "GET";
var request;
function requestHandler() {
if (request.readyState === XMLHttpRequest.DONE) {
if (request.status === 200) {
if (request.responseText == "B") {
alert("You are not authorized to access this GLink, as you are outside the permitted radius. If you think this is an error, please try again on a mobile device.");
} else {
window.location.replace(request.responseText);
}
} else {
console.log("Error sending data to server.");
}
}
}
function storeLocation(position) {
lat = position.coords.latitude;
long = position.coords.longitude;
}
function callbackFunction(position) {
storeLocation(position);
request = new XMLHttpRequest();
request.onreadystatechange = requestHandler;
if (method == "GET") {
request.open("GET","/checkloc.php?latitude=" + encodeURIComponent(lat) + "&longitude=" + encodeURIComponent(long) + "&glink=" + encodeURIComponent(glink));
request.send();
} else if (method == "POST") {
request.open("POST","/checkloc.php");
request.send("latitude=" + encodeURIComponent(lat) + "&longitude=" + encodeURIComponent(long));
}
}
function get_location() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(callbackFunction);
} else {
alert('You cannot access this GLink as your browser does not support geolocation.');
}
}
</script>
</body>
</html>

View File

@@ -1,14 +0,0 @@
console.log('Beginning database execution');
const cassandra = require('cassandra-driver');
const client = new cassandra.Client({
contactPoints: ['127.0.0.1:9042'],
keyspace: 'glink',
});
const query = 'SELECT name FROM data WHERE id = ?';
console.log(query);
client.execute(query, [5]).then(result => console.log('User name is %s',result.rows[0].name));

View File

@@ -1,42 +1,119 @@
<?php <?php
ini_set('display_errors', 1); require_once 'db.inc.php';
use Casssandra;
$cluster = Cassandra::cluster()->build(); function gen_base62_rand_shortlink($len) {
$keyspace = 'glink'; $rand_bytes = random_bytes(intval(($len * 2) / 3));
$rand_string = base64_encode($rand_bytes);
$rand_string = str_replace("+","",$rand_string);
$rand_string = str_replace("/","",$rand_string);
$rand_string = str_replace("=","",$rand_string);
if (mb_strlen($rand_string) < $len) {
$curlen = mb_strlen($rand_string);
$rand_string = $rand_string . gen_rand_shortlink($len - $curlen);
}
return $rand_string;
}
function gen_rand_shortlink($len) {
$to_return = '';
$possible_chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
while (mb_strlen($to_return) < $len) {
$to_return = $to_return . $possible_chars[rand(0, mb_strlen($possible_chars)-1)];
}
return $to_return;
}
ini_set('display_errors', 1);
$session = init_cass_db();
$url = $_GET["url"]; $url = $_GET["url"];
if (isset($_GET["restricted"])) {
$is_geo = 1;
} else {
$is_geo = 0;
}
if ($is_geo == 1) {
$radius = $_GET["radius"];
$latitude = $_GET["latitude"];
$latitude = doubleval($latitude);
$longitude = $_GET["longitude"];
$longitude = doubleval($longitude);
}
$matches = preg_match('/^http(s)*:\\/\\/[a-zA-Z0-9\\-]+(\\.[a-zA-Z0-9\\-]+)+$/',$url);
if (($matches == 0) || ($matches == false)) {
printf("The URL entered was invalid. Please try again.");
return;
}
$shortlink = $_GET["glink"]; $shortlink = $_GET["glink"];
$session = $cluster->connect($keyspace); if ($shortlink != '') {
$matches_shortlink = preg_match('/^[a-zA-Z]+$/',$shortlink);
if (($matches_shortlink == 0) || ($matches_shortlink == false)) {
printf("The GLink entered was invalid. The GLink can only contain letters. Please try again.");
return;
}
} else {
/* generate a random shortlink */
gen_shortlink:
$rand_string = gen_rand_shortlink(6); /* the function is defined at the start of this file */
$shortlink = $rand_string;
/* Check if shortlink is already taken by querying the database */
$statement = $session->prepare('SELECT url FROM data WHERE shortlink=? ALLOW FILTERING');
$result = $session->execute($statement,array('arguments' => array($shortlink)));
if ($result->count() != 0) {
goto gen_shortlink;
}
}
//$statement = new Cassandra\SimpleStatement('SELECT name FROM data WHERE id=5'); //$statement = new Cassandra\SimpleStatement('SELECT name FROM data WHERE id=5');
$statement = $session->prepare('SELECT url FROM data WHERE shortlink=? ALLOW FILTERING');
$options = array('arguments' => array($shortlink));
$result = $session->execute($statement,$options);
if ($result->count() != 0) {
printf('That GLink is already taken. Please try another one.');
exit;
}
$rand_num = rand(0,99999999); $rand_num = rand(0,99999999);
$values = array( $statement = $session->prepare('INSERT INTO data (id, url, shortlink, is_geo, radius, latitude, longitude, when_created) VALUES (?,?,?,?,?,?,?,toTimestamp(now())) USING TTL 20');
'id' => $rand_num,
'url' => $url,
'shortlink' => $shortlink,
);
$statement = new Cassandra\SimpleStatement('INSERT INTO data (id, url, shortlink, when_created) VALUES (?,?,?,toTimestamp(now()))');
$options = array('arguments' => $values);
$result = $session->execute($statement,$options);
$statement = new Cassandra\SimpleStatement('SELECT url,shortlink FROM data WHERE id=?'); if ($is_geo == 1) {
$options = array('arguments' => array('id' => $rand_num)); $options = array($rand_num,$url,$shortlink,boolval($is_geo),intval($radius), $latitude, $longitude);
$result = $session->execute($statement,$options); } else {
$options = array($rand_num,$url,$shortlink,boolval($is_geo),null,null,null);
}
$result = $session->execute($statement,array('arguments' => $options));
//$stringRepresentation= json_encode($result[0]); //$stringRepresentation= json_encode($result[0]);
//printf("%s\n\n\n",$stringRepresentation); //printf("%s\n\n\n",$stringRepresentation);
foreach($result as $row) { //foreach($result as $row) {
if (is_null($row)) { // if (is_null($row)) {
printf('Unsuccessful'); // printf('Unsuccessful');
} else { // } else {
printf('Successful: The URL you entered was: %s and your GLink is: https://glink.zip/%s', $row['url'],$row['shortlink']); printf('Successful: The URL you entered was: %s and your GLink is: https://glink.zip/%s', $url,$shortlink);
} // }
} //}
//printf('Done'); //printf('Done');
?> ?>

109
signup.html Normal file
View File

@@ -0,0 +1,109 @@
<!DOCTYPE html>
<html lang="en" class="h-full bg-white">
<head>
<link rel="stylesheet" href="output.css">
<title>Title</title>
</head>
<body class="h-full">
<div class="flex min-h-full flex-col justify-center px-6 py-12 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-sm">
<img class="mx-auto h-10 w-auto" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=600" alt="Your Company">
<h2 class="mt-10 text-center text-2xl font-bold leading-9 tracking-tight text-gray-900">Sign up for an account</h2>
</div>
<div class="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
<form class="space-y-6" action="signup.php" method="GET"> <!--Change to php-->
<div>
<label for="email" class="block text-sm font-medium leading-6 text-gray-900">Email address</label>
<div class="mt-2">
<input id="email" name="email" type="email" autocomplete="email" required class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
<div id="email-error" class="hidden mt-2 text-red-800 text-xs">
invalid Email
</div>
</div>
</div>
<div>
<div class="flex items-center justify-between">
<label for="password" class="block text-sm font-medium leading-6 text-gray-900">Password</label>
</div>
<div class="mt-2 relative block">
<input id="password" name="password" type="password" autocomplete="off" required class="block w-11/12 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
<span id="pswd-invisible" class="absolute inset-y-0 right-0 flex items-center px-1 rounded-r-md">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" color="black"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z">
</path>
</svg>
</span>
<span id="pswd-visible" class="absolute inset-y-0 right-0 flex items-center px-1 hidden">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21">
</path>
</svg>
</span>
</div>
<p id="domain" class="hidden text-red-800 text-xs">
<b>Invalid characters entered</b>
</p>
<p id="letter" class="hidden text-red-800 text-xs">
A <b>lowercase</b> letter
</p>
<p id="capital" class="hidden text-red-800 text-xs">
A <b>capital (uppercase)</b> letter
</p>
<p id="number" class="hidden text-red-800 text-xs">
A <b>number</b>
</p>
<p id="symbol" class="hidden text-red-800 text-xs">
A <b>symbol</b>
</p>
<p id="length" class="hidden text-red-800 text-xs">
Minimum <b>10 characters</b>
</p>
</div>
<div>
<div class="flex items-center justify-between">
<label for="verify" class="block text-sm font-medium leading-6 text-gray-900">Retype Password</label>
</div>
<div class="mt-2 relative block">
<input id="verify" name="verify" type="password" autocomplete="off" required class="block w-11/12 rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6">
<span id="check-pswd-invisible" class="absolute inset-y-0 right-0 flex items-center px-1 rounded-r-md">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" color="black"
d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z">
</path>
</svg>
</span>
<span id="check-pswd-visible" class="absolute inset-y-0 right-0 flex items-center px-1 hidden">
<svg class="w-6 h-6 m-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M13.875 18.825A10.05 10.05 0 0112 19c-4.478 0-8.268-2.943-9.543-7a9.97 9.97 0 011.563-3.029m5.858.908a3 3 0 114.243 4.243M9.878 9.878l4.242 4.242M9.88 9.88l-3.29-3.29m7.532 7.532l3.29 3.29M3 3l3.59 3.59m0 0A9.953 9.953 0 0112 5c4.478 0 8.268 2.943 9.543 7a10.025 10.025 0 01-4.132 5.411m0 0L21 21">
</path>
</svg>
</span>
</div>
<p id="check-password-error" class="hidden text-red-800 text x-s">
Passwords <b>do not</b> match
</p>
</div>
<div>
<button type="submit" class="flex w-full justify-center rounded-md bg-indigo-600 px-3 py-1.5 text-sm font-semibold leading-6 text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Sign up</button>
</div>
</form>
</div>
</div>
<script src="login.js"></script>
</body>
</html>

28
signup.php Normal file
View File

@@ -0,0 +1,28 @@
<?php
require_once 'db.inc.php';
$email = $_GET['email'];
$email = strval($email);
$username = $_GET['username'];
$password = $_GET['password'];
$id = rand(0,99999999);
$hash = password_hash($password,PASSWORD_BCRYPT);
$session = init_cass_db();
$statement = $session->prepare("SELECT id FROM users WHERE email=? ALLOW FILTERING;");
$result = $session->execute($statement, array('arguments' => array($email)));
if ($result->count() != 0) {
echo('The username or email address already exists. Please try another email address.');
exit();
}
$statement = $session->prepare('INSERT INTO users (id,email,username,password_hash) VALUES (?,?,null,?);');
$result = $session->execute($statement, array('arguments' => array($id,$email,$hash)));
echo('Registration successful.');
?>