= $len ) {
$mod = bcmod( $num, $len );
$num = bcdiv( $num, $len );
$string = $chars[$mod] . $string;
}
$string = $chars[$num] . $string;
return yourls_apply_filter( 'int2string', $string, $num, $chars );
}
// function to convert a string (3jk) to an integer (1337)
function yourls_string2int( $string, $chars = null ) {
if( $chars == null )
$chars = yourls_get_shorturl_charset();
$integer = 0;
$string = strrev( $string );
$baselen = strlen( $chars );
$inputlen = strlen( $string );
for ($i = 0; $i < $inputlen; $i++) {
$index = strpos( $chars, $string[$i] );
$integer = bcadd( $integer, bcmul( $index, bcpow( $baselen, $i ) ) );
}
return yourls_apply_filter( 'string2int', $integer, $string, $chars );
}
// Make sure a link keyword (ie "1fv" as in "site.com/1fv") is valid.
function yourls_sanitize_string( $string ) {
// make a regexp pattern with the shorturl charset, and remove everything but this
$pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() );
$valid = substr(preg_replace('/[^'.$pattern.']/', '', $string ), 0, 199);
return yourls_apply_filter( 'sanitize_string', $valid, $string );
}
// Make an optimized regexp pattern from a string of characters
function yourls_make_regexp_pattern( $string ) {
$pattern = preg_quote( $string, '-' ); // add - as an escaped characters -- this is fixed in PHP 5.3
// TODO: replace char sequences by smart sequences such as 0-9, a-z, A-Z ... ?
return $pattern;
}
// Alias function. I was always getting it wrong.
function yourls_sanitize_keyword( $keyword ) {
return yourls_sanitize_string( $keyword );
}
// Sanitize a page title. No HTML per W3C http://www.w3.org/TR/html401/struct/global.html#h-7.4.2
function yourls_sanitize_title( $title ) {
// TODO: make stronger. Implement KSES?
$title = strip_tags( $title );
return $title;
}
// Is an URL a short URL?
function yourls_is_shorturl( $shorturl ) {
// TODO: make sure this function evolves with the feature set.
$is_short = false;
$keyword = preg_replace( '!^'.YOURLS_SITE.'/!', '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
if( $keyword && $keyword == yourls_sanitize_string( $keyword ) && yourls_keyword_is_taken( $keyword ) ) {
$is_short = true;
}
return yourls_apply_filter( 'is_shorturl', $is_short, $shorturl );
}
// A few sanity checks on the URL
function yourls_sanitize_url($url) {
// make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
$url = str_replace('http://http://', 'http://', $url);
// make sure there's a protocol, add http:// if not
if ( !preg_match('!^([a-zA-Z]+://)!', $url ) )
$url = 'http://'.$url;
$url = yourls_clean_url($url);
return substr( $url, 0, 1999 );
}
// Function to filter all invalid characters from a URL. Stolen from WP's clean_url()
function yourls_clean_url( $url ) {
$url = preg_replace('|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*\'"()\\x80-\\xff]|i', '', $url );
$strip = array('%0d', '%0a', '%0D', '%0A');
$url = yourls_deep_replace($strip, $url);
$url = str_replace(';//', '://', $url);
$url = str_replace('&', '&', $url); // Revert & not to break query strings
return $url;
}
// Perform a replacement while a string is found, eg $subject = '%0%0%0DDD', $search ='%0D' -> $result =''
// Stolen from WP's _deep_replace
function yourls_deep_replace($search, $subject){
$found = true;
while($found) {
$found = false;
foreach( (array) $search as $val ) {
while(strpos($subject, $val) !== false) {
$found = true;
$subject = str_replace($val, '', $subject);
}
}
}
return $subject;
}
// 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) );
}
// Make sure a integer is safe
// Note: this is not checking for integers, since integers on 32bits system are way too limited
// TODO: find a way to validate as integer
function yourls_intval($in) {
return yourls_escape($in);
}
// Escape a string
function yourls_escape( $in ) {
return mysql_real_escape_string($in);
}
// Check to see if a given keyword is reserved (ie reserved URL or an existing page)
// Returns bool
function yourls_keyword_is_reserved( $keyword ) {
global $yourls_reserved_URL;
$keyword = yourls_sanitize_keyword( $keyword );
$reserved = false;
if ( in_array( $keyword, $yourls_reserved_URL)
or file_exists( YOURLS_ABSPATH ."/pages/$keyword.php" )
or is_dir( YOURLS_ABSPATH ."/$keyword" )
)
$reserved = true;
return yourls_apply_filter( 'keyword_is_reserved', $reserved, $keyword );
}
// Function: Get IP Address. Returns a DB safe string.
function yourls_get_IP() {
if( !empty( $_SERVER['REMOTE_ADDR'] ) ) {
$ip = $_SERVER['REMOTE_ADDR'];
} else {
if(!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else if(!empty($_SERVER['HTTP_VIA '])) {
$ip = $_SERVER['HTTP_VIA '];
}
}
return yourls_apply_filter( 'get_IP', yourls_sanitize_ip( $ip ) );
}
// Sanitize an IP address
function yourls_sanitize_ip( $ip ) {
return preg_replace( '/[^0-9a-fA-F:., ]/', '', $ip );
}
// Make sure a date is m(m)/d(d)/yyyy, return false otherwise
function yourls_sanitize_date( $date ) {
if( !preg_match( '!^\d{1,2}/\d{1,2}/\d{4}$!' , $date ) ) {
return false;
}
return $date;
}
// Sanitize a date for SQL search. Return false if malformed input.
function yourls_sanitize_date_for_sql( $date ) {
if( !yourls_sanitize_date( $date ) )
return false;
return date('Y-m-d', strtotime( $date ) );
}
// Add the "Edit" row
function yourls_table_edit_row( $keyword ) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$keyword = yourls_sanitize_string( $keyword );
$id = yourls_string2int( $keyword ); // used as HTML #id
$url = yourls_get_keyword_longurl( $keyword );
$title = yourls_get_keyword_title( $keyword );
$safe_url = stripslashes( $url );
$safe_title = stripslashes( $title );
$www = YOURLS_SITE;
if( $url ) {
$return = <<Original URL: Short URL: $www/
Title:
RETURN;
} else {
$return = ' ';
}
$return = yourls_apply_filter( 'table_edit_row', $return, $keyword, $url, $title );
return $return;
}
// Add a link row
function yourls_table_add_row( $keyword, $url, $title = '', $ip, $clicks, $timestamp ) {
$keyword = yourls_sanitize_string( $keyword );
$display_keyword = htmlentities( $keyword );
$url = yourls_sanitize_url( $url );
$display_url = htmlentities( yourls_trim_long_string( $url ) );
$title = yourls_sanitize_title( $title ) ;
$display_title = htmlentities( yourls_trim_long_string( $title ), ENT_QUOTES, 'UTF-8' );
$id = yourls_string2int( $keyword ); // used as HTML #id
$date = date( 'M d, Y H:i', $timestamp+( YOURLS_HOURS_OFFSET * 3600) );
$clicks = number_format($clicks, 0, '', '');
$shorturl = YOURLS_SITE.'/'.$keyword;
$statlink = $shorturl.'+';
if( $title ) {
$display_link = "$display_titleError, URL not found
$display_url";
} else {
$display_link = "$display_url";
}
$actions = <<$display_keyword $display_link $date $ip $clicks $actions
ROW;
$row = yourls_apply_filter( 'table_add_row', $row, $keyword, $url, $title, $ip, $clicks, $timestamp );
return $row;
}
// Get next id a new link will have if no custom keyword provided
function yourls_get_next_decimal() {
return yourls_apply_filter( 'get_next_decimal', (int)yourls_get_option( 'next_id' ) );
}
// Update id for next link with no custom keyword
function yourls_update_next_decimal( $int = '' ) {
$int = ( $int == '' ) ? yourls_get_next_decimal() + 1 : (int)$int ;
$update = yourls_update_option( 'next_id', $int );
yourls_do_action( 'update_next_decimal', $int, $update );
return $update;
}
// Delete a link in the DB
function yourls_delete_link_by_keyword( $keyword ) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$keyword = yourls_sanitize_string( $keyword );
$delete = $ydb->query("DELETE FROM `$table` WHERE `keyword` = '$keyword';");
yourls_do_action( 'delete_link', $keyword, $delete );
return $delete;
}
// SQL query to insert a new link in the DB. Returns boolean for success or failure of the inserting
function yourls_insert_link_in_db( $url, $keyword, $title = '' ) {
global $ydb;
$url = addslashes( yourls_sanitize_url( $url ) );
$keyword = addslashes( yourls_sanitize_keyword( $keyword ) );
$title = addslashes( yourls_sanitize_title( $title ) );
$table = YOURLS_DB_TABLE_URL;
$timestamp = date('Y-m-d H:i:s');
$ip = yourls_get_IP();
$insert = $ydb->query("INSERT INTO `$table` VALUES('$keyword', '$url', '$title', '$timestamp', '$ip', 0);");
yourls_do_action( 'insert_link', (bool)$insert, $url, $keyword, $title, $timestamp, $ip );
return (bool)$insert;
}
// Add a new link in the DB, either with custom keyword, or find one
function yourls_add_new_link( $url, $keyword = '', $title = '' ) {
global $ydb;
if ( !$url || $url == 'http://' || $url == 'https://' ) {
$return['status'] = 'fail';
$return['code'] = 'error:nourl';
$return['message'] = 'Missing URL input';
$return['errorCode'] = '400';
yourls_do_action( 'add_new_link_fail_nourl' );
return $return;
}
// Prevent DB flood
$ip = yourls_get_IP();
yourls_check_IP_flood( $ip );
// Prevent internal redirection loops: cannot shorten a shortened URL
$url = yourls_escape( yourls_sanitize_url($url) );
if( preg_match( '!^'.YOURLS_SITE.'/!', $url ) ) {
if( yourls_is_shorturl( $url ) ) {
$return['status'] = 'fail';
$return['code'] = 'error:noloop';
$return['message'] = 'URL is a short URL';
$return['errorCode'] = '400';
yourls_do_action( 'add_new_link_fail_noloop' );
return $return;
}
}
yourls_do_action( 'pre_add_new_link', $url, $keyword );
$table = YOURLS_DB_TABLE_URL;
$strip_url = stripslashes($url);
$url_exists = $ydb->get_row("SELECT * FROM `$table` WHERE `url` = '".$strip_url."';");
$return = array();
// New URL : store it -- or: URL exists, but duplicates allowed
if( !$url_exists || yourls_allow_duplicate_longurls() ) {
if( isset( $title ) && !empty( $title ) ) {
$title = yourls_sanitize_title( $title );
} else {
$title = yourls_get_remote_title( $url );
}
// Custom keyword provided
if ( $keyword ) {
$keyword = yourls_escape( yourls_sanitize_string($keyword) );
$keyword = yourls_apply_filter( 'custom_keyword', $keyword );
if ( !yourls_keyword_is_free($keyword) ) {
// This shorturl either reserved or taken already
$return['status'] = 'fail';
$return['code'] = 'error:keyword';
$return['message'] = 'Short URL '.$keyword.' already exists in database or is reserved';
} else {
// all clear, store !
yourls_insert_link_in_db( $url, $keyword, $title );
$return['url'] = array('keyword' => $keyword, 'url' => $strip_url, 'title' => $title, 'date' => date('Y-m-d H:i:s'), 'ip' => $ip );
$return['status'] = 'success';
$return['message'] = yourls_trim_long_string( $strip_url ).' added to database';
$return['title'] = $title;
$return['html'] = yourls_table_add_row( $keyword, $url, $title, $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();
$ok = false;
do {
$keyword = yourls_int2string( $id );
$keyword = yourls_apply_filter( 'random_keyword', $keyword );
$free = yourls_keyword_is_free($keyword);
$add_url = @yourls_insert_link_in_db( $url, $keyword, $title );
$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_keyword( $keyword );
$return['extra_info'] .= '(deleted '.$keyword.')';
} else {
// everything ok, populate needed vars
$return['url'] = array('keyword' => $keyword, 'url' => $strip_url, 'title' => $title, 'date' => $timestamp, 'ip' => $ip );
$return['status'] = 'success';
$return['message'] = yourls_trim_long_string( $strip_url ).' added to database';
$return['title'] = $title;
$return['html'] = yourls_table_add_row( $keyword, $url, $title, $ip, 0, time() );
$return['shorturl'] = YOURLS_SITE .'/'. $keyword;
}
$id++;
} while (!$ok);
@yourls_update_next_decimal($id);
}
// URL was already stored
} else {
$return['status'] = 'fail';
$return['code'] = 'error:url';
$return['url'] = array( 'keyword' => $keyword, 'url' => $strip_url, 'title' => $url_exists->title, 'date' => $url_exists->timestamp, 'ip' => $url_exists->ip, 'clicks' => $url_exists->clicks );
$return['message'] = yourls_trim_long_string( $strip_url ).' already exists in database';
$return['title'] = $url_exists->title;
$return['shorturl'] = YOURLS_SITE .'/'. $url_exists->keyword;
}
yourls_do_action( 'post_add_new_link', $url, $keyword );
$return['statusCode'] = 200; // regardless of result, this is still a valid request
return $return;
}
// Edit a link
function yourls_edit_link( $url, $keyword, $newkeyword='', $title='' ) {
global $ydb;
$table = YOURLS_DB_TABLE_URL;
$url = yourls_escape(yourls_sanitize_url($url));
$keyword = yourls_escape(yourls_sanitize_string( $keyword ));
$title = yourls_escape(yourls_sanitize_title( $title ));
$newkeyword = yourls_escape(yourls_sanitize_string( $newkeyword ));
$strip_url = stripslashes($url);
$strip_title = stripslashes($title);
$old_url = $ydb->get_var("SELECT `url` FROM `$table` WHERE `keyword` = '$keyword';");
$old_id = $id = yourls_string2int( $keyword );
$new_id = ( $newkeyword == '' ? $old_id : yourls_string2int( $newkeyword ) );
// Check if new URL is not here already
if ( $old_url != $url && !yourls_allow_duplicate_longurls() ) {
$new_url_already_there = intval($ydb->get_var("SELECT COUNT(keyword) FROM `$table` WHERE `url` = '$strip_url';"));
} else {
$new_url_already_there = false;
}
// Check if the new keyword is not here already
if ( $newkeyword != $keyword ) {
$keyword_is_ok = yourls_keyword_is_free( $newkeyword );
} else {
$keyword_is_ok = true;
}
yourls_do_action( 'pre_edit_link', $url, $keyword, $newkeyword, $new_url_already_there, $keyword_is_ok );
// All clear, update
if ( ( !$new_url_already_there || yourls_allow_duplicate_longurls() ) && $keyword_is_ok ) {
$update_url = $ydb->query("UPDATE `$table` SET `url` = '$url', `keyword` = '$newkeyword', `title` = '$title' WHERE `keyword` = '$keyword';");
if( $update_url ) {
$return['url'] = array( 'keyword' => $newkeyword, 'shorturl' => YOURLS_SITE.'/'.$newkeyword, 'url' => $strip_url, 'display_url' => yourls_trim_long_string( $strip_url ), 'new_id' => $new_id, 'title' => $strip_title, 'display_title' => yourls_trim_long_string( $strip_title ) );
$return['status'] = 'success';
$return['message'] = 'Link updated in database';
} else {
$return['status'] = 'fail';
$return['message'] = 'Error updating '. yourls_trim_long_string( $strip_url ).' (Short URL: '.$keyword.') to database';
}
// Nope
} else {
$return['status'] = 'fail';
$return['message'] = 'URL or keyword already exists in database';
}
return yourls_apply_filter( 'edit_link', $return, $url, $keyword, $newkeyword, $title, $new_url_already_there, $keyword_is_ok );
}
// Update a title link (no checks for duplicates etc..)
function yourls_edit_link_title( $keyword, $title ) {
global $ydb;
$keyword = yourls_escape( yourls_sanitize_keyword( $keyword ) );
$title = yourls_escape( yourls_sanitize_title( $title ) );
$table = YOURLS_DB_TABLE_URL;
$update = $ydb->query("UPDATE `$table` SET `title` = '$title' WHERE `keyword` = '$keyword';");
return $update;
}
// Check if keyword id is free (ie not already taken, and not reserved). Return bool.
function yourls_keyword_is_free( $keyword ) {
$free = true;
if ( yourls_keyword_is_reserved( $keyword ) or yourls_keyword_is_taken( $keyword ) )
$free = false;
return yourls_apply_filter( 'keyword_is_free', $free, $keyword );
}
// Check if a keyword is taken (ie there is already a short URL with this id). Return bool.
function yourls_keyword_is_taken( $keyword ) {
global $ydb;
$keyword = yourls_sanitize_keyword( $keyword );
$taken = false;
$table = YOURLS_DB_TABLE_URL;
$already_exists = $ydb->get_var("SELECT COUNT(`keyword`) FROM `$table` WHERE `keyword` = '$keyword';");
if ( $already_exists )
$taken = true;
return yourls_apply_filter( 'keyword_is_taken', $taken, $keyword );
}
// Display a page
function yourls_page( $page ) {
$include = YOURLS_ABSPATH . "/pages/$page.php";
if (!file_exists($include)) {
yourls_die("Page '$page' not found", 'Not found', 404);
}
yourls_do_action( 'pre_page', $page );
include($include);
yourls_do_action( 'post_page', $page );
die();
}
// Connect to DB
function yourls_db_connect() {
global $ydb;
if (!defined('YOURLS_DB_USER')
or !defined('YOURLS_DB_PASS')
or !defined('YOURLS_DB_NAME')
or !defined('YOURLS_DB_HOST')
or !class_exists('ezSQL_mysql')
) yourls_die ('DB config missing, or could not find DB class', 'Fatal error', 503);
// Are we standalone or in the WordPress environment?
if ( class_exists('wpdb') ) {
$ydb = new wpdb(YOURLS_DB_USER, YOURLS_DB_PASS, YOURLS_DB_NAME, YOURLS_DB_HOST);
} else {
$ydb = new ezSQL_mysql(YOURLS_DB_USER, YOURLS_DB_PASS, YOURLS_DB_NAME, YOURLS_DB_HOST);
}
if ( $ydb->last_error )
yourls_die( $ydb->last_error, 'Fatal error', 503 );
if ( defined('YOURLS_DEBUG') && YOURLS_DEBUG === true )
$ydb->show_errors = true;
return $ydb;
}
// Return XML output.
function yourls_xml_encode($array) {
require_once(YOURLS_INC.'/functions-xml.php');
$converter= new yourls_array2xml;
return $converter->array2xml($array);
}
// Return array of all informations associated with keyword. Returns false if keyword not found. Set optional $use_cache to false to force fetching from DB
function yourls_get_keyword_infos( $keyword, $use_cache = true ) {
global $ydb;
$keyword = yourls_sanitize_string( $keyword );
yourls_do_action( 'pre_get_keyword', $keyword, $use_cache );
if( isset( $ydb->infos[$keyword] ) && $use_cache == true ) {
return yourls_apply_filter( 'get_keyword_infos', $ydb->infos[$keyword], $keyword );
}
yourls_do_action( 'get_keyword_not_cached', $keyword );
$table = YOURLS_DB_TABLE_URL;
$infos = $ydb->get_row("SELECT * FROM `$table` WHERE `keyword` = '$keyword'");
if( $infos ) {
$infos = (array)$infos;
$ydb->infos[$keyword] = $infos;
} else {
$ydb->infos[$keyword] = false;
}
return yourls_apply_filter( 'get_keyword_infos', $ydb->infos[$keyword], $keyword );
}
// Return (string) selected information associated with a keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_info( $keyword, $field, $notfound = false ) {
$keyword = yourls_sanitize_string( $keyword );
$infos = yourls_get_keyword_infos( $keyword );
$return = $notfound;
if ( isset($infos[$field]) && $infos[$field] !== false )
$return = $infos[$field];
return yourls_apply_filter( 'get_keyword_info', $return, $keyword, $field, $notfound );
}
// Return title associated with keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_title( $keyword, $notfound = false ) {
return yourls_get_keyword_info( $keyword, 'title', $notfound );
}
// Return long URL associated with keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_longurl( $keyword, $notfound = false ) {
return yourls_get_keyword_info( $keyword, 'url', $notfound );
}
// Return number of clicks on a keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_clicks( $keyword, $notfound = false ) {
return yourls_get_keyword_info( $keyword, 'clicks', $notfound );
}
// Return IP that added a keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_IP( $keyword, $notfound = false ) {
return yourls_get_keyword_info( $keyword, 'ip', $notfound );
}
// Return timestamp associated with a keyword. Optional $notfound = string default message if nothing found
function yourls_get_keyword_timestamp( $keyword, $notfound = false ) {
return yourls_get_keyword_info( $keyword, 'timestamp', $notfound );
}
// Update click count on a short URL. Return 0/1 for error/success.
function yourls_update_clicks( $keyword ) {
global $ydb;
$keyword = yourls_sanitize_string( $keyword );
$table = YOURLS_DB_TABLE_URL;
$update = $ydb->query("UPDATE `$table` SET `clicks` = clicks + 1 WHERE `keyword` = '$keyword'");
yourls_do_action( 'update_clicks', $keyword, $update );
return $update;
}
// Return array of stats. (string)$filter is 'bottom', 'last', 'rand' or 'top'. (int)$limit is the number of links to return
function yourls_get_stats( $filter = 'top', $limit = 10 ) {
global $ydb;
switch( $filter ) {
case 'bottom':
$sort_by = 'clicks';
$sort_order = 'asc';
break;
case 'last':
$sort_by = 'timestamp';
$sort_order = 'desc';
break;
case 'rand':
case 'random':
$sort_by = 'RAND()';
$sort_order = '';
break;
case 'top':
default:
$sort_by = 'clicks';
$sort_order = 'desc';
break;
}
// Fetch links
$limit = intval( $limit );
if ( $limit > 0 ) {
$table_url = YOURLS_DB_TABLE_URL;
$results = $ydb->get_results("SELECT * FROM `$table_url` WHERE 1=1 ORDER BY `$sort_by` $sort_order LIMIT 0, $limit;");
$return = array();
$i = 1;
foreach ( (array)$results as $res) {
$return['links']['link_'.$i++] = array(
'shorturl' => YOURLS_SITE .'/'. $res->keyword,
'url' => $res->url,
'title' => $res->title,
'timestamp'=> $res->timestamp,
'ip' => $res->ip,
'clicks' => $res->clicks,
);
}
}
$return['stats'] = yourls_get_db_stats();
$return['statusCode'] = 200;
return yourls_apply_filter( 'get_stats', $return, $filter, $limit );
}
// Return array of stats. (string)$filter is 'bottom', 'last', 'rand' or 'top'. (int)$limit is the number of links to return
function yourls_get_link_stats( $shorturl ) {
global $ydb;
$table_url = YOURLS_DB_TABLE_URL;
$res = $ydb->get_row("SELECT * FROM `$table_url` WHERE keyword = '$shorturl';");
$return = array();
if( !$res ) {
// non existent link
$return = array(
'statusCode' => 404,
'message' => 'Error: short URL not found',
);
} else {
$return = array(
'statusCode' => 200,
'message' => 'success',
'link' => array(
'shorturl' => YOURLS_SITE .'/'. $res->keyword,
'url' => $res->url,
'title' => $res->title,
'timestamp'=> $res->timestamp,
'ip' => $res->ip,
'clicks' => $res->clicks,
)
);
}
return yourls_apply_filter( 'get_link_stats', $return, $shorturl );
}
// Return array for API stat requests
function yourls_api_stats( $filter = 'top', $limit = 10 ) {
$return = yourls_get_stats( $filter, $limit );
$return['simple'] = 'Need either XML or JSON format for stats';
$return['message'] = 'success';
return yourls_apply_filter( 'api_stats', $return, $filter, $limit );
}
// Return array for API stat requests
function yourls_api_url_stats($shorturl) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$return = yourls_get_link_stats( $keyword );
$return['simple'] = 'Need either XML or JSON format for stats';
return yourls_apply_filter( 'api_url_stats', $return, $shorturl );
}
// Expand short url to long url
function yourls_api_expand( $shorturl ) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$longurl = yourls_get_keyword_longurl( $keyword );
if( $longurl ) {
$return = array(
'keyword' => $keyword,
'shorturl' => YOURLS_SITE . "/$keyword",
'longurl' => $longurl,
'simple' => $longurl,
'message' => 'success',
'statusCode' => 200,
);
} else {
$return = array(
'keyword' => $keyword,
'simple' => 'not found',
'message' => 'Error: short URL not found',
'errorCode' => 404,
);
}
return yourls_apply_filter( 'api_expand', $return, $shorturl );
}
// 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 yourls_apply_filter( 'get_db_stats', $return, $where );
}
// Return API result. Dies after this
function yourls_api_output( $mode, $return ) {
if( isset( $return['simple'] ) ) {
$simple = $return['simple'];
unset( $return['simple'] );
}
yourls_do_action( 'pre_api_output', $mode, $return );
switch ( $mode ) {
case 'json':
header('Content-type: application/json');
echo json_encode($return);
break;
case 'xml':
header('Content-type: application/xml');
echo yourls_xml_encode($return);
break;
case 'simple':
default:
if( isset( $simple ) )
echo $simple;
break;
}
yourls_do_action( 'api_output', $mode, $return );
die();
}
// Get number of SQL queries performed
function yourls_get_num_queries() {
global $ydb;
return yourls_apply_filter( 'get_num_queries', $ydb->num_queries );
}
// 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 yourls_apply_filter( 'get_user_agent', substr( $ua, 0, 254 ) );
}
// Redirect to another page
function yourls_redirect( $location, $code = 301 ) {
yourls_do_action( 'pre_redirect', $location, $code );
// Redirect, either properly if possible, or via Javascript otherwise
if( !headers_sent() ) {
yourls_status_header( $code );
header("Location: $location");
} else {
yourls_redirect_javascript( $location );
}
die();
}
// Set HTTP status header
function yourls_status_header( $code = 200 ) {
if( headers_sent() )
return;
$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);
@header ("$protocol $code $desc"); // This causes problems on IIS and some FastCGI setups
yourls_do_action( 'status_header', $code );
}
// Redirect to another page using Javascript. Set optional (bool)$dontwait to false to force manual redirection (make sure a message has been read by user)
function yourls_redirect_javascript( $location, $dontwait = true ) {
if( $dontwait ) {
echo <<
Things should not last very long, thank you for your patience and please excuse the inconvenience'; yourls_die( $message, $title , 503 ); } } // Toggle maintenance mode function yourls_maintenance_mode( $maintenance = true ) { yourls_update_option( 'maintenance_mode', (bool)$maintenance ); } // Check if a string seems to be UTF-8. Stolen from WP. function yourls_seems_utf8($str) { $length = strlen($str); for ($i=0; $i < $length; $i++) { $c = ord($str[$i]); if ($c < 0x80) $n = 0; # 0bbbbbbb elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b else return false; # Does not match any model for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ? if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80)) return false; } } return true; }