initial commit based on SVN rev. 711
18
.gitignore
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
# osx noise
|
||||
.DS_Store
|
||||
profile
|
||||
|
||||
# xcode noise
|
||||
build/*
|
||||
*.mode1
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspective
|
||||
*.perspectivev3
|
||||
*.pbxuser
|
||||
*.xcworkspace
|
||||
xcuserdata
|
||||
|
||||
# svn & cvs
|
||||
.svn
|
||||
CVS
|
51
admin/admin-ajax.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
define('YOURLS_AJAX', true);
|
||||
define('YOURLS_ADMIN', true);
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
yourls_maybe_require_auth();
|
||||
|
||||
// This file will output a JSON string
|
||||
header('Content-type: application/json');
|
||||
|
||||
if( !isset( $_REQUEST['action'] ) )
|
||||
die();
|
||||
|
||||
// Pick action
|
||||
$action = $_REQUEST['action'];
|
||||
switch( $action ) {
|
||||
|
||||
case 'add':
|
||||
yourls_verify_nonce( 'add_url', $_REQUEST['nonce'], false, 'omg error' );
|
||||
$return = yourls_add_new_link( $_REQUEST['url'], $_REQUEST['keyword'] );
|
||||
echo json_encode($return);
|
||||
break;
|
||||
|
||||
case 'edit_display':
|
||||
yourls_verify_nonce( 'edit-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
|
||||
$row = yourls_table_edit_row ( $_REQUEST['keyword'] );
|
||||
echo json_encode( array('html' => $row) );
|
||||
break;
|
||||
|
||||
case 'edit_save':
|
||||
yourls_verify_nonce( 'edit-save_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
|
||||
$return = yourls_edit_link( $_REQUEST['url'], $_REQUEST['keyword'], $_REQUEST['newkeyword'], $_REQUEST['title'] );
|
||||
echo json_encode($return);
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
yourls_verify_nonce( 'delete-link_'.$_REQUEST['id'], $_REQUEST['nonce'], false, 'omg error' );
|
||||
$query = yourls_delete_link_by_keyword( $_REQUEST['keyword'] );
|
||||
echo json_encode(array('success'=>$query));
|
||||
break;
|
||||
|
||||
case 'logout':
|
||||
// unused for the moment
|
||||
yourls_logout();
|
||||
break;
|
||||
|
||||
default:
|
||||
yourls_do_action( 'yourls_ajax_'.$action );
|
||||
|
||||
}
|
||||
|
||||
die();
|
280
admin/index.php
Normal file
@ -0,0 +1,280 @@
|
||||
<?php
|
||||
define( 'YOURLS_ADMIN', true );
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
yourls_maybe_require_auth();
|
||||
|
||||
// Variables
|
||||
$table_url = YOURLS_DB_TABLE_URL;
|
||||
// Default SQL behavior
|
||||
$where = $search_display = $search_text = $search_url = $url = $keyword = '';
|
||||
$search_in_text = 'URL';
|
||||
$search_in_sql = 'url';
|
||||
$sort_by_text = 'Short URL';
|
||||
$sort_by_sql = 'timestamp';
|
||||
$sort_order_text = 'Descending Order';
|
||||
$sort_order_sql = 'desc';
|
||||
$page = ( isset( $_GET['page'] ) ? intval($_GET['page']) : 1 );
|
||||
$search = ( isset( $_GET['s_search'] ) ? htmlspecialchars( trim($_GET['s_search']) ) : '' );
|
||||
$perpage = ( isset( $_GET['perpage'] ) && intval( $_GET['perpage'] ) ? intval($_GET['perpage']) : 15 );
|
||||
$link_limit = ( isset( $_GET['link_limit'] ) && !empty( $_GET['link_limit'] ) ) ? intval($_GET['link_limit']) : '' ;
|
||||
if ( $link_limit !== '' ) {
|
||||
$link_filter = ( isset( $_GET['link_filter'] ) && $_GET['link_filter'] == 'more' ? 'more' : 'less' ) ;
|
||||
$link_moreless = ( $link_filter == 'more' ? '>' : '<' );
|
||||
$where = " AND clicks $link_moreless $link_limit";
|
||||
} else {
|
||||
$link_filter = '';
|
||||
}
|
||||
$date_filter = 'before';
|
||||
$date_first = $date_second = '';
|
||||
$base_page = yourls_admin_url( 'index.php' );
|
||||
|
||||
// Searching
|
||||
if( !empty($search) && !empty($_GET['s_in']) ) {
|
||||
switch($_GET['s_in']) {
|
||||
case 'keyword':
|
||||
$search_in_text = 'Short URL';
|
||||
$search_in_sql = 'keyword';
|
||||
break;
|
||||
case 'url':
|
||||
$search_in_text = 'URL';
|
||||
$search_in_sql = 'url';
|
||||
break;
|
||||
case 'title':
|
||||
$search_in_text = 'Title';
|
||||
$search_in_sql = 'title';
|
||||
break;
|
||||
case 'ip':
|
||||
$search_in_text = 'IP Address';
|
||||
$search_in_sql = 'ip';
|
||||
break;
|
||||
}
|
||||
$search_text = stripslashes($search);
|
||||
$search_display = "Searching for <strong>$search_text</strong> in <strong>$search_in_text</strong>. ";
|
||||
$search_url = "&s_search=$search_text &s_in=$search_in_sql";
|
||||
$search = str_replace('*', '%', '*'.$search.'*');
|
||||
$where .= " AND `$search_in_sql` LIKE ('$search')";
|
||||
}
|
||||
|
||||
// Time span
|
||||
if( !empty($_GET['date_filter']) ) {
|
||||
switch($_GET['date_filter']) {
|
||||
case 'before':
|
||||
$date_filter = 'before';
|
||||
if( yourls_sanitize_date( $_GET['date_first'] ) ) {
|
||||
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
|
||||
$where .= " AND `timestamp` < '$date_first_sql'";
|
||||
$date_first = $_GET['date_first'];
|
||||
}
|
||||
break;
|
||||
case 'after':
|
||||
$date_filter = 'after';
|
||||
if( yourls_sanitize_date( $_GET['date_first'] ) ) {
|
||||
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
|
||||
$where .= " AND `timestamp` > '$date_first_sql'";
|
||||
$date_first = $_GET['date_first'];
|
||||
}
|
||||
break;
|
||||
case 'between':
|
||||
$date_filter = 'between';
|
||||
if( yourls_sanitize_date( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_second'] ) ) {
|
||||
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
|
||||
$date_second_sql = yourls_sanitize_date_for_sql( $_GET['date_second'] );
|
||||
$where .= " AND `timestamp` BETWEEN '$date_first_sql' AND '$date_second_sql'";
|
||||
$date_first = $_GET['date_first'];
|
||||
$date_second = $_GET['date_second'];
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Sorting
|
||||
if( !empty($_GET['s_by']) || !empty($_GET['s_order']) ) {
|
||||
switch($_GET['s_by']) {
|
||||
case 'keyword':
|
||||
$sort_by_text = 'Short URL';
|
||||
$sort_by_sql = 'keyword';
|
||||
break;
|
||||
case 'url':
|
||||
$sort_by_text = 'URL';
|
||||
$sort_by_sql = 'url';
|
||||
break;
|
||||
case 'timestamp':
|
||||
$sort_by_text = 'Date';
|
||||
$sort_by_sql = 'timestamp';
|
||||
break;
|
||||
case 'ip':
|
||||
$sort_by_text = 'IP Address';
|
||||
$sort_by_sql = 'ip';
|
||||
break;
|
||||
case 'clicks':
|
||||
$sort_by_text = 'Clicks';
|
||||
$sort_by_sql = 'clicks';
|
||||
break;
|
||||
}
|
||||
switch($_GET['s_order']) {
|
||||
case 'asc':
|
||||
$sort_order_text = 'Ascending Order';
|
||||
$sort_order_sql = 'asc';
|
||||
break;
|
||||
case 'desc':
|
||||
$sort_order_text = 'Descending Order';
|
||||
$sort_order_sql = 'desc';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Get URLs Count for current filter, total links in DB & total clicks
|
||||
list( $total_urls, $total_clicks ) = array_values( yourls_get_db_stats() );
|
||||
if ( $where ) {
|
||||
list( $total_items, $total_items_clicks ) = array_values( yourls_get_db_stats( $where ) );
|
||||
} else {
|
||||
$total_items = $total_urls;
|
||||
$total_items_clicks = false;
|
||||
}
|
||||
|
||||
// This is a bookmarklet
|
||||
if ( isset( $_GET['u'] ) ) {
|
||||
$is_bookmark = true;
|
||||
yourls_do_action( 'bookmarklet' );
|
||||
|
||||
$url = yourls_sanitize_url( $_GET['u'] );
|
||||
$keyword = ( isset( $_GET['k'] ) ? yourls_sanitize_keyword( $_GET['k'] ) : '' );
|
||||
$title = ( isset( $_GET['t'] ) ? yourls_sanitize_title( $_GET['t'] ) : '' );
|
||||
$return = yourls_add_new_link( $url, $keyword, $title );
|
||||
|
||||
// If fails because keyword already exist, retry with no keyword
|
||||
if ( isset( $return['status'] ) && $return['status'] == 'fail' && isset( $return['code'] ) && $return['code'] == 'error:keyword' ) {
|
||||
$msg = $return['message'];
|
||||
$return = yourls_add_new_link( $url, '', $ydb );
|
||||
$return['message'] .= ' ('.$msg.')';
|
||||
}
|
||||
|
||||
// Stop here if bookmarklet with a JSON callback function
|
||||
if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
|
||||
$short = $return['shorturl'] ? $return['shorturl'] : '';
|
||||
$message = $return['message'];
|
||||
header('Content-type: application/json');
|
||||
echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
$s_url = stripslashes( $url );
|
||||
$where = " AND `url` LIKE '$s_url' ";
|
||||
|
||||
$page = $total_pages = $perpage = 1;
|
||||
$offset = 0;
|
||||
|
||||
$text = ( isset( $_GET['s'] ) ? stripslashes( $_GET['s'] ) : '' );
|
||||
|
||||
|
||||
// This is not a bookmarklet
|
||||
} else {
|
||||
$is_bookmark = false;
|
||||
|
||||
// Checking $page, $offset, $perpage
|
||||
if(empty($page) || $page == 0) { $page = 1; }
|
||||
if(empty($offset)) { $offset = 0; }
|
||||
if(empty($perpage) || $perpage == 0) { $perpage = 50; }
|
||||
|
||||
// Determine $offset
|
||||
$offset = ($page-1) * $perpage;
|
||||
|
||||
// Determine Max Number Of Items To Display On Page
|
||||
if(($offset + $perpage) > $total_items) {
|
||||
$max_on_page = $total_items;
|
||||
} else {
|
||||
$max_on_page = ($offset + $perpage);
|
||||
}
|
||||
|
||||
// Determine Number Of Items To Display On Page
|
||||
if (($offset + 1) > ($total_items)) {
|
||||
$display_on_page = $total_items;
|
||||
} else {
|
||||
$display_on_page = ($offset + 1);
|
||||
}
|
||||
|
||||
// Determing Total Amount Of Pages
|
||||
$total_pages = ceil($total_items / $perpage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Begin output of the page
|
||||
$context = ( $is_bookmark ? 'bookmark' : 'index' );
|
||||
yourls_html_head( $context );
|
||||
yourls_html_logo();
|
||||
yourls_html_menu() ;
|
||||
|
||||
if ( !$is_bookmark ) { ?>
|
||||
<p><?php echo $search_display; ?></p>
|
||||
<p>Display <strong><?php echo $display_on_page; ?></strong> to <strong class='increment'><?php echo $max_on_page; ?></strong> of <strong class='increment'><?php echo $total_items; ?></strong> URLs<?php if( $total_items_clicks !== false ) echo ", counting <strong>$total_items_clicks</strong> " . yourls_plural('click', $total_items_clicks) ?>.</p>
|
||||
<?php } ?>
|
||||
<p>Overall, tracking <strong class='increment'><?php echo number_format($total_urls); ?></strong> links, <strong><?php echo number_format($total_clicks); ?></strong> clicks, and counting!</p>
|
||||
|
||||
<?php yourls_html_addnew(); ?>
|
||||
|
||||
<?php
|
||||
// If bookmarklet, add message. Otherwise, hide hidden share box.
|
||||
if ( !$is_bookmark ) {
|
||||
yourls_share_box( '', '', '', '', '<h2>Your short link</h2>', '<h2>Quick Share</h2>', true );
|
||||
} else {
|
||||
echo '<script type="text/javascript">$(document).ready(function(){
|
||||
feedback( "' . $return['message'] . '", "'. $return['status'] .'");
|
||||
init_clipboard();
|
||||
});</script>';
|
||||
}
|
||||
|
||||
yourls_table_head();
|
||||
|
||||
if ( !$is_bookmark ) {
|
||||
$params = array(
|
||||
'search_text' => $search_text,
|
||||
'search_in_sql' => $search_in_sql,
|
||||
'sort_by_sql' => $sort_by_sql,
|
||||
'sort_order_sql' => $sort_order_sql,
|
||||
'page' => $page,
|
||||
'perpage' => $perpage,
|
||||
'link_filter' => $link_filter,
|
||||
'link_limit' => $link_limit,
|
||||
'total_pages' => $total_pages,
|
||||
'search_url' => $search_url,
|
||||
'date_filter' => $date_filter,
|
||||
'date_first' => $date_first,
|
||||
'date_second' => $date_second,
|
||||
);
|
||||
yourls_html_tfooter( $params );
|
||||
}
|
||||
|
||||
yourls_table_tbody_start();
|
||||
|
||||
// Main Query
|
||||
$where = yourls_apply_filter( 'admin_list_where', $where );
|
||||
$url_results = $ydb->get_results("SELECT * FROM `$table_url` WHERE 1=1 $where ORDER BY `$sort_by_sql` $sort_order_sql LIMIT $offset, $perpage;");
|
||||
$found_rows = false;
|
||||
if( $url_results ) {
|
||||
$found_rows = true;
|
||||
foreach( $url_results as $url_result ) {
|
||||
$keyword = yourls_sanitize_string( $url_result->keyword );
|
||||
$timestamp = strtotime( $url_result->timestamp );
|
||||
$url = stripslashes( $url_result->url );
|
||||
$ip = $url_result->ip;
|
||||
$title = $url_result->title ? $url_result->title : '';
|
||||
$clicks = $url_result->clicks;
|
||||
|
||||
echo yourls_table_add_row( $keyword, $url, $title, $ip, $clicks, $timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
$display = $found_rows ? 'display:none' : '';
|
||||
echo '<tr id="nourl_found" style="'.$display.'"><td colspan="6">No URL</td></tr>';
|
||||
|
||||
yourls_table_tbody_end();
|
||||
|
||||
yourls_table_end();
|
||||
|
||||
if ( $is_bookmark )
|
||||
yourls_share_box( $url, $return['shorturl'], $title, $text );
|
||||
?>
|
||||
|
||||
<?php yourls_html_footer( ); ?>
|
79
admin/install.php
Normal file
@ -0,0 +1,79 @@
|
||||
<?php
|
||||
define( 'YOURLS_INSTALLING', true );
|
||||
define( 'YOURLS_ADMIN', true );
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
require_once( YOURLS_INC.'/functions-install.php' );
|
||||
|
||||
$error = array();
|
||||
$warning = array();
|
||||
$success = array();
|
||||
|
||||
// Check pre-requisites
|
||||
if ( !yourls_check_database_version() )
|
||||
$error[] = 'MySQL version is too old. Ask your server admin for an upgrade.';
|
||||
|
||||
if ( !yourls_check_php_version() )
|
||||
$error[] = 'PHP version is too old. Ask your server admin for an upgrade.';
|
||||
|
||||
// Check additional stuff
|
||||
if ( !yourls_check_curl() )
|
||||
$warning[] = 'PHP extension <tt>cURL</tt> is not installed. This server won\'t be able to use the remote API';
|
||||
|
||||
// Is YOURLS already installed ?
|
||||
if ( yourls_is_installed() ) {
|
||||
$error[] = 'YOURLS already installed.';
|
||||
// check if .htaccess exists, recreate otherwise. No error checking.
|
||||
if( !file_exists( YOURLS_ABSPATH.'/.htaccess' ) ) {
|
||||
yourls_create_htaccess();
|
||||
}
|
||||
}
|
||||
|
||||
// Start install if possible and needed
|
||||
if ( isset($_REQUEST['install']) && count( $error ) == 0 ) {
|
||||
// Create/update .htaccess file
|
||||
if ( yourls_create_htaccess() ) {
|
||||
$success[] = 'File <tt>.htaccess</tt> successfully created/updated.';
|
||||
} else {
|
||||
$warning[] = 'Could not write file <tt>.htaccess</tt> in YOURLS root directory. You will have to do it manually. See <a href="http://yourls.org/htaccess">how</a>.';
|
||||
}
|
||||
|
||||
// Create SQL tables
|
||||
$install = yourls_create_sql_tables();
|
||||
if ( isset( $install['error'] ) )
|
||||
$error = array_merge( $error, $install['error'] );
|
||||
if ( isset( $install['success'] ) )
|
||||
$success = array_merge( $success, $install['success'] );
|
||||
}
|
||||
|
||||
|
||||
// Start output
|
||||
yourls_html_head( 'install', 'Install YOURLS' );
|
||||
?>
|
||||
<div id="login">
|
||||
<form method="post" action="?"><?php // reset any QUERY parameters ?>
|
||||
<p>
|
||||
<img src="<?php echo YOURLS_SITE; ?>/images/yourls-logo.png" alt="YOURLS" title="YOURLS" />
|
||||
</p>
|
||||
<?php
|
||||
// Print errors, warnings and success messages
|
||||
foreach ( array ('error', 'warning', 'success') as $info ) {
|
||||
if ( count( $$info ) > 0 ) {
|
||||
echo "<ul class='$info'>";
|
||||
foreach( $$info as $msg ) {
|
||||
echo '<li>'.$msg."</li>\n";
|
||||
}
|
||||
echo '</ul>';
|
||||
}
|
||||
}
|
||||
|
||||
// Display install button or link to admin area if applicable
|
||||
if( !yourls_is_installed() && !isset($_REQUEST['install']) ) {
|
||||
echo '<p> </p><p style="text-align: center;"><input type="submit" name="install" value="Install YOURLS" class="button" /></p>';
|
||||
} else {
|
||||
if( count($error) == 0 )
|
||||
echo '<p> </p><p style="text-align: center;">» <a href="'.yourls_admin_url().'" title="YOURLS Administration Page">YOURLS Administration Page</a></p>';
|
||||
}
|
||||
?>
|
||||
</form>
|
||||
</div>
|
||||
<?php yourls_html_footer(); ?>
|
158
admin/plugins.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
define( 'YOURLS_ADMIN', true );
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
yourls_maybe_require_auth();
|
||||
|
||||
// Handle plugin administration pages
|
||||
if( isset( $_GET['page'] ) && !empty( $_GET['page'] ) ) {
|
||||
yourls_plugin_admin_page( $_GET['page'] );
|
||||
}
|
||||
|
||||
// Handle activation/deactivation of plugins
|
||||
if( isset( $_GET['action'] ) ) {
|
||||
|
||||
// Check nonce
|
||||
yourls_verify_nonce( 'manage_plugins', $_REQUEST['nonce'] );
|
||||
|
||||
// Check plugin file is valid
|
||||
if( isset( $_GET['plugin'] ) && yourls_validate_plugin_file( YOURLS_PLUGINDIR.'/'.$_GET['plugin'].'/plugin.php') ) {
|
||||
|
||||
global $ydb;
|
||||
// Activate / Deactive
|
||||
switch( $_GET['action'] ) {
|
||||
case 'activate':
|
||||
$result = yourls_activate_plugin( $_GET['plugin'].'/plugin.php' );
|
||||
if( $result === true )
|
||||
yourls_redirect( yourls_admin_url( 'plugins.php?success=activated' ), 302 );
|
||||
|
||||
break;
|
||||
|
||||
case 'deactivate':
|
||||
$result = yourls_deactivate_plugin( $_GET['plugin'].'/plugin.php' );
|
||||
if( $result === true )
|
||||
yourls_redirect( yourls_admin_url( 'plugins.php?success=deactivated' ), 302 );
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$result = 'Unsupported action';
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$result = 'No plugin specified, or not a valid plugin';
|
||||
}
|
||||
|
||||
yourls_add_notice( $result );
|
||||
}
|
||||
|
||||
// Handle message upon succesfull (de)activation
|
||||
if( isset( $_GET['success'] ) ) {
|
||||
if( $_GET['success'] == 'activated' OR $_GET['success'] == 'deactivated' ) {
|
||||
yourls_add_notice( 'Plugin '.$_GET['success'] );
|
||||
}
|
||||
}
|
||||
|
||||
yourls_html_head( 'plugins', 'Manage Plugins' );
|
||||
yourls_html_logo();
|
||||
yourls_html_menu();
|
||||
?>
|
||||
|
||||
<h2>Plugins</h2>
|
||||
|
||||
<?php
|
||||
$plugins = (array)yourls_get_plugins();
|
||||
$count = count( $plugins );
|
||||
$count_active = yourls_has_active_plugins();
|
||||
?>
|
||||
|
||||
<p id="plugin_summary">You currently have <strong><?php echo $count.' '.yourls_plural( 'plugin', $count ); ?></strong> installed, and <strong><?php echo $count_active; ?></strong> activated</p>
|
||||
|
||||
<table id="main_table" class="tblSorter" cellpadding="0" cellspacing="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Plugin Name</th>
|
||||
<th>Version</th>
|
||||
<th>Description</th>
|
||||
<th>Author</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
$nonce = yourls_create_nonce( 'manage_plugins' );
|
||||
|
||||
foreach( $plugins as $file=>$plugin ) {
|
||||
|
||||
// default fields to read from the plugin header
|
||||
$fields = array(
|
||||
'name' => 'Plugin Name',
|
||||
'uri' => 'Plugin URI',
|
||||
'desc' => 'Description',
|
||||
'version' => 'Version',
|
||||
'author' => 'Author',
|
||||
'author_uri' => 'Author URI'
|
||||
);
|
||||
|
||||
// Loop through all default fields, get value if any and reset it
|
||||
foreach( $fields as $field=>$value ) {
|
||||
if( isset( $plugin[ $value ] ) ) {
|
||||
$data[ $field ] = $plugin[ $value ];
|
||||
} else {
|
||||
$data[ $field ] = '(no info)';
|
||||
}
|
||||
unset( $plugin[$value] );
|
||||
}
|
||||
|
||||
$plugindir = trim( dirname( $file ), '/' );
|
||||
|
||||
if( yourls_is_active_plugin( $file ) ) {
|
||||
$class = 'active';
|
||||
$action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'deactivate', 'plugin' => $plugindir ) ) );
|
||||
$action_anchor = 'Deactivate';
|
||||
} else {
|
||||
$class = 'inactive';
|
||||
$action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'activate', 'plugin' => $plugindir ) ) );
|
||||
$action_anchor = 'Activate';
|
||||
}
|
||||
|
||||
// Other "Fields: Value" in the header? Get them too
|
||||
if( $plugin ) {
|
||||
foreach( $plugin as $extra_field=>$extra_value ) {
|
||||
$data['desc'] .= "<br/>\n<em>$extra_field</em>: $extra_value";
|
||||
unset( $plugin[$extra_value] );
|
||||
}
|
||||
}
|
||||
|
||||
$data['desc'] .= "<br/><small>plugin file location: $file</small>";
|
||||
|
||||
printf( "<tr class='plugin %s'><td class='plugin_name'><a href='%s'>%s</a></td><td class='plugin_version'>%s</td><td class='plugin_desc'>%s</td><td class='plugin_author'><a href='%s'>%s</a></td><td class='plugin_actions actions'><a href='%s'>%s</a></td></tr>",
|
||||
$class, $data['uri'], $data['name'], $data['version'], $data['desc'], $data['author_uri'], $data['author'], $action_url, $action_anchor
|
||||
);
|
||||
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<script type="text/javascript">
|
||||
yourls_defaultsort = 0;
|
||||
yourls_defaultorder = 0;
|
||||
<?php if ($count_active) { ?>
|
||||
$('#plugin_summary').append('<span id="toggle_plugins">filter</span>');
|
||||
$('#toggle_plugins').css({'background':'transparent url("../images/filter.gif") top left no-repeat','display':'inline-block','text-indent':'-9999px','width':'16px','height':'16px','margin-left':'3px','cursor':'pointer'})
|
||||
.attr('title', 'Toggle active/inactive plugins')
|
||||
.click(function(){
|
||||
$('#main_table tr.inactive').toggle();
|
||||
});
|
||||
<?php } ?>
|
||||
</script>
|
||||
|
||||
<p>If something goes wrong after you activate a plugin and you cannot use YOURLS or access this page, simply rename or delete its directory, or rename the plugin file to something different than <code>plugin.php</code>.</p>
|
||||
|
||||
<h3>More plugins</h3>
|
||||
|
||||
<p>For more plugins, head to the official <a href="http://code.google.com/p/yourls/wiki/PluginList">Plugin list</a>.</p>
|
||||
|
||||
|
||||
<?php yourls_html_footer(); ?>
|
105
admin/tools.php
Normal file
@ -0,0 +1,105 @@
|
||||
<?php
|
||||
define( 'YOURLS_ADMIN', true );
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
yourls_maybe_require_auth();
|
||||
|
||||
yourls_html_head( 'tools', 'Cool YOURLS Tools' );
|
||||
yourls_html_logo();
|
||||
yourls_html_menu();
|
||||
?>
|
||||
|
||||
<div class="sub_wrap">
|
||||
|
||||
<h2>Bookmarklets</h2>
|
||||
|
||||
<p>YOURLS comes with <span>four</span> handy <span>bookmarklets</span> for easier link shortening.</p>
|
||||
|
||||
<h3>Standard or Instant, Simple or Custom</h3>
|
||||
|
||||
<ul>
|
||||
<li>The <span>Standard Bookmarklets</span> will take you to a page where you can easily edit or delete your brand new short URL.</li>
|
||||
|
||||
<li>The <span>Instant Bookmarklets</span> will pop the short URL without leaving the page you are viewing.</li>
|
||||
|
||||
<li>The <span>Simple Bookmarklets</span> will generate a short URL with a random or sequential keyword</li>
|
||||
|
||||
<li>The <span>Custom Keyword Bookmarklets</span> will prompt you for a custom keyword first</li>
|
||||
</ul>
|
||||
|
||||
<p>With the Standard Bookmarklets you will also get a <span>Quick Share</span> tool box to make posting to Twitter, Facebook or Friendfeed a snap. If you want to share a description along with the link you're shortening, simply <span>select text</span> on the page you're viewing before clicking on your bookmarklet link</p>
|
||||
|
||||
<h3>The Bookmarklets</h3>
|
||||
|
||||
<p>Click and drag links to your toolbar (or right-click and bookmark it)</p>
|
||||
|
||||
<table class="tblSorter" cellpadding="0" cellspacing="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<th>Standard (new page)</th>
|
||||
<th>Instant (popup)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th class="header">Simple</th>
|
||||
<td><a href="javascript:(function()%7Bvar%20d=document,w=window,enc=encodeURIComponent,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),s2=((s.toString()=='')?s:('%22'+enc(s)+'%22')),f='<?php echo yourls_admin_url('index.php'); ?>',l=d.location,p='?u='+enc(l.href)+'&t='+enc(d.title)+'&s='+s2,u=f+p;try%7Bthrow('ozhismygod');%7Dcatch(z)%7Ba=function()%7Bif(!w.open(u))l.href=u;%7D;if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();%7Dvoid(0);%7D)()" class="bookmarklet" onclick="alert('Drag to your toolbar!');return false;">Shorten</a></td>
|
||||
<td><a href="javascript:(function()%7Bvar%20d=document,s=d.createElement('script');window.yourls_callback=function(r)%7Bif(r.short_url)%7Bprompt(r.message,r.short_url);%7Delse%7Balert('An%20error%20occured:%20'+r.message);%7D%7D;s.src='<?php echo yourls_admin_url('index.php'); ?>?u='+encodeURIComponent(d.location.href)+'&jsonp=yourls';void(d.body.appendChild(s));%7D)();" class="bookmarklet" onclick="alert('Drag to your toolbar!');return false;">Instant Shorten</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class="header">Custom Keyword</th>
|
||||
<td><a href="javascript:(function()%7Bvar%20d=document,w=window,enc=encodeURIComponent,e=w.getSelection,k=d.getSelection,x=d.selection,s=(e?e():(k)?k():(x?x.createRange().text:0)),s2=((s.toString()=='')?s:('%22'+enc(s)+'%22')),f='<?php echo yourls_admin_url('index.php'); ?>',l=d.location,k=prompt(%22Custom%20URL%22),k2=(k?'&k='+k:%22%22),p='?u='+enc(l.href)+'&t='+enc(d.title)+''+s2+k2,u=f+p;if(k!=null)%7Btry%7Bthrow('ozhismygod');%7Dcatch(z)%7Ba=function()%7Bif(!w.open(u))l.href=u;%7D;if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();%7Dvoid(0)%7D%7D)()" class="bookmarklet" onclick="alert('Drag to your toolbar!');return false;">Custom shorten</a></td>
|
||||
<td><a href="javascript:(function()%7Bvar%20d=document,k=prompt('Custom%20URL'),s=d.createElement('script');if(k!=null){window.yourls_callback=function(r)%7Bif(r.short_url)%7Bprompt(r.message,r.short_url);%7Delse%7Balert('An%20error%20occured:%20'+r.message);%7D%7D;s.src='<?php echo yourls_admin_url('index.php'); ?>?u='+encodeURIComponent(d.location.href)+'&k='+k+'&jsonp=yourls';void(d.body.appendChild(s));%7D%7D)();" class="bookmarklet" onclick="alert('Drag to your toolbar!');return false;">Instant Custom Shorten</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2>Prefix-n-Shorten</h2>
|
||||
|
||||
<p>When viewing a page, you can also prefix its full URL: just head to your browser's address bar, add "<span><?php echo preg_replace('@https?://@', '', YOURLS_SITE); ?>/</span>" to the beginning of the current URL (right before its 'http://' part) and hit enter.</p>
|
||||
|
||||
<p>Note: this will probably not work if your web server is running on Windows <?php if( yourls_is_windows() ) echo '(which seems to be the case here)'; ?>.</p>
|
||||
|
||||
|
||||
<?php if( yourls_is_private() ) { ?>
|
||||
|
||||
<h2>Secure passwordless API call</h2>
|
||||
|
||||
<p>YOURLS allows API calls the old fashioned way, using <tt>username</tt> and <tt>password</tt>
|
||||
parameters. If you're worried about sending your credentials into the wild, you can also make API
|
||||
calls without using your login or your password, using a secret signature token.</p>
|
||||
|
||||
<p>Your secret signature token: <strong><code><?php echo yourls_auth_signature(); ?></code></strong>
|
||||
(It's a secret. Keep it secret)</p>
|
||||
|
||||
<p>This signature token can only be used with the API, not with the admin interface.</p>
|
||||
|
||||
<ul>
|
||||
<li><h3>Usage of the signature token</h3>
|
||||
<p>Simply use parameter <tt>signature</tt> in your API requests. Example:</p>
|
||||
<p><code><?php echo YOURLS_SITE; ?>/yourls-api.php?signature=<?php echo yourls_auth_signature(); ?>&action=...</code></p>
|
||||
</li>
|
||||
|
||||
<li><h3>Usage of a time limited signature token</h3>
|
||||
<pre><code><?php
|
||||
$timestamp = time();
|
||||
<tt>// actual value: $time = <?php $time = time(); echo $time; ?></tt>
|
||||
$signature = md5( $timestamp . '<?php echo yourls_auth_signature(); ?>' );
|
||||
<tt>// actual value: $signature = "<?php $sign = md5( $time. yourls_auth_signature() ); echo $sign; ?>"</tt>
|
||||
?>
|
||||
</code></pre>
|
||||
<p>Now use parameters <tt>signature</tt> and <tt>timestamp</tt> in your API requests. Example:</p>
|
||||
<p><code><?php echo YOURLS_SITE; ?>/yourls-api.php?timestamp=<strong>$timestamp</strong>&signature=<strong>$signature</strong>&action=...</code></p>
|
||||
<p>Actual values:<br/>
|
||||
<tt><?php echo YOURLS_SITE; ?>/yourls-api.php?timestamp=<?php echo $time; ?>&signature=<?php echo $sign; ?>&action=...</tt></p>
|
||||
<p>This URL would be valid for only <?php echo YOURLS_NONCE_LIFE; ?> seconds</p>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>(See the <a href="<?php echo YOURLS_SITE; ?>/readme.html#API">API documentation</a> for more)</p>
|
||||
|
||||
</div>
|
||||
|
||||
<?php } // end is private ?>
|
||||
|
||||
<?php yourls_html_footer(); ?>
|
88
admin/upgrade.php
Normal file
@ -0,0 +1,88 @@
|
||||
<?php
|
||||
define( 'YOURLS_ADMIN', true );
|
||||
define( 'YOURLS_NO_UPGRADE_CHECK', true ); // Bypass version checking to prevent loop
|
||||
require_once( dirname(dirname(__FILE__)).'/includes/load-yourls.php' );
|
||||
require_once( YOURLS_INC.'/functions-upgrade.php' );
|
||||
require_once( YOURLS_INC.'/functions-install.php' );
|
||||
yourls_maybe_require_auth();
|
||||
|
||||
yourls_html_head( 'upgrade', 'Upgrade YOURLS' );
|
||||
yourls_html_logo();
|
||||
yourls_html_menu();
|
||||
?>
|
||||
<h2>Upgrade YOURLS</h2>
|
||||
<?php
|
||||
|
||||
// Check if upgrade is needed
|
||||
if ( !yourls_upgrade_is_needed() ) {
|
||||
echo '<p>Upgrade not required. Go <a href="'.yourls_admin_url('index.php').'">back to play</a>!</p>';
|
||||
|
||||
|
||||
} else {
|
||||
/*
|
||||
step 1: create new tables and populate them, update old tables structure,
|
||||
step 2: convert each row of outdated tables if needed
|
||||
step 3: - if applicable finish updating outdated tables (indexes etc)
|
||||
- update version & db_version in options, this is all done!
|
||||
*/
|
||||
|
||||
// From what are we upgrading?
|
||||
if ( isset( $_GET['oldver'] ) && isset( $_GET['oldsql'] ) ) {
|
||||
$oldver = yourls_sanitize_version( $_GET['oldver'] );
|
||||
$oldsql = yourls_sanitize_version( $_GET['oldsql'] );
|
||||
} else {
|
||||
list( $oldver, $oldsql ) = yourls_get_current_version_from_sql();
|
||||
}
|
||||
|
||||
// To what are we upgrading ?
|
||||
$newver = YOURLS_VERSION;
|
||||
$newsql = YOURLS_DB_VERSION;
|
||||
|
||||
// Verbose & ugly details
|
||||
$ydb->show_errors = true;
|
||||
|
||||
// Let's go
|
||||
$step = ( isset( $_GET['step'] ) ? intval( $_GET['step'] ) : 0 );
|
||||
switch( $step ) {
|
||||
|
||||
default:
|
||||
case 0:
|
||||
echo "
|
||||
<p>Your current installation needs to be upgraded.</p>
|
||||
<p>Please, pretty please, it is recommended that
|
||||
you <strong>backup</strong> your database<br/>(you should do this regularly anyway)</p>
|
||||
<p>Nothing awful <em>should</em> happen, but this doesn't mean it <em>won't</em> happen, right? ;)</p>
|
||||
<p>On every step, if <span class='error'>something goes wrong</span>, you'll see a message and hopefully a way to fix</p>
|
||||
<p>If everything goes too fast and you cannot read, <span class='success'>good for you</span>, let it go :)</p>
|
||||
<p>Once you are ready, press Upgrade!</p>
|
||||
<form action='upgrade.php?' method='get'>
|
||||
<input type='hidden' name='step' value='1' />
|
||||
<input type='hidden' name='oldver' value='$oldver' />
|
||||
<input type='hidden' name='newver' value='$newver' />
|
||||
<input type='hidden' name='oldsql' value='$oldsql' />
|
||||
<input type='hidden' name='newsql' value='$newsql' />
|
||||
<input type='submit' class='primary' value='Upgrade' />
|
||||
</form>";
|
||||
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
$upgrade = yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
$upgrade = yourls_upgrade( 3, $oldver, $newver, $oldsql, $newsql );
|
||||
$admin = yourls_admin_url('index.php');
|
||||
echo "
|
||||
<p>Your installation is now up to date !</p>
|
||||
<p>Go back to <a href='$admin'>the admin interface</a></p>
|
||||
";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
|
||||
<?php yourls_html_footer(); ?>
|
78
changelog.txt
Normal file
@ -0,0 +1,78 @@
|
||||
*** YOURLS Changelog ***
|
||||
|
||||
This file attempts to list the main changes through all versions of YOURLS. For a much more detailed
|
||||
list, simply refer to the commit messages: http://code.google.com/p/yourls/source/list
|
||||
|
||||
1.0
|
||||
- initial release
|
||||
|
||||
1.0.1
|
||||
- don't remember. Trivial stuff probably.
|
||||
|
||||
1.1
|
||||
- don't remember. Some little bugs I guess.
|
||||
|
||||
1.2
|
||||
- don't remember. A few tiny stuff for sure.
|
||||
|
||||
1.3-RC1
|
||||
- added bookmarklet and tools page
|
||||
- improved XSS filter when adding new URL
|
||||
- code cleanup in admin/index.php to separate code and display
|
||||
- added favicon
|
||||
- stricter coding to prevent notices with undefined indexes
|
||||
- hide PHP notices & SQL errors & warnings, unless YOURLS_DEBUG constant set to true
|
||||
|
||||
1.4
|
||||
- added an upgrader from 1.3 to 1.4
|
||||
- change in logic: now using a global object $ydb for everything related to DB and other globally needed stuff
|
||||
- change in logic: include "load-yourls.php" instead of "config.php" to start engine
|
||||
- change in DB schema: now storing URLs with their keyword as used in shorturl, allowing for any keyword length
|
||||
- change in DB schema: new table for storing various options including next_id, dropping table of the same name
|
||||
- change in DB schema: new table for storing hits (for stats)
|
||||
- improved the installer, with .htaccess file creation
|
||||
- layout tweak: now prettier, isn't it?
|
||||
- stats! OMG stats!
|
||||
|
||||
1.4.1
|
||||
- fixed base 62 URLs (keywords with MiXeD CaSe)
|
||||
- new & secure auth method for API calls, with no need to use login & password combo
|
||||
- allow SSL enforcement for admin pages
|
||||
- new API method: stats for individual URL.
|
||||
- prevent internal redirection loops
|
||||
- filter and search URLs & short URLs by date
|
||||
|
||||
1.4.2
|
||||
- fixed bug in auth function
|
||||
- added sample public API file
|
||||
- added check in API requests for WordPress plugin when adding a new short URL
|
||||
- prettier sample public interface
|
||||
|
||||
1.4.3
|
||||
- fixed bug no-stats-showing-ffs due to inconsistency in DB schema
|
||||
- improve error reporting with API method url-stat
|
||||
|
||||
1.5
|
||||
- added: plugin architecture! OMG plugins!!1!!1!
|
||||
- added: directory /user, config.php can be moved there
|
||||
- added: new "instant bookmarklets"
|
||||
- added: 1 click copy-to-clipboard a la bitly
|
||||
- change in logic: now all request are handled by PHP and don't rely on .htaccess
|
||||
- added: saving URL titles
|
||||
- added: support for prefix-n-shorten: sho.rt/http://example.com/
|
||||
- added: core plugin to allow hyphens in URLs
|
||||
- added: core sample plugin to wrap redirected URLs in a social toolbar
|
||||
- added: core sample plugin to show how to create administration page in plugins
|
||||
- added: core plugin to display a random pretty background
|
||||
- changed: layout now using a more consistent palette, see http://yourls.org/palette
|
||||
- added: anti XSS and anti CSRF measures
|
||||
- added: interactive map if possible in stat traffic by countries
|
||||
- fixed: lots of bugs
|
||||
|
||||
1.5.1
|
||||
- added: full jsonp support
|
||||
- added: ability to use encrypted passwords in the config file
|
||||
- fixed: support for http://www.sho.rt/bleh and http://sho.rt/bleh
|
||||
- fixed: bugs, bugs, bugs
|
||||
- added: hooks, hooks, hooks
|
||||
- improved: things, things, things
|
14
css/cal.css
Normal file
@ -0,0 +1,14 @@
|
||||
/* Calendar */
|
||||
.datepicker { border-collapse: collapse; border: 2px solid #999; position: absolute; }
|
||||
.datepicker tr.controls th { height: 22px; font-size: 11px; }
|
||||
.datepicker select { font-size: 11px; }
|
||||
.datepicker tr.days th { height: 18px; }
|
||||
.datepicker tfoot td { height: 18px; text-align: center; text-transform: capitalize; }
|
||||
.datepicker th, .datepicker tfoot td { background: #eee; font: 10px/18px Verdana, Arial, Helvetica, sans-serif; }
|
||||
.datepicker th span, .datepicker tfoot td span { font-weight: bold; }
|
||||
.datepicker tbody td { width: 24px; height: 24px; border: 1px solid #ccc; font: 11px/22px Arial, Helvetica, sans-serif; text-align: center; background: #fff; }
|
||||
.datepicker tbody td.date { cursor: pointer; }
|
||||
.datepicker tbody td.date.over { background-color: #99ffff; }
|
||||
.datepicker tbody td.date.chosen { font-weight: bold; background-color: #ccffcc; }
|
||||
/* Form defaults */
|
||||
#date_and, #date_second {display:none}
|
113
css/infos.css
Normal file
@ -0,0 +1,113 @@
|
||||
h3 span.label {
|
||||
width:100px;
|
||||
display:inline-block;
|
||||
}
|
||||
|
||||
ul.toggle_display {
|
||||
display:none;
|
||||
list-style-type:none;
|
||||
margin-left:0;
|
||||
margin-right:23px;
|
||||
padding:12px 5px 3px;
|
||||
border-bottom:1px solid #C7E7FF;
|
||||
}
|
||||
ul.toggle_display li {
|
||||
padding:0;
|
||||
}
|
||||
#tabs ul#headers li, #tabs ul#headers li h2, #stats_lines li{
|
||||
display: inline;
|
||||
margin-right: 10px;
|
||||
}
|
||||
#tabs ul#headers {
|
||||
border-bottom:1px solid #E3F3FF;
|
||||
padding:12px 5px 3px 5px;
|
||||
float:left;
|
||||
}
|
||||
.wrap_unfloat {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
#tabs ul#headers li a {
|
||||
color:#595441;
|
||||
border:1px solid #C7E7FF;
|
||||
-moz-border-radius:10px 10px 0 0;
|
||||
-webkit-border-radius:10px 10px 0 0;
|
||||
border-radius:10px 10px 0 0;
|
||||
padding:10px 5px 5px 15px;
|
||||
background:#E3F3FF;
|
||||
}
|
||||
|
||||
#tabs ul#headers li a:hover {
|
||||
text-decoration:none;
|
||||
background:#88C0EB;
|
||||
}
|
||||
|
||||
#tabs ul#headers li a.selected {
|
||||
border-bottom:2px solid #fff;
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
#tabs ul#headers li a.selected:hover {
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
#stats_lines li a {
|
||||
-moz-border-radius:10px 10px 0 0;
|
||||
-webkit-border-radius:10px 10px 0 0;
|
||||
border-radius:10px 10px 0 0;
|
||||
padding:3px 10px;
|
||||
background:#E3F3FF;
|
||||
border:1px solid #C7E7FF;
|
||||
}
|
||||
#stats_lines li a:hover {
|
||||
text-decoration:none;
|
||||
background:#C7E7FF;
|
||||
}
|
||||
#stats_lines li a.selected {
|
||||
background:#fff;
|
||||
border:1px solid #C7E7FF;
|
||||
border-bottom:1px solid white;
|
||||
}
|
||||
#stats_lines li a.selected:hover {
|
||||
background:#fff;
|
||||
}
|
||||
.tab {
|
||||
padding:10px;
|
||||
}
|
||||
li#sites_various { padding-left:22px; padding-top:4px;}
|
||||
|
||||
li.sites_list img, #longurl img {width:16px; height: 16px; display:inline-block;}
|
||||
|
||||
#referrer_cell { min-width: 300px;}
|
||||
|
||||
#details_clicks li.bestday {
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
ul.no_bullet {
|
||||
list-style-type: none;
|
||||
margin-left:0;
|
||||
padding:0;
|
||||
}
|
||||
ul.no_bullet li {
|
||||
margin-bottom:5px;
|
||||
}
|
||||
#historical_clicks {
|
||||
float:left;
|
||||
margin:0;
|
||||
}
|
||||
#historical_clicks li {
|
||||
padding:2px 10px;
|
||||
margin:0;
|
||||
}
|
||||
#historical_clicks li:hover {
|
||||
background:#C7E7FF !important;
|
||||
}
|
||||
#historical_clicks span.historical_link {
|
||||
min-width:130px;
|
||||
display:inline-block;
|
||||
}
|
||||
#historical_clicks span.historical_count {
|
||||
min-width:100px;
|
||||
display:inline-block;
|
||||
}
|
BIN
css/palette.png
Normal file
After Width: | Height: | Size: 10 KiB |
65
css/share.css
Normal file
@ -0,0 +1,65 @@
|
||||
#shareboxes, #tweet {
|
||||
overflow:hidden;
|
||||
}
|
||||
|
||||
#shareboxes{
|
||||
margin-top:15px;
|
||||
}
|
||||
|
||||
div.share {
|
||||
-moz-border-radius:5px;
|
||||
-webkit-border-radius:5px;
|
||||
border-radius:5px;
|
||||
border:2px solid #88c0eb;
|
||||
background:#fff;
|
||||
margin-right:1em;
|
||||
padding:0 1em;
|
||||
float:left;
|
||||
height:140px;
|
||||
}
|
||||
#origlink{
|
||||
display:inline-block;
|
||||
white-space:pre;
|
||||
width:183px;
|
||||
overflow:hidden;
|
||||
vertical-align:-2px;
|
||||
}
|
||||
#copybox {
|
||||
width:250px;
|
||||
}
|
||||
#sharebox {
|
||||
width:500px;
|
||||
}
|
||||
#tweet_body {
|
||||
float:left;
|
||||
width:450px;
|
||||
height:4em;
|
||||
font-size:12px;
|
||||
}
|
||||
#charcount {
|
||||
padding-left:5px;
|
||||
color:#88c0eb;
|
||||
}
|
||||
#charcount.negative {
|
||||
color:red;
|
||||
}
|
||||
#share_links a {
|
||||
padding:0 12px 0 18px;
|
||||
font-weight:bold
|
||||
}
|
||||
#share_links a:hover {
|
||||
background-position:2px center;
|
||||
}
|
||||
#share_tw {background:transparent url(../images/twitter.png) left center no-repeat;}
|
||||
#share_fb {background:transparent url(../images/facebook.png) left center no-repeat;}
|
||||
#share_ff {background:transparent url(../images/friendfeed.png) left center no-repeat;}
|
||||
|
||||
#copylink{
|
||||
cursor:pointer;
|
||||
background:transparent url(../images/copy.png) 130% center no-repeat;
|
||||
}
|
||||
|
||||
#copylink:hover, #copylink.hover {
|
||||
background-position:100% 50%;
|
||||
}
|
||||
|
330
css/style.css
Normal file
@ -0,0 +1,330 @@
|
||||
body {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 12px;
|
||||
color: #595441;
|
||||
background:#e3f3ff;
|
||||
text-align:center;
|
||||
margin-top:0px;
|
||||
padding-top:10px;
|
||||
}
|
||||
#wrap {
|
||||
width:950px;
|
||||
min-height:150px;
|
||||
margin:0 auto;
|
||||
background:white;
|
||||
text-align:left;
|
||||
padding:5px 20px 10px 20px;
|
||||
border-left:3px solid #2a85b3;
|
||||
border-right:3px solid #2a85b3;
|
||||
border-bottom:3px solid #2a85b3;
|
||||
border-top:3px solid #2a85b3;
|
||||
-moz-border-radius:20px;
|
||||
-webkit-border-radius:20px;
|
||||
border-radius:20px;
|
||||
}
|
||||
.hide-if-no-js {display: none;}
|
||||
div, p, td {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 12px;
|
||||
}
|
||||
a, a:link, a:active, a:visited {
|
||||
color: #2a85b3;
|
||||
text-decoration: none;
|
||||
}
|
||||
a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
h1 {height:50px;margin:0;float:right;width:500px;}
|
||||
h1 a {text-align:right;font-size:20px;float:right;}
|
||||
h1 a, h1 a:link, h1 a:active, h1 a:visited {color:#2a85b3}
|
||||
h1 a:hover{text-decoration:none;}
|
||||
h1 a:hover span{text-decoration:underline;color:#88c0eb}
|
||||
|
||||
ul#admin_menu {
|
||||
min-height:100px;
|
||||
list-style-type:none;
|
||||
padding:0;
|
||||
font-size:105%;
|
||||
}
|
||||
ul#admin_menu li {
|
||||
color:#aaa;
|
||||
padding:1px 0;
|
||||
}
|
||||
ul#admin_menu li:hover {
|
||||
list-style-type:square;
|
||||
color:#000;
|
||||
}
|
||||
|
||||
code {
|
||||
background:#eaeaef;
|
||||
padding:0 2px;
|
||||
}
|
||||
tt {
|
||||
background:#ffc;
|
||||
padding:0 2px;
|
||||
}
|
||||
|
||||
input, textarea {
|
||||
-moz-border-radius:3px;
|
||||
-webkit-border-radius:3px;
|
||||
border-radius:3px;
|
||||
}
|
||||
Input.text, select, textarea {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 10px;
|
||||
color: #595441;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #88c0eb;
|
||||
margin:1px;
|
||||
}
|
||||
input.button {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 10px;
|
||||
color: #595441;
|
||||
font-weight: bold;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #88c0eb;
|
||||
cursor:pointer;
|
||||
}
|
||||
input.primary {
|
||||
border:2px solid #2A85B3;
|
||||
background:#fafafe;
|
||||
}
|
||||
input.text:focus, textarea:focus {
|
||||
border:2px solid #2A85B3;
|
||||
margin:0px;
|
||||
}
|
||||
tr.edit-row td {
|
||||
background:#e3f3ff !important;
|
||||
}
|
||||
#new_url {
|
||||
text-align:center;
|
||||
padding:1px;
|
||||
border:1px solid #CDCDCD;
|
||||
background:#fff;
|
||||
clear:both;
|
||||
}
|
||||
#new_url div {
|
||||
background:#C7E7FF;
|
||||
padding:4px;
|
||||
}
|
||||
#new_url_form {
|
||||
padding:4px;
|
||||
}
|
||||
#new_url #feedback {
|
||||
background:#ff8;
|
||||
color:#88c0eb;
|
||||
width:50%;
|
||||
margin:0px 25%;
|
||||
padding:2px;
|
||||
border:1px solid #ff8;
|
||||
}
|
||||
#new_url #feedback .fail {
|
||||
color:#f55;
|
||||
}
|
||||
td.url small a{
|
||||
color:#bbc;
|
||||
}
|
||||
body.desktop td.actions input,body.desktop td.actions a {
|
||||
visibility:hidden;
|
||||
}
|
||||
td.actions input.disabled, td.actions input.loading {
|
||||
visibility:visible;
|
||||
}
|
||||
tr:hover td.actions input, tr:hover td.actions a {
|
||||
visibility:visible;
|
||||
}
|
||||
td.actions .button {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 10px;
|
||||
color: #595441;
|
||||
font-weight: bold;
|
||||
background-color: #FFFFFF;
|
||||
border: 1px solid #88c0eb;
|
||||
-moz-border-radius:3px;
|
||||
-webkit-border-radius:3px;
|
||||
border-radius:3px;
|
||||
cursor:pointer;
|
||||
height:22px;
|
||||
width:22px;
|
||||
margin-top:0px;
|
||||
margin-right:5px;
|
||||
display:block;
|
||||
float:left;
|
||||
text-indent:-9999px;
|
||||
outline:0px;
|
||||
}
|
||||
td.actions .button:active {
|
||||
border:1px solid #000;
|
||||
}
|
||||
td.actions .button:hover {
|
||||
text-decoration:none;
|
||||
}
|
||||
td.actions .button.disabled, #add-button.disabled {
|
||||
border:1px solid #333;
|
||||
background:#ccc;
|
||||
}
|
||||
td.actions .button.loading, #add-button.loading {
|
||||
background:#cc7 url(../images/loading.gif) center center no-repeat;
|
||||
color:#cc7;
|
||||
}
|
||||
td.actions .button_share {
|
||||
background:transparent url(../images/share.png) 2px center no-repeat;
|
||||
}
|
||||
td.actions .button_edit {
|
||||
background:transparent url(../images/pencil.png) 2px center no-repeat;
|
||||
}
|
||||
td.actions .button_delete {
|
||||
background:transparent url(../images/delete.png) 2px center no-repeat;
|
||||
}
|
||||
td.actions .button_stats {
|
||||
background:transparent url(../images/chart_bar.png) 2px center no-repeat;
|
||||
}
|
||||
#main_table tfoot th, #main_table tfoot th div {
|
||||
font-size:10px;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
background:#fee;
|
||||
}
|
||||
.warning {
|
||||
color: orange;
|
||||
background:#ffe9bf;
|
||||
}
|
||||
.success {
|
||||
color: green;
|
||||
background:#efe;
|
||||
}
|
||||
#login {
|
||||
width: 300px;
|
||||
margin: 200px auto 0px auto;
|
||||
}
|
||||
#login p{
|
||||
font-weight: bold;
|
||||
}
|
||||
#login .text {
|
||||
width: 100%;
|
||||
}
|
||||
#login ul {
|
||||
padding-left:0px;
|
||||
list-style-type:none;
|
||||
text-indent:0;
|
||||
}
|
||||
#login ul li {
|
||||
padding:0 0 5px 20px;
|
||||
}
|
||||
#login ul.error li {
|
||||
background:transparent url(../images/cancel.png) top left no-repeat;
|
||||
}
|
||||
#login ul.warning li {
|
||||
background:transparent url(../images/error.png) top left no-repeat;
|
||||
}
|
||||
#login ul.success li {
|
||||
background:transparent url(../images/accept.png) top left no-repeat;
|
||||
}
|
||||
.sub_wrap {
|
||||
width:580px;
|
||||
padding-bottom:30px;
|
||||
text-align:justify;
|
||||
}
|
||||
.sub_wrap span {
|
||||
background:#ffa;
|
||||
padding:0 2px;
|
||||
}
|
||||
a.bookmarklet {
|
||||
border:2px solid #2a85b3;
|
||||
-moz-border-radius:3px;
|
||||
-webkit-border-radius:3px;
|
||||
border-radius:3px;
|
||||
padding:5px 5px 5px 20px;
|
||||
background:#eef url(../images/favicon.gif) 2px center no-repeat;
|
||||
margin:3px;
|
||||
display:block;
|
||||
float:left;
|
||||
}
|
||||
a.bookmarklet:hover {
|
||||
text-decoration:none;
|
||||
background-position:3px center;
|
||||
}
|
||||
#footer {
|
||||
text-align:center;
|
||||
margin-top:20px;
|
||||
}
|
||||
#footer p {
|
||||
padding:10px;
|
||||
background:white;
|
||||
margin:0 auto;
|
||||
width:950px;
|
||||
-moz-border-radius:10px;
|
||||
-webkit-border-radius:10px;
|
||||
border-radius:10px;
|
||||
border:2px solid #2a85b3;
|
||||
-moz-border-radius-bottomleft:30px;
|
||||
-moz-border-radius-bottomright:30px;
|
||||
-webkit-border-bottom-left-radius:25px;
|
||||
-webkit-border-bottom-right-radius:25px;
|
||||
border-bottom-left-radius:25px;
|
||||
border-bottom-right-radius:25px;
|
||||
}
|
||||
#footer p a {
|
||||
background:#fff url(../images/favicon.gif) 2px center no-repeat;
|
||||
padding-left:20px;
|
||||
}
|
||||
|
||||
.notice {
|
||||
border:1px solid #2a85b3;
|
||||
background: #F3FAFD;
|
||||
-moz-border-radius:6px;
|
||||
-webkit-border-radius:6px;
|
||||
border-radius:6px;
|
||||
width:70%;
|
||||
margin-left:15%;
|
||||
padding-left:10px;
|
||||
margin-bottom:5px;
|
||||
}
|
||||
|
||||
|
||||
.jquery-notify-bar {
|
||||
width:100%;
|
||||
position:fixed;
|
||||
top:0;
|
||||
left:0;
|
||||
z-index:32768;
|
||||
background-color:#efefef;
|
||||
font-size:18px;
|
||||
color:#000;
|
||||
text-align:center;
|
||||
font-family: Arial, Verdana, sans-serif;
|
||||
padding:20px 0px;
|
||||
border-bottom:1px solid #bbb;
|
||||
filter:alpha(opacity=95);
|
||||
-moz-opacity:0.95;
|
||||
-khtml-opacity:0.95;
|
||||
opacity:0.95;
|
||||
-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.5);
|
||||
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
|
||||
text-shadow: 0 1px 1px rgba(0,0,0,0.1);
|
||||
}
|
||||
.jquery-notify-bar.error ,.jquery-notify-bar.fail {
|
||||
color:#f00;
|
||||
background-color:#fdd;
|
||||
}
|
||||
.jquery-notify-bar.error span,.jquery-notify-bar.fail span{
|
||||
background:transparent url("../images/error.png") no-repeat left center;
|
||||
padding-left:20px;
|
||||
}.jquery-notify-bar.success span{
|
||||
background:transparent url("../images/accept.png") no-repeat left center;
|
||||
padding-left:20px;
|
||||
}
|
||||
.jquery-notify-bar.success {
|
||||
color:#060;
|
||||
background-color:#aea;
|
||||
}
|
||||
.notify-bar-close {
|
||||
position:absolute;
|
||||
left:95%;
|
||||
font-size:11px;
|
||||
}
|
||||
tr.plugin.active a{ font-weight:bolder;}
|
||||
body.desktop tr.plugin td.plugin_desc small{ visibility:hidden;}
|
||||
tr:hover.plugin td.plugin_desc small{ visibility:visible;}
|
92
css/tablesorter.css
Normal file
@ -0,0 +1,92 @@
|
||||
/* jQuery Table Sorter */
|
||||
table.tblSorter {
|
||||
font-family:Verdana, Arial;
|
||||
background-color: #CDCDCD;
|
||||
margin:10px 0px 0px;
|
||||
font-size: 8pt;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
table.tblSorter thead tr th, table.tblSorter tfoot tr th, table.tblSorter th.header {
|
||||
background-color: #C7E7FF;
|
||||
border: 1px solid #FFF;
|
||||
font-size: 8pt;
|
||||
padding: 4px;
|
||||
}
|
||||
table.tblSorter tfoot tr th {
|
||||
background-color: #E3F3FF;
|
||||
}
|
||||
table.tblSorter thead tr .header {
|
||||
background-image: url('../images/bg.gif');
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
cursor: pointer;
|
||||
padding-right:10px;
|
||||
}
|
||||
table.tblSorter tbody tr:hover td {
|
||||
background-color:#F3FAFD;
|
||||
}
|
||||
table.tblSorter tbody td {
|
||||
color: #3D3D3D;
|
||||
padding: 4px;
|
||||
background-color: #FFF;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.tblSorter tbody tr.even td {
|
||||
|
||||
}
|
||||
table.tblSorter tbody tr.odd td {
|
||||
|
||||
}
|
||||
table.tblSorter thead tr .headerSortUp {
|
||||
background-image: url('../images/desc.gif');
|
||||
}
|
||||
table.tblSorter thead tr .headerSortDown {
|
||||
background-image: url('../images/asc.gif');
|
||||
}
|
||||
table.tblSorter thead tr .headerSortDown, table.tblSorter thead tr .headerSortUp {
|
||||
background-color: #88c0eb;
|
||||
}
|
||||
table.tblSorter tfoot tr {
|
||||
background-color: #BCD9E8;
|
||||
}
|
||||
#filter_form{
|
||||
float:left;
|
||||
max-width:69%;
|
||||
}
|
||||
#filter_buttons{
|
||||
float:right;
|
||||
}
|
||||
#pagination{
|
||||
text-align:right;
|
||||
float:right;
|
||||
width:30%;
|
||||
}
|
||||
.navigation .nav_total{
|
||||
display:block;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
.navigation .nav_link a, .navigation .nav_current {
|
||||
border:1px solid #CDCDCD;
|
||||
margin:0px 2px;
|
||||
padding:2px 1px;
|
||||
background:#fff;
|
||||
text-align:center;
|
||||
min-width:15px;
|
||||
display:inline-block;
|
||||
}
|
||||
.navigation .nav_current {
|
||||
border:0px;
|
||||
background:none;
|
||||
}
|
||||
.navigation .nav_first a, .navigation .nav_last a {
|
||||
padding:2px 2px;
|
||||
}
|
||||
.navigation .nav_prev:before, .navigation .nav_next:after {
|
||||
content:"...";
|
||||
}
|
||||
.navigation .nav_link a:hover {
|
||||
border:1px solid #BCD9E8;
|
||||
background:#BCD9E8;
|
||||
text-decoration:none;
|
||||
}
|
BIN
images/accept.png
Normal file
After Width: | Height: | Size: 781 B |
BIN
images/asc.gif
Normal file
After Width: | Height: | Size: 54 B |
BIN
images/bg.gif
Normal file
After Width: | Height: | Size: 64 B |
BIN
images/blank.gif
Normal file
After Width: | Height: | Size: 42 B |
BIN
images/cancel.png
Normal file
After Width: | Height: | Size: 587 B |
BIN
images/chart_bar.png
Normal file
After Width: | Height: | Size: 541 B |
BIN
images/chart_bar_add.png
Normal file
After Width: | Height: | Size: 626 B |
BIN
images/copy-large.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
images/copy.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/delete.png
Normal file
After Width: | Height: | Size: 715 B |
BIN
images/desc.gif
Normal file
After Width: | Height: | Size: 54 B |
BIN
images/error.png
Normal file
After Width: | Height: | Size: 666 B |
BIN
images/facebook.png
Normal file
After Width: | Height: | Size: 318 B |
BIN
images/favicon.gif
Normal file
After Width: | Height: | Size: 88 B |
BIN
images/filter.gif
Normal file
After Width: | Height: | Size: 870 B |
BIN
images/friendfeed.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
images/loading.gif
Normal file
After Width: | Height: | Size: 771 B |
BIN
images/pencil.png
Normal file
After Width: | Height: | Size: 450 B |
BIN
images/share.png
Normal file
After Width: | Height: | Size: 1007 B |
BIN
images/twitter.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
images/yourls-logo.png
Normal file
After Width: | Height: | Size: 12 KiB |
28
includes/auth.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
// No direct call
|
||||
if( !defined( 'YOURLS_ABSPATH' ) ) die();
|
||||
|
||||
$auth = yourls_apply_filter( 'is_valid_user', yourls_is_valid_user() );
|
||||
|
||||
if( $auth !== true ) {
|
||||
|
||||
// API mode,
|
||||
if ( yourls_is_API() ) {
|
||||
$format = ( isset($_REQUEST['format']) ? $_REQUEST['format'] : 'xml' );
|
||||
$callback = ( isset($_REQUEST['callback']) ? $_REQUEST['callback'] : '' );
|
||||
yourls_api_output( $format, array(
|
||||
'simple' => $auth,
|
||||
'message' => $auth,
|
||||
'errorCode' => 403,
|
||||
'callback' => $callback,
|
||||
) );
|
||||
|
||||
// Regular mode
|
||||
} else {
|
||||
yourls_login_screen( $auth );
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
yourls_do_action( 'auth_successful' );
|
407
includes/class-mysql.php
Normal file
@ -0,0 +1,407 @@
|
||||
<?php
|
||||
/*
|
||||
+----------------------------------------------------------------+
|
||||
| |
|
||||
| ezSQL |
|
||||
| Copyright (c) 2006 Justin Vincent |
|
||||
| |
|
||||
| File Written By: |
|
||||
| - Justin Vincent (justin@visunet.ie) |
|
||||
| - http://php.justinvincent.com |
|
||||
| |
|
||||
| File Information: |
|
||||
| - MYSQL Database Class |
|
||||
| - class-mysql.php |
|
||||
| |
|
||||
+----------------------------------------------------------------+
|
||||
*/
|
||||
|
||||
|
||||
### ezSQL Constants. Might be defined in the WordPress environment if YOURLS plugin used.
|
||||
if( !defined('EZSQL_VERSION') )
|
||||
define('EZSQL_VERSION','2.0');
|
||||
if( !defined('OBJECT') )
|
||||
define('OBJECT','OBJECT',true);
|
||||
if( !defined('ARRAY_A') )
|
||||
define('ARRAY_A','ARRAY_A',true);
|
||||
if( !defined('ARRAY_N') )
|
||||
define('ARRAY_N','ARRAY_N',true);
|
||||
if( !defined('EZSQL_CORE_ERROR') )
|
||||
define('EZSQL_CORE_ERROR','ezSQLcore can not be used by itself (it is designed for use by database specific modules).');
|
||||
|
||||
|
||||
### ezSQL Core Class
|
||||
// Core class containg common functions to manipulate query result sets once returned
|
||||
class ezSQLcore{
|
||||
var $trace = false; // same as $debug_all
|
||||
var $debug_all = false; // same as $trace
|
||||
var $debug_called = false;
|
||||
var $vardump_called = false;
|
||||
var $show_errors = false;
|
||||
var $num_queries = 0;
|
||||
var $last_query = null;
|
||||
var $last_error = null;
|
||||
var $col_info = null;
|
||||
var $captured_errors = array();
|
||||
var $all_queries = '';
|
||||
|
||||
## Constructor
|
||||
function ezSQLcore() { }
|
||||
|
||||
## Connect to DB - over-ridden by specific DB class
|
||||
function connect() { die(EZSQL_CORE_ERROR); }
|
||||
|
||||
## Select DB - over-ridden by specific DB class
|
||||
function select() { die(EZSQL_CORE_ERROR); }
|
||||
|
||||
## Basic Query - over-ridden by specific DB class
|
||||
function query() { die(EZSQL_CORE_ERROR); }
|
||||
|
||||
## Format a string correctly for safe insert - over-ridden by specific DB class
|
||||
function escape() { die(EZSQL_CORE_ERROR); }
|
||||
|
||||
## Return database specific system date syntax
|
||||
function sysdate() { die(EZSQL_CORE_ERROR); }
|
||||
|
||||
## Print SQL/DB error - over-ridden by specific DB class
|
||||
function register_error($err_str) {
|
||||
// Keep track of last error
|
||||
$this->last_error = $err_str;
|
||||
// Capture all errors to an error array no matter what happens
|
||||
$this->captured_errors[] = array ('error_str' => $err_str, 'query' => $this->last_query);
|
||||
}
|
||||
|
||||
## Show Errors
|
||||
function show_errors() { $this->show_errors = true; }
|
||||
|
||||
## Hide Errors
|
||||
function hide_errors() { $this->show_errors = false; }
|
||||
|
||||
## Kill cached query results
|
||||
function flush() {
|
||||
// Get rid of these
|
||||
$this->last_result = null;
|
||||
$this->col_info = null;
|
||||
$this->last_query = null;
|
||||
}
|
||||
|
||||
## Get one variable from the DB - see docs for more detail
|
||||
function get_var($query=null,$x=0,$y=0) {
|
||||
// Log how the function was called
|
||||
$this->func_call = "\$db->get_var(\"$query\",$x,$y)";
|
||||
// If there is a query then perform it if not then use cached results..
|
||||
if ($query) {
|
||||
$this->query($query);
|
||||
}
|
||||
// Extract var out of cached results based x,y vals
|
||||
if ($this->last_result[$y]){
|
||||
$values = array_values(get_object_vars($this->last_result[$y]));
|
||||
}
|
||||
// If there is a value return it else return null
|
||||
return (isset($values[$x]) && $values[$x]!=='')?$values[$x]:null;
|
||||
}
|
||||
|
||||
## Get one row from the DB - see docs for more detail
|
||||
function get_row($query=null,$output=OBJECT,$y=0) {
|
||||
// Log how the function was called
|
||||
$this->func_call = "\$db->get_row(\"$query\",$output,$y)";
|
||||
// If there is a query then perform it if not then use cached results..
|
||||
if ($query) {
|
||||
$this->query($query);
|
||||
}
|
||||
// If the output is an object then return object using the row offset..
|
||||
if ($output == OBJECT) {
|
||||
return $this->last_result[$y]?$this->last_result[$y]:null;
|
||||
// If the output is an associative array then return row as such..
|
||||
} elseif ($output == ARRAY_A) {
|
||||
return $this->last_result[$y]?get_object_vars($this->last_result[$y]):null;
|
||||
// If the output is an numerical array then return row as such..
|
||||
} elseif ($output == ARRAY_N) {
|
||||
return $this->last_result[$y]?array_values(get_object_vars($this->last_result[$y])):null;
|
||||
// If invalid output type was specified..
|
||||
} else {
|
||||
$this->print_error(" \$db->get_row(string query, output type, int offset) -- Output type must be one of: OBJECT, ARRAY_A, ARRAY_N");
|
||||
}
|
||||
}
|
||||
|
||||
## Function to get 1 column from the cached result set based in X index see docs for usage and info
|
||||
function get_col($query=null,$x=0) {
|
||||
// If there is a query then perform it if not then use cached results..
|
||||
if ($query) {
|
||||
$this->query($query);
|
||||
}
|
||||
|
||||
// Extract the column values
|
||||
for ($i=0; $i < count($this->last_result); $i++) {
|
||||
$new_array[$i] = $this->get_var(null,$x,$i);
|
||||
}
|
||||
return $new_array;
|
||||
}
|
||||
|
||||
## Return the the query as a result set - see docs for more details
|
||||
function get_results($query=null, $output = OBJECT) {
|
||||
// Log how the function was called
|
||||
$this->func_call = "\$db->get_results(\"$query\", $output)";
|
||||
// If there is a query then perform it if not then use cached results..
|
||||
if ($query) {
|
||||
$this->query($query);
|
||||
}
|
||||
// Send back array of objects. Each row is an object
|
||||
if ($output == OBJECT) {
|
||||
return $this->last_result;
|
||||
} elseif ($output == ARRAY_A || $output == ARRAY_N) {
|
||||
if ($this->last_result) {
|
||||
$i=0;
|
||||
foreach($this->last_result as $row) {
|
||||
$new_array[$i] = get_object_vars($row);
|
||||
if ($output == ARRAY_N) {
|
||||
$new_array[$i] = array_values($new_array[$i]);
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
return $new_array;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Function to get column meta data info pertaining to the last query see docs for more info and usage
|
||||
function get_col_info($info_type="name",$col_offset=-1) {
|
||||
if ($this->col_info) {
|
||||
if ($col_offset == -1) {
|
||||
$i=0;
|
||||
foreach($this->col_info as $col) {
|
||||
$new_array[$i] = $col->{$info_type};
|
||||
$i++;
|
||||
}
|
||||
return $new_array;
|
||||
} else {
|
||||
return $this->col_info[$col_offset]->{$info_type};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Dumps the contents of any input variable to screen in a nicely formatted and easy to understand way - any type: Object, Var or Array
|
||||
function vardump($mixed='') {
|
||||
echo "<p><table><tr><td bgcolor=ffffff><blockquote><font color=000090>";
|
||||
echo "<pre><font face=arial>";
|
||||
if (!$this->vardump_called) {
|
||||
echo "<font color=800080><b>ezSQL</b> (v".EZSQL_VERSION.") <b>Variable Dump..</b></font>\n\n";
|
||||
}
|
||||
$var_type = gettype ($mixed);
|
||||
print_r(($mixed?$mixed:"<font color=red>No Value / False</font>"));
|
||||
echo "\n\n<b>Type:</b> " . ucfirst($var_type) . "\n";
|
||||
echo "<b>Last Query</b> [$this->num_queries]<b>:</b> ".($this->last_query?$this->last_query:"NULL")."\n";
|
||||
echo "<b>Last Function Call:</b> " . ($this->func_call?$this->func_call:"None")."\n";
|
||||
echo "<b>Last Rows Returned:</b> ".count($this->last_result)."\n";
|
||||
echo "</font></pre></font></blockquote></td></tr></table>".$this->donation();
|
||||
echo "\n<hr size=1 noshade color=dddddd>";
|
||||
$this->vardump_called = true;
|
||||
}
|
||||
|
||||
## Alias for the above function
|
||||
function dumpvar($mixed) { $this->vardump($mixed); }
|
||||
|
||||
## Displays the last query string that was sent to the database & a table listing results (if there were any). (abstracted into a seperate file to save server overhead).
|
||||
function debug() {
|
||||
echo "<blockquote>";
|
||||
// Only show ezSQL credits once..
|
||||
if (!$this->debug_called) {
|
||||
echo "<font color=800080 face=arial size=2><b>ezSQL</b> (v".EZSQL_VERSION.") <b>Debug..</b></font><p>\n";
|
||||
}
|
||||
if ($this->last_error) {
|
||||
echo "<font face=arial size=2 color=000099><b>Last Error --</b> [<font color=000000><b>$this->last_error</b></font>]<p>";
|
||||
}
|
||||
echo "<font face=arial size=2 color=000099><b>Query</b> [$this->num_queries] <b>--</b> ";
|
||||
echo "[<font color=000000><b>$this->last_query</b></font>]</font><p>";
|
||||
echo "<font face=arial size=2 color=000099><b>Query Result..</b></font>";
|
||||
echo "<blockquote>";
|
||||
if ($this->col_info) {
|
||||
// Results top rows
|
||||
echo "<table cellpadding=5 cellspacing=1 bgcolor=555555>";
|
||||
echo "<tr bgcolor=eeeeee><td nowrap valign=bottom><font color=555599 face=arial size=2><b>(row)</b></font></td>";
|
||||
for ($i=0; $i < count($this->col_info); $i++) {
|
||||
echo "<td nowrap align=left valign=top><font size=1 color=555599 face=arial>{$this->col_info[$i]->type} {$this->col_info[$i]->max_length}</font><br><span style='font-family: arial; font-size: 10pt; font-weight: bold;'>{$this->col_info[$i]->name}</span></td>";
|
||||
}
|
||||
echo "</tr>";
|
||||
// print main results
|
||||
if ($this->last_result) {
|
||||
$i=0;
|
||||
foreach ($this->get_results(null,ARRAY_N) as $one_row) {
|
||||
$i++;
|
||||
echo "<tr bgcolor=ffffff><td bgcolor=eeeeee nowrap align=middle><font size=2 color=555599 face=arial>$i</font></td>";
|
||||
foreach ($one_row as $item) {
|
||||
echo "<td nowrap><font face=arial size=2>$item</font></td>";
|
||||
}
|
||||
echo "</tr>";
|
||||
}
|
||||
} else {
|
||||
echo "<tr bgcolor=ffffff><td colspan=".(count($this->col_info)+1)."><font face=arial size=2>No Results</font></td></tr>";
|
||||
}
|
||||
echo "</table>";
|
||||
} else {
|
||||
echo "<font face=arial size=2>No Results</font>";
|
||||
}
|
||||
echo "</blockquote></blockquote>".$this->donation()."<hr noshade color=dddddd size=1>";
|
||||
$this->debug_called = true;
|
||||
}
|
||||
|
||||
## Naughty little function to ask for some remuniration!
|
||||
function donation() {
|
||||
return "<font size=1 face=arial color=000000>If ezSQL has helped <a href=\"https://www.paypal.com/xclick/business=justin%40justinvincent.com&item_name=ezSQL&no_note=1&tax=0\" style=\"color: 0000CC;\">make a donation!?</a> <!--[ go on! you know you want to! ]--></font>";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
### ezSQL MYSQL Class Variables
|
||||
$ezsql_mysql_str = array
|
||||
(
|
||||
1 => 'Require $dbuser and $dbpassword to connect to a database server',
|
||||
2 => 'Error establishing mySQL database connection. Correct user/password? Correct hostname? Database server running?',
|
||||
3 => 'Require $dbname to select a database',
|
||||
4 => 'mySQL database connection is not active',
|
||||
5 => 'Unexpected error while trying to select database'
|
||||
);
|
||||
if ( ! function_exists ('mysql_connect') ) die('<b>Fatal Error:</b> ezSQL_mysql requires mySQL Lib to be compiled and or linked in to the PHP engine');
|
||||
if ( ! class_exists ('ezSQLcore') ) die('<b>Fatal Error:</b> ezSQL_mysql requires ezSQLcore (ez_sql_core.php) to be included/loaded before it can be used');
|
||||
|
||||
|
||||
### ezSQL MYSQL Class
|
||||
class ezSQL_mysql extends ezSQLcore {
|
||||
|
||||
## Constructor - allow the user to perform a qucik connect at the same time as initialising the ezSQL_mysql class
|
||||
function ezSQL_mysql($dbuser='', $dbpassword='', $dbname='', $dbhost='localhost') {
|
||||
if ($dbuser && $dbname) {
|
||||
$this->quick_connect($dbuser, $dbpassword, $dbname, $dbhost);
|
||||
}
|
||||
}
|
||||
|
||||
## Short hand way to connect to mySQL database server and select a mySQL database at the same time
|
||||
function quick_connect($dbuser='', $dbpassword='', $dbname='', $dbhost='localhost') {
|
||||
$return_val = false;
|
||||
if ( ! $this->connect($dbuser, $dbpassword, $dbhost,true) ) ;
|
||||
else if ( ! $this->select($dbname) ) ;
|
||||
else $return_val = true;
|
||||
return $return_val;
|
||||
}
|
||||
|
||||
## Try to connect to mySQL database server
|
||||
function connect($dbuser='', $dbpassword='', $dbhost='localhost'){
|
||||
global $ezsql_mysql_str; $return_val = false;
|
||||
// Must have a user and a password
|
||||
if (!$dbuser){
|
||||
$this->register_error($ezsql_mysql_str[1].' in '.__FILE__.' on line '.__LINE__);
|
||||
$this->show_errors ? trigger_error($ezsql_mysql_str[1],E_USER_WARNING) : null;
|
||||
// Try to establish the server database handle
|
||||
} else if (!$this->dbh = @mysql_connect($dbhost,$dbuser,$dbpassword)) {
|
||||
$this->register_error($ezsql_mysql_str[2].' in '.__FILE__.' on line '.__LINE__);
|
||||
$this->show_errors ? trigger_error($ezsql_mysql_str[2],E_USER_WARNING) : null;
|
||||
} else {
|
||||
$return_val = true;
|
||||
}
|
||||
return $return_val;
|
||||
}
|
||||
|
||||
## Close
|
||||
function close() {
|
||||
return mysql_close($this->dbh);
|
||||
}
|
||||
|
||||
## Try to select a mySQL database
|
||||
function select($dbname='') {
|
||||
global $ezsql_mysql_str; $return_val = false;
|
||||
// Must have a database name
|
||||
if (!$dbname) {
|
||||
$this->register_error($ezsql_mysql_str[3].' in '.__FILE__.' on line '.__LINE__);
|
||||
$this->show_errors ? trigger_error($ezsql_mysql_str[3],E_USER_WARNING) : null;
|
||||
// Must have an active database connection
|
||||
} else if (!$this->dbh) {
|
||||
$this->register_error($ezsql_mysql_str[4].' in '.__FILE__.' on line '.__LINE__);
|
||||
$this->show_errors ? trigger_error($ezsql_mysql_str[4],E_USER_WARNING) : null;
|
||||
// Try to connect to the database
|
||||
} else if (!@mysql_select_db($dbname,$this->dbh)) {
|
||||
// Try to get error supplied by mysql if not use our own
|
||||
if ( !$str = @mysql_error($this->dbh)) {
|
||||
$str = $ezsql_mysql_str[5];
|
||||
}
|
||||
$this->register_error($str.' in '.__FILE__.' on line '.__LINE__);
|
||||
$this->show_errors ? trigger_error($str,E_USER_WARNING) : null;
|
||||
} else {
|
||||
$return_val = true;
|
||||
}
|
||||
return $return_val;
|
||||
}
|
||||
|
||||
## Format a mySQL string correctly for safe mySQL insert (no mater if magic quotes are on or not)
|
||||
function escape($str) {
|
||||
return mysql_escape_string(stripslashes($str));
|
||||
}
|
||||
|
||||
## Return mySQL specific system date syntax
|
||||
function sysdate() {
|
||||
return 'NOW()';
|
||||
}
|
||||
|
||||
## Perform mySQL query and try to detirmin result value
|
||||
function query($query) {
|
||||
// For reg expressions
|
||||
$query = trim($query);
|
||||
// Initialise return
|
||||
$return_val = 0;
|
||||
// Flush cached values..
|
||||
$this->flush();
|
||||
// Log how the function was called
|
||||
$this->func_call = "\$db->query(\"$query\")";
|
||||
// Keep track of the last query for debug..
|
||||
$this->last_query = $query;
|
||||
// Perform the query via std mysql_query function..
|
||||
$this->result = @mysql_query($query,$this->dbh);
|
||||
$this->num_queries++;
|
||||
$this->all_queries .= $query.'<br />';
|
||||
// If there is an error then take note of it..
|
||||
if ($str = @mysql_error($this->dbh)) {
|
||||
$this->register_error($str);
|
||||
$this->show_errors ? trigger_error($str,E_USER_WARNING) : null;
|
||||
return false;
|
||||
}
|
||||
// Query was an insert, delete, update, replace
|
||||
if (preg_match("/^(insert|delete|update|replace)\s+/i",$query)) {
|
||||
$this->rows_affected = @mysql_affected_rows();
|
||||
// Take note of the insert_id
|
||||
if (preg_match("/^(insert|replace)\s+/i",$query)) {
|
||||
$this->insert_id = @mysql_insert_id($this->dbh);
|
||||
}
|
||||
// Return number fo rows affected
|
||||
$return_val = $this->rows_affected;
|
||||
// Query was a select
|
||||
} else {
|
||||
// Take note of column info
|
||||
$i=0;
|
||||
while ($i < @mysql_num_fields($this->result)) {
|
||||
$this->col_info[$i] = @mysql_fetch_field($this->result);
|
||||
$i++;
|
||||
}
|
||||
// Store Query Results
|
||||
$num_rows=0;
|
||||
while ($row = @mysql_fetch_object($this->result)) {
|
||||
// Store relults as an objects within main array
|
||||
$this->last_result[$num_rows] = $row;
|
||||
$num_rows++;
|
||||
}
|
||||
@mysql_free_result($this->result);
|
||||
// Log number of rows the query returned
|
||||
$this->num_rows = $num_rows;
|
||||
// Return number of rows selected
|
||||
$return_val = $this->num_rows;
|
||||
}
|
||||
// If debug ALL queries
|
||||
$this->trace || $this->debug_all ? $this->debug() : null ;
|
||||
return $return_val;
|
||||
}
|
||||
|
||||
function mysql_version() {
|
||||
return mysql_get_server_info( $this->dbh ) ;
|
||||
}
|
||||
}
|
||||
?>
|
195
includes/functions-auth.php
Normal file
@ -0,0 +1,195 @@
|
||||
<?php
|
||||
// Check for valid user. Returns true or an error message
|
||||
function yourls_is_valid_user() {
|
||||
static $valid = false;
|
||||
|
||||
if( $valid )
|
||||
return true;
|
||||
|
||||
// Logout request
|
||||
if( isset( $_GET['action'] ) && $_GET['action'] == 'logout') {
|
||||
yourls_store_cookie( null );
|
||||
return 'Logged out successfully';
|
||||
}
|
||||
|
||||
// Check cookies or login request. Login form has precedence.
|
||||
global $yourls_user_passwords;
|
||||
|
||||
// Determine auth method and check credentials
|
||||
if
|
||||
// API only: Secure (no login or pwd) and time limited token
|
||||
// ?timestamp=12345678&signature=md5(totoblah12345678)
|
||||
( yourls_is_API() &&
|
||||
isset($_REQUEST['timestamp']) && !empty($_REQUEST['timestamp']) &&
|
||||
isset($_REQUEST['signature']) && !empty($_REQUEST['signature'])
|
||||
)
|
||||
{
|
||||
$valid = yourls_check_signature_timestamp();
|
||||
}
|
||||
|
||||
elseif
|
||||
// API only: Secure (no login or pwd)
|
||||
// ?signature=md5(totoblah)
|
||||
( yourls_is_API() &&
|
||||
!isset($_REQUEST['timestamp']) &&
|
||||
isset($_REQUEST['signature']) && !empty($_REQUEST['signature'])
|
||||
)
|
||||
{
|
||||
$valid = yourls_check_signature();
|
||||
}
|
||||
|
||||
elseif
|
||||
// API or normal: login with username & pwd
|
||||
( isset($_REQUEST['username']) && isset($_REQUEST['password'])
|
||||
&& !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) )
|
||||
{
|
||||
$valid = yourls_check_username_password();
|
||||
}
|
||||
|
||||
elseif
|
||||
// Normal only: cookies
|
||||
( !yourls_is_API() &&
|
||||
isset($_COOKIE['yourls_username']) && isset($_COOKIE['yourls_password']) )
|
||||
{
|
||||
$valid = yourls_check_auth_cookie();
|
||||
}
|
||||
|
||||
// Login for the win!
|
||||
if ( $valid ) {
|
||||
// (Re)store encrypted cookie and tell it's ok
|
||||
if ( !yourls_is_API() ) // No need to store a cookie when used in API mode.
|
||||
yourls_store_cookie( YOURLS_USER );
|
||||
return true;
|
||||
}
|
||||
|
||||
// Login failed
|
||||
if ( isset($_REQUEST['username']) || isset($_REQUEST['password']) ) {
|
||||
return 'Invalid username or password';
|
||||
} else {
|
||||
return 'Please log in';
|
||||
}
|
||||
}
|
||||
|
||||
// Check auth against list of login=>pwd. Sets user if applicable, returns bool
|
||||
function yourls_check_username_password() {
|
||||
global $yourls_user_passwords;
|
||||
if( isset( $yourls_user_passwords[ $_REQUEST['username'] ] ) && yourls_check_password_hash( $yourls_user_passwords[ $_REQUEST['username'] ], $_REQUEST['password'] ) ) {
|
||||
yourls_set_user( $_REQUEST['username'] );
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check a REQUEST password sent in plain text against stored password which can be a salted hash
|
||||
function yourls_check_password_hash( $stored, $plaintext ) {
|
||||
if ( substr( $stored, 0, 4 ) == 'md5:' and strlen( $stored ) == 42 ) {
|
||||
// Stored password is a salted hash: "md5:<$r = rand(10000,99999)>:<md5($r.'thepassword')>"
|
||||
// And 42. Of course. http://www.google.com/search?q=the+answer+to+life+the+universe+and+everything
|
||||
list( $temp, $salt, $md5 ) = split( ':', $stored );
|
||||
return( $stored == 'md5:'.$salt.':'.md5( $salt.$plaintext ) );
|
||||
} else {
|
||||
// Password was sent in clear
|
||||
return( $stored == $plaintext );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check auth against encrypted COOKIE data. Sets user if applicable, returns bool
|
||||
function yourls_check_auth_cookie() {
|
||||
global $yourls_user_passwords;
|
||||
foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
|
||||
if(
|
||||
yourls_salt($valid_user) == $_COOKIE['yourls_username']
|
||||
&& yourls_salt($valid_password) == $_COOKIE['yourls_password']
|
||||
) {
|
||||
yourls_set_user( $valid_user );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check auth against signature and timestamp. Sets user if applicable, returns bool
|
||||
function yourls_check_signature_timestamp() {
|
||||
// Timestamp in PHP : time()
|
||||
// Timestamp in JS: parseInt(new Date().getTime() / 1000)
|
||||
global $yourls_user_passwords;
|
||||
foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
|
||||
if (
|
||||
(
|
||||
md5( $_REQUEST['timestamp'].yourls_auth_signature( $valid_user ) ) == $_REQUEST['signature']
|
||||
or
|
||||
md5( yourls_auth_signature( $valid_user ).$_REQUEST['timestamp'] ) == $_REQUEST['signature']
|
||||
)
|
||||
&&
|
||||
yourls_check_timestamp( $_REQUEST['timestamp'] )
|
||||
) {
|
||||
yourls_set_user( $valid_user );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check auth against signature. Sets user if applicable, returns bool
|
||||
function yourls_check_signature() {
|
||||
global $yourls_user_passwords;
|
||||
foreach( $yourls_user_passwords as $valid_user => $valid_password ) {
|
||||
if ( yourls_auth_signature( $valid_user ) == $_REQUEST['signature'] ) {
|
||||
yourls_set_user( $valid_user );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Generate secret signature hash
|
||||
function yourls_auth_signature( $username = false ) {
|
||||
if( !$username && defined('YOURLS_USER') ) {
|
||||
$username = YOURLS_USER;
|
||||
}
|
||||
return ( $username ? substr( yourls_salt( $username ), 0, 10 ) : 'Cannot generate auth signature: no username' );
|
||||
}
|
||||
|
||||
// Check a timestamp is from the past and not too old
|
||||
function yourls_check_timestamp( $time ) {
|
||||
$now = time();
|
||||
return ( $now >= $time && ceil( $now - $time ) < YOURLS_NONCE_LIFE );
|
||||
}
|
||||
|
||||
// Store new cookie. No $user will delete the cookie.
|
||||
function yourls_store_cookie( $user = null ) {
|
||||
if( !$user ) {
|
||||
$pass = null;
|
||||
$time = time() - 3600;
|
||||
} else {
|
||||
global $yourls_user_passwords;
|
||||
if( isset($yourls_user_passwords[$user]) ) {
|
||||
$pass = $yourls_user_passwords[$user];
|
||||
} else {
|
||||
die('Stealing cookies?'); // This should never happen
|
||||
}
|
||||
$time = time() + YOURLS_COOKIE_LIFE;
|
||||
}
|
||||
|
||||
$domain = yourls_apply_filter( 'setcookie_domain', parse_url( YOURLS_SITE, 1 ) );
|
||||
$secure = yourls_apply_filter( 'setcookie_secure', yourls_is_ssl() );
|
||||
$httponly = yourls_apply_filter( 'setcookie_httponly', true );
|
||||
|
||||
if ( !headers_sent() ) {
|
||||
// Set httponly if the php version is >= 5.2.0
|
||||
if( version_compare( phpversion(), '5.2.0', 'ge' ) ) {
|
||||
setcookie('yourls_username', yourls_salt( $user ), $time, '/', $domain, $secure, $httponly );
|
||||
setcookie('yourls_password', yourls_salt( $pass ), $time, '/', $domain, $secure, $httponly );
|
||||
} else {
|
||||
setcookie('yourls_username', yourls_salt( $user ), $time, '/', $domain, $secure );
|
||||
setcookie('yourls_password', yourls_salt( $pass ), $time, '/', $domain, $secure );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set user name
|
||||
function yourls_set_user( $user ) {
|
||||
if( !defined('YOURLS_USER') )
|
||||
define('YOURLS_USER', $user);
|
||||
}
|
151
includes/functions-compat.php
Normal file
@ -0,0 +1,151 @@
|
||||
<?php
|
||||
|
||||
// json_encode for PHP prior to 5.2
|
||||
if( !function_exists( 'json_encode' ) ) {
|
||||
function json_encode( $array ) {
|
||||
return yourls_array_to_json( $array );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an associative array of arbitrary depth and dimension into JSON representation. Used for compatibility with older PHP builds.
|
||||
*
|
||||
* @param $array The array to convert.
|
||||
* @return mixed The resulting JSON string, or false if the argument was not an array.
|
||||
* @author Andy Rusterholz
|
||||
* @link http://php.net/json_encode (see comments)
|
||||
*/
|
||||
function yourls_array_to_json( $array ){
|
||||
|
||||
if( !is_array( $array ) ){
|
||||
return false;
|
||||
}
|
||||
|
||||
$associative = count( array_diff( array_keys($array), array_keys( array_keys( $array )) ));
|
||||
if( $associative ){
|
||||
|
||||
$construct = array();
|
||||
foreach( $array as $key => $value ){
|
||||
|
||||
// We first copy each key/value pair into a staging array,
|
||||
// formatting each key and value properly as we go.
|
||||
|
||||
// Format the key:
|
||||
if( is_numeric($key) ){
|
||||
$key = "key_$key";
|
||||
}
|
||||
$key = '"'.addslashes($key).'"';
|
||||
|
||||
// Format the value:
|
||||
if( is_array( $value )){
|
||||
$value = yourls_array_to_json( $value );
|
||||
} else if( !is_numeric( $value ) || is_string( $value ) ){
|
||||
$value = '"'.addslashes($value).'"';
|
||||
}
|
||||
|
||||
// Add to staging array:
|
||||
$construct[] = "$key: $value";
|
||||
}
|
||||
|
||||
// Then we collapse the staging array into the JSON form:
|
||||
$result = "{ " . implode( ", ", $construct ) . " }";
|
||||
|
||||
} else { // If the array is a vector (not associative):
|
||||
|
||||
$construct = array();
|
||||
foreach( $array as $value ){
|
||||
|
||||
// Format the value:
|
||||
if( is_array( $value )){
|
||||
$value = yourls_array_to_json( $value );
|
||||
} else if( !is_numeric( $value ) || is_string( $value ) ){
|
||||
$value = '"'.addslashes($value).'"';
|
||||
}
|
||||
|
||||
// Add to staging array:
|
||||
$construct[] = $value;
|
||||
}
|
||||
|
||||
// Then we collapse the staging array into the JSON form:
|
||||
$result = "[ " . implode( ", ", $construct ) . " ]";
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
// Compat http_build_query for PHP4
|
||||
if (!function_exists('http_build_query')) {
|
||||
function http_build_query($data, $prefix=null, $sep=null) {
|
||||
return yourls_http_build_query($data, $prefix, $sep);
|
||||
}
|
||||
}
|
||||
|
||||
// from php.net (modified by Mark Jaquith to behave like the native PHP5 function)
|
||||
function yourls_http_build_query($data, $prefix=null, $sep=null, $key='', $urlencode=true) {
|
||||
$ret = array();
|
||||
|
||||
foreach ( (array) $data as $k => $v ) {
|
||||
if ( $urlencode)
|
||||
$k = urlencode($k);
|
||||
if ( is_int($k) && $prefix != null )
|
||||
$k = $prefix.$k;
|
||||
if ( !empty($key) )
|
||||
$k = $key . '%5B' . $k . '%5D';
|
||||
if ( $v === NULL )
|
||||
continue;
|
||||
elseif ( $v === FALSE )
|
||||
$v = '0';
|
||||
|
||||
if ( is_array($v) || is_object($v) )
|
||||
array_push($ret,yourls_http_build_query($v, '', $sep, $k, $urlencode));
|
||||
elseif ( $urlencode )
|
||||
array_push($ret, $k.'='.urlencode($v));
|
||||
else
|
||||
array_push($ret, $k.'='.$v);
|
||||
}
|
||||
|
||||
if ( NULL === $sep )
|
||||
$sep = ini_get('arg_separator.output');
|
||||
|
||||
return implode($sep, $ret);
|
||||
}
|
||||
|
||||
// htmlspecialchars_decode for PHP < 5.1
|
||||
if ( !function_exists('htmlspecialchars_decode') ) {
|
||||
function htmlspecialchars_decode($text) {
|
||||
return strtr($text, array_flip(get_html_translation_table(HTML_SPECIALCHARS)));
|
||||
}
|
||||
}
|
||||
|
||||
// BC Math functions (assuming if one doesn't exist, none does)
|
||||
if ( !function_exists( 'bcdiv' )) {
|
||||
function bcdiv( $dividend, $divisor ) {
|
||||
$quotient = floor( $dividend/$divisor );
|
||||
return $quotient;
|
||||
}
|
||||
function bcmod( $dividend, $modulo ) {
|
||||
$remainder = $dividend%$modulo;
|
||||
return $remainder;
|
||||
}
|
||||
function bcmul( $left, $right ) {
|
||||
return $left * $right;
|
||||
}
|
||||
function bcadd( $left, $right ) {
|
||||
return $left + $right;
|
||||
}
|
||||
function bcpow( $base, $power ) {
|
||||
return pow( $base, $power );
|
||||
}
|
||||
}
|
||||
|
||||
// Replacement for property_exists() (5.1+)
|
||||
if ( !function_exists( 'property_exists' ) ) {
|
||||
function property_exists( $class, $property ) {
|
||||
if ( is_object( $class ) ) {
|
||||
$vars = get_object_vars( $class );
|
||||
} else {
|
||||
$vars = get_class_vars( $class );
|
||||
}
|
||||
return array_key_exists( $property, $vars );
|
||||
}
|
||||
}
|
211
includes/functions-formatting.php
Normal file
@ -0,0 +1,211 @@
|
||||
<?php
|
||||
/*
|
||||
* YOURLS
|
||||
* Function library for anything related to formatting / validating / sanitizing
|
||||
*/
|
||||
|
||||
// function to convert an integer (1337) to a string (3jk).
|
||||
function yourls_int2string( $num, $chars = null ) {
|
||||
if( $chars == null )
|
||||
$chars = yourls_get_shorturl_charset();
|
||||
$string = '';
|
||||
$len = strlen( $chars );
|
||||
while( $num >= $len ) {
|
||||
$mod = bcmod( $num, $len );
|
||||
$num = bcdiv( $num, $len );
|
||||
$string = $chars[$mod] . $string;
|
||||
}
|
||||
$string = $chars[$num] . $string;
|
||||
|
||||
return yourls_apply_filter( 'int2string', $string, $num, $chars );
|
||||
}
|
||||
|
||||
// function to convert a string (3jk) to an integer (1337)
|
||||
function yourls_string2int( $string, $chars = null ) {
|
||||
if( $chars == null )
|
||||
$chars = yourls_get_shorturl_charset();
|
||||
$integer = 0;
|
||||
$string = strrev( $string );
|
||||
$baselen = strlen( $chars );
|
||||
$inputlen = strlen( $string );
|
||||
for ($i = 0; $i < $inputlen; $i++) {
|
||||
$index = strpos( $chars, $string[$i] );
|
||||
$integer = bcadd( $integer, bcmul( $index, bcpow( $baselen, $i ) ) );
|
||||
}
|
||||
|
||||
return yourls_apply_filter( 'string2int', $integer, $string, $chars );
|
||||
}
|
||||
|
||||
// return a unique(ish) hash for a string to be used as a valid HTML id
|
||||
function yourls_string2htmlid( $string ) {
|
||||
return yourls_apply_filter( 'string2htmlid', 'y'.abs( crc32( $string ) ) );
|
||||
}
|
||||
|
||||
// Make sure a link keyword (ie "1fv" as in "site.com/1fv") is valid.
|
||||
function yourls_sanitize_string( $string ) {
|
||||
// make a regexp pattern with the shorturl charset, and remove everything but this
|
||||
$pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() );
|
||||
$valid = substr(preg_replace('![^'.$pattern.']!', '', $string ), 0, 199);
|
||||
|
||||
return yourls_apply_filter( 'sanitize_string', $valid, $string );
|
||||
}
|
||||
|
||||
// Alias function. I was always getting it wrong.
|
||||
function yourls_sanitize_keyword( $keyword ) {
|
||||
return yourls_sanitize_string( $keyword );
|
||||
}
|
||||
|
||||
// Sanitize a page title. No HTML per W3C http://www.w3.org/TR/html401/struct/global.html#h-7.4.2
|
||||
function yourls_sanitize_title( $title ) {
|
||||
// TODO: make stronger Implement KSES?
|
||||
$title = strip_tags( $title );
|
||||
// Remove extra white space
|
||||
$title = preg_replace( "/\s+/", ' ', trim( $title ) );
|
||||
return $title;
|
||||
}
|
||||
|
||||
// A few sanity checks on the URL
|
||||
function yourls_sanitize_url( $url, $force_protocol = true, $force_lowercase = true ) {
|
||||
// make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
|
||||
$url = str_replace(
|
||||
array( 'http://http://', 'http://https://' ),
|
||||
array( 'http://', 'https://' ),
|
||||
$url
|
||||
);
|
||||
|
||||
if( $force_protocol ) {
|
||||
// make sure there's a protocol, add http:// if not
|
||||
if ( !preg_match('!^([a-zA-Z]+://)!', $url ) )
|
||||
$url = 'http://'.$url;
|
||||
}
|
||||
|
||||
if( $force_lowercase ) {
|
||||
// force scheme and domain to lowercase - see issue 591
|
||||
preg_match( '!^([a-zA-Z]+://([^/]+))(.*)$!', $url, $matches );
|
||||
if( isset( $matches[1] ) && isset( $matches[3] ) )
|
||||
$url = strtolower( $matches[1] ) . $matches[3];
|
||||
}
|
||||
|
||||
// clean and shave
|
||||
$url = yourls_clean_url( $url );
|
||||
return substr( $url, 0, 1999 );
|
||||
}
|
||||
|
||||
// Function to filter all invalid characters from a URL. Stolen from WP's clean_url()
|
||||
function yourls_clean_url( $url ) {
|
||||
$url = preg_replace( '|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*\'"()\\x80-\\xff]|i', '', $url );
|
||||
$strip = array( '%0d', '%0a', '%0D', '%0A' );
|
||||
$url = yourls_deep_replace( $strip, $url );
|
||||
$url = str_replace( ';//', '://', $url );
|
||||
$url = str_replace( '&', '&', $url ); // Revert & not to break query strings
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
// Perform a replacement while a string is found, eg $subject = '%0%0%0DDD', $search ='%0D' -> $result =''
|
||||
// Stolen from WP's _deep_replace
|
||||
function yourls_deep_replace($search, $subject){
|
||||
$found = true;
|
||||
while($found) {
|
||||
$found = false;
|
||||
foreach( (array) $search as $val ) {
|
||||
while(strpos($subject, $val) !== false) {
|
||||
$found = true;
|
||||
$subject = str_replace($val, '', $subject);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $subject;
|
||||
}
|
||||
|
||||
// Make sure an integer is a valid integer (PHP's intval() limits to too small numbers)
|
||||
// TODO FIXME FFS: unused ?
|
||||
function yourls_sanitize_int($in) {
|
||||
return ( substr(preg_replace('/[^0-9]/', '', strval($in) ), 0, 20) );
|
||||
}
|
||||
|
||||
// Make sure a integer is safe
|
||||
// Note: this is not checking for integers, since integers on 32bits system are way too limited
|
||||
// TODO: find a way to validate as integer
|
||||
function yourls_intval($in) {
|
||||
return yourls_escape($in);
|
||||
}
|
||||
|
||||
// Escape a string
|
||||
function yourls_escape( $in ) {
|
||||
return mysql_real_escape_string($in);
|
||||
}
|
||||
|
||||
// Sanitize an IP address
|
||||
function yourls_sanitize_ip( $ip ) {
|
||||
return preg_replace( '/[^0-9a-fA-F:., ]/', '', $ip );
|
||||
}
|
||||
|
||||
// Make sure a date is m(m)/d(d)/yyyy, return false otherwise
|
||||
function yourls_sanitize_date( $date ) {
|
||||
if( !preg_match( '!^\d{1,2}/\d{1,2}/\d{4}$!' , $date ) ) {
|
||||
return false;
|
||||
}
|
||||
return $date;
|
||||
}
|
||||
|
||||
// Sanitize a date for SQL search. Return false if malformed input.
|
||||
function yourls_sanitize_date_for_sql( $date ) {
|
||||
if( !yourls_sanitize_date( $date ) )
|
||||
return false;
|
||||
return date('Y-m-d', strtotime( $date ) );
|
||||
}
|
||||
|
||||
// Return word or words if more than one
|
||||
function yourls_plural( $word, $count=1 ) {
|
||||
return $word . ($count > 1 ? 's' : '');
|
||||
}
|
||||
|
||||
// Return trimmed string
|
||||
function yourls_trim_long_string( $string, $length = 60, $append = '[...]' ) {
|
||||
$newstring = $string;
|
||||
if( function_exists('mb_substr') ) {
|
||||
if ( mb_strlen( $newstring ) > $length ) {
|
||||
$newstring = mb_substr( $newstring, 0, $length - mb_strlen( $append ), 'UTF-8' ) . $append;
|
||||
}
|
||||
} else {
|
||||
if ( strlen( $newstring ) > $length ) {
|
||||
$newstring = substr( $newstring, 0, $length - strlen( $append ) ) . $append;
|
||||
}
|
||||
}
|
||||
return yourls_apply_filter( 'trim_long_string', $newstring, $string, $length, $append );
|
||||
}
|
||||
|
||||
// Sanitize a version number (1.4.1-whatever -> 1.4.1)
|
||||
function yourls_sanitize_version( $ver ) {
|
||||
return preg_replace( '/[^0-9.]/', '', $ver );
|
||||
}
|
||||
|
||||
// Sanitize a filename (no Win32 stuff)
|
||||
function yourls_sanitize_filename( $file ) {
|
||||
$file = str_replace( '\\', '/', $file ); // sanitize for Win32 installs
|
||||
$file = preg_replace( '|/+|' ,'/', $file ); // remove any duplicate slash
|
||||
return $file;
|
||||
}
|
||||
|
||||
// Check if a string seems to be UTF-8. Stolen from WP.
|
||||
function yourls_seems_utf8($str) {
|
||||
$length = strlen($str);
|
||||
for ($i=0; $i < $length; $i++) {
|
||||
$c = ord($str[$i]);
|
||||
if ($c < 0x80) $n = 0; # 0bbbbbbb
|
||||
elseif (($c & 0xE0) == 0xC0) $n=1; # 110bbbbb
|
||||
elseif (($c & 0xF0) == 0xE0) $n=2; # 1110bbbb
|
||||
elseif (($c & 0xF8) == 0xF0) $n=3; # 11110bbb
|
||||
elseif (($c & 0xFC) == 0xF8) $n=4; # 111110bb
|
||||
elseif (($c & 0xFE) == 0xFC) $n=5; # 1111110b
|
||||
else return false; # Does not match any model
|
||||
for ($j=0; $j<$n; $j++) { # n bytes matching 10bbbbbb follow ?
|
||||
if ((++$i == $length) || ((ord($str[$i]) & 0xC0) != 0x80))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
626
includes/functions-html.php
Normal file
@ -0,0 +1,626 @@
|
||||
<?php
|
||||
|
||||
// Display <h1> header and logo
|
||||
function yourls_html_logo() {
|
||||
yourls_do_action( 'pre_html_logo' );
|
||||
?>
|
||||
<h1>
|
||||
<a href="<?php echo yourls_admin_url('index.php') ?>" title="YOURLS"><span>YOURLS</span>: <span>Y</span>our <span>O</span>wn <span>URL</span> <span>S</span>hortener<br/>
|
||||
<img src="<?php yourls_site_url(); ?>/images/yourls-logo.png" alt="YOURLS" title="YOURLS" border="0" style="border: 0px;" /></a>
|
||||
</h1>
|
||||
<?php
|
||||
yourls_do_action( 'html_logo' );
|
||||
}
|
||||
|
||||
// Display HTML head and <body> tag
|
||||
function yourls_html_head( $context = 'index', $title = '' ) {
|
||||
|
||||
yourls_do_action( 'pre_html_head', $context, $title );
|
||||
|
||||
// All components to false, except when specified true
|
||||
$share = $insert = $tablesorter = $tabs = $cal = false;
|
||||
|
||||
// Load components as needed
|
||||
switch ( $context ) {
|
||||
case 'infos':
|
||||
$share = $tabs = true;
|
||||
break;
|
||||
|
||||
case 'bookmark':
|
||||
$share = $insert = $tablesorter = true;
|
||||
break;
|
||||
|
||||
case 'index':
|
||||
$insert = $tablesorter = $cal = $share = true;
|
||||
break;
|
||||
|
||||
case 'plugins':
|
||||
case 'tools':
|
||||
$tablesorter = true;
|
||||
break;
|
||||
|
||||
case 'install':
|
||||
case 'login':
|
||||
case 'new':
|
||||
case 'upgrade':
|
||||
break;
|
||||
}
|
||||
|
||||
// Force no cache for all admin pages
|
||||
if( yourls_is_admin() && !headers_sent() ) {
|
||||
header( 'Expires: Thu, 23 Mar 1972 07:00:00 GMT' );
|
||||
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . ' GMT' );
|
||||
header( 'Cache-Control: no-cache, must-revalidate, max-age=0' );
|
||||
header( 'Pragma: no-cache' );
|
||||
yourls_do_action( 'admin_headers', $context, $title );
|
||||
}
|
||||
|
||||
// Store page context in global object
|
||||
global $ydb;
|
||||
$ydb->context = $context;
|
||||
|
||||
// Body class
|
||||
$bodyclass = yourls_apply_filter( 'bodyclass', '' );
|
||||
$bodyclass .= ( yourls_is_mobile_device() ? 'mobile' : 'desktop' );
|
||||
|
||||
// Page title
|
||||
$_title = 'YOURLS — Your Own URL Shortener | ' . yourls_link();
|
||||
$title = $title ? $title . " « " . $_title : $_title;
|
||||
$title = yourls_apply_filter( 'html_title', $title, $context );
|
||||
|
||||
?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title><?php echo $title ?></title>
|
||||
<link rel="icon" type="image/gif" href="<?php yourls_site_url(); ?>/images/favicon.gif" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="chrome=1" />
|
||||
<meta name="author" content="Ozh RICHARD & Lester CHAN for http://yourls.org/" />
|
||||
<meta name="generator" content="YOURLS <?php echo YOURLS_VERSION ?>" />
|
||||
<meta name="description" content="Insert URL « YOURLS » Your Own URL Shortener' | <?php yourls_site_url(); ?>" />
|
||||
<script src="<?php yourls_site_url(); ?>/js/jquery-1.6.1.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<script src="<?php yourls_site_url(); ?>/js/common.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<script src="<?php yourls_site_url(); ?>/js/jquery.notifybar.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/style.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
|
||||
<?php if ($tabs) { ?>
|
||||
<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/infos.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
|
||||
<script src="<?php yourls_site_url(); ?>/js/infos.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<?php } ?>
|
||||
<?php if ($tablesorter) { ?>
|
||||
<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/tablesorter.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
|
||||
<script src="<?php yourls_site_url(); ?>/js/jquery.tablesorter.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<?php } ?>
|
||||
<?php if ($insert) { ?>
|
||||
<script src="<?php yourls_site_url(); ?>/js/insert.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<?php } ?>
|
||||
<?php if ($share) { ?>
|
||||
<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/share.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
|
||||
<script src="<?php yourls_site_url(); ?>/js/share.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<script src="<?php yourls_site_url(); ?>/js/jquery.zclip.min.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<?php } ?>
|
||||
<?php if ($cal) { ?>
|
||||
<link rel="stylesheet" href="<?php yourls_site_url(); ?>/css/cal.css?v=<?php echo YOURLS_VERSION; ?>" type="text/css" media="screen" />
|
||||
<script src="<?php yourls_site_url(); ?>/js/jquery.cal.js?v=<?php echo YOURLS_VERSION; ?>" type="text/javascript"></script>
|
||||
<?php } ?>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
var ajaxurl = '<?php echo yourls_admin_url( 'admin-ajax.php' ); ?>';
|
||||
var zclipurl = '<?php yourls_site_url(); ?>/js/ZeroClipboard.swf';
|
||||
//]]>
|
||||
</script>
|
||||
<?php yourls_do_action( 'html_head', $context ); ?>
|
||||
</head>
|
||||
<body class="<?php echo $context; ?> <?php echo $bodyclass; ?>">
|
||||
<div id="wrap">
|
||||
<?php
|
||||
}
|
||||
|
||||
// Display HTML footer (including closing body & html tags)
|
||||
function yourls_html_footer() {
|
||||
global $ydb;
|
||||
|
||||
$num_queries = $ydb->num_queries > 1 ? $ydb->num_queries.' queries' : $ydb->num_queries.' query';
|
||||
?>
|
||||
</div> <?php // wrap ?>
|
||||
<div id="footer"><p>Powered by <a href="http://yourls.org/" title="YOURLS">YOURLS</a> v<?php echo YOURLS_VERSION; echo ' – '.$num_queries; ?></p></div>
|
||||
<?php if( defined('YOURLS_DEBUG') && YOURLS_DEBUG == true ) {
|
||||
echo '<p>'. $ydb->all_queries .'<p>';
|
||||
} ?>
|
||||
<?php yourls_do_action( 'html_footer', $ydb->context ); ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Display "Add new URL" box
|
||||
function yourls_html_addnew( $url = '', $keyword = '' ) {
|
||||
$url = $url ? $url : 'http://';
|
||||
?>
|
||||
<div id="new_url">
|
||||
<div>
|
||||
<form id="new_url_form" action="" method="get">
|
||||
<div><strong>Enter the URL</strong>:<input type="text" id="add-url" name="url" value="<?php echo $url; ?>" class="text" size="80" />
|
||||
Optional: <strong>Custom short URL</strong>:<input type="text" id="add-keyword" name="keyword" value="<?php echo $keyword; ?>" class="text" size="8" />
|
||||
<?php yourls_nonce_field( 'add_url', 'nonce-add' ); ?>
|
||||
<input type="button" id="add-button" name="add-button" value="Shorten The URL" class="button" onclick="add();" /></div>
|
||||
</form>
|
||||
<div id="feedback" style="display:none"></div>
|
||||
</div>
|
||||
<?php yourls_do_action( 'html_addnew' ); ?>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Display main table's footer
|
||||
function yourls_html_tfooter( $params = array() ) {
|
||||
extract( $params ); // extract $search_text, $page, $search_in_sql ...
|
||||
|
||||
?>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<th colspan="6">
|
||||
<div id="filter_form">
|
||||
<form action="" method="get">
|
||||
<div id="filter_options">
|
||||
Search for
|
||||
<input type="text" name="s_search" class="text" size="15" value="<?php echo $search_text; ?>" />
|
||||
in
|
||||
<select name="s_in" size="1">
|
||||
<option value="keyword"<?php if($search_in_sql == 'keyword') { echo ' selected="selected"'; } ?>>Short URL</option>
|
||||
<option value="url"<?php if($search_in_sql == 'url') { echo ' selected="selected"'; } ?>>URL</option>
|
||||
<option value="title"<?php if($search_in_sql == 'title') { echo ' selected="selected"'; } ?>>Title</option>
|
||||
<option value="ip"<?php if($search_in_sql == 'ip') { echo ' selected="selected"'; } ?>>IP</option>
|
||||
</select>
|
||||
– Order by
|
||||
<select name="s_by" size="1">
|
||||
<option value="id"<?php if($sort_by_sql == 'keyword') { echo ' selected="selected"'; } ?>>Short URL</option>
|
||||
<option value="url"<?php if($sort_by_sql == 'url') { echo ' selected="selected"'; } ?>>URL</option>
|
||||
<option value="timestamp"<?php if($sort_by_sql == 'timestamp') { echo ' selected="selected"'; } ?>>Date</option>
|
||||
<option value="ip"<?php if($sort_by_sql == 'ip') { echo ' selected="selected"'; } ?>>IP</option>
|
||||
<option value="clicks"<?php if($sort_by_sql == 'clicks') { echo ' selected="selected"'; } ?>>Clicks</option>
|
||||
</select>
|
||||
<select name="s_order" size="1">
|
||||
<option value="asc"<?php if($sort_order_sql == 'asc') { echo ' selected="selected"'; } ?>>Ascending</option>
|
||||
<option value="desc"<?php if($sort_order_sql == 'desc') { echo ' selected="selected"'; } ?>>Descending</option>
|
||||
</select>
|
||||
– Show
|
||||
<input type="text" name="perpage" class="text" size="2" value="<?php echo $perpage; ?>" /> rows<br/>
|
||||
|
||||
Show links with
|
||||
<select name="link_filter" size="1">
|
||||
<option value="more"<?php if($link_filter === 'more') { echo ' selected="selected"'; } ?>>more</option>
|
||||
<option value="less"<?php if($link_filter === 'less') { echo ' selected="selected"'; } ?>>less</option>
|
||||
</select>
|
||||
than
|
||||
<input type="text" name="link_limit" class="text" size="4" value="<?php echo $link_limit; ?>" />clicks<br/>
|
||||
|
||||
Show links created
|
||||
<select name="date_filter" id="date_filter" size="1">
|
||||
<option value="before"<?php if($date_filter === 'before') { echo ' selected="selected"'; } ?>>before</option>
|
||||
<option value="after"<?php if($date_filter === 'after') { echo ' selected="selected"'; } ?>>after</option>
|
||||
<option value="between"<?php if($date_filter === 'between') { echo ' selected="selected"'; } ?>> between</option>
|
||||
</select>
|
||||
<input type="text" name="date_first" id="date_first" class="text" size="12" value="<?php echo $date_first; ?>" />
|
||||
<span id="date_and" <?php if($date_filter === 'between') { echo ' style="display:inline"'; } ?>> and </span>
|
||||
<input type="text" name="date_second" id="date_second" class="text" size="12" value="<?php echo $date_second; ?>" <?php if($date_filter === 'between') { echo ' style="display:inline"'; } ?>/>
|
||||
|
||||
<div id="filter_buttons">
|
||||
<input type="submit" id="submit-sort" value="Search" class="button primary" />
|
||||
|
||||
<input type="button" id="submit-clear-filter" value="Clear" class="button" onclick="window.parent.location.href = 'index.php'" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div id="pagination">
|
||||
<span class="navigation">
|
||||
<?php if( $total_pages > 1 ) { ?>
|
||||
<span class="nav_total"><?php echo $total_pages .' '. yourls_plural( 'page', $total_pages ); ?></span>
|
||||
<?php
|
||||
$base_page = yourls_admin_url( 'index.php' );
|
||||
// Pagination offsets: min( max ( zomg! ) );
|
||||
$p_start = max( min( $total_pages - 4, $page - 2 ), 1 );
|
||||
$p_end = min( max( 5, $page + 2 ), $total_pages );
|
||||
if( $p_start >= 2 ) {
|
||||
$link = yourls_add_query_arg( array_merge( $params, array( 'page' => 1 ) ), $base_page );
|
||||
echo '<span class="nav_link nav_first"><a href="' . $link . '" title="Go to First Page">« First</a></span>';
|
||||
echo '<span class="nav_link nav_prev"></span>';
|
||||
}
|
||||
for( $i = $p_start ; $i <= $p_end; $i++ ) {
|
||||
if( $i == $page ) {
|
||||
echo "<span class='nav_link nav_current'>$i</span>";
|
||||
} else {
|
||||
$link = yourls_add_query_arg( array_merge( $params, array( 'page' => $i ) ), $base_page );
|
||||
echo '<span class="nav_link nav_goto"><a href="' . $link . '" title="Page '.$i.'">'.$i.'</a></span>';
|
||||
}
|
||||
}
|
||||
if( ( $p_end ) < $total_pages ) {
|
||||
$link = yourls_add_query_arg( array_merge( $params, array( 'page' => $total_pages ) ), $base_page );
|
||||
echo '<span class="nav_link nav_next"></span>';
|
||||
echo '<span class="nav_link nav_last"><a href="' . $link . '" title="Go to Last Page">Last »</a></span>';
|
||||
}
|
||||
?>
|
||||
<?php } ?>
|
||||
</span>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
<?php yourls_do_action( 'html_tfooter' ); ?>
|
||||
</tfoot>
|
||||
<?php
|
||||
}
|
||||
|
||||
// Display the Quick Share box
|
||||
function yourls_share_box( $longurl, $shorturl, $title='', $text='', $shortlink_title = '<h2>Your short link</h2>', $share_title = '<h2>Quick Share</h2>', $hidden = false ) {
|
||||
// Allow plugins to short-circuit the whole function
|
||||
$pre = yourls_apply_filter( 'shunt_share_box', false );
|
||||
if ( false !== $pre )
|
||||
return $pre;
|
||||
|
||||
$text = ( $text ? '"'.$text.'" ' : '' );
|
||||
$title = ( $title ? "$title " : '' );
|
||||
$share = htmlspecialchars_decode( $title.$text.$shorturl );
|
||||
$count = 140 - strlen( $share );
|
||||
$hidden = ( $hidden ? 'style="display:none;"' : '' );
|
||||
|
||||
// Allow plugins to filter all data
|
||||
$data = compact( 'longurl', 'shorturl', 'title', 'text', 'shortlink_title', 'share_title', 'share', 'count', 'hidden' );
|
||||
$data = yourls_apply_filter( 'share_box_data', $data );
|
||||
extract( $data );
|
||||
|
||||
$_share = rawurlencode( $share );
|
||||
$_url = rawurlencode( $shorturl );
|
||||
?>
|
||||
|
||||
<div id="shareboxes" <?php echo $hidden; ?>>
|
||||
|
||||
<?php yourls_do_action( 'shareboxes_before', $longurl, $shorturl, $title, $text ); ?>
|
||||
|
||||
<div id="copybox" class="share">
|
||||
<?php echo $shortlink_title; ?>
|
||||
<p><input id="copylink" class="text" size="32" value="<?php echo $shorturl; ?>" /></p>
|
||||
<p><small>Long link: <a id="origlink" href="<?php echo $longurl; ?>"><?php echo $longurl; ?></a></small>
|
||||
<?php if( yourls_do_log_redirect() ) { ?>
|
||||
<br/><small>Stats: <a id="statlink" href="<?php echo $shorturl; ?>+"><?php echo $shorturl; ?>+</a></small>
|
||||
<input type="hidden" id="titlelink" value="<?php echo $title; ?>" />
|
||||
<?php } ?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php yourls_do_action( 'shareboxes_middle', $longurl, $shorturl, $title, $text ); ?>
|
||||
|
||||
<div id="sharebox" class="share">
|
||||
<?php echo $share_title; ?>
|
||||
<div id="tweet">
|
||||
<span id="charcount" class="hide-if-no-js"><?php echo $count; ?></span>
|
||||
<textarea id="tweet_body"><?php echo $share; ?></textarea>
|
||||
</div>
|
||||
<p id="share_links">Share with
|
||||
<a id="share_tw" href="http://twitter.com/home?status=<?php echo $_share; ?>" title="Tweet this!" onclick="share('tw');return false">Twitter</a>
|
||||
<a id="share_fb" href="http://www.facebook.com/share.php?u=<?php echo $_url; ?>" title="Share on Facebook" onclick="share('fb');return false;">Facebook</a>
|
||||
<a id="share_ff" href="http://friendfeed.com/share/bookmarklet/frame#title=<?php echo $_share; ?>" title="Share on Friendfeed" onclick="javascript:share('ff');return false;">FriendFeed</a>
|
||||
<?php
|
||||
yourls_do_action( 'share_links', $longurl, $shorturl, $title, $text );
|
||||
// Note: on the main admin page, there are no parameters passed to the sharebox when it's drawn.
|
||||
?>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<?php yourls_do_action( 'shareboxes_after', $longurl, $shorturl, $title, $text ); ?>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
}
|
||||
|
||||
// Die die die
|
||||
function yourls_die( $message = '', $title = '', $header_code = 200 ) {
|
||||
yourls_status_header( $header_code );
|
||||
|
||||
yourls_html_head();
|
||||
yourls_html_logo();
|
||||
echo yourls_apply_filter( 'die_title', "<h2>$title</h2>" );
|
||||
echo yourls_apply_filter( 'die_message', "<p>$message</p>" );
|
||||
yourls_do_action( 'yourls_die' );
|
||||
yourls_html_footer();
|
||||
die();
|
||||
}
|
||||
|
||||
// Add the "Edit" row
|
||||
function yourls_table_edit_row( $keyword ) {
|
||||
global $ydb;
|
||||
|
||||
$table = YOURLS_DB_TABLE_URL;
|
||||
$keyword = yourls_sanitize_string( $keyword );
|
||||
$id = yourls_string2htmlid( $keyword ); // used as HTML #id
|
||||
$url = yourls_get_keyword_longurl( $keyword );
|
||||
$title = htmlspecialchars( yourls_get_keyword_title( $keyword ) );
|
||||
$safe_url = stripslashes( $url );
|
||||
$safe_title = stripslashes( $title );
|
||||
$www = yourls_link();
|
||||
|
||||
$save_link = yourls_nonce_url( 'save-link_'.$id,
|
||||
yourls_add_query_arg( array( 'id' => $id, 'action' => 'edit_save', 'keyword' => $keyword ), yourls_admin_url( 'admin-ajax.php' ) )
|
||||
);
|
||||
|
||||
$nonce = yourls_create_nonce( 'edit-save_'.$id );
|
||||
|
||||
if( $url ) {
|
||||
$return = <<<RETURN
|
||||
<tr id="edit-$id" class="edit-row"><td colspan="5"><strong>Original URL</strong>:<input type="text" id="edit-url-$id" name="edit-url-$id" value="$safe_url" class="text" size="70" /> <strong>Short URL</strong>: $www<input type="text" id="edit-keyword-$id" name="edit-keyword-$id" value="$keyword" class="text" size="10" /><br/><strong>Title</strong>: <input type="text" id="edit-title-$id" name="edit-title-$id" value="$safe_title" class="text" size="60" /></td><td colspan="1"><input type="button" id="edit-submit-$id" name="edit-submit-$id" value="Save" title="Save new values" class="button" onclick="edit_save('$id');" /> <input type="button" id="edit-close-$id" name="edit-close-$id" value="X" title="Cancel editing" class="button" onclick="hide_edit('$id');" /><input type="hidden" id="old_keyword_$id" value="$keyword"/><input type="hidden" id="nonce_$id" value="$nonce"/></td></tr>
|
||||
RETURN;
|
||||
} else {
|
||||
$return = '<tr><td colspan="6">Error, URL not found</td></tr>';
|
||||
}
|
||||
|
||||
$return = yourls_apply_filter( 'table_edit_row', $return, $keyword, $url, $title );
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
// Add a link row
|
||||
function yourls_table_add_row( $keyword, $url, $title = '', $ip, $clicks, $timestamp ) {
|
||||
$keyword = yourls_sanitize_string( $keyword );
|
||||
$display_keyword = htmlentities( $keyword );
|
||||
|
||||
$url = yourls_sanitize_url( $url );
|
||||
$display_url = htmlentities( yourls_trim_long_string( $url ) );
|
||||
$title_url = htmlspecialchars( $url );
|
||||
|
||||
$title = yourls_sanitize_title( $title ) ;
|
||||
$display_title = yourls_trim_long_string( $title );
|
||||
$title = htmlspecialchars( $title );
|
||||
|
||||
$id = yourls_string2htmlid( $keyword ); // used as HTML #id
|
||||
$date = date( 'M d, Y H:i', $timestamp+( YOURLS_HOURS_OFFSET * 3600 ) );
|
||||
$clicks = number_format( $clicks, 0, '', '' );
|
||||
|
||||
$shorturl = yourls_link( $keyword );
|
||||
$statlink = yourls_statlink( $keyword );
|
||||
if( yourls_is_ssl() )
|
||||
$statlink = str_replace( 'http://', 'https://', $statlink );
|
||||
|
||||
if( $title ) {
|
||||
$display_link = "<a href=\"$url\" title=\"$title\">$display_title</a><br/><small><a href=\"$url\" title=\"$title_url\">$display_url</a></small>";
|
||||
} else {
|
||||
$display_link = "<a href=\"$url\" title=\"$title_url\">$display_url</a>";
|
||||
}
|
||||
|
||||
$delete_link = yourls_nonce_url( 'delete-link_'.$id,
|
||||
yourls_add_query_arg( array( 'id' => $id, 'action' => 'delete', 'keyword' => $keyword ), yourls_admin_url( 'admin-ajax.php' ) )
|
||||
);
|
||||
|
||||
$edit_link = yourls_nonce_url( 'edit-link_'.$id,
|
||||
yourls_add_query_arg( array( 'id' => $id, 'action' => 'edit', 'keyword' => $keyword ), yourls_admin_url( 'admin-ajax.php' ) )
|
||||
);
|
||||
|
||||
// Action button links
|
||||
$actions = array(
|
||||
'stats' => array(
|
||||
'href' => $statlink,
|
||||
'id' => "statlink-$id",
|
||||
'title' => 'Stats',
|
||||
'anchor' => 'Stats',
|
||||
),
|
||||
'share' => array(
|
||||
'href' => '',
|
||||
'id' => "share-button-$id",
|
||||
'title' => 'Share',
|
||||
'anchor' => 'Share',
|
||||
'onclick' => "toggle_share('$id');return false;",
|
||||
),
|
||||
'edit' => array(
|
||||
'href' => $edit_link,
|
||||
'id' => "edit-button-$id",
|
||||
'title' => 'Edit',
|
||||
'anchor' => 'Edit',
|
||||
'onclick' => "edit('$id');return false;",
|
||||
),
|
||||
'delete' => array(
|
||||
'href' => $delete_link,
|
||||
'id' => "delete-button-$id",
|
||||
'title' => 'Delete',
|
||||
'anchor' => 'Delete',
|
||||
'onclick' => "remove('$id');return false;",
|
||||
)
|
||||
);
|
||||
$actions = yourls_apply_filter( 'table_add_row_action_array', $actions );
|
||||
$action_links = '';
|
||||
foreach( $actions as $key => $action ) {
|
||||
$onclick = isset( $action['onclick'] ) ? 'onclick="' . $action['onclick'] . '"' : '' ;
|
||||
$action_links .= sprintf( '<a href="%s" id="%s" title="%s" class="%s" %s>%s</a>',
|
||||
$action['href'], $action['id'], $action['title'], 'button button_'.$key, $onclick, $action['anchor']
|
||||
);
|
||||
}
|
||||
$action_links = yourls_apply_filter( 'action_links', $action_links, $keyword, $url, $ip, $clicks, $timestamp );
|
||||
|
||||
$row = <<<ROW
|
||||
<tr id="id-$id"><td id="keyword-$id" class="keyword"><a href="$shorturl">$display_keyword</a></td><td id="url-$id" class="url">$display_link</td><td id="timestamp-$id" class="timestamp">$date</td><td id="ip-$id" class="ip">$ip</td><td id="clicks-$id" class="clicks">$clicks</td><td class="actions" id="actions-$id">$action_links<input type="hidden" id="keyword_$id" value="$keyword"/></td></tr>
|
||||
ROW;
|
||||
$row = yourls_apply_filter( 'table_add_row', $row, $keyword, $url, $title, $ip, $clicks, $timestamp );
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
// Echo the main table head
|
||||
function yourls_table_head() {
|
||||
$start = '<table id="main_table" class="tblSorter" cellpadding="0" cellspacing="1"><thead><tr>'."\n";
|
||||
echo yourls_apply_filter( 'table_head_start', $start );
|
||||
|
||||
$cells = yourls_apply_filter( 'table_head_cells', array(
|
||||
'shorturl' => 'Short URL ',
|
||||
'longurl' => 'Original URL',
|
||||
'date' => 'Date',
|
||||
'ip' => 'IP',
|
||||
'clicks' => 'Clicks ',
|
||||
'actions' => 'Actions'
|
||||
) );
|
||||
foreach( $cells as $k => $v ) {
|
||||
echo "<th id='main_table_head_$k'>$v</th>\n";
|
||||
}
|
||||
|
||||
$end = "</tr></thead>\n";
|
||||
echo yourls_apply_filter( 'table_head_end', $end );
|
||||
}
|
||||
|
||||
// Echo the tbody start tag
|
||||
function yourls_table_tbody_start() {
|
||||
echo yourls_apply_filter( 'table_tbody_start', '<tbody>' );
|
||||
}
|
||||
|
||||
// Echo the tbody end tag
|
||||
function yourls_table_tbody_end() {
|
||||
echo yourls_apply_filter( 'table_tbody_end', '</tbody>' );
|
||||
}
|
||||
|
||||
// Echo the table start tag
|
||||
function yourls_table_end() {
|
||||
echo yourls_apply_filter( 'table_end', '</table>' );
|
||||
}
|
||||
|
||||
// Echo HTML tag for a link
|
||||
function yourls_html_link( $href, $title = '', $element = '' ) {
|
||||
if( !$title )
|
||||
$title = $href;
|
||||
if( $element )
|
||||
$element = "id='$element'";
|
||||
echo yourls_apply_filter( 'html_link', "<a href='$href' $element>$title</a>" );
|
||||
}
|
||||
|
||||
// Display the login screen. Nothing past this point.
|
||||
function yourls_login_screen( $error_msg = '' ) {
|
||||
yourls_html_head( 'login' );
|
||||
|
||||
$action = ( isset($_GET['action']) && $_GET['action'] == 'logout' ? '?' : '' );
|
||||
|
||||
yourls_html_logo();
|
||||
?>
|
||||
<div id="login">
|
||||
<form method="post" action="<?php echo $action; ?>"> <?php // reset any QUERY parameters ?>
|
||||
<?php
|
||||
if(!empty($error_msg)) {
|
||||
echo '<p class="error">'.$error_msg.'</p>';
|
||||
}
|
||||
?>
|
||||
<p>
|
||||
<label for="username">Username</label><br />
|
||||
<input type="text" id="username" name="username" size="30" class="text" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">Password</label><br />
|
||||
<input type="password" id="password" name="password" size="30" class="text" />
|
||||
</p>
|
||||
<p style="text-align: right;">
|
||||
<input type="submit" id="submit" name="submit" value="Login" class="button" />
|
||||
</p>
|
||||
</form>
|
||||
<script type="text/javascript">$('#username').focus();</script>
|
||||
</div>
|
||||
<?php
|
||||
yourls_html_footer();
|
||||
die();
|
||||
}
|
||||
|
||||
// Display the admin menu
|
||||
function yourls_html_menu() {
|
||||
|
||||
// Build menu links
|
||||
if( defined( 'YOURLS_USER' ) ) {
|
||||
$logout_link = yourls_apply_filter( 'logout_link', 'Hello <strong>' . YOURLS_USER . '</strong> (<a href="?action=logout" title="Logout">Logout</a>)' );
|
||||
} else {
|
||||
$logout_link = yourls_apply_filter( 'logout_link', '' );
|
||||
}
|
||||
$help_link = yourls_apply_filter( 'help_link', '<a href="' . yourls_site_url( false ) .'/readme.html">Help</a>' );
|
||||
|
||||
$admin_links = array();
|
||||
$admin_sublinks = array();
|
||||
|
||||
$admin_links['admin'] = array(
|
||||
'url' => yourls_admin_url('index.php'),
|
||||
'title' => 'Go to the admin interface',
|
||||
'anchor' => 'Admin interface'
|
||||
);
|
||||
|
||||
if( yourls_is_admin() ) {
|
||||
$admin_links['tools'] = array(
|
||||
'url' => yourls_admin_url('tools.php'),
|
||||
'anchor' => 'Tools',
|
||||
);
|
||||
$admin_links['plugins'] = array(
|
||||
'url' => yourls_admin_url('plugins.php'),
|
||||
'anchor' => 'Manage Plugins',
|
||||
);
|
||||
$admin_sublinks['plugins'] = yourls_list_plugin_admin_pages();
|
||||
}
|
||||
|
||||
$admin_links = yourls_apply_filter( 'admin_links', $admin_links );
|
||||
$admin_sublinks = yourls_apply_filter( 'admin_sublinks', $admin_sublinks );
|
||||
|
||||
// Now output menu
|
||||
echo '<ul id="admin_menu">'."\n";
|
||||
if ( yourls_is_private() && isset( $logout_link ) )
|
||||
echo '<li id="admin_menu_logout_link">' . $logout_link .'</li>';
|
||||
|
||||
foreach( (array)$admin_links as $link => $ar ) {
|
||||
if( isset( $ar['url'] ) ) {
|
||||
$anchor = isset( $ar['anchor'] ) ? $ar['anchor'] : $link;
|
||||
$title = isset( $ar['title'] ) ? 'title="' . $ar['title'] . '"' : '';
|
||||
printf( '<li id="admin_menu_%s_link" class="admin_menu_toplevel"><a href="%s" %s>%s</a>', $link, $ar['url'], $title, $anchor );
|
||||
}
|
||||
// Output submenu if any. TODO: clean up, too many code duplicated here
|
||||
if( isset( $admin_sublinks[$link] ) ) {
|
||||
echo "<ul>\n";
|
||||
foreach( $admin_sublinks[$link] as $link => $ar ) {
|
||||
if( isset( $ar['url'] ) ) {
|
||||
$anchor = isset( $ar['anchor'] ) ? $ar['anchor'] : $link;
|
||||
$title = isset( $ar['title'] ) ? 'title="' . $ar['title'] . '"' : '';
|
||||
printf( '<li id="admin_menu_%s_link" class="admin_menu_sublevel admin_menu_sublevel_%s"><a href="%s" %s>%s</a>', $link, $link, $ar['url'], $title, $anchor );
|
||||
}
|
||||
}
|
||||
echo "</ul>\n";
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $help_link ) )
|
||||
echo '<li id="admin_menu_help_link">' . $help_link .'</li>';
|
||||
|
||||
yourls_do_action( 'admin_menu' );
|
||||
echo "</ul>\n";
|
||||
yourls_do_action( 'admin_notices' );
|
||||
yourls_do_action( 'admin_notice' ); // because I never remember if it's 'notices' or 'notice'
|
||||
/*
|
||||
To display a notice:
|
||||
$message = "<div>OMG, dude, I mean!</div>" );
|
||||
yourls_add_action( 'admin_notices', create_function( '', "echo '$message';" ) );
|
||||
*/
|
||||
}
|
||||
|
||||
// Wrapper to admin notices
|
||||
function yourls_add_notice( $message ) {
|
||||
$message = yourls_notice_box( $message );
|
||||
yourls_add_action( 'admin_notices', create_function( '', "echo '$message';" ) );
|
||||
}
|
||||
|
||||
// Return a formatted notice
|
||||
function yourls_notice_box( $message ) {
|
||||
return <<<HTML
|
||||
<div class="notice">
|
||||
<p>$message</p>
|
||||
</div>
|
||||
HTML;
|
||||
}
|
||||
|
||||
// Display a page
|
||||
function yourls_page( $page ) {
|
||||
$include = YOURLS_ABSPATH . "/pages/$page.php";
|
||||
if( !file_exists($include) ) {
|
||||
yourls_die( "Page '$page' not found", 'Not found', 404 );
|
||||
}
|
||||
yourls_do_action( 'pre_page', $page );
|
||||
include($include);
|
||||
yourls_do_action( 'post_page', $page );
|
||||
die();
|
||||
}
|
||||
|
171
includes/functions-http.php
Normal file
@ -0,0 +1,171 @@
|
||||
<?php
|
||||
// TODO: improve this.
|
||||
// yourls_get_http_transport: use static vars
|
||||
// yourls_get_remote_content: return array( content, status, code )
|
||||
|
||||
// Determine best transport for GET request.
|
||||
// Order of preference: curl, fopen, fsockopen.
|
||||
// Return 'curl', 'fopen', 'fsockopen' or false if nothing works
|
||||
function yourls_get_http_transport( $url ) {
|
||||
|
||||
$transports = array();
|
||||
|
||||
$scheme = parse_url( $url, PHP_URL_SCHEME );
|
||||
$is_ssl = ( $scheme == 'https' || $scheme == 'ssl' );
|
||||
|
||||
// Test transports by order of preference, best first
|
||||
|
||||
// curl
|
||||
if( function_exists('curl_init') && function_exists('curl_exec') )
|
||||
$transports[]= 'curl';
|
||||
|
||||
// fopen. Doesn't work with https?
|
||||
if( !$is_ssl && function_exists('fopen') && ini_get('allow_url_fopen') )
|
||||
$transports[]= 'fopen';
|
||||
|
||||
// fsock
|
||||
if( function_exists( 'fsockopen' ) )
|
||||
$transports[]= 'fsockopen';
|
||||
|
||||
$best = ( $transports ? array_shift( $transports ) : false );
|
||||
|
||||
return yourls_apply_filter( 'get_http_transport', $best, $transports );
|
||||
}
|
||||
|
||||
// Get remote content via a GET request using best transport available
|
||||
// Returns $content (might be an error message) or false if no transport available
|
||||
function yourls_get_remote_content( $url, $maxlen = 4096, $timeout = 5 ) {
|
||||
$url = yourls_sanitize_url( $url );
|
||||
|
||||
$transport = yourls_get_http_transport( $url );
|
||||
if( $transport ) {
|
||||
$content = call_user_func( 'yourls_get_remote_content_'.$transport, $url, $maxlen, $timeout );
|
||||
} else {
|
||||
$content = false;
|
||||
}
|
||||
|
||||
return yourls_apply_filter( 'get_remote_content', $content, $url, $maxlen, $timeout );
|
||||
}
|
||||
|
||||
// Get remote content using curl. Needs sanitized $url. Returns $content or false
|
||||
function yourls_get_remote_content_curl( $url, $maxlen = 4096, $timeout = 5 ) {
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt( $ch, CURLOPT_URL, $url );
|
||||
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
|
||||
curl_setopt( $ch, CURLOPT_TIMEOUT, $timeout );
|
||||
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 );
|
||||
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 ); // follow redirects...
|
||||
curl_setopt( $ch, CURLOPT_MAXREDIRS, 3 ); // ... but not more than 3
|
||||
curl_setopt( $ch, CURLOPT_USERAGENT, yourls_http_user_agent() );
|
||||
curl_setopt( $ch, CURLOPT_RANGE, "0-{$maxlen}" ); // Get no more than $maxlen
|
||||
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 ); // dont check SSL certificates
|
||||
curl_setopt( $ch, CURLOPT_HEADER, 0 );
|
||||
|
||||
$response = curl_exec( $ch );
|
||||
|
||||
if( !$response || curl_error( $ch ) ) {
|
||||
//$response = 'Error: '.curl_error( $ch );
|
||||
return false;
|
||||
}
|
||||
|
||||
curl_close( $ch );
|
||||
|
||||
return substr( $response, 0, $maxlen ); // substr in case CURLOPT_RANGE not supported
|
||||
}
|
||||
|
||||
// Get remote content using fopen. Needs sanitized $url. Returns $content or false
|
||||
function yourls_get_remote_content_fopen( $url, $maxlen = 4096, $timeout = 5 ) {
|
||||
$content = false;
|
||||
|
||||
$initial_timeout = @ini_set( 'default_socket_timeout', $timeout );
|
||||
$initial_user_agent = @ini_set( 'user_agent', yourls_http_user_agent() );
|
||||
|
||||
// Basic error reporting shortcut
|
||||
set_error_handler( create_function('$code, $string', 'global $ydb; $ydb->fopen_error = $string;') );
|
||||
|
||||
$fp = fopen( $url, 'r');
|
||||
if( $fp !== false ) {
|
||||
$buffer = min( $maxlen, 4096 );
|
||||
while ( !feof( $fp ) && !( strlen( $content ) >= $maxlen ) ) {
|
||||
$content .= fread( $fp, $buffer );
|
||||
}
|
||||
fclose( $fp );
|
||||
}
|
||||
|
||||
if( $initial_timeout !== false )
|
||||
@ini_set('default_socket_timeout', $initial_timeout);
|
||||
if( $initial_user_agent !== false )
|
||||
@ini_set('user_agent', $initial_user_agent);
|
||||
|
||||
|
||||
restore_error_handler();
|
||||
|
||||
if( !$content ) {
|
||||
//global $ydb;
|
||||
//$content = 'Error: '.strip_tags( $ydb->fopen_error );
|
||||
return false;
|
||||
}
|
||||
|
||||
return $content;
|
||||
}
|
||||
|
||||
// Get remote content using fsockopen. Needs sanitized $url. Returns $content or false
|
||||
function yourls_get_remote_content_fsockopen( $url, $maxlen = 4096, $timeout = 5 ) {
|
||||
// get the host name and url path
|
||||
$parsed_url = parse_url($url);
|
||||
|
||||
$host = $parsed_url['host'];
|
||||
if ( isset($parsed_url['path']) ) {
|
||||
$path = $parsed_url['path'];
|
||||
} else {
|
||||
$path = '/'; // the url is pointing to the host like http://www.mysite.com
|
||||
}
|
||||
|
||||
if (isset($parsed_url['query'])) {
|
||||
$path .= '?' . $parsed_url['query'];
|
||||
}
|
||||
|
||||
if (isset($parsed_url['port'])) {
|
||||
$port = $parsed_url['port'];
|
||||
} else {
|
||||
$port = '80';
|
||||
}
|
||||
|
||||
$response = false;
|
||||
|
||||
// connect to the remote server
|
||||
$fp = @fsockopen( $host, $port, $errno, $errstr, $timeout );
|
||||
var_dump( $errno, $errstr );
|
||||
if( $fp !== false ) {
|
||||
// send some fake headers to mimick a standard browser
|
||||
fputs($fp, "GET $path HTTP/1.0\r\n" .
|
||||
"Host: $host\r\n" .
|
||||
"User-Agent: " . yourls_http_user_agent() . "\r\n" .
|
||||
"Accept: */*\r\n" .
|
||||
"Accept-Language: en-us,en;q=0.5\r\n" .
|
||||
"Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\n" .
|
||||
"Keep-Alive: 300\r\n" .
|
||||
"Connection: keep-alive\r\n" .
|
||||
"Referer: http://$host\r\n\r\n");
|
||||
|
||||
// retrieve the response from the remote server
|
||||
$buffer = min( $maxlen, 4096 );
|
||||
while ( !feof( $fp ) && !( strlen( $response ) >= $maxlen ) ) { // get more or less $maxlen bytes (between $maxlen and ($maxlen + ($maxlen-1)) actually)
|
||||
$response .= fread( $fp, $buffer );
|
||||
}
|
||||
|
||||
fclose( $fp );
|
||||
} else {
|
||||
//$response = trim( "Error: #$errno. $errstr" );
|
||||
return false;
|
||||
}
|
||||
|
||||
// return the file content
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Return funky user agent string
|
||||
function yourls_http_user_agent() {
|
||||
return yourls_apply_filter( 'http_user_agent', 'YOURLS v'.YOURLS_VERSION.' +http://yourls.org/ (running on '.YOURLS_SITE.')' );
|
||||
}
|
282
includes/functions-infos.php
Normal file
@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
// Echoes an image tag of Google Charts map from sorted array of 'country_code' => 'number of visits' (sort by DESC)
|
||||
function yourls_stats_countries_map( $countries ) {
|
||||
yourls_do_action( 'stats_countries_map' );
|
||||
|
||||
// Echo static map. Will be hidden if JS
|
||||
$map = array(
|
||||
'cht' => 't',
|
||||
'chs' => '440x220',
|
||||
'chtm'=> 'world',
|
||||
'chco'=> 'FFFFFF,88C0EB,2A85B3,1F669C',
|
||||
'chld'=> join('' , array_keys( $countries ) ),
|
||||
'chd' => 't:'. join(',' , $countries ),
|
||||
'chf' => 'bg,s,EAF7FE'
|
||||
);
|
||||
$map_src = 'http://chart.apis.google.com/chart?' . http_build_query( $map );
|
||||
//$map_src = yourls_match_current_protocol( $map_src, 'http://chart.apis.', 'https://www.' );
|
||||
|
||||
$static = "<img id='yourls_stat_countries_static' class='hide-if-js' src='$map_src' width='440' height='220' border='0' />";
|
||||
echo yourls_apply_filter( 'stats_countries_static', $static, $countries );
|
||||
|
||||
// Echo dynamic map. Will be hidden if no JS
|
||||
$jsapi = yourls_match_current_protocol( 'http://www.google.com/jsapi' );
|
||||
$dynamic = <<<MAP
|
||||
<script type='text/javascript' src='$jsapi'></script>
|
||||
<script type='text/javascript'>
|
||||
google.load('visualization', '1', {'packages': ['geomap']});
|
||||
google.setOnLoadCallback(drawMap);
|
||||
function drawMap() {
|
||||
var data = new google.visualization.DataTable();
|
||||
MAP;
|
||||
$dynamic .= '
|
||||
data.addRows('.count( $countries ).');
|
||||
';
|
||||
$dynamic .= "
|
||||
data.addColumn('string', 'Country');
|
||||
data.addColumn('number', 'Hits');
|
||||
";
|
||||
$i = 0;
|
||||
foreach( $countries as $c => $v ) {
|
||||
$dynamic .= "
|
||||
data.setValue($i, 0, '$c');
|
||||
data.setValue($i, 1, $v);
|
||||
";
|
||||
$i++;
|
||||
}
|
||||
|
||||
$dynamic .= <<<MAP
|
||||
var options = {};
|
||||
options['dataMode'] = 'regions';
|
||||
options['width'] = '550px';
|
||||
options['height'] = '340px';
|
||||
options['colors'] = [0x88C0EB,0x2A85B3,0x1F669C];
|
||||
var container = document.getElementById('yourls_stat_countries');
|
||||
var geomap = new google.visualization.GeoMap(container);
|
||||
geomap.draw(data, options);
|
||||
};
|
||||
</script>
|
||||
<div id="yourls_stat_countries"></div>
|
||||
MAP;
|
||||
|
||||
echo yourls_apply_filter( 'stats_countries_dynamic', $dynamic, $countries );
|
||||
}
|
||||
|
||||
// Echoes an image tag of Google Charts pie from sorted array of 'data' => 'value' (sort by DESC). Optional $limit = (integer) limit list of X first countries, sorted by most visits
|
||||
function yourls_stats_pie( $data, $limit = 10, $size = '340x220', $colors = 'C7E7FF,1F669C' ) {
|
||||
yourls_do_action( 'stats_pie' );
|
||||
|
||||
// Trim array: $limit first item + the sum of all others
|
||||
if ( count( $data ) > $limit ) {
|
||||
$i= 0;
|
||||
$trim_data = array('Others' => 0);
|
||||
foreach( $data as $item=>$value ) {
|
||||
$i++;
|
||||
if( $i <= $limit ) {
|
||||
$trim_data[$item] = $value;
|
||||
} else {
|
||||
$trim_data['Others'] += $value;
|
||||
}
|
||||
}
|
||||
$data = $trim_data;
|
||||
}
|
||||
|
||||
// Scale items
|
||||
$_data = yourls_scale_data( $data );
|
||||
|
||||
// Hmmm, pie
|
||||
$pie = array(
|
||||
'cht' => 'p',
|
||||
'chs' => $size,
|
||||
'chd' => 't:'.( join(',' , $_data ) ),
|
||||
'chco'=> $colors,
|
||||
'chl' => join('|' , array_keys( $data ) )
|
||||
);
|
||||
$pie_src = 'http://chart.apis.google.com/chart?' . http_build_query( $pie );
|
||||
//$pie_src = yourls_match_current_protocol( $pie_src, 'http://chart.apis.', 'https://www.' );
|
||||
list( $size_x, $size_y ) = explode( 'x', $size );
|
||||
|
||||
$pie = "<img src='$pie_src' width='$size_x' height='$size_y' border='0' />";
|
||||
echo yourls_apply_filter( 'stats_pie', $pie, $data, $limit, $size, $colors );
|
||||
}
|
||||
|
||||
// Build a list of all daily values between d1/m1/y1 to d2/m2/y2.
|
||||
function yourls_build_list_of_days( $dates ) {
|
||||
/* Say we have an array like:
|
||||
$dates = array (
|
||||
2009 => array (
|
||||
'08' => array (
|
||||
29 => 15,
|
||||
30 => 5,
|
||||
),
|
||||
'09' => array (
|
||||
'02' => 3,
|
||||
'03' => 5,
|
||||
'04' => 2,
|
||||
'05' => 99,
|
||||
),
|
||||
),
|
||||
)
|
||||
*/
|
||||
|
||||
if( !$dates )
|
||||
return array();
|
||||
|
||||
// Get first & last years from our range. In our example: 2009 & 2009
|
||||
$first_year = key( $dates );
|
||||
$last_year = end( array_keys($dates) );
|
||||
reset( $dates );
|
||||
|
||||
// Get first & last months from our range. In our example: 08 & 09
|
||||
$first_month = key( $dates[$first_year] );
|
||||
$last_month = end( array_keys($dates[$last_year]) );
|
||||
reset( $dates );
|
||||
|
||||
// Get first & last days from our range. In our example: 29 & 05
|
||||
$first_day = key( $dates[$first_year][$first_month] );
|
||||
$last_day = end( array_keys($dates[$last_year][$last_month]) );
|
||||
|
||||
// Now build a list of all years (2009), month (08 & 09) and days (all from 2009-08-29 to 2009-09-05)
|
||||
$list_of_years = array();
|
||||
$list_of_months = array();
|
||||
$list_of_days = array();
|
||||
for ( $year = $first_year; $year <= $last_year; $year++ ) {
|
||||
$_year = sprintf('%04d', $year);
|
||||
$list_of_years[$_year] = $_year;
|
||||
$current_first_month = ( $year == $first_year ? $first_month : '01' );
|
||||
$current_last_month = ( $year == $last_year ? $last_month : '12' );
|
||||
for ( $month = $current_first_month; $month <= $current_last_month; $month++ ) {
|
||||
$_month = sprintf('%02d', $month);
|
||||
$list_of_months[$_month] = $_month;
|
||||
$current_first_day = ( $year == $first_year && $month == $first_month ? $first_day : '01' );
|
||||
$current_last_day = ( $year == $last_year && $month == $last_month ? $last_day : yourls_days_in_month($month, $year) );
|
||||
for ( $day = $current_first_day; $day <= $current_last_day; $day++ ) {
|
||||
$day = sprintf('%02d', $day);
|
||||
$list_of_days["$_year-$_month-$day"] = isset( $dates[$_year][$_month][$day] ) ? $dates[$_year][$_month][$day] : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'list_of_days' => $list_of_days,
|
||||
'list_of_months' => $list_of_months,
|
||||
'list_of_years' => $list_of_years,
|
||||
);
|
||||
}
|
||||
|
||||
// Echoes an image tag of Google Charts line graph from array of values (eg 'number of clicks'). $legend1_list & legend2_list are values used for the 2 x-axis labels
|
||||
function yourls_stats_line( $values, $legend1_list, $legend2_list ) {
|
||||
yourls_do_action( 'stats_line' );
|
||||
|
||||
// If we have only 1 day of data, prepend a fake day with 0 hits for a prettier graph
|
||||
if ( count( $values ) == 1 )
|
||||
array_unshift( $values, 0 );
|
||||
|
||||
$values = yourls_array_granularity( $values, 30 );
|
||||
|
||||
// If x-axis labels have only 1 value, double it for a nicer graph
|
||||
if( count( $legend1_list ) == 1 )
|
||||
$legend1_list[] = current( $legend1_list );
|
||||
if( count( $legend2_list ) == 1 )
|
||||
$legend2_list[] = current( $legend2_list );
|
||||
|
||||
// Make the chart
|
||||
$legend1 = join('|', $legend1_list );
|
||||
$legend2 = join('|', $legend2_list );
|
||||
$max = max( $values );
|
||||
if ( $max >= 4 ) {
|
||||
$label_clicks = '0|'.intval( $max / 4 ).'|'.intval( $max / 2 ).'|'.intval( $max / 1.5 ).'|'.$max;
|
||||
} else {
|
||||
$label_clicks = array();
|
||||
for ($i = 0; $i <= $max; $i++) {
|
||||
$label_clicks[] = $i;
|
||||
}
|
||||
$label_clicks = join( '|', $label_clicks );
|
||||
}
|
||||
$line = array(
|
||||
'cht' => 'lc',
|
||||
'chs' => '440x220',
|
||||
'chxt'=> 'x,x,y',
|
||||
'chd' => 't:'.( join(',' , $values ) ),
|
||||
'chds' => '0,'.$max,
|
||||
'chm' => 'B,E3F3FF,0,0,0|o,2a85b3,0,-1,6|o,FFFFFF,0,-1,4',
|
||||
'chco' => '2a85b3',
|
||||
'chxl'=> '0:|'. $legend1 .'|1:|'. $legend2 .'|2:|'. $label_clicks
|
||||
);
|
||||
$line_src = 'http://chart.apis.google.com/chart?' . http_build_query( $line );
|
||||
//$line_src = yourls_match_current_protocol( $line_src, 'http://chart.apis.', 'https://www.' );
|
||||
|
||||
echo yourls_apply_filter( 'stats_line', "<img src='$line_src' />", $values, $legend1_list, $legend2_list );
|
||||
}
|
||||
|
||||
// Return the number of days in a month. From php.net, used if PHP built without calendar functions
|
||||
function yourls_days_in_month($month, $year) {
|
||||
// calculate number of days in a month
|
||||
return $month == 2 ? ($year % 4 ? 28 : ($year % 100 ? 29 : ($year % 400 ? 28 : 29))) : (($month - 1) % 7 % 2 ? 30 : 31);
|
||||
}
|
||||
|
||||
// Get max value from date array of 'year-month-day' = 'hits'
|
||||
function yourls_stats_get_best_day( $list_of_days ) {
|
||||
$max = 0; $day = 0;
|
||||
$max = max( $list_of_days );
|
||||
foreach( $list_of_days as $k=>$v ) {
|
||||
if ( $v == $max )
|
||||
return array( 'day' => $k, 'max' => $max );
|
||||
}
|
||||
}
|
||||
|
||||
// Return domain of a URL
|
||||
function yourls_get_domain( $url, $include_scheme = false ) {
|
||||
$parse = @parse_url( $url ); // Hiding ugly stuff coming from malformed referrer URLs
|
||||
|
||||
// Get host & scheme. Fall back to path if not found.
|
||||
$host = isset( $parse['host'] ) ? $parse['host'] : '';
|
||||
$scheme = isset( $parse['scheme'] ) ? $parse['scheme'] : '';
|
||||
$path = isset( $parse['path'] ) ? $parse['path'] : '';
|
||||
if( !$host )
|
||||
$host = $path;
|
||||
|
||||
if ( $include_scheme && $scheme )
|
||||
$host = $scheme.'://'.$host;
|
||||
|
||||
return $host;
|
||||
}
|
||||
|
||||
// Return favicon URL
|
||||
function yourls_get_favicon_url( $url ) {
|
||||
return yourls_match_current_protocol( 'http://www.google.com/s2/u/0/favicons?domain=' . yourls_get_domain( $url, false ) );
|
||||
}
|
||||
|
||||
// Scale array of data from 0 to 100 max
|
||||
function yourls_scale_data( $data ) {
|
||||
$max = max( $data );
|
||||
if( $max > 100 ) {
|
||||
foreach( $data as $k=>$v ) {
|
||||
$data[$k] = intval( $v / $max * 100 );
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
// Tweak granularity of array $array: keep only $grain values. This make less accurate but less messy graphs when too much values. See http://code.google.com/apis/chart/formats.html#granularity
|
||||
function yourls_array_granularity( $array, $grain = 100, $preserve_max = true ) {
|
||||
if ( count( $array ) > $grain ) {
|
||||
$max = max( $array );
|
||||
$step = intval( count( $array ) / $grain );
|
||||
$i = 0;
|
||||
// Loop through each item and unset except every $step (optional preserve the max value)
|
||||
foreach( $array as $k=>$v ) {
|
||||
$i++;
|
||||
if ( $i % $step != 0 ) {
|
||||
if ( $preserve_max == false ) {
|
||||
unset( $array[$k] );
|
||||
} else {
|
||||
if ( $v < $max )
|
||||
unset( $array[$k] );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $array;
|
||||
}
|
199
includes/functions-install.php
Normal file
@ -0,0 +1,199 @@
|
||||
<?php
|
||||
|
||||
// Check if mod_rewrite is enabled. Note: unused, not reliable enough.
|
||||
function yourls_check_mod_rewrite() {
|
||||
return yourls_apache_mod_loaded('mod_rewrite');
|
||||
}
|
||||
|
||||
// Check if extension cURL is enabled
|
||||
function yourls_check_curl() {
|
||||
return function_exists('curl_init');
|
||||
}
|
||||
|
||||
// Check if server has MySQL 4.1+
|
||||
function yourls_check_database_version() {
|
||||
global $ydb;
|
||||
return ( version_compare( '4.1', $ydb->mysql_version() ) <= 0 );
|
||||
}
|
||||
|
||||
// Check if PHP > 4.3
|
||||
function yourls_check_php_version() {
|
||||
return ( version_compare( '4.3', phpversion() ) <= 0 );
|
||||
}
|
||||
|
||||
// Check if server is an Apache
|
||||
function yourls_is_apache() {
|
||||
return (
|
||||
strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false
|
||||
|| strpos($_SERVER['SERVER_SOFTWARE'], 'LiteSpeed') !== false
|
||||
);
|
||||
}
|
||||
|
||||
// Check if module exists in Apache config. Input string eg 'mod_rewrite', return true or $default. Stolen from WordPress
|
||||
function yourls_apache_mod_loaded($mod, $default = false) {
|
||||
if ( !yourls_is_apache() )
|
||||
return false;
|
||||
|
||||
if ( function_exists('apache_get_modules') ) {
|
||||
$mods = apache_get_modules();
|
||||
if ( in_array($mod, $mods) )
|
||||
return true;
|
||||
} elseif ( function_exists('phpinfo') ) {
|
||||
ob_start();
|
||||
phpinfo(8);
|
||||
$phpinfo = ob_get_clean();
|
||||
if ( false !== strpos($phpinfo, $mod) )
|
||||
return true;
|
||||
}
|
||||
return $default;
|
||||
}
|
||||
|
||||
// Create .htaccess. Returns boolean
|
||||
function yourls_create_htaccess() {
|
||||
$host = parse_url( YOURLS_SITE );
|
||||
$path = ( isset( $host['path'] ) ? $host['path'] : '' );
|
||||
|
||||
$content = array(
|
||||
'<IfModule mod_rewrite.c>',
|
||||
'RewriteEngine On',
|
||||
'RewriteBase '.$path.'/',
|
||||
'RewriteCond %{REQUEST_FILENAME} !-f',
|
||||
'RewriteCond %{REQUEST_FILENAME} !-d',
|
||||
'RewriteRule ^(.*)$ '.$path.'/yourls-loader.php [L]',
|
||||
'</IfModule>',
|
||||
);
|
||||
|
||||
$filename = YOURLS_ABSPATH.'/.htaccess';
|
||||
|
||||
return ( yourls_insert_with_markers( $filename, 'YOURLS', $content ) );
|
||||
}
|
||||
|
||||
// Inserts $insertion (text in an array of lines) into $filename (.htaccess) between BEGIN/END $marker block. Returns bool. Stolen from WP
|
||||
function yourls_insert_with_markers( $filename, $marker, $insertion ) {
|
||||
if (!file_exists( $filename ) || is_writeable( $filename ) ) {
|
||||
if (!file_exists( $filename ) ) {
|
||||
$markerdata = '';
|
||||
} else {
|
||||
$markerdata = explode( "\n", implode( '', file( $filename ) ) );
|
||||
}
|
||||
|
||||
if ( !$f = @fopen( $filename, 'w' ) )
|
||||
return false;
|
||||
|
||||
$foundit = false;
|
||||
if ( $markerdata ) {
|
||||
$state = true;
|
||||
foreach ( $markerdata as $n => $markerline ) {
|
||||
if (strpos($markerline, '# BEGIN ' . $marker) !== false)
|
||||
$state = false;
|
||||
if ( $state ) {
|
||||
if ( $n + 1 < count( $markerdata ) )
|
||||
fwrite( $f, "{$markerline}\n" );
|
||||
else
|
||||
fwrite( $f, "{$markerline}" );
|
||||
}
|
||||
if (strpos($markerline, '# END ' . $marker) !== false) {
|
||||
fwrite( $f, "# BEGIN {$marker}\n" );
|
||||
if ( is_array( $insertion ))
|
||||
foreach ( $insertion as $insertline )
|
||||
fwrite( $f, "{$insertline}\n" );
|
||||
fwrite( $f, "# END {$marker}\n" );
|
||||
$state = true;
|
||||
$foundit = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!$foundit) {
|
||||
fwrite( $f, "\n\n# BEGIN {$marker}\n" );
|
||||
foreach ( $insertion as $insertline )
|
||||
fwrite( $f, "{$insertline}\n" );
|
||||
fwrite( $f, "# END {$marker}\n\n" );
|
||||
}
|
||||
fclose( $f );
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create MySQL tables. Return array( 'success' => array of success strings, 'errors' => array of error strings )
|
||||
function yourls_create_sql_tables() {
|
||||
global $ydb;
|
||||
|
||||
$error_msg = array();
|
||||
$success_msg = array();
|
||||
|
||||
// Create Table Query
|
||||
$create_tables = array();
|
||||
$create_tables[YOURLS_DB_TABLE_URL] =
|
||||
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_URL.'` ('.
|
||||
'`keyword` varchar(200) BINARY NOT NULL,'.
|
||||
'`url` text BINARY NOT NULL,'.
|
||||
'`title` text CHARACTER SET utf8,'.
|
||||
'`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,'.
|
||||
'`ip` VARCHAR(41) NOT NULL,'.
|
||||
'`clicks` INT(10) UNSIGNED NOT NULL,'.
|
||||
' PRIMARY KEY (`keyword`),'.
|
||||
' KEY `timestamp` (`timestamp`),'.
|
||||
' KEY `ip` (`ip`)'.
|
||||
');';
|
||||
|
||||
$create_tables[YOURLS_DB_TABLE_OPTIONS] =
|
||||
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('.
|
||||
'`option_id` bigint(20) unsigned NOT NULL auto_increment,'.
|
||||
'`option_name` varchar(64) NOT NULL default "",'.
|
||||
'`option_value` longtext NOT NULL,'.
|
||||
'PRIMARY KEY (`option_id`,`option_name`),'.
|
||||
'KEY `option_name` (`option_name`)'.
|
||||
') AUTO_INCREMENT=1 ;';
|
||||
|
||||
$create_tables[YOURLS_DB_TABLE_LOG] =
|
||||
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('.
|
||||
'`click_id` int(11) NOT NULL auto_increment,'.
|
||||
'`click_time` datetime NOT NULL,'.
|
||||
'`shorturl` varchar(200) BINARY NOT NULL,'.
|
||||
'`referrer` varchar(200) NOT NULL,'.
|
||||
'`user_agent` varchar(255) NOT NULL,'.
|
||||
'`ip_address` varchar(41) NOT NULL,'.
|
||||
'`country_code` char(2) NOT NULL,'.
|
||||
'PRIMARY KEY (`click_id`),'.
|
||||
'KEY `shorturl` (`shorturl`)'.
|
||||
') AUTO_INCREMENT=1 ;';
|
||||
|
||||
|
||||
$create_table_count = 0;
|
||||
|
||||
$ydb->show_errors = true;
|
||||
|
||||
// Create tables
|
||||
foreach ( $create_tables as $table_name => $table_query ) {
|
||||
$ydb->query($table_query);
|
||||
$create_success = $ydb->query("SHOW TABLES LIKE '$table_name'");
|
||||
if($create_success) {
|
||||
$create_table_count++;
|
||||
$success_msg[] = "Table '$table_name' created.";
|
||||
} else {
|
||||
$error_msg[] = "Error creating table '$table_name'.";
|
||||
}
|
||||
}
|
||||
|
||||
// Insert data into tables
|
||||
yourls_update_option( 'version', YOURLS_VERSION );
|
||||
yourls_update_option( 'db_version', YOURLS_DB_VERSION );
|
||||
yourls_update_option( 'next_id', 1 );
|
||||
|
||||
// Insert sample links
|
||||
yourls_insert_link_in_db( 'http://planetozh.com/blog/', 'ozhblog', 'planetOzh: Ozh\' blog' );
|
||||
yourls_insert_link_in_db( 'http://ozh.org/', 'ozh', 'ozh.org' );
|
||||
yourls_insert_link_in_db( 'http://yourls.org/', 'yourls', 'YOURLS: Your Own URL Shortener' );
|
||||
|
||||
// Check results of operations
|
||||
if ( sizeof($create_tables) == $create_table_count ) {
|
||||
$success_msg[] = 'YOURLS tables successfully created.';
|
||||
} else {
|
||||
$error_msg[] = "Error creating YOURLS tables.";
|
||||
}
|
||||
|
||||
return array( 'success' => $success_msg, 'error' => $error_msg );
|
||||
}
|
||||
?>
|
508
includes/functions-plugins.php
Normal file
@ -0,0 +1,508 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* The filter/plugin API is located in this file, which allows for creating filters
|
||||
* and hooking functions, and methods. The functions or methods will be run when
|
||||
* the filter is called.
|
||||
*
|
||||
* Any of the syntaxes explained in the PHP documentation for the
|
||||
* {@link http://us2.php.net/manual/en/language.pseudo-types.php#language.types.callback 'callback'}
|
||||
* type are valid.
|
||||
*
|
||||
* This API is heavily inspired by the one I implemented in Zenphoto 1.3, which was heavily inspired by the one used in WordPress.
|
||||
*
|
||||
* @author Ozh
|
||||
* @since 1.5
|
||||
*/
|
||||
|
||||
$yourls_filters = array();
|
||||
/* This global var will collect filters with the following structure:
|
||||
* $yourls_filters['hook']['array of priorities']['serialized function names']['array of ['array (functions, accepted_args)]']
|
||||
*/
|
||||
|
||||
/**
|
||||
* Registers a filtering function
|
||||
*
|
||||
* Typical use:
|
||||
* yourls_add_filter('some_hook', 'function_handler_for_hook');
|
||||
*
|
||||
* @global array $yourls_filters Storage for all of the filters
|
||||
* @param string $hook the name of the YOURLS element to be filtered or YOURLS action to be triggered
|
||||
* @param callback $function_name the name of the function that is to be called.
|
||||
* @param integer $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default=10, lower=earlier execution, and functions with the same priority are executed in the order in which they were added to the filter)
|
||||
* @param int $accepted_args optional. The number of arguments the function accept (default is the number provided).
|
||||
*/
|
||||
function yourls_add_filter( $hook, $function_name, $priority = 10, $accepted_args = NULL, $type = 'filter' ) {
|
||||
global $yourls_filters;
|
||||
// At this point, we cannot check if the function exists, as it may well be defined later (which is OK)
|
||||
$id = yourls_filter_unique_id( $hook, $function_name, $priority );
|
||||
|
||||
$yourls_filters[$hook][$priority][$id] = array(
|
||||
'function' => $function_name,
|
||||
'accepted_args' => $accepted_args,
|
||||
'type' => $type,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hooks a function on to a specific action.
|
||||
*
|
||||
* Actions are the hooks that YOURLS launches at specific points
|
||||
* during execution, or when specific events occur. Plugins can specify that
|
||||
* one or more of its PHP functions are executed at these points, using the
|
||||
* Action API.
|
||||
*
|
||||
* @param string $hook The name of the action to which the $function_to_add is hooked.
|
||||
* @param callback $function_name The name of the function you wish to be called.
|
||||
* @param int $priority optional. Used to specify the order in which the functions associated with a particular action are executed (default: 10). Lower numbers correspond with earlier execution, and functions with the same priority are executed in the order in which they were added to the action.
|
||||
* @param int $accepted_args optional. The number of arguments the function accept (default 1).
|
||||
*/
|
||||
function yourls_add_action( $hook, $function_name, $priority = 10, $accepted_args = 1 ) {
|
||||
return yourls_add_filter( $hook, $function_name, $priority, $accepted_args, 'action' );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Build Unique ID for storage and retrieval.
|
||||
*
|
||||
* Simply using a function name is not enough, as several functions can have the same name when they are enclosed in classes.
|
||||
*
|
||||
* @global array $yourls_filters storage for all of the filters
|
||||
* @param string $hook hook to which the function is attached
|
||||
* @param string|array $function used for creating unique id
|
||||
* @param int|bool $priority used in counting how many hooks were applied. If === false and $function is an object reference, we return the unique id only if it already has one, false otherwise.
|
||||
* @param string $type filter or action
|
||||
* @return string unique ID for usage as array key
|
||||
*/
|
||||
function yourls_filter_unique_id( $hook, $function, $priority ) {
|
||||
global $yourls_filters;
|
||||
|
||||
// If function then just skip all of the tests and not overwrite the following.
|
||||
if ( is_string($function) )
|
||||
return $function;
|
||||
// Object Class Calling
|
||||
else if (is_object($function[0]) ) {
|
||||
$obj_idx = get_class($function[0]).$function[1];
|
||||
if ( !isset($function[0]->_yourls_filters_id) ) {
|
||||
if ( false === $priority )
|
||||
return false;
|
||||
$count = isset($yourls_filters[$hook][$priority]) ? count((array)$yourls_filters[$hook][$priority]) : 0;
|
||||
$function[0]->_yourls_filters_id = $count;
|
||||
$obj_idx .= $count;
|
||||
unset($count);
|
||||
} else
|
||||
$obj_idx .= $function[0]->_yourls_filters_id;
|
||||
return $obj_idx;
|
||||
}
|
||||
// Static Calling
|
||||
else if ( is_string($function[0]) )
|
||||
return $function[0].$function[1];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a filtering operation on a YOURLS element or event.
|
||||
*
|
||||
* Typical use:
|
||||
*
|
||||
* 1) Modify a variable if a function is attached to hook 'yourls_hook'
|
||||
* $yourls_var = "default value";
|
||||
* $yourls_var = yourls_apply_filter( 'yourls_hook', $yourls_var );
|
||||
*
|
||||
* 2) Trigger functions is attached to event 'yourls_event'
|
||||
* yourls_apply_filter( 'yourls_event' );
|
||||
* (see yourls_do_action() )
|
||||
*
|
||||
* Returns an element which may have been filtered by a filter.
|
||||
*
|
||||
* @global array $yourls_filters storage for all of the filters
|
||||
* @param string $hook the name of the YOURLS element or action
|
||||
* @param mixed $value the value of the element before filtering
|
||||
* @return mixed
|
||||
*/
|
||||
function yourls_apply_filter( $hook, $value = '' ) {
|
||||
global $yourls_filters;
|
||||
if ( !isset( $yourls_filters[$hook] ) )
|
||||
return $value;
|
||||
|
||||
$args = func_get_args();
|
||||
|
||||
// Sort filters by priority
|
||||
ksort( $yourls_filters[$hook] );
|
||||
|
||||
// Loops through each filter
|
||||
reset( $yourls_filters[$hook] );
|
||||
do {
|
||||
foreach( (array) current($yourls_filters[$hook]) as $the_ ) {
|
||||
if ( !is_null($the_['function']) ){
|
||||
$args[1] = $value;
|
||||
$count = $the_['accepted_args'];
|
||||
if (is_null($count)) {
|
||||
$_value = call_user_func_array($the_['function'], array_slice($args, 1));
|
||||
} else {
|
||||
$_value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $count));
|
||||
}
|
||||
}
|
||||
if( $the_['type'] == 'filter' )
|
||||
$value = $_value;
|
||||
}
|
||||
|
||||
} while ( next($yourls_filters[$hook]) !== false );
|
||||
|
||||
if( $the_['type'] == 'filter' )
|
||||
return $value;
|
||||
}
|
||||
|
||||
function yourls_do_action( $hook, $arg = '' ) {
|
||||
$args = array();
|
||||
if ( is_array($arg) && 1 == count($arg) && isset($arg[0]) && is_object($arg[0]) ) // array(&$this)
|
||||
$args[] =& $arg[0];
|
||||
else
|
||||
$args[] = $arg;
|
||||
for ( $a = 2; $a < func_num_args(); $a++ )
|
||||
$args[] = func_get_arg($a);
|
||||
|
||||
yourls_apply_filter( $hook, $args );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes a function from a specified filter hook.
|
||||
*
|
||||
* This function removes a function attached to a specified filter hook. This
|
||||
* method can be used to remove default functions attached to a specific filter
|
||||
* hook and possibly replace them with a substitute.
|
||||
*
|
||||
* To remove a hook, the $function_to_remove and $priority arguments must match
|
||||
* when the hook was added.
|
||||
*
|
||||
* @global array $yourls_filters storage for all of the filters
|
||||
* @param string $hook The filter hook to which the function to be removed is hooked.
|
||||
* @param callback $function_to_remove The name of the function which should be removed.
|
||||
* @param int $priority optional. The priority of the function (default: 10).
|
||||
* @param int $accepted_args optional. The number of arguments the function accepts (default: 1).
|
||||
* @return boolean Whether the function was registered as a filter before it was removed.
|
||||
*/
|
||||
function yourls_remove_filter( $hook, $function_to_remove, $priority = 10, $accepted_args = 1 ) {
|
||||
global $yourls_filters;
|
||||
|
||||
$function_to_remove = yourls_filter_unique_id($hook, $function_to_remove, $priority);
|
||||
|
||||
$remove = isset ($yourls_filters[$hook][$priority][$function_to_remove]);
|
||||
|
||||
if ( $remove === true ) {
|
||||
unset ($yourls_filters[$hook][$priority][$function_to_remove]);
|
||||
if ( empty($yourls_filters[$hook][$priority]) )
|
||||
unset ($yourls_filters[$hook]);
|
||||
}
|
||||
return $remove;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if any filter has been registered for a hook.
|
||||
*
|
||||
* @global array $yourls_filters storage for all of the filters
|
||||
* @param string $hook The name of the filter hook.
|
||||
* @param callback $function_to_check optional. If specified, return the priority of that function on this hook or false if not attached.
|
||||
* @return int|boolean Optionally returns the priority on that hook for the specified function.
|
||||
*/
|
||||
function yourls_has_filter( $hook, $function_to_check = false ) {
|
||||
global $yourls_filters;
|
||||
|
||||
$has = !empty($yourls_filters[$hook]);
|
||||
if ( false === $function_to_check || false == $has ) {
|
||||
return $has;
|
||||
}
|
||||
if ( !$idx = yourls_filter_unique_id($hook, $function_to_check, false) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ( (array) array_keys($yourls_filters[$hook]) as $priority ) {
|
||||
if ( isset($yourls_filters[$hook][$priority][$idx]) )
|
||||
return $priority;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function yourls_has_action( $hook, $function_to_check = false ) {
|
||||
return yourls_has_filter( $hook, $function_to_check );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of active plugins
|
||||
*
|
||||
* @return integer Number of activated plugins
|
||||
*/
|
||||
function yourls_has_active_plugins( ) {
|
||||
global $ydb;
|
||||
|
||||
if( !property_exists( $ydb, 'plugins' ) || !$ydb->plugins )
|
||||
$ydb->plugins = array();
|
||||
|
||||
return count( $ydb->plugins );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* List plugins in /user/plugins
|
||||
*
|
||||
* @global $ydb Storage of mostly everything YOURLS needs to know
|
||||
* @return array Array of [/plugindir/plugin.php]=>array('Name'=>'Ozh', 'Title'=>'Hello', )
|
||||
*/
|
||||
function yourls_get_plugins( ) {
|
||||
global $ydb;
|
||||
|
||||
$plugins = (array) glob( YOURLS_PLUGINDIR .'/*/plugin.php');
|
||||
|
||||
if( !$plugins )
|
||||
return array();
|
||||
|
||||
foreach( $plugins as $key=>$plugin ) {
|
||||
$_plugin = yourls_plugin_basename( $plugin );
|
||||
$plugins[ $_plugin ] = yourls_get_plugin_data( $plugin );
|
||||
unset( $plugins[ $key ] );
|
||||
}
|
||||
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a plugin is active
|
||||
*
|
||||
* @param string $file Physical path to plugin file
|
||||
* @return bool
|
||||
*/
|
||||
function yourls_is_active_plugin( $plugin ) {
|
||||
if( !yourls_has_active_plugins( ) )
|
||||
return false;
|
||||
|
||||
global $ydb;
|
||||
$plugin = yourls_plugin_basename( $plugin );
|
||||
|
||||
return in_array( $plugin, $ydb->plugins );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a plugin header
|
||||
*
|
||||
* @param string $file Physical path to plugin file
|
||||
* @return array Array of 'Field'=>'Value' from plugin comment header lines of the form "Field: Value"
|
||||
*/
|
||||
function yourls_get_plugin_data( $file ) {
|
||||
$fp = fopen( $file, 'r' ); // assuming $file is readable, since yourls_load_plugins() filters this
|
||||
$data = fread( $fp, 8192 ); // get first 8kb
|
||||
fclose( $fp );
|
||||
|
||||
// Capture all the header within first comment block
|
||||
if( !preg_match( '!.*?/\*(.*?)\*/!ms', $data, $matches ) )
|
||||
return array();
|
||||
|
||||
// Capture each line with "Something: some text"
|
||||
unset( $data );
|
||||
$lines = preg_split( "[\n|\r]", $matches[1] );
|
||||
unset( $matches );
|
||||
|
||||
$plugin_data = array();
|
||||
foreach( $lines as $line ) {
|
||||
if( !preg_match( '!(.*?):\s+(.*)!', $line, $matches ) )
|
||||
continue;
|
||||
|
||||
list( $null, $field, $value ) = array_map( 'trim', $matches);
|
||||
$plugin_data[ $field ] = $value;
|
||||
}
|
||||
|
||||
return $plugin_data;
|
||||
}
|
||||
|
||||
// Include active plugins
|
||||
function yourls_load_plugins() {
|
||||
global $ydb;
|
||||
$ydb->plugins = array();
|
||||
$active_plugins = yourls_get_option( 'active_plugins' );
|
||||
|
||||
// Don't load plugins when installing or updating
|
||||
if( !$active_plugins OR ( defined( 'YOURLS_INSTALLING' ) AND YOURLS_INSTALLING ) OR yourls_upgrade_is_needed() )
|
||||
return;
|
||||
|
||||
foreach( (array)$active_plugins as $key=>$plugin ) {
|
||||
if( yourls_validate_plugin_file( YOURLS_PLUGINDIR.'/'.$plugin ) ) {
|
||||
include_once( YOURLS_PLUGINDIR.'/'.$plugin );
|
||||
$ydb->plugins[] = $plugin;
|
||||
unset( $active_plugins[$key] );
|
||||
}
|
||||
}
|
||||
|
||||
// $active_plugins should be empty now, if not, a plugin could not be find: remove it
|
||||
if( count( $active_plugins ) ) {
|
||||
$missing = '<strong>'.join( '</strong>, <strong>', $active_plugins ).'</strong>';
|
||||
yourls_update_option( 'active_plugins', $ydb->plugins );
|
||||
$message = 'Could not find and deactivated '. yourls_plural( 'plugin', count( $active_plugins ) ) .' '. $missing;
|
||||
yourls_add_notice( $message );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file is safe for inclusion (well, "safe", no guarantee)
|
||||
*
|
||||
* @param string $file Full pathname to a file
|
||||
*/
|
||||
function yourls_validate_plugin_file( $file ) {
|
||||
if (
|
||||
false !== strpos( $file, '..' )
|
||||
OR
|
||||
false !== strpos( $file, './' )
|
||||
OR
|
||||
'plugin.php' !== substr( $file, -10 ) // a plugin must be named 'plugin.php'
|
||||
OR
|
||||
!is_readable( $file )
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate a plugin
|
||||
*
|
||||
* @param string $plugin Plugin filename (full or relative to plugins directory)
|
||||
* @return mixed string if error or true if success
|
||||
*/
|
||||
function yourls_activate_plugin( $plugin ) {
|
||||
// validate file
|
||||
$plugin = yourls_plugin_basename( $plugin );
|
||||
$plugindir = yourls_sanitize_filename( YOURLS_PLUGINDIR );
|
||||
if( !yourls_validate_plugin_file( $plugindir.'/'.$plugin ) )
|
||||
return 'Not a valid plugin file';
|
||||
|
||||
// check not activated already
|
||||
global $ydb;
|
||||
if( yourls_has_active_plugins() && in_array( $plugin, $ydb->plugins ) )
|
||||
return 'Plugin already activated';
|
||||
|
||||
// attempt activation. TODO: uber cool fail proof sandbox like in WP.
|
||||
ob_start();
|
||||
include( YOURLS_PLUGINDIR.'/'.$plugin );
|
||||
if ( ob_get_length() > 0 ) {
|
||||
// there was some output: error
|
||||
$output = ob_get_clean();
|
||||
return 'Plugin generated expected output. Error was: <br/><pre>'.$output.'</pre>';
|
||||
}
|
||||
|
||||
// so far, so good: update active plugin list
|
||||
$ydb->plugins[] = $plugin;
|
||||
yourls_update_option( 'active_plugins', $ydb->plugins );
|
||||
yourls_do_action( 'activated_plugin', $plugin );
|
||||
yourls_do_action( 'activated_' . $plugin );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dectivate a plugin
|
||||
*
|
||||
* @param string $plugin Plugin filename (full relative to plugins directory)
|
||||
* @return mixed string if error or true if success
|
||||
*/
|
||||
function yourls_deactivate_plugin( $plugin ) {
|
||||
$plugin = yourls_plugin_basename( $plugin );
|
||||
|
||||
// Check plugin is active
|
||||
if( !yourls_is_active_plugin( $plugin ) )
|
||||
return 'Plugin not active';
|
||||
|
||||
// Deactivate the plugin
|
||||
global $ydb;
|
||||
$key = array_search( $plugin, $ydb->plugins );
|
||||
if( $key !== false ) {
|
||||
array_splice( $ydb->plugins, $key, 1 );
|
||||
}
|
||||
|
||||
yourls_update_option( 'active_plugins', $ydb->plugins );
|
||||
yourls_do_action( 'deactivated_plugin', $plugin );
|
||||
yourls_do_action( 'deactivated_' . $plugin );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the path of a plugin file, relative to the plugins directory
|
||||
*/
|
||||
function yourls_plugin_basename( $file ) {
|
||||
$file = yourls_sanitize_filename( $file );
|
||||
$plugindir = yourls_sanitize_filename( YOURLS_PLUGINDIR );
|
||||
$file = str_replace( $plugindir, '', $file );
|
||||
return trim( $file, '/' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the URL of the directory a plugin
|
||||
*/
|
||||
function yourls_plugin_url( $file ) {
|
||||
$url = YOURLS_PLUGINURL . '/' . yourls_plugin_basename( $file );
|
||||
if( yourls_is_ssl() or yourls_needs_ssl() )
|
||||
$url = str_replace('http://', 'https://', $url);
|
||||
return yourls_apply_filter( 'plugin_url', $url, $file );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display list of links to plugin admin pages, if any
|
||||
*/
|
||||
function yourls_list_plugin_admin_pages() {
|
||||
global $ydb;
|
||||
|
||||
if( !property_exists( $ydb, 'plugin_pages' ) || !$ydb->plugin_pages )
|
||||
return;
|
||||
|
||||
$plugin_links = array();
|
||||
foreach( (array)$ydb->plugin_pages as $plugin => $page ) {
|
||||
$plugin_links[$plugin] = array(
|
||||
'url' => yourls_admin_url( 'plugins.php?page='.$page['slug'] ),
|
||||
'anchor' => $page['title'],
|
||||
);
|
||||
}
|
||||
return $plugin_links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a plugin administration page
|
||||
*/
|
||||
function yourls_register_plugin_page( $slug, $title, $function ) {
|
||||
global $ydb;
|
||||
|
||||
if( !property_exists( $ydb, 'plugin_pages' ) || !$ydb->plugin_pages )
|
||||
$ydb->plugin_pages = array();
|
||||
|
||||
$ydb->plugin_pages[ $slug ] = array(
|
||||
'slug' => $slug,
|
||||
'title' => $title,
|
||||
'function' => $function,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle plugin administration page
|
||||
*
|
||||
*/
|
||||
function yourls_plugin_admin_page( $plugin_page ) {
|
||||
global $ydb;
|
||||
|
||||
// Check the plugin page is actually registered
|
||||
if( !isset( $ydb->plugin_pages[$plugin_page] ) ) {
|
||||
yourls_die( 'This page does not exist. Maybe a plugin you thought was activated is inactive?', 'Invalid link' );
|
||||
}
|
||||
|
||||
// Draw the page itself
|
||||
yourls_do_action( 'load-' . $plugin_page);
|
||||
yourls_html_head( 'plugin_page_' . $plugin_page, $ydb->plugin_pages[$plugin_page]['title'] );
|
||||
yourls_html_logo();
|
||||
yourls_html_menu();
|
||||
|
||||
call_user_func( $ydb->plugin_pages[$plugin_page]['function'] );
|
||||
|
||||
yourls_html_footer();
|
||||
|
||||
die();
|
||||
}
|
309
includes/functions-upgrade.php
Normal file
@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
// Upgrade YOURLS and DB schema
|
||||
function yourls_upgrade( $step, $oldver, $newver, $oldsql, $newsql ) {
|
||||
// special case for 1.3: the upgrade is a multi step procedure
|
||||
if( $oldsql == 100 ) {
|
||||
yourls_upgrade_to_14( $step );
|
||||
}
|
||||
|
||||
// other upgrades which are done in a single pass
|
||||
switch( $step ) {
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
if( $oldsql < 210 )
|
||||
yourls_upgrade_to_141();
|
||||
|
||||
if( $oldsql < 220 )
|
||||
yourls_upgrade_to_143();
|
||||
|
||||
if( $oldsql < 250 )
|
||||
yourls_upgrade_to_15();
|
||||
|
||||
if( $oldsql < 482 )
|
||||
yourls_upgrade_482();
|
||||
|
||||
yourls_redirect_javascript( yourls_admin_url( "upgrade.php?step=3" ) );
|
||||
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Update options to reflect latest version
|
||||
yourls_update_option( 'version', YOURLS_VERSION );
|
||||
yourls_update_option( 'db_version', YOURLS_DB_VERSION );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Upgrade r482
|
||||
function yourls_upgrade_482() {
|
||||
// Change URL title charset to UTF8
|
||||
global $ydb;
|
||||
$table_url = YOURLS_DB_TABLE_URL;
|
||||
$sql = "ALTER TABLE `$table_url` CHANGE `title` `title` TEXT CHARACTER SET utf8;";
|
||||
$ydb->query( $sql );
|
||||
echo "<p>Updating table structure. Please wait...</p>";
|
||||
}
|
||||
|
||||
/************************** 1.4.3 -> 1.5 **************************/
|
||||
|
||||
// Main func for upgrade from 1.4.3 to 1.5
|
||||
function yourls_upgrade_to_15( ) {
|
||||
// Create empty 'active_plugins' entry in the option if needed
|
||||
if( yourls_get_option( 'active_plugins' ) === false )
|
||||
yourls_add_option( 'active_plugins', array() );
|
||||
echo "<p>Enabling the plugin API. Please wait...</p>";
|
||||
|
||||
// Alter URL table to store titles
|
||||
global $ydb;
|
||||
$table_url = YOURLS_DB_TABLE_URL;
|
||||
$sql = "ALTER TABLE `$table_url` ADD `title` TEXT AFTER `url`;";
|
||||
$ydb->query( $sql );
|
||||
echo "<p>Updating table structure. Please wait...</p>";
|
||||
|
||||
// Update .htaccess
|
||||
yourls_create_htaccess();
|
||||
echo "<p>Updating .htaccess file. Please wait...</p>";
|
||||
}
|
||||
|
||||
/************************** 1.4.1 -> 1.4.3 **************************/
|
||||
|
||||
// Main func for upgrade from 1.4.1 to 1.4.3
|
||||
function yourls_upgrade_to_143( ) {
|
||||
// Check if we have 'keyword' (borked install) or 'shorturl' (ok install)
|
||||
global $ydb;
|
||||
$table_log = YOURLS_DB_TABLE_LOG;
|
||||
$sql = "SHOW COLUMNS FROM `$table_log`";
|
||||
$cols = $ydb->get_results( $sql );
|
||||
if ( $cols[2]->Field == 'keyword' ) {
|
||||
$sql = "ALTER TABLE `$table_log` CHANGE `keyword` `shorturl` VARCHAR( 200 ) BINARY;";
|
||||
$ydb->query( $sql );
|
||||
}
|
||||
echo "<p>Structure of existing tables updated. Please wait...</p>";
|
||||
}
|
||||
|
||||
/************************** 1.4 -> 1.4.1 **************************/
|
||||
|
||||
// Main func for upgrade from 1.4 to 1.4.1
|
||||
function yourls_upgrade_to_141( ) {
|
||||
// Kill old cookies from 1.3 and prior
|
||||
setcookie('yourls_username', null, time() - 3600 );
|
||||
setcookie('yourls_password', null, time() - 3600 );
|
||||
// alter table URL
|
||||
yourls_alter_url_table_to_141();
|
||||
// recreate the htaccess file if needed
|
||||
yourls_create_htaccess();
|
||||
}
|
||||
|
||||
// Alter table URL to 1.4.1
|
||||
function yourls_alter_url_table_to_141() {
|
||||
global $ydb;
|
||||
$table_url = YOURLS_DB_TABLE_URL;
|
||||
$alter = "ALTER TABLE `$table_url` CHANGE `keyword` `keyword` VARCHAR( 200 ) BINARY, CHANGE `url` `url` TEXT BINARY ";
|
||||
$ydb->query( $alter );
|
||||
echo "<p>Structure of existing tables updated. Please wait...</p>";
|
||||
}
|
||||
|
||||
|
||||
/************************** 1.3 -> 1.4 **************************/
|
||||
|
||||
// Main func for upgrade from 1.3-RC1 to 1.4
|
||||
function yourls_upgrade_to_14( $step ) {
|
||||
|
||||
switch( $step ) {
|
||||
case 1:
|
||||
// create table log & table options
|
||||
// update table url structure
|
||||
// update .htaccess
|
||||
yourls_create_tables_for_14(); // no value returned, assuming it went OK
|
||||
yourls_alter_url_table_to_14(); // no value returned, assuming it went OK
|
||||
$clean = yourls_clean_htaccess_for_14(); // returns bool
|
||||
$create = yourls_create_htaccess(); // returns bool
|
||||
if ( !$create )
|
||||
echo "<p class='warning'>Please create your <tt>.htaccess</tt> file (I could not do it for you). Please refer to <a href='http://yourls.org/htaccess'>http://yourls.org/htaccess</a>.";
|
||||
yourls_redirect_javascript( yourls_admin_url( "upgrade.php?step=2&oldver=1.3&newver=1.4&oldsql=100&newsql=200" ), $create );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// convert each link in table url
|
||||
yourls_update_table_to_14();
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// update table url structure part 2: recreate indexes
|
||||
yourls_alter_url_table_to_14_part_two();
|
||||
// update version & db_version & next_id in the option table
|
||||
// attempt to drop YOURLS_DB_TABLE_NEXTDEC
|
||||
yourls_update_options_to_14();
|
||||
// Now upgrade to 1.4.1
|
||||
yourls_redirect_javascript( yourls_admin_url( "upgrade.php?step=1&oldver=1.4&newver=1.4.1&oldsql=200&newsql=210" ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Update options to reflect new version
|
||||
function yourls_update_options_to_14() {
|
||||
yourls_update_option( 'version', '1.4' );
|
||||
yourls_update_option( 'db_version', '200' );
|
||||
|
||||
if( defined('YOURLS_DB_TABLE_NEXTDEC') ) {
|
||||
global $ydb;
|
||||
$table = YOURLS_DB_TABLE_NEXTDEC;
|
||||
$next_id = $ydb->get_var("SELECT `next_id` FROM `$table`");
|
||||
yourls_update_option( 'next_id', $next_id );
|
||||
@$ydb->query( "DROP TABLE `$table`" );
|
||||
} else {
|
||||
yourls_update_option( 'next_id', 1 ); // In case someone mistakenly deleted the next_id constant or table too early
|
||||
}
|
||||
}
|
||||
|
||||
// Create new tables for YOURLS 1.4: options & log
|
||||
function yourls_create_tables_for_14() {
|
||||
global $ydb;
|
||||
|
||||
$queries = array();
|
||||
|
||||
$queries[YOURLS_DB_TABLE_OPTIONS] =
|
||||
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('.
|
||||
'`option_id` int(11) unsigned NOT NULL auto_increment,'.
|
||||
'`option_name` varchar(64) NOT NULL default "",'.
|
||||
'`option_value` longtext NOT NULL,'.
|
||||
'PRIMARY KEY (`option_id`,`option_name`),'.
|
||||
'KEY `option_name` (`option_name`)'.
|
||||
');';
|
||||
|
||||
$queries[YOURLS_DB_TABLE_LOG] =
|
||||
'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('.
|
||||
'`click_id` int(11) NOT NULL auto_increment,'.
|
||||
'`click_time` datetime NOT NULL,'.
|
||||
'`shorturl` varchar(200) NOT NULL,'.
|
||||
'`referrer` varchar(200) NOT NULL,'.
|
||||
'`user_agent` varchar(255) NOT NULL,'.
|
||||
'`ip_address` varchar(41) NOT NULL,'.
|
||||
'`country_code` char(2) NOT NULL,'.
|
||||
'PRIMARY KEY (`click_id`),'.
|
||||
'KEY `shorturl` (`shorturl`)'.
|
||||
');';
|
||||
|
||||
foreach( $queries as $query ) {
|
||||
$ydb->query( $query ); // There's no result to be returned to check if table was created (except making another query to check table existence, which we'll avoid)
|
||||
}
|
||||
|
||||
echo "<p>New tables created. Please wait...</p>";
|
||||
|
||||
}
|
||||
|
||||
// Alter table structure, part 1 (change schema, drop index)
|
||||
function yourls_alter_url_table_to_14() {
|
||||
global $ydb;
|
||||
$table = YOURLS_DB_TABLE_URL;
|
||||
|
||||
$alters = array();
|
||||
$results = array();
|
||||
$alters[] = "ALTER TABLE `$table` CHANGE `id` `keyword` VARCHAR( 200 ) NOT NULL";
|
||||
$alters[] = "ALTER TABLE `$table` CHANGE `url` `url` TEXT NOT NULL";
|
||||
$alters[] = "ALTER TABLE `$table` DROP PRIMARY KEY";
|
||||
|
||||
foreach ( $alters as $query ) {
|
||||
$ydb->query( $query );
|
||||
}
|
||||
|
||||
echo "<p>Structure of existing tables updated. Please wait...</p>";
|
||||
}
|
||||
|
||||
// Alter table structure, part 2 (recreate indexes after the table is up to date)
|
||||
function yourls_alter_url_table_to_14_part_two() {
|
||||
global $ydb;
|
||||
$table = YOURLS_DB_TABLE_URL;
|
||||
|
||||
$alters = array();
|
||||
$alters[] = "ALTER TABLE `$table` ADD PRIMARY KEY ( `keyword` )";
|
||||
$alters[] = "ALTER TABLE `$table` ADD INDEX ( `ip` )";
|
||||
$alters[] = "ALTER TABLE `$table` ADD INDEX ( `timestamp` )";
|
||||
|
||||
foreach ( $alters as $query ) {
|
||||
$ydb->query( $query );
|
||||
}
|
||||
|
||||
echo "<p>New table index created</p>";
|
||||
}
|
||||
|
||||
// Convert each link from 1.3 (id) to 1.4 (keyword) structure
|
||||
function yourls_update_table_to_14() {
|
||||
global $ydb;
|
||||
$table = YOURLS_DB_TABLE_URL;
|
||||
|
||||
// Modify each link to reflect new structure
|
||||
$chunk = 45;
|
||||
$from = isset($_GET['from']) ? intval( $_GET['from'] ) : 0 ;
|
||||
$total = yourls_get_db_stats();
|
||||
$total = $total['total_links'];
|
||||
|
||||
$sql = "SELECT `keyword`,`url` FROM `$table` WHERE 1=1 ORDER BY `url` ASC LIMIT $from, $chunk ;";
|
||||
|
||||
$rows = $ydb->get_results($sql);
|
||||
|
||||
$count = 0;
|
||||
$queries = 0;
|
||||
foreach( $rows as $row ) {
|
||||
$keyword = $row->keyword;
|
||||
$url = $row->url;
|
||||
$newkeyword = yourls_int2string( $keyword );
|
||||
$ydb->query("UPDATE `$table` SET `keyword` = '$newkeyword' WHERE `url` = '$url';");
|
||||
if( $ydb->result === true ) {
|
||||
$queries++;
|
||||
} else {
|
||||
echo "<p>Huho... Could not update rown with url='$url', from keyword '$keyword' to keyword '$newkeyword'</p>"; // Find what went wrong :/
|
||||
}
|
||||
$count++;
|
||||
}
|
||||
|
||||
// All done for this chunk of queries, did it all go as expected?
|
||||
$success = true;
|
||||
if( $count != $queries ) {
|
||||
$success = false;
|
||||
$num = $count - $queries;
|
||||
echo "<p>$num error(s) occured while updating the URL table :(</p>";
|
||||
}
|
||||
|
||||
if ( $count == $chunk ) {
|
||||
// there are probably other rows to convert
|
||||
$from = $from + $chunk;
|
||||
$remain = $total - $from;
|
||||
echo "<p>Converted $chunk database rows ($remain remaining). Continuing... Please do not close this window until it's finished!</p>";
|
||||
yourls_redirect_javascript( yourls_admin_url( "upgrade.php?step=2&oldver=1.3&newver=1.4&oldsql=100&newsql=200&from=$from" ), $success );
|
||||
} else {
|
||||
// All done
|
||||
echo '<p>All rows converted! Please wait...</p>';
|
||||
yourls_redirect_javascript( yourls_admin_url( "upgrade.php?step=3&oldver=1.3&newver=1.4&oldsql=100&newsql=200" ), $success );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Clean .htaccess as it existed before 1.4. Returns boolean
|
||||
function yourls_clean_htaccess_for_14() {
|
||||
$filename = YOURLS_ABSPATH.'/.htaccess';
|
||||
|
||||
$result = false;
|
||||
if( is_writeable( $filename ) ) {
|
||||
$contents = implode( '', file( $filename ) );
|
||||
// remove "ShortURL" block
|
||||
$contents = preg_replace( '/# BEGIN ShortURL.*# END ShortURL/s', '', $contents );
|
||||
// comment out deprecated RewriteRule
|
||||
$find = 'RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]';
|
||||
$replace = "# You can safely remove this 5 lines block -- it's no longer used in YOURLS\n".
|
||||
"# $find";
|
||||
$contents = str_replace( $find, $replace, $contents );
|
||||
|
||||
// Write cleaned file
|
||||
$f = fopen( $filename, 'w' );
|
||||
fwrite( $f, $contents );
|
||||
fclose( $f );
|
||||
|
||||
$result = true;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
83
includes/functions-xml.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
/*************************************************************************/
|
||||
/* This class stores associative arrays in an xml formated string. */
|
||||
/* There's also a function thar retrieves them. If you try to use */
|
||||
/* xml2array with a general xml, it can fail, since there can be some */
|
||||
/* repeated indexes.... */
|
||||
/* Source: http://www.phpclasses.org/browse/package/2286/ */
|
||||
/*************************************************************************/
|
||||
|
||||
class yourls_array2xml {
|
||||
var $text;
|
||||
var $arrays, $keys, $node_flag, $depth, $xml_parser;
|
||||
/*Converts an array to an xml string*/
|
||||
function array2xml($array) {
|
||||
//global $text;
|
||||
$this->text="<?xml version=\"1.0\" encoding=\"iso-8859-1\"?><result>";
|
||||
$this->text.= $this->array_transform($array);
|
||||
$this->text .="</result>";
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
function array_transform($array){
|
||||
//global $array_text;
|
||||
foreach($array as $key => $value){
|
||||
if(!is_array($value)){
|
||||
//BEGIN code mod by Doug Vanderweide, 13 Jan 2011
|
||||
//does $value contain html entities?
|
||||
if(strlen($value) != strlen(htmlentities($value))) {
|
||||
//if so, encode as CDATA
|
||||
$value = "<![CDATA[" . htmlentities($value) . "]]>";
|
||||
}
|
||||
$this->text .= "<$key>$value</$key>";
|
||||
//END code mod
|
||||
} else {
|
||||
$this->text.="<$key>";
|
||||
$this->array_transform($value);
|
||||
$this->text.="</$key>";
|
||||
}
|
||||
}
|
||||
//return $array_text;
|
||||
|
||||
}
|
||||
/*Transform an XML string to associative array "XML Parser Functions"*/
|
||||
function xml2array($xml){
|
||||
$this->depth=-1;
|
||||
$this->xml_parser = xml_parser_create();
|
||||
xml_set_object($this->xml_parser, $this);
|
||||
xml_parser_set_option ($this->xml_parser,XML_OPTION_CASE_FOLDING,0);//Don't put tags uppercase
|
||||
xml_set_element_handler($this->xml_parser, "startElement", "endElement");
|
||||
xml_set_character_data_handler($this->xml_parser,"characterData");
|
||||
xml_parse($this->xml_parser,$xml,true);
|
||||
xml_parser_free($this->xml_parser);
|
||||
return $this->arrays[0];
|
||||
|
||||
}
|
||||
function startElement($parser, $name, $attrs)
|
||||
{
|
||||
$this->keys[]=$name; //We add a key
|
||||
$this->node_flag=1;
|
||||
$this->depth++;
|
||||
}
|
||||
function characterData($parser,$data)
|
||||
{
|
||||
$key=end($this->keys);
|
||||
$this->arrays[$this->depth][$key]=$data;
|
||||
$this->node_flag=0; //So that we don't add as an array, but as an element
|
||||
}
|
||||
function endElement($parser, $name)
|
||||
{
|
||||
$key=array_pop($this->keys);
|
||||
//If $node_flag==1 we add as an array, if not, as an element
|
||||
if($this->node_flag==1){
|
||||
$this->arrays[$this->depth][$key]=$this->arrays[$this->depth+1];
|
||||
unset($this->arrays[$this->depth+1]);
|
||||
}
|
||||
$this->node_flag=1;
|
||||
$this->depth--;
|
||||
}
|
||||
|
||||
}//End of the class
|
||||
|
||||
|
||||
?>
|
1673
includes/functions.php
Normal file
BIN
includes/geo/GeoIP.dat
Normal file
BIN
includes/geo/flags/flag_.gif
Normal file
After Width: | Height: | Size: 218 B |
BIN
includes/geo/flags/flag_a1.gif
Normal file
After Width: | Height: | Size: 980 B |
BIN
includes/geo/flags/flag_a2.gif
Normal file
After Width: | Height: | Size: 980 B |
BIN
includes/geo/flags/flag_ac.gif
Normal file
After Width: | Height: | Size: 588 B |
BIN
includes/geo/flags/flag_ad.gif
Normal file
After Width: | Height: | Size: 169 B |
BIN
includes/geo/flags/flag_ae.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_af.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ag.gif
Normal file
After Width: | Height: | Size: 489 B |
BIN
includes/geo/flags/flag_ai.gif
Normal file
After Width: | Height: | Size: 588 B |
BIN
includes/geo/flags/flag_al.gif
Normal file
After Width: | Height: | Size: 1005 B |
BIN
includes/geo/flags/flag_am.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_an.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ao.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ap.gif
Normal file
After Width: | Height: | Size: 901 B |
BIN
includes/geo/flags/flag_aq.gif
Normal file
After Width: | Height: | Size: 300 B |
BIN
includes/geo/flags/flag_ar.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_as.gif
Normal file
After Width: | Height: | Size: 588 B |
BIN
includes/geo/flags/flag_at.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_au.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_aw.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ax.gif
Normal file
After Width: | Height: | Size: 229 B |
BIN
includes/geo/flags/flag_az.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ba.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bb.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bd.gif
Normal file
After Width: | Height: | Size: 1005 B |
BIN
includes/geo/flags/flag_be.gif
Normal file
After Width: | Height: | Size: 1003 B |
BIN
includes/geo/flags/flag_bf.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bg.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bh.gif
Normal file
After Width: | Height: | Size: 998 B |
BIN
includes/geo/flags/flag_bi.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bj.gif
Normal file
After Width: | Height: | Size: 1005 B |
BIN
includes/geo/flags/flag_bl.gif
Normal file
After Width: | Height: | Size: 995 B |
BIN
includes/geo/flags/flag_bm.gif
Normal file
After Width: | Height: | Size: 1000 B |
BIN
includes/geo/flags/flag_bn.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bo.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_br.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bs.gif
Normal file
After Width: | Height: | Size: 1004 B |
BIN
includes/geo/flags/flag_bt.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bv.gif
Normal file
After Width: | Height: | Size: 175 B |
BIN
includes/geo/flags/flag_bw.gif
Normal file
After Width: | Height: | Size: 999 B |
BIN
includes/geo/flags/flag_bx.gif
Normal file
After Width: | Height: | Size: 995 B |
BIN
includes/geo/flags/flag_by.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_bz.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ca.gif
Normal file
After Width: | Height: | Size: 1005 B |
BIN
includes/geo/flags/flag_cc.gif
Normal file
After Width: | Height: | Size: 326 B |
BIN
includes/geo/flags/flag_cd.gif
Normal file
After Width: | Height: | Size: 300 B |
BIN
includes/geo/flags/flag_cf.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_cg.gif
Normal file
After Width: | Height: | Size: 1001 B |
BIN
includes/geo/flags/flag_ch.gif
Normal file
After Width: | Height: | Size: 1004 B |
BIN
includes/geo/flags/flag_ci.gif
Normal file
After Width: | Height: | Size: 1006 B |
BIN
includes/geo/flags/flag_ck.gif
Normal file
After Width: | Height: | Size: 1006 B |