// GNU/GPL License define('CONFIG_FILE', dirname(__FILE__) . '/' . basename(__FILE__, '.php') . '.config.php'); if (file_exists(CONFIG_FILE)) { require CONFIG_FILE; } if (!defined('DB_FILE')) define('DB_FILE', dirname(__FILE__) . '/urls.sqlite'); if (!defined('BASE_URL')) define('BASE_URL', 'http://'. $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF']); if (!defined('REDIR_URL')) define('REDIR_URL', BASE_URL . '?'); if (!defined('ENABLE_API')) define('ENABLE_API', true); if (!defined('ENABLE_EXPORT')) define('ENABLE_EXPORT', true); // TinyURL class class TinyURL { private $db; static private $base_index = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$-_+!*\'(),'; static private function baseConv($num, $base=null) { if (is_null($base)) $base = strlen(self::$base_index); $index = substr(self::$base_index, 0, $base); $out = ""; for ($t = floor(log10($num) / log10($base)); $t >= 0; $t--) { $a = floor($num / pow($base, $t)); $out = $out . substr($index, $a, 1); $num = $num - ($a * pow($base, $t)); } return $out; } static private function baseConvReverse($num, $base=null) { if (is_null($base)) $base = strlen(self::$base_index); $index = substr(self::$base_index, 0, $base); $out = 0; $len = strlen($num) - 1; for ($t = 0; $t <= $len; $t++) { $out = $out + strpos($index, substr($num, $t, 1)) * pow($base, $len - $t); } return $out; } public function __construct() { $init = file_exists(DB_FILE) ? false : true; $this->db = new SQLite3(DB_FILE); if ($init) { $this->db->exec('CREATE TABLE urls (id VARCHAR(255) NOT NULL PRIMARY KEY, url VARCHAR(255) NOT NULL);'); } } public function checkID($id) { return preg_match('!^['.preg_quote(self::$base_index, '!') . ']{1,254}$!', $id) ? true : false; } public function add($url, $id=null) { if (trim($id)) { if (!$this->checkID($id)) { return false; } $res = $this->db->querySingle('SELECT 1 FROM urls WHERE id = \''.$this->db->escapeString($id).'\';'); if (!empty($res)) { return false; } } else { $id = false; $length = 1; while (!$id) { $id = substr(sha1(mt_rand() . uniqid()), 0, $length++); $id = self::baseConv(hexdec($id)); $res = $this->db->querySingle('SELECT 1 FROM urls WHERE id = \''.$this->db->escapeString($id).'\';'); if (!empty($res)) { $id = false; } } } $this->db->exec('INSERT INTO urls (id, url) VALUES (\''.$this->db->escapeString($id).'\', "'.$this->db->escapeString($url).'");'); return $id; } public function getUrl($id) { $res = $this->db->querySingle('SELECT url FROM urls WHERE id="'.$this->db->escapeString($id).'";'); return $res; } public function checkUrl($url) { $url = parse_url($url); if (empty($url['host']) || empty($url['scheme'])) return false; return true; } public function listAll() { $res = $this->db->query('SELECT * FROM urls;'); $out = array(); while ($row = $res->fetchArray(SQLITE3_ASSOC)) { $out[$row['id']] = $row['url']; } return $out; } } $tiny = new TinyURL; if (isset($_GET['export'])) { header('Content-Type: text/csv'); foreach ($tiny->listAll() as $key=>$value) { echo $key . "\t" . $value . "\n"; } exit; } $html = ''; $msg = false; if(!empty($_SERVER['QUERY_STRING']) && !isset($_GET['msg']) && !isset($_GET['api']) && !isset($_GET['togglePreview'])) { $params = explode('&', $_SERVER['QUERY_STRING']); $url = $tiny->getUrl($params[0]); if(empty($url)) { header('HTTP/1.1 404 Not Found', true, 404); echo '

404 Not Found

'; exit; } elseif ((empty($params[1]) || $params[1] != 'preview') && empty($_REQUEST['preview'])) { header('Location: '.$url); } echo '

Click on the link to get redirected:

'; echo '
'.htmlspecialchars(wordwrap($url, 80, '
', true)).'
'; exit; } elseif (isset($_GET['api']) || !empty($_POST['create'])) { $msg = false; if (isset($_GET['api'])) $src =& $_GET; else $src =& $_POST; if (empty($src['url']) || !trim($src['url'])) $msg = 'Empty URL.'; elseif (!$tiny->checkUrl($src['url'])) $msg = 'URL is not valid.'; elseif (!empty($src['id'])) { if (!$tiny->checkID($src['id'])) $msg = 'ID is not valid.'; elseif ($tiny->getUrl($src['id'])) $msg = 'ID already exists, choose another.'; } if (!$msg) { $id = $tiny->add($src['url'], $src['id']); $url = REDIR_URL . $id; } if (isset($_GET['api'])) { if (!ENABLE_API) { header('HTTP/1.1 404 Not Found', true, 404); echo "API is disabled."; exit; } $return = array('success' => $msg ? '0' : '1', 'message' => $msg ? $msg : $url); switch ($_GET['api']) { case 'js': header('Content-Type: text/javascript'); echo 'var tiny_response = '.json_encode($return).';'; exit; case 'json': header('Content-Type: application/json'); echo json_encode($return); exit; case 'xml': header('Content-Type: text/xml'); echo ''; echo "\n"; echo "\n"; foreach ($return as $key=>$value) echo ' <'.$key.'>'.$value.'\n"; echo ""; exit; default: header('Content-Type: text/plain'); echo $msg ? 'FAIL' : 'OK'; echo "\n"; echo $msg ? $msg : $url; exit; } } else { if ($msg) { $html = '

'.htmlspecialchars($msg).'

'; } else { $html = '

URL successfully created!

'.htmlspecialchars($url).'

'; } } } else { if (isset($_GET['togglePreview'])) { $expire = time() + (3600 * 24 * 355.25 * 5); $url = parse_url(BASE_URL); $path = isset($url['path']) ? $url['path'] : '/'; if (!empty($_COOKIE['preview'])) { setcookie('preview', '', $expire, $path); unset($_COOKIE['preview']); } else { setcookie('preview', '1', $expire, $path); $_COOKIE['preview'] = 1; } } $html = '
Create your mini-URL

How to use this service?

Just copy/paste the long URL you want to make shorter in the Long URL field. The click Create Mini-URL and you will get a new short URL you can copy/paste in services that don\'t accept long URLs (like Twitter).

Can I preview the URLs before being redirected?

Yes if you like you can add &preview at the end of each short URL. Or if you want to have a preview for all URLs of this service, just click here: '.(empty($_COOKIE['preview']) ? 'Enable preview' : 'Disable preview').'.

'; if (ENABLE_API) { $html .= '

API

There is a simple and easy to use API for this service to create new URLs. Just make a GET request to '.BASE_URL.' with those parameters:

api
Return type. Possible values: json, js, text, xml.
url
URL to make shorter.
id (optional)
Desired ID for short URL.

You will get in return two different data, the first will be the success of the query, either 0 or 1 (FAIL or OK for text return) and the second one will be either the error message or the created URL depending if the query succeed or not.

'; } if (ENABLE_EXPORT) { $html .= '

Database export

You can make a simple export of the entire database of this service simply by requesting this URL:
'.BASE_URL.'?export.

The output format is a classic CSV.

'; } $html .= '
'; } echo ' Tiny-Mini-URL

Tiny-Mini-URL service

'.$html.'
'; ?>