Permalink
Browse files

Initial commit.

  • Loading branch information...
mathiasbynens committed Nov 29, 2010
0 parents commit b580047a1a58038a7df1f548b9e0c80c205585f9
Showing with 135 additions and 0 deletions.
  1. +1 −0 .gitattributes
  2. +1 −0 .gitignore
  3. +3 −0 .htaccess
  4. +29 −0 README.md
  5. +11 −0 config.php
  6. +7 −0 database.sql
  7. +31 −0 index.php
  8. +52 −0 shorten-url.php
@@ -0,0 +1 @@
+* crlf=input
@@ -0,0 +1 @@
+.DS_Store
@@ -0,0 +1,3 @@
+RewriteEngine On
+RewriteBase /
+RewriteRule ^(.*)? index.php?$1 [L,NC]
@@ -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/)_
@@ -0,0 +1,11 @@
+<?php
+
+define('MYSQLI_HOST', 'localhost');
+define('MYSQLI_USER', 'user');
+define('MYSQLI_PASSWORD', 'password');
+define('MYSQLI_DATABASE', 'database');
+define('TWITTER_USERNAME', 'mathias');
+define('SHORT_URL', 'http://mths.be/'); // include the trailing slash!
+define('DEFAULT_URL', 'http://mathiasbynens.be'); // omit the trailing slash!
+
+?>
@@ -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';
@@ -0,0 +1,31 @@
+<?php
+
+require('config.php');
+
+function redirect($url) {
+ header('Location: ' . $url, null, 301);
+ die();
+}
+
+if (isset($_SERVER['REDIRECT_QUERY_STRING'])) {
+ $slug = $db->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 . '/');
+}
+
+?>
@@ -0,0 +1,52 @@
+<?php
+
+require('config.php');
+
+header('Content-Type: text/plain;charset=UTF-8');
+
+$db = new mysqli(MYSQLI_HOST, MYSQLI_USER, MYSQLI_PASSWORD, MYSQLI_DATABASE);
+$db->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`');
+ }
+ }
+ }
+}
+
+?>

0 comments on commit b580047

Please sign in to comment.