2013-04-07 12:52:52 +02:00
< ? php
/*
* YOURLS
* Function library
*/
/**
* Determine the allowed character set in short URLs
2017-06-20 23:12:04 +02:00
*
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_shorturl_charset () {
static $charset = null ;
if ( $charset !== null )
return $charset ;
2014-02-02 19:07:14 +01:00
2014-02-02 20:30:57 +01:00
if ( defined ( 'YOURLS_URL_CONVERT' ) && in_array ( YOURLS_URL_CONVERT , array ( 62 , 64 ) ) ) {
$charset = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' ;
} else {
2017-06-20 23:12:04 +02:00
// defined to 36, or wrongly defined
2014-02-02 20:30:57 +01:00
$charset = '0123456789abcdefghijklmnopqrstuvwxyz' ;
}
2013-04-07 12:52:52 +02:00
$charset = yourls_apply_filter ( 'get_shorturl_charset' , $charset );
return $charset ;
}
2017-06-20 23:12:04 +02:00
2013-02-13 09:45:33 +00:00
/**
* Make an optimized regexp pattern from a string of characters
2017-06-20 23:12:04 +02:00
*
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_make_regexp_pattern ( $string ) {
2017-04-02 18:29:31 +02:00
$pattern = preg_quote ( $string , '@' ); // add @ as an escaped character because @ is used as the regexp delimiter in yourls-loader.php
2014-11-05 17:13:16 +01:00
// Simple benchmarks show that regexp with smarter sequences (0-9, a-z, A-Z...) are not faster or slower than 0123456789 etc...
2013-04-07 12:52:52 +02:00
return $pattern ;
}
2013-02-13 09:45:33 +00:00
/**
2013-05-01 00:17:54 +02:00
* Is a URL a short URL ? Accept either 'http://sho.rt/abc' or 'abc'
2017-06-20 23:12:04 +02:00
*
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_is_shorturl ( $shorturl ) {
// TODO: make sure this function evolves with the feature set.
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$is_short = false ;
2017-06-20 23:12:04 +02:00
2013-05-01 00:17:54 +02:00
// Is $shorturl a URL (http://sho.rt/abc) or a keyword (abc) ?
if ( yourls_get_protocol ( $shorturl ) ) {
$keyword = yourls_get_relative_url ( $shorturl );
} else {
$keyword = $shorturl ;
}
2017-06-20 23:12:04 +02:00
2013-05-01 00:17:54 +02:00
// Check if it's a valid && used keyword
2013-04-07 12:52:52 +02:00
if ( $keyword && $keyword == yourls_sanitize_string ( $keyword ) && yourls_keyword_is_taken ( $keyword ) ) {
$is_short = true ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'is_shorturl' , $is_short , $shorturl );
}
2013-02-13 09:45:33 +00:00
/**
* Check to see if a given keyword is reserved ( ie reserved URL or an existing page ) . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_keyword_is_reserved ( $keyword ) {
global $yourls_reserved_URL ;
$keyword = yourls_sanitize_keyword ( $keyword );
$reserved = false ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( in_array ( $keyword , $yourls_reserved_URL )
2020-04-18 15:43:33 +02:00
or file_exists ( YOURLS_PAGEDIR . " / $keyword .php " )
2013-04-07 12:52:52 +02:00
or is_dir ( YOURLS_ABSPATH . " / $keyword " )
)
$reserved = true ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'keyword_is_reserved' , $reserved , $keyword );
}
2013-02-13 09:45:33 +00:00
/**
* Function : Get client IP Address . Returns a DB safe string .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_IP () {
2013-05-03 17:48:23 +02:00
$ip = '' ;
2013-04-07 12:52:52 +02:00
// Precedence: if set, X-Forwarded-For > HTTP_X_FORWARDED_FOR > HTTP_CLIENT_IP > HTTP_VIA > REMOTE_ADDR
$headers = array ( 'X-Forwarded-For' , 'HTTP_X_FORWARDED_FOR' , 'HTTP_CLIENT_IP' , 'HTTP_VIA' , 'REMOTE_ADDR' );
foreach ( $headers as $header ) {
if ( ! empty ( $_SERVER [ $header ] ) ) {
$ip = $_SERVER [ $header ];
break ;
}
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// headers can contain multiple IPs (X-Forwarded-For = client, proxy1, proxy2). Take first one.
if ( strpos ( $ip , ',' ) !== false )
$ip = substr ( $ip , 0 , strpos ( $ip , ',' ) );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'get_IP' , yourls_sanitize_ip ( $ip ) );
}
2013-02-13 09:45:33 +00:00
/**
* Get next id a new link will have if no custom keyword provided
*
2020-03-31 18:00:05 +02:00
* @ since 1.0
* @ return int id of next link
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_next_decimal () {
return yourls_apply_filter ( 'get_next_decimal' , ( int ) yourls_get_option ( 'next_id' ) );
}
2013-02-13 09:45:33 +00:00
/**
* Update id for next link with no custom keyword
*
2020-03-31 18:00:05 +02:00
* Note : this function relies upon yourls_update_option (), which will return either true or false
* depending if there has been an actual MySQL query updating the DB .
* In other words , this function may return false yet this would not mean it has functionnaly failed
* In other words I ' m not sure we really need this function to return something : face_with_eyes_looking_up :
* See issue 2621 for more on this .
*
* @ since 1.0
* @ param integer $int id for next link
* @ return bool true or false depending on if there has been an actual MySQL query . See note above .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
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 ;
}
2013-02-13 09:45:33 +00:00
/**
* Delete a link in the DB
*
*/
2013-04-07 12:52:52 +02:00
function yourls_delete_link_by_keyword ( $keyword ) {
2013-12-30 19:35:50 +01:00
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_delete_link_by_keyword' , null , $keyword );
if ( null !== $pre )
return $pre ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
global $ydb ;
$table = YOURLS_DB_TABLE_URL ;
2017-09-02 19:09:56 +02:00
$keyword = yourls_sanitize_string ( $keyword );
$delete = $ydb -> fetchAffected ( " DELETE FROM ` $table ` WHERE `keyword` = :keyword " , array ( 'keyword' => $keyword ));
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'delete_link' , $keyword , $delete );
return $delete ;
}
2013-02-13 09:45:33 +00:00
/**
* SQL query to insert a new link in the DB . Returns boolean for success or failure of the inserting
*
*/
2013-04-07 12:52:52 +02:00
function yourls_insert_link_in_db ( $url , $keyword , $title = '' ) {
global $ydb ;
2017-06-20 23:12:04 +02:00
2017-09-02 19:09:56 +02:00
$url = yourls_sanitize_url ( $url );
$keyword = yourls_sanitize_keyword ( $keyword );
$title = yourls_sanitize_title ( $title );
$timestamp = date ( 'Y-m-d H:i:s' );
$ip = yourls_get_IP ();
$table = YOURLS_DB_TABLE_URL ;
$binds = array (
'keyword' => $keyword ,
'url' => $url ,
'title' => $title ,
'timestamp' => $timestamp ,
'ip' => $ip ,
);
$insert = $ydb -> fetchAffected ( " INSERT INTO ` $table ` (`keyword`, `url`, `title`, `timestamp`, `ip`, `clicks`) VALUES(:keyword, :url, :title, :timestamp, :ip, 0); " , $binds );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'insert_link' , ( bool ) $insert , $url , $keyword , $title , $timestamp , $ip );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return ( bool ) $insert ;
}
2013-02-13 09:45:33 +00:00
/**
2017-08-31 21:03:59 +02:00
* Check if a long URL already exists in the DB . Return NULL ( doesn ' t exist ) or an object with URL informations .
2013-02-13 09:45:33 +00:00
*
2017-08-31 21:03:59 +02:00
* @ since 1.5 . 1
* @ param string $url URL to check if already shortened
* @ return mixed NULL if does not already exist in DB , or object with URL information as properties ( eg keyword , url , title , ... )
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_url_exists ( $url ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_url_exists' , false , $url );
if ( false !== $pre )
return $pre ;
global $ydb ;
$table = YOURLS_DB_TABLE_URL ;
2017-08-31 21:03:59 +02:00
$url = yourls_sanitize_url ( $url );
$url_exists = $ydb -> fetchObject ( " SELECT * FROM ` $table ` WHERE `url` = :url " , array ( 'url' => $url ));
2017-06-20 23:12:04 +02:00
2017-09-02 19:09:56 +02:00
if ( $url_exists === false ) {
$url_exists = NULL ;
}
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'url_exists' , $url_exists , $url );
}
2013-02-13 09:45:33 +00:00
/**
* Add a new link in the DB , either with custom keyword , or find one
*
*/
2013-04-07 12:52:52 +02:00
function yourls_add_new_link ( $url , $keyword = '' , $title = '' ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_add_new_link' , false , $url , $keyword , $title );
if ( false !== $pre )
return $pre ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$url = yourls_encodeURI ( $url );
2017-09-02 19:09:56 +02:00
$url = yourls_sanitize_url ( $url );
2013-04-07 12:52:52 +02:00
if ( ! $url || $url == 'http://' || $url == 'https://' ) {
$return [ 'status' ] = 'fail' ;
$return [ 'code' ] = 'error:nourl' ;
$return [ 'message' ] = yourls__ ( 'Missing or malformed URL' );
$return [ 'errorCode' ] = '400' ;
return yourls_apply_filter ( 'add_new_link_fail_nourl' , $return , $url , $keyword , $title );
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Prevent DB flood
$ip = yourls_get_IP ();
yourls_check_IP_flood ( $ip );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Prevent internal redirection loops: cannot shorten a shortened URL
if ( yourls_get_relative_url ( $url ) ) {
if ( yourls_is_shorturl ( $url ) ) {
$return [ 'status' ] = 'fail' ;
$return [ 'code' ] = 'error:noloop' ;
$return [ 'message' ] = yourls__ ( 'URL is a short URL' );
$return [ 'errorCode' ] = '400' ;
return yourls_apply_filter ( 'add_new_link_fail_noloop' , $return , $url , $keyword , $title );
}
}
yourls_do_action ( 'pre_add_new_link' , $url , $keyword , $title );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$strip_url = stripslashes ( $url );
$return = array ();
// duplicates allowed or new URL => store it
if ( yourls_allow_duplicate_longurls () || ! ( $url_exists = yourls_url_exists ( $url ) ) ) {
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( isset ( $title ) && ! empty ( $title ) ) {
$title = yourls_sanitize_title ( $title );
} else {
$title = yourls_get_remote_title ( $url );
}
$title = yourls_apply_filter ( 'add_new_title' , $title , $url , $keyword );
// Custom keyword provided
if ( $keyword ) {
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'add_new_link_custom_keyword' , $url , $keyword , $title );
2017-06-20 23:12:04 +02:00
2017-09-02 19:09:56 +02:00
$keyword = yourls_sanitize_string ( $keyword );
2013-04-07 12:52:52 +02:00
$keyword = yourls_apply_filter ( 'custom_keyword' , $keyword , $url , $title );
if ( ! yourls_keyword_is_free ( $keyword ) ) {
// This shorturl either reserved or taken already
$return [ 'status' ] = 'fail' ;
$return [ 'code' ] = 'error:keyword' ;
$return [ 'message' ] = yourls_s ( 'Short URL %s already exists in database or is reserved' , $keyword );
} 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' ] = /* //translators: eg "http://someurl/ added to DB" */ yourls_s ( '%s added to database' , yourls_trim_long_string ( $strip_url ) );
$return [ 'title' ] = $title ;
$return [ 'html' ] = yourls_table_add_row ( $keyword , $url , $title , $ip , 0 , time () );
$return [ 'shorturl' ] = YOURLS_SITE . '/' . $keyword ;
}
2017-06-20 23:12:04 +02:00
// Create random keyword
2013-04-07 12:52:52 +02:00
} else {
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'add_new_link_create_keyword' , $url , $keyword , $title );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$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 , $url , $title );
2013-05-14 19:47:55 +02:00
if ( yourls_keyword_is_free ( $keyword ) ) {
2017-09-02 19:09:56 +02:00
if ( yourls_insert_link_in_db ( $url , $keyword , $title )){
2013-05-14 19:47:55 +02:00
// everything ok, populate needed vars
$return [ 'url' ] = array ( 'keyword' => $keyword , 'url' => $strip_url , 'title' => $title , 'date' => $timestamp , 'ip' => $ip );
$return [ 'status' ] = 'success' ;
$return [ 'message' ] = /* //translators: eg "http://someurl/ added to DB" */ yourls_s ( '%s added to database' , yourls_trim_long_string ( $strip_url ) );
$return [ 'title' ] = $title ;
$return [ 'html' ] = yourls_table_add_row ( $keyword , $url , $title , $ip , 0 , time () );
$return [ 'shorturl' ] = YOURLS_SITE . '/' . $keyword ;
2017-09-02 19:09:56 +02:00
} else {
2013-06-06 17:53:31 +02:00
// database error, couldnt store result
2013-05-14 19:47:55 +02:00
$return [ 'status' ] = 'fail' ;
$return [ 'code' ] = 'error:db' ;
2013-06-06 17:53:31 +02:00
$return [ 'message' ] = yourls_s ( 'Error saving url to database' );
2013-05-14 19:47:55 +02:00
}
$ok = true ;
2013-04-07 12:52:52 +02:00
}
$id ++ ;
} while ( ! $ok );
@ yourls_update_next_decimal ( $id );
}
// URL was already stored
} else {
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'add_new_link_already_stored' , $url , $keyword , $title );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$return [ 'status' ] = 'fail' ;
$return [ 'code' ] = 'error:url' ;
$return [ 'url' ] = array ( 'keyword' => $url_exists -> keyword , 'url' => $strip_url , 'title' => $url_exists -> title , 'date' => $url_exists -> timestamp , 'ip' => $url_exists -> ip , 'clicks' => $url_exists -> clicks );
2014-05-06 14:08:49 +02:00
$return [ 'message' ] = /* //translators: eg "http://someurl/ already exists" */ yourls_s ( '%s already exists in database' , yourls_trim_long_string ( $strip_url ) );
2017-06-20 23:12:04 +02:00
$return [ 'title' ] = $url_exists -> title ;
2014-05-06 14:08:49 +02:00
$return [ 'shorturl' ] = YOURLS_SITE . '/' . $url_exists -> keyword ;
2013-04-07 12:52:52 +02:00
}
2017-06-20 23:12:04 +02:00
2018-10-26 09:48:12 +03:00
yourls_do_action ( 'post_add_new_link' , $url , $keyword , $title , $return );
2013-04-07 12:52:52 +02:00
$return [ 'statusCode' ] = 200 ; // regardless of result, this is still a valid request
return yourls_apply_filter ( 'add_new_link' , $return , $url , $keyword , $title );
}
2013-02-13 09:45:33 +00:00
/**
* Edit a link
*
*/
2013-04-07 12:52:52 +02:00
function yourls_edit_link ( $url , $keyword , $newkeyword = '' , $title = '' ) {
2013-12-30 19:35:50 +01:00
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_edit_link' , null , $keyword , $url , $keyword , $newkeyword , $title );
if ( null !== $pre )
return $pre ;
2013-04-07 12:52:52 +02:00
global $ydb ;
$table = YOURLS_DB_TABLE_URL ;
2017-09-01 18:34:35 +02:00
$url = yourls_sanitize_url ( $url );
$keyword = yourls_sanitize_string ( $keyword );
$title = yourls_sanitize_title ( $title );
$newkeyword = yourls_sanitize_string ( $newkeyword );
2013-04-07 12:52:52 +02:00
$strip_url = stripslashes ( $url );
$strip_title = stripslashes ( $title );
2017-09-01 18:34:35 +02:00
2020-04-08 16:11:45 +02:00
if ( ! $url OR ! $newkeyword ) {
$return [ 'status' ] = 'fail' ;
$return [ 'message' ] = yourls__ ( 'Long URL or Short URL cannot be blank' );
return yourls_apply_filter ( 'edit_link' , $return , $url , $keyword , $newkeyword , $title );
}
2017-09-01 18:34:35 +02:00
$old_url = $ydb -> fetchValue ( " SELECT `url` FROM ` $table ` WHERE `keyword` = :keyword " , array ( 'keyword' => $keyword ));
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Check if new URL is not here already
if ( $old_url != $url && ! yourls_allow_duplicate_longurls () ) {
2017-09-01 18:34:35 +02:00
$new_url_already_there = intval ( $ydb -> fetchValue ( " SELECT COUNT(keyword) FROM ` $table ` WHERE `url` = :url; " , array ( 'url' => $url )));
2013-04-07 12:52:52 +02:00
} else {
$new_url_already_there = false ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// 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 ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'pre_edit_link' , $url , $keyword , $newkeyword , $new_url_already_there , $keyword_is_ok );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// All clear, update
if ( ( ! $new_url_already_there || yourls_allow_duplicate_longurls () ) && $keyword_is_ok ) {
2017-09-02 19:09:56 +02:00
$sql = " UPDATE ` $table ` SET `url` = :url, `keyword` = :newkeyword, `title` = :title WHERE `keyword` = :keyword " ;
$binds = array ( 'url' => $url , 'newkeyword' => $newkeyword , 'title' => $title , 'keyword' => $keyword );
$update_url = $ydb -> fetchAffected ( $sql , $binds );
2013-04-07 12:52:52 +02:00
if ( $update_url ) {
$return [ 'url' ] = array ( 'keyword' => $newkeyword , 'shorturl' => YOURLS_SITE . '/' . $newkeyword , 'url' => $strip_url , 'display_url' => yourls_trim_long_string ( $strip_url ), 'title' => $strip_title , 'display_title' => yourls_trim_long_string ( $strip_title ) );
$return [ 'status' ] = 'success' ;
$return [ 'message' ] = yourls__ ( 'Link updated in database' );
} else {
$return [ 'status' ] = 'fail' ;
$return [ 'message' ] = /* //translators: "Error updating http://someurl/ (Shorturl: http://sho.rt/blah)" */ yourls_s ( 'Error updating %s (Short URL: %s)' , yourls_trim_long_string ( $strip_url ), $keyword ) ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Nope
} else {
$return [ 'status' ] = 'fail' ;
$return [ 'message' ] = yourls__ ( 'URL or keyword already exists in database' );
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'edit_link' , $return , $url , $keyword , $newkeyword , $title , $new_url_already_there , $keyword_is_ok );
}
2013-02-13 09:45:33 +00:00
/**
* Update a title link ( no checks for duplicates etc .. )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_edit_link_title ( $keyword , $title ) {
2013-12-30 19:35:50 +01:00
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_edit_link_title' , null , $keyword , $title );
if ( null !== $pre )
return $pre ;
2013-04-07 12:52:52 +02:00
global $ydb ;
2017-06-20 23:12:04 +02:00
2017-09-02 19:09:56 +02:00
$keyword = yourls_sanitize_keyword ( $keyword );
$title = yourls_sanitize_title ( $title );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$table = YOURLS_DB_TABLE_URL ;
2017-09-02 19:09:56 +02:00
$update = $ydb -> fetchAffected ( " UPDATE ` $table ` SET `title` = :title WHERE `keyword` = :keyword; " , array ( 'title' => $title , 'keyword' => $keyword ));
2013-04-07 12:52:52 +02:00
return $update ;
}
2013-02-13 09:45:33 +00:00
/**
* Check if keyword id is free ( ie not already taken , and not reserved ) . Return bool .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_keyword_is_free ( $keyword ) {
$free = true ;
if ( yourls_keyword_is_reserved ( $keyword ) or yourls_keyword_is_taken ( $keyword ) )
$free = false ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'keyword_is_free' , $free , $keyword );
}
2013-02-13 09:45:33 +00:00
/**
2017-06-20 23:12:04 +02:00
* Check if a keyword is taken ( ie there is already a short URL with this id ) . Return bool .
2013-02-13 09:45:33 +00:00
*
*/
2013-04-07 12:52:52 +02:00
function yourls_keyword_is_taken ( $keyword ) {
2013-04-25 23:06:54 +03:00
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_keyword_is_taken' , false , $keyword );
if ( false !== $pre )
2013-04-26 15:01:38 +03:00
return $pre ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
global $ydb ;
2017-09-01 18:34:35 +02:00
$keyword = yourls_sanitize_keyword ( $keyword );
2013-04-07 12:52:52 +02:00
$taken = false ;
$table = YOURLS_DB_TABLE_URL ;
2017-08-21 21:32:25 +02:00
2017-09-01 18:34:35 +02:00
$already_exists = $ydb -> fetchValue ( " SELECT COUNT(`keyword`) FROM ` $table ` WHERE `keyword` = :keyword; " , array ( 'keyword' => $keyword ));
2013-04-07 12:52:52 +02:00
if ( $already_exists )
$taken = true ;
return yourls_apply_filter ( 'keyword_is_taken' , $taken , $keyword );
}
2013-02-13 09:45:33 +00:00
/**
* Return XML output .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_xml_encode ( $array ) {
require_once ( YOURLS_INC . '/functions-xml.php' );
$converter = new yourls_array2xml ;
return $converter -> array2xml ( $array );
}
2013-02-13 09:45:33 +00:00
/**
2013-05-03 17:48:23 +02:00
* Return array of all information associated with keyword . Returns false if keyword not found . Set optional $use_cache to false to force fetching from DB
2013-02-13 09:45:33 +00:00
*
2017-08-31 21:03:59 +02:00
* @ since 1.4
* @ param string $keyword Short URL keyword
* @ param bool $use_cache Default true , set to false to force fetching from DB
* @ return false | object false if not found , object with URL properties if found
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_infos ( $keyword , $use_cache = true ) {
global $ydb ;
2017-08-31 21:03:59 +02:00
$keyword = yourls_sanitize_string ( $keyword );
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'pre_get_keyword' , $keyword , $use_cache );
2017-08-22 09:06:23 +02:00
if ( $ydb -> has_infos ( $keyword ) && $use_cache === true ) {
2017-08-21 21:32:25 +02:00
return yourls_apply_filter ( 'get_keyword_infos' , $ydb -> get_infos ( $keyword ), $keyword );
2013-04-07 12:52:52 +02:00
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'get_keyword_not_cached' , $keyword );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$table = YOURLS_DB_TABLE_URL ;
2017-08-31 21:03:59 +02:00
$infos = $ydb -> fetchObject ( " SELECT * FROM ` $table ` WHERE `keyword` = :keyword " , array ( 'keyword' => $keyword ));
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( $infos ) {
$infos = ( array ) $infos ;
2017-08-21 21:32:25 +02:00
$ydb -> set_infos ( $keyword , $infos );
2013-04-07 12:52:52 +02:00
} else {
2017-08-31 21:03:59 +02:00
// is NULL if not found
$infos = false ;
2017-08-21 21:32:25 +02:00
$ydb -> set_infos ( $keyword , false );
2013-04-07 12:52:52 +02:00
}
2017-06-20 23:12:04 +02:00
2017-08-21 21:32:25 +02:00
return yourls_apply_filter ( 'get_keyword_infos' , $infos , $keyword );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Return ( string ) selected information associated with a keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_info ( $keyword , $field , $notfound = false ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_get_keyword_info' , false , $keyword , $field , $notfound );
if ( false !== $pre )
return $pre ;
$keyword = yourls_sanitize_string ( $keyword );
$infos = yourls_get_keyword_infos ( $keyword );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$return = $notfound ;
if ( isset ( $infos [ $field ] ) && $infos [ $field ] !== false )
$return = $infos [ $field ];
2017-06-20 23:12:04 +02:00
return yourls_apply_filter ( 'get_keyword_info' , $return , $keyword , $field , $notfound );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Return title associated with keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_title ( $keyword , $notfound = false ) {
return yourls_get_keyword_info ( $keyword , 'title' , $notfound );
}
2013-02-13 09:45:33 +00:00
/**
* Return long URL associated with keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_longurl ( $keyword , $notfound = false ) {
return yourls_get_keyword_info ( $keyword , 'url' , $notfound );
}
2013-02-13 09:45:33 +00:00
/**
* Return number of clicks on a keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_clicks ( $keyword , $notfound = false ) {
return yourls_get_keyword_info ( $keyword , 'clicks' , $notfound );
}
2013-02-13 09:45:33 +00:00
/**
* Return IP that added a keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_IP ( $keyword , $notfound = false ) {
return yourls_get_keyword_info ( $keyword , 'ip' , $notfound );
}
2013-02-13 09:45:33 +00:00
/**
* Return timestamp associated with a keyword . Optional $notfound = string default message if nothing found
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_keyword_timestamp ( $keyword , $notfound = false ) {
return yourls_get_keyword_info ( $keyword , 'timestamp' , $notfound );
}
2013-02-13 09:45:33 +00:00
/**
* Update click count on a short URL . Return 0 / 1 for error / success .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_update_clicks ( $keyword , $clicks = false ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_update_clicks' , false , $keyword , $clicks );
if ( false !== $pre )
return $pre ;
global $ydb ;
2017-09-02 19:09:56 +02:00
$keyword = yourls_sanitize_string ( $keyword );
2013-04-07 12:52:52 +02:00
$table = YOURLS_DB_TABLE_URL ;
if ( $clicks !== false && is_int ( $clicks ) && $clicks >= 0 )
2017-09-02 19:09:56 +02:00
$update = $ydb -> fetchAffected ( " UPDATE ` $table ` SET `clicks` = :clicks WHERE `keyword` = :keyword " , array ( 'clicks' => $clicks , 'keyword' => $keyword ) );
2013-04-07 12:52:52 +02:00
else
2017-09-02 19:09:56 +02:00
$update = $ydb -> fetchAffected ( " UPDATE ` $table ` SET `clicks` = clicks + 1 WHERE `keyword` = :keyword " , array ( 'keyword' => $keyword ) );
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'update_clicks' , $keyword , $update , $clicks );
return $update ;
}
2013-02-13 09:45:33 +00:00
/**
* Return array of stats . ( string ) $filter is 'bottom' , 'last' , 'rand' or 'top' . ( int ) $limit is the number of links to return
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_stats ( $filter = 'top' , $limit = 10 , $start = 0 ) {
global $ydb ;
switch ( $filter ) {
case 'bottom' :
2019-03-24 22:27:11 +01:00
$sort_by = '`clicks`' ;
2013-04-07 12:52:52 +02:00
$sort_order = 'asc' ;
break ;
case 'last' :
2019-03-24 22:27:11 +01:00
$sort_by = '`timestamp`' ;
2013-04-07 12:52:52 +02:00
$sort_order = 'desc' ;
break ;
case 'rand' :
case 'random' :
$sort_by = 'RAND()' ;
$sort_order = '' ;
break ;
case 'top' :
default :
2019-03-24 22:27:11 +01:00
$sort_by = '`clicks`' ;
2013-04-07 12:52:52 +02:00
$sort_order = 'desc' ;
break ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Fetch links
$limit = intval ( $limit );
$start = intval ( $start );
if ( $limit > 0 ) {
$table_url = YOURLS_DB_TABLE_URL ;
2019-03-24 22:27:11 +01:00
$results = $ydb -> fetchObjects ( " SELECT * FROM ` $table_url ` WHERE 1=1 ORDER BY $sort_by $sort_order LIMIT $start , $limit ; " );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$return = array ();
$i = 1 ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
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 ();
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$return [ 'statusCode' ] = 200 ;
return yourls_apply_filter ( 'get_stats' , $return , $filter , $limit , $start );
}
2013-02-13 09:45:33 +00:00
/**
* Return array of stats . ( string ) $filter is 'bottom' , 'last' , 'rand' or 'top' . ( int ) $limit is the number of links to return
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_link_stats ( $shorturl ) {
global $ydb ;
$table_url = YOURLS_DB_TABLE_URL ;
2017-08-31 21:03:59 +02:00
$shorturl = yourls_sanitize_keyword ( $shorturl );
2017-06-20 23:12:04 +02:00
2017-08-31 21:03:59 +02:00
$res = $ydb -> fetchObject ( " SELECT * FROM ` $table_url ` WHERE `keyword` = :keyword " , array ( 'keyword' => $shorturl ));
2013-04-07 12:52:52 +02:00
$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 );
}
2013-02-13 09:45:33 +00:00
/**
* Get total number of URLs and sum of clicks . Input : optional " AND WHERE " clause . Returns array
*
2017-08-31 20:12:10 +02:00
* The $where parameter will contain additional SQL arguments :
* $where [ 'sql' ] will concatenate SQL clauses : $where [ 'sql' ] = ' AND something = :value AND otherthing < :othervalue' ;
* $where [ 'binds' ] will hold the ( name => value ) placeholder pairs : $where [ 'binds' ] = array ( 'value' => $value , 'othervalue' => $value2 )
2014-01-02 19:22:46 +01:00
*
2017-08-31 20:12:10 +02:00
* @ param $where array See comment above
* @ return array
2013-02-13 09:45:33 +00:00
*/
2017-08-31 20:07:25 +02:00
function yourls_get_db_stats ( $where = array ( 'sql' => '' , 'binds' => array ()) ) {
2013-04-07 12:52:52 +02:00
global $ydb ;
$table_url = YOURLS_DB_TABLE_URL ;
2017-08-31 20:07:25 +02:00
$totals = $ydb -> fetchObject ( " SELECT COUNT(keyword) as count, SUM(clicks) as sum FROM ` $table_url ` WHERE 1=1 " . $where [ 'sql' ] , $where [ 'binds' ] );
2013-04-07 12:52:52 +02:00
$return = array ( 'total_links' => $totals -> count , 'total_clicks' => $totals -> sum );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'get_db_stats' , $return , $where );
}
2013-02-13 09:45:33 +00:00
/**
* Get number of SQL queries performed
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_num_queries () {
global $ydb ;
2017-08-20 14:01:13 +02:00
return yourls_apply_filter ( 'get_num_queries' , $ydb -> get_num_queries () );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Returns a sanitized a user agent string . Given what I found on http :// www . user - agents . org / it should be OK .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_user_agent () {
if ( ! isset ( $_SERVER [ 'HTTP_USER_AGENT' ] ) )
return '-' ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$ua = strip_tags ( html_entity_decode ( $_SERVER [ 'HTTP_USER_AGENT' ] ));
$ua = preg_replace ( '![^0-9a-zA-Z\':., /{}\(\)\[\]\+@&\!\?;_\-=~\*\#]!' , '' , $ua );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'get_user_agent' , substr ( $ua , 0 , 254 ) );
}
2013-02-13 09:45:33 +00:00
/**
* Redirect to another page
*
2020-03-25 14:41:20 +01:00
* YOURLS redirection , either to internal or external URLs . If headers have not been sent , redirection
* is achieved with PHP 's header(). If headers have been sent already and we' re not in a command line
* client , redirection occurs with Javascript .
*
* @ since 1.4
* @ param string $location URL to redirect to
* @ param int $code HTTP status code to send
* @ return int 1 for header redirection , 2 for js redirection , 3 otherwise
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_redirect ( $location , $code = 301 ) {
yourls_do_action ( 'pre_redirect' , $location , $code );
$location = yourls_apply_filter ( 'redirect_location' , $location , $code );
$code = yourls_apply_filter ( 'redirect_code' , $code , $location );
// Redirect, either properly if possible, or via Javascript otherwise
if ( ! headers_sent () ) {
yourls_status_header ( $code );
header ( " Location: $location " );
2020-03-25 14:41:20 +01:00
return 1 ;
2013-04-07 12:52:52 +02:00
}
2020-03-25 14:41:20 +01:00
if ( php_sapi_name () !== 'cli' ) {
yourls_redirect_javascript ( $location );
return 2 ;
}
return 3 ;
2013-04-07 12:52:52 +02:00
}
2018-08-05 19:34:22 +02:00
/**
* Redirect to an existing short URL
*
* Redirect client to an existing short URL ( no check performed ) and execute misc tasks : update
* clicks for short URL , update logs , and send a nocache header to prevent bots indexing short
* URLS ( see #2202)
*
* @ since 1.7 . 3
* @ param string $url
* @ param string $keyword
*/
function yourls_redirect_shorturl ( $url , $keyword ) {
yourls_do_action ( 'redirect_shorturl' , $url , $keyword );
// Update click count in main table
$update_clicks = yourls_update_clicks ( $keyword );
// Update detailed log for stats
$log_redirect = yourls_log_redirect ( $keyword );
// Tell (Google)bots not to index this short URL, see #2202
if ( ! headers_sent () ) {
header ( " X-Robots-Tag: noindex " , true );
}
yourls_redirect ( $url , 301 );
}
2013-02-13 09:45:33 +00:00
/**
* Set HTTP status header
*
2015-05-27 17:40:45 +02:00
* @ since 1.4
* @ param int $code status header code
* @ return bool whether header was sent
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_status_header ( $code = 200 ) {
2015-05-27 17:40:45 +02:00
yourls_do_action ( 'status_header' , $code );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( headers_sent () )
2015-05-27 17:40:45 +02:00
return false ;
2017-06-20 23:12:04 +02:00
2013-09-02 12:50:03 +02:00
$protocol = $_SERVER [ 'SERVER_PROTOCOL' ];
2013-04-07 12:52:52 +02:00
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
2017-06-20 23:12:04 +02:00
2015-05-27 17:40:45 +02:00
return true ;
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* 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 )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_redirect_javascript ( $location , $dontwait = true ) {
yourls_do_action ( 'pre_redirect_javascript' , $location , $dontwait );
$location = yourls_apply_filter ( 'redirect_javascript' , $location , $dontwait );
if ( $dontwait ) {
$message = yourls_s ( 'if you are not redirected after 10 seconds, please <a href="%s">click here</a>' , $location );
echo <<< REDIR
< script type = " text/javascript " >
window . location = " $location " ;
</ script >
< small > ( $message ) </ small >
REDIR ;
} else {
echo '<p>' . yourls_s ( 'Please <a href="%s">click here</a>' , $location ) . '</p>' ;
}
yourls_do_action ( 'post_redirect_javascript' , $location );
}
2013-02-13 09:45:33 +00:00
/**
* Return a HTTP status code
*
*/
2013-04-07 12:52:52 +02:00
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 '' ;
}
2013-02-13 09:45:33 +00:00
/**
* Log a redirect ( for stats )
*
2014-02-08 22:44:39 +01:00
* This function does not check for the existence of a valid keyword , in order to save a query . Make sure the keyword
* exists before calling it .
*
* @ since 1.4
* @ param string $keyword short URL keyword
* @ return mixed Result of the INSERT query ( 1 on success )
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_log_redirect ( $keyword ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_log_redirect' , false , $keyword );
if ( false !== $pre )
return $pre ;
if ( ! yourls_do_log_redirect () )
return true ;
global $ydb ;
$table = YOURLS_DB_TABLE_LOG ;
2017-09-02 19:09:56 +02:00
$ip = yourls_get_IP ();
$binds = array (
'now' => date ( 'Y-m-d H:i:s' ),
'keyword' => yourls_sanitize_string ( $keyword ),
2019-11-06 22:10:01 +01:00
'referrer' => isset ( $_SERVER [ 'HTTP_REFERER' ]) ? yourls_sanitize_url_safe ( substr ( $_SERVER [ 'HTTP_REFERER' ], 0 , 200 )) : 'direct' ,
'ua' => substr ( yourls_get_user_agent (), 0 , 255 ),
2017-09-02 19:09:56 +02:00
'ip' => $ip ,
'location' => yourls_geo_ip_to_countrycode ( $ip ),
);
return $ydb -> fetchAffected ( " INSERT INTO ` $table ` (click_time, shorturl, referrer, user_agent, ip_address, country_code) VALUES (:now, :keyword, :referrer, :ua, :ip, :location) " , $binds );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if we want to not log redirects ( for stats )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_do_log_redirect () {
return ( ! defined ( 'YOURLS_NOSTATS' ) || YOURLS_NOSTATS != true );
}
2013-02-13 09:45:33 +00:00
/**
* Converts an IP to a 2 letter country code , using GeoIP database if available in includes / geo /
*
2013-09-06 17:10:33 +02:00
* @ since 1.4
* @ param string $ip IP or , if empty string , will be current user IP
* @ param string $defaut Default string to return if IP doesn ' t resolve to a country ( malformed , private IP ... )
* @ return string 2 letter country code ( eg 'US' ) or $default
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_geo_ip_to_countrycode ( $ip = '' , $default = '' ) {
// Allow plugins to short-circuit the Geo IP API
$location = yourls_apply_filter ( 'shunt_geo_ip_to_countrycode' , false , $ip , $default ); // at this point $ip can be '', check if your plugin hooks in here
if ( false !== $location )
return $location ;
2017-06-20 23:12:04 +02:00
2020-04-08 17:40:00 +02:00
// At this point, $location == false
2013-04-07 12:52:52 +02:00
if ( $ip == '' )
$ip = yourls_get_IP ();
2017-06-20 23:12:04 +02:00
2017-08-09 17:56:11 +02:00
// Allow plugins to stick to YOURLS internals but provide another DB
$db = yourls_apply_filter ( 'geo_ip_path_to_db' , YOURLS_INC . '/geo/GeoLite2-Country.mmdb' );
if ( ! is_readable ( $db )) {
return $default ;
}
2017-06-20 23:12:04 +02:00
2017-08-09 17:56:11 +02:00
$reader = new \GeoIp2\Database\Reader ( $db );
try {
$record = $reader -> country ( $ip );
$location = $record -> country -> isoCode ; // eg 'US'
} catch ( \Exception $e ) {
/*
Unused for now , Exception and $e -> getMessage () can be one of :
- Exception : \GeoIp2\Exception\AddressNotFoundException
When : valid IP not found
Error message : " The address 10.0.0.30 is not in the database "
- Exception : \InvalidArgumentException
When : IP is not valid , or DB not readable
Error message : " The value " 10.0 . 0.300 " is not a valid IP address " , " The file " / path / to / GeoLite2 - Country . mmdb " does not exist or is not readable "
- Exception : \MaxMind\Db\Reader\InvalidDatabaseException
When : DB is readable but is corrupt or invalid
Error message : " The MaxMind DB file's search tree is corrupt "
- or obviously \Exception for any other error ( ? )
*/
2020-04-08 17:40:00 +02:00
}
if ( ! $location ) {
2017-08-09 17:56:11 +02:00
$location = $default ;
}
2013-04-07 12:52:52 +02:00
2017-08-09 17:56:11 +02:00
return yourls_apply_filter ( 'geo_ip_to_countrycode' , $location , $ip , $default );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Converts a 2 letter country code to long name ( ie AU -> Australia )
*
2017-08-09 17:56:11 +02:00
* This associative array is the one used by MaxMind internal functions , it may differ from other lists ( eg " A1 " does not universally stand for " Anon proxy " )
*
* @ since 1.4
* @ param string $code 2 letter country code , eg 'FR'
* @ return string Country long name ( eg 'France' ) or an empty string if not found
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_geo_countrycode_to_countryname ( $code ) {
2017-08-09 17:56:11 +02:00
// Allow plugins to short-circuit the function
2013-04-07 12:52:52 +02:00
$country = yourls_apply_filter ( 'shunt_geo_countrycode_to_countryname' , false , $code );
if ( false !== $country )
return $country ;
2017-08-09 17:56:11 +02:00
// Weeeeeeeeeeee
$countries = array (
'A1' => 'Anonymous Proxy' , 'A2' => 'Satellite Provider' , 'AD' => 'Andorra' , 'AE' => 'United Arab Emirates' , 'AF' => 'Afghanistan' ,
'AG' => 'Antigua and Barbuda' , 'AI' => 'Anguilla' , 'AL' => 'Albania' , 'AM' => 'Armenia' , 'AO' => 'Angola' ,
'AP' => 'Asia/Pacific Region' , 'AQ' => 'Antarctica' , 'AR' => 'Argentina' , 'AS' => 'American Samoa' , 'AT' => 'Austria' ,
'AU' => 'Australia' , 'AW' => 'Aruba' , 'AX' => 'Aland Islands' , 'AZ' => 'Azerbaijan' , 'BA' => 'Bosnia and Herzegovina' ,
'BB' => 'Barbados' , 'BD' => 'Bangladesh' , 'BE' => 'Belgium' , 'BF' => 'Burkina Faso' , 'BG' => 'Bulgaria' ,
'BH' => 'Bahrain' , 'BI' => 'Burundi' , 'BJ' => 'Benin' , 'BL' => 'Saint Barthelemy' , 'BM' => 'Bermuda' ,
'BN' => 'Brunei Darussalam' , 'BO' => 'Bolivia' , 'BQ' => 'Bonaire, Saint Eustatius and Saba' , 'BR' => 'Brazil' , 'BS' => 'Bahamas' ,
'BT' => 'Bhutan' , 'BV' => 'Bouvet Island' , 'BW' => 'Botswana' , 'BY' => 'Belarus' , 'BZ' => 'Belize' ,
'CA' => 'Canada' , 'CC' => 'Cocos (Keeling) Islands' , 'CD' => 'Congo, The Democratic Republic of the' , 'CF' => 'Central African Republic' , 'CG' => 'Congo' ,
'CH' => 'Switzerland' , 'CI' => 'Cote D\'Ivoire' , 'CK' => 'Cook Islands' , 'CL' => 'Chile' , 'CM' => 'Cameroon' ,
'CN' => 'China' , 'CO' => 'Colombia' , 'CR' => 'Costa Rica' , 'CU' => 'Cuba' , 'CV' => 'Cape Verde' ,
'CW' => 'Curacao' , 'CX' => 'Christmas Island' , 'CY' => 'Cyprus' , 'CZ' => 'Czech Republic' , 'DE' => 'Germany' ,
'DJ' => 'Djibouti' , 'DK' => 'Denmark' , 'DM' => 'Dominica' , 'DO' => 'Dominican Republic' , 'DZ' => 'Algeria' ,
'EC' => 'Ecuador' , 'EE' => 'Estonia' , 'EG' => 'Egypt' , 'EH' => 'Western Sahara' , 'ER' => 'Eritrea' ,
'ES' => 'Spain' , 'ET' => 'Ethiopia' , 'EU' => 'Europe' , 'FI' => 'Finland' , 'FJ' => 'Fiji' ,
'FK' => 'Falkland Islands (Malvinas)' , 'FM' => 'Micronesia, Federated States of' , 'FO' => 'Faroe Islands' , 'FR' => 'France' , 'GA' => 'Gabon' ,
'GB' => 'United Kingdom' , 'GD' => 'Grenada' , 'GE' => 'Georgia' , 'GF' => 'French Guiana' , 'GG' => 'Guernsey' ,
'GH' => 'Ghana' , 'GI' => 'Gibraltar' , 'GL' => 'Greenland' , 'GM' => 'Gambia' , 'GN' => 'Guinea' ,
'GP' => 'Guadeloupe' , 'GQ' => 'Equatorial Guinea' , 'GR' => 'Greece' , 'GS' => 'South Georgia and the South Sandwich Islands' , 'GT' => 'Guatemala' ,
'GU' => 'Guam' , 'GW' => 'Guinea-Bissau' , 'GY' => 'Guyana' , 'HK' => 'Hong Kong' , 'HM' => 'Heard Island and McDonald Islands' ,
'HN' => 'Honduras' , 'HR' => 'Croatia' , 'HT' => 'Haiti' , 'HU' => 'Hungary' , 'ID' => 'Indonesia' ,
'IE' => 'Ireland' , 'IL' => 'Israel' , 'IM' => 'Isle of Man' , 'IN' => 'India' , 'IO' => 'British Indian Ocean Territory' ,
'IQ' => 'Iraq' , 'IR' => 'Iran, Islamic Republic of' , 'IS' => 'Iceland' , 'IT' => 'Italy' , 'JE' => 'Jersey' ,
'JM' => 'Jamaica' , 'JO' => 'Jordan' , 'JP' => 'Japan' , 'KE' => 'Kenya' , 'KG' => 'Kyrgyzstan' ,
'KH' => 'Cambodia' , 'KI' => 'Kiribati' , 'KM' => 'Comoros' , 'KN' => 'Saint Kitts and Nevis' , 'KP' => 'Korea, Democratic People\'s Republic of' ,
'KR' => 'Korea, Republic of' , 'KW' => 'Kuwait' , 'KY' => 'Cayman Islands' , 'KZ' => 'Kazakhstan' , 'LA' => 'Lao People\'s Democratic Republic' ,
'LB' => 'Lebanon' , 'LC' => 'Saint Lucia' , 'LI' => 'Liechtenstein' , 'LK' => 'Sri Lanka' , 'LR' => 'Liberia' ,
'LS' => 'Lesotho' , 'LT' => 'Lithuania' , 'LU' => 'Luxembourg' , 'LV' => 'Latvia' , 'LY' => 'Libya' ,
'MA' => 'Morocco' , 'MC' => 'Monaco' , 'MD' => 'Moldova, Republic of' , 'ME' => 'Montenegro' , 'MF' => 'Saint Martin' ,
'MG' => 'Madagascar' , 'MH' => 'Marshall Islands' , 'MK' => 'Macedonia' , 'ML' => 'Mali' , 'MM' => 'Myanmar' ,
'MN' => 'Mongolia' , 'MO' => 'Macau' , 'MP' => 'Northern Mariana Islands' , 'MQ' => 'Martinique' , 'MR' => 'Mauritania' ,
'MS' => 'Montserrat' , 'MT' => 'Malta' , 'MU' => 'Mauritius' , 'MV' => 'Maldives' , 'MW' => 'Malawi' ,
'MX' => 'Mexico' , 'MY' => 'Malaysia' , 'MZ' => 'Mozambique' , 'NA' => 'Namibia' , 'NC' => 'New Caledonia' ,
'NE' => 'Niger' , 'NF' => 'Norfolk Island' , 'NG' => 'Nigeria' , 'NI' => 'Nicaragua' , 'NL' => 'Netherlands' ,
'NO' => 'Norway' , 'NP' => 'Nepal' , 'NR' => 'Nauru' , 'NU' => 'Niue' , 'NZ' => 'New Zealand' ,
'O1' => 'Other' , 'OM' => 'Oman' , 'PA' => 'Panama' , 'PE' => 'Peru' , 'PF' => 'French Polynesia' ,
'PG' => 'Papua New Guinea' , 'PH' => 'Philippines' , 'PK' => 'Pakistan' , 'PL' => 'Poland' , 'PM' => 'Saint Pierre and Miquelon' ,
'PN' => 'Pitcairn Islands' , 'PR' => 'Puerto Rico' , 'PS' => 'Palestinian Territory' , 'PT' => 'Portugal' , 'PW' => 'Palau' ,
'PY' => 'Paraguay' , 'QA' => 'Qatar' , 'RE' => 'Reunion' , 'RO' => 'Romania' , 'RS' => 'Serbia' ,
'RU' => 'Russian Federation' , 'RW' => 'Rwanda' , 'SA' => 'Saudi Arabia' , 'SB' => 'Solomon Islands' , 'SC' => 'Seychelles' ,
'SD' => 'Sudan' , 'SE' => 'Sweden' , 'SG' => 'Singapore' , 'SH' => 'Saint Helena' , 'SI' => 'Slovenia' ,
'SJ' => 'Svalbard and Jan Mayen' , 'SK' => 'Slovakia' , 'SL' => 'Sierra Leone' , 'SM' => 'San Marino' , 'SN' => 'Senegal' ,
'SO' => 'Somalia' , 'SR' => 'Suriname' , 'SS' => 'South Sudan' , 'ST' => 'Sao Tome and Principe' , 'SV' => 'El Salvador' ,
'SX' => 'Sint Maarten (Dutch part)' , 'SY' => 'Syrian Arab Republic' , 'SZ' => 'Swaziland' , 'TC' => 'Turks and Caicos Islands' , 'TD' => 'Chad' ,
'TF' => 'French Southern Territories' , 'TG' => 'Togo' , 'TH' => 'Thailand' , 'TJ' => 'Tajikistan' , 'TK' => 'Tokelau' ,
'TL' => 'Timor-Leste' , 'TM' => 'Turkmenistan' , 'TN' => 'Tunisia' , 'TO' => 'Tonga' , 'TR' => 'Turkey' ,
'TT' => 'Trinidad and Tobago' , 'TV' => 'Tuvalu' , 'TW' => 'Taiwan' , 'TZ' => 'Tanzania, United Republic of' , 'UA' => 'Ukraine' ,
'UG' => 'Uganda' , 'UM' => 'United States Minor Outlying Islands' , 'US' => 'United States' , 'UY' => 'Uruguay' , 'UZ' => 'Uzbekistan' ,
'VA' => 'Holy See (Vatican City State)' , 'VC' => 'Saint Vincent and the Grenadines' , 'VE' => 'Venezuela' , 'VG' => 'Virgin Islands, British' , 'VI' => 'Virgin Islands, U.S.' ,
'VN' => 'Vietnam' , 'VU' => 'Vanuatu' , 'WF' => 'Wallis and Futuna' , 'WS' => 'Samoa' , 'YE' => 'Yemen' ,
'YT' => 'Mayotte' , 'ZA' => 'South Africa' , 'ZM' => 'Zambia' , 'ZW' => 'Zimbabwe' ,
);
$code = strtoupper ( $code );
if ( array_key_exists ( $code , $countries )) {
$name = $countries [ $code ];
} else {
$name = '' ;
}
2017-06-20 23:12:04 +02:00
2017-08-09 17:56:11 +02:00
return yourls_apply_filter ( 'geo_countrycode_to_countryname' , $name );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Return flag URL from 2 letter country code
*
*/
2013-04-07 12:52:52 +02:00
function yourls_geo_get_flag ( $code ) {
if ( file_exists ( YOURLS_INC . '/geo/flags/flag_' . strtolower ( $code ) . '.gif' ) ) {
$img = yourls_match_current_protocol ( YOURLS_SITE . '/includes/geo/flags/flag_' . ( strtolower ( $code ) ) . '.gif' );
} else {
$img = false ;
}
return yourls_apply_filter ( 'geo_get_flag' , $img , $code );
}
2013-02-13 09:45:33 +00:00
/**
* Check if an upgrade is needed
*
*/
2013-04-07 12:52:52 +02:00
function yourls_upgrade_is_needed () {
// check YOURLS_DB_VERSION exist && match values stored in YOURLS_DB_TABLE_OPTIONS
list ( $currentver , $currentsql ) = yourls_get_current_version_from_sql ();
if ( $currentsql < YOURLS_DB_VERSION )
return true ;
2017-06-20 23:12:04 +02:00
2019-01-27 01:36:15 -05:00
// Check if YOURLS_VERSION exist && match value stored in YOURLS_DB_TABLE_OPTIONS, update DB if required
if ( $currentver < YOURLS_VERSION )
yourls_update_option ( 'version' , YOURLS_VERSION );
2019-03-24 22:27:11 +01:00
2013-04-07 12:52:52 +02:00
return false ;
}
2013-02-13 09:45:33 +00:00
/**
* Get current version & db version as stored in the options DB . Prior to 1.4 there ' s no option table .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_get_current_version_from_sql () {
$currentver = yourls_get_option ( 'version' );
$currentsql = yourls_get_option ( 'db_version' );
// Values if version is 1.3
if ( ! $currentver )
$currentver = '1.3' ;
if ( ! $currentsql )
$currentsql = '100' ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return array ( $currentver , $currentsql );
}
2013-02-13 09:45:33 +00:00
/**
* Read an option from DB ( or from cache if available ) . Return value or $default if not found
*
2013-12-25 12:30:35 +01:00
* Pretty much stolen from WordPress
*
* @ since 1.4
2017-08-18 19:56:01 +02:00
* @ param string $option_name Option name . Expected to not be SQL - escaped .
2013-12-25 12:30:35 +01:00
* @ param mixed $default Optional value to return if option doesn ' t exist . Default false .
* @ return mixed Value set for the option .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_option ( $option_name , $default = false ) {
// Allow plugins to short-circuit options
$pre = yourls_apply_filter ( 'shunt_option_' . $option_name , false );
if ( false !== $pre )
return $pre ;
2017-08-18 19:56:01 +02:00
global $ydb ;
$option = new \YOURLS\Database\Options ( $ydb );
$value = $option -> get ( $option_name , $default );
2013-04-07 12:52:52 +02:00
2017-08-18 19:56:01 +02:00
return yourls_apply_filter ( 'get_option_' . $option_name , $value );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Read all options from DB at once
*
2014-02-07 11:16:44 +01:00
* The goal is to read all options at once and then populate array $ydb -> option , to prevent further
2013-12-25 12:30:35 +01:00
* SQL queries if we need to read an option value later .
2014-02-07 11:16:44 +01:00
* It ' s also a simple check whether YOURLS is installed or not ( no option = assuming not installed ) after
* a check for DB server reachability has been performed
2013-12-25 12:30:35 +01:00
*
* @ since 1.4
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_all_options () {
// Allow plugins to short-circuit all options. (Note: regular plugins are loaded after all options)
$pre = yourls_apply_filter ( 'shunt_all_options' , false );
if ( false !== $pre )
return $pre ;
2017-08-18 19:56:01 +02:00
global $ydb ;
$options = new \YOURLS\Database\Options ( $ydb );
2013-05-03 22:48:48 +02:00
2017-09-06 21:58:28 +02:00
if ( $options -> get_all_options () === false ) {
// Zero option found but no unexpected error so far: YOURLS isn't installed
2017-08-18 19:56:01 +02:00
yourls_set_installed ( false );
2017-09-06 21:58:28 +02:00
return ;
2017-08-18 19:56:01 +02:00
}
yourls_set_installed ( true );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Update ( add if doesn ' t exist ) an option to DB
*
2013-12-25 12:30:35 +01:00
* Pretty much stolen from WordPress
*
* @ since 1.4
2017-08-18 19:56:01 +02:00
* @ param string $option_name Option name . Expected to not be SQL - escaped .
2013-12-25 12:30:35 +01:00
* @ param mixed $newvalue Option value . Must be serializable if non - scalar . Expected to not be SQL - escaped .
* @ return bool False if value was not updated , true otherwise .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_update_option ( $option_name , $newvalue ) {
global $ydb ;
2017-08-18 19:56:01 +02:00
$option = new \YOURLS\Database\Options ( $ydb );
$update = $option -> update ( $option_name , $newvalue );
2013-04-07 12:52:52 +02:00
2017-08-18 19:56:01 +02:00
return $update ;
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Add an option to the DB
*
2013-12-25 12:30:35 +01:00
* Pretty much stolen from WordPress
*
* @ since 1.4
2017-08-18 19:56:01 +02:00
* @ param string $name Name of option to add . Expected to not be SQL - escaped .
2013-12-25 12:30:35 +01:00
* @ param mixed $value Optional option value . Must be serializable if non - scalar . Expected to not be SQL - escaped .
* @ return bool False if option was not added and true otherwise .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_add_option ( $name , $value = '' ) {
global $ydb ;
2017-06-20 23:12:04 +02:00
2017-08-18 19:56:01 +02:00
$option = new \YOURLS\Database\Options ( $ydb );
$add = $option -> add ( $name , $value );
2017-06-20 23:12:04 +02:00
2017-08-18 19:56:01 +02:00
return $add ;
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Delete an option from the DB
*
2013-12-25 12:30:35 +01:00
* Pretty much stolen from WordPress
*
* @ since 1.4
2017-08-18 19:56:01 +02:00
* @ param string $name Option name to delete . Expected to not be SQL - escaped .
2013-12-25 12:30:35 +01:00
* @ return bool True , if option is successfully deleted . False on failure .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_delete_option ( $name ) {
global $ydb ;
2017-06-20 23:12:04 +02:00
2017-08-18 19:56:01 +02:00
$option = new \YOURLS\Database\Options ( $ydb );
$delete = $option -> delete ( $name );
2017-06-20 23:12:04 +02:00
2017-08-18 19:56:01 +02:00
return $delete ;
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Serialize data if needed . Stolen from WordPress
*
2013-12-25 12:51:23 +01:00
* @ since 1.4
* @ param mixed $data Data that might be serialized .
* @ return mixed A scalar data
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_maybe_serialize ( $data ) {
if ( is_array ( $data ) || is_object ( $data ) )
return serialize ( $data );
2013-12-25 12:51:23 +01:00
if ( yourls_is_serialized ( $data , false ) )
2013-04-07 12:52:52 +02:00
return serialize ( $data );
return $data ;
}
2013-02-13 09:45:33 +00:00
/**
* Check value to find if it was serialized . Stolen from WordPress
*
2013-12-25 12:51:23 +01:00
* @ since 1.4
* @ param mixed $data Value to check to see if was serialized .
* @ param bool $strict Optional . Whether to be strict about the end of the string . Defaults true .
* @ return bool False if not serialized and true if it was .
2013-02-13 09:45:33 +00:00
*/
2013-12-25 12:51:23 +01:00
function yourls_is_serialized ( $data , $strict = true ) {
2013-04-07 12:52:52 +02:00
// if it isn't a string, it isn't serialized
2013-12-25 12:51:23 +01:00
if ( ! is_string ( $data ) )
2013-04-07 12:52:52 +02:00
return false ;
$data = trim ( $data );
2013-12-25 12:51:23 +01:00
if ( 'N;' == $data )
2013-04-07 12:52:52 +02:00
return true ;
2013-12-25 12:51:23 +01:00
$length = strlen ( $data );
if ( $length < 4 )
2013-04-07 12:52:52 +02:00
return false ;
2013-12-25 12:51:23 +01:00
if ( ':' !== $data [ 1 ] )
return false ;
if ( $strict ) {
$lastc = $data [ $length - 1 ];
if ( ';' !== $lastc && '}' !== $lastc )
return false ;
} else {
$semicolon = strpos ( $data , ';' );
$brace = strpos ( $data , '}' );
// Either ; or } must exist.
if ( false === $semicolon && false === $brace )
return false ;
// But neither must be in the first X characters.
if ( false !== $semicolon && $semicolon < 3 )
return false ;
if ( false !== $brace && $brace < 4 )
return false ;
}
$token = $data [ 0 ];
switch ( $token ) {
case 's' :
if ( $strict ) {
if ( '"' !== $data [ $length - 2 ] )
return false ;
} elseif ( false === strpos ( $data , '"' ) ) {
return false ;
}
// or else fall through
2013-04-07 12:52:52 +02:00
case 'a' :
case 'O' :
2013-12-25 12:51:23 +01:00
return ( bool ) preg_match ( " /^ { $token } :[0-9]+:/s " , $data );
2013-04-07 12:52:52 +02:00
case 'b' :
case 'i' :
case 'd' :
2013-12-25 12:51:23 +01:00
$end = $strict ? '$' : '' ;
return ( bool ) preg_match ( " /^ { $token } :[0-9.E-]+; $end / " , $data );
2013-04-07 12:52:52 +02:00
}
return false ;
}
2013-02-13 09:45:33 +00:00
/**
* Unserialize value only if it was serialized . Stolen from WP
*
2013-12-25 12:51:23 +01:00
* @ since 1.4
* @ param string $original Maybe unserialized original , if is needed .
* @ return mixed Unserialized data can be any type .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
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 ;
}
2013-02-13 09:45:33 +00:00
/**
* Determine if the current page is private
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_private () {
$private = false ;
if ( defined ( 'YOURLS_PRIVATE' ) && YOURLS_PRIVATE == true ) {
// Allow overruling for particular pages:
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// API
if ( yourls_is_API () ) {
if ( ! defined ( 'YOURLS_PRIVATE_API' ) || YOURLS_PRIVATE_API != false )
2017-06-20 23:12:04 +02:00
$private = true ;
2013-04-07 12:52:52 +02:00
// Infos
} elseif ( yourls_is_infos () ) {
if ( ! defined ( 'YOURLS_PRIVATE_INFOS' ) || YOURLS_PRIVATE_INFOS !== false )
$private = true ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Others
} else {
$private = true ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'is_private' , $private );
}
2013-02-13 09:45:33 +00:00
/**
* Show login form if required
*
*/
2013-04-07 12:52:52 +02:00
function yourls_maybe_require_auth () {
2013-04-14 20:25:37 +02:00
if ( yourls_is_private () ) {
yourls_do_action ( 'require_auth' );
2013-04-07 12:52:52 +02:00
require_once ( YOURLS_INC . '/auth.php' );
2013-04-14 20:25:37 +02:00
} else {
yourls_do_action ( 'require_no_auth' );
}
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Allow several short URLs for the same long URL ?
*
*/
2013-04-07 12:52:52 +02:00
function yourls_allow_duplicate_longurls () {
// special treatment if API to check for WordPress plugin requests
if ( yourls_is_API () ) {
2017-06-20 23:12:04 +02:00
if ( isset ( $_REQUEST [ 'source' ]) && $_REQUEST [ 'source' ] == 'plugin' )
2013-04-07 12:52:52 +02:00
return false ;
}
return ( defined ( 'YOURLS_UNIQUE_URLS' ) && YOURLS_UNIQUE_URLS == false );
}
2013-11-17 22:22:52 -05:00
/**
2013-12-11 17:44:36 +01:00
* Return array of keywords that redirect to the submitted long URL
2013-11-17 22:22:52 -05:00
*
2013-12-11 17:44:36 +01:00
* @ since 1.7
* @ param string $longurl long url
* @ param string $order Optional SORT order ( can be 'ASC' or 'DESC' )
* @ return array array of keywords
2013-11-17 22:22:52 -05:00
*/
2017-09-01 17:30:33 +02:00
function yourls_get_longurl_keywords ( $longurl , $order = 'ASC' ) {
2013-04-07 12:52:52 +02:00
global $ydb ;
2017-09-01 17:30:33 +02:00
$longurl = yourls_sanitize_url ( $longurl );
2013-12-11 17:44:36 +01:00
$table = YOURLS_DB_TABLE_URL ;
2017-09-01 17:30:33 +02:00
$sql = " SELECT `keyword` FROM ` $table ` WHERE `url` = :url " ;
2017-06-20 23:12:04 +02:00
2017-09-01 17:30:33 +02:00
if ( in_array ( $order , array ( 'ASC' , 'DESC' ))) {
$sql .= " ORDER BY `keyword` " . $order ;
}
return yourls_apply_filter ( 'get_longurl_keywords' , $ydb -> fetchCol ( $sql , array ( 'url' => $longurl )), $longurl );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if an IP shortens URL too fast to prevent DB flood . Return true , or die .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_check_IP_flood ( $ip = '' ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_check_IP_flood' , false , $ip );
if ( false !== $pre )
return $pre ;
yourls_do_action ( 'pre_check_ip_flood' , $ip ); // at this point $ip can be '', check it if your plugin hooks in here
2013-12-11 18:31:57 +01:00
// Raise white flag if installing or if no flood delay defined
2013-04-07 12:52:52 +02:00
if (
( defined ( 'YOURLS_FLOOD_DELAY_SECONDS' ) && YOURLS_FLOOD_DELAY_SECONDS === 0 ) ||
2013-12-11 18:31:57 +01:00
! defined ( 'YOURLS_FLOOD_DELAY_SECONDS' ) ||
yourls_is_installing ()
2013-04-07 12:52:52 +02:00
)
return true ;
2013-12-11 18:33:58 +01:00
// Don't throttle logged in users
if ( yourls_is_private () ) {
if ( yourls_is_valid_user () === true )
return true ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Don't throttle whitelist IPs
if ( defined ( 'YOURLS_FLOOD_IP_WHITELIST' ) && YOURLS_FLOOD_IP_WHITELIST ) {
$whitelist_ips = explode ( ',' , YOURLS_FLOOD_IP_WHITELIST );
foreach ( ( array ) $whitelist_ips as $whitelist_ip ) {
$whitelist_ip = trim ( $whitelist_ip );
if ( $whitelist_ip == $ip )
return true ;
}
}
2017-06-20 23:12:04 +02:00
2013-12-11 18:33:58 +01:00
$ip = ( $ip ? yourls_sanitize_ip ( $ip ) : yourls_get_IP () );
2013-04-07 12:52:52 +02:00
yourls_do_action ( 'check_ip_flood' , $ip );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
global $ydb ;
$table = YOURLS_DB_TABLE_URL ;
2017-06-20 23:12:04 +02:00
2017-09-01 18:34:35 +02:00
$lasttime = $ydb -> fetchValue ( " SELECT `timestamp` FROM $table WHERE `ip` = :ip ORDER BY `timestamp` DESC LIMIT 1 " , array ( 'ip' => $ip ) );
2013-04-07 12:52:52 +02:00
if ( $lasttime ) {
$now = date ( 'U' );
$then = date ( 'U' , strtotime ( $lasttime ) );
if ( ( $now - $then ) <= YOURLS_FLOOD_DELAY_SECONDS ) {
// Flood!
yourls_do_action ( 'ip_flood' , $ip , $now - $then );
2015-07-28 19:09:44 -05:00
yourls_die ( yourls__ ( 'Too many URLs added too fast. Slow down please.' ), yourls__ ( 'Too Many Requests' ), 429 );
2013-04-07 12:52:52 +02:00
}
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return true ;
}
/**
* Check if YOURLS is installing
*
* @ return bool
* @ since 1.6
*/
function yourls_is_installing () {
$installing = defined ( 'YOURLS_INSTALLING' ) && YOURLS_INSTALLING == true ;
return yourls_apply_filter ( 'is_installing' , $installing );
}
/**
* Check if YOURLS is upgrading
*
* @ return bool
* @ since 1.6
*/
function yourls_is_upgrading () {
$upgrading = defined ( 'YOURLS_UPGRADING' ) && YOURLS_UPGRADING == true ;
return yourls_apply_filter ( 'is_upgrading' , $upgrading );
}
2013-02-13 09:45:33 +00:00
/**
* Check if YOURLS is installed
*
2013-05-05 00:29:16 +02:00
* Checks property $ydb -> installed that is created by yourls_get_all_options ()
2013-05-04 23:48:06 +02:00
*
* See inline comment for updating from 1.3 or prior .
*
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_is_installed () {
2013-05-04 23:48:06 +02:00
global $ydb ;
2017-08-28 21:16:27 +02:00
return yourls_apply_filter ( 'is_installed' , $ydb -> is_installed () );
2017-08-18 19:56:01 +02:00
}
2017-06-20 23:12:04 +02:00
2017-08-18 19:56:01 +02:00
/**
* Set installed state
*
* @ since 1.7 . 3
* @ param bool $bool whether YOURLS is installed or not
* @ return void
*/
function yourls_set_installed ( $bool ) {
global $ydb ;
$ydb -> set_installed ( $bool );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Generate random string of ( int ) $length length and type $type ( see function for details )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_rnd_string ( $length = 5 , $type = 0 , $charlist = '' ) {
$str = '' ;
$length = intval ( $length );
// define possible characters
switch ( $type ) {
// custom char list, or comply to charset as defined in config
case '0' :
$possible = $charlist ? $charlist : yourls_get_shorturl_charset () ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// no vowels to make no offending word, no 0/1/o/l to avoid confusion between letters & digits. Perfect for passwords.
case '1' :
$possible = " 23456789bcdfghjkmnpqrstvwxyz " ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Same, with lower + upper
case '2' :
$possible = " 23456789bcdfghjkmnpqrstvwxyzBCDFGHJKMNPQRSTVWXYZ " ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// all letters, lowercase
case '3' :
$possible = " abcdefghijklmnopqrstuvwxyz " ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// all letters, lowercase + uppercase
case '4' :
$possible = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
break ;
2017-06-20 23:12:04 +02:00
// all digits & letters lowercase
2013-04-07 12:52:52 +02:00
case '5' :
$possible = " 0123456789abcdefghijklmnopqrstuvwxyz " ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// all digits & letters lowercase + uppercase
case '6' :
$possible = " 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ " ;
break ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
}
2014-02-07 15:14:50 +01:00
$str = substr ( str_shuffle ( $possible ), 0 , $length );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'rnd_string' , $str , $length , $type , $charlist );
}
2013-02-13 09:45:33 +00:00
/**
2013-04-07 12:52:52 +02:00
* Add a query var to a URL and return URL . Completely stolen from WP .
2017-06-20 23:12:04 +02:00
*
2013-04-07 12:52:52 +02:00
* Works with one of these parameter patterns :
* array ( 'var' => 'value' )
* array ( 'var' => 'value' ), $url
* 'var' , 'value'
2017-06-20 23:12:04 +02:00
* 'var' , 'value' , $url
2013-05-03 17:48:23 +02:00
* If $url omitted , uses $_SERVER [ 'REQUEST_URI' ]
2013-02-13 09:45:33 +00:00
*
2015-04-20 19:50:06 +02:00
* The result of this function call is a URL : it should be escaped before being printed as HTML
*
* @ since 1.5
* @ param string | array $param1 Either newkey or an associative_array .
* @ param string $param2 Either newvalue or oldquery or URI .
* @ param string $param3 Optional . Old query or URI .
* @ return string New URL query string .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_add_query_arg () {
$ret = '' ;
if ( is_array ( func_get_arg ( 0 ) ) ) {
if ( @ func_num_args () < 2 || false === @ func_get_arg ( 1 ) )
$uri = $_SERVER [ 'REQUEST_URI' ];
else
$uri = @ func_get_arg ( 1 );
} else {
if ( @ func_num_args () < 3 || false === @ func_get_arg ( 2 ) )
$uri = $_SERVER [ 'REQUEST_URI' ];
else
$uri = @ func_get_arg ( 2 );
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$uri = str_replace ( '&' , '&' , $uri );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( $frag = strstr ( $uri , '#' ) )
$uri = substr ( $uri , 0 , - strlen ( $frag ) );
else
$frag = '' ;
if ( preg_match ( '|^https?://|i' , $uri , $matches ) ) {
$protocol = $matches [ 0 ];
$uri = substr ( $uri , strlen ( $protocol ) );
} else {
$protocol = '' ;
}
if ( strpos ( $uri , '?' ) !== false ) {
$parts = explode ( '?' , $uri , 2 );
if ( 1 == count ( $parts ) ) {
$base = '?' ;
$query = $parts [ 0 ];
} else {
$base = $parts [ 0 ] . '?' ;
$query = $parts [ 1 ];
}
} elseif ( ! empty ( $protocol ) || strpos ( $uri , '=' ) === false ) {
$base = $uri . '?' ;
$query = '' ;
} else {
$base = '' ;
$query = $uri ;
}
parse_str ( $query , $qs );
$qs = yourls_urlencode_deep ( $qs ); // this re-URL-encodes things that were already in the query string
if ( is_array ( func_get_arg ( 0 ) ) ) {
$kayvees = func_get_arg ( 0 );
$qs = array_merge ( $qs , $kayvees );
} else {
$qs [ func_get_arg ( 0 )] = func_get_arg ( 1 );
}
foreach ( ( array ) $qs as $k => $v ) {
if ( $v === false )
unset ( $qs [ $k ] );
}
$ret = http_build_query ( $qs );
$ret = trim ( $ret , '?' );
$ret = preg_replace ( '#=(&|$)#' , '$1' , $ret );
$ret = $protocol . $base . $ret . $frag ;
$ret = rtrim ( $ret , '?' );
return $ret ;
}
2013-02-13 09:45:33 +00:00
/**
* Navigates through an array and encodes the values to be used in a URL . Stolen from WP , used in yourls_add_query_arg ()
*
*/
2013-04-07 12:52:52 +02:00
function yourls_urlencode_deep ( $value ) {
$value = is_array ( $value ) ? array_map ( 'yourls_urlencode_deep' , $value ) : urlencode ( $value );
return $value ;
}
2013-02-13 09:45:33 +00:00
/**
* Remove arg from query . Opposite of yourls_add_query_arg . Stolen from WP .
*
2015-04-20 19:50:06 +02:00
* The result of this function call is a URL : it should be escaped before being printed as HTML
*
* @ since 1.5
* @ param string | array $key Query key or keys to remove .
* @ param bool | string $query Optional . When false uses the $_SERVER value . Default false .
* @ return string New URL query string .
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_remove_query_arg ( $key , $query = false ) {
if ( is_array ( $key ) ) { // removing multiple keys
foreach ( $key as $k )
$query = yourls_add_query_arg ( $k , false , $query );
return $query ;
}
return yourls_add_query_arg ( $key , false , $query );
}
2013-02-13 09:45:33 +00:00
/**
* Converts keyword into short link ( prepend with YOURLS base URL )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_link ( $keyword = '' ) {
$link = YOURLS_SITE . '/' . yourls_sanitize_keyword ( $keyword );
return yourls_apply_filter ( 'yourls_link' , $link , $keyword );
}
2013-02-13 09:45:33 +00:00
/**
* Converts keyword into stat link ( prepend with YOURLS base URL , append + )
*
*/
2013-04-07 12:52:52 +02:00
function yourls_statlink ( $keyword = '' ) {
$link = YOURLS_SITE . '/' . yourls_sanitize_keyword ( $keyword ) . '+' ;
if ( yourls_is_ssl () )
2014-02-02 17:18:45 +01:00
$link = yourls_set_url_scheme ( $link , 'https' );
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'yourls_statlink' , $link , $keyword );
}
2013-02-13 09:45:33 +00:00
/**
* Check if we ' re in API mode . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_API () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_API' ) && YOURLS_API == true ;
return yourls_apply_filter ( 'is_API' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if we ' re in Ajax mode . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_Ajax () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_AJAX' ) && YOURLS_AJAX == true ;
return yourls_apply_filter ( 'is_Ajax' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if we ' re in GO mode ( yourls - go . php ) . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_GO () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_GO' ) && YOURLS_GO == true ;
return yourls_apply_filter ( 'is_GO' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if we ' re displaying stats infos ( yourls - infos . php ) . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_infos () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_INFOS' ) && YOURLS_INFOS == true ;
return yourls_apply_filter ( 'is_infos' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if we ' re in the admin area . Returns bool
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_admin () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_ADMIN' ) && YOURLS_ADMIN == true ;
return yourls_apply_filter ( 'is_admin' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Check if the server seems to be running on Windows . Not exactly sure how reliable this is .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_windows () {
return defined ( 'DIRECTORY_SEPARATOR' ) && DIRECTORY_SEPARATOR == '\\' ;
}
2013-02-13 09:45:33 +00:00
/**
* Check if SSL is required . Returns bool .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_needs_ssl () {
2015-05-07 22:00:32 +02:00
$return = defined ( 'YOURLS_ADMIN_SSL' ) && YOURLS_ADMIN_SSL == true ;
return yourls_apply_filter ( 'needs_ssl' , $return );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Return admin link , with SSL preference if applicable .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_admin_url ( $page = '' ) {
$admin = YOURLS_SITE . '/admin/' . $page ;
2015-05-07 22:00:32 +02:00
if ( yourls_is_ssl () or yourls_needs_ssl () ) {
2014-02-02 17:18:45 +01:00
$admin = yourls_set_url_scheme ( $admin , 'https' );
2015-05-07 22:00:32 +02:00
}
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'admin_url' , $admin , $page );
}
2013-02-13 09:45:33 +00:00
/**
* Return YOURLS_SITE or URL under YOURLS setup , with SSL preference
*
*/
2013-04-07 12:52:52 +02:00
function yourls_site_url ( $echo = true , $url = '' ) {
$url = yourls_get_relative_url ( $url );
$url = trim ( YOURLS_SITE . '/' . $url , '/' );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Do not enforce (checking yourls_need_ssl() ) but check current usage so it won't force SSL on non-admin pages
2015-05-07 22:00:32 +02:00
if ( yourls_is_ssl () ) {
2014-02-02 17:18:45 +01:00
$url = yourls_set_url_scheme ( $url , 'https' );
2015-05-07 22:00:32 +02:00
}
2013-04-07 12:52:52 +02:00
$url = yourls_apply_filter ( 'site_url' , $url );
2015-05-07 22:00:32 +02:00
if ( $echo ) {
2013-04-07 12:52:52 +02:00
echo $url ;
2015-05-07 22:00:32 +02:00
}
2013-04-07 12:52:52 +02:00
return $url ;
}
2013-02-13 09:45:33 +00:00
/**
* Check if SSL is used , returns bool . Stolen from WP .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_ssl () {
$is_ssl = false ;
if ( isset ( $_SERVER [ 'HTTPS' ] ) ) {
if ( 'on' == strtolower ( $_SERVER [ 'HTTPS' ] ) )
$is_ssl = true ;
if ( '1' == $_SERVER [ 'HTTPS' ] )
$is_ssl = true ;
} elseif ( isset ( $_SERVER [ 'SERVER_PORT' ] ) && ( '443' == $_SERVER [ 'SERVER_PORT' ] ) ) {
$is_ssl = true ;
}
return yourls_apply_filter ( 'is_ssl' , $is_ssl );
}
2013-02-13 09:45:33 +00:00
/**
2013-12-13 22:08:22 +01:00
* Get a remote page title
*
* This function returns a string : either the page title as defined in HTML , or the URL if not found
* The function tries to convert funky characters found in titles to UTF8 , from the detected charset .
* Charset in use is guessed from HTML meta tag , or if not found , from server 's ' content - type ' response .
2013-02-13 09:45:33 +00:00
*
2013-12-13 22:08:22 +01:00
* @ param string $url URL
* @ return string Title ( sanitized ) or the URL if no title found
2013-02-13 09:45:33 +00:00
*/
2013-04-07 12:52:52 +02:00
function yourls_get_remote_title ( $url ) {
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_get_remote_title' , false , $url );
if ( false !== $pre )
return $pre ;
$url = yourls_sanitize_url ( $url );
2017-06-20 23:12:04 +02:00
// Only deal with http(s)://
2013-11-12 11:47:40 +01:00
if ( ! in_array ( yourls_get_protocol ( $url ), array ( 'http://' , 'https://' ) ) )
2017-06-20 23:12:04 +02:00
return $url ;
2013-04-07 12:52:52 +02:00
$title = $charset = false ;
2017-06-20 23:12:04 +02:00
2015-12-18 22:04:30 +01:00
$max_bytes = yourls_apply_filter ( 'get_remote_title_max_byte' , 32768 ); // limit data fetching to 32K in order to find a <title> tag
2017-06-20 23:12:04 +02:00
2015-11-28 17:47:08 +01:00
$response = yourls_http_get ( $url , array (), array (), array ( 'max_bytes' => $max_bytes ) ); // can be a Request object or an error string
2013-12-13 22:08:22 +01:00
if ( is_string ( $response ) ) {
return $url ;
}
2017-06-20 23:12:04 +02:00
2013-12-13 22:08:22 +01:00
// Page content. No content? Return the URL
$content = $response -> body ;
2013-11-12 11:47:40 +01:00
if ( ! $content )
2013-04-07 12:52:52 +02:00
return $url ;
2017-06-20 23:12:04 +02:00
2013-12-13 22:08:22 +01:00
// look for <title>. No title found? Return the URL
2013-11-12 11:47:40 +01:00
if ( preg_match ( '/<title>(.*?)<\/title>/is' , $content , $found ) ) {
$title = $found [ 1 ];
unset ( $found );
2013-04-07 12:52:52 +02:00
}
2013-12-13 22:08:22 +01:00
if ( ! $title )
2013-11-12 11:47:40 +01:00
return $url ;
2017-06-20 23:12:04 +02:00
2013-12-13 22:08:22 +01:00
// Now we have a title. We'll try to get proper utf8 from it.
2017-06-20 23:12:04 +02:00
2013-12-13 22:08:22 +01:00
// Get charset as (and if) defined by the HTML meta tag. We should match
2013-11-12 11:47:40 +01:00
// <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
2013-12-13 22:08:22 +01:00
// or <meta charset='utf-8'> and all possible variations: see https://gist.github.com/ozh/7951236
if ( preg_match ( '/<meta[^>]*charset\s*=["\' ]*([a-zA-Z0-9\-_]+)/is' , $content , $found ) ) {
$charset = $found [ 1 ];
2013-11-12 11:47:40 +01:00
unset ( $found );
2013-12-13 22:08:22 +01:00
} else {
// No charset found in HTML. Get charset as (and if) defined by the server response
$_charset = current ( $response -> headers -> getValues ( 'content-type' ) );
if ( preg_match ( '/charset=(\S+)/' , $_charset , $found ) ) {
$charset = trim ( $found [ 1 ], ';' );
2013-04-07 12:52:52 +02:00
unset ( $found );
}
}
2013-12-13 22:08:22 +01:00
// Conversion to utf-8 if what we have is not utf8 already
if ( strtolower ( $charset ) != 'utf-8' && function_exists ( 'mb_convert_encoding' ) ) {
// We use @ to remove warnings because mb_ functions are easily bitching about illegal chars
2013-04-07 12:52:52 +02:00
if ( $charset ) {
$title = @ mb_convert_encoding ( $title , 'UTF-8' , $charset );
} else {
$title = @ mb_convert_encoding ( $title , 'UTF-8' );
}
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Remove HTML entities
$title = html_entity_decode ( $title , ENT_QUOTES , 'UTF-8' );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Strip out evil things
2014-11-05 22:54:33 +01:00
$title = yourls_sanitize_title ( $title , $url );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'get_remote_title' , $title , $url );
}
2013-02-13 09:45:33 +00:00
/**
* Quick UA check for mobile devices . Return boolean .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_is_mobile_device () {
// Strings searched
$mobiles = array (
'android' , 'blackberry' , 'blazer' ,
'compal' , 'elaine' , 'fennec' , 'hiptop' ,
'iemobile' , 'iphone' , 'ipod' , 'ipad' ,
'iris' , 'kindle' , 'opera mobi' , 'opera mini' ,
'palm' , 'phone' , 'pocket' , 'psp' , 'symbian' ,
'treo' , 'wap' , 'windows ce' , 'windows phone'
);
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Current user-agent
$current = strtolower ( $_SERVER [ 'HTTP_USER_AGENT' ] );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Check and return
$is_mobile = ( str_replace ( $mobiles , '' , $current ) != $current );
return yourls_apply_filter ( 'is_mobile_device' , $is_mobile );
}
2013-02-13 09:45:33 +00:00
/**
2015-04-10 22:46:06 +02:00
* Get request in YOURLS base ( eg in 'http://sho.rt/yourls/abcd' get 'abdc' )
2013-02-13 09:45:33 +00:00
*
2017-06-20 23:12:04 +02:00
* With no parameter passed , this function will guess current page and consider
2020-03-25 14:41:20 +01:00
* it is the requested page .
2017-06-20 23:12:04 +02:00
* For testing purposes , parameters can be passed .
*
* @ since 1.5
* @ param string $yourls_site Optional , YOURLS installation URL ( default to constant YOURLS_SITE )
2020-03-25 14:41:20 +01:00
* @ param string $uri Optional , page requested ( default to $_SERVER [ 'REQUEST_URI' ] eg '/yourls/abcd' )
2017-06-20 23:12:04 +02:00
* @ return string request relative to YOURLS base ( eg 'abdc' )
2013-02-13 09:45:33 +00:00
*/
2017-06-20 23:12:04 +02:00
function yourls_get_request ( $yourls_site = false , $uri = false ) {
2013-04-07 12:52:52 +02:00
// Allow plugins to short-circuit the whole function
$pre = yourls_apply_filter ( 'shunt_get_request' , false );
if ( false !== $pre )
return $pre ;
2017-06-20 23:12:04 +02:00
yourls_do_action ( 'pre_get_request' , $yourls_site , $uri );
// Default values
if ( false === $yourls_site ) {
$yourls_site = YOURLS_SITE ;
}
if ( false === $uri ) {
2020-03-25 14:41:20 +01:00
$uri = $_SERVER [ 'REQUEST_URI' ];
2017-06-20 23:12:04 +02:00
}
// Even though the config sample states YOURLS_SITE should be set without trailing slash...
$yourls_site = rtrim ( $yourls_site , '/' );
2020-03-25 14:41:20 +01:00
// Now strip the YOURLS_SITE path part out of the requested URI, and get the request relative to YOURLS base
// +---------------------------+-------------------------+---------------------+--------------+
// | if we request | and YOURLS is hosted on | YOURLS path part is | "request" is |
// +---------------------------+-------------------------+---------------------+--------------+
// | http://sho.rt/abc | http://sho.rt | / | abc |
// | https://SHO.rt/subdir/abc | https://shor.rt/subdir/ | /subdir/ | abc |
// +---------------------------+-------------------------+---------------------+--------------+
// and so on. You can find various test cases in /tests/tests/utilities/get_request.php
// Take only the URL_PATH part of YOURLS_SITE (ie "https://sho.rt:1337/path/to/yourls" -> "/path/to/yourls")
$yourls_site = parse_url ( $yourls_site , PHP_URL_PATH ) . '/' ;
// Strip path part from request if exists
$request = $uri ;
if ( substr ( $uri , 0 , strlen ( $yourls_site )) == $yourls_site ) {
$request = ltrim ( substr ( $uri , strlen ( $yourls_site )), '/' );
}
2013-04-07 12:52:52 +02:00
// Unless request looks like a full URL (ie request is a simple keyword) strip query string
if ( ! preg_match ( " @^[a-zA-Z]+://.+@ " , $request ) ) {
$request = current ( explode ( '?' , $request ) );
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return yourls_apply_filter ( 'get_request' , $request );
}
2013-02-13 09:45:33 +00:00
/**
2020-03-25 14:41:20 +01:00
* Change protocol of a URL to HTTPS if we are currently on HTTPS
2013-02-13 09:45:33 +00:00
*
2020-03-25 14:41:20 +01:00
* This function is used to avoid insert 'http://' images or scripts in a page when it ' s served through HTTPS ,
* to avoid " mixed content " errors .
* So :
* - if you are on http :// sho . rt / , 'http://something' and 'https://something' are left untouched .
* - if you are on https :/ sho . rt / , 'http://something' is changed to 'https://something'
*
* So , arguably , this function is poorly named . It should be something like yourls_match_current_protocol_if_we_re_on_https
*
* @ since 1.5 . 1
* @ param string $url a URL
* @ param string $normal Optional , the standard scheme ( defaults to 'http://' )
* @ param string $ssl Optional , the SSL scheme ( defaults to 'https://' )
* @ return string the modified URL , if applicable
2013-02-13 09:45:33 +00:00
*/
2013-12-04 17:39:30 +01:00
function yourls_match_current_protocol ( $url , $normal = 'http://' , $ssl = 'https://' ) {
2020-03-25 14:41:20 +01:00
// we're only doing something if we're currently serving through SSL and the input URL begins with 'http://' or 'https://'
if ( yourls_is_ssl () && in_array ( yourls_get_protocol ( $url ), array ( 'http://' , 'https://' ) ) ) {
$url = str_replace ( $normal , $ssl , $url );
}
return yourls_apply_filter ( 'match_current_protocol' , $url );
2013-04-07 12:52:52 +02:00
}
2013-02-13 09:45:33 +00:00
/**
* Fix $_SERVER [ 'REQUEST_URI' ] variable for various setups . Stolen from WP .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_fix_request_uri () {
$default_server_values = array (
'SERVER_SOFTWARE' => '' ,
'REQUEST_URI' => '' ,
);
$_SERVER = array_merge ( $default_server_values , $_SERVER );
// Fix for IIS when running with PHP ISAPI
if ( empty ( $_SERVER [ 'REQUEST_URI' ] ) || ( php_sapi_name () != 'cgi-fcgi' && preg_match ( '/^Microsoft-IIS\//' , $_SERVER [ 'SERVER_SOFTWARE' ] ) ) ) {
// IIS Mod-Rewrite
if ( isset ( $_SERVER [ 'HTTP_X_ORIGINAL_URL' ] ) ) {
$_SERVER [ 'REQUEST_URI' ] = $_SERVER [ 'HTTP_X_ORIGINAL_URL' ];
}
// IIS Isapi_Rewrite
else if ( isset ( $_SERVER [ 'HTTP_X_REWRITE_URL' ] ) ) {
$_SERVER [ 'REQUEST_URI' ] = $_SERVER [ 'HTTP_X_REWRITE_URL' ];
} else {
// Use ORIG_PATH_INFO if there is no PATH_INFO
if ( ! isset ( $_SERVER [ 'PATH_INFO' ] ) && isset ( $_SERVER [ 'ORIG_PATH_INFO' ] ) )
$_SERVER [ 'PATH_INFO' ] = $_SERVER [ 'ORIG_PATH_INFO' ];
// Some IIS + PHP configurations puts the script-name in the path-info (No need to append it twice)
if ( isset ( $_SERVER [ 'PATH_INFO' ] ) ) {
if ( $_SERVER [ 'PATH_INFO' ] == $_SERVER [ 'SCRIPT_NAME' ] )
$_SERVER [ 'REQUEST_URI' ] = $_SERVER [ 'PATH_INFO' ];
else
$_SERVER [ 'REQUEST_URI' ] = $_SERVER [ 'SCRIPT_NAME' ] . $_SERVER [ 'PATH_INFO' ];
}
// Append the query string if it exists and isn't null
if ( ! empty ( $_SERVER [ 'QUERY_STRING' ] ) ) {
$_SERVER [ 'REQUEST_URI' ] .= '?' . $_SERVER [ 'QUERY_STRING' ];
}
}
}
}
2013-02-13 09:45:33 +00:00
/**
* Shutdown function , runs just before PHP shuts down execution . Stolen from WP
*
*/
2013-04-07 12:52:52 +02:00
function yourls_shutdown () {
yourls_do_action ( 'shutdown' );
}
2013-02-13 09:45:33 +00:00
/**
* Auto detect custom favicon in / user directory , fallback to YOURLS favicon , and echo / return its URL
*
*/
2013-04-07 12:52:52 +02:00
function yourls_favicon ( $echo = true ) {
static $favicon = null ;
2017-06-20 23:12:04 +02:00
2014-03-17 21:09:52 +01:00
if ( $favicon !== null ) {
if ( $echo ) {
echo $favicon ;
}
2017-06-20 23:12:04 +02:00
return $favicon ;
2014-03-17 21:09:52 +01:00
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$custom = null ;
// search for favicon.(gif|ico|png|jpg|svg)
foreach ( array ( 'gif' , 'ico' , 'png' , 'jpg' , 'svg' ) as $ext ) {
if ( file_exists ( YOURLS_USERDIR . '/favicon.' . $ext ) ) {
$custom = 'favicon.' . $ext ;
break ;
}
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
if ( $custom ) {
$favicon = yourls_site_url ( false , YOURLS_USERURL . '/' . $custom );
} else {
$favicon = yourls_site_url ( false ) . '/images/favicon.gif' ;
}
2014-03-17 21:09:52 +01:00
if ( $echo ) {
2013-04-07 12:52:52 +02:00
echo $favicon ;
2014-03-17 21:09:52 +01:00
}
2013-04-07 12:52:52 +02:00
return $favicon ;
}
2013-02-13 09:45:33 +00:00
/**
* Check for maintenance mode . If yes , die . See yourls_maintenance_mode () . Stolen from WP .
*
*/
2013-04-07 12:52:52 +02:00
function yourls_check_maintenance_mode () {
$file = YOURLS_ABSPATH . '/.maintenance' ;
if ( ! file_exists ( $file ) || yourls_is_upgrading () || yourls_is_installing () )
return ;
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
global $maintenance_start ;
2013-09-07 17:49:56 +02:00
include_once ( $file );
2013-04-07 12:52:52 +02:00
// If the $maintenance_start timestamp is older than 10 minutes, don't die.
if ( ( time () - $maintenance_start ) >= 600 )
return ;
// Use any /user/maintenance.php file
if ( file_exists ( YOURLS_USERDIR . '/maintenance.php' ) ) {
2013-09-07 17:49:56 +02:00
include_once ( YOURLS_USERDIR . '/maintenance.php' );
2013-04-07 12:52:52 +02:00
die ();
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// https://www.youtube.com/watch?v=Xw-m4jEY-Ns
$title = yourls__ ( 'Service temporarily unavailable' );
$message = yourls__ ( 'Our service is currently undergoing scheduled maintenance.' ) . " </p> \n <p> " .
yourls__ ( 'Things should not last very long, thank you for your patience and please excuse the inconvenience' );
yourls_die ( $message , $title , 503 );
}
/**
* Return current admin page , or null if not an admin page
*
* @ return mixed string if admin page , null if not an admin page
* @ since 1.6
*/
function yourls_current_admin_page () {
if ( yourls_is_admin () ) {
$current = substr ( yourls_get_request (), 6 );
2017-06-20 23:12:04 +02:00
if ( $current === false )
2013-04-07 12:52:52 +02:00
$current = 'index.php' ; // if current page is http://sho.rt/admin/ instead of http://sho.rt/admin/index.php
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
return $current ;
}
return null ;
}
/**
* Check if a URL protocol is allowed
*
* Checks a URL against a list of whitelisted protocols . Protocols must be defined with
* their complete scheme name , ie 'stuff:' or 'stuff://' ( for instance , 'mailto:' is a valid
* protocol , 'mailto://' isn 't, and ' http : ' with no double slashed isn' t either
*
* @ since 1.6
2014-11-05 22:35:51 +01:00
* @ see yourls_get_protocol ()
2013-04-07 12:52:52 +02:00
*
* @ param string $url URL to be check
* @ param array $protocols Optional . Array of protocols , defaults to global $yourls_allowedprotocols
* @ return boolean true if protocol allowed , false otherwise
*/
function yourls_is_allowed_protocol ( $url , $protocols = array () ) {
if ( ! $protocols ) {
global $yourls_allowedprotocols ;
$protocols = $yourls_allowedprotocols ;
}
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
$protocol = yourls_get_protocol ( $url );
return yourls_apply_filter ( 'is_allowed_protocol' , in_array ( $protocol , $protocols ), $url , $protocols );
}
/**
* Get protocol from a URL ( eg mailto : , http :// ... )
*
2014-11-05 22:35:51 +01:00
* What we liberally call a " protocol " in YOURLS is the scheme name + colon + double slashes if present of a URI . Examples :
* " something://blah " -> " something:// "
* " something:blah " -> " something: "
* " something:/blah " -> " something: "
*
* Unit Tests for this function are located in tests / format / urls . php
*
2013-04-07 12:52:52 +02:00
* @ since 1.6
*
* @ param string $url URL to be check
* @ return string Protocol , with slash slash if applicable . Empty string if no protocol
*/
function yourls_get_protocol ( $url ) {
2014-11-05 22:35:51 +01:00
preg_match ( '!^[a-zA-Z][a-zA-Z0-9\+\.-]+:(//)?!' , $url , $matches );
2013-04-07 12:52:52 +02:00
/*
http :// en . wikipedia . org / wiki / URI_scheme #Generic_syntax
The scheme name consists of a sequence of characters beginning with a letter and followed by any
combination of letters , digits , plus ( " + " ), period ( " . " ), or hyphen ( " - " ) . Although schemes are
case - insensitive , the canonical form is lowercase and documents that specify schemes must do so
with lowercase letters . It is followed by a colon ( " : " ) .
*/
$protocol = ( isset ( $matches [ 0 ] ) ? $matches [ 0 ] : '' );
return yourls_apply_filter ( 'get_protocol' , $protocol , $url );
}
/**
* Get relative URL ( eg 'abc' from 'http://sho.rt/abc' )
*
* Treat indifferently http & https . If a URL isn ' t relative to the YOURLS install , return it as is
* or return empty string if $strict is true
*
* @ since 1.6
* @ param string $url URL to relativize
* @ param bool $strict if true and if URL isn ' t relative to YOURLS install , return empty string
2017-06-20 23:12:04 +02:00
* @ return string URL
2013-04-07 12:52:52 +02:00
*/
function yourls_get_relative_url ( $url , $strict = true ) {
$url = yourls_sanitize_url ( $url );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Remove protocols to make it easier
$noproto_url = str_replace ( 'https:' , 'http:' , $url );
$noproto_site = str_replace ( 'https:' , 'http:' , YOURLS_SITE );
2017-06-20 23:12:04 +02:00
2013-04-07 12:52:52 +02:00
// Trim URL from YOURLS root URL : if no modification made, URL wasn't relative
$_url = str_replace ( $noproto_site . '/' , '' , $noproto_url );
if ( $_url == $noproto_url )
$_url = ( $strict ? '' : $url );
return yourls_apply_filter ( 'get_relative_url' , $_url , $url );
}
/**
* Marks a function as deprecated and informs when it has been used . Stolen from WP .
*
* There is a hook deprecated_function that will be called that can be used
* to get the backtrace up to what file and function called the deprecated
* function .
*
* The current behavior is to trigger a user error if YOURLS_DEBUG is true .
*
* This function is to be used in every function that is deprecated .
*
* @ since 1.6
* @ uses yourls_do_action () Calls 'deprecated_function' and passes the function name , what to use instead ,
* and the version the function was deprecated in .
2014-10-26 16:34:41 +01:00
* @ uses yourls_apply_filter () Calls 'deprecated_function_trigger_error' and expects boolean value of true to do
2013-04-07 12:52:52 +02:00
* trigger or false to not trigger error .
*
* @ param string $function The function that was called
* @ param string $version The version of WordPress that deprecated the function
* @ param string $replacement Optional . The function that should have been called
*/
function yourls_deprecated_function ( $function , $version , $replacement = null ) {
yourls_do_action ( 'deprecated_function' , $function , $replacement , $version );
// Allow plugin to filter the output error trigger
2020-03-14 17:29:31 +01:00
if ( yourls_get_debug_mode () && yourls_apply_filter ( 'deprecated_function_trigger_error' , true ) ) {
2013-04-07 12:52:52 +02:00
if ( ! is_null ( $replacement ) )
trigger_error ( sprintf ( yourls__ ( '%1$s is <strong>deprecated</strong> since version %2$s! Use %3$s instead.' ), $function , $version , $replacement ) );
else
trigger_error ( sprintf ( yourls__ ( '%1$s is <strong>deprecated</strong> since version %2$s with no alternative available.' ), $function , $version ) );
}
}
/**
* Return the value if not an empty string
*
* Used with array_filter (), to remove empty keys but not keys with value 0 or false
*
* @ since 1.6
* @ param mixed $val Value to test against ''
* @ return bool True if not an empty string
*/
function yourls_return_if_not_empty_string ( $val ) {
return ( $val !== '' );
}
2013-12-26 15:40:47 +01:00
2015-05-03 12:37:13 +02:00
/**
* Returns true .
*
* Useful for returning true to filters easily .
*
* @ since 1.7 . 1
* @ return bool True .
*/
function yourls_return_true () {
return true ;
}
/**
* Returns false .
*
* Useful for returning false to filters easily .
*
* @ since 1.7 . 1
* @ return bool False .
*/
function yourls_return_false () {
return false ;
}
/**
* Returns 0.
*
* Useful for returning 0 to filters easily .
*
* @ since 1.7 . 1
* @ return int 0.
*/
function yourls_return_zero () {
return 0 ;
}
/**
* Returns an empty array .
*
* Useful for returning an empty array to filters easily .
*
* @ since 1.7 . 1
* @ return array Empty array .
*/
function yourls_return_empty_array () {
return array ();
}
/**
* Returns null .
*
* Useful for returning null to filters easily .
*
* @ since 1.7 . 1
* @ return null Null value .
*/
function yourls_return_null () {
return null ;
}
/**
* Returns an empty string .
*
* Useful for returning an empty string to filters easily .
*
* @ since 1.7 . 1
* @ return string Empty string .
*/
function yourls_return_empty_string () {
return '' ;
}
2013-12-26 15:40:47 +01:00
/**
* Add a message to the debug log
*
* When in debug mode ( YOURLS_DEBUG == true ) the debug log is echoed in yourls_html_footer ()
* Log messages are appended to $ydb -> debug_log array , which is instanciated within class ezSQLcore_YOURLS
*
* @ since 1.7
* @ param string $msg Message to add to the debug log
* @ return string The message itself
*/
function yourls_debug_log ( $msg ) {
global $ydb ;
2020-04-05 13:37:42 +02:00
yourls_do_action ( 'debug_log' , $msg );
2017-08-21 15:19:55 +02:00
$ydb -> getProfiler () -> log ( $msg );
2013-12-26 15:40:47 +01:00
return $msg ;
2013-12-28 13:00:18 +01:00
}
2017-08-21 15:19:55 +02:00
/**
* Get the debug log
*
* @ since 1.7 . 3
* @ return array
*/
function yourls_get_debug_log () {
global $ydb ;
2017-09-06 21:58:28 +02:00
// Check if we have a profiler registered (will not be the case if the DB hasn't been properly connected to)
if ( $ydb -> getProfiler ()) {
return $ydb -> getProfiler () -> get_log ();
}
return array ();
2017-08-21 15:19:55 +02:00
}
2017-08-18 19:56:01 +02:00
/**
2020-03-14 17:29:31 +01:00
* Debug mode set
2017-08-18 19:56:01 +02:00
*
* @ since 1.7 . 3
* @ param bool $bool Debug on or off
*/
function yourls_debug_mode ( $bool ) {
global $ydb ;
$bool = ( bool ) $bool ;
2017-09-13 22:45:48 +02:00
// log queries if true
2017-08-18 19:56:01 +02:00
$ydb -> getProfiler () -> setActive ( $bool );
2017-09-13 22:45:48 +02:00
// report notices if true
if ( $bool === true ) {
error_reporting ( - 1 );
} else {
error_reporting ( E_ERROR | E_PARSE );
}
2017-08-18 19:56:01 +02:00
}
2020-03-14 17:29:31 +01:00
/**
* Return YOURLS debug mode
*
* @ since 1.7 . 7
* @ return bool
*/
function yourls_get_debug_mode () {
return ( defined ( 'YOURLS_DEBUG' ) && YOURLS_DEBUG == true );
}
2013-12-28 13:00:18 +01:00
/**
* Explode a URL in an array of ( 'protocol' , 'slashes if any' , 'rest of the URL' )
*
* Some hosts trip up when a query string contains 'http://' - see http :// git . io / j1FlJg
* The idea is that instead of passing the whole URL to a bookmarklet , eg index . php ? u = http :// blah . com ,
* we pass it by pieces to fool the server , eg index . php ? proto = http :& slashes =//& rest = blah . com
*
* Known limitation : this won 't work if the rest of the URL itself contains ' http :// ' , for example
* if rest = blah . com / file . php ? url = http :// foo . com
*
* Sample returns :
*
* with 'mailto:jsmith@example.com?subject=hey' :
* array ( 'protocol' => 'mailto:' , 'slashes' => '' , 'rest' => 'jsmith@example.com?subject=hey' )
*
* with 'http://example.com/blah.html' :
* array ( 'protocol' => 'http:' , 'slashes' => '//' , 'rest' => 'example.com/blah.html' )
*
* @ since 1.7
* @ param string $url URL to be parsed
* @ param array $array Optional , array of key names to be used in returned array
* @ return mixed false if no protocol found , array of ( 'protocol' , 'slashes' , 'rest' ) otherwise
*/
function yourls_get_protocol_slashes_and_rest ( $url , $array = array ( 'protocol' , 'slashes' , 'rest' ) ) {
$proto = yourls_get_protocol ( $url );
2017-06-20 23:12:04 +02:00
2013-12-28 13:00:18 +01:00
if ( ! $proto or count ( $array ) != 3 )
return false ;
2017-06-20 23:12:04 +02:00
2013-12-28 13:00:18 +01:00
list ( $null , $rest ) = explode ( $proto , $url , 2 );
2017-06-20 23:12:04 +02:00
2013-12-28 13:00:18 +01:00
list ( $proto , $slashes ) = explode ( ':' , $proto );
2017-06-20 23:12:04 +02:00
2013-12-28 13:00:18 +01:00
return array ( $array [ 0 ] => $proto . ':' , $array [ 1 ] => $slashes , $array [ 2 ] => $rest );
}
2014-02-02 17:18:45 +01:00
/**
* Set URL scheme ( to HTTP or HTTPS )
*
* @ since 1.7 . 1
* @ param string $url URL
* @ param string $scheme scheme , either 'http' or 'https'
* @ return string URL with chosen scheme
*/
function yourls_set_url_scheme ( $url , $scheme = false ) {
if ( $scheme != 'http' && $scheme != 'https' ) {
return $url ;
}
return preg_replace ( '!^[a-zA-Z0-9\+\.-]+://!' , $scheme . '://' , $url );
}
2017-05-12 23:31:28 +02:00
/**
* Tell if there is a new YOURLS version
*
* This function checks , if needed , if there ' s a new version of YOURLS and , if applicable , display
* an update notice .
*
* @ since 1.7 . 3
*/
function yourls_tell_if_new_version () {
$check = yourls_maybe_check_core_version ();
yourls_debug_log ( 'Check for new version: ' . ( $check ? 'yes' : 'no' ) );
yourls_new_core_version_notice ();
}