Skip to content

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathiasbynens committed Nov 29, 2010
0 parents commit b580047
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* crlf=input
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.DS_Store
3 changes: 3 additions & 0 deletions .htaccess
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
RewriteEngine On
RewriteBase /
RewriteRule ^(.*)? index.php?$1 [L,NC]
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -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/)_
11 changes: 11 additions & 0 deletions config.php
Original file line number Diff line number Diff line change
@@ -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!

?>
7 changes: 7 additions & 0 deletions database.sql
Original file line number Diff line number Diff line change
@@ -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';
31 changes: 31 additions & 0 deletions index.php
Original file line number Diff line number Diff line change
@@ -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 . '/');
}

?>
52 changes: 52 additions & 0 deletions shorten-url.php
Original file line number Diff line number Diff line change
@@ -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.