Redis-only version of lob.li - Almost complete.

This version removes all the mysql stuff and uses a redis db for everything.
This commit is contained in:
alopexc0de 2014-07-25 17:41:51 -04:00
parent e52c236e47
commit adfcc57e00
No known key found for this signature in database
GPG Key ID: 48E847F18074C953
3 changed files with 201 additions and 115 deletions

View File

@ -13,41 +13,56 @@
5 - Successful lob.li link resolve
6 - Successful lookup of non-lob.li link
7 - Unsuccessful lookup of non-lob.li link
8 - Lookup of link Stats (returns 8 $sep JSONarray)
*/
function shorten($sdb, $link, $seperator){
$sql = "SELECT * FROM `links` WHERE `link` = '$link' LIMIT 1;";
if($result = $sdb->query($sql)){
if($row = $result->fetch_assoc()){
$short = $row['shortlink'];
return "1$seperator$short";
}
}
if(checkRemoteFile($link) !== true) return "2$seperator$link";
$title = getRemoteTitle($link);
$short = substr(number_format(time() * mt_rand(),0,'',''),0,5);
$short = base_convert($short, 10, 36);
$dpass = substr(number_format(time() * mt_rand(),0,'',''),0,10);
$dpass = base_convert($short.$dpass, 10, 36);
function shorten($redis, $link, $linkage, $seperator){
$short = $redis->get("links:id:$link");
if($short){
$title = $redis->get("links:title:$link");
return "1$seperator$link$seperator$title";
}else{
do {
if(checkRemoteFile($link) !== true) return "2$seperator$link";
$title = getRemoteTitle($url);
$sql = "INSERT INTO `links` (link, shortlink, title, dpass, ddate) VALUES ('$link', '$short', '$title', '$dpass', NOW())";
$short = substr(number_format(time() * mt_rand(),0,'',''),0,5);
$short = base_convert($short, 10, 36);
if($result = $sdb->query($sql)): return "0$seperator$short$seperator$title";
else: return '3'.$seperator.$sdb->error;
endif;
if(!$redis->exists("links:id:$short")) {
break;
}
} while (1);
$xTime = 3136320000; // About 100 years, give or take
// Delete the links in 24 hours, 1 week, 1 month respectevly
if($linkage == '0') $xTime = 86400;
if($linkage == '1') $xTime = 604800;
if($linkage == '2') $xTime = 2628000;
$redis->setex("links:id:$short", $xTime, $link);
$redis->setex("links:title:$short", $xTime, $title);
$redis->setex("links:date:$short", $xTime, date("d/m/Y", strtotime($str)));
$redis->setex("tracking:clicks:$link", $xTime, 1);
return "0$seperator$short$seperator$title";
}
}
function stats($sdb, $seperator){
function stats($redis, $seperator){
$tracking = $redis->keys("tracking:clicks:*");
$tracking = rsort($tracking);
$tracking = array_slice($tracking, 0, 5, true);
return "8$seperator".json_encode($tracking);
}
function getRemoteTitle($url){
$url = parse_url($url);
$tags = get_meta_tags($url['scheme'].'://'.$url['host']);
$ret = sanitize($tags['description']);
return $ret;
if($tags = get_meta_tags($url['scheme'].'://'.$url['host'])){
$ret = $tags['description'];
return $ret;
}else{ return false; }
}
function checkRemoteFile($ip=null){
@ -77,10 +92,11 @@
return false;
}
function sanitize($input){
if ($input == null) die("4");
function sanitize($input, $seperator){
if ($input == null) die("4$seperator");
$output = strip_tags($input);
$output = stripslashes($output);
//filter_input(INPUT_GET, 'name', FILTER_SANITIZE_STRING)
$output = mysql_real_escape_string($output);
return $output;
}

View File

@ -1,6 +1,22 @@
<?php
session_start();
/*
Redis scheme:
links:
id:
link id - set to website
title:
link id - set to page description
date:
link id - set to today's date
tracking:
clicks:
link id - int, increments with each unique IP
ip:
link id - list holding all visiting IPs for that link
*/
// Generate a token on the fly. This should prevent POST spam attacks directly into process.php
$token = substr(number_format(time() * mt_rand(),0,'',''),0,10);
$token = base_convert($token, 10, 36);
@ -13,47 +29,31 @@
require('Include/PHP/db.php');
function followLink($shortdb, $redis, $link){
$link = $shortdb->real_escape_string(strtolower(stripslashes(strip_tags($link))));
$link = str_replace('/', '', $link);
$sql = "SELECT * FROM `tracking` WHERE `id` = '$link' LIMIT 1;"; // Testing to see if the link has been visited before
if($result = $shortdb->query($sql)){
if($row = $result->fetch_assoc()){
$sql = "UPDATE `tracking` SET `clicks` = `clicks` + 1 WHERE `id` = '$link'"; // Yes it has, increment clicks by 1
if($result = $shortdb->query($sql)){
if($result->num_rows == 0){
die ($shortdb->error);
}
}
}
}else{
$sql = "INSERT INTO `tracking` (id, clicks) VALUES ('$link', 1)"; // No it hasn't, add 1 click to the table
if($result = $shortdb->query($sql)){
if($result->num_rows == 0){
die ($shortdb->error);
function followLink($redis, $link){
if (isset($_SERVER["HTTP_CF_CONNECTING_IP"])) { // Get true IP of visiter if going through cloudflare
$_SERVER['REMOTE_ADDR'] = $_SERVER["HTTP_CF_CONNECTING_IP"];
}
$ipTrack = $redis->lRange("tracking:ip:$link", 0, -1);
if(!in_array($_SERVER['REMOTE_ADDR'], $ipTrack)){ // Check to see if visiter hit this link before (This would make it a lot easier to skew statistics if anyone would register multiples times)
$redis->rPush("tracking:ip:$link", $_SERVER['REMOTE_ADDR']);
// Tracking code
$tracking = $redis->get("tracking:clicks:$link");
$trTtl = $redis->ttl("links:id:$link");
if(!$tracking || $trTtl != -2){
$tracking = $redis->set("tracking:clicks:$link", 1);
}else{
if($trTtl == -2){ // The link has been deleted, no need to track it anymore
break;
}
$tracking = $redis->incr("tracking:clicks:$link");
}
}
// Try to find it in the redis db first, if not there, add it
$short = $redis->get($link);
if (!$short || $short == null) {
$sql = "SELECT * FROM `links` WHERE `shortlink` = '$link' LIMIT 1;";
if($result = $shortdb->query($sql)){
if($row = $result->fetch_assoc()){
$llink = $row['link'];
$redis->set($link, $llink);
echo $llink;
//header("location:$link");
exit(5); // Stop script execution to save on resources
}
}
}else{
$short = $redis->get("links:id:$link");
if($short){
echo $short;
exit(5);
}
@ -72,7 +72,7 @@
// This has been depreciated. Still here for backwards compatibility with existing links
if(!empty($_GET['l'])){
followLink($shortdb, $redis, $_GET['l']);
followLink($redis, $_GET['l']);
}
// New way to check for valid short links, two characters shorter than the if statement above
@ -83,7 +83,7 @@
if($key == "resolv"){ header("location:http://r.lob.li"); exit(12); }
if($key == "about"){ header("location:http://a.lob.li"); exit(13); }
followLink($shortdb, $redis, $key);
followLink($redis, $key);
}
?>
<!DOCTYPE html>
@ -124,10 +124,10 @@
<div class="input-group">
<span class="input-group-addon lexp">
<select name="linkage" id="linkage">
<option selected="selected">24hrs</option>
<option>1 Week</option>
<option>1 Month</option>
<option>Forever</option>
<option value="0" selected="selected">24hrs</option>
<option value="1">1 Week</option>
<option value="2">1 Month</option>
<option value="3">Forever</option>
</select>
</span>
<input type="text" class="form-control input-lg" id="link" name="link" placeholder="http://" required autofocus>
@ -172,10 +172,6 @@
$('#homelink').addClass('active');
});
$(function () {
$("[rel='tooltip']").tooltip();
});
function copyToClipboard(text){
window.prompt ("Copy to clipboard: Ctrl+C, Enter (when closed I will open your link in a new tab)", text);
}

View File

@ -18,6 +18,7 @@
5 - Successful lob.li link resolve
6 - Successful lookup of non-lob.li link
7 - Unsuccessful lookup of non-lob.li link
8 - Lookup of link Stats (returns 8 $sep JSONarray)
*/
$short = "";
@ -26,40 +27,6 @@
$title = "";
$messages = array(
"
<div class=\"alert alert-success\" id=\"success\">
Your link: <a href=\"http://lob.li/$short\" title=\"$title\" target=\"lobli.$short\">lob.li/$short</a>
<a href=\"#\" id=\"copylink\" title=\"Copy Link\" onclick=\"copyToClipboard('http://lob.li/$short');\">
<!--<a href=\"#\" id=\"newlink\" title=\"New Link\"> This would require changing how I generate links, and I don't feel like doing it right now - 6/22/12 1:21am EST
<span class=\"glyphicon glyphicon-refresh\" style=\"float:right;\"></span>
</a>-->
<span class=\"glyphicon glyphicon-link\" style=\"float:right;padding-right:1%;\"></span>
</a>
</div>
",
"
<div class=\"alert alert-warning\" id=\"warning\">
Existing link: <a href=\"http://lob.li/$short\" title=\"$title\" target=\"lobli.$short\">lob.li/$short</a>
<a href=\"#\" id=\"copylink\" title=\"Copy Link\" onclick=\"copyToClipboard('http://lob.li/$short');\">
<span class=\"glyphicon glyphicon-link\" style=\"float:right;padding-right:1%;\"></span>
</a>
</div>
",
"
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - Your link: <a href=\"$link\" target=\"$link\">$link</a> didn't resolve to a website. <br />Please check your link and try again.
</div>
",
"
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - Well this is embarrassing... This never happens, but I appear to have suffered a database error. <br />Here's what I know: $error
</div>
",
"
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - The sanitize function seems to have failed. This shouldn't happen, maybe <a href=\"mailto:c0de@unps.us\">c0de</a> forgot a semi-colon somewhere or something.
</div>
",
"
<div class=\"alert alert-success\" id=\"success\">
Your Resolved link: <a href=\"$link\" title=\"$title\">
@ -87,18 +54,125 @@
"
);
if(empty($_GET['token']) || $_GET['token'] != $_SESSION['token'] || empty($_POST[$catchid]) || $_POST[$catchid] != $catchVal){
die("<div id=\"danger\" class=\"alert alert-danger\">Oh Noes! Something happened and I can't continue.<br />Please try again by using the form located at <a href=\"http://lob.li\">lob.li</a>.</div>");
}
require('Include/PHP/functions.php');
if(!empty($_POST['link'])){
$short = sanitize($_POST['link']);
if(!isset($_GET['getstats'])){
$stats = stats($redis, $seperator);
$stats = explode($seperator, $stats);
if(!empty($_GET['type'])){
if($_GET['type'] == "htmltable"){
foreach($stats as $stat){ // There should only be 5, but the page doesn't limit how many
$id = explode(":", $stat);
$id = $id[2]; // Grab just the short link ID
$linkData = $redis->lRange("links:$id", 0, -1);
$link = $linkData[0];
$title = $linkData[1];
$date = $linkData[2];
$trackClicks = $redis->get("tracking:clicks:$id");
echo "
<tr class=\"success\">
<td></td>
<td class=\"centertab\"><a href=\"#\">$id</a></td>
<td><a href=\"$link\" title=\"$title\" class="res">$link</a></td>
<td class=\"centertab\">$trackClicks</td>
<td>$date</td>
</tr>
";
}
}elseif($_GET['type'] == "json"){
echo $stats[1];
exit;
}else{
die("ERROR: Wrong type. I accept htmltable or json as my type<br>htmltable will send the partial table that loads on <a href=\"http://s.lob.li\">lob.li/stats</a>, json outputs raw json array");
}
}
}
if(!empty($_POST['link']) && !empty($_POST['linkage'])){
if(empty($_GET['token']) || $_GET['token'] != $_SESSION['token'] || empty($_POST[$catchid]) || $_POST[$catchid] != $catchVal){
die("<div id=\"danger\" class=\"alert alert-danger\">Oh Noes! Something happened and I can't continue.<br />Please try again by using the form located at <a href=\"http://lob.li\">lob.li</a>.</div>");
}
//$short = sanitize($_POST['link'], $seperator);
$short = $_POST['link'];
$linkage = $_POST['linkage'];
//echo $short;
if(strpos($short, "http://") === false && strpos($short, "https://") === false){
$short = "http://$short";
}
echo shorten($shortdb, $short, $seperator);
echo shorten($redis, $short, $linkage, $seperator);
$reShort = shorten($redis, $short, $linkage, $seperator);
$reShort = explode($seperator, $reShort);
$retCode = $reShort[0];
switch($retCode){
case "0": // Successful link Shorten
$short = $reShort[1];
$title = $reShort[2];
echo "
<div class=\"alert alert-success\" id=\"success\">
Your link: <a href=\"http://lob.li/$short\" title=\"$title\" target=\"lobli.$short\">lob.li/$short</a>
<a href=\"#\" id=\"copylink\" title=\"Copy Link\" onclick=\"copyToClipboard('http://lob.li/$short');\">
<!--<a href=\"#\" id=\"newlink\" title=\"New Link\"> This would require changing how I generate links, and I don't feel like doing it right now - 6/22/12 1:21am EST
<span class=\"glyphicon glyphicon-refresh\" style=\"float:right;\"></span>
</a>-->
<span class=\"glyphicon glyphicon-link\" style=\"float:right;padding-right:1%;\"></span>
</a>
</div>
";
break;
case "1": // Existing Short Link Found
$short = $reShort[1];
$title = $reShort[2];
echo "
<div class=\"alert alert-warning\" id=\"warning\">
Existing link: <a href=\"http://lob.li/$short\" title=\"$title\" target=\"lobli.$short\">lob.li/$short</a>
<a href=\"#\" id=\"copylink\" title=\"Copy Link\" onclick=\"copyToClipboard('http://lob.li/$short');\">
<span class=\"glyphicon glyphicon-link\" style=\"float:right;padding-right:1%;\"></span>
</a>
</div>
";
break;
case "2": // Dead Link
$link = $reShort[1];
echo "
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - Your link: <a href=\"$link\" target=\"$link\">$link</a> didn't resolve to a website. <br />Please check your link and try again.
</div>
";
break;
case "3": // DB Error
$error = $reShort[1];
echo "
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - Well this is embarrassing... This never happens, but I appear to have suffered a database error. <br />Here's what I know: $error
</div>
";
break;
case "4": // Sanitize Failure Error
echo "
<div class=\"alert alert-danger\" id=\"danger\">
ERROR! - The sanitize function seems to have failed. This shouldn't happen, maybe <a href=\"mailto:c0de@unps.us\">c0de</a> forgot a semi-colon somewhere or something.
</div>
";
break;
default:
echo "<div id=\"danger\" class=\"alert alert-danger\">Oh Noes! Something happened and I can't continue.<br />Please try again by using the form located at <a href=\"http://lob.li\">lob.li</a>.</div>";
break;
}
exit;
//foreach($messages as $message){
// echo $message;