From b580047a1a58038a7df1f548b9e0c80c205585f9 Mon Sep 17 00:00:00 2001 From: Mathias Bynens Date: Mon, 29 Nov 2010 21:44:02 +0100 Subject: [PATCH] Initial commit. --- .gitattributes | 1 + .gitignore | 1 + .htaccess | 3 +++ README.md | 29 +++++++++++++++++++++++++++ config.php | 11 +++++++++++ database.sql | 7 +++++++ index.php | 31 +++++++++++++++++++++++++++++ shorten-url.php | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 135 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .htaccess create mode 100644 README.md create mode 100644 config.php create mode 100644 database.sql create mode 100644 index.php create mode 100644 shorten-url.php diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..f5a0e1b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* crlf=input \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..270f66e --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +RewriteEngine On +RewriteBase / +RewriteRule ^(.*)? index.php?$1 [L,NC] \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8309b41 --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +# Simple PHP URL shortener + +## Installation + +1) Download the source code as located within this repository, and upload it to your web server. +2) Use `database.sql` to create the `redirect` table in a database of choice. +3) Edit `config.php` and enter your database credentials. + +## Features + +* Redirect to Twitter when given a numerical slug, e.g. `http://mths.be/8065633451249664` → `http://twitter.com/mathias/status/8065633451249664`. +* Redirect to your main website when no slug is entered, e.g. `http://mths.be/` → `http://mathiasbynens.be/`. +* Redirect to a specific page on your main website when an unknown slug (not in the database) is used, e.g. `http://mths.be/demo/jquery-size` → `http://mathiasbynens.be/demo/jquery-size`. +* Ignores weird trailing characters (`!`, `"`, `#`, `$`, `%`, `&`, `'`, `(`, `)`, `*`, `+`, `,`, `-`, `.`, `/`, `@`, `:`, `;`, `<`, `=`, `>`, `[`, `\`, `]`, `^`, `_`, `{`, `|`, `}`, `~`) in slugs — useful when your short URL is run through a crappy link parser, e.g. `http://mths.be/aaa)` → same effect as visiting `http://mths.be/aaa`. +* Generates short, easy-to-type URLs using only `[a-z]` characters. +* DRY, minimal code. +* Correct, semantic use of the available HTTP status codes. + +## Favelets / Bookmarklets + +### Prompt + + javascript:(function(){var%20q=prompt('URL:');if(q){document.location='http://foo.bar/shorten-url.php?'+encodeURIComponent(q)}})(); + +### Shorten this URL + + javascript:(function(){document.location='http://foo.bar/shorten-url.php?'+encodeURIComponent(location.href)})(); + +_— [Mathias](http://mathiasbynens.be/)_ \ No newline at end of file diff --git a/config.php b/config.php new file mode 100644 index 0000000..f47ed9a --- /dev/null +++ b/config.php @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/database.sql b/database.sql new file mode 100644 index 0000000..bc02ffd --- /dev/null +++ b/database.sql @@ -0,0 +1,7 @@ +CREATE TABLE `redirect` ( + `slug` varchar(14) collate utf8_unicode_ci NOT NULL, + `url` varchar(620) collate utf8_unicode_ci NOT NULL, + `date` datetime NOT NULL, + `hits` bigint(20) NOT NULL default '0', + PRIMARY KEY (`slug`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='Used for the URL shortener'; \ No newline at end of file diff --git a/index.php b/index.php new file mode 100644 index 0000000..a70147c --- /dev/null +++ b/index.php @@ -0,0 +1,31 @@ +real_escape_string(rtrim($_SERVER['REDIRECT_QUERY_STRING'], '!"#$%&\'()*+,-./@:;<=>[\\]^_`{|}~')); + if (is_numeric($slug) && strlen($slug) > 3) { + redirect('http://twitter.com/' . TWITTER_USERNAME . '/status' . $_SERVER['REQUEST_URI']); + } + $db = new mysqli(MYSQLI_HOST, MYSQLI_USER, MYSQLI_PASSWORD, MYSQLI_DATABASE); + $db->query('SET NAMES "utf8"'); + $result = $db->query('SELECT `url` FROM `redirect` WHERE `slug` = "' . $slug . '"'); + if ($result && $result->num_rows > 0) { + while ($item = $result->fetch_object()) { + if ($db->query('UPDATE `redirect` SET `hits` = `hits` + 1 WHERE `slug` = "' . $slug . '"')) { + redirect($item->url); + } + } + } else { + redirect(DEFAULT_URL . $_SERVER['REQUEST_URI']); + } +} else { + redirect(DEFAULT_URL . '/'); +} + +?> \ No newline at end of file diff --git a/shorten-url.php b/shorten-url.php new file mode 100644 index 0000000..ac78e69 --- /dev/null +++ b/shorten-url.php @@ -0,0 +1,52 @@ +query('SET NAMES "utf8"'); + +$url = $db->real_escape_string(urldecode(trim($_SERVER['QUERY_STRING']))); + +if (in_array($url, array('', 'about:blank', 'undefined', 'http://localhost/'))) { + die('Enter a URL'); +} + +function nextLetter(&$str) { + $str = ('z' === $str ? 'a' : ++$str); +} + +function getNextShortURL($s) { + $a = str_split($s); + $c = count($a); + if (preg_match('/^z*$/', $s)) { // string consists entirely of `z` + return str_repeat('a', $c + 1); + } + while ('z' === $a[--$c]) { + nextLetter($a[$c]); + } + nextLetter($a[$c]); + return implode($a); +} + +$result = $db->query('SELECT `slug` FROM `redirect` WHERE `url` = "' . $url . '" LIMIT 1'); +if ($result && $result->num_rows > 0) { // If there’s already a short URL for this URL + $item = $result->fetch_object(); + echo SHORT_URL . $item->slug; + die(); +} else { + $result = $db->query('SELECT `slug`, `url` FROM `redirect` ORDER BY `date` DESC LIMIT 1'); + if ($result && $result->num_rows > 0) { + while ($item = $result->fetch_object()) { + $slug = getNextShortURL($item->slug); + if ($url !== $item->url && $db->query('INSERT INTO `redirect` (`slug`, `url`, `date`, `hits`) VALUES ("' . $slug . '", "' . $url . '", NOW(), 0)')) { + header('HTTP/1.1 201 Created'); + echo SHORT_URL . $slug; + $db->query('OPTIMIZE TABLE `redirect`'); + } + } + } +} + +?> \ No newline at end of file