1.4-alpha massive commit:

- now using a global object $ydb for everything related to DB and other globally needed stuff
- change in DB schema: now storing URLs with their keyword as used in shorturl, allowing for any keyword length
- change in DB schema: new table for storing various options including next_id, dropping table of the same name
- change in DB schema: new table for storing hits (for stats)
- added an upgrader from 1.3 to 1.4
- improved the installer, with .htaccess file creation


git-svn-id: http://yourls.googlecode.com/svn/trunk@103 12232710-3e20-11de-b438-597f59cd7555
This commit is contained in:
ozhozh 2009-09-02 20:26:34 +00:00
parent b2ea1003f9
commit 8f6fabba4b
14 changed files with 805 additions and 148 deletions

View File

@ -10,8 +10,8 @@ $table_url = YOURLS_DB_TABLE_URL;
$where = $search_display = $search_text = $search_url = $url = $keyword = '';
$search_in_text = 'URL';
$search_in_sql = 'url';
$sort_by_text = 'ID';
$sort_by_sql = 'id';
$sort_by_text = 'Short URL';
$sort_by_sql = 'keyword';
$sort_order_text = 'Descending Order';
$sort_order_sql = 'desc';
$page = ( isset( $_GET['page'] ) ? intval($_GET['page']) : 1 );
@ -30,9 +30,9 @@ $base_page = YOURLS_SITE . '/admin/index.php';
// Searching
if(!empty($search) && !empty($_GET['s_in'])) {
switch($_GET['s_in']) {
case 'id':
$search_in_text = 'ID';
$search_in_sql = 'id';
case 'keyword':
$search_in_text = 'Short URL';
$search_in_sql = 'keyword';
break;
case 'url':
$search_in_text = 'URL';
@ -53,9 +53,9 @@ if(!empty($search) && !empty($_GET['s_in'])) {
// Sorting
if(!empty($_GET['s_by']) || !empty($_GET['s_order'])) {
switch($_GET['s_by']) {
case 'id':
$sort_by_text = 'ID';
$sort_by_sql = 'id';
case 'keyword':
$sort_by_text = 'Short URL';
$sort_by_sql = 'keyword';
break;
case 'url':
$sort_by_text = 'URL';
@ -87,8 +87,8 @@ if(!empty($_GET['s_by']) || !empty($_GET['s_order'])) {
}
// Get URLs Count for current filter, total links in DB & total clicks
$total_items = $ydb->get_var("SELECT COUNT(id) FROM $table_url WHERE 1=1 $where");
$totals = $ydb->get_row("SELECT COUNT(id) as c, SUM(clicks) as s FROM $table_url WHERE 1=1");
$total_items = $ydb->get_var("SELECT COUNT(keyword) FROM $table_url WHERE 1=1 $where");
$totals = $ydb->get_row("SELECT COUNT(keyword) as c, SUM(clicks) as s FROM $table_url WHERE 1=1");
// This is a bookmarklet
if ( isset( $_GET['u'] ) ) {
@ -96,10 +96,10 @@ if ( isset( $_GET['u'] ) ) {
$url = $_GET['u'];
$keyword = ( isset( $_GET['k'] ) ? $_GET['k'] : '' );
$return = yourls_add_new_link( $url, $keyword, $ydb );
$return = yourls_add_new_link( $url, $keyword );
// If fails because keyword already exist, retry with no keyword
if ( $return['status'] == 'fail' && $return['code'] == 'error:keyword' ) {
if ( isset( $return['status'] ) && $return['status'] == 'fail' && isset( $return['code'] ) && $return['code'] == 'error:keyword' ) {
$msg = $return['message'];
$return = yourls_add_new_link( $url, '', $ydb );
$return['message'] .= ' ('.$msg.')';
@ -175,9 +175,8 @@ yourls_html_head( $context );
<table id="tblUrl" class="tblSorter" cellpadding="0" cellspacing="1">
<thead>
<tr>
<th>Link&nbsp;ID&nbsp;&nbsp;</th>
<th>Original URL</th>
<th>Short URL</th>
<th>Original URL</th>
<th>Date</th>
<th>IP</th>
<th>Clicks&nbsp;&nbsp;</th>
@ -207,20 +206,19 @@ yourls_html_head( $context );
<tbody>
<?php
// Main Query
$url_results = $ydb->get_results("SELECT * FROM $table_url WHERE 1=1 $where ORDER BY $sort_by_sql $sort_order_sql LIMIT $offset, $perpage;");
if($url_results) {
$url_results = $ydb->get_results("SELECT * FROM `$table_url` WHERE 1=1 $where ORDER BY $sort_by_sql $sort_order_sql LIMIT $offset, $perpage;");
if( $url_results ) {
foreach( $url_results as $url_result ) {
$base36 = yourls_int2string($url_result->id);
$keyword = yourls_sanitize_string($url_result->keyword);
$timestamp = strtotime($url_result->timestamp);
$id = ($url_result->id);
$url = stripslashes($url_result->url);
$ip = $url_result->ip;
$clicks = $url_result->clicks;
echo yourls_table_add_row($id, $base36, $url, $ip, $clicks, $timestamp );
echo yourls_table_add_row( $keyword, $url, $ip, $clicks, $timestamp );
}
} else {
echo '<tr class="nourl_found"><td colspan="7">No URL Found</td></tr>';
echo '<tr class="nourl_found"><td colspan="6">No URL Found</td></tr>';
}
?>
</tbody>

View File

@ -16,17 +16,17 @@ switch( stripslashes($_REQUEST['mode']) ) {
break;
case 'edit_display':
$row = yourls_table_edit_row ( $_REQUEST['id'] );
$row = yourls_table_edit_row ( $_REQUEST['keyword'] );
echo yourls_json_encode( array('html' => $row) );
break;
case 'edit_save':
$return = yourls_edit_link( $_REQUEST['url'], $_REQUEST['id'], $_REQUEST['newid'] );
$return = yourls_edit_link( $_REQUEST['url'], $_REQUEST['keyword'], $_REQUEST['newkeyword'] );
echo yourls_json_encode($return);
break;
case 'delete':
$query = yourls_delete_link_by_id( $_REQUEST['id'] );
$query = yourls_delete_link_by_keyword( $_REQUEST['keyword'] );
echo yourls_json_encode(array('success'=>$query));
break;

94
admin/upgrade.php Normal file
View File

@ -0,0 +1,94 @@
<?php
// Require Files
define( 'YOURLS_NO_VERSION_CHECK', true ); // Bypass version checking to prevent loop
require_once( dirname(dirname(__FILE__)).'/includes/config.php' );
require_once( dirname(dirname(__FILE__)).'/includes/functions-upgrade.php' );
if (defined('YOURLS_PRIVATE') && YOURLS_PRIVATE == true)
require_once( dirname(dirname(__FILE__)).'/includes/auth.php' );
yourls_html_head( 'tools' );
?>
<h1>
<a href="<?php echo YOURLS_SITE; ?>/admin/index.php" title="YOURLS"><span>YOURLS</span>: <span>Y</span>our <span>O</span>wn <span>URL</span> <span>S</span>hortener<br/>
<img src="<?php echo YOURLS_SITE; ?>/images/yourls-logo.png" alt="YOURLS" title="YOURLS" style="border: 0px;" /></a>
</h1>
<?php if ( defined('YOURLS_PRIVATE') && YOURLS_PRIVATE == true ) { ?>
<p>Your are logged in as: <strong><?php echo YOURLS_USER; ?></strong>. <a href="?mode=logout" title="Logout">Logout</a></p>
<?php } ?>
<div id="tools_desc">
<h2>Upgrade YOURLS</h2>
<?php
// Check if upgrade is needed
if ( !yourls_upgrade_is_needed() ) {
echo '<p>Upgrade not required. Go <a href="'.YOURLS_SITE.'/admin/index.php">back to play</a>!</p>';
} else {
/*
step 1: create new tables and populate them, update old tables structure,
step 2: convert each row of outdated tables if needed
step 3: if applicable finish updating outdated tables (indexes etc)
step 4: update version & db_version in options, this is all done!
*/
// From what are we upgrading?
if ( isset( $_GET['oldver'] ) && isset( $_GET['oldsql'] ) ) {
$oldver = intval( $_GET['oldver'] );
$oldsql = intval( $_GET['oldsql'] );
} else {
list( $oldver, $oldsql ) = yourls_get_current_version_from_sql();
}
// To what are we upgrading ?
$newver = YOURLS_VERSION;
$newsql = YOURLS_DB_VERSION;
// Let's go
$step = ( isset( $_GET['step'] ) ? intval( $_GET['step'] ) : 0 );
switch( $step ) {
default:
case 0:
echo "
<p>Your current installation needs to be upgraded.</p>
<p>Please, pretty please, it is recommended that
you <strong>backup</strong> your database (you should do this regularly anyway)</p>
<p>Nothing awful *should* happen, but this doesn't mean it *won't* happen, right?</p>
<p>Once you are ready, press Upgrade!</p>
<form action='upgrade.php?' method='get'>
<input type='hidden' name='step' value='1' />
<input type='hidden' name='oldver' value='$oldver' />
<input type='hidden' name='newver' value='$newver' />
<input type='hidden' name='oldsql' value='$oldsql' />
<input type='hidden' name='newsql' value='$newsql' />
<input type='submit' class='primary' value='Upgrade' />
</form>";
break;
case 1:
case 2:
case 3:
yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql );
break;
case 4:
yourls_upgrade( 4, $oldver, $newver, $oldsql, $newsql );
$admin = YOURLS_SITE.'/admin/index.php';
echo "
<p>Your installation is now up to date :)</p>
<p>Go back to <a href='$admin'>the admin interface</a></p>
";
}
}
?>
</div>
<?php yourls_html_footer(); ?>

32
changelog.txt Normal file
View File

@ -0,0 +1,32 @@
*** YOURLS Changelog ***
This file attempts to list the major changes through all versions of YOURLS. For a much more detailed
list, simply refer to the commit messages: http://code.google.com/p/yourls/source/list
1.0
- initial release
1.0.1
- don't remember. Trivial stuff probably.
1.1
- don't remember. Some little bugs I guess.
1.2
- don't remember. A few tiny stuff for sure.
1.3-RC1
- added bookmarklet and tools page
- improved XSS filter when adding new URL
- code cleanup in admin/index.php to separate code and display
- added favicon
- stricter coding to prevent notices with undefined indexes
- hide PHP notices & SQL errors & warnings, unless YOURLS_DEBUG constant set to true
1.4
- now using a global object $ydb for everything related to DB and other globally needed stuff
- change in DB schema: now storing URLs with their keyword as used in shorturl, allowing for any keyword length
- change in DB schema: new table for storing various options including next_id, dropping table of the same name
- change in DB schema: new table for storing hits (for stats)
- added an upgrader from 1.3 to 1.4
- improved the installer, with .htaccess file creation

View File

@ -394,11 +394,4 @@ class ezSQL_mysql extends ezSQLcore {
return mysql_get_server_info( $this->dbh ) ;
}
}
// Create the YOURLS DB object
if ( function_exists( 'yourls_db_connect' ) ) {
global $ydb;
yourls_db_connect();
}
?>

View File

@ -15,17 +15,23 @@ define('YOURLS_DB_NAME', 'yourls');
/** MySQL hostname */
define('YOURLS_DB_HOST', 'localhost');
/** MySQL URL table name. Don't change this if in doubt. */
/** MySQL table name to store URLs. Don't change this if in doubt. */
define('YOURLS_DB_TABLE_URL', 'yourls_url');
/** MySQL Next ID table name. Don't change this if in doubt. */
define('YOURLS_DB_TABLE_NEXTDEC', 'yourls_next_id');
/** MySQL table name to store a few options. Don't change this if in doubt. */
define('YOURLS_DB_TABLE_OPTIONS', 'yourls_options');
/** MySQL table name to log redirects (for stats). Don't change this if in doubt. */
define('YOURLS_DB_TABLE_LOG', 'yourls_log');
/*
** Site options
*/
/** Turn this on to enable error reporting. Recommended value is false **/
/** Turn this on to enable error reporting. Leave this to false **/
define('YOURLS_DEBUG', false);
/** Short domain URL, no trailing slash */
@ -70,9 +76,4 @@ $yourls_reserved_URL = array(
/******************** DO NOT EDIT ANYTHING ELSE ********************/
// Include everything except auth functions
require_once (dirname(__FILE__).'/version.php');
require_once (dirname(__FILE__).'/functions.php');
require_once (dirname(__FILE__).'/functions-baseconvert.php');
require_once (dirname(__FILE__).'/class-mysql.php');
require_once (dirname(__FILE__).'/load-yourls.php');

View File

@ -142,23 +142,42 @@ function yourls_create_sql_tables() {
$create_tables = array();
$create_tables[YOURLS_DB_TABLE_URL] =
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_URL.'` ('.
'`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,'.
'`keyword` varchar(200) NOT NULL,'.
'`url` VARCHAR(200) NOT NULL,'.
'`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,'.
'`ip` VARCHAR(41) NOT NULL,'.
'`clicks` INT(10) UNSIGNED NOT NULL,'.
'PRIMARY KEY (`id`)'.
') ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;';
'PRIMARY KEY (`keyword`)'.
') ENGINE=MyISAM DEFAULT CHARSET=utf8 ;';
$create_tables[YOURLS_DB_TABLE_OPTIONS] =
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('.
'`option_id` bigint(20) unsigned NOT NULL auto_increment,'.
'`option_name` varchar(64) NOT NULL default "",'.
'`option_value` longtext NOT NULL,'.
'PRIMARY KEY (`option_id`,`option_name`),'.
'KEY `option_name` (`option_name`)'.
') ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;';
$create_tables[YOURLS_DB_TABLE_LOG] =
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('.
'`click_id` int(11) NOT NULL auto_increment,'.
'`click_time` datetime NOT NULL,'.
'`shorturl` varchar(200) NOT NULL,'.
'`referrer` varchar(200) NOT NULL,'.
'`user_agent` varchar(255) NOT NULL,'.
'`ip_address` varchar(41) NOT NULL,'.
'`country_code` char(2) NOT NULL,'.
'PRIMARY KEY (`click_id`),'.
'KEY `shorturl` (`shorturl`,`referrer`,`country_code`)'.
') ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;';
$create_tables[YOURLS_DB_TABLE_NEXTDEC] =
'CREATE TABLE `'.YOURLS_DB_TABLE_NEXTDEC.'` ('.
'`next_id` BIGINT NOT NULL ,'.
'PRIMARY KEY (`next_id`)'.
') ENGINE = MYISAM ;';
// Insert Initial Records
$insert_queries = array();
$insert_queries[] = 'INSERT INTO '.YOURLS_DB_TABLE_NEXTDEC.' VALUES (1)';
$insert_queries[] = 'INSERT INTO '.YOURLS_DB_TABLE_OPTIONS.' VALUES (1, "next_id", 1)';
$insert_queries[] = 'INSERT INTO '.YOURLS_DB_TABLE_OPTIONS.' VALUES (2, "version", '.YOURLS_VERSION.')';
$insert_queries[] = 'INSERT INTO '.YOURLS_DB_TABLE_OPTIONS.' VALUES (3, "db_version", '.YOURLS_DB_VERSION.')';
$create_table_count = 0;
$insert_query_count = 0;
@ -197,5 +216,4 @@ function yourls_create_sql_tables() {
return array( 'success' => $success_msg, 'error' => $error_msg );
}
?>

View File

@ -0,0 +1,159 @@
<?php
// Upgrade YOURLS and DB schema
function yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql ) {
// As of now, there's no other upgrading possibility.
// In the future this function may contain tests to upgrade
// from any release to the latest
yourls_upgrade_to_14( $step );
}
// Upgrade DB Schema from 1.3-RC1 or prior to 1.4
function yourls_upgrade_to_14( $step ) {
switch( $step ) {
case 1:
// create table log & table options
// update table url structure
yourls_create_tables_for_14();
yourls_alter_url_table_to_14();
yourls_redirect_javascript( YOURLS_SITE."/admin/upgrade.php?step=2&oldver=1.3&newver=1.4&oldsql=100&newsql=200" );
break;
case 2:
// convert each link in table url
yourls_update_table_to_14();
break;
case 3:
// update table url structure part 2: recreate indexes
yourls_alter_url_table_to_14_part_two();
yourls_redirect_javascript( YOURLS_SITE."/admin/upgrade.php?step=4&oldver=1.3&newver=1.4&oldsql=100&newsql=200" );
break;
case 4:
// update version & db_version & next_id in the option table
// attempt to drop YOURLS_DB_TABLE_NEXTDEC
yourls_update_options_to_14();
}
}
// Update options to reflect new version
function yourls_update_options_to_14() {
yourls_update_option( 'version', YOURLS_VERSION );
yourls_update_option( 'db_version', YOURLS_DB_VERSION );
global $ydb;
$table = YOURLS_DB_TABLE_NEXTDEC;
$next_id = $ydb->get_var("SELECT `next_id` FROM `$table`");
yourls_update_option( 'next_id', $next_id );
@$ydb->query( "DROP TABLE `$table`" );
}
// Create new tables for YOURLS 1.4: options & log
function yourls_create_tables_for_14() {
global $ydb;
$queries = array();
$queries[YOURLS_DB_TABLE_OPTIONS] =
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('.
'`option_id` int(11) unsigned NOT NULL auto_increment,'.
'`option_name` varchar(64) NOT NULL default "",'.
'`option_value` longtext NOT NULL,'.
'PRIMARY KEY (`option_id`,`option_name`),'.
'KEY `option_name` (`option_name`)'.
');';
$queries[YOURLS_DB_TABLE_LOG] =
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('.
'`click_id` int(11) NOT NULL auto_increment,'.
'`click_time` datetime NOT NULL,'.
'`shorturl` varchar(200) NOT NULL,'.
'`referrer` varchar(200) NOT NULL,'.
'`user_agent` varchar(255) NOT NULL,'.
'`ip_address` varchar(41) NOT NULL,'.
'`country_code` char(2) NOT NULL,'.
'PRIMARY KEY (`click_id`),'.
'KEY `shorturl` (`shorturl`,`referrer`,`country_code`)'.
');';
foreach( $queries as $query ) {
$ydb->query( $query );
}
echo "<p>New tables created. Please wait...</p>";
}
// Alter table structure, part 1 (change schema, drop index)
function yourls_alter_url_table_to_14() {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$alters = array();
$results = array();
$alters[] = "ALTER TABLE `$table` CHANGE `id` `keyword` VARCHAR( 200 ) NOT NULL";
$alters[] = "ALTER TABLE `$table` DROP PRIMARY KEY";
foreach ( $alters as $query ) {
$ydb->query( $query );
}
echo "<p>Structure of existing tables updated. Please wait...</p>";
}
// Alter table structure, part 2 (recreate index after the table is up to date)
function yourls_alter_url_table_to_14_part_two() {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$alters = array();
$alters[] = "ALTER TABLE `$table` ADD PRIMARY KEY ( `keyword` )";
foreach ( $alters as $query ) {
$ydb->query( $query );
}
echo "<p>New table index created</p>";
}
// Convert each link from 1.3 (id) to 1.4 (keyword) structure
function yourls_update_table_to_14() {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
// Modify each link to reflect new structure
$chunk = 30;
$from = isset($_GET['from']) ? intval( $_GET['from'] ) : 0 ;
$total = yourls_get_db_stats();
$total = $total['total_links'];
$sql = "SELECT `keyword`,`url` FROM `$table` WHERE 1=1 ORDER BY `url` ASC LIMIT $from, $chunk ;";
$rows = $ydb->get_results($sql);
$count = 0;
foreach( $rows as $row ) {
$keyword = $row->keyword;
$url = $row->url;
$newkeyword = yourls_int2string( $keyword );
$result = $ydb->query("UPDATE `$table` SET `keyword` = '$newkeyword' WHERE `url` = '$url';");
$count++;
}
if ( $count == $chunk ) {
// there are probably other rows to convert
$from = $from + $chunk;
$remain = $total - $from;
echo "<p>Converted $chunk database rows ($remain remaining). Continuing... Please do not close this window until it's finished!</p>";
yourls_redirect_javascript( YOURLS_SITE."/admin/upgrade.php?step=2&oldver=1.3&newver=1.4&oldsql=100&newsql=200&from=$from" );
} else {
// All done
echo '<p>All rows converted! Please wait...</p>';
yourls_redirect_javascript( YOURLS_SITE."/admin/upgrade.php?step=3&oldver=1.3&newver=1.4&oldsql=100&newsql=200" );
}
}

View File

@ -30,7 +30,7 @@ class yourls_array2xml {
$this->text.="</$key>";
}
}
return $array_text;
//return $array_text;
}
/*Transform an XML string to associative array "XML Parser Functions"*/

View File

@ -25,11 +25,11 @@ function yourls_string2int( $str ) {
return yourls_base2base(trim($str), YOURLS_URL_CONVERT, 10);
}
// Make sure a link id (site.com/1fv) is valid.
// Make sure a link keyword (ie "1fv" as in "site.com/1fv") is valid.
function yourls_sanitize_string($in) {
if (YOURLS_URL_CONVERT <= 37)
$in = strtolower($in);
return substr(preg_replace('/[^a-zA-Z0-9]/', '', $in), 0, 12);
return substr(preg_replace('/[^a-zA-Z0-9]/', '', $in), 0, 199);
}
// A few sanity checks on the URL
@ -40,8 +40,10 @@ function yourls_sanitize_url($url) {
// make sure there's a protocol, add http:// if not
if ( !preg_match('!^([a-zA-Z]+://)!', $url ) )
$url = 'http://'.$url;
return yourls_clean_url($url);
$url = yourls_clean_url($url);
return substr( $url, 0, 199 );
}
// Function to filter all invalid characters from a URL. Stolen from WP's clean_url()
@ -72,7 +74,8 @@ function yourls_deep_replace($search, $subject){
}
// Make sure an id link is a valid integer (PHP's intval() limits to too small numbers)
// Make sure an integer is a valid integer (PHP's intval() limits to too small numbers)
// TODO FIXME FFS: unused ?
function yourls_sanitize_int($in) {
return ( substr(preg_replace('/[^0-9]/', '', strval($in) ), 0, 20) );
}
@ -84,12 +87,16 @@ function yourls_intval($in) {
return mysql_real_escape_string($in);
}
// Escape a string
function yourls_escape( $in ) {
return mysql_real_escape_string($in);
}
// Check to see if a given integer id is reserved (ie reserved URL or an existing page)
// Check to see if a given keyword is reserved (ie reserved URL or an existing page)
// Returns bool
function yourls_is_reserved_id($id) {
function yourls_keyword_is_reserved( $keyword ) {
global $yourls_reserved_URL;
$keyword = yourls_int2string( yourls_intval($id) );
if ( in_array( $keyword, $yourls_reserved_URL)
or file_exists(dirname(dirname(__FILE__))."/pages/$keyword.php")
or is_dir(dirname(dirname(__FILE__))."$keyword")
@ -99,7 +106,7 @@ function yourls_is_reserved_id($id) {
return false;
}
// Function: Get IP Address
// Function: Get IP Address. Returns a DB safe string.
function yourls_get_IP() {
if(!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip_address = $_SERVER['HTTP_CLIENT_IP'];
@ -114,37 +121,45 @@ function yourls_get_IP() {
$ip_address = explode(',', $ip_address);
$ip_address = $ip_address[0];
}
$ip_address = preg_replace( '/[^0-9a-fA-F:., ]/', '', $ip_address );
return $ip_address;
}
// Add the "Edit" row
function yourls_table_edit_row($id) {
function yourls_table_edit_row( $keyword ) {
global $ydb;
$id = yourls_intval($id);
$table = YOURLS_DB_TABLE_URL;
$url = $ydb->get_row("SELECT `url` FROM `$table` WHERE `id` = '$id';");
$safe_url = stripslashes($url->url);
$keyword = yourls_int2string($id);
if($url) {
$return = <<<RETURN
<tr id="edit-$id" class="edit-row"><td colspan="6">Edit: <strong>original URL</strong>:<input type="text" id="edit-url-$id" name="edit-url-$id" value="$safe_url" class="text" size="100" /><strong>short URL</strong>:<input type="text" id="edit-id-$id" name="edit-id-$id" value="$keyword" class="text" size="10" /></td><td colspan="1"><input type="button" id="edit-submit-$id" name="edit-submit-$id" value="Save" title="Save new values" class="button" onclick="edit_save('$id');" />&nbsp;<input type="button" id="edit-close-$id" name="edit-close-$id" value="X" title="Cancel editing" class="button" onclick="hide_edit('$id');" /></td></tr>
$keyword = yourls_sanitize_string( $keyword );
$id = yourls_string2int( $keyword ); // used as HTML #id
$url = $ydb->get_row("SELECT `url` FROM `$table` WHERE `keyword` = '$keyword';");
$safe_url = stripslashes( $url->url );
$www = YOURLS_SITE;
if( $url ) {
$return = <<<RETURN
<tr id="edit-$id" class="edit-row"><td colspan="5"><strong>Original URL</strong>:<input type="text" id="edit-url-$id" name="edit-url-$id" value="$safe_url" class="text" size="100" /> <strong>Short URL</strong>: $www/<input type="text" id="edit-keyword-$id" name="edit-keyword-$id" value="$keyword" class="text" size="10" /></td><td colspan="1"><input type="button" id="edit-submit-$id" name="edit-submit-$id" value="Save" title="Save new values" class="button" onclick="edit_save('$id');" />&nbsp;<input type="button" id="edit-close-$id" name="edit-close-$id" value="X" title="Cancel editing" class="button" onclick="hide_edit('$id');" /><input type="hidden" id="old_keyword_$id" value="$keyword"/></td></tr>
RETURN;
} else {
$return = '<tr><td colspan="7">Invalid URL ID</td></tr>';
$return = '<tr><td colspan="6">Error, URL not found</td></tr>';
}
return $return;
}
// Add a link row
function yourls_table_add_row( $id, $keyword, $url, $ip, $clicks, $timestamp ) {
function yourls_table_add_row( $keyword, $url, $ip, $clicks, $timestamp ) {
$keyword = yourls_sanitize_string( $keyword );
$id = yourls_string2int( $keyword ); // used as HTML #id
$date = date( 'M d, Y H:i', $timestamp+( YOURLS_HOURS_OFFSET * 3600) );
$clicks = number_format($clicks);
$www = YOURLS_SITE;
$shorturl = YOURLS_SITE.'/'.$keyword;
return <<<ROW
<tr id="id-$id"><td id="keyword-$id">$keyword</td><td id="url-$id"><a href="$url" title="$url">$url</a></td><td id="shorturl-$id"><a href="$www/$keyword" title="$www/$keyword">$www/$keyword</a></td><td id="timestamp-$id">$date</td><td>$ip</td> <td>$clicks</td><td class="actions"><input type="button" id="edit-button-$id" name="edit-button" value="Edit" class="button" onclick="edit('$id');" />&nbsp;<input type="button" id="delete-button-$id" name="delete-button" value="Del" class="button" onclick="remove('$id');" /></td></tr>
<tr id="id-$id"><td id="keyword-$id"><a href="$shorturl">$shorturl</a></td><td id="url-$id"><a href="$url" title="$url">$url</a></td><td id="timestamp-$id">$date</td><td>$ip</td><td>$clicks</td><td class="actions"><input type="button" id="edit-button-$id" name="edit-button" value="Edit" class="button" onclick="edit('$id');" />&nbsp;<input type="button" id="delete-button-$id" name="delete-button" value="Del" class="button" onclick="remove('$id');" /><input type="hidden" id="keyword_$id" value="$keyword"/></td></tr>
ROW;
}
@ -160,32 +175,34 @@ function yourls_get_next_decimal() {
function yourls_update_next_decimal($int = '') {
global $ydb;
$int = ( $int == '' ) ? 'next+1' : (int)$int ;
$int = ( $int == '' ) ? 'next_id+1' : (int)$int ;
$table = YOURLS_DB_TABLE_NEXTDEC;
return $ydb->query("UPDATE `$table` set next_id=$int");
}
// Delete a link in the DB
function yourls_delete_link_by_id($id) {
function yourls_delete_link_by_keyword( $keyword ) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$id = yourls_intval($id);
return $ydb->query("DELETE FROM `$table` WHERE `id` = $id;");
$keyword = yourls_sanitize_string( $keyword );
return $ydb->query("DELETE FROM `$table` WHERE `keyword` = '$keyword';");
}
// SQL query to insert a new link in the DB. Needs sanitized data. Returns boolean for success or failure of the inserting
function yourls_insert_link_in_db($url, $id) {
function yourls_insert_link_in_db($url, $keyword) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$timestamp = date('Y-m-d H:i:s');
$ip = yourls_get_IP();
return $ydb->query("INSERT INTO `$table` VALUES($id, '$url', '$timestamp', '$ip', 0);");
$insert = $ydb->query("INSERT INTO `$table` VALUES('$keyword', '$url', '$timestamp', '$ip', 0);");
return (bool)$insert;
}
// Add a new link in the DB, either with custom keyword, or find one
function yourls_add_new_link($url, $keyword = '') {
function yourls_add_new_link( $url, $keyword = '' ) {
global $ydb;
if ( !$url || $url == 'http://' || $url == 'https://' ) {
@ -196,9 +213,9 @@ function yourls_add_new_link($url, $keyword = '') {
}
$table = YOURLS_DB_TABLE_URL;
$url = mysql_real_escape_string(yourls_sanitize_url($url));
$url = mysql_real_escape_string( yourls_sanitize_url($url) );
$strip_url = stripslashes($url);
$url_exists = $ydb->get_row("SELECT id,url FROM `$table` WHERE `url` = '".$strip_url."';");
$url_exists = $ydb->get_row("SELECT keyword,url FROM `$table` WHERE `url` = '".$strip_url."';");
$ip = yourls_get_IP();
$return = array();
@ -206,55 +223,55 @@ function yourls_add_new_link($url, $keyword = '') {
if( !$url_exists ) {
// Custom keyword provided
if ($keyword) {
if ( $keyword ) {
$keyword = mysql_real_escape_string(yourls_sanitize_string($keyword));
if (!yourls_keyword_is_free($keyword, $ydb)) {
// This id either reserved or taken already
if ( !yourls_keyword_is_free($keyword) ) {
// This shorturl either reserved or taken already
$return['status'] = 'fail';
$return['code'] = 'error:keyword';
$return['message'] = 'URL id '.$keyword.' already exists in database or is reserved';
$return['message'] = 'Short URL '.$keyword.' already exists in database or is reserved';
} else {
// all clear, store !
$id = yourls_string2int($keyword);
yourls_insert_link_in_db($url, $id, $ydb);
$return['url'] = array('id' => $id, 'keyword' => $keyword, 'url' => $strip_url, 'date' => date('Y-m-d H:i:s'), 'ip' => yourls_get_IP() );
yourls_insert_link_in_db($url, $keyword);
$return['url'] = array('keyword' => $keyword, 'url' => $strip_url, 'date' => date('Y-m-d H:i:s'), 'ip' => $ip );
$return['status'] = 'success';
$return['message'] = $strip_url.' added to database';
$return['html'] = yourls_table_add_row( $id, $keyword, $url, yourls_get_IP(), 0, time() );
$return['html'] = yourls_table_add_row( $keyword, $url, $ip, 0, time() );
$return['shorturl'] = YOURLS_SITE .'/'. $keyword;
}
// Create random keyword
} else {
$timestamp = date('Y-m-d H:i:s');
$id = yourls_get_next_decimal($ydb);
$id = yourls_get_next_decimal();
$ok = false;
do {
$add_url = @yourls_insert_link_in_db($url, $id, $ydb);
$free = !yourls_is_reserved_id( $id );
$keyword = yourls_int2string( $id );
$free = yourls_keyword_is_free($keyword);
$add_url = @yourls_insert_link_in_db($url, $keyword);
$ok = ($free && $add_url);
if ( $ok === false && $add_url === 1 ) {
// we stored something, but shouldn't have (ie reserved id)
$delete = yourls_delete_link_by_id( $id, $ydb );
$return['extra_info'] .= '(deleted '.$id.')';
$delete = yourls_delete_link_by_keyword( $keyword );
$return['extra_info'] .= '(deleted '.$keyword.')';
} else {
// everything ok, populate needed vars
$keyword = yourls_int2string($id);
$return['url'] = array('id' => $id, 'keyword' => $keyword, 'url' => $strip_url, 'date' => $timestamp, 'ip' => $ip);
$return['url'] = array('keyword' => $keyword, 'url' => $strip_url, 'date' => $timestamp, 'ip' => $ip );
$return['status'] = 'success';
$return['message'] = $strip_url.' added to database';
$return['html'] = yourls_table_add_row( $id, $keyword, $url, $ip, 0, time() );
$return['html'] = yourls_table_add_row( $keyword, $url, $ip, 0, time() );
$return['shorturl'] = YOURLS_SITE .'/'. $keyword;
}
$id++;
} while (!$ok);
@yourls_update_next_decimal($id, $ydb);
@yourls_update_next_decimal($id);
}
} else {
// URL was already stored
$return['status'] = 'fail';
$return['code'] = 'error:url';
$return['message'] = $strip_url.' already exists in database';
$return['shorturl'] = YOURLS_SITE .'/'. yourls_int2string( $url_exists->id );
$return['shorturl'] = YOURLS_SITE .'/'. $url_exists->keyword;
}
return $return;
@ -262,45 +279,42 @@ function yourls_add_new_link($url, $keyword = '') {
// Edit a link
function yourls_edit_link($url, $id, $keyword='') {
function yourls_edit_link($url, $keyword, $newkeyword='') {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$url = mysql_real_escape_string(yourls_sanitize_url($url));
$id = yourls_intval($id);
$keyword = yourls_sanitize_string( $keyword );
$newkeyword = yourls_sanitize_string( $newkeyword );
$strip_url = stripslashes($url);
$old_url = $ydb->get_var("SELECT `url` FROM `$table` WHERE `id` = '".$id."';");
$old_url = $ydb->get_var("SELECT `url` FROM `$table` WHERE `keyword` = '$keyword';");
// Check if new URL is not here already
if ($old_url != $url) {
$url_exists = intval($ydb->get_var("SELECT id FROM `$table` WHERE `url` = '".$strip_url."';"));
$new_url_already_there = intval($ydb->get_var("SELECT COUNT(keyword) FROM `$table` WHERE `url` = '$strip_url';"));
} else {
$url_exists = false;
$new_url_already_there = false;
}
// Check if the new keyword is not here already
$newid = ( $keyword ? yourls_string2int($keyword) : $id );
if ($newid != $id) {
$id_exists = intval($ydb->get_var("SELECT id FROM `$table` WHERE `id` = '".$newid."';"));
$id_free = yourls_keyword_is_free($keyword, $ydb);
$id_is_ok = ($id_exists == 0) && $id_free;
if ( $newkeyword != $keyword ) {
$keyword_is_ok = yourls_keyword_is_free( $newkeyword );
} else {
$id_is_ok = true;
$keyword_is_ok = true;
}
// All clear, update
if($url_exists == 0 && $id_is_ok ) {
if ( !$new_url_already_there && $keyword_is_ok ) {
$timestamp4screen = date( 'Y M d H:i', time()+( yourls_HOURS_OFFSET * 3600) );
$timestamp4db = date('Y-m-d H:i:s', time()+( yourls_HOURS_OFFSET * 3600) );
$update_url = $ydb->query("UPDATE `$table` SET `url` = '$url', `timestamp` = '$timestamp4db', `id` = '$newid' WHERE `id` = $id;");
if($update_url) {
$return['url'] = array('id' => $newid, 'keyword' => $keyword, 'shorturl' => YOURLS_SITE.'/'.$keyword, 'url' => $strip_url, 'date' => $timestamp4screen);
$update_url = $ydb->query("UPDATE `$table` SET `url` = '$url', `timestamp` = '$timestamp4db', `keyword` = '$newkeyword' WHERE `keyword` = '$keyword';");
if( $update_url ) {
$return['url'] = array( 'keyword' => $newkeyword, 'shorturl' => YOURLS_SITE.'/'.$newkeyword, 'url' => $strip_url, 'date' => $timestamp4screen);
$return['status'] = 'success';
$return['message'] = 'Link updated in database';
} else {
$return['status'] = 'fail';
$return['message'] = 'Error updating '.$strip_url.' (ID: '.$id.') to database';
$return['message'] = 'Error updating '.$strip_url.' (Short URL: '.$keyword.') to database';
}
// Nope
@ -314,15 +328,14 @@ function yourls_edit_link($url, $id, $keyword='') {
// Check if keyword id is free (ie not already taken, and not reserved)
function yourls_keyword_is_free($str) {
function yourls_keyword_is_free( $keyword ) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$id = yourls_string2int($str);
if ( yourls_is_reserved_id($id) )
if ( yourls_keyword_is_reserved($keyword) )
return false;
$already_exists = intval($ydb->get_var("SELECT `id` FROM `$table` WHERE `id` = '".$id."';"));
$already_exists = $ydb->get_var("SELECT COUNT(`keyword`) FROM `$table` WHERE `keyword` = '$keyword';");
if ( $already_exists )
return false;
@ -331,7 +344,7 @@ function yourls_keyword_is_free($str) {
// Display a page
function yourls_page($page) {
function yourls_page( $page ) {
$include = dirname(dirname(__FILE__))."/pages/$page.php";
if (!file_exists($include)) {
die("Page '$page' not found");
@ -355,6 +368,9 @@ function yourls_db_connect() {
if ( $ydb->last_error )
die( $ydb->last_error );
if ( defined('YOURLS_DEBUG') && YOURLS_DEBUG === true )
$ydb->show_errors = true;
// return $ydb;
}
@ -375,6 +391,29 @@ function yourls_xml_encode($array) {
return $converter->array2xml($array);
}
// Return long URL associated with keyword. Optional $notfound = string default message if nothing found
function yourls_get_longurl( $keyword, $notfound = false ) {
global $ydb;
$keyword = yourls_sanitize_string( $keyword );
$table = YOURLS_DB_TABLE_URL;
$url = stripslashes($ydb->get_var("SELECT `url` FROM `$table` WHERE `keyword` = '$keyword'"));
if( $url )
return $url;
return $notfound;
}
// Update click count on a short URL
function yourls_update_clicks( $keyword ) {
global $ydb;
$keyword = yourls_sanitize_string( $keyword );
$table = YOURLS_DB_TABLE_URL;
return $ydb->query("UPDATE `$table` SET `clicks` = clicks + 1 WHERE `keyword` = '$keyword'");
}
// Return array for API stat requests
function yourls_api_stats( $filter, $limit ) {
global $ydb;
@ -409,7 +448,7 @@ function yourls_api_stats( $filter, $limit ) {
foreach ($results as $res) {
$return['links']['link_'.$i++] = array(
'shorturl' => YOURLS_SITE .'/'. yourls_int2string($res->id),
'shorturl' => YOURLS_SITE .'/'. $res->keyword,
'url' => $res->url,
'timestamp' => $res->timestamp,
'ip' => $res->ip,
@ -417,12 +456,21 @@ function yourls_api_stats( $filter, $limit ) {
);
}
$totals = $ydb->get_row("SELECT COUNT(id) as c, SUM(clicks) as s FROM $table_url WHERE 1=1");
$return['stats'] = array( 'total_links' => $totals->c, 'total_clicks' => $totals->s );
$return['stats'] = yourls_get_db_stats();
return $return;
}
// Get total number of URLs and sum of clicks. Input: optional "AND WHERE" clause. Returns array
function yourls_get_db_stats( $where = '' ) {
global $ydb;
$table_url = YOURLS_DB_TABLE_URL;
$totals = $ydb->get_row("SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM $table_url WHERE 1=1 $where");
return array( 'total_links' => $totals->count, 'total_clicks' => $totals->sum );
}
// Return API result. Dies after this
function yourls_api_output( $mode, $return ) {
switch ( $mode ) {
@ -464,6 +512,7 @@ function yourls_html_head( $context = 'index' ) {
case 'login':
case 'new':
case 'tools':
case 'upgrade':
$share = false;
$insert = false;
$tablesorter = false;
@ -612,7 +661,7 @@ function yourls_html_tfooter( $params = array() ) {
function yourls_share_box( $longurl, $shorturl, $title='', $text='' ) {
$text = ( $text ? '"'.$text.'" ' : '' );
$title = ( $title ? "$title " : '' );
$share = $title.$text.$shorturl ;
$share = htmlentities( $title.$text.$shorturl );
$_share = rawurlencode( $share );
$_url = rawurlencode( $shorturl );
$count = 140 - strlen( $share );
@ -689,4 +738,296 @@ function yourls_http_build_query($data, $prefix=null, $sep=null, $key='', $urlen
return implode($sep, $ret);
}
//
// Returns a sanitized a user agent string. Given what I found on http://www.user-agents.org/ it should be OK.
function yourls_get_user_agent() {
if ( !isset( $_SERVER['HTTP_USER_AGENT'] ) )
return '-';
$ua = strip_tags( html_entity_decode( $_SERVER['HTTP_USER_AGENT'] ));
$ua = preg_replace('![^0-9a-zA-Z\':., /{}\(\)\[\]\+@&\!\?;_\-=~\*\#]!', '', $ua );
return substr( $ua, 0, 254 );
}
// Redirect to another page
function yourls_redirect( $location, $code = 301 ) {
// Anti fool check: cannot redirect to the URL we currently are on
if( preg_replace('!^[^:]+://!', '', $location) != $_SERVER["SERVER_NAME"].$_SERVER['REQUEST_URI'] ) {
$protocol = $_SERVER["SERVER_PROTOCOL"];
if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
$protocol = 'HTTP/1.0';
$code = intval( $code );
$desc = yourls_get_HTTP_status($code);
if ( php_sapi_name() != 'cgi-fcgi' )
header ("$protocol $code $desc"); // This causes problems on IIS and some FastCGI setups
header("Location: $location");
die();
}
}
// Redirect to another page using Javascript
function yourls_redirect_javascript( $location ) {
echo <<<REDIR
<script type="text/javascript">
//window.location="$location";
</script>
<small>(if you are not redirected after 10 seconds, please <a href="$location">click here</a>)</small>
REDIR;
}
// Return a HTTP status code
function yourls_get_HTTP_status( $code ) {
$code = intval( $code );
$headers_desc = array(
100 => 'Continue',
101 => 'Switching Protocols',
102 => 'Processing',
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
207 => 'Multi-Status',
226 => 'IM Used',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Found',
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
306 => 'Reserved',
307 => 'Temporary Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
402 => 'Payment Required',
403 => 'Forbidden',
404 => 'Not Found',
405 => 'Method Not Allowed',
406 => 'Not Acceptable',
407 => 'Proxy Authentication Required',
408 => 'Request Timeout',
409 => 'Conflict',
410 => 'Gone',
411 => 'Length Required',
412 => 'Precondition Failed',
413 => 'Request Entity Too Large',
414 => 'Request-URI Too Long',
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
422 => 'Unprocessable Entity',
423 => 'Locked',
424 => 'Failed Dependency',
426 => 'Upgrade Required',
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
506 => 'Variant Also Negotiates',
507 => 'Insufficient Storage',
510 => 'Not Extended'
);
if ( isset( $headers_desc[$code] ) )
return $headers_desc[$code];
else
return '';
}
// Log a redirect (for stats)
function yourls_log_redirect( $keyword ) {
global $ydb;
$table = YOURLS_DB_TABLE_LOG;
$keyword = yourls_sanitize_string( $keyword );
$referrer = ( isset( $_SERVER['HTTP_REFERER'] ) ? yourls_sanitize_url( $_SERVER['HTTP_REFERER'] ) : 'direct' );
$ua = yourls_get_user_agent();
$ip = yourls_get_IP();
$location = yourls_get_location( $ip );
return $ydb->query( "INSERT INTO `$table` VALUES ('', NOW(), '$url', '$referrer', '$ua', '$ip', '$location')" );
}
// Converts an IP to a 2 letter country code, using GeoIP database if available in includes/geo/
function yourls_get_location( $ip = '', $default = '' ) {
if ( !file_exists( dirname(__FILE__).'/geo/GeoIP.dat') || !file_exists( dirname(__FILE__).'/geo/geoip.inc') )
return $default;
if ( $ip = '' )
$ip = yourls_get_IP();
require_once( dirname(__FILE__).'/geo/geoip.inc') ;
$gi = geoip_open( dirname(__FILE__).'/geo/GeoIP.dat', GEOIP_STANDARD);
$location = geoip_country_code_by_addr($gi, $ip);
geoip_close($gi);
return $location;
}
// Check if an upgrade is needed
function yourls_upgrade_is_needed() {
// check YOURLS_VERSION && YOURLS_DB_VERSION exist && match values stored in YOURLS_DB_TABLE_OPTIONS
list( $currentver, $currentsql ) = yourls_get_current_version_from_sql();
// Using floatval() to get 1.4 from 1.4-alpha
if( ( $currentver < floatval( YOURLS_VERSION ) ) || ( $currentsql < floatval( YOURLS_DB_VERSION ) ) )
return true;
return false;
}
// Get current version & db version as stored in the options DB
function yourls_get_current_version_from_sql() {
if( !defined('YOURLS_DB_TABLE_OPTIONS') )
die('<p>Your <tt>config.php</tt> does not contain all the required constant definitions. Please check <tt>config-sample.php</tt> and update your config accordingly, there are new stuffs!</p>');
global $ydb;
$table = YOURLS_DB_TABLE_OPTIONS;
$currentver = @$ydb->get_var("SELECT `option_value` FROM $table WHERE `option_name` = 'version'");
$currentsql = @$ydb->get_var("SELECT `option_value` FROM $table WHERE `option_name` = 'db_version'");
if( !$currentver )
$currentver = '1.3';
if( !$currentsql )
$currentsql = '100';
return array( $currentver, $currentsql);
}
// Read an option from DB (or from cache if available). Return value or $default if not found
function yourls_get_option( $option_name, $default = false ) {
if ( !isset( $ydb->option[$option_name] ) ) {
global $ydb;
$table = YOURLS_DB_TABLE_OPTIONS;
$option_name = yourls_escape( $option_name );
$row = $ydb->get_row( "SELECT `option_value` FROM `$table` WHERE `option_name` = '$option_name' LIMIT 1" );
if ( is_object( $row) ) { // Has to be get_row instead of get_var because of funkiness with 0, false, null values
$value = $row->option_value;
} else { // option does not exist, so we must cache its non-existence
$value = $default;
}
$ydb->option[$option_name] = yourls_maybe_unserialize( $value );
}
return $ydb->option[$option_name];
}
// Update (add if doesn't exist) an option to DB
function yourls_update_option( $option_name, $newvalue ) {
global $ydb;
$table = YOURLS_DB_TABLE_OPTIONS;
$safe_option_name = yourls_escape( $option_name );
$newvalue = yourls_escape( $newvalue );
$oldvalue = yourls_get_option( $safe_option_name );
// If the new and old values are the same, no need to update.
if ( $newvalue === $oldvalue )
return false;
if ( false === $oldvalue ) {
yourls_add_option( $option_name, $newvalue );
return true;
}
$_newvalue = yourls_maybe_serialize( $newvalue );
$ydb->query( "UPDATE `$table` SET `option_value` = '$_newvalue' WHERE `option_name` = '$option_name'");
if ( $ydb->rows_affected == 1 ) {
$ydb->option[$option_name] = $newvalue;
return true;
}
return false;
}
// Add an option to the DB
function yourls_add_option( $name, $value = '' ) {
global $ydb;
$table = YOURLS_DB_TABLE_OPTIONS;
$safe_name = yourls_escape( $name );
$value = yourls_escape( $value );
// Make sure the option doesn't already exist. We can check the 'notoptions' cache before we ask for a db query
if ( false !== yourls_get_option( $safe_name ) )
return;
$_value = yourls_maybe_serialize( $value );
$ydb->query( "INSERT INTO `$table` (`option_name`, `option_value`) VALUES ('$name', '$_value')" );
$ydb->option[$name] = $value;
return;
}
// Delete an option from the DB
function yourls_delete_option( $name ) {
global $ydb;
$table = YOURLS_DB_TABLE_OPTIONS;
$name = yourls_escape( $name );
// Get the ID, if no ID then return
$option = $ydb->get_row( "SELECT option_id FROM `$table` WHERE `option_name` = '$name'" );
if ( is_null($option) || !$option->option_id )
return false;
$ydb->query( "DELETE FROM `$table` WHERE `option_name` = '$name'" );
return true;
}
// Serialize data if needed. Stolen from WordPress
function yourls_maybe_serialize( $data ) {
if ( is_array( $data ) || is_object( $data ) )
return serialize( $data );
if ( yourls_is_serialized( $data ) )
return serialize( $data );
return $data;
}
// Check value to find if it was serialized. Stolen from WordPress
function yourls_is_serialized( $data ) {
// if it isn't a string, it isn't serialized
if ( !is_string( $data ) )
return false;
$data = trim( $data );
if ( 'N;' == $data )
return true;
if ( !preg_match( '/^([adObis]):/', $data, $badions ) )
return false;
switch ( $badions[1] ) {
case 'a' :
case 'O' :
case 's' :
if ( preg_match( "/^{$badions[1]}:[0-9]+:.*[;}]\$/s", $data ) )
return true;
break;
case 'b' :
case 'i' :
case 'd' :
if ( preg_match( "/^{$badions[1]}:[0-9.E-]+;\$/", $data ) )
return true;
break;
}
return false;
}
// Unserialize value only if it was serialized. Stolen from WP
function yourls_maybe_unserialize( $original ) {
if ( yourls_is_serialized( $original ) ) // don't attempt to unserialize data that wasn't serialized going in
return @unserialize( $original );
return $original;
}

24
includes/load-yourls.php Normal file
View File

@ -0,0 +1,24 @@
<?php
// This file initialize everything
// Include everything except auth functions
require_once (dirname(__FILE__).'/version.php');
require_once (dirname(__FILE__).'/functions.php');
require_once (dirname(__FILE__).'/functions-baseconvert.php');
require_once (dirname(__FILE__).'/class-mysql.php');
// Create the YOURLS object $ydb that will contain everything we globally need
if ( function_exists( 'yourls_db_connect' ) ) {
global $ydb;
yourls_db_connect();
}
// Read option right from start ?
// TODO: think about it
// Check if upgrade is needed. Note: this is bypassable with define('YOURLS_NO_VERSION_CHECK', true)
if ( !defined('YOURLS_NO_VERSION_CHECK') || YOURLS_NO_VERSION_CHECK != true ) {
if ( yourls_upgrade_is_needed() ) {
yourls_redirect( YOURLS_SITE .'/admin/upgrade.php' );
}
}

View File

@ -1,5 +1,5 @@
<?php
// Bump this when updating the zip package
define('YOURLS_VERSION', '1.3-RC1');
define('YOURLS_VERSION', '1.4-alpha');
define('YOURLS_DB_VERSION', '200');
?>

View File

@ -5,8 +5,8 @@ $(document).ready(function(){
$('#new_url_form').attr('action', 'javascript:add();');
if ($("#tblUrl tr.nourl_found").length != 1) {
$("#tblUrl").tablesorter({
sortList:[[3,1]], // Sort on column #3 (numbering starts at 0)
headers: { 6: {sorter: false} }, // no sorter on column #6
sortList:[[2,1]], // Sort on column #3 (numbering starts at 0)
headers: { 5: {sorter: false} }, // no sorter on column #6
widgets: ['zebra'] // prettify
});
}
@ -43,9 +43,10 @@ function add() {
function edit(id) {
add_loading("#edit-button-" + id);
add_loading("#delete-button-" + id);
var keyword = $('#keyword_'+id).val();
$.getJSON(
"index_ajax.php",
{ mode: "edit_display", id: id },
{ mode: "edit_display", keyword: keyword },
function(data){
$("#id-" + id).after( data.html );
$("#edit-url-"+ id).focus();
@ -60,9 +61,10 @@ function remove(id) {
if (!confirm('Really delete?')) {
return;
}
var keyword = $('#keyword_'+id).val();
$.getJSON(
"index_ajax.php",
{ mode: "delete", id: id },
{ mode: "delete", keyword: keyword },
function(data){
if (data.success == 1) {
$("#id-" + id).fadeOut(function(){$(this).remove();zebra_table();});
@ -85,15 +87,16 @@ function hide_edit(id) {
function edit_save(id) {
add_loading("#edit-close-" + id);
var newurl = $("#edit-url-" + id).val();
var newid = $("#edit-id-" + id).val();
var newkeyword = $("#edit-keyword-" + id).val();
var keyword = $('#old_keyword_'+id).val();
var www = $('#yourls-site').val();
$.getJSON(
"index_ajax.php",
{mode:'edit_save', url: newurl, id: id, newid: newid },
{mode:'edit_save', url: newurl, keyword: keyword, newkeyword: newkeyword },
function(data){
if(data.status == 'success') {
$("#url-" + id).html('<a href="' + data.url.url + '" title="' + data.url.url + '">' + data.url.url + '</a>');
$("#keyword-" + id).html(data.url.keyword);
$("#shorturl-" + id).html('<a href="' + data.url.shorturl + '" title="' + data.url.shorturl + '">' + data.url.shorturl + '</a>');
$("#keyword-" + id).html('<a href="' + data.url.shorturl + '" title="' + data.url.shorturl + '">' + data.url.shorturl + '</a>');
$("#timestamp-" + id).html(data.url.date);
$("#edit-" + id).fadeOut(200, function(){
$('#tblUrl tbody').trigger("update");

View File

@ -12,22 +12,17 @@ if ( !$keyword ) {
exit();
}
$id = yourls_sanitize_int( yourls_string2int($keyword) );
// Get URL From Database
$table = YOURLS_DB_TABLE_URL;
$url = stripslashes($ydb->get_var("SELECT `url` FROM `$table` WHERE id = $id"));
$protocol = $_SERVER["SERVER_PROTOCOL"];
if ( 'HTTP/1.1' != $protocol && 'HTTP/1.0' != $protocol )
$protocol = 'HTTP/1.0';
$url = yourls_get_longurl( $keyword );
// URL found
if(!empty($url)) {
$update_clicks = $ydb->query("UPDATE `$table` SET `clicks` = clicks + 1 WHERE `id` = $id");
header ($protocol.' 301 Moved Permanently');
header ('Location: '. $url);
if( !empty($url) ) {
// Update click count in main table
$update_clicks = yourls_update_clicks( $keyword );
// Update detailed log for stats
$log_redirect = yourls_log_redirect( $keyword );
yourls_redirect( $url, 301 );
// URL not found. Either reserved, or page, or doesn't exist
} else {
@ -38,8 +33,7 @@ if(!empty($url)) {
// Either reserved id, or no such id
} else {
header ($protocol.' 307 Temporary Redirect'); // no 404 to tell browser this might change, and also to not pollute logs
header ('Location: '. YOURLS_SITE);
yourls_redirect( YOURLS_SITE, 307 ); // no 404 to tell browser this might change, and also to not pollute logs
}
}
exit();