Fix end of line

This commit is contained in:
LeoColomb 2013-04-07 12:52:52 +02:00
parent 37d0d35407
commit 3daf6593d8
67 changed files with 13805 additions and 13803 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

View File

@ -1,96 +1,96 @@
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
- added: support for any favicon dropped in the /user directory
- updated: Google Visualization API instead of deprecated Google Charts
- fixed: bugs, bugs, bugs
- added: hooks, hooks, hooks
- improved: things, things, things
1.6
---
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
- added: support for any favicon dropped in the /user directory
- updated: Google Visualization API instead of deprecated Google Charts
- fixed: bugs, bugs, bugs
- added: hooks, hooks, hooks
- improved: things, things, things
1.6
---
- added: custom API actions

View File

@ -1,26 +1,26 @@
__ ______ _ _ _____ _ _____
\ \ / / __ \| | | | __ \| | / ____|
\ \_/ / | | | | | | |__) | | | (___
\ /| | | | | | | _ /| | \___ \
| | | |__| | |__| | | \ \| |____ ____) |
|_| \____/ \____/|_| \_\______|_____/
YOURLS - Your Own URL Shortener - A URL shortening script
---------------------------------------------------------------
This program is free software. Do whatever the hell you want with it.
This program is distributed in the hope that it will be useful and/or
fun to use. There is absolutely no guarantee of any kind about anything.
For more text, have a look at http://www.gnu.org/licenses/gpl.txt
---------------------------------------------------------------
This software incorporates code stolen from WordPress, as shown by
comments in source where applicable.
---------------------------------------------------------------
By Lester CHAN (initial idea), Ozh RICHARD (development) and contributors.
__ ______ _ _ _____ _ _____
\ \ / / __ \| | | | __ \| | / ____|
\ \_/ / | | | | | | |__) | | | (___
\ /| | | | | | | _ /| | \___ \
| | | |__| | |__| | | \ \| |____ ____) |
|_| \____/ \____/|_| \_\______|_____/
YOURLS - Your Own URL Shortener - A URL shortening script
---------------------------------------------------------------
This program is free software. Do whatever the hell you want with it.
This program is distributed in the hope that it will be useful and/or
fun to use. There is absolutely no guarantee of any kind about anything.
For more text, have a look at http://www.gnu.org/licenses/gpl.txt
---------------------------------------------------------------
This software incorporates code stolen from WordPress, as shown by
comments in source where applicable.
---------------------------------------------------------------
By Lester CHAN (initial idea), Ozh RICHARD (development) and contributors.

View File

@ -1,16 +1,16 @@
![yourls](http://yourls.org/images/yourls-logo.png)
[YOURLS](http://yourls.org)
======
**YOURLS** is a set of PHP script that will allow you to run your own URL shortener. You'll have full control over your data, detailed stats and analytics, plugins, and more. It's free.
Useful links
------------
* [Project home & doc](http://yourls.org)
* [Official blog](http://blog.yourls.org)
* [Wiki documentation](https://github.com/YOURLS/YOURLS/wiki/)
* [Issue tracker](https://github.com/YOURLS/YOURLS/issues)
* [Release archive](https://github.com/YOURLS/YOURLS/tags)
License
-------
![yourls](http://yourls.org/images/yourls-logo.png)
[YOURLS](http://yourls.org)
======
**YOURLS** is a set of PHP script that will allow you to run your own URL shortener. You'll have full control over your data, detailed stats and analytics, plugins, and more. It's free.
Useful links
------------
* [Project home & doc](http://yourls.org)
* [Official blog](http://blog.yourls.org)
* [Wiki documentation](https://github.com/YOURLS/YOURLS/wiki/)
* [Issue tracker](https://github.com/YOURLS/YOURLS/issues)
* [Release archive](https://github.com/YOURLS/YOURLS/tags)
License
-------
Free software. Do whatever the hell you want with it.

View File

@ -1,51 +1,51 @@
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_AJAX', 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();
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_AJAX', 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();

View File

@ -1,295 +1,295 @@
<?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;
$where = $search_sentence = $search_text = $url = $keyword = '';
$date_filter = $date_first = $date_second = '';
$base_page = yourls_admin_url( 'index.php' );
// Default SQL behavior
$search_in_text = yourls__( 'URL' );
$search_in = 'url';
$sort_by_text = yourls__( 'Short URL' );
$sort_by = 'timestamp';
$sort_order = 'desc';
$page = ( isset( $_GET['page'] ) ? intval($_GET['page']) : 1 );
$search = ( isset( $_GET['search'] ) ? htmlspecialchars( trim($_GET['search']) ) : '' );
$perpage = ( isset( $_GET['perpage'] ) && intval( $_GET['perpage'] ) ? intval($_GET['perpage']) : 15 );
$click_limit = ( isset( $_GET['click_limit'] ) && $_GET['click_limit'] !== '' ) ? intval( $_GET['click_limit'] ) : '' ;
if ( $click_limit !== '' ) {
$click_filter = ( isset( $_GET['click_filter'] ) && $_GET['click_filter'] == 'more' ? 'more' : 'less' ) ;
$click_moreless = ( $click_filter == 'more' ? '>' : '<' );
$where = " AND clicks $click_moreless $click_limit";
} else {
$click_filter = '';
}
// Searching
if( !empty( $search ) && !empty( $_GET['search_in'] ) ) {
switch( $_GET['search_in'] ) {
case 'keyword':
$search_in_text = yourls__( 'Short URL' );
$search_in = 'keyword';
break;
case 'url':
$search_in_text = yourls__( 'URL' );
$search_in = 'url';
break;
case 'title':
$search_in_text = yourls__( 'Title' );
$search_in = 'title';
break;
case 'ip':
$search_in_text = yourls__( 'IP Address' );
$search_in = 'ip';
break;
}
$search_sentence = yourls_s( 'Searching for <strong>%1$s</strong> in <strong>%2$s</strong>.', yourls_esc_html( $search ), yourls_esc_html( $search_in_text ) );
$search_url = yourls_sanitize_url( "&amp;search=$search&amp;search_in=$search_in" );
$search_text = $search;
$search = str_replace( '*', '%', '*' . yourls_escape( $search ) . '*' );
$where .= " AND `$search_in` LIKE ('$search')";
}
// Time span
if( !empty( $_GET['date_filter'] ) ) {
switch( $_GET['date_filter'] ) {
case 'before':
$date_filter = 'before';
if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
$where .= " AND `timestamp` < '$date_first_sql'";
}
break;
case 'after':
$date_filter = 'after';
if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$where .= " AND `timestamp` > '$date_first_sql'";
}
break;
case 'between':
$date_filter = 'between';
if( isset( $_GET['date_first'] ) && isset( $_GET['date_second'] ) && 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'] );
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$date_second = yourls_sanitize_date( $_GET['date_second'] );
$where .= " AND `timestamp` BETWEEN '$date_first_sql' AND '$date_second_sql'";
}
break;
}
}
// Sorting
if( !empty( $_GET['sort_by'] ) || !empty( $_GET['sort_order'] ) ) {
switch( $_GET['sort_by'] ) {
case 'keyword':
$sort_by_text = yourls__( 'Short URL' );
$sort_by = 'keyword';
break;
case 'url':
$sort_by_text = yourls__( 'URL' );
$sort_by = 'url';
break;
case 'timestamp':
$sort_by_text = yourls__( 'Date' );
$sort_by = 'timestamp';
break;
case 'ip':
$sort_by_text = yourls__( 'IP Address' );
$sort_by = 'ip';
break;
case 'clicks':
$sort_by_text = yourls__( 'Clicks' );
$sort_by = 'clicks';
break;
}
switch( $_GET['sort_order'] ) {
case 'asc':
$sort_order = 'asc';
break;
case 'desc':
$sort_order = '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' );
// No sanitization needed here: everything happens in yourls_add_new_link()
$url = ( $_GET['u'] );
$keyword = ( isset( $_GET['k'] ) ? ( $_GET['k'] ) : '' );
$title = ( isset( $_GET['t'] ) ? ( $_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();
}
// Now use the URL that has been sanitized and returned by yourls_add_new_link()
$url = $return['url']['url'];
$where = sprintf( " AND `url` LIKE '%s' ", yourls_escape( $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() ;
yourls_do_action( 'admin_page_before_content' );
if ( !$is_bookmark ) { ?>
<p><?php echo $search_sentence; ?></p>
<p><?php
printf( yourls__( 'Display <strong>%1$s</strong> to <strong class="increment">%2$s</strong> of <strong class="increment">%3$s</strong> URLs' ), $display_on_page, $max_on_page, $total_items );
if( $total_items_clicks !== false )
echo ", " . sprintf( yourls_n( 'counting <strong>1</strong> click', 'counting <strong>%s</strong> clicks', $total_items_clicks ), yourls_number_format_i18n( $total_items_clicks ) );
?>.</p>
<?php } ?>
<p><?php printf( yourls__( 'Overall, tracking <strong class="increment">%1$s</strong> links, <strong>%2$s</strong> clicks, and counting!' ), yourls_number_format_i18n( $total_urls ), yourls_number_format_i18n( $total_clicks ) ); ?></p>
<?php yourls_do_action( 'admin_page_before_form' ); ?>
<?php yourls_html_addnew(); ?>
<?php
// If bookmarklet, add message. Otherwise, hide hidden share box.
if ( !$is_bookmark ) {
yourls_share_box( '', '', '', '', '', '', true );
} else {
echo '<script type="text/javascript">$(document).ready(function(){
feedback( "' . $return['message'] . '", "'. $return['status'] .'");
init_clipboard();
});</script>';
}
yourls_do_action( 'admin_page_before_table' );
yourls_table_head();
if ( !$is_bookmark ) {
$params = array(
'search' => $search,
'search_text' => $search_text,
'search_in' => $search_in,
'sort_by' => $sort_by,
'sort_order' => $sort_order,
'page' => $page,
'perpage' => $perpage,
'click_filter' => $click_filter,
'click_limit' => $click_limit,
'total_pages' => $total_pages,
'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` $sort_order 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">' . yourls__('No URL') . '</td></tr>';
yourls_table_tbody_end();
yourls_table_end();
yourls_do_action( 'admin_page_after_table' );
if ( $is_bookmark )
yourls_share_box( $url, $return['shorturl'], $title, $text );
?>
<?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;
$where = $search_sentence = $search_text = $url = $keyword = '';
$date_filter = $date_first = $date_second = '';
$base_page = yourls_admin_url( 'index.php' );
// Default SQL behavior
$search_in_text = yourls__( 'URL' );
$search_in = 'url';
$sort_by_text = yourls__( 'Short URL' );
$sort_by = 'timestamp';
$sort_order = 'desc';
$page = ( isset( $_GET['page'] ) ? intval($_GET['page']) : 1 );
$search = ( isset( $_GET['search'] ) ? htmlspecialchars( trim($_GET['search']) ) : '' );
$perpage = ( isset( $_GET['perpage'] ) && intval( $_GET['perpage'] ) ? intval($_GET['perpage']) : 15 );
$click_limit = ( isset( $_GET['click_limit'] ) && $_GET['click_limit'] !== '' ) ? intval( $_GET['click_limit'] ) : '' ;
if ( $click_limit !== '' ) {
$click_filter = ( isset( $_GET['click_filter'] ) && $_GET['click_filter'] == 'more' ? 'more' : 'less' ) ;
$click_moreless = ( $click_filter == 'more' ? '>' : '<' );
$where = " AND clicks $click_moreless $click_limit";
} else {
$click_filter = '';
}
// Searching
if( !empty( $search ) && !empty( $_GET['search_in'] ) ) {
switch( $_GET['search_in'] ) {
case 'keyword':
$search_in_text = yourls__( 'Short URL' );
$search_in = 'keyword';
break;
case 'url':
$search_in_text = yourls__( 'URL' );
$search_in = 'url';
break;
case 'title':
$search_in_text = yourls__( 'Title' );
$search_in = 'title';
break;
case 'ip':
$search_in_text = yourls__( 'IP Address' );
$search_in = 'ip';
break;
}
$search_sentence = yourls_s( 'Searching for <strong>%1$s</strong> in <strong>%2$s</strong>.', yourls_esc_html( $search ), yourls_esc_html( $search_in_text ) );
$search_url = yourls_sanitize_url( "&amp;search=$search&amp;search_in=$search_in" );
$search_text = $search;
$search = str_replace( '*', '%', '*' . yourls_escape( $search ) . '*' );
$where .= " AND `$search_in` LIKE ('$search')";
}
// Time span
if( !empty( $_GET['date_filter'] ) ) {
switch( $_GET['date_filter'] ) {
case 'before':
$date_filter = 'before';
if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
$where .= " AND `timestamp` < '$date_first_sql'";
}
break;
case 'after':
$date_filter = 'after';
if( isset( $_GET['date_first'] ) && yourls_sanitize_date( $_GET['date_first'] ) ) {
$date_first_sql = yourls_sanitize_date_for_sql( $_GET['date_first'] );
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$where .= " AND `timestamp` > '$date_first_sql'";
}
break;
case 'between':
$date_filter = 'between';
if( isset( $_GET['date_first'] ) && isset( $_GET['date_second'] ) && 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'] );
$date_first = yourls_sanitize_date( $_GET['date_first'] );
$date_second = yourls_sanitize_date( $_GET['date_second'] );
$where .= " AND `timestamp` BETWEEN '$date_first_sql' AND '$date_second_sql'";
}
break;
}
}
// Sorting
if( !empty( $_GET['sort_by'] ) || !empty( $_GET['sort_order'] ) ) {
switch( $_GET['sort_by'] ) {
case 'keyword':
$sort_by_text = yourls__( 'Short URL' );
$sort_by = 'keyword';
break;
case 'url':
$sort_by_text = yourls__( 'URL' );
$sort_by = 'url';
break;
case 'timestamp':
$sort_by_text = yourls__( 'Date' );
$sort_by = 'timestamp';
break;
case 'ip':
$sort_by_text = yourls__( 'IP Address' );
$sort_by = 'ip';
break;
case 'clicks':
$sort_by_text = yourls__( 'Clicks' );
$sort_by = 'clicks';
break;
}
switch( $_GET['sort_order'] ) {
case 'asc':
$sort_order = 'asc';
break;
case 'desc':
$sort_order = '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' );
// No sanitization needed here: everything happens in yourls_add_new_link()
$url = ( $_GET['u'] );
$keyword = ( isset( $_GET['k'] ) ? ( $_GET['k'] ) : '' );
$title = ( isset( $_GET['t'] ) ? ( $_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();
}
// Now use the URL that has been sanitized and returned by yourls_add_new_link()
$url = $return['url']['url'];
$where = sprintf( " AND `url` LIKE '%s' ", yourls_escape( $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() ;
yourls_do_action( 'admin_page_before_content' );
if ( !$is_bookmark ) { ?>
<p><?php echo $search_sentence; ?></p>
<p><?php
printf( yourls__( 'Display <strong>%1$s</strong> to <strong class="increment">%2$s</strong> of <strong class="increment">%3$s</strong> URLs' ), $display_on_page, $max_on_page, $total_items );
if( $total_items_clicks !== false )
echo ", " . sprintf( yourls_n( 'counting <strong>1</strong> click', 'counting <strong>%s</strong> clicks', $total_items_clicks ), yourls_number_format_i18n( $total_items_clicks ) );
?>.</p>
<?php } ?>
<p><?php printf( yourls__( 'Overall, tracking <strong class="increment">%1$s</strong> links, <strong>%2$s</strong> clicks, and counting!' ), yourls_number_format_i18n( $total_urls ), yourls_number_format_i18n( $total_clicks ) ); ?></p>
<?php yourls_do_action( 'admin_page_before_form' ); ?>
<?php yourls_html_addnew(); ?>
<?php
// If bookmarklet, add message. Otherwise, hide hidden share box.
if ( !$is_bookmark ) {
yourls_share_box( '', '', '', '', '', '', true );
} else {
echo '<script type="text/javascript">$(document).ready(function(){
feedback( "' . $return['message'] . '", "'. $return['status'] .'");
init_clipboard();
});</script>';
}
yourls_do_action( 'admin_page_before_table' );
yourls_table_head();
if ( !$is_bookmark ) {
$params = array(
'search' => $search,
'search_text' => $search_text,
'search_in' => $search_in,
'sort_by' => $sort_by,
'sort_order' => $sort_order,
'page' => $page,
'perpage' => $perpage,
'click_filter' => $click_filter,
'click_limit' => $click_limit,
'total_pages' => $total_pages,
'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` $sort_order 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">' . yourls__('No URL') . '</td></tr>';
yourls_table_tbody_end();
yourls_table_end();
yourls_do_action( 'admin_page_after_table' );
if ( $is_bookmark )
yourls_share_box( $url, $return['shorturl'], $title, $text );
?>
<?php yourls_html_footer( ); ?>

View File

@ -1,75 +1,75 @@
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_INSTALLING', 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[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'MySQL' );
if ( !yourls_check_php_version() )
$error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'PHP' );
// Is YOURLS already installed ?
if ( yourls_is_installed() ) {
$error[] = yourls__( '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[] = yourls__( 'File <tt>.htaccess</tt> successfully created/updated.' );
} else {
$warning[] = yourls__( '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', yourls__( 'Install YOURLS' ) );
?>
<div id="login">
<form method="post" action="?"><?php // reset any QUERY parameters ?>
<p>
<img src="<?php yourls_site_url(); ?>/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 style="text-align: center;"><input type="submit" name="install" value="' . yourls__( 'Install YOURLS') .'" class="button" /></p>';
} else {
if( count($error) == 0 )
echo '<p style="text-align: center;">&raquo; <a href="'.yourls_admin_url().'" title="' . yourls__( 'YOURLS Administration Page') . '">' . yourls__( 'YOURLS Administration Page') . '</a></p>';
}
?>
</form>
</div>
<?php yourls_html_footer(); ?>
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_INSTALLING', 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[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'MySQL' );
if ( !yourls_check_php_version() )
$error[] = yourls_s( '%s version is too old. Ask your server admin for an upgrade.', 'PHP' );
// Is YOURLS already installed ?
if ( yourls_is_installed() ) {
$error[] = yourls__( '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[] = yourls__( 'File <tt>.htaccess</tt> successfully created/updated.' );
} else {
$warning[] = yourls__( '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', yourls__( 'Install YOURLS' ) );
?>
<div id="login">
<form method="post" action="?"><?php // reset any QUERY parameters ?>
<p>
<img src="<?php yourls_site_url(); ?>/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 style="text-align: center;"><input type="submit" name="install" value="' . yourls__( 'Install YOURLS') .'" class="button" /></p>';
} else {
if( count($error) == 0 )
echo '<p style="text-align: center;">&raquo; <a href="'.yourls_admin_url().'" title="' . yourls__( 'YOURLS Administration Page') . '">' . yourls__( 'YOURLS Administration Page') . '</a></p>';
}
?>
</form>
</div>
<?php yourls_html_footer(); ?>

View File

@ -1,164 +1,164 @@
<?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 = yourls__( 'Unsupported action' );
break;
}
} else {
$result = yourls__( 'No plugin specified, or not a valid plugin' );
}
yourls_add_notice( $result );
}
// Handle message upon succesfull (de)activation
if( isset( $_GET['success'] ) && ( ( $_GET['success'] == 'activated' ) OR ( $_GET['success'] == 'deactivated' ) ) ) {
if( $_GET['success'] == 'activated' ) {
$message = yourls__( 'Plugin has been activated' );
} elseif ( $_GET['success'] == 'deactivated' ) {
$message = yourls__( 'Plugin has been deactivated' );
}
yourls_add_notice( $message );
}
yourls_html_head( 'plugins', yourls__( 'Manage Plugins' ) );
yourls_html_logo();
yourls_html_menu();
?>
<h2><?php yourls_e( 'Plugins' ); ?></h2>
<?php
$plugins = (array)yourls_get_plugins();
uasort( $plugins, 'yourls_plugins_sort_callback' );
$count = count( $plugins );
$plugins_count = sprintf( yourls_n( '%s plugin', '%s plugins', $count ), $count );
$count_active = yourls_has_active_plugins();
?>
<p id="plugin_summary"><?php /* //translators: "you have '3 plugins' installed and '1' activated" */ yourls_se( 'You currently have <strong>%1$s</strong> installed, and <strong>%2$s</strong> activated', $plugins_count, $count_active ); ?></p>
<table id="main_table" class="tblSorter" cellpadding="0" cellspacing="1">
<thead>
<tr>
<th><?php yourls_e( 'Plugin Name' ); ?></th>
<th><?php yourls_e( 'Version' ); ?></th>
<th><?php yourls_e( 'Description' ); ?></th>
<th><?php yourls_e( 'Author' ); ?></th>
<th><?php yourls_e( '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 = yourls__( 'Deactivate' );
} else {
$class = 'inactive';
$action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'activate', 'plugin' => $plugindir ) ) );
$action_anchor = yourls__( '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>' . yourls_s( 'plugin file location: %s', $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', '<?php echo yourls_esc_attr__( 'Toggle active/inactive plugins' ); ?>')
.click(function(){
$('#main_table tr.inactive').toggle();
});
<?php } ?>
</script>
<p><?php yourls_e( '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><?php yourls_e( 'More plugins' ); ?></h3>
<p><?php yourls_e( 'For more plugins, head to the official <a href="http://yourls.org/pluginlist">Plugin list</a>.' ); ?></p>
<?php yourls_html_footer(); ?>
<?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 = yourls__( 'Unsupported action' );
break;
}
} else {
$result = yourls__( 'No plugin specified, or not a valid plugin' );
}
yourls_add_notice( $result );
}
// Handle message upon succesfull (de)activation
if( isset( $_GET['success'] ) && ( ( $_GET['success'] == 'activated' ) OR ( $_GET['success'] == 'deactivated' ) ) ) {
if( $_GET['success'] == 'activated' ) {
$message = yourls__( 'Plugin has been activated' );
} elseif ( $_GET['success'] == 'deactivated' ) {
$message = yourls__( 'Plugin has been deactivated' );
}
yourls_add_notice( $message );
}
yourls_html_head( 'plugins', yourls__( 'Manage Plugins' ) );
yourls_html_logo();
yourls_html_menu();
?>
<h2><?php yourls_e( 'Plugins' ); ?></h2>
<?php
$plugins = (array)yourls_get_plugins();
uasort( $plugins, 'yourls_plugins_sort_callback' );
$count = count( $plugins );
$plugins_count = sprintf( yourls_n( '%s plugin', '%s plugins', $count ), $count );
$count_active = yourls_has_active_plugins();
?>
<p id="plugin_summary"><?php /* //translators: "you have '3 plugins' installed and '1' activated" */ yourls_se( 'You currently have <strong>%1$s</strong> installed, and <strong>%2$s</strong> activated', $plugins_count, $count_active ); ?></p>
<table id="main_table" class="tblSorter" cellpadding="0" cellspacing="1">
<thead>
<tr>
<th><?php yourls_e( 'Plugin Name' ); ?></th>
<th><?php yourls_e( 'Version' ); ?></th>
<th><?php yourls_e( 'Description' ); ?></th>
<th><?php yourls_e( 'Author' ); ?></th>
<th><?php yourls_e( '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 = yourls__( 'Deactivate' );
} else {
$class = 'inactive';
$action_url = yourls_nonce_url( 'manage_plugins', yourls_add_query_arg( array('action' => 'activate', 'plugin' => $plugindir ) ) );
$action_anchor = yourls__( '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>' . yourls_s( 'plugin file location: %s', $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', '<?php echo yourls_esc_attr__( 'Toggle active/inactive plugins' ); ?>')
.click(function(){
$('#main_table tr.inactive').toggle();
});
<?php } ?>
</script>
<p><?php yourls_e( '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><?php yourls_e( 'More plugins' ); ?></h3>
<p><?php yourls_e( 'For more plugins, head to the official <a href="http://yourls.org/pluginlist">Plugin list</a>.' ); ?></p>
<?php yourls_html_footer(); ?>

View File

@ -1,117 +1,117 @@
<?php
define( 'YOURLS_ADMIN', true );
require_once( dirname( dirname( __FILE__ ) ).'/includes/load-yourls.php' );
yourls_maybe_require_auth();
yourls_html_head( 'tools', yourls__( 'Cool YOURLS Tools' ) );
yourls_html_logo();
yourls_html_menu();
?>
<div class="sub_wrap">
<h2><?php yourls_e( 'Bookmarklets' ); ?></h2>
<p><?php yourls_e( 'YOURLS comes with <span>four</span> handy <span>bookmarklets</span> for easier link shortening.' ); ?></p>
<h3><?php yourls_e( 'Standard or Instant, Simple or Custom' ); ?></h3>
<ul>
<li><?php yourls_e( '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><?php yourls_e( 'The <span>Instant Bookmarklets</span> will pop the short URL without leaving the page you are viewing.' ); ?></li>
<li><?php yourls_e( 'The <span>Simple Bookmarklets</span> will generate a short URL with a random or sequential keyword.' ); ?></li>
<li><?php yourls_e( 'The <span>Custom Keyword Bookmarklets</span> will prompt you for a custom keyword first.' ); ?></li>
</ul>
<p><?php
yourls_e( "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." );
echo "\n";
yourls_e( "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><?php yourls_e( 'The Bookmarklets' ); ?></h3>
<p><?php yourls_e( 'Click and drag links to your toolbar (or right-click and bookmark it)' ); ?></p>
<table class="tblSorter" cellpadding="0" cellspacing="1">
<thead>
<tr>
<td>&nbsp;</td>
<th><?php yourls_e( 'Standard (new page)' ); ?></th>
<th><?php yourls_e( 'Instant (popup)' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<th class="header"><?php yourls_e( '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:enc(s)),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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( '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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( 'Instant Shorten' ); ?></a></td>
</tr>
<tr>
<th class="header"><?php yourls_e( '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:enc(s)),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)+'&s='+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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( '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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( 'Instant Custom Shorten' ); ?></a></td>
</tr>
</tbody>
</table>
<h2><?php yourls_e( 'Prefix-n-Shorten' ); ?></h2>
<p><?php yourls_se( "When viewing a page, you can also prefix its full URL: just head to your browser's address bar, add \"<span>%s</span>\" to the beginning of the current URL (right before its 'http://' part) and hit enter.", preg_replace('@https?://@', '', YOURLS_SITE) . '/' ); ?></p>
<p><?php
yourls_e( 'Note: this will probably not work if your web server is running on Windows' );
if( yourls_is_windows() )
yourls_e( ' (which seems to be the case here)' );
?>.</p>
<?php if( yourls_is_private() ) { ?>
<h2><?php yourls_e( 'Secure passwordless API call' ); ?></h2>
<p><?php
yourls_e( 'YOURLS allows API calls the old fashioned way, using <tt>username</tt> and <tt>password</tt> parameters.' );
echo "\n";
yourls_e( "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><?php
yourls_se( 'Your secret signature token: <strong><code>%s</code></strong>', yourls_auth_signature() );
yourls_e( "(It's a secret. Keep it secret) ");
?></p>
<p><?php yourls_e( 'This signature token can only be used with the API, not with the admin interface.' ); ?></p>
<ul>
<li><h3><?php yourls_e( 'Usage of the signature token' ); ?></h3>
<p><?php yourls_e( '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><?php yourls_e( 'Usage of a time limited signature token' ); ?></h3>
<pre><code>&lt;?php
$timestamp = time();
<tt>// <?php yourls_e( 'actual value:' ); ?> $time = <?php $time = time(); echo $time; ?></tt>
$signature = md5( $timestamp . '<?php echo yourls_auth_signature(); ?>' );
<tt>// <?php yourls_e( 'actual value:' ); ?> $signature = "<?php $sign = md5( $time. yourls_auth_signature() ); echo $sign; ?>"</tt>
?>
</code></pre>
<p><?php yourls_e( '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><?php yourls_e( 'Actual values:' ); ?><br/>
<tt><?php echo YOURLS_SITE; ?>/yourls-api.php?timestamp=<?php echo $time; ?>&signature=<?php echo $sign; ?>&action=...</tt></p>
<p><?php yourls_se( 'This URL would be valid for only %s seconds', YOURLS_NONCE_LIFE ); ?></p>
</li>
</ul>
<p><?php yourls_se( 'See the <a href="%s">API documentation</a> for more', YOURLS_SITE . '/readme.html#API' ); ?></p>
</div>
<?php } // end is private ?>
<?php yourls_html_footer(); ?>
<?php
define( 'YOURLS_ADMIN', true );
require_once( dirname( dirname( __FILE__ ) ).'/includes/load-yourls.php' );
yourls_maybe_require_auth();
yourls_html_head( 'tools', yourls__( 'Cool YOURLS Tools' ) );
yourls_html_logo();
yourls_html_menu();
?>
<div class="sub_wrap">
<h2><?php yourls_e( 'Bookmarklets' ); ?></h2>
<p><?php yourls_e( 'YOURLS comes with <span>four</span> handy <span>bookmarklets</span> for easier link shortening.' ); ?></p>
<h3><?php yourls_e( 'Standard or Instant, Simple or Custom' ); ?></h3>
<ul>
<li><?php yourls_e( '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><?php yourls_e( 'The <span>Instant Bookmarklets</span> will pop the short URL without leaving the page you are viewing.' ); ?></li>
<li><?php yourls_e( 'The <span>Simple Bookmarklets</span> will generate a short URL with a random or sequential keyword.' ); ?></li>
<li><?php yourls_e( 'The <span>Custom Keyword Bookmarklets</span> will prompt you for a custom keyword first.' ); ?></li>
</ul>
<p><?php
yourls_e( "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." );
echo "\n";
yourls_e( "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><?php yourls_e( 'The Bookmarklets' ); ?></h3>
<p><?php yourls_e( 'Click and drag links to your toolbar (or right-click and bookmark it)' ); ?></p>
<table class="tblSorter" cellpadding="0" cellspacing="1">
<thead>
<tr>
<td>&nbsp;</td>
<th><?php yourls_e( 'Standard (new page)' ); ?></th>
<th><?php yourls_e( 'Instant (popup)' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<th class="header"><?php yourls_e( '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:enc(s)),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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( '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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( 'Instant Shorten' ); ?></a></td>
</tr>
<tr>
<th class="header"><?php yourls_e( '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:enc(s)),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)+'&s='+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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( '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('<?php echo yourls_esc_attr__( 'Drag to your toolbar!' ); ?>');return false;"><?php yourls_e( 'Instant Custom Shorten' ); ?></a></td>
</tr>
</tbody>
</table>
<h2><?php yourls_e( 'Prefix-n-Shorten' ); ?></h2>
<p><?php yourls_se( "When viewing a page, you can also prefix its full URL: just head to your browser's address bar, add \"<span>%s</span>\" to the beginning of the current URL (right before its 'http://' part) and hit enter.", preg_replace('@https?://@', '', YOURLS_SITE) . '/' ); ?></p>
<p><?php
yourls_e( 'Note: this will probably not work if your web server is running on Windows' );
if( yourls_is_windows() )
yourls_e( ' (which seems to be the case here)' );
?>.</p>
<?php if( yourls_is_private() ) { ?>
<h2><?php yourls_e( 'Secure passwordless API call' ); ?></h2>
<p><?php
yourls_e( 'YOURLS allows API calls the old fashioned way, using <tt>username</tt> and <tt>password</tt> parameters.' );
echo "\n";
yourls_e( "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><?php
yourls_se( 'Your secret signature token: <strong><code>%s</code></strong>', yourls_auth_signature() );
yourls_e( "(It's a secret. Keep it secret) ");
?></p>
<p><?php yourls_e( 'This signature token can only be used with the API, not with the admin interface.' ); ?></p>
<ul>
<li><h3><?php yourls_e( 'Usage of the signature token' ); ?></h3>
<p><?php yourls_e( '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><?php yourls_e( 'Usage of a time limited signature token' ); ?></h3>
<pre><code>&lt;?php
$timestamp = time();
<tt>// <?php yourls_e( 'actual value:' ); ?> $time = <?php $time = time(); echo $time; ?></tt>
$signature = md5( $timestamp . '<?php echo yourls_auth_signature(); ?>' );
<tt>// <?php yourls_e( 'actual value:' ); ?> $signature = "<?php $sign = md5( $time. yourls_auth_signature() ); echo $sign; ?>"</tt>
?>
</code></pre>
<p><?php yourls_e( '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><?php yourls_e( 'Actual values:' ); ?><br/>
<tt><?php echo YOURLS_SITE; ?>/yourls-api.php?timestamp=<?php echo $time; ?>&signature=<?php echo $sign; ?>&action=...</tt></p>
<p><?php yourls_se( 'This URL would be valid for only %s seconds', YOURLS_NONCE_LIFE ); ?></p>
</li>
</ul>
<p><?php yourls_se( 'See the <a href="%s">API documentation</a> for more', YOURLS_SITE . '/readme.html#API' ); ?></p>
</div>
<?php } // end is private ?>
<?php yourls_html_footer(); ?>

View File

@ -1,86 +1,86 @@
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_UPGRADING', true );
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', yourls__( 'Upgrade YOURLS' ) );
yourls_html_logo();
yourls_html_menu();
?>
<h2><?php yourls_e( 'Upgrade YOURLS' ); ?></h2>
<?php
// Check if upgrade is needed
if ( !yourls_upgrade_is_needed() ) {
echo '<p>' . yourls_s( 'Upgrade not required. Go <a href="%s">back to play</a>!', yourls_admin_url('index.php') ) . '</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:
?>
<p><?php yourls_e( 'Your current installation needs to be upgraded.' ); ?></p>
<p><?php yourls_e( 'Please, pretty please, it is recommended that you <strong>backup</strong> your database<br/>(you should do this regularly anyway)' ); ?></p>
<p><?php yourls_e( "Nothing awful <em>should</em> happen, but this doesn't mean it <em>won't</em> happen, right? ;)" ); ?></p>
<p><?php yourls_e( "On every step, if <span class='error'>something goes wrong</span>, you'll see a message and hopefully a way to fix." ); ?></p>
<p><?php yourls_e( 'If everything goes too fast and you cannot read, <span class="success">good for you</span>, let it go :)' ); ?></p>
<p><?php yourls_e( 'Once you are ready, press "Upgrade" !' ); ?></p>
<?php
echo "
<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='" . yourls_esc_attr__( '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 );
echo '<p>' . yourls__( 'Your installation is now up to date ! ' ) . '</p>';
echo '<p>' . yourls_s( 'Go back to <a href="%s">the admin interface</a>', yourls_admin_url('index.php') ) . '</p>';
}
}
?>
<?php yourls_html_footer(); ?>
<?php
define( 'YOURLS_ADMIN', true );
define( 'YOURLS_UPGRADING', true );
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', yourls__( 'Upgrade YOURLS' ) );
yourls_html_logo();
yourls_html_menu();
?>
<h2><?php yourls_e( 'Upgrade YOURLS' ); ?></h2>
<?php
// Check if upgrade is needed
if ( !yourls_upgrade_is_needed() ) {
echo '<p>' . yourls_s( 'Upgrade not required. Go <a href="%s">back to play</a>!', yourls_admin_url('index.php') ) . '</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:
?>
<p><?php yourls_e( 'Your current installation needs to be upgraded.' ); ?></p>
<p><?php yourls_e( 'Please, pretty please, it is recommended that you <strong>backup</strong> your database<br/>(you should do this regularly anyway)' ); ?></p>
<p><?php yourls_e( "Nothing awful <em>should</em> happen, but this doesn't mean it <em>won't</em> happen, right? ;)" ); ?></p>
<p><?php yourls_e( "On every step, if <span class='error'>something goes wrong</span>, you'll see a message and hopefully a way to fix." ); ?></p>
<p><?php yourls_e( 'If everything goes too fast and you cannot read, <span class="success">good for you</span>, let it go :)' ); ?></p>
<p><?php yourls_e( 'Once you are ready, press "Upgrade" !' ); ?></p>
<?php
echo "
<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='" . yourls_esc_attr__( '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 );
echo '<p>' . yourls__( 'Your installation is now up to date ! ' ) . '</p>';
echo '<p>' . yourls_s( 'Go back to <a href="%s">the admin interface</a>', yourls_admin_url('index.php') ) . '</p>';
}
}
?>
<?php yourls_html_footer(); ?>

View File

@ -1,14 +1,14 @@
/* Calendar */
.datepicker { border-collapse: collapse; border: 2px solid #999; position: absolute; width: 215px }
.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 */
/* Calendar */
.datepicker { border-collapse: collapse; border: 2px solid #999; position: absolute; width: 215px }
.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}

View File

@ -1,113 +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, #details_clicks li span.best_month, #details_clicks li span.best_year {
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;
}
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, #details_clicks li span.best_month, #details_clicks li span.best_year {
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;
}

View File

@ -1,65 +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%;
}
#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%;
}

View File

@ -1,330 +1,330 @@
body {
font-family: Verdana, Arial;
font-size: 12px;
color: #595441;
background:#e3f3ff;
text-align:center;
margin-top:0px;
padding-top:10px;
}
#wrap {
max-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;max-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;
}
#add-url {width:400px}
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 {
max-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:inline-block;
}
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;
max-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;}
body {
font-family: Verdana, Arial;
font-size: 12px;
color: #595441;
background:#e3f3ff;
text-align:center;
margin-top:0px;
padding-top:10px;
}
#wrap {
max-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;max-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;
}
#add-url {width:400px}
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 {
max-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:inline-block;
}
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;
max-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;}

View File

@ -1,104 +1,104 @@
/* 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 .tablesorter-header {
background-image: url('../images/bg.gif');
background-repeat: no-repeat;
background-position: center right;
cursor: pointer;
padding-right:10px;
}
table.tblSorter thead tr .sorter-false {
background-image: none;
cursor:default;
}
table.tblSorter tbody td {
color: #3D3D3D;
padding: 4px;
background-color: #FFF;
vertical-align: top;
}
table.tblSorter tbody tr.normal-row td {
background: #F1F9FF;
}
table.tblSorter tbody tr.alt-row td {
}
table.tblSorter tbody tr.normal-row:hover td {
background-color:#F1FFF6;
}
table.tblSorter tbody tr.alt-row:hover td {
background-color:#F1FFF6;
}
table.tblSorter thead tr .tablesorter-headerDesc {
background-image: url('../images/desc.gif');
background-repeat: no-repeat;
background-position: center right;
}
table.tblSorter thead tr .tablesorter-headerAsc {
background-image: url('../images/asc.gif');
background-repeat: no-repeat;
background-position: center right;
}
table.tblSorter thead tr .tablesorter-headerAsc, table.tblSorter thead tr .tablesorter-headerDesc {
background-color: #91C7F2;
}
table.tblSorter tfoot tr {
background-color: #BCD9E8;
}
#filter_form{
float:left;
text-align: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;
/* 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 .tablesorter-header {
background-image: url('../images/bg.gif');
background-repeat: no-repeat;
background-position: center right;
cursor: pointer;
padding-right:10px;
}
table.tblSorter thead tr .sorter-false {
background-image: none;
cursor:default;
}
table.tblSorter tbody td {
color: #3D3D3D;
padding: 4px;
background-color: #FFF;
vertical-align: top;
}
table.tblSorter tbody tr.normal-row td {
background: #F1F9FF;
}
table.tblSorter tbody tr.alt-row td {
}
table.tblSorter tbody tr.normal-row:hover td {
background-color:#F1FFF6;
}
table.tblSorter tbody tr.alt-row:hover td {
background-color:#F1FFF6;
}
table.tblSorter thead tr .tablesorter-headerDesc {
background-image: url('../images/desc.gif');
background-repeat: no-repeat;
background-position: center right;
}
table.tblSorter thead tr .tablesorter-headerAsc {
background-image: url('../images/asc.gif');
background-repeat: no-repeat;
background-position: center right;
}
table.tblSorter thead tr .tablesorter-headerAsc, table.tblSorter thead tr .tablesorter-headerDesc {
background-color: #91C7F2;
}
table.tblSorter tfoot tr {
background-color: #BCD9E8;
}
#filter_form{
float:left;
text-align: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;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,202 +1,202 @@
<?php
/*
* YOURLS
* Functions for the API
*
* Note about translation : this file should NOT be translation ready
* API messages and returns are supposed to be programmatically tested, so default English is expected
*
*/
/**
* API function wrapper: Shorten a URL
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_shorturl() {
$url = ( isset( $_REQUEST['url'] ) ? $_REQUEST['url'] : '' );
$keyword = ( isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' );
$title = ( isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' );
$return = yourls_add_new_link( $url, $keyword, $title );
$return['simple'] = ( isset( $return['shorturl'] ) ? $return['shorturl'] : '' ); // This one will be used in case output mode is 'simple'
unset( $return['html'] ); // in API mode, no need for our internal HTML output
return yourls_apply_filter( 'api_result_shorturl', $return );
}
/**
* API function wrapper: Stats about links (XX top, bottom, last, rand)
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_stats() {
$filter = ( isset( $_REQUEST['filter'] ) ? $_REQUEST['filter'] : '' );
$limit = ( isset( $_REQUEST['limit'] ) ? $_REQUEST['limit'] : '' );
$start = ( isset( $_REQUEST['start'] ) ? $_REQUEST['start'] : '' );
return yourls_apply_filter( 'api_result_stats', yourls_api_stats( $filter, $limit, $start ) );
}
/**
* API function wrapper: Just the global counts of shorturls and clicks
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_db_stats() {
return yourls_apply_filter( 'api_result_db_stats', yourls_api_db_stats() );
}
/**
* API function wrapper: Stats for a shorturl
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_url_stats() {
$shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' );
return yourls_apply_filter( 'api_result_url_stats', yourls_api_url_stats( $shorturl ) );
}
/**
* API function wrapper: Expand a short link
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_expand() {
$shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' );
return yourls_apply_filter( 'api_result_expand', yourls_api_expand( $shorturl ) );
}
/**
* API function wrapper: return version numbers
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_version() {
$return['version'] = $return['simple'] = YOURLS_VERSION;
if( isset( $_REQUEST['db'] ) && $_REQUEST['db'] == 1 )
$return['db_version'] = YOURLS_DB_VERSION;
return yourls_apply_filter( 'api_result_version', $return );
}
<?php
/*
* YOURLS
* Functions for the API
*
* Note about translation : this file should NOT be translation ready
* API messages and returns are supposed to be programmatically tested, so default English is expected
*
*/
/**
* API function wrapper: Shorten a URL
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_shorturl() {
$url = ( isset( $_REQUEST['url'] ) ? $_REQUEST['url'] : '' );
$keyword = ( isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' );
$title = ( isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' );
$return = yourls_add_new_link( $url, $keyword, $title );
$return['simple'] = ( isset( $return['shorturl'] ) ? $return['shorturl'] : '' ); // This one will be used in case output mode is 'simple'
unset( $return['html'] ); // in API mode, no need for our internal HTML output
return yourls_apply_filter( 'api_result_shorturl', $return );
}
/**
* API function wrapper: Stats about links (XX top, bottom, last, rand)
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_stats() {
$filter = ( isset( $_REQUEST['filter'] ) ? $_REQUEST['filter'] : '' );
$limit = ( isset( $_REQUEST['limit'] ) ? $_REQUEST['limit'] : '' );
$start = ( isset( $_REQUEST['start'] ) ? $_REQUEST['start'] : '' );
return yourls_apply_filter( 'api_result_stats', yourls_api_stats( $filter, $limit, $start ) );
}
/**
* API function wrapper: Just the global counts of shorturls and clicks
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_db_stats() {
return yourls_apply_filter( 'api_result_db_stats', yourls_api_db_stats() );
}
/**
* API function wrapper: Stats for a shorturl
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_url_stats() {
$shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' );
return yourls_apply_filter( 'api_result_url_stats', yourls_api_url_stats( $shorturl ) );
}
/**
* API function wrapper: Expand a short link
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_expand() {
$shorturl = ( isset( $_REQUEST['shorturl'] ) ? $_REQUEST['shorturl'] : '' );
return yourls_apply_filter( 'api_result_expand', yourls_api_expand( $shorturl ) );
}
/**
* API function wrapper: return version numbers
*
* @since 1.6
* @return array Result of API call
*/
function yourls_api_action_version() {
$return['version'] = $return['simple'] = YOURLS_VERSION;
if( isset( $_REQUEST['db'] ) && $_REQUEST['db'] == 1 )
$return['db_version'] = YOURLS_DB_VERSION;
return yourls_apply_filter( 'api_result_version', $return );
}
/**
* Return API result. Dies after this
*
*/
function yourls_api_output( $mode, $return ) {
if( isset( $return['simple'] ) ) {
$simple = $return['simple'];
unset( $return['simple'] );
}
yourls_do_action( 'pre_api_output', $mode, $return );
if( isset( $return['statusCode'] ) ) {
$code = $return['statusCode'];
} elseif ( isset( $return['errorCode'] ) ) {
$code = $return['errorCode'];
} else {
$code = 200;
}
yourls_status_header( $code );
switch ( $mode ) {
case 'jsonp':
header( 'Content-type: application/javascript' );
echo $return['callback'] . '(' . json_encode( $return ) . ')';
break;
case 'json':
header( 'Content-type: application/json' );
echo json_encode( $return );
break;
case 'xml':
header( 'Content-type: application/xml' );
echo yourls_xml_encode( $return );
break;
case 'simple':
default:
if( isset( $simple ) )
echo $simple;
break;
}
yourls_do_action( 'api_output', $mode, $return );
die();
}
function yourls_api_output( $mode, $return ) {
if( isset( $return['simple'] ) ) {
$simple = $return['simple'];
unset( $return['simple'] );
}
yourls_do_action( 'pre_api_output', $mode, $return );
if( isset( $return['statusCode'] ) ) {
$code = $return['statusCode'];
} elseif ( isset( $return['errorCode'] ) ) {
$code = $return['errorCode'];
} else {
$code = 200;
}
yourls_status_header( $code );
switch ( $mode ) {
case 'jsonp':
header( 'Content-type: application/javascript' );
echo $return['callback'] . '(' . json_encode( $return ) . ')';
break;
case 'json':
header( 'Content-type: application/json' );
echo json_encode( $return );
break;
case 'xml':
header( 'Content-type: application/xml' );
echo yourls_xml_encode( $return );
break;
case 'simple':
default:
if( isset( $simple ) )
echo $simple;
break;
}
yourls_do_action( 'api_output', $mode, $return );
die();
}
/**
* Return array for API stat requests
*
*/
function yourls_api_stats( $filter = 'top', $limit = 10, $start = 0 ) {
$return = yourls_get_stats( $filter, $limit, $start );
$return['simple'] = 'Need either XML or JSON format for stats';
$return['message'] = 'success';
return yourls_apply_filter( 'api_stats', $return, $filter, $limit, $start );
}
function yourls_api_stats( $filter = 'top', $limit = 10, $start = 0 ) {
$return = yourls_get_stats( $filter, $limit, $start );
$return['simple'] = 'Need either XML or JSON format for stats';
$return['message'] = 'success';
return yourls_apply_filter( 'api_stats', $return, $filter, $limit, $start );
}
/**
* Return array for counts of shorturls and clicks
*
*/
function yourls_api_db_stats() {
$return = array(
'db-stats' => yourls_get_db_stats(),
'statusCode' => 200,
'simple' => 'Need either XML or JSON format for stats',
'message' => 'success',
);
return yourls_apply_filter( 'api_db_stats', $return );
}
function yourls_api_db_stats() {
$return = array(
'db-stats' => yourls_get_db_stats(),
'statusCode' => 200,
'simple' => 'Need either XML or JSON format for stats',
'message' => 'success',
);
return yourls_apply_filter( 'api_db_stats', $return );
}
/**
* Return array for API stat requests
*
*/
function yourls_api_url_stats( $shorturl ) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$return = yourls_get_link_stats( $keyword );
$return['simple'] = 'Need either XML or JSON format for stats';
return yourls_apply_filter( 'api_url_stats', $return, $shorturl );
}
function yourls_api_url_stats( $shorturl ) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$return = yourls_get_link_stats( $keyword );
$return['simple'] = 'Need either XML or JSON format for stats';
return yourls_apply_filter( 'api_url_stats', $return, $shorturl );
}
/**
* Expand short url to long url
*
*/
function yourls_api_expand( $shorturl ) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$longurl = yourls_get_keyword_longurl( $keyword );
if( $longurl ) {
$return = array(
'keyword' => $keyword,
'shorturl' => YOURLS_SITE . "/$keyword",
'longurl' => $longurl,
'simple' => $longurl,
'message' => 'success',
'statusCode' => 200,
);
} else {
$return = array(
'keyword' => $keyword,
'simple' => 'not found',
'message' => 'Error: short URL not found',
'errorCode' => 404,
);
}
return yourls_apply_filter( 'api_expand', $return, $shorturl );
}
function yourls_api_expand( $shorturl ) {
$keyword = str_replace( YOURLS_SITE . '/' , '', $shorturl ); // accept either 'http://ozh.in/abc' or 'abc'
$keyword = yourls_sanitize_string( $keyword );
$longurl = yourls_get_keyword_longurl( $keyword );
if( $longurl ) {
$return = array(
'keyword' => $keyword,
'shorturl' => YOURLS_SITE . "/$keyword",
'longurl' => $longurl,
'simple' => $longurl,
'message' => 'success',
'statusCode' => 200,
);
} else {
$return = array(
'keyword' => $keyword,
'simple' => 'not found',
'message' => 'Error: short URL not found',
'errorCode' => 404,
);
}
return yourls_apply_filter( 'api_expand', $return, $shorturl );
}

View File

@ -1,245 +1,245 @@
<?php
<?php
/**
* Check for valid user. Returns true or an error message
*
*/
function yourls_is_valid_user() {
static $valid = false;
if( $valid )
return true;
$unfiltered_valid = false;
// Logout request
if( isset( $_GET['action'] ) && $_GET['action'] == 'logout' ) {
yourls_do_action( 'logout' );
yourls_store_cookie( null );
return yourls__( 'Logged out successfully' );
}
// Check cookies or login request. Login form has precedence.
global $yourls_user_passwords;
yourls_do_action( 'pre_login' );
// 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'] )
)
{
yourls_do_action( 'pre_login_signature_timestamp' );
$unfiltered_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'] )
)
{
yourls_do_action( 'pre_login_signature' );
$unfiltered_valid = yourls_check_signature();
}
elseif
// API or normal: login with username & pwd
( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] )
&& !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) )
{
yourls_do_action( 'pre_login_username_password' );
$unfiltered_valid = yourls_check_username_password();
}
elseif
// Normal only: cookies
( !yourls_is_API() &&
isset( $_COOKIE['yourls_username'] ) && isset( $_COOKIE['yourls_password'] ) )
{
yourls_do_action( 'pre_login_cookie' );
$unfiltered_valid = yourls_check_auth_cookie();
}
$valid = yourls_apply_filter( 'is_valid_user', $unfiltered_valid );
// Login for the win!
if ( $valid ) {
yourls_do_action( 'login' );
// (Re)store encrypted cookie if needed and tell it's ok
if ( !yourls_is_API() && $unfiltered_valid )
yourls_store_cookie( YOURLS_USER );
return true;
}
// Login failed
yourls_do_action( 'login_failed' );
if ( isset( $_REQUEST['username'] ) || isset( $_REQUEST['password'] ) ) {
return yourls__( 'Invalid username or password' );
} else {
return yourls__( 'Please log in' );
}
}
function yourls_is_valid_user() {
static $valid = false;
if( $valid )
return true;
$unfiltered_valid = false;
// Logout request
if( isset( $_GET['action'] ) && $_GET['action'] == 'logout' ) {
yourls_do_action( 'logout' );
yourls_store_cookie( null );
return yourls__( 'Logged out successfully' );
}
// Check cookies or login request. Login form has precedence.
global $yourls_user_passwords;
yourls_do_action( 'pre_login' );
// 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'] )
)
{
yourls_do_action( 'pre_login_signature_timestamp' );
$unfiltered_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'] )
)
{
yourls_do_action( 'pre_login_signature' );
$unfiltered_valid = yourls_check_signature();
}
elseif
// API or normal: login with username & pwd
( isset( $_REQUEST['username'] ) && isset( $_REQUEST['password'] )
&& !empty( $_REQUEST['username'] ) && !empty( $_REQUEST['password'] ) )
{
yourls_do_action( 'pre_login_username_password' );
$unfiltered_valid = yourls_check_username_password();
}
elseif
// Normal only: cookies
( !yourls_is_API() &&
isset( $_COOKIE['yourls_username'] ) && isset( $_COOKIE['yourls_password'] ) )
{
yourls_do_action( 'pre_login_cookie' );
$unfiltered_valid = yourls_check_auth_cookie();
}
$valid = yourls_apply_filter( 'is_valid_user', $unfiltered_valid );
// Login for the win!
if ( $valid ) {
yourls_do_action( 'login' );
// (Re)store encrypted cookie if needed and tell it's ok
if ( !yourls_is_API() && $unfiltered_valid )
yourls_store_cookie( YOURLS_USER );
return true;
}
// Login failed
yourls_do_action( 'login_failed' );
if ( isset( $_REQUEST['username'] ) || isset( $_REQUEST['password'] ) ) {
return yourls__( 'Invalid username or password' );
} else {
return yourls__( '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;
}
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 ) = explode( ':', $stored );
return( $stored == 'md5:'.$salt.':'.md5( $salt.$plaintext ) );
} else {
// Password was sent in clear
$message = '';
$message .= yourls__( '<strong>Notice</strong>: your password is stored as clear text in your <tt>config.php</tt>' );
$message .= yourls__( 'Did you know you can easily improve the security of your YOURLS install by <strong>encrypting</strong> your password?' );
$message .= yourls__( 'See <a href="http://yourls.org/userpassword">UsernamePassword</a> for details' );
yourls_add_notice( $message, 'notice' );
return( $stored == $plaintext );
}
}
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 ) = explode( ':', $stored );
return( $stored == 'md5:'.$salt.':'.md5( $salt.$plaintext ) );
} else {
// Password was sent in clear
$message = '';
$message .= yourls__( '<strong>Notice</strong>: your password is stored as clear text in your <tt>config.php</tt>' );
$message .= yourls__( 'Did you know you can easily improve the security of your YOURLS install by <strong>encrypting</strong> your password?' );
$message .= yourls__( 'See <a href="http://yourls.org/userpassword">UsernamePassword</a> for details' );
yourls_add_notice( $message, 'notice' );
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;
}
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;
}
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;
}
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' );
}
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 if timestamp is not too old
*
*/
function yourls_check_timestamp( $time ) {
$now = time();
// Allow timestamp to be a little in the future or the past -- see Issue 766
return yourls_apply_filter( 'check_timestamp', abs( $now - $time ) < YOURLS_NONCE_LIFE, $time );
}
function yourls_check_timestamp( $time ) {
$now = time();
// Allow timestamp to be a little in the future or the past -- see Issue 766
return yourls_apply_filter( 'check_timestamp', abs( $now - $time ) < YOURLS_NONCE_LIFE, $time );
}
/**
* 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 );
}
}
}
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 );
}
function yourls_set_user( $user ) {
if( !defined( 'YOURLS_USER' ) )
define( 'YOURLS_USER', $user );
}

View File

@ -1,171 +1,171 @@
<?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 );
}
}
/**
* Compat http_build_query for PHP4. Stolen from WP.
*
* 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 );
}
}
<?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 );
}
}
/**
* Compat http_build_query for PHP4. Stolen from WP.
*
* 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 );
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,190 +1,190 @@
<?php
// TODO: improve this.
// yourls_get_http_transport: use static vars
// yourls_get_remote_content: return array( content, status, code )
<?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. Return 'curl', 'fopen', 'fsockopen' or false if nothing works
*
* Order of preference: curl, fopen, fsockopen.
* Determine best transport for GET request. Return 'curl', 'fopen', 'fsockopen' or false if nothing works
*
* Order of preference: curl, fopen, fsockopen.
*
*/
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 );
}
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
*
* 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 );
}
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
}
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;
}
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;
}
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.')' );
}
function yourls_http_user_agent() {
return yourls_apply_filter( 'http_user_agent', 'YOURLS v'.YOURLS_VERSION.' +http://yourls.org/ (running on '.YOURLS_SITE.')' );
}

View File

@ -1,295 +1,295 @@
<?php
<?php
/**
* Check if mod_rewrite is enabled. Note: unused, not reliable enough.
*
*/
function yourls_check_mod_rewrite() {
return yourls_apache_mod_loaded( 'mod_rewrite' );
}
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' );
}
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 );
}
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 );
}
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
);
}
function yourls_is_apache() {
return (
strpos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) !== false
|| strpos( $_SERVER['SERVER_SOFTWARE'], 'LiteSpeed' ) !== false
);
}
/**
* Check if server is running IIS
*
*/
function yourls_is_iis() {
return ( strpos( $_SERVER['SERVER_SOFTWARE'], 'IIS' ) !== false );
}
function yourls_is_iis() {
return ( strpos( $_SERVER['SERVER_SOFTWARE'], 'IIS' ) !== 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;
}
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 or web.config. Returns boolean
*
*/
function yourls_create_htaccess() {
$host = parse_url( YOURLS_SITE );
$path = ( isset( $host['path'] ) ? $host['path'] : '' );
if ( yourls_is_iis() ) {
// Prepare content for a web.config file
$content = array(
'<?'.'xml version="1.0" encoding="UTF-8"?>',
'<configuration>',
' <system.webServer>',
' <rewrite>',
' <rules>',
' <rule name="YOURLS" stopProcessing="true">',
' <match url="^(.*)$" ignoreCase="false" />',
' <conditions>',
' <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />',
' <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />',
' </conditions>',
' <action type="Rewrite" url="'.$path.'/yourls-loader.php" appendQueryString="true" />',
' </rule>',
' </rules>',
' </rewrite>',
' </system.webServer>',
'</configuration>',
);
$filename = YOURLS_ABSPATH.'/web.config';
$marker = 'none';
} else {
// Prepare content for a .htaccess file
$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';
$marker = 'YOURLS';
}
return ( yourls_insert_with_markers( $filename, $marker, $content ) );
}
function yourls_create_htaccess() {
$host = parse_url( YOURLS_SITE );
$path = ( isset( $host['path'] ) ? $host['path'] : '' );
if ( yourls_is_iis() ) {
// Prepare content for a web.config file
$content = array(
'<?'.'xml version="1.0" encoding="UTF-8"?>',
'<configuration>',
' <system.webServer>',
' <rewrite>',
' <rules>',
' <rule name="YOURLS" stopProcessing="true">',
' <match url="^(.*)$" ignoreCase="false" />',
' <conditions>',
' <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />',
' <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />',
' </conditions>',
' <action type="Rewrite" url="'.$path.'/yourls-loader.php" appendQueryString="true" />',
' </rule>',
' </rules>',
' </rewrite>',
' </system.webServer>',
'</configuration>',
);
$filename = YOURLS_ABSPATH.'/web.config';
$marker = 'none';
} else {
// Prepare content for a .htaccess file
$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';
$marker = 'YOURLS';
}
return ( yourls_insert_with_markers( $filename, $marker, $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 ) {
if ( $marker != 'none' )
fwrite( $f, "# BEGIN {$marker}\n" );
if ( is_array( $insertion ) )
foreach ( $insertion as $insertline )
fwrite( $f, "{$insertline}\n" );
if ( $marker != 'none' )
fwrite( $f, "# END {$marker}\n" );
$state = true;
$foundit = true;
}
}
}
if ( !$foundit ) {
if ( $marker != 'none' )
fwrite( $f, "\n\n# BEGIN {$marker}\n" );
foreach ( $insertion as $insertline )
fwrite( $f, "{$insertline}\n" );
if ( $marker != 'none' )
fwrite( $f, "# END {$marker}\n\n" );
}
fclose( $f );
return true;
} else {
return false;
}
}
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 ) {
if ( $marker != 'none' )
fwrite( $f, "# BEGIN {$marker}\n" );
if ( is_array( $insertion ) )
foreach ( $insertion as $insertline )
fwrite( $f, "{$insertline}\n" );
if ( $marker != 'none' )
fwrite( $f, "# END {$marker}\n" );
$state = true;
$foundit = true;
}
}
}
if ( !$foundit ) {
if ( $marker != 'none' )
fwrite( $f, "\n\n# BEGIN {$marker}\n" );
foreach ( $insertion as $insertline )
fwrite( $f, "{$insertline}\n" );
if ( $marker != 'none' )
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[] = yourls_s( "Table '%s' created.", $table_name );
} else {
$error_msg[] = yourls_s( "Error creating table '%s'.", $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__( 'YOURLS tables successfully created.' );
} else {
$error_msg[] = yourls__( 'Error creating YOURLS tables.' );
}
return array( 'success' => $success_msg, 'error' => $error_msg );
}
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[] = yourls_s( "Table '%s' created.", $table_name );
} else {
$error_msg[] = yourls_s( "Error creating table '%s'.", $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__( 'YOURLS tables successfully created.' );
} else {
$error_msg[] = yourls__( 'Error creating YOURLS tables.' );
}
return array( 'success' => $success_msg, 'error' => $error_msg );
}
/**
* Toggle maintenance mode. Inspired from WP. Returns true for success, false otherwise
*
*/
function yourls_maintenance_mode( $maintenance = true ) {
$file = YOURLS_ABSPATH . '/.maintenance' ;
// Turn maintenance mode on : create .maintenance file
if ( (bool)$maintenance ) {
if ( ! ( $fp = @fopen( $file, 'w' ) ) )
return false;
$maintenance_string = '<?php $maintenance_start = ' . time() . '; ?>';
@fwrite( $fp, $maintenance_string );
@fclose( $fp );
@chmod( $file, 0644 ); // Read and write for owner, read for everybody else
// Not sure why the fwrite would fail if the fopen worked... Just in case
return( is_readable( $file ) );
// Turn maintenance mode off : delete the .maintenance file
} else {
return @unlink($file);
}
function yourls_maintenance_mode( $maintenance = true ) {
$file = YOURLS_ABSPATH . '/.maintenance' ;
// Turn maintenance mode on : create .maintenance file
if ( (bool)$maintenance ) {
if ( ! ( $fp = @fopen( $file, 'w' ) ) )
return false;
$maintenance_string = '<?php $maintenance_start = ' . time() . '; ?>';
@fwrite( $fp, $maintenance_string );
@fclose( $fp );
@chmod( $file, 0644 ); // Read and write for owner, read for everybody else
// Not sure why the fwrite would fail if the fopen worked... Just in case
return( is_readable( $file ) );
// Turn maintenance mode off : delete the .maintenance file
} else {
return @unlink($file);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,348 +1,348 @@
<?php
<?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;
}
}
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 **************************/
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 **************************/
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 **************************/
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();
}
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 **************************/
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;
}
}
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
}
}
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>";
}
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>";
}
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>";
}
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 );
}
}
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;
}
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;
}

View File

@ -1,81 +1,81 @@
<?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
<?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

File diff suppressed because it is too large Load Diff

View File

@ -1,177 +1,177 @@
<?php
// This file initialize everything needed for YOURLS
// Include settings
if( file_exists( dirname( dirname( __FILE__ ) ) . '/user/config.php' ) ) {
// config.php in /user/
require_once( dirname( dirname( __FILE__ ) ) . '/user/config.php' );
} elseif ( file_exists( dirname( __FILE__ ) . '/config.php' ) ) {
// config.php in /includes/
require_once( dirname( __FILE__ ) . '/config.php' );
} else {
// config.php not found :(
die( '<p class="error">Cannot find <tt>config.php</tt>.</p><p>Please read the <tt>readme.html</tt> to learn how to install YOURLS</p>' );
}
// Check if config.php was properly updated for 1.4
if( !defined( 'YOURLS_DB_PREFIX' ) )
die( '<p class="error">Your <tt>config.php</tt> does not contain all the required constant definitions.</p><p>Please check <tt>config-sample.php</tt> and update your config accordingly, there are new stuffs!</p>' );
// Define core constants that have not been user defined in config.php
// physical path of YOURLS root
if( !defined( 'YOURLS_ABSPATH' ) )
define( 'YOURLS_ABSPATH', str_replace( '\\', '/', dirname( dirname( __FILE__ ) ) ) );
// physical path of includes directory
if( !defined( 'YOURLS_INC' ) )
define( 'YOURLS_INC', YOURLS_ABSPATH.'/includes' );
// physical path of user directory
if( !defined( 'YOURLS_USERDIR' ) )
define( 'YOURLS_USERDIR', YOURLS_ABSPATH.'/user' );
// URL of user directory
if( !defined( 'YOURLS_USERURL' ) )
define( 'YOURLS_USERURL', YOURLS_SITE.'/user' );
// physical path of translations directory
if( !defined( 'YOURLS_LANG_DIR' ) )
define( 'YOURLS_LANG_DIR', YOURLS_USERDIR.'/languages' );
// physical path of plugins directory
if( !defined( 'YOURLS_PLUGINDIR' ) )
define( 'YOURLS_PLUGINDIR', YOURLS_USERDIR.'/plugins' );
// URL of plugins directory
if( !defined( 'YOURLS_PLUGINURL' ) )
define( 'YOURLS_PLUGINURL', YOURLS_USERURL.'/plugins' );
// physical path of pages directory
if( !defined( 'YOURLS_PAGEDIR' ) )
define('YOURLS_PAGEDIR', YOURLS_ABSPATH.'/pages' );
// table to store URLs
if( !defined( 'YOURLS_DB_TABLE_URL' ) )
define( 'YOURLS_DB_TABLE_URL', YOURLS_DB_PREFIX.'url' );
// table to store options
if( !defined( 'YOURLS_DB_TABLE_OPTIONS' ) )
define( 'YOURLS_DB_TABLE_OPTIONS', YOURLS_DB_PREFIX.'options' );
// table to store hits, for stats
if( !defined( 'YOURLS_DB_TABLE_LOG' ) )
define( 'YOURLS_DB_TABLE_LOG', YOURLS_DB_PREFIX.'log' );
// minimum delay in sec before a same IP can add another URL. Note: logged in users are not throttled down.
if( !defined( 'YOURLS_FLOOD_DELAY_SECONDS' ) )
define( 'YOURLS_FLOOD_DELAY_SECONDS', 15 );
// comma separated list of IPs that can bypass flood check.
if( !defined( 'YOURLS_FLOOD_IP_WHITELIST' ) )
define( 'YOURLS_FLOOD_IP_WHITELIST', '' );
// life span of an auth cookie in seconds (60*60*24*7 = 7 days)
if( !defined( 'YOURLS_COOKIE_LIFE' ) )
define( 'YOURLS_COOKIE_LIFE', 60*60*24*7 );
// life span of a nonce in seconds
if( !defined( 'YOURLS_NONCE_LIFE' ) )
define( 'YOURLS_NONCE_LIFE', 43200 ); // 3600 * 12
// if set to true, disable stat logging (no use for it, too busy servers, ...)
if( !defined( 'YOURLS_NOSTATS' ) )
define( 'YOURLS_NOSTATS', false );
// if set to true, force https:// in the admin area
if( !defined( 'YOURLS_ADMIN_SSL' ) )
define( 'YOURLS_ADMIN_SSL', false );
// if set to true, verbose debug infos. Will break things. Don't enable.
if( !defined( 'YOURLS_DEBUG' ) )
define( 'YOURLS_DEBUG', false );
// Error reporting
if( defined( 'YOURLS_DEBUG' ) && YOURLS_DEBUG == true ) {
error_reporting( -1 );
} else {
error_reporting( E_ERROR | E_PARSE );
}
// Include all functions
require_once( YOURLS_INC.'/version.php' );
require_once( YOURLS_INC.'/functions.php');
require_once( YOURLS_INC.'/functions-plugins.php' );
require_once( YOURLS_INC.'/functions-formatting.php' );
require_once( YOURLS_INC.'/functions-api.php' );
require_once( YOURLS_INC.'/functions-kses.php' );
require_once( YOURLS_INC.'/functions-l10n.php' );
require_once( YOURLS_INC.'/functions-compat.php' );
require_once( YOURLS_INC.'/functions-html.php' );
// Allow drop-in replacement for the DB engine
if( file_exists( YOURLS_USERDIR.'/db.php' ) ) {
require_once( YOURLS_USERDIR.'/db.php' );
} else {
require_once( YOURLS_INC.'/class-mysql.php' );
}
// Load auth functions if needed
if( yourls_is_private() )
require_once( YOURLS_INC.'/functions-auth.php' );
// Allow early inclusion of a cache layer
if( file_exists( YOURLS_USERDIR.'/cache.php' ) )
require_once( YOURLS_USERDIR.'/cache.php' );
// Load locale
yourls_load_default_textdomain();
// Check if we are in maintenance mode - if yes, it will die here.
yourls_check_maintenance_mode();
// If request for an admin page is http:// and SSL is required, redirect
if( yourls_is_admin() && yourls_needs_ssl() && !yourls_is_ssl() ) {
if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
yourls_redirect( preg_replace( '|^http://|', 'https://', $_SERVER['REQUEST_URI'] ) );
exit();
} else {
yourls_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
exit();
}
}
// Fix REQUEST_URI for IIS
yourls_fix_request_uri();
// Create the YOURLS object $ydb that will contain everything we globally need
global $ydb;
yourls_db_connect();
// Read options right from start
yourls_get_all_options();
// Register shutdown function
register_shutdown_function( 'yourls_shutdown' );
// Core now loaded
yourls_do_action( 'init' ); // plugins can't see this, not loaded yet
// Check if need to redirect to install procedure
if( !yourls_is_installed() && !yourls_is_installing() ) {
yourls_redirect( yourls_admin_url( 'install.php' ), 302 );
}
// Check if upgrade is needed (bypassed if upgrading or installing)
if ( !yourls_is_upgrading() && !yourls_is_installing() ) {
if ( yourls_upgrade_is_needed() ) {
yourls_redirect( YOURLS_SITE .'/admin/upgrade.php', 302 );
}
}
// Init all plugins
yourls_load_plugins();
yourls_do_action( 'plugins_loaded' );
if( yourls_is_admin() )
yourls_do_action( 'admin_init' );
<?php
// This file initialize everything needed for YOURLS
// Include settings
if( file_exists( dirname( dirname( __FILE__ ) ) . '/user/config.php' ) ) {
// config.php in /user/
require_once( dirname( dirname( __FILE__ ) ) . '/user/config.php' );
} elseif ( file_exists( dirname( __FILE__ ) . '/config.php' ) ) {
// config.php in /includes/
require_once( dirname( __FILE__ ) . '/config.php' );
} else {
// config.php not found :(
die( '<p class="error">Cannot find <tt>config.php</tt>.</p><p>Please read the <tt>readme.html</tt> to learn how to install YOURLS</p>' );
}
// Check if config.php was properly updated for 1.4
if( !defined( 'YOURLS_DB_PREFIX' ) )
die( '<p class="error">Your <tt>config.php</tt> does not contain all the required constant definitions.</p><p>Please check <tt>config-sample.php</tt> and update your config accordingly, there are new stuffs!</p>' );
// Define core constants that have not been user defined in config.php
// physical path of YOURLS root
if( !defined( 'YOURLS_ABSPATH' ) )
define( 'YOURLS_ABSPATH', str_replace( '\\', '/', dirname( dirname( __FILE__ ) ) ) );
// physical path of includes directory
if( !defined( 'YOURLS_INC' ) )
define( 'YOURLS_INC', YOURLS_ABSPATH.'/includes' );
// physical path of user directory
if( !defined( 'YOURLS_USERDIR' ) )
define( 'YOURLS_USERDIR', YOURLS_ABSPATH.'/user' );
// URL of user directory
if( !defined( 'YOURLS_USERURL' ) )
define( 'YOURLS_USERURL', YOURLS_SITE.'/user' );
// physical path of translations directory
if( !defined( 'YOURLS_LANG_DIR' ) )
define( 'YOURLS_LANG_DIR', YOURLS_USERDIR.'/languages' );
// physical path of plugins directory
if( !defined( 'YOURLS_PLUGINDIR' ) )
define( 'YOURLS_PLUGINDIR', YOURLS_USERDIR.'/plugins' );
// URL of plugins directory
if( !defined( 'YOURLS_PLUGINURL' ) )
define( 'YOURLS_PLUGINURL', YOURLS_USERURL.'/plugins' );
// physical path of pages directory
if( !defined( 'YOURLS_PAGEDIR' ) )
define('YOURLS_PAGEDIR', YOURLS_ABSPATH.'/pages' );
// table to store URLs
if( !defined( 'YOURLS_DB_TABLE_URL' ) )
define( 'YOURLS_DB_TABLE_URL', YOURLS_DB_PREFIX.'url' );
// table to store options
if( !defined( 'YOURLS_DB_TABLE_OPTIONS' ) )
define( 'YOURLS_DB_TABLE_OPTIONS', YOURLS_DB_PREFIX.'options' );
// table to store hits, for stats
if( !defined( 'YOURLS_DB_TABLE_LOG' ) )
define( 'YOURLS_DB_TABLE_LOG', YOURLS_DB_PREFIX.'log' );
// minimum delay in sec before a same IP can add another URL. Note: logged in users are not throttled down.
if( !defined( 'YOURLS_FLOOD_DELAY_SECONDS' ) )
define( 'YOURLS_FLOOD_DELAY_SECONDS', 15 );
// comma separated list of IPs that can bypass flood check.
if( !defined( 'YOURLS_FLOOD_IP_WHITELIST' ) )
define( 'YOURLS_FLOOD_IP_WHITELIST', '' );
// life span of an auth cookie in seconds (60*60*24*7 = 7 days)
if( !defined( 'YOURLS_COOKIE_LIFE' ) )
define( 'YOURLS_COOKIE_LIFE', 60*60*24*7 );
// life span of a nonce in seconds
if( !defined( 'YOURLS_NONCE_LIFE' ) )
define( 'YOURLS_NONCE_LIFE', 43200 ); // 3600 * 12
// if set to true, disable stat logging (no use for it, too busy servers, ...)
if( !defined( 'YOURLS_NOSTATS' ) )
define( 'YOURLS_NOSTATS', false );
// if set to true, force https:// in the admin area
if( !defined( 'YOURLS_ADMIN_SSL' ) )
define( 'YOURLS_ADMIN_SSL', false );
// if set to true, verbose debug infos. Will break things. Don't enable.
if( !defined( 'YOURLS_DEBUG' ) )
define( 'YOURLS_DEBUG', false );
// Error reporting
if( defined( 'YOURLS_DEBUG' ) && YOURLS_DEBUG == true ) {
error_reporting( -1 );
} else {
error_reporting( E_ERROR | E_PARSE );
}
// Include all functions
require_once( YOURLS_INC.'/version.php' );
require_once( YOURLS_INC.'/functions.php');
require_once( YOURLS_INC.'/functions-plugins.php' );
require_once( YOURLS_INC.'/functions-formatting.php' );
require_once( YOURLS_INC.'/functions-api.php' );
require_once( YOURLS_INC.'/functions-kses.php' );
require_once( YOURLS_INC.'/functions-l10n.php' );
require_once( YOURLS_INC.'/functions-compat.php' );
require_once( YOURLS_INC.'/functions-html.php' );
// Allow drop-in replacement for the DB engine
if( file_exists( YOURLS_USERDIR.'/db.php' ) ) {
require_once( YOURLS_USERDIR.'/db.php' );
} else {
require_once( YOURLS_INC.'/class-mysql.php' );
}
// Load auth functions if needed
if( yourls_is_private() )
require_once( YOURLS_INC.'/functions-auth.php' );
// Allow early inclusion of a cache layer
if( file_exists( YOURLS_USERDIR.'/cache.php' ) )
require_once( YOURLS_USERDIR.'/cache.php' );
// Load locale
yourls_load_default_textdomain();
// Check if we are in maintenance mode - if yes, it will die here.
yourls_check_maintenance_mode();
// If request for an admin page is http:// and SSL is required, redirect
if( yourls_is_admin() && yourls_needs_ssl() && !yourls_is_ssl() ) {
if ( 0 === strpos( $_SERVER['REQUEST_URI'], 'http' ) ) {
yourls_redirect( preg_replace( '|^http://|', 'https://', $_SERVER['REQUEST_URI'] ) );
exit();
} else {
yourls_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'] );
exit();
}
}
// Fix REQUEST_URI for IIS
yourls_fix_request_uri();
// Create the YOURLS object $ydb that will contain everything we globally need
global $ydb;
yourls_db_connect();
// Read options right from start
yourls_get_all_options();
// Register shutdown function
register_shutdown_function( 'yourls_shutdown' );
// Core now loaded
yourls_do_action( 'init' ); // plugins can't see this, not loaded yet
// Check if need to redirect to install procedure
if( !yourls_is_installed() && !yourls_is_installing() ) {
yourls_redirect( yourls_admin_url( 'install.php' ), 302 );
}
// Check if upgrade is needed (bypassed if upgrading or installing)
if ( !yourls_is_upgrading() && !yourls_is_installing() ) {
if ( yourls_upgrade_is_needed() ) {
yourls_redirect( YOURLS_SITE .'/admin/upgrade.php', 302 );
}
}
// Init all plugins
yourls_load_plugins();
yourls_do_action( 'plugins_loaded' );
if( yourls_is_admin() )
yourls_do_action( 'admin_init' );

View File

@ -1,78 +1,78 @@
<?php
/**
* Contains Translation_Entry class
*
* @version $Id: entry.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage entry
*/
if ( !class_exists( 'Translation_Entry' ) ):
/**
* Translation_Entry class encapsulates a translatable string
*/
class Translation_Entry {
/**
* Whether the entry contains a string and its plural form, default is false
*
* @var boolean
*/
var $is_plural = false;
var $context = null;
var $singular = null;
var $plural = null;
var $translations = array();
var $translator_comments = '';
var $extracted_comments = '';
var $references = array();
var $flags = array();
/**
* @param array $args associative array, support following keys:
* - singular (string) -- the string to translate, if omitted and empty entry will be created
* - plural (string) -- the plural form of the string, setting this will set {@link $is_plural} to true
* - translations (array) -- translations of the string and possibly -- its plural forms
* - context (string) -- a string differentiating two equal strings used in different contexts
* - translator_comments (string) -- comments left by translators
* - extracted_comments (string) -- comments left by developers
* - references (array) -- places in the code this strings is used, in relative_to_root_path/file.php:linenum form
* - flags (array) -- flags like php-format
*/
function Translation_Entry($args=array()) {
// if no singular -- empty object
if (!isset($args['singular'])) {
return;
}
// get member variable values from args hash
foreach ($args as $varname => $value) {
$this->$varname = $value;
}
if (isset($args['plural'])) $this->is_plural = true;
if (!is_array($this->translations)) $this->translations = array();
if (!is_array($this->references)) $this->references = array();
if (!is_array($this->flags)) $this->flags = array();
}
/**
* Generates a unique key for this entry
*
* @return string|bool the key or false if the entry is empty
*/
function key() {
if (is_null($this->singular)) return false;
// prepend context and EOT, like in MO files
return is_null($this->context)? $this->singular : $this->context.chr(4).$this->singular;
}
function merge_with(&$other) {
$this->flags = array_unique( array_merge( $this->flags, $other->flags ) );
$this->references = array_unique( array_merge( $this->references, $other->references ) );
if ( $this->extracted_comments != $other->extracted_comments ) {
$this->extracted_comments .= $other->extracted_comments;
}
}
}
<?php
/**
* Contains Translation_Entry class
*
* @version $Id: entry.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage entry
*/
if ( !class_exists( 'Translation_Entry' ) ):
/**
* Translation_Entry class encapsulates a translatable string
*/
class Translation_Entry {
/**
* Whether the entry contains a string and its plural form, default is false
*
* @var boolean
*/
var $is_plural = false;
var $context = null;
var $singular = null;
var $plural = null;
var $translations = array();
var $translator_comments = '';
var $extracted_comments = '';
var $references = array();
var $flags = array();
/**
* @param array $args associative array, support following keys:
* - singular (string) -- the string to translate, if omitted and empty entry will be created
* - plural (string) -- the plural form of the string, setting this will set {@link $is_plural} to true
* - translations (array) -- translations of the string and possibly -- its plural forms
* - context (string) -- a string differentiating two equal strings used in different contexts
* - translator_comments (string) -- comments left by translators
* - extracted_comments (string) -- comments left by developers
* - references (array) -- places in the code this strings is used, in relative_to_root_path/file.php:linenum form
* - flags (array) -- flags like php-format
*/
function Translation_Entry($args=array()) {
// if no singular -- empty object
if (!isset($args['singular'])) {
return;
}
// get member variable values from args hash
foreach ($args as $varname => $value) {
$this->$varname = $value;
}
if (isset($args['plural'])) $this->is_plural = true;
if (!is_array($this->translations)) $this->translations = array();
if (!is_array($this->references)) $this->references = array();
if (!is_array($this->flags)) $this->flags = array();
}
/**
* Generates a unique key for this entry
*
* @return string|bool the key or false if the entry is empty
*/
function key() {
if (is_null($this->singular)) return false;
// prepend context and EOT, like in MO files
return is_null($this->context)? $this->singular : $this->context.chr(4).$this->singular;
}
function merge_with(&$other) {
$this->flags = array_unique( array_merge( $this->flags, $other->flags ) );
$this->references = array_unique( array_merge( $this->references, $other->references ) );
if ( $this->extracted_comments != $other->extracted_comments ) {
$this->extracted_comments .= $other->extracted_comments;
}
}
}
endif;

View File

@ -1,257 +1,257 @@
<?php
/**
* Class for working with MO files
*
* @version $Id: mo.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage mo
*/
require_once dirname(__FILE__) . '/translations.php';
require_once dirname(__FILE__) . '/streams.php';
if ( !class_exists( 'MO' ) ):
class MO extends Gettext_Translations {
var $_nplurals = 2;
/**
* Fills up with the entries from MO file $filename
*
* @param string $filename MO file to load
*/
function import_from_file($filename) {
$reader = new POMO_FileReader($filename);
if (!$reader->is_resource())
return false;
return $this->import_from_reader($reader);
}
function export_to_file($filename) {
$fh = fopen($filename, 'wb');
if ( !$fh ) return false;
$res = $this->export_to_file_handle( $fh );
fclose($fh);
return $res;
}
function export() {
$tmp_fh = fopen("php://temp", 'r+');
if ( !$tmp_fh ) return false;
$this->export_to_file_handle( $tmp_fh );
rewind( $tmp_fh );
return stream_get_contents( $tmp_fh );
}
function is_entry_good_for_export( $entry ) {
if ( empty( $entry->translations ) ) {
return false;
}
if ( !array_filter( $entry->translations ) ) {
return false;
}
return true;
}
function export_to_file_handle($fh) {
$entries = array_filter( $this->entries, array( $this, 'is_entry_good_for_export' ) );
ksort($entries);
$magic = 0x950412de;
$revision = 0;
$total = count($entries) + 1; // all the headers are one entry
$originals_lenghts_addr = 28;
$translations_lenghts_addr = $originals_lenghts_addr + 8 * $total;
$size_of_hash = 0;
$hash_addr = $translations_lenghts_addr + 8 * $total;
$current_addr = $hash_addr;
fwrite($fh, pack('V*', $magic, $revision, $total, $originals_lenghts_addr,
$translations_lenghts_addr, $size_of_hash, $hash_addr));
fseek($fh, $originals_lenghts_addr);
// headers' msgid is an empty string
fwrite($fh, pack('VV', 0, $current_addr));
$current_addr++;
$originals_table = chr(0);
foreach($entries as $entry) {
$originals_table .= $this->export_original($entry) . chr(0);
$length = strlen($this->export_original($entry));
fwrite($fh, pack('VV', $length, $current_addr));
$current_addr += $length + 1; // account for the NULL byte after
}
$exported_headers = $this->export_headers();
fwrite($fh, pack('VV', strlen($exported_headers), $current_addr));
$current_addr += strlen($exported_headers) + 1;
$translations_table = $exported_headers . chr(0);
foreach($entries as $entry) {
$translations_table .= $this->export_translations($entry) . chr(0);
$length = strlen($this->export_translations($entry));
fwrite($fh, pack('VV', $length, $current_addr));
$current_addr += $length + 1;
}
fwrite($fh, $originals_table);
fwrite($fh, $translations_table);
return true;
}
function export_original($entry) {
//TODO: warnings for control characters
$exported = $entry->singular;
if ($entry->is_plural) $exported .= chr(0).$entry->plural;
if (!is_null($entry->context)) $exported = $entry->context . chr(4) . $exported;
return $exported;
}
function export_translations($entry) {
//TODO: warnings for control characters
return implode(chr(0), $entry->translations);
}
function export_headers() {
$exported = '';
foreach($this->headers as $header => $value) {
$exported.= "$header: $value\n";
}
return $exported;
}
function get_byteorder($magic) {
// The magic is 0x950412de
// bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565
$magic_little = (int) - 1794895138;
$magic_little_64 = (int) 2500072158;
// 0xde120495
$magic_big = ((int) - 569244523) & 0xFFFFFFFF;
if ($magic_little == $magic || $magic_little_64 == $magic) {
return 'little';
} else if ($magic_big == $magic) {
return 'big';
} else {
return false;
}
}
function import_from_reader($reader) {
$endian_string = MO::get_byteorder($reader->readint32());
if (false === $endian_string) {
return false;
}
$reader->setEndian($endian_string);
$endian = ('big' == $endian_string)? 'N' : 'V';
$header = $reader->read(24);
if ($reader->strlen($header) != 24)
return false;
// parse header
$header = unpack("{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header);
if (!is_array($header))
return false;
extract( $header );
// support revision 0 of MO format specs, only
if ($revision != 0)
return false;
// seek to data blocks
$reader->seekto($originals_lenghts_addr);
// read originals' indices
$originals_lengths_length = $translations_lenghts_addr - $originals_lenghts_addr;
if ( $originals_lengths_length != $total * 8 )
return false;
$originals = $reader->read($originals_lengths_length);
if ( $reader->strlen( $originals ) != $originals_lengths_length )
return false;
// read translations' indices
$translations_lenghts_length = $hash_addr - $translations_lenghts_addr;
if ( $translations_lenghts_length != $total * 8 )
return false;
$translations = $reader->read($translations_lenghts_length);
if ( $reader->strlen( $translations ) != $translations_lenghts_length )
return false;
// transform raw data into set of indices
$originals = $reader->str_split( $originals, 8 );
$translations = $reader->str_split( $translations, 8 );
// skip hash table
$strings_addr = $hash_addr + $hash_length * 4;
$reader->seekto($strings_addr);
$strings = $reader->read_all();
$reader->close();
for ( $i = 0; $i < $total; $i++ ) {
$o = unpack( "{$endian}length/{$endian}pos", $originals[$i] );
$t = unpack( "{$endian}length/{$endian}pos", $translations[$i] );
if ( !$o || !$t ) return false;
// adjust offset due to reading strings to separate space before
$o['pos'] -= $strings_addr;
$t['pos'] -= $strings_addr;
$original = $reader->substr( $strings, $o['pos'], $o['length'] );
$translation = $reader->substr( $strings, $t['pos'], $t['length'] );
if ('' === $original) {
$this->set_headers($this->make_headers($translation));
} else {
$entry = &$this->make_entry($original, $translation);
$this->entries[$entry->key()] = &$entry;
}
}
return true;
}
/**
* Build a Translation_Entry from original string and translation strings,
* found in a MO file
*
* @static
* @param string $original original string to translate from MO file. Might contain
* 0x04 as context separator or 0x00 as singular/plural separator
* @param string $translation translation string from MO file. Might contain
* 0x00 as a plural translations separator
*/
function &make_entry($original, $translation) {
$entry = new Translation_Entry();
// look for context
$parts = explode(chr(4), $original);
if (isset($parts[1])) {
$original = $parts[1];
$entry->context = $parts[0];
}
// look for plural original
$parts = explode(chr(0), $original);
$entry->singular = $parts[0];
if (isset($parts[1])) {
$entry->is_plural = true;
$entry->plural = $parts[1];
}
// plural translations are also separated by \0
$entry->translations = explode(chr(0), $translation);
return $entry;
}
function select_plural_form($count) {
return $this->gettext_select_plural_form($count);
}
function get_plural_forms_count() {
return $this->_nplurals;
}
}
<?php
/**
* Class for working with MO files
*
* @version $Id: mo.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage mo
*/
require_once dirname(__FILE__) . '/translations.php';
require_once dirname(__FILE__) . '/streams.php';
if ( !class_exists( 'MO' ) ):
class MO extends Gettext_Translations {
var $_nplurals = 2;
/**
* Fills up with the entries from MO file $filename
*
* @param string $filename MO file to load
*/
function import_from_file($filename) {
$reader = new POMO_FileReader($filename);
if (!$reader->is_resource())
return false;
return $this->import_from_reader($reader);
}
function export_to_file($filename) {
$fh = fopen($filename, 'wb');
if ( !$fh ) return false;
$res = $this->export_to_file_handle( $fh );
fclose($fh);
return $res;
}
function export() {
$tmp_fh = fopen("php://temp", 'r+');
if ( !$tmp_fh ) return false;
$this->export_to_file_handle( $tmp_fh );
rewind( $tmp_fh );
return stream_get_contents( $tmp_fh );
}
function is_entry_good_for_export( $entry ) {
if ( empty( $entry->translations ) ) {
return false;
}
if ( !array_filter( $entry->translations ) ) {
return false;
}
return true;
}
function export_to_file_handle($fh) {
$entries = array_filter( $this->entries, array( $this, 'is_entry_good_for_export' ) );
ksort($entries);
$magic = 0x950412de;
$revision = 0;
$total = count($entries) + 1; // all the headers are one entry
$originals_lenghts_addr = 28;
$translations_lenghts_addr = $originals_lenghts_addr + 8 * $total;
$size_of_hash = 0;
$hash_addr = $translations_lenghts_addr + 8 * $total;
$current_addr = $hash_addr;
fwrite($fh, pack('V*', $magic, $revision, $total, $originals_lenghts_addr,
$translations_lenghts_addr, $size_of_hash, $hash_addr));
fseek($fh, $originals_lenghts_addr);
// headers' msgid is an empty string
fwrite($fh, pack('VV', 0, $current_addr));
$current_addr++;
$originals_table = chr(0);
foreach($entries as $entry) {
$originals_table .= $this->export_original($entry) . chr(0);
$length = strlen($this->export_original($entry));
fwrite($fh, pack('VV', $length, $current_addr));
$current_addr += $length + 1; // account for the NULL byte after
}
$exported_headers = $this->export_headers();
fwrite($fh, pack('VV', strlen($exported_headers), $current_addr));
$current_addr += strlen($exported_headers) + 1;
$translations_table = $exported_headers . chr(0);
foreach($entries as $entry) {
$translations_table .= $this->export_translations($entry) . chr(0);
$length = strlen($this->export_translations($entry));
fwrite($fh, pack('VV', $length, $current_addr));
$current_addr += $length + 1;
}
fwrite($fh, $originals_table);
fwrite($fh, $translations_table);
return true;
}
function export_original($entry) {
//TODO: warnings for control characters
$exported = $entry->singular;
if ($entry->is_plural) $exported .= chr(0).$entry->plural;
if (!is_null($entry->context)) $exported = $entry->context . chr(4) . $exported;
return $exported;
}
function export_translations($entry) {
//TODO: warnings for control characters
return implode(chr(0), $entry->translations);
}
function export_headers() {
$exported = '';
foreach($this->headers as $header => $value) {
$exported.= "$header: $value\n";
}
return $exported;
}
function get_byteorder($magic) {
// The magic is 0x950412de
// bug in PHP 5.0.2, see https://savannah.nongnu.org/bugs/?func=detailitem&item_id=10565
$magic_little = (int) - 1794895138;
$magic_little_64 = (int) 2500072158;
// 0xde120495
$magic_big = ((int) - 569244523) & 0xFFFFFFFF;
if ($magic_little == $magic || $magic_little_64 == $magic) {
return 'little';
} else if ($magic_big == $magic) {
return 'big';
} else {
return false;
}
}
function import_from_reader($reader) {
$endian_string = MO::get_byteorder($reader->readint32());
if (false === $endian_string) {
return false;
}
$reader->setEndian($endian_string);
$endian = ('big' == $endian_string)? 'N' : 'V';
$header = $reader->read(24);
if ($reader->strlen($header) != 24)
return false;
// parse header
$header = unpack("{$endian}revision/{$endian}total/{$endian}originals_lenghts_addr/{$endian}translations_lenghts_addr/{$endian}hash_length/{$endian}hash_addr", $header);
if (!is_array($header))
return false;
extract( $header );
// support revision 0 of MO format specs, only
if ($revision != 0)
return false;
// seek to data blocks
$reader->seekto($originals_lenghts_addr);
// read originals' indices
$originals_lengths_length = $translations_lenghts_addr - $originals_lenghts_addr;
if ( $originals_lengths_length != $total * 8 )
return false;
$originals = $reader->read($originals_lengths_length);
if ( $reader->strlen( $originals ) != $originals_lengths_length )
return false;
// read translations' indices
$translations_lenghts_length = $hash_addr - $translations_lenghts_addr;
if ( $translations_lenghts_length != $total * 8 )
return false;
$translations = $reader->read($translations_lenghts_length);
if ( $reader->strlen( $translations ) != $translations_lenghts_length )
return false;
// transform raw data into set of indices
$originals = $reader->str_split( $originals, 8 );
$translations = $reader->str_split( $translations, 8 );
// skip hash table
$strings_addr = $hash_addr + $hash_length * 4;
$reader->seekto($strings_addr);
$strings = $reader->read_all();
$reader->close();
for ( $i = 0; $i < $total; $i++ ) {
$o = unpack( "{$endian}length/{$endian}pos", $originals[$i] );
$t = unpack( "{$endian}length/{$endian}pos", $translations[$i] );
if ( !$o || !$t ) return false;
// adjust offset due to reading strings to separate space before
$o['pos'] -= $strings_addr;
$t['pos'] -= $strings_addr;
$original = $reader->substr( $strings, $o['pos'], $o['length'] );
$translation = $reader->substr( $strings, $t['pos'], $t['length'] );
if ('' === $original) {
$this->set_headers($this->make_headers($translation));
} else {
$entry = &$this->make_entry($original, $translation);
$this->entries[$entry->key()] = &$entry;
}
}
return true;
}
/**
* Build a Translation_Entry from original string and translation strings,
* found in a MO file
*
* @static
* @param string $original original string to translate from MO file. Might contain
* 0x04 as context separator or 0x00 as singular/plural separator
* @param string $translation translation string from MO file. Might contain
* 0x00 as a plural translations separator
*/
function &make_entry($original, $translation) {
$entry = new Translation_Entry();
// look for context
$parts = explode(chr(4), $original);
if (isset($parts[1])) {
$original = $parts[1];
$entry->context = $parts[0];
}
// look for plural original
$parts = explode(chr(0), $original);
$entry->singular = $parts[0];
if (isset($parts[1])) {
$entry->is_plural = true;
$entry->plural = $parts[1];
}
// plural translations are also separated by \0
$entry->translations = explode(chr(0), $translation);
return $entry;
}
function select_plural_form($count) {
return $this->gettext_select_plural_form($count);
}
function get_plural_forms_count() {
return $this->_nplurals;
}
}
endif;

View File

@ -1,384 +1,384 @@
<?php
/**
* Class for working with PO files
*
* @version $Id: po.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage po
*/
require_once dirname(__FILE__) . '/translations.php';
define('PO_MAX_LINE_LEN', 79);
ini_set('auto_detect_line_endings', 1);
/**
* Routines for working with PO files
*/
if ( !class_exists( 'PO' ) ):
class PO extends Gettext_Translations {
var $comments_before_headers = '';
/**
* Exports headers to a PO entry
*
* @return string msgid/msgstr PO entry for this PO file headers, doesn't contain newline at the end
*/
function export_headers() {
$header_string = '';
foreach($this->headers as $header => $value) {
$header_string.= "$header: $value\n";
}
$poified = PO::poify($header_string);
if ($this->comments_before_headers)
$before_headers = $this->prepend_each_line(rtrim($this->comments_before_headers)."\n", '# ');
else
$before_headers = '';
return rtrim("{$before_headers}msgid \"\"\nmsgstr $poified");
}
/**
* Exports all entries to PO format
*
* @return string sequence of mgsgid/msgstr PO strings, doesn't containt newline at the end
*/
function export_entries() {
//TODO sorting
return implode("\n\n", array_map(array('PO', 'export_entry'), $this->entries));
}
/**
* Exports the whole PO file as a string
*
* @param bool $include_headers whether to include the headers in the export
* @return string ready for inclusion in PO file string for headers and all the enrtries
*/
function export($include_headers = true) {
$res = '';
if ($include_headers) {
$res .= $this->export_headers();
$res .= "\n\n";
}
$res .= $this->export_entries();
return $res;
}
/**
* Same as {@link export}, but writes the result to a file
*
* @param string $filename where to write the PO string
* @param bool $include_headers whether to include tje headers in the export
* @return bool true on success, false on error
*/
function export_to_file($filename, $include_headers = true) {
$fh = fopen($filename, 'w');
if (false === $fh) return false;
$export = $this->export($include_headers);
$res = fwrite($fh, $export);
if (false === $res) return false;
return fclose($fh);
}
/**
* Text to include as a comment before the start of the PO contents
*
* Doesn't need to include # in the beginning of lines, these are added automatically
*/
function set_comment_before_headers( $text ) {
$this->comments_before_headers = $text;
}
/**
* Formats a string in PO-style
*
* @static
* @param string $string the string to format
* @return string the poified string
*/
function poify($string) {
$quote = '"';
$slash = '\\';
$newline = "\n";
$replaces = array(
"$slash" => "$slash$slash",
"$quote" => "$slash$quote",
"\t" => '\t',
);
$string = str_replace(array_keys($replaces), array_values($replaces), $string);
$po = $quote.implode("${slash}n$quote$newline$quote", explode($newline, $string)).$quote;
// add empty string on first line for readbility
if (false !== strpos($string, $newline) &&
(substr_count($string, $newline) > 1 || !($newline === substr($string, -strlen($newline))))) {
$po = "$quote$quote$newline$po";
}
// remove empty strings
$po = str_replace("$newline$quote$quote", '', $po);
return $po;
}
/**
* Gives back the original string from a PO-formatted string
*
* @static
* @param string $string PO-formatted string
* @return string enascaped string
*/
function unpoify($string) {
$escapes = array('t' => "\t", 'n' => "\n", '\\' => '\\');
$lines = array_map('trim', explode("\n", $string));
$lines = array_map(array('PO', 'trim_quotes'), $lines);
$unpoified = '';
$previous_is_backslash = false;
foreach($lines as $line) {
preg_match_all('/./u', $line, $chars);
$chars = $chars[0];
foreach($chars as $char) {
if (!$previous_is_backslash) {
if ('\\' == $char)
$previous_is_backslash = true;
else
$unpoified .= $char;
} else {
$previous_is_backslash = false;
$unpoified .= isset($escapes[$char])? $escapes[$char] : $char;
}
}
}
return $unpoified;
}
/**
* Inserts $with in the beginning of every new line of $string and
* returns the modified string
*
* @static
* @param string $string prepend lines in this string
* @param string $with prepend lines with this string
*/
function prepend_each_line($string, $with) {
$php_with = var_export($with, true);
$lines = explode("\n", $string);
// do not prepend the string on the last empty line, artefact by explode
if ("\n" == substr($string, -1)) unset($lines[count($lines) - 1]);
$res = implode("\n", array_map(create_function('$x', "return $php_with.\$x;"), $lines));
// give back the empty line, we ignored above
if ("\n" == substr($string, -1)) $res .= "\n";
return $res;
}
/**
* Prepare a text as a comment -- wraps the lines and prepends #
* and a special character to each line
*
* @access private
* @param string $text the comment text
* @param string $char character to denote a special PO comment,
* like :, default is a space
*/
function comment_block($text, $char=' ') {
$text = wordwrap($text, PO_MAX_LINE_LEN - 3);
return PO::prepend_each_line($text, "#$char ");
}
/**
* Builds a string from the entry for inclusion in PO file
*
* @static
* @param object &$entry the entry to convert to po string
* @return string|bool PO-style formatted string for the entry or
* false if the entry is empty
*/
function export_entry(&$entry) {
if (is_null($entry->singular)) return false;
$po = array();
if (!empty($entry->translator_comments)) $po[] = PO::comment_block($entry->translator_comments);
if (!empty($entry->extracted_comments)) $po[] = PO::comment_block($entry->extracted_comments, '.');
if (!empty($entry->references)) $po[] = PO::comment_block(implode(' ', $entry->references), ':');
if (!empty($entry->flags)) $po[] = PO::comment_block(implode(", ", $entry->flags), ',');
if (!is_null($entry->context)) $po[] = 'msgctxt '.PO::poify($entry->context);
$po[] = 'msgid '.PO::poify($entry->singular);
if (!$entry->is_plural) {
$translation = empty($entry->translations)? '' : $entry->translations[0];
$po[] = 'msgstr '.PO::poify($translation);
} else {
$po[] = 'msgid_plural '.PO::poify($entry->plural);
$translations = empty($entry->translations)? array('', '') : $entry->translations;
foreach($translations as $i => $translation) {
$po[] = "msgstr[$i] ".PO::poify($translation);
}
}
return implode("\n", $po);
}
function import_from_file($filename) {
$f = fopen($filename, 'r');
if (!$f) return false;
$lineno = 0;
while (true) {
$res = $this->read_entry($f, $lineno);
if (!$res) break;
if ($res['entry']->singular == '') {
$this->set_headers($this->make_headers($res['entry']->translations[0]));
} else {
$this->add_entry($res['entry']);
}
}
PO::read_line($f, 'clear');
if ( false === $res ) {
return false;
}
if ( ! $this->headers && ! $this->entries ) {
return false;
}
return true;
}
function read_entry($f, $lineno = 0) {
$entry = new Translation_Entry();
// where were we in the last step
// can be: comment, msgctxt, msgid, msgid_plural, msgstr, msgstr_plural
$context = '';
$msgstr_index = 0;
$is_final = create_function('$context', 'return $context == "msgstr" || $context == "msgstr_plural";');
while (true) {
$lineno++;
$line = PO::read_line($f);
if (!$line) {
if (feof($f)) {
if ($is_final($context))
break;
elseif (!$context) // we haven't read a line and eof came
return null;
else
return false;
} else {
return false;
}
}
if ($line == "\n") continue;
$line = trim($line);
if (preg_match('/^#/', $line, $m)) {
// the comment is the start of a new entry
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
// comments have to be at the beginning
if ($context && $context != 'comment') {
return false;
}
// add comment
$this->add_comment_to_entry($entry, $line);;
} elseif (preg_match('/^msgctxt\s+(".*")/', $line, $m)) {
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
if ($context && $context != 'comment') {
return false;
}
$context = 'msgctxt';
$entry->context .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgid\s+(".*")/', $line, $m)) {
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
if ($context && $context != 'msgctxt' && $context != 'comment') {
return false;
}
$context = 'msgid';
$entry->singular .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgid_plural\s+(".*")/', $line, $m)) {
if ($context != 'msgid') {
return false;
}
$context = 'msgid_plural';
$entry->is_plural = true;
$entry->plural .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgstr\s+(".*")/', $line, $m)) {
if ($context != 'msgid') {
return false;
}
$context = 'msgstr';
$entry->translations = array(PO::unpoify($m[1]));
} elseif (preg_match('/^msgstr\[(\d+)\]\s+(".*")/', $line, $m)) {
if ($context != 'msgid_plural' && $context != 'msgstr_plural') {
return false;
}
$context = 'msgstr_plural';
$msgstr_index = $m[1];
$entry->translations[$m[1]] = PO::unpoify($m[2]);
} elseif (preg_match('/^".*"$/', $line)) {
$unpoified = PO::unpoify($line);
switch ($context) {
case 'msgid':
$entry->singular .= $unpoified; break;
case 'msgctxt':
$entry->context .= $unpoified; break;
case 'msgid_plural':
$entry->plural .= $unpoified; break;
case 'msgstr':
$entry->translations[0] .= $unpoified; break;
case 'msgstr_plural':
$entry->translations[$msgstr_index] .= $unpoified; break;
default:
return false;
}
} else {
return false;
}
}
if (array() == array_filter($entry->translations, create_function('$t', 'return $t || "0" === $t;'))) {
$entry->translations = array();
}
return array('entry' => $entry, 'lineno' => $lineno);
}
function read_line($f, $action = 'read') {
static $last_line = '';
static $use_last_line = false;
if ('clear' == $action) {
$last_line = '';
return true;
}
if ('put-back' == $action) {
$use_last_line = true;
return true;
}
$line = $use_last_line? $last_line : fgets($f);
$line = ( "\r\n" == substr( $line, -2 ) ) ? rtrim( $line, "\r\n" ) . "\n" : $line;
$last_line = $line;
$use_last_line = false;
return $line;
}
function add_comment_to_entry(&$entry, $po_comment_line) {
$first_two = substr($po_comment_line, 0, 2);
$comment = trim(substr($po_comment_line, 2));
if ('#:' == $first_two) {
$entry->references = array_merge($entry->references, preg_split('/\s+/', $comment));
} elseif ('#.' == $first_two) {
$entry->extracted_comments = trim($entry->extracted_comments . "\n" . $comment);
} elseif ('#,' == $first_two) {
$entry->flags = array_merge($entry->flags, preg_split('/,\s*/', $comment));
} else {
$entry->translator_comments = trim($entry->translator_comments . "\n" . $comment);
}
}
function trim_quotes($s) {
if ( substr($s, 0, 1) == '"') $s = substr($s, 1);
if ( substr($s, -1, 1) == '"') $s = substr($s, 0, -1);
return $s;
}
}
endif;
<?php
/**
* Class for working with PO files
*
* @version $Id: po.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage po
*/
require_once dirname(__FILE__) . '/translations.php';
define('PO_MAX_LINE_LEN', 79);
ini_set('auto_detect_line_endings', 1);
/**
* Routines for working with PO files
*/
if ( !class_exists( 'PO' ) ):
class PO extends Gettext_Translations {
var $comments_before_headers = '';
/**
* Exports headers to a PO entry
*
* @return string msgid/msgstr PO entry for this PO file headers, doesn't contain newline at the end
*/
function export_headers() {
$header_string = '';
foreach($this->headers as $header => $value) {
$header_string.= "$header: $value\n";
}
$poified = PO::poify($header_string);
if ($this->comments_before_headers)
$before_headers = $this->prepend_each_line(rtrim($this->comments_before_headers)."\n", '# ');
else
$before_headers = '';
return rtrim("{$before_headers}msgid \"\"\nmsgstr $poified");
}
/**
* Exports all entries to PO format
*
* @return string sequence of mgsgid/msgstr PO strings, doesn't containt newline at the end
*/
function export_entries() {
//TODO sorting
return implode("\n\n", array_map(array('PO', 'export_entry'), $this->entries));
}
/**
* Exports the whole PO file as a string
*
* @param bool $include_headers whether to include the headers in the export
* @return string ready for inclusion in PO file string for headers and all the enrtries
*/
function export($include_headers = true) {
$res = '';
if ($include_headers) {
$res .= $this->export_headers();
$res .= "\n\n";
}
$res .= $this->export_entries();
return $res;
}
/**
* Same as {@link export}, but writes the result to a file
*
* @param string $filename where to write the PO string
* @param bool $include_headers whether to include tje headers in the export
* @return bool true on success, false on error
*/
function export_to_file($filename, $include_headers = true) {
$fh = fopen($filename, 'w');
if (false === $fh) return false;
$export = $this->export($include_headers);
$res = fwrite($fh, $export);
if (false === $res) return false;
return fclose($fh);
}
/**
* Text to include as a comment before the start of the PO contents
*
* Doesn't need to include # in the beginning of lines, these are added automatically
*/
function set_comment_before_headers( $text ) {
$this->comments_before_headers = $text;
}
/**
* Formats a string in PO-style
*
* @static
* @param string $string the string to format
* @return string the poified string
*/
function poify($string) {
$quote = '"';
$slash = '\\';
$newline = "\n";
$replaces = array(
"$slash" => "$slash$slash",
"$quote" => "$slash$quote",
"\t" => '\t',
);
$string = str_replace(array_keys($replaces), array_values($replaces), $string);
$po = $quote.implode("${slash}n$quote$newline$quote", explode($newline, $string)).$quote;
// add empty string on first line for readbility
if (false !== strpos($string, $newline) &&
(substr_count($string, $newline) > 1 || !($newline === substr($string, -strlen($newline))))) {
$po = "$quote$quote$newline$po";
}
// remove empty strings
$po = str_replace("$newline$quote$quote", '', $po);
return $po;
}
/**
* Gives back the original string from a PO-formatted string
*
* @static
* @param string $string PO-formatted string
* @return string enascaped string
*/
function unpoify($string) {
$escapes = array('t' => "\t", 'n' => "\n", '\\' => '\\');
$lines = array_map('trim', explode("\n", $string));
$lines = array_map(array('PO', 'trim_quotes'), $lines);
$unpoified = '';
$previous_is_backslash = false;
foreach($lines as $line) {
preg_match_all('/./u', $line, $chars);
$chars = $chars[0];
foreach($chars as $char) {
if (!$previous_is_backslash) {
if ('\\' == $char)
$previous_is_backslash = true;
else
$unpoified .= $char;
} else {
$previous_is_backslash = false;
$unpoified .= isset($escapes[$char])? $escapes[$char] : $char;
}
}
}
return $unpoified;
}
/**
* Inserts $with in the beginning of every new line of $string and
* returns the modified string
*
* @static
* @param string $string prepend lines in this string
* @param string $with prepend lines with this string
*/
function prepend_each_line($string, $with) {
$php_with = var_export($with, true);
$lines = explode("\n", $string);
// do not prepend the string on the last empty line, artefact by explode
if ("\n" == substr($string, -1)) unset($lines[count($lines) - 1]);
$res = implode("\n", array_map(create_function('$x', "return $php_with.\$x;"), $lines));
// give back the empty line, we ignored above
if ("\n" == substr($string, -1)) $res .= "\n";
return $res;
}
/**
* Prepare a text as a comment -- wraps the lines and prepends #
* and a special character to each line
*
* @access private
* @param string $text the comment text
* @param string $char character to denote a special PO comment,
* like :, default is a space
*/
function comment_block($text, $char=' ') {
$text = wordwrap($text, PO_MAX_LINE_LEN - 3);
return PO::prepend_each_line($text, "#$char ");
}
/**
* Builds a string from the entry for inclusion in PO file
*
* @static
* @param object &$entry the entry to convert to po string
* @return string|bool PO-style formatted string for the entry or
* false if the entry is empty
*/
function export_entry(&$entry) {
if (is_null($entry->singular)) return false;
$po = array();
if (!empty($entry->translator_comments)) $po[] = PO::comment_block($entry->translator_comments);
if (!empty($entry->extracted_comments)) $po[] = PO::comment_block($entry->extracted_comments, '.');
if (!empty($entry->references)) $po[] = PO::comment_block(implode(' ', $entry->references), ':');
if (!empty($entry->flags)) $po[] = PO::comment_block(implode(", ", $entry->flags), ',');
if (!is_null($entry->context)) $po[] = 'msgctxt '.PO::poify($entry->context);
$po[] = 'msgid '.PO::poify($entry->singular);
if (!$entry->is_plural) {
$translation = empty($entry->translations)? '' : $entry->translations[0];
$po[] = 'msgstr '.PO::poify($translation);
} else {
$po[] = 'msgid_plural '.PO::poify($entry->plural);
$translations = empty($entry->translations)? array('', '') : $entry->translations;
foreach($translations as $i => $translation) {
$po[] = "msgstr[$i] ".PO::poify($translation);
}
}
return implode("\n", $po);
}
function import_from_file($filename) {
$f = fopen($filename, 'r');
if (!$f) return false;
$lineno = 0;
while (true) {
$res = $this->read_entry($f, $lineno);
if (!$res) break;
if ($res['entry']->singular == '') {
$this->set_headers($this->make_headers($res['entry']->translations[0]));
} else {
$this->add_entry($res['entry']);
}
}
PO::read_line($f, 'clear');
if ( false === $res ) {
return false;
}
if ( ! $this->headers && ! $this->entries ) {
return false;
}
return true;
}
function read_entry($f, $lineno = 0) {
$entry = new Translation_Entry();
// where were we in the last step
// can be: comment, msgctxt, msgid, msgid_plural, msgstr, msgstr_plural
$context = '';
$msgstr_index = 0;
$is_final = create_function('$context', 'return $context == "msgstr" || $context == "msgstr_plural";');
while (true) {
$lineno++;
$line = PO::read_line($f);
if (!$line) {
if (feof($f)) {
if ($is_final($context))
break;
elseif (!$context) // we haven't read a line and eof came
return null;
else
return false;
} else {
return false;
}
}
if ($line == "\n") continue;
$line = trim($line);
if (preg_match('/^#/', $line, $m)) {
// the comment is the start of a new entry
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
// comments have to be at the beginning
if ($context && $context != 'comment') {
return false;
}
// add comment
$this->add_comment_to_entry($entry, $line);;
} elseif (preg_match('/^msgctxt\s+(".*")/', $line, $m)) {
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
if ($context && $context != 'comment') {
return false;
}
$context = 'msgctxt';
$entry->context .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgid\s+(".*")/', $line, $m)) {
if ($is_final($context)) {
PO::read_line($f, 'put-back');
$lineno--;
break;
}
if ($context && $context != 'msgctxt' && $context != 'comment') {
return false;
}
$context = 'msgid';
$entry->singular .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgid_plural\s+(".*")/', $line, $m)) {
if ($context != 'msgid') {
return false;
}
$context = 'msgid_plural';
$entry->is_plural = true;
$entry->plural .= PO::unpoify($m[1]);
} elseif (preg_match('/^msgstr\s+(".*")/', $line, $m)) {
if ($context != 'msgid') {
return false;
}
$context = 'msgstr';
$entry->translations = array(PO::unpoify($m[1]));
} elseif (preg_match('/^msgstr\[(\d+)\]\s+(".*")/', $line, $m)) {
if ($context != 'msgid_plural' && $context != 'msgstr_plural') {
return false;
}
$context = 'msgstr_plural';
$msgstr_index = $m[1];
$entry->translations[$m[1]] = PO::unpoify($m[2]);
} elseif (preg_match('/^".*"$/', $line)) {
$unpoified = PO::unpoify($line);
switch ($context) {
case 'msgid':
$entry->singular .= $unpoified; break;
case 'msgctxt':
$entry->context .= $unpoified; break;
case 'msgid_plural':
$entry->plural .= $unpoified; break;
case 'msgstr':
$entry->translations[0] .= $unpoified; break;
case 'msgstr_plural':
$entry->translations[$msgstr_index] .= $unpoified; break;
default:
return false;
}
} else {
return false;
}
}
if (array() == array_filter($entry->translations, create_function('$t', 'return $t || "0" === $t;'))) {
$entry->translations = array();
}
return array('entry' => $entry, 'lineno' => $lineno);
}
function read_line($f, $action = 'read') {
static $last_line = '';
static $use_last_line = false;
if ('clear' == $action) {
$last_line = '';
return true;
}
if ('put-back' == $action) {
$use_last_line = true;
return true;
}
$line = $use_last_line? $last_line : fgets($f);
$line = ( "\r\n" == substr( $line, -2 ) ) ? rtrim( $line, "\r\n" ) . "\n" : $line;
$last_line = $line;
$use_last_line = false;
return $line;
}
function add_comment_to_entry(&$entry, $po_comment_line) {
$first_two = substr($po_comment_line, 0, 2);
$comment = trim(substr($po_comment_line, 2));
if ('#:' == $first_two) {
$entry->references = array_merge($entry->references, preg_split('/\s+/', $comment));
} elseif ('#.' == $first_two) {
$entry->extracted_comments = trim($entry->extracted_comments . "\n" . $comment);
} elseif ('#,' == $first_two) {
$entry->flags = array_merge($entry->flags, preg_split('/,\s*/', $comment));
} else {
$entry->translator_comments = trim($entry->translator_comments . "\n" . $comment);
}
}
function trim_quotes($s) {
if ( substr($s, 0, 1) == '"') $s = substr($s, 1);
if ( substr($s, -1, 1) == '"') $s = substr($s, 0, -1);
return $s;
}
}
endif;

View File

@ -1,209 +1,209 @@
<?php
/**
* Classes, which help reading streams of data from files.
* Based on the classes from Danilo Segan <danilo@kvota.net>
*
* @version $Id: streams.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage streams
*/
if ( !class_exists( 'POMO_Reader' ) ):
class POMO_Reader {
var $endian = 'little';
var $_post = '';
function POMO_Reader() {
$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr');
$this->_pos = 0;
}
/**
* Sets the endianness of the file.
*
* @param $endian string 'big' or 'little'
*/
function setEndian($endian) {
$this->endian = $endian;
}
/**
* Reads a 32bit Integer from the Stream
*
* @return mixed The integer, corresponding to the next 32 bits from
* the stream of false if there are not enough bytes or on error
*/
function readint32() {
$bytes = $this->read(4);
if (4 != $this->strlen($bytes))
return false;
$endian_letter = ('big' == $this->endian)? 'N' : 'V';
$int = unpack($endian_letter, $bytes);
return array_shift($int);
}
/**
* Reads an array of 32-bit Integers from the Stream
*
* @param integer count How many elements should be read
* @return mixed Array of integers or false if there isn't
* enough data or on error
*/
function readint32array($count) {
$bytes = $this->read(4 * $count);
if (4*$count != $this->strlen($bytes))
return false;
$endian_letter = ('big' == $this->endian)? 'N' : 'V';
return unpack($endian_letter.$count, $bytes);
}
function substr($string, $start, $length) {
if ($this->is_overloaded) {
return mb_substr($string, $start, $length, 'ascii');
} else {
return substr($string, $start, $length);
}
}
function strlen($string) {
if ($this->is_overloaded) {
return mb_strlen($string, 'ascii');
} else {
return strlen($string);
}
}
function str_split($string, $chunk_size) {
if (!function_exists('str_split')) {
$length = $this->strlen($string);
$out = array();
for ($i = 0; $i < $length; $i += $chunk_size)
$out[] = $this->substr($string, $i, $chunk_size);
return $out;
} else {
return str_split( $string, $chunk_size );
}
}
function pos() {
return $this->_pos;
}
function is_resource() {
return true;
}
function close() {
return true;
}
}
endif;
if ( !class_exists( 'POMO_FileReader' ) ):
class POMO_FileReader extends POMO_Reader {
function POMO_FileReader($filename) {
parent::POMO_Reader();
$this->_f = fopen($filename, 'rb');
}
function read($bytes) {
return fread($this->_f, $bytes);
}
function seekto($pos) {
if ( -1 == fseek($this->_f, $pos, SEEK_SET)) {
return false;
}
$this->_pos = $pos;
return true;
}
function is_resource() {
return is_resource($this->_f);
}
function feof() {
return feof($this->_f);
}
function close() {
return fclose($this->_f);
}
function read_all() {
$all = '';
while ( !$this->feof() )
$all .= $this->read(4096);
return $all;
}
}
endif;
if ( !class_exists( 'POMO_StringReader' ) ):
/**
* Provides file-like methods for manipulating a string instead
* of a physical file.
*/
class POMO_StringReader extends POMO_Reader {
var $_str = '';
function POMO_StringReader($str = '') {
parent::POMO_Reader();
$this->_str = $str;
$this->_pos = 0;
}
function read($bytes) {
$data = $this->substr($this->_str, $this->_pos, $bytes);
$this->_pos += $bytes;
if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str);
return $data;
}
function seekto($pos) {
$this->_pos = $pos;
if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str);
return $this->_pos;
}
function length() {
return $this->strlen($this->_str);
}
function read_all() {
return $this->substr($this->_str, $this->_pos, $this->strlen($this->_str));
}
}
endif;
if ( !class_exists( 'POMO_CachedFileReader' ) ):
/**
* Reads the contents of the file in the beginning.
*/
class POMO_CachedFileReader extends POMO_StringReader {
function POMO_CachedFileReader($filename) {
parent::POMO_StringReader();
$this->_str = file_get_contents($filename);
if (false === $this->_str)
return false;
$this->_pos = 0;
}
}
endif;
if ( !class_exists( 'POMO_CachedIntFileReader' ) ):
/**
* Reads the contents of the file in the beginning.
*/
class POMO_CachedIntFileReader extends POMO_CachedFileReader {
function POMO_CachedIntFileReader($filename) {
parent::POMO_CachedFileReader($filename);
}
}
<?php
/**
* Classes, which help reading streams of data from files.
* Based on the classes from Danilo Segan <danilo@kvota.net>
*
* @version $Id: streams.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage streams
*/
if ( !class_exists( 'POMO_Reader' ) ):
class POMO_Reader {
var $endian = 'little';
var $_post = '';
function POMO_Reader() {
$this->is_overloaded = ((ini_get("mbstring.func_overload") & 2) != 0) && function_exists('mb_substr');
$this->_pos = 0;
}
/**
* Sets the endianness of the file.
*
* @param $endian string 'big' or 'little'
*/
function setEndian($endian) {
$this->endian = $endian;
}
/**
* Reads a 32bit Integer from the Stream
*
* @return mixed The integer, corresponding to the next 32 bits from
* the stream of false if there are not enough bytes or on error
*/
function readint32() {
$bytes = $this->read(4);
if (4 != $this->strlen($bytes))
return false;
$endian_letter = ('big' == $this->endian)? 'N' : 'V';
$int = unpack($endian_letter, $bytes);
return array_shift($int);
}
/**
* Reads an array of 32-bit Integers from the Stream
*
* @param integer count How many elements should be read
* @return mixed Array of integers or false if there isn't
* enough data or on error
*/
function readint32array($count) {
$bytes = $this->read(4 * $count);
if (4*$count != $this->strlen($bytes))
return false;
$endian_letter = ('big' == $this->endian)? 'N' : 'V';
return unpack($endian_letter.$count, $bytes);
}
function substr($string, $start, $length) {
if ($this->is_overloaded) {
return mb_substr($string, $start, $length, 'ascii');
} else {
return substr($string, $start, $length);
}
}
function strlen($string) {
if ($this->is_overloaded) {
return mb_strlen($string, 'ascii');
} else {
return strlen($string);
}
}
function str_split($string, $chunk_size) {
if (!function_exists('str_split')) {
$length = $this->strlen($string);
$out = array();
for ($i = 0; $i < $length; $i += $chunk_size)
$out[] = $this->substr($string, $i, $chunk_size);
return $out;
} else {
return str_split( $string, $chunk_size );
}
}
function pos() {
return $this->_pos;
}
function is_resource() {
return true;
}
function close() {
return true;
}
}
endif;
if ( !class_exists( 'POMO_FileReader' ) ):
class POMO_FileReader extends POMO_Reader {
function POMO_FileReader($filename) {
parent::POMO_Reader();
$this->_f = fopen($filename, 'rb');
}
function read($bytes) {
return fread($this->_f, $bytes);
}
function seekto($pos) {
if ( -1 == fseek($this->_f, $pos, SEEK_SET)) {
return false;
}
$this->_pos = $pos;
return true;
}
function is_resource() {
return is_resource($this->_f);
}
function feof() {
return feof($this->_f);
}
function close() {
return fclose($this->_f);
}
function read_all() {
$all = '';
while ( !$this->feof() )
$all .= $this->read(4096);
return $all;
}
}
endif;
if ( !class_exists( 'POMO_StringReader' ) ):
/**
* Provides file-like methods for manipulating a string instead
* of a physical file.
*/
class POMO_StringReader extends POMO_Reader {
var $_str = '';
function POMO_StringReader($str = '') {
parent::POMO_Reader();
$this->_str = $str;
$this->_pos = 0;
}
function read($bytes) {
$data = $this->substr($this->_str, $this->_pos, $bytes);
$this->_pos += $bytes;
if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str);
return $data;
}
function seekto($pos) {
$this->_pos = $pos;
if ($this->strlen($this->_str) < $this->_pos) $this->_pos = $this->strlen($this->_str);
return $this->_pos;
}
function length() {
return $this->strlen($this->_str);
}
function read_all() {
return $this->substr($this->_str, $this->_pos, $this->strlen($this->_str));
}
}
endif;
if ( !class_exists( 'POMO_CachedFileReader' ) ):
/**
* Reads the contents of the file in the beginning.
*/
class POMO_CachedFileReader extends POMO_StringReader {
function POMO_CachedFileReader($filename) {
parent::POMO_StringReader();
$this->_str = file_get_contents($filename);
if (false === $this->_str)
return false;
$this->_pos = 0;
}
}
endif;
if ( !class_exists( 'POMO_CachedIntFileReader' ) ):
/**
* Reads the contents of the file in the beginning.
*/
class POMO_CachedIntFileReader extends POMO_CachedFileReader {
function POMO_CachedIntFileReader($filename) {
parent::POMO_CachedFileReader($filename);
}
}
endif;

View File

@ -1,275 +1,275 @@
<?php
/**
* Class for a set of entries for translation and their associated headers
*
* @version $Id: translations.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage translations
*/
require_once dirname(__FILE__) . '/entry.php';
if ( !class_exists( 'Translations' ) ):
class Translations {
var $entries = array();
var $headers = array();
/**
* Add entry to the PO structure
*
* @param object &$entry
* @return bool true on success, false if the entry doesn't have a key
*/
function add_entry($entry) {
if (is_array($entry)) {
$entry = new Translation_Entry($entry);
}
$key = $entry->key();
if (false === $key) return false;
$this->entries[$key] = &$entry;
return true;
}
function add_entry_or_merge($entry) {
if (is_array($entry)) {
$entry = new Translation_Entry($entry);
}
$key = $entry->key();
if (false === $key) return false;
if (isset($this->entries[$key]))
$this->entries[$key]->merge_with($entry);
else
$this->entries[$key] = &$entry;
return true;
}
/**
* Sets $header PO header to $value
*
* If the header already exists, it will be overwritten
*
* TODO: this should be out of this class, it is gettext specific
*
* @param string $header header name, without trailing :
* @param string $value header value, without trailing \n
*/
function set_header($header, $value) {
$this->headers[$header] = $value;
}
function set_headers($headers) {
foreach($headers as $header => $value) {
$this->set_header($header, $value);
}
}
function get_header($header) {
return isset($this->headers[$header])? $this->headers[$header] : false;
}
function translate_entry(&$entry) {
$key = $entry->key();
return isset($this->entries[$key])? $this->entries[$key] : false;
}
function translate($singular, $context=null) {
$entry = new Translation_Entry(array('singular' => $singular, 'context' => $context));
$translated = $this->translate_entry($entry);
return ($translated && !empty($translated->translations))? $translated->translations[0] : $singular;
}
/**
* Given the number of items, returns the 0-based index of the plural form to use
*
* Here, in the base Translations class, the common logic for English is implemented:
* 0 if there is one element, 1 otherwise
*
* This function should be overrided by the sub-classes. For example MO/PO can derive the logic
* from their headers.
*
* @param integer $count number of items
*/
function select_plural_form($count) {
return 1 == $count? 0 : 1;
}
function get_plural_forms_count() {
return 2;
}
function translate_plural($singular, $plural, $count, $context = null) {
$entry = new Translation_Entry(array('singular' => $singular, 'plural' => $plural, 'context' => $context));
$translated = $this->translate_entry($entry);
$index = $this->select_plural_form($count);
$total_plural_forms = $this->get_plural_forms_count();
if ($translated && 0 <= $index && $index < $total_plural_forms &&
is_array($translated->translations) &&
isset($translated->translations[$index]))
return $translated->translations[$index];
else
return 1 == $count? $singular : $plural;
}
/**
* Merge $other in the current object.
*
* @param Object &$other Another Translation object, whose translations will be merged in this one
* @return void
**/
function merge_with(&$other) {
foreach( $other->entries as $entry ) {
$this->entries[$entry->key()] = $entry;
}
}
function merge_originals_with(&$other) {
foreach( $other->entries as $entry ) {
if ( !isset( $this->entries[$entry->key()] ) )
$this->entries[$entry->key()] = $entry;
else
$this->entries[$entry->key()]->merge_with($entry);
}
}
}
class Gettext_Translations extends Translations {
/**
* The gettext implementation of select_plural_form.
*
* It lives in this class, because there are more than one descendand, which will use it and
* they can't share it effectively.
*
*/
function gettext_select_plural_form($count) {
if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) {
list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms'));
$this->_nplurals = $nplurals;
$this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression);
}
return call_user_func($this->_gettext_select_plural_form, $count);
}
function nplurals_and_expression_from_header($header) {
if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) {
$nplurals = (int)$matches[1];
$expression = trim($this->parenthesize_plural_exression($matches[2]));
return array($nplurals, $expression);
} else {
return array(2, 'n != 1');
}
}
/**
* Makes a function, which will return the right translation index, according to the
* plural forms header
*/
function make_plural_form_function($nplurals, $expression) {
$expression = str_replace('n', '$n', $expression);
$func_body = "
\$index = (int)($expression);
return (\$index < $nplurals)? \$index : $nplurals - 1;";
return create_function('$n', $func_body);
}
/**
* Adds parantheses to the inner parts of ternary operators in
* plural expressions, because PHP evaluates ternary oerators from left to right
*
* @param string $expression the expression without parentheses
* @return string the expression with parentheses added
*/
function parenthesize_plural_exression($expression) {
$expression .= ';';
$res = '';
$depth = 0;
for ($i = 0; $i < strlen($expression); ++$i) {
$char = $expression[$i];
switch ($char) {
case '?':
$res .= ' ? (';
$depth++;
break;
case ':':
$res .= ') : (';
break;
case ';':
$res .= str_repeat(')', $depth) . ';';
$depth= 0;
break;
default:
$res .= $char;
}
}
return rtrim($res, ';');
}
function make_headers($translation) {
$headers = array();
// sometimes \ns are used instead of real new lines
$translation = str_replace('\n', "\n", $translation);
$lines = explode("\n", $translation);
foreach($lines as $line) {
$parts = explode(':', $line, 2);
if (!isset($parts[1])) continue;
$headers[trim($parts[0])] = trim($parts[1]);
}
return $headers;
}
function set_header($header, $value) {
parent::set_header($header, $value);
if ('Plural-Forms' == $header) {
list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms'));
$this->_nplurals = $nplurals;
$this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression);
}
}
}
endif;
if ( !class_exists( 'NOOP_Translations' ) ):
/**
* Provides the same interface as Translations, but doesn't do anything
*/
class NOOP_Translations {
var $entries = array();
var $headers = array();
function add_entry($entry) {
return true;
}
function set_header($header, $value) {
}
function set_headers($headers) {
}
function get_header($header) {
return false;
}
function translate_entry(&$entry) {
return false;
}
function translate($singular, $context=null) {
return $singular;
}
function select_plural_form($count) {
return 1 == $count? 0 : 1;
}
function get_plural_forms_count() {
return 2;
}
function translate_plural($singular, $plural, $count, $context = null) {
return 1 == $count? $singular : $plural;
}
function merge_with(&$other) {
}
}
endif;
<?php
/**
* Class for a set of entries for translation and their associated headers
*
* @version $Id: translations.php 718 2012-10-31 00:32:02Z nbachiyski $
* @package pomo
* @subpackage translations
*/
require_once dirname(__FILE__) . '/entry.php';
if ( !class_exists( 'Translations' ) ):
class Translations {
var $entries = array();
var $headers = array();
/**
* Add entry to the PO structure
*
* @param object &$entry
* @return bool true on success, false if the entry doesn't have a key
*/
function add_entry($entry) {
if (is_array($entry)) {
$entry = new Translation_Entry($entry);
}
$key = $entry->key();
if (false === $key) return false;
$this->entries[$key] = &$entry;
return true;
}
function add_entry_or_merge($entry) {
if (is_array($entry)) {
$entry = new Translation_Entry($entry);
}
$key = $entry->key();
if (false === $key) return false;
if (isset($this->entries[$key]))
$this->entries[$key]->merge_with($entry);
else
$this->entries[$key] = &$entry;
return true;
}
/**
* Sets $header PO header to $value
*
* If the header already exists, it will be overwritten
*
* TODO: this should be out of this class, it is gettext specific
*
* @param string $header header name, without trailing :
* @param string $value header value, without trailing \n
*/
function set_header($header, $value) {
$this->headers[$header] = $value;
}
function set_headers($headers) {
foreach($headers as $header => $value) {
$this->set_header($header, $value);
}
}
function get_header($header) {
return isset($this->headers[$header])? $this->headers[$header] : false;
}
function translate_entry(&$entry) {
$key = $entry->key();
return isset($this->entries[$key])? $this->entries[$key] : false;
}
function translate($singular, $context=null) {
$entry = new Translation_Entry(array('singular' => $singular, 'context' => $context));
$translated = $this->translate_entry($entry);
return ($translated && !empty($translated->translations))? $translated->translations[0] : $singular;
}
/**
* Given the number of items, returns the 0-based index of the plural form to use
*
* Here, in the base Translations class, the common logic for English is implemented:
* 0 if there is one element, 1 otherwise
*
* This function should be overrided by the sub-classes. For example MO/PO can derive the logic
* from their headers.
*
* @param integer $count number of items
*/
function select_plural_form($count) {
return 1 == $count? 0 : 1;
}
function get_plural_forms_count() {
return 2;
}
function translate_plural($singular, $plural, $count, $context = null) {
$entry = new Translation_Entry(array('singular' => $singular, 'plural' => $plural, 'context' => $context));
$translated = $this->translate_entry($entry);
$index = $this->select_plural_form($count);
$total_plural_forms = $this->get_plural_forms_count();
if ($translated && 0 <= $index && $index < $total_plural_forms &&
is_array($translated->translations) &&
isset($translated->translations[$index]))
return $translated->translations[$index];
else
return 1 == $count? $singular : $plural;
}
/**
* Merge $other in the current object.
*
* @param Object &$other Another Translation object, whose translations will be merged in this one
* @return void
**/
function merge_with(&$other) {
foreach( $other->entries as $entry ) {
$this->entries[$entry->key()] = $entry;
}
}
function merge_originals_with(&$other) {
foreach( $other->entries as $entry ) {
if ( !isset( $this->entries[$entry->key()] ) )
$this->entries[$entry->key()] = $entry;
else
$this->entries[$entry->key()]->merge_with($entry);
}
}
}
class Gettext_Translations extends Translations {
/**
* The gettext implementation of select_plural_form.
*
* It lives in this class, because there are more than one descendand, which will use it and
* they can't share it effectively.
*
*/
function gettext_select_plural_form($count) {
if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) {
list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms'));
$this->_nplurals = $nplurals;
$this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression);
}
return call_user_func($this->_gettext_select_plural_form, $count);
}
function nplurals_and_expression_from_header($header) {
if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) {
$nplurals = (int)$matches[1];
$expression = trim($this->parenthesize_plural_exression($matches[2]));
return array($nplurals, $expression);
} else {
return array(2, 'n != 1');
}
}
/**
* Makes a function, which will return the right translation index, according to the
* plural forms header
*/
function make_plural_form_function($nplurals, $expression) {
$expression = str_replace('n', '$n', $expression);
$func_body = "
\$index = (int)($expression);
return (\$index < $nplurals)? \$index : $nplurals - 1;";
return create_function('$n', $func_body);
}
/**
* Adds parantheses to the inner parts of ternary operators in
* plural expressions, because PHP evaluates ternary oerators from left to right
*
* @param string $expression the expression without parentheses
* @return string the expression with parentheses added
*/
function parenthesize_plural_exression($expression) {
$expression .= ';';
$res = '';
$depth = 0;
for ($i = 0; $i < strlen($expression); ++$i) {
$char = $expression[$i];
switch ($char) {
case '?':
$res .= ' ? (';
$depth++;
break;
case ':':
$res .= ') : (';
break;
case ';':
$res .= str_repeat(')', $depth) . ';';
$depth= 0;
break;
default:
$res .= $char;
}
}
return rtrim($res, ';');
}
function make_headers($translation) {
$headers = array();
// sometimes \ns are used instead of real new lines
$translation = str_replace('\n', "\n", $translation);
$lines = explode("\n", $translation);
foreach($lines as $line) {
$parts = explode(':', $line, 2);
if (!isset($parts[1])) continue;
$headers[trim($parts[0])] = trim($parts[1]);
}
return $headers;
}
function set_header($header, $value) {
parent::set_header($header, $value);
if ('Plural-Forms' == $header) {
list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms'));
$this->_nplurals = $nplurals;
$this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression);
}
}
}
endif;
if ( !class_exists( 'NOOP_Translations' ) ):
/**
* Provides the same interface as Translations, but doesn't do anything
*/
class NOOP_Translations {
var $entries = array();
var $headers = array();
function add_entry($entry) {
return true;
}
function set_header($header, $value) {
}
function set_headers($headers) {
}
function get_header($header) {
return false;
}
function translate_entry(&$entry) {
return false;
}
function translate($singular, $context=null) {
return $singular;
}
function select_plural_form($count) {
return 1 == $count? 0 : 1;
}
function get_plural_forms_count() {
return 2;
}
function translate_plural($singular, $plural, $count, $context = null) {
return 1 == $count? $singular : $plural;
}
function merge_with(&$other) {
}
}
endif;

View File

@ -1,4 +1,4 @@
<?php
// Bump this when updating the zip package
define( 'YOURLS_VERSION', '1.6-polyglot' );
define( 'YOURLS_DB_VERSION', '482' );
<?php
// Bump this when updating the zip package
define( 'YOURLS_VERSION', '1.6-polyglot' );
define( 'YOURLS_DB_VERSION', '482' );

View File

@ -1,157 +1,157 @@
// Handle .hide-if-no-js and .hide-if-js styles
$(document).ready(function(){
$('.hide-if-no-js').removeClass('hide-if-no-js');
$('.hide-if-js').hide();
});
// Change an element text an revert in a smooth pulse. el is an element id like '#copybox h2'
function html_pulse( el, newtext ){
var oldtext = $(el).html();
// Fast pulse to "Copied" and revert
$(el).fadeTo(
"normal",
0.01,
function(){
$(el)
.html( newtext )
.css('opacity', 1)
.fadeTo(
"slow", 1, // this fades from 1 to 1: just a 'sleep(1)' actually
function(){
$(el).fadeTo("normal", 0.01, function(){$(el).html( oldtext ).css('opacity', 1)});
}
);
}
);
}
// Update feedback message
function feedback(msg, type, delay) {
closeme = ( type == 'fail' || type == 'error' ) ? true : false;
delay = delay || ( closeme == true ? 10000 : 3500 );
$.notifyBar({
html: '<span>'+msg+'</span>',
delay: delay,
animationSpeed: "normal",
close: closeme,
cls: type
});
return true;
}
// Unused for now
function logout() {
$.ajax({
type: "POST",
url: ajaxurl,
data: {action:'logout'},
success: function() {
window.parent.location.href = window.parent.location.href;
}
});
}
// Begin the spinning animation & disable a button
function add_loading(el) {
$(el).attr("disabled", "disabled").addClass('disabled').addClass('loading');
}
// End spinning animation
function end_loading(el) {
$(el).removeClass('loading');
}
// Un-disable an element
function end_disable(el) {
$(el).removeAttr("disabled").removeClass('disabled');
}
// Trim long string
function trim_long_string( string, length) {
var newstring = string;
length = length || 60;
if ( newstring.length > length ) {
newstring = newstring.substr(0, (length - 5) ) + '[...]';
}
return newstring;
}
// Get the var=xxx from a query string
function get_var_from_query( url, varname, default_val ) {
if( varname == undefined ) {
varname = 'nonce';
}
if( default_val == undefined ) {
default_val = '';
}
// Split the url on '?' and get only the params (which is element 1)
url = url.split('?')[1];
// Now split those params on '&' so we can get each one individually (Ex. param_var=param_value)
url = url.split('&');
// Now we have to find the varname in that array using methods that IE likes (Curse you IE!!!)
var i=0;
for( i=0; i<url.length; i++ ){
// So split the first param elemment on '=' and check the param_var to see if it matches varname (element 0)
if( url[i].split('=')[0] == varname ){
// If it matches we want to return the param_value
return url[i].split('=')[1];
}
}
// If we didn't find anything then we just return the default_val
return default_val;
}
/**
* Jquery Cookie plugin
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Available at http://plugins.jquery.com/files/jquery.cookie.js.txt
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};
// Handle .hide-if-no-js and .hide-if-js styles
$(document).ready(function(){
$('.hide-if-no-js').removeClass('hide-if-no-js');
$('.hide-if-js').hide();
});
// Change an element text an revert in a smooth pulse. el is an element id like '#copybox h2'
function html_pulse( el, newtext ){
var oldtext = $(el).html();
// Fast pulse to "Copied" and revert
$(el).fadeTo(
"normal",
0.01,
function(){
$(el)
.html( newtext )
.css('opacity', 1)
.fadeTo(
"slow", 1, // this fades from 1 to 1: just a 'sleep(1)' actually
function(){
$(el).fadeTo("normal", 0.01, function(){$(el).html( oldtext ).css('opacity', 1)});
}
);
}
);
}
// Update feedback message
function feedback(msg, type, delay) {
closeme = ( type == 'fail' || type == 'error' ) ? true : false;
delay = delay || ( closeme == true ? 10000 : 3500 );
$.notifyBar({
html: '<span>'+msg+'</span>',
delay: delay,
animationSpeed: "normal",
close: closeme,
cls: type
});
return true;
}
// Unused for now
function logout() {
$.ajax({
type: "POST",
url: ajaxurl,
data: {action:'logout'},
success: function() {
window.parent.location.href = window.parent.location.href;
}
});
}
// Begin the spinning animation & disable a button
function add_loading(el) {
$(el).attr("disabled", "disabled").addClass('disabled').addClass('loading');
}
// End spinning animation
function end_loading(el) {
$(el).removeClass('loading');
}
// Un-disable an element
function end_disable(el) {
$(el).removeAttr("disabled").removeClass('disabled');
}
// Trim long string
function trim_long_string( string, length) {
var newstring = string;
length = length || 60;
if ( newstring.length > length ) {
newstring = newstring.substr(0, (length - 5) ) + '[...]';
}
return newstring;
}
// Get the var=xxx from a query string
function get_var_from_query( url, varname, default_val ) {
if( varname == undefined ) {
varname = 'nonce';
}
if( default_val == undefined ) {
default_val = '';
}
// Split the url on '?' and get only the params (which is element 1)
url = url.split('?')[1];
// Now split those params on '&' so we can get each one individually (Ex. param_var=param_value)
url = url.split('&');
// Now we have to find the varname in that array using methods that IE likes (Curse you IE!!!)
var i=0;
for( i=0; i<url.length; i++ ){
// So split the first param elemment on '=' and check the param_var to see if it matches varname (element 0)
if( url[i].split('=')[0] == varname ){
// If it matches we want to return the param_value
return url[i].split('=')[1];
}
}
// If we didn't find anything then we just return the default_val
return default_val;
}
/**
* Jquery Cookie plugin
* Copyright (c) 2006 Klaus Hartl (stilbuero.de)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Available at http://plugins.jquery.com/files/jquery.cookie.js.txt
*/
jQuery.cookie = function(name, value, options) {
if (typeof value != 'undefined') { // name and value given, set cookie
options = options || {};
if (value === null) {
value = '';
options.expires = -1;
}
var expires = '';
if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
var date;
if (typeof options.expires == 'number') {
date = new Date();
date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
} else {
date = options.expires;
}
expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
}
// CAUTION: Needed to parenthesize options.path and options.domain
// in the following expressions, otherwise they evaluate to undefined
// in the packed version for some reason...
var path = options.path ? '; path=' + (options.path) : '';
var domain = options.domain ? '; domain=' + (options.domain) : '';
var secure = options.secure ? '; secure' : '';
document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
} else { // only name given, get cookie
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
};

View File

@ -1,48 +1,48 @@
$(document).ready(function(){
$('ul.toggle_display').css('display', 'block');
$('.tab h2').css('display','none');
// Toggle tabs
$('ul.toggle_display li a').click(function(){
var target = $(this).attr('href').replace('#', ''); // 'stat_tab_location'
var divs = target.split('_')[1]; // 'tab'
$('div.'+divs).css('display', 'none');
$('div#'+target).css('display', 'block');
$('ul.stat_'+divs+' li a').removeClass('selected');
$('ul.stat_'+divs+' li a[href="#'+target+'"]').addClass('selected').css('outline', 'none').blur();
return false;
});
// Activate main tab
if (location.hash) {
$('#tabs ul#headers li a[href="'+location.hash+'"]').click();
} else {
$('#tabs ul#headers li a:first').click();
}
// Activate first line graph
$('#stats_lines li a:first').click();
// Prettify list
$('#historical_clicks li:odd').css('background', '#E3F3FF');
// Toggle detail lists
$('a.details').click(function(){
var target = $(this).attr('id').replace('more_', 'details_');
$('#'+target).toggle();
return false;
});
// If an image src is erroneous (404 or anything) replace it with a transparent gif
$('.fix_images').each(function(i,img) {
$(img).error(function(){
$(img).attr('src', 'images/blank.gif');
});
});
// If we have the zeroclipboard thing, init it when Share Tab is displayed
$('#tabs ul#headers li a[href="#stat_tab_share"]').click(function(){
init_clipboard();
});
$(document).ready(function(){
$('ul.toggle_display').css('display', 'block');
$('.tab h2').css('display','none');
// Toggle tabs
$('ul.toggle_display li a').click(function(){
var target = $(this).attr('href').replace('#', ''); // 'stat_tab_location'
var divs = target.split('_')[1]; // 'tab'
$('div.'+divs).css('display', 'none');
$('div#'+target).css('display', 'block');
$('ul.stat_'+divs+' li a').removeClass('selected');
$('ul.stat_'+divs+' li a[href="#'+target+'"]').addClass('selected').css('outline', 'none').blur();
return false;
});
// Activate main tab
if (location.hash) {
$('#tabs ul#headers li a[href="'+location.hash+'"]').click();
} else {
$('#tabs ul#headers li a:first').click();
}
// Activate first line graph
$('#stats_lines li a:first').click();
// Prettify list
$('#historical_clicks li:odd').css('background', '#E3F3FF');
// Toggle detail lists
$('a.details').click(function(){
var target = $(this).attr('id').replace('more_', 'details_');
$('#'+target).toggle();
return false;
});
// If an image src is erroneous (404 or anything) replace it with a transparent gif
$('.fix_images').each(function(i,img) {
$(img).error(function(){
$(img).attr('src', 'images/blank.gif');
});
});
// If we have the zeroclipboard thing, init it when Share Tab is displayed
$('#tabs ul#headers li a[href="#stat_tab_share"]').click(function(){
init_clipboard();
});
});

View File

@ -1,202 +1,202 @@
// Init some stuff
$(document).ready(function(){
$('#add-url, #add-keyword').keypress(function(e){
if (e.which == 13) {add_link();}
});
add_link_reset();
$('#new_url_form').attr('action', 'javascript:add_link();');
$('input.text').focus(function(){
$(this).select();
});
// this one actually has little impact, the .hasClass('disabled') in each edit_link_display(), remove() etc... fires faster
$(document).on( 'click', 'a.button', function() {
if( $(this).hasClass('disabled') ) {
return false;
}
});
});
// Create new link and add to table
function add_link() {
if( $('#add-button').hasClass('disabled') ) {
return false;
}
var newurl = $("#add-url").val();
var nonce = $("#nonce-add").val();
if ( !newurl || newurl == 'http://' || newurl == 'https://' ) {
return;
}
var keyword = $("#add-keyword").val();
add_loading("#add-button");
$.getJSON(
ajaxurl,
{action:'add', url: newurl, keyword: keyword, nonce: nonce},
function(data){
if(data.status == 'success') {
$('#main_table tbody').prepend( data.html ).trigger("update");
$('#nourl_found').css('display', 'none');
zebra_table();
increment_counter();
toggle_share_fill_boxes( data.url.url, data.shorturl, data.url.title );
}
add_link_reset();
end_loading("#add-button");
end_disable("#add-button");
feedback(data.message, data.status);
}
);
}
function toggle_share_fill_boxes( url, shorturl, title ) {
$('#copylink').val( shorturl );
$('#titlelink').val( title );
$('#origlink').attr( 'href', url ).html( url );
$('#statlink').attr( 'href', shorturl+'+' ).html( shorturl+'+' );
var tweet = ( title ? title + ' ' + shorturl : shorturl );
$('#tweet_body').val( tweet ).keypress();
$('#shareboxes').slideDown( '300', function(){ init_clipboard(); } ); // clipboard re-initialized after slidedown to make sure the invisible Flash element is correctly positionned
$('#tweet_body').keypress();
}
// Display the edition interface
function edit_link_display(id) {
if( $('#edit-button-'+id).hasClass('disabled') ) {
return false;
}
add_loading('#actions-'+id+' .button');
var keyword = $('#keyword_'+id).val();
var nonce = get_var_from_query( $('#edit-button-'+id).attr('href'), 'nonce' );
$.getJSON(
ajaxurl,
{ action: "edit_display", keyword: keyword, nonce: nonce, id: id },
function(data){
$("#id-" + id).after( data.html );
$("#edit-url-"+ id).focus();
end_loading('#actions-'+id+' .button');
}
);
}
// Delete a link
function remove_link(id) {
if( $('#delete-button-'+id).hasClass('disabled') ) {
return false;
}
if (!confirm('Really delete?')) {
return;
}
var keyword = $('#keyword_'+id).val();
var nonce = get_var_from_query( $('#delete-button-'+id).attr('href'), 'nonce' );
$.getJSON(
ajaxurl,
{ action: "delete", keyword: keyword, nonce: nonce, id: id },
function(data){
if (data.success == 1) {
$("#id-" + id).fadeOut(function(){
$(this).remove();
if( $('#main_table tbody tr').length == 1 ) {
$('#nourl_found').css('display', '');
}
zebra_table();
});
decrement_counter();
} else {
alert('something wrong happened while deleting :/');
}
}
);
}
// Redirect to stat page
function go_stats(link) {
window.location=link;
}
// Cancel edition of a link
function edit_link_hide(id) {
$("#edit-" + id).fadeOut(200, function(){
end_disable('#actions-'+id+' .button');
});
}
// Save edition of a link
function edit_link_save(id) {
add_loading("#edit-close-" + id);
var newurl = encodeURI( $("#edit-url-" + id).val() );
var newkeyword = $("#edit-keyword-" + id).val();
var title = $("#edit-title-" + id).val();
var keyword = $('#old_keyword_'+id).val();
var nonce = $('#nonce_'+id).val();
var www = $('#yourls-site').val();
$.getJSON(
ajaxurl,
{action:'edit_save', url: newurl, id: id, keyword: keyword, newkeyword: newkeyword, title: title, nonce: nonce },
function(data){
if(data.status == 'success') {
if( data.url.title != '' ) {
var display_link = '<a href="' + data.url.url + '" title="' + data.url.url + '">' + data.url.display_title + '</a><br/><small><a href="' + data.url.url + '">' + data.url.display_url + '</a></small>';
} else {
var display_link = '<a href="' + data.url.url + '" title="' + data.url.url + '">' + data.url.display_url + '</a>';
}
$("#url-" + id).html(display_link);
$("#keyword-" + id).html('<a href="' + data.url.shorturl + '" title="' + data.url.shorturl + '">' + data.url.keyword + '</a>');
$("#timestamp-" + id).html(data.url.date);
$("#edit-" + id).fadeOut(200, function(){
$('#main_table tbody').trigger("update");
});
$('#keyword_'+id).val( newkeyword );
$('#statlink-'+id).attr( 'href', data.url.shorturl+'+' );
}
feedback(data.message, data.status);
end_loading("#edit-close-" + id);
end_disable("#actions-" + id + ' .button');
}
);
}
// Prettify table with odd & even rows
function zebra_table() {
$("#main_table tbody tr:even").removeClass('odd').addClass('even');
$("#main_table tbody tr:odd").removeClass('even').addClass('odd');
$('#main_table tbody').trigger("update");
}
// Ready to add another URL
function add_link_reset() {
$('#add-url').val('http://').focus();
$('#add-keyword').val('');
}
// Increment URL counters
function increment_counter() {
$('.increment').each(function(){
$(this).html( parseInt($(this).html()) + 1);
});
}
// Decrement URL counters
function decrement_counter() {
$('.increment').each(function(){
$(this).html( parseInt($(this).html()) - 1 );
});
}
// Toggle Share box
function toggle_share(id) {
if( $('#share-button-'+id).hasClass('disabled') ) {
return false;
}
var link = $('#url-'+id+' a:first');
var longurl = link.attr('href');
var title = link.attr('title');
var shorturl = $('#keyword-'+id+' a:first').attr('href');
toggle_share_fill_boxes( longurl, shorturl, title );
}
// Init some stuff
$(document).ready(function(){
$('#add-url, #add-keyword').keypress(function(e){
if (e.which == 13) {add_link();}
});
add_link_reset();
$('#new_url_form').attr('action', 'javascript:add_link();');
$('input.text').focus(function(){
$(this).select();
});
// this one actually has little impact, the .hasClass('disabled') in each edit_link_display(), remove() etc... fires faster
$(document).on( 'click', 'a.button', function() {
if( $(this).hasClass('disabled') ) {
return false;
}
});
});
// Create new link and add to table
function add_link() {
if( $('#add-button').hasClass('disabled') ) {
return false;
}
var newurl = $("#add-url").val();
var nonce = $("#nonce-add").val();
if ( !newurl || newurl == 'http://' || newurl == 'https://' ) {
return;
}
var keyword = $("#add-keyword").val();
add_loading("#add-button");
$.getJSON(
ajaxurl,
{action:'add', url: newurl, keyword: keyword, nonce: nonce},
function(data){
if(data.status == 'success') {
$('#main_table tbody').prepend( data.html ).trigger("update");
$('#nourl_found').css('display', 'none');
zebra_table();
increment_counter();
toggle_share_fill_boxes( data.url.url, data.shorturl, data.url.title );
}
add_link_reset();
end_loading("#add-button");
end_disable("#add-button");
feedback(data.message, data.status);
}
);
}
function toggle_share_fill_boxes( url, shorturl, title ) {
$('#copylink').val( shorturl );
$('#titlelink').val( title );
$('#origlink').attr( 'href', url ).html( url );
$('#statlink').attr( 'href', shorturl+'+' ).html( shorturl+'+' );
var tweet = ( title ? title + ' ' + shorturl : shorturl );
$('#tweet_body').val( tweet ).keypress();
$('#shareboxes').slideDown( '300', function(){ init_clipboard(); } ); // clipboard re-initialized after slidedown to make sure the invisible Flash element is correctly positionned
$('#tweet_body').keypress();
}
// Display the edition interface
function edit_link_display(id) {
if( $('#edit-button-'+id).hasClass('disabled') ) {
return false;
}
add_loading('#actions-'+id+' .button');
var keyword = $('#keyword_'+id).val();
var nonce = get_var_from_query( $('#edit-button-'+id).attr('href'), 'nonce' );
$.getJSON(
ajaxurl,
{ action: "edit_display", keyword: keyword, nonce: nonce, id: id },
function(data){
$("#id-" + id).after( data.html );
$("#edit-url-"+ id).focus();
end_loading('#actions-'+id+' .button');
}
);
}
// Delete a link
function remove_link(id) {
if( $('#delete-button-'+id).hasClass('disabled') ) {
return false;
}
if (!confirm('Really delete?')) {
return;
}
var keyword = $('#keyword_'+id).val();
var nonce = get_var_from_query( $('#delete-button-'+id).attr('href'), 'nonce' );
$.getJSON(
ajaxurl,
{ action: "delete", keyword: keyword, nonce: nonce, id: id },
function(data){
if (data.success == 1) {
$("#id-" + id).fadeOut(function(){
$(this).remove();
if( $('#main_table tbody tr').length == 1 ) {
$('#nourl_found').css('display', '');
}
zebra_table();
});
decrement_counter();
} else {
alert('something wrong happened while deleting :/');
}
}
);
}
// Redirect to stat page
function go_stats(link) {
window.location=link;
}
// Cancel edition of a link
function edit_link_hide(id) {
$("#edit-" + id).fadeOut(200, function(){
end_disable('#actions-'+id+' .button');
});
}
// Save edition of a link
function edit_link_save(id) {
add_loading("#edit-close-" + id);
var newurl = encodeURI( $("#edit-url-" + id).val() );
var newkeyword = $("#edit-keyword-" + id).val();
var title = $("#edit-title-" + id).val();
var keyword = $('#old_keyword_'+id).val();
var nonce = $('#nonce_'+id).val();
var www = $('#yourls-site').val();
$.getJSON(
ajaxurl,
{action:'edit_save', url: newurl, id: id, keyword: keyword, newkeyword: newkeyword, title: title, nonce: nonce },
function(data){
if(data.status == 'success') {
if( data.url.title != '' ) {
var display_link = '<a href="' + data.url.url + '" title="' + data.url.url + '">' + data.url.display_title + '</a><br/><small><a href="' + data.url.url + '">' + data.url.display_url + '</a></small>';
} else {
var display_link = '<a href="' + data.url.url + '" title="' + data.url.url + '">' + data.url.display_url + '</a>';
}
$("#url-" + id).html(display_link);
$("#keyword-" + id).html('<a href="' + data.url.shorturl + '" title="' + data.url.shorturl + '">' + data.url.keyword + '</a>');
$("#timestamp-" + id).html(data.url.date);
$("#edit-" + id).fadeOut(200, function(){
$('#main_table tbody').trigger("update");
});
$('#keyword_'+id).val( newkeyword );
$('#statlink-'+id).attr( 'href', data.url.shorturl+'+' );
}
feedback(data.message, data.status);
end_loading("#edit-close-" + id);
end_disable("#actions-" + id + ' .button');
}
);
}
// Prettify table with odd & even rows
function zebra_table() {
$("#main_table tbody tr:even").removeClass('odd').addClass('even');
$("#main_table tbody tr:odd").removeClass('even').addClass('odd');
$('#main_table tbody').trigger("update");
}
// Ready to add another URL
function add_link_reset() {
$('#add-url').val('http://').focus();
$('#add-keyword').val('');
}
// Increment URL counters
function increment_counter() {
$('.increment').each(function(){
$(this).html( parseInt($(this).html()) + 1);
});
}
// Decrement URL counters
function decrement_counter() {
$('.increment').each(function(){
$(this).html( parseInt($(this).html()) - 1 );
});
}
// Toggle Share box
function toggle_share(id) {
if( $('#share-button-'+id).hasClass('disabled') ) {
return false;
}
var link = $('#url-'+id+' a:first');
var longurl = link.attr('href');
var title = link.attr('title');
var shorturl = $('#keyword-'+id+' a:first').attr('href');
toggle_share_fill_boxes( longurl, shorturl, title );
}

File diff suppressed because one or more lines are too long

View File

@ -1,319 +1,319 @@
/**
the script only works on "input [type=text]"
http://teddevito.com/demos/calendar.php
**/
// don't declare anything out here in the global namespace
(function($) { // create private scope (inside you can use $ instead of jQuery)
// functions and vars declared here are effectively 'singletons'. there will be only a single
// instance of them. so this is a good place to declare any immutable items or stateless
// functions. for example:
var today = new Date(); // used in defaults
var months = 'January,February,March,April,May,June,July,August,September,October,November,December'.split(',');
var months = l10n_cal_month;
var monthlengths = '31,28,31,30,31,30,31,31,30,31,30,31'.split(',');
var dateRegEx = /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/;
var yearRegEx = /^\d{4,4}$/;
// next, declare the plugin function
$.fn.simpleDatepicker = function(options) {
// functions and vars declared here are created each time your plugn function is invoked
// you could probably refactor your 'build', 'load_month', etc, functions to be passed
// the DOM element from below
var opts = jQuery.extend({}, jQuery.fn.simpleDatepicker.defaults, options);
// replaces a date string with a date object in opts.startdate and opts.enddate, if one exists
// populates two new properties with a ready-to-use year: opts.startyear and opts.endyear
setupYearRange();
/** extracts and setup a valid year range from the opts object **/
function setupYearRange () {
var startyear, endyear;
if (opts.startdate.constructor == Date) {
startyear = opts.startdate.getFullYear();
} else if (opts.startdate) {
if (yearRegEx.test(opts.startdate)) {
startyear = opts.startdate;
} else if (dateRegEx.test(opts.startdate)) {
opts.startdate = new Date(opts.startdate);
startyear = opts.startdate.getFullYear();
} else {
startyear = today.getFullYear();
}
} else {
startyear = today.getFullYear();
}
opts.startyear = startyear;
if (opts.enddate.constructor == Date) {
endyear = opts.enddate.getFullYear();
} else if (opts.enddate) {
if (yearRegEx.test(opts.enddate)) {
endyear = opts.enddate;
} else if (dateRegEx.test(opts.enddate)) {
opts.enddate = new Date(opts.enddate);
endyear = opts.enddate.getFullYear();
} else {
endyear = today.getFullYear();
}
} else {
endyear = today.getFullYear();
}
opts.endyear = endyear;
}
/** HTML factory for the actual datepicker table element **/
// has to read the year range so it can setup the correct years in our HTML <select>
function newDatepickerHTML () {
var years = [];
// process year range into an array
for (var i = 0; i <= opts.endyear - opts.startyear; i ++) years[i] = opts.startyear + i;
// build the table structure
var table = jQuery('<table class="datepicker" cellpadding="0" cellspacing="0"></table>');
table.append('<thead></thead>');
table.append('<tfoot></tfoot>');
table.append('<tbody></tbody>');
// month select field
var monthselect = '<select name="month">';
for (var i in l10n_cal_month) monthselect += '<option value="'+i+'">'+l10n_cal_month[i]+'</option>';
monthselect += '</select>';
// year select field
var yearselect = '<select name="year">';
for (var i in years) yearselect += '<option>'+years[i]+'</option>';
yearselect += '</select>';
jQuery("thead",table).append('<tr class="controls"><th colspan="7"><span class="prevMonth">&laquo;</span>&nbsp;'+monthselect+yearselect+'&nbsp;<span class="nextMonth">&raquo;</span></th></tr>');
jQuery("thead",table).append('<tr class="days"><th>'+l10n_cal_days[0]+'</th><th>'+l10n_cal_days[1]+'</th><th>'+l10n_cal_days[2]+'</th><th>'+l10n_cal_days[3]+'</th><th>'+l10n_cal_days[4]+'</th><th>'+l10n_cal_days[5]+'</th><th>'+l10n_cal_days[6]+'</th></tr>');
jQuery("tfoot",table).append('<tr><td colspan="2"><span class="today">'+l10n_cal_today+'</span></td><td colspan="3">&nbsp;</td><td colspan="2"><span class="close">'+l10n_cal_close+'</span></td></tr>');
for (var i = 0; i < 6; i++) jQuery("tbody",table).append('<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>');
return table;
}
/** get the real position of the input (well, anything really) **/
//http://www.quirksmode.org/js/findpos.html
function findPosition (obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return [curleft,curtop];
} else {
return false;
}
}
/** load the initial date and handle all date-navigation **/
// initial calendar load (e is null)
// prevMonth & nextMonth buttons
// onchange for the select fields
function loadMonth (e, el, datepicker, chosendate) {
// reference our years for the nextMonth and prevMonth buttons
var mo = jQuery("select[name=month]", datepicker).get(0).selectedIndex;
var yr = jQuery("select[name=year]", datepicker).get(0).selectedIndex;
var yrs = jQuery("select[name=year] option", datepicker).get().length;
// first try to process buttons that may change the month we're on
if (e && jQuery(e.target).hasClass('prevMonth')) {
if (0 == mo && yr) {
yr -= 1; mo = 11;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = 11;
jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr;
} else {
mo -= 1;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo;
}
} else if (e && jQuery(e.target).hasClass('nextMonth')) {
if (11 == mo && yr + 1 < yrs) {
yr += 1; mo = 0;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = 0;
jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr;
} else {
mo += 1;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo;
}
}
// maybe hide buttons
if (0 == mo && !yr) jQuery("span.prevMonth", datepicker).hide();
else jQuery("span.prevMonth", datepicker).show();
if (yr + 1 == yrs && 11 == mo) jQuery("span.nextMonth", datepicker).hide();
else jQuery("span.nextMonth", datepicker).show();
// clear the old cells
var cells = jQuery("tbody td", datepicker).unbind().empty().removeClass('date');
// figure out what month and year to load
var m = jQuery("select[name=month]", datepicker).val();
var y = jQuery("select[name=year]", datepicker).val();
var d = new Date(y, m, 1);
var startindex = d.getDay();
var numdays = monthlengths[m];
// http://en.wikipedia.org/wiki/Leap_year
if (1 == m && ((y%4 == 0 && y%100 != 0) || y%400 == 0)) numdays = 29;
// test for end dates (instead of just a year range)
if (opts.startdate.constructor == Date) {
var startMonth = opts.startdate.getMonth();
var startDate = opts.startdate.getDate();
}
if (opts.enddate.constructor == Date) {
var endMonth = opts.enddate.getMonth();
var endDate = opts.enddate.getDate();
}
// walk through the index and populate each cell, binding events too
for (var i = 0; i < numdays; i++) {
var cell = jQuery(cells.get(i+startindex)).removeClass('chosen');
// test that the date falls within a range, if we have a range
if (
(yr || ((!startDate && !startMonth) || ((i+1 >= startDate && mo == startMonth) || mo > startMonth))) &&
(yr + 1 < yrs || ((!endDate && !endMonth) || ((i+1 <= endDate && mo == endMonth) || mo < endMonth)))) {
cell
.text(i+1)
.addClass('date')
.hover(
function () { jQuery(this).addClass('over'); },
function () { jQuery(this).removeClass('over'); })
.click(function () {
var chosenDateObj = new Date(jQuery("select[name=year]", datepicker).val(), jQuery("select[name=month]", datepicker).val(), jQuery(this).text());
closeIt(el, datepicker, chosenDateObj);
});
// highlight the previous chosen date
if (i+1 == chosendate.getDate() && m == chosendate.getMonth() && y == chosendate.getFullYear()) cell.addClass('chosen');
}
}
}
/** closes the datepicker **/
// sets the currently matched input element's value to the date, if one is available
// remove the table element from the DOM
// indicate that there is no datepicker for the currently matched input element
function closeIt (el, datepicker, dateObj) {
if (dateObj && dateObj.constructor == Date)
el.val(jQuery.fn.simpleDatepicker.formatOutput(dateObj));
datepicker.remove();
datepicker = null;
jQuery.data(el.get(0), "simpleDatepicker", { hasDatepicker : false });
}
// iterate the matched nodeset
return this.each(function() {
// functions and vars declared here are created for each matched element. so if
// your functions need to manage or access per-node state you can defined them
// here and use $this to get at the DOM element
if ( jQuery(this).is('input') && 'text' == jQuery(this).attr('type')) {
var datepicker;
jQuery.data(jQuery(this).get(0), "simpleDatepicker", { hasDatepicker : false });
// open a datepicker on the click event
jQuery(this).click(function (ev) {
var $this = jQuery(ev.target);
if (false == jQuery.data($this.get(0), "simpleDatepicker").hasDatepicker) {
// store data telling us there is already a datepicker
jQuery.data($this.get(0), "simpleDatepicker", { hasDatepicker : true });
// validate the form's initial content for a date
var initialDate = $this.val();
if (initialDate && dateRegEx.test(initialDate)) {
var chosendate = new Date(initialDate);
} else if (opts.chosendate.constructor == Date) {
var chosendate = opts.chosendate;
} else if (opts.chosendate) {
var chosendate = new Date(opts.chosendate);
} else {
var chosendate = today;
}
// insert the datepicker in the DOM
datepicker = newDatepickerHTML();
jQuery("body").prepend(datepicker);
// position the datepicker
var elPos = findPosition($this.get(0));
var x = (parseInt(opts.x) ? parseInt(opts.x) : 0) + elPos[0];
var y = (parseInt(opts.y) ? parseInt(opts.y) : 0) + elPos[1];
jQuery(datepicker).css({ position: 'absolute', left: x, top: y });
// bind events to the table controls
jQuery("span", datepicker).css("cursor","pointer");
jQuery("select", datepicker).bind('change', function () { loadMonth (null, $this, datepicker, chosendate); });
jQuery("span.prevMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); });
jQuery("span.nextMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); });
jQuery("span.today", datepicker).click(function () { closeIt($this, datepicker, new Date()); });
jQuery("span.close", datepicker).click(function () { closeIt($this, datepicker); });
// set the initial values for the month and year select fields
// and load the first month
jQuery("select[name=month]", datepicker).get(0).selectedIndex = chosendate.getMonth();
jQuery("select[name=year]", datepicker).get(0).selectedIndex = Math.max(0, chosendate.getFullYear() - opts.startyear);
loadMonth(null, $this, datepicker, chosendate);
}
});
}
});
};
// finally, I like to expose default plugin options as public so they can be manipulated. one
// way to do this is to add a property to the already-public plugin fn
jQuery.fn.simpleDatepicker.formatOutput = function (dateObj) {
return (dateObj.getMonth() + 1) + "/" + dateObj.getDate() + "/" + dateObj.getFullYear();
};
jQuery.fn.simpleDatepicker.defaults = {
// date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/
chosendate : today,
// date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/
// or four digit year
startdate : today.getFullYear(),
enddate : today.getFullYear() + 1,
// offset from the top left corner of the input element
x : 1, // must be in px
y : 18 // must be in px
};
})(jQuery);
// Init the form
$(document).ready(function(){
$('#date_first').simpleDatepicker({startdate: 2005, enddate: 2100});
$('#date_second').simpleDatepicker({startdate: 2005, enddate: 2100});
$('#date_filter').change(function(){
var show = $(this).val() == 'between' ? 'inline' : 'none';
$('#date_second').css('display', show);
$('#date_and').css('display', show);
});
/**
the script only works on "input [type=text]"
http://teddevito.com/demos/calendar.php
**/
// don't declare anything out here in the global namespace
(function($) { // create private scope (inside you can use $ instead of jQuery)
// functions and vars declared here are effectively 'singletons'. there will be only a single
// instance of them. so this is a good place to declare any immutable items or stateless
// functions. for example:
var today = new Date(); // used in defaults
var months = 'January,February,March,April,May,June,July,August,September,October,November,December'.split(',');
var months = l10n_cal_month;
var monthlengths = '31,28,31,30,31,30,31,31,30,31,30,31'.split(',');
var dateRegEx = /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/;
var yearRegEx = /^\d{4,4}$/;
// next, declare the plugin function
$.fn.simpleDatepicker = function(options) {
// functions and vars declared here are created each time your plugn function is invoked
// you could probably refactor your 'build', 'load_month', etc, functions to be passed
// the DOM element from below
var opts = jQuery.extend({}, jQuery.fn.simpleDatepicker.defaults, options);
// replaces a date string with a date object in opts.startdate and opts.enddate, if one exists
// populates two new properties with a ready-to-use year: opts.startyear and opts.endyear
setupYearRange();
/** extracts and setup a valid year range from the opts object **/
function setupYearRange () {
var startyear, endyear;
if (opts.startdate.constructor == Date) {
startyear = opts.startdate.getFullYear();
} else if (opts.startdate) {
if (yearRegEx.test(opts.startdate)) {
startyear = opts.startdate;
} else if (dateRegEx.test(opts.startdate)) {
opts.startdate = new Date(opts.startdate);
startyear = opts.startdate.getFullYear();
} else {
startyear = today.getFullYear();
}
} else {
startyear = today.getFullYear();
}
opts.startyear = startyear;
if (opts.enddate.constructor == Date) {
endyear = opts.enddate.getFullYear();
} else if (opts.enddate) {
if (yearRegEx.test(opts.enddate)) {
endyear = opts.enddate;
} else if (dateRegEx.test(opts.enddate)) {
opts.enddate = new Date(opts.enddate);
endyear = opts.enddate.getFullYear();
} else {
endyear = today.getFullYear();
}
} else {
endyear = today.getFullYear();
}
opts.endyear = endyear;
}
/** HTML factory for the actual datepicker table element **/
// has to read the year range so it can setup the correct years in our HTML <select>
function newDatepickerHTML () {
var years = [];
// process year range into an array
for (var i = 0; i <= opts.endyear - opts.startyear; i ++) years[i] = opts.startyear + i;
// build the table structure
var table = jQuery('<table class="datepicker" cellpadding="0" cellspacing="0"></table>');
table.append('<thead></thead>');
table.append('<tfoot></tfoot>');
table.append('<tbody></tbody>');
// month select field
var monthselect = '<select name="month">';
for (var i in l10n_cal_month) monthselect += '<option value="'+i+'">'+l10n_cal_month[i]+'</option>';
monthselect += '</select>';
// year select field
var yearselect = '<select name="year">';
for (var i in years) yearselect += '<option>'+years[i]+'</option>';
yearselect += '</select>';
jQuery("thead",table).append('<tr class="controls"><th colspan="7"><span class="prevMonth">&laquo;</span>&nbsp;'+monthselect+yearselect+'&nbsp;<span class="nextMonth">&raquo;</span></th></tr>');
jQuery("thead",table).append('<tr class="days"><th>'+l10n_cal_days[0]+'</th><th>'+l10n_cal_days[1]+'</th><th>'+l10n_cal_days[2]+'</th><th>'+l10n_cal_days[3]+'</th><th>'+l10n_cal_days[4]+'</th><th>'+l10n_cal_days[5]+'</th><th>'+l10n_cal_days[6]+'</th></tr>');
jQuery("tfoot",table).append('<tr><td colspan="2"><span class="today">'+l10n_cal_today+'</span></td><td colspan="3">&nbsp;</td><td colspan="2"><span class="close">'+l10n_cal_close+'</span></td></tr>');
for (var i = 0; i < 6; i++) jQuery("tbody",table).append('<tr><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>');
return table;
}
/** get the real position of the input (well, anything really) **/
//http://www.quirksmode.org/js/findpos.html
function findPosition (obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return [curleft,curtop];
} else {
return false;
}
}
/** load the initial date and handle all date-navigation **/
// initial calendar load (e is null)
// prevMonth & nextMonth buttons
// onchange for the select fields
function loadMonth (e, el, datepicker, chosendate) {
// reference our years for the nextMonth and prevMonth buttons
var mo = jQuery("select[name=month]", datepicker).get(0).selectedIndex;
var yr = jQuery("select[name=year]", datepicker).get(0).selectedIndex;
var yrs = jQuery("select[name=year] option", datepicker).get().length;
// first try to process buttons that may change the month we're on
if (e && jQuery(e.target).hasClass('prevMonth')) {
if (0 == mo && yr) {
yr -= 1; mo = 11;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = 11;
jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr;
} else {
mo -= 1;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo;
}
} else if (e && jQuery(e.target).hasClass('nextMonth')) {
if (11 == mo && yr + 1 < yrs) {
yr += 1; mo = 0;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = 0;
jQuery("select[name=year]", datepicker).get(0).selectedIndex = yr;
} else {
mo += 1;
jQuery("select[name=month]", datepicker).get(0).selectedIndex = mo;
}
}
// maybe hide buttons
if (0 == mo && !yr) jQuery("span.prevMonth", datepicker).hide();
else jQuery("span.prevMonth", datepicker).show();
if (yr + 1 == yrs && 11 == mo) jQuery("span.nextMonth", datepicker).hide();
else jQuery("span.nextMonth", datepicker).show();
// clear the old cells
var cells = jQuery("tbody td", datepicker).unbind().empty().removeClass('date');
// figure out what month and year to load
var m = jQuery("select[name=month]", datepicker).val();
var y = jQuery("select[name=year]", datepicker).val();
var d = new Date(y, m, 1);
var startindex = d.getDay();
var numdays = monthlengths[m];
// http://en.wikipedia.org/wiki/Leap_year
if (1 == m && ((y%4 == 0 && y%100 != 0) || y%400 == 0)) numdays = 29;
// test for end dates (instead of just a year range)
if (opts.startdate.constructor == Date) {
var startMonth = opts.startdate.getMonth();
var startDate = opts.startdate.getDate();
}
if (opts.enddate.constructor == Date) {
var endMonth = opts.enddate.getMonth();
var endDate = opts.enddate.getDate();
}
// walk through the index and populate each cell, binding events too
for (var i = 0; i < numdays; i++) {
var cell = jQuery(cells.get(i+startindex)).removeClass('chosen');
// test that the date falls within a range, if we have a range
if (
(yr || ((!startDate && !startMonth) || ((i+1 >= startDate && mo == startMonth) || mo > startMonth))) &&
(yr + 1 < yrs || ((!endDate && !endMonth) || ((i+1 <= endDate && mo == endMonth) || mo < endMonth)))) {
cell
.text(i+1)
.addClass('date')
.hover(
function () { jQuery(this).addClass('over'); },
function () { jQuery(this).removeClass('over'); })
.click(function () {
var chosenDateObj = new Date(jQuery("select[name=year]", datepicker).val(), jQuery("select[name=month]", datepicker).val(), jQuery(this).text());
closeIt(el, datepicker, chosenDateObj);
});
// highlight the previous chosen date
if (i+1 == chosendate.getDate() && m == chosendate.getMonth() && y == chosendate.getFullYear()) cell.addClass('chosen');
}
}
}
/** closes the datepicker **/
// sets the currently matched input element's value to the date, if one is available
// remove the table element from the DOM
// indicate that there is no datepicker for the currently matched input element
function closeIt (el, datepicker, dateObj) {
if (dateObj && dateObj.constructor == Date)
el.val(jQuery.fn.simpleDatepicker.formatOutput(dateObj));
datepicker.remove();
datepicker = null;
jQuery.data(el.get(0), "simpleDatepicker", { hasDatepicker : false });
}
// iterate the matched nodeset
return this.each(function() {
// functions and vars declared here are created for each matched element. so if
// your functions need to manage or access per-node state you can defined them
// here and use $this to get at the DOM element
if ( jQuery(this).is('input') && 'text' == jQuery(this).attr('type')) {
var datepicker;
jQuery.data(jQuery(this).get(0), "simpleDatepicker", { hasDatepicker : false });
// open a datepicker on the click event
jQuery(this).click(function (ev) {
var $this = jQuery(ev.target);
if (false == jQuery.data($this.get(0), "simpleDatepicker").hasDatepicker) {
// store data telling us there is already a datepicker
jQuery.data($this.get(0), "simpleDatepicker", { hasDatepicker : true });
// validate the form's initial content for a date
var initialDate = $this.val();
if (initialDate && dateRegEx.test(initialDate)) {
var chosendate = new Date(initialDate);
} else if (opts.chosendate.constructor == Date) {
var chosendate = opts.chosendate;
} else if (opts.chosendate) {
var chosendate = new Date(opts.chosendate);
} else {
var chosendate = today;
}
// insert the datepicker in the DOM
datepicker = newDatepickerHTML();
jQuery("body").prepend(datepicker);
// position the datepicker
var elPos = findPosition($this.get(0));
var x = (parseInt(opts.x) ? parseInt(opts.x) : 0) + elPos[0];
var y = (parseInt(opts.y) ? parseInt(opts.y) : 0) + elPos[1];
jQuery(datepicker).css({ position: 'absolute', left: x, top: y });
// bind events to the table controls
jQuery("span", datepicker).css("cursor","pointer");
jQuery("select", datepicker).bind('change', function () { loadMonth (null, $this, datepicker, chosendate); });
jQuery("span.prevMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); });
jQuery("span.nextMonth", datepicker).click(function (e) { loadMonth (e, $this, datepicker, chosendate); });
jQuery("span.today", datepicker).click(function () { closeIt($this, datepicker, new Date()); });
jQuery("span.close", datepicker).click(function () { closeIt($this, datepicker); });
// set the initial values for the month and year select fields
// and load the first month
jQuery("select[name=month]", datepicker).get(0).selectedIndex = chosendate.getMonth();
jQuery("select[name=year]", datepicker).get(0).selectedIndex = Math.max(0, chosendate.getFullYear() - opts.startyear);
loadMonth(null, $this, datepicker, chosendate);
}
});
}
});
};
// finally, I like to expose default plugin options as public so they can be manipulated. one
// way to do this is to add a property to the already-public plugin fn
jQuery.fn.simpleDatepicker.formatOutput = function (dateObj) {
return (dateObj.getMonth() + 1) + "/" + dateObj.getDate() + "/" + dateObj.getFullYear();
};
jQuery.fn.simpleDatepicker.defaults = {
// date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/
chosendate : today,
// date string matching /^\d{1,2}\/\d{1,2}\/\d{2}|\d{4}$/
// or four digit year
startdate : today.getFullYear(),
enddate : today.getFullYear() + 1,
// offset from the top left corner of the input element
x : 1, // must be in px
y : 18 // must be in px
};
})(jQuery);
// Init the form
$(document).ready(function(){
$('#date_first').simpleDatepicker({startdate: 2005, enddate: 2100});
$('#date_second').simpleDatepicker({startdate: 2005, enddate: 2100});
$('#date_filter').change(function(){
var show = $(this).val() == 'between' ? 'inline' : 'none';
$('#date_second').css('display', show);
$('#date_and').css('display', show);
});
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,57 +1,57 @@
$(document).ready(function(){
$('#tweet_body').focus();
$('#tweet_body').keypress(function(){
setTimeout( function(){update_share()}, 50 ); // we're delaying, otherwise keypress() always triggers too fast before current key press actually inserts a letter?!! Go figure.
});
})
function update_share() {
var text = encodeURIComponent( $('#tweet_body').val() );
var url = encodeURIComponent( $('#copylink').val() );
var tw = 'http://twitter.com/intent/tweet?status='+text;
var ff = 'http://friendfeed.com/share/bookmarklet/frame#title='+text ;
var fb = 'http://www.facebook.com/share.php?u='+url ;
$('#share_tw').attr('href', tw);
$('#share_ff').attr('href', ff);
$('#share_fb').attr('href', fb);
var charcount = parseInt(140 - $('#tweet_body').val().length);
$('#charcount')
.toggleClass("negative", charcount < 0)
.text( charcount );
}
function share(dest) {
var url = $('#share_'+dest).attr('href');
switch (dest) {
case 'ff':
//$('body').append('<script type="text/javascript" src="http://friendfeed.com/share/bookmarklet/javascript"></script>');
window.open(url, 'ff','toolbar=no,width=500,height=350');
break;
case 'fb':
//var url = $('#share_fb').attr('href');
window.open( url, 'fb','toolbar=no,width=1000,height=550');
break;
case 'tw':
//var url = $('#share_tw').attr('href');
window.open(url, 'tw','toolbar=no,width=800,height=550');
break;
}
return false;
}
function init_clipboard() {
$('#copylink').click(function(){
$(this).select();
})
$('#copylink').zclip({
path: zclipurl,
copy: $('#copylink').val(),
afterCopy:function(){
html_pulse( '#copybox h2, #copybox h3', 'Copied!' );
}
});
};
$(document).ready(function(){
$('#tweet_body').focus();
$('#tweet_body').keypress(function(){
setTimeout( function(){update_share()}, 50 ); // we're delaying, otherwise keypress() always triggers too fast before current key press actually inserts a letter?!! Go figure.
});
})
function update_share() {
var text = encodeURIComponent( $('#tweet_body').val() );
var url = encodeURIComponent( $('#copylink').val() );
var tw = 'http://twitter.com/intent/tweet?status='+text;
var ff = 'http://friendfeed.com/share/bookmarklet/frame#title='+text ;
var fb = 'http://www.facebook.com/share.php?u='+url ;
$('#share_tw').attr('href', tw);
$('#share_ff').attr('href', ff);
$('#share_fb').attr('href', fb);
var charcount = parseInt(140 - $('#tweet_body').val().length);
$('#charcount')
.toggleClass("negative", charcount < 0)
.text( charcount );
}
function share(dest) {
var url = $('#share_'+dest).attr('href');
switch (dest) {
case 'ff':
//$('body').append('<script type="text/javascript" src="http://friendfeed.com/share/bookmarklet/javascript"></script>');
window.open(url, 'ff','toolbar=no,width=500,height=350');
break;
case 'fb':
//var url = $('#share_fb').attr('href');
window.open( url, 'fb','toolbar=no,width=1000,height=550');
break;
case 'tw':
//var url = $('#share_tw').attr('href');
window.open(url, 'tw','toolbar=no,width=800,height=550');
break;
}
return false;
}
function init_clipboard() {
$('#copylink').click(function(){
$(this).select();
})
$('#copylink').zclip({
path: zclipurl,
copy: $('#copylink').val(),
afterCopy:function(){
html_pulse( '#copybox h2, #copybox h3', 'Copied!' );
}
});
};

View File

@ -1,23 +1,23 @@
<?php
// Make sure we're in YOURLS context
if( !defined( 'YOURLS_ABSPATH' ) ) {
// Attempt to guess URL via YOURLS
$url = 'http://' . $_SERVER['HTTP_HOST'] . str_replace( array( '/pages/', '.php' ) , array ( '/', '' ), $_SERVER['REQUEST_URI'] );
echo "Try this instead: <a href='$url'>$url</a>";
die();
}
// Display page content. Any PHP, HTML and YOURLS function can go here.
$url = YOURLS_SITE . '/examplepage';
yourls_html_head( 'examplepage', 'Example page' );
?>
<p>This is an example page. Its URL is simply <?php echo $url; ?></p>
<?php
yourls_html_footer();
<?php
// Make sure we're in YOURLS context
if( !defined( 'YOURLS_ABSPATH' ) ) {
// Attempt to guess URL via YOURLS
$url = 'http://' . $_SERVER['HTTP_HOST'] . str_replace( array( '/pages/', '.php' ) , array ( '/', '' ), $_SERVER['REQUEST_URI'] );
echo "Try this instead: <a href='$url'>$url</a>";
die();
}
// Display page content. Any PHP, HTML and YOURLS function can go here.
$url = YOURLS_SITE . '/examplepage';
yourls_html_head( 'examplepage', 'Example page' );
?>
<p>This is an example page. Its URL is simply <?php echo $url; ?></p>
<?php
yourls_html_footer();

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +1,13 @@
<?php
/*
* This file shows how to implement a public API (no login or username needed) for your setup
* even if your install is private (no public access to admin area)
*
* Rename this file like "api.php" and put it in the same directory as yourls-api.php
*
*/
define('YOURLS_PRIVATE', false);
<?php
/*
* This file shows how to implement a public API (no login or username needed) for your setup
* even if your install is private (no public access to admin area)
*
* Rename this file like "api.php" and put it in the same directory as yourls-api.php
*
*/
define('YOURLS_PRIVATE', false);
require_once( dirname(__FILE__).'/yourls-api.php' );

View File

@ -1,116 +1,116 @@
<?php
/*
* This is an example file for a public interface and a bookmarklet. It
* is provided so you can build from it and customize to suit your needs.
* It's not really part of the project. Don't submit feature requests
* about this file. It's _your_ job to make it what you need it to be :)
*
* Rename to .php
*
*/
// Start YOURLS engine
require_once( dirname(__FILE__).'/includes/load-yourls.php' );
// Change this to match the URL of your public interface. Something like: http://yoursite.com/index.php
$page = YOURLS_SITE . '/sample-public-front-page.php' ;
// Part to be executed if FORM has been submitted
if ( isset( $_REQUEST['url'] ) && $_REQUEST['url'] != 'http://' ) {
// Get parameters -- they will all be sanitized in yourls_add_new_link()
$url = $_REQUEST['url'];
$keyword = isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ;
$title = isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ;
$text = isset( $_REQUEST['text'] ) ? $_REQUEST['text'] : '' ;
// Create short URL, receive array $return with various information
$return = yourls_add_new_link( $url, $keyword, $title );
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
$message = isset( $return['message'] ) ? $return['message'] : '';
$title = isset( $return['title'] ) ? $return['title'] : '';
// Stop here if bookmarklet with a JSON callback function ("instant" bookmarklets)
if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
$short = $return['shorturl'] ? $return['shorturl'] : '';
$message = "Short URL (Ctrl+C to copy)";
header('Content-type: application/json');
echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
die();
}
}
// Insert <head> markup and all CSS & JS files
yourls_html_head();
// Display title
echo "<h1>YOURLS - Your Own URL Shortener</h1>\n";
// Display left hand menu
yourls_html_menu() ;
// Part to be executed if FORM has been submitted
if ( isset( $_REQUEST['url'] ) && $_REQUEST['url'] != 'http://' ) {
// Display result message of short link creation
if( isset( $message ) ) {
echo "<h2>$message</h2>";
}
// Include the Copy box and the Quick Share box
yourls_share_box( $url, $shorturl, $title, $text );
// Initialize clipboard -- requires js/share.js and js/jquery.zclip.min.js to be properly loaded in the <head>
echo <<<JS
<script>
init_clipboard();
</script>
JS;
// Part to be executed when no form has been submitted
} else {
$site = YOURLS_SITE;
// Display the form
echo <<<HTML
<h2>Enter a new URL to shorten</h2>
<form method="post" action="">
<p><label>URL: <input type="text" class="text" name="url" value="http://" /></label></p>
<p><label>Optional custom short URL: $site/<input type="text" class="text" name="keyword" /></label></p>
<p><label>Optional title: <input type="text" class="text" name="title" /></label></p>
<p><input type="submit" class="button primary" value="Shorten" /></p>
</form>
HTML;
}
?>
<h2>Bookmarklets</h2>
<p>Bookmark these links:</p>
<p>
<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:enc(s)),f='<?php echo $page; ?>',l=d.location,p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+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">Simple Shorten</a>
<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 $page; ?>?url='+encodeURIComponent(d.location.href)+'&jsonp=yourls';void(d.body.appendChild(s));%7D)();" class="bookmarklet">Instant Shorten</a>
<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:enc(s)),f='<?php echo $page; ?>',l=d.location,k=prompt(%22Custom%20URL%22),k2=(k?'&keyword='+k:%22%22),p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+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">Custom Shorten</a>
<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 $page; ?>?url='+encodeURIComponent(d.location.href)+'&keyword='+k+'&jsonp=yourls';void(d.body.appendChild(s));%7D%7D)();" class="bookmarklet">Instant Custom Shorten</a>
</p>
<h2>Please note</h2>
<p>Be aware that a public interface <strong>will</strong> attract spammers. You are strongly advised to install anti spam plugins and any appropriate counter measure to deal with this issue.</p>
<?php
// Display page footer
yourls_html_footer();
<?php
/*
* This is an example file for a public interface and a bookmarklet. It
* is provided so you can build from it and customize to suit your needs.
* It's not really part of the project. Don't submit feature requests
* about this file. It's _your_ job to make it what you need it to be :)
*
* Rename to .php
*
*/
// Start YOURLS engine
require_once( dirname(__FILE__).'/includes/load-yourls.php' );
// Change this to match the URL of your public interface. Something like: http://yoursite.com/index.php
$page = YOURLS_SITE . '/sample-public-front-page.php' ;
// Part to be executed if FORM has been submitted
if ( isset( $_REQUEST['url'] ) && $_REQUEST['url'] != 'http://' ) {
// Get parameters -- they will all be sanitized in yourls_add_new_link()
$url = $_REQUEST['url'];
$keyword = isset( $_REQUEST['keyword'] ) ? $_REQUEST['keyword'] : '' ;
$title = isset( $_REQUEST['title'] ) ? $_REQUEST['title'] : '' ;
$text = isset( $_REQUEST['text'] ) ? $_REQUEST['text'] : '' ;
// Create short URL, receive array $return with various information
$return = yourls_add_new_link( $url, $keyword, $title );
$shorturl = isset( $return['shorturl'] ) ? $return['shorturl'] : '';
$message = isset( $return['message'] ) ? $return['message'] : '';
$title = isset( $return['title'] ) ? $return['title'] : '';
// Stop here if bookmarklet with a JSON callback function ("instant" bookmarklets)
if( isset( $_GET['jsonp'] ) && $_GET['jsonp'] == 'yourls' ) {
$short = $return['shorturl'] ? $return['shorturl'] : '';
$message = "Short URL (Ctrl+C to copy)";
header('Content-type: application/json');
echo yourls_apply_filter( 'bookmarklet_jsonp', "yourls_callback({'short_url':'$short','message':'$message'});" );
die();
}
}
// Insert <head> markup and all CSS & JS files
yourls_html_head();
// Display title
echo "<h1>YOURLS - Your Own URL Shortener</h1>\n";
// Display left hand menu
yourls_html_menu() ;
// Part to be executed if FORM has been submitted
if ( isset( $_REQUEST['url'] ) && $_REQUEST['url'] != 'http://' ) {
// Display result message of short link creation
if( isset( $message ) ) {
echo "<h2>$message</h2>";
}
// Include the Copy box and the Quick Share box
yourls_share_box( $url, $shorturl, $title, $text );
// Initialize clipboard -- requires js/share.js and js/jquery.zclip.min.js to be properly loaded in the <head>
echo <<<JS
<script>
init_clipboard();
</script>
JS;
// Part to be executed when no form has been submitted
} else {
$site = YOURLS_SITE;
// Display the form
echo <<<HTML
<h2>Enter a new URL to shorten</h2>
<form method="post" action="">
<p><label>URL: <input type="text" class="text" name="url" value="http://" /></label></p>
<p><label>Optional custom short URL: $site/<input type="text" class="text" name="keyword" /></label></p>
<p><label>Optional title: <input type="text" class="text" name="title" /></label></p>
<p><input type="submit" class="button primary" value="Shorten" /></p>
</form>
HTML;
}
?>
<h2>Bookmarklets</h2>
<p>Bookmark these links:</p>
<p>
<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:enc(s)),f='<?php echo $page; ?>',l=d.location,p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+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">Simple Shorten</a>
<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 $page; ?>?url='+encodeURIComponent(d.location.href)+'&jsonp=yourls';void(d.body.appendChild(s));%7D)();" class="bookmarklet">Instant Shorten</a>
<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:enc(s)),f='<?php echo $page; ?>',l=d.location,k=prompt(%22Custom%20URL%22),k2=(k?'&keyword='+k:%22%22),p='?url='+enc(l.href)+'&title='+enc(d.title)+'&text='+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">Custom Shorten</a>
<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 $page; ?>?url='+encodeURIComponent(d.location.href)+'&keyword='+k+'&jsonp=yourls';void(d.body.appendChild(s));%7D%7D)();" class="bookmarklet">Instant Custom Shorten</a>
</p>
<h2>Please note</h2>
<p>Be aware that a public interface <strong>will</strong> attract spammers. You are strongly advised to install anti spam plugins and any appropriate counter measure to deal with this issue.</p>
<?php
// Display page footer
yourls_html_footer();

View File

@ -1,47 +1,47 @@
<?php
/*
* YOURLS : sample file showing how to use the API
* This shows how to tap into your YOURLS install API from *ANOTHER* server
* not from a file hosted on the same server. It's just a bit dumb to make a
* remote HTTP request to the server the request originates from.
*
* Rename to .php
*
*/
// EDIT THIS: your auth parameters
$username = 'joe';
$password = '123456';
// EDIT THIS: the query parameters
$url = 'http://planetozh.com/blog/'; // URL to shrink
$keyword = 'ozh'; // optional keyword
$format = 'json'; // output format: 'json', 'xml' or 'simple'
// EDIT THIS: the URL of the API file
$api_url = 'http://yoursite/yourls-api.php';
// Init the CURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result
curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request
curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST
'url' => $url,
'keyword' => $keyword,
'format' => $format,
'action' => 'shorturl',
'username' => $username,
'password' => $password
));
// Fetch and return content
$data = curl_exec($ch);
curl_close($ch);
// Do something with the result. Here, we just echo it.
echo $data;
<?php
/*
* YOURLS : sample file showing how to use the API
* This shows how to tap into your YOURLS install API from *ANOTHER* server
* not from a file hosted on the same server. It's just a bit dumb to make a
* remote HTTP request to the server the request originates from.
*
* Rename to .php
*
*/
// EDIT THIS: your auth parameters
$username = 'joe';
$password = '123456';
// EDIT THIS: the query parameters
$url = 'http://planetozh.com/blog/'; // URL to shrink
$keyword = 'ozh'; // optional keyword
$format = 'json'; // output format: 'json', 'xml' or 'simple'
// EDIT THIS: the URL of the API file
$api_url = 'http://yoursite/yourls-api.php';
// Init the CURL session
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $api_url);
curl_setopt($ch, CURLOPT_HEADER, 0); // No header in the result
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return, do not echo result
curl_setopt($ch, CURLOPT_POST, 1); // This is a POST request
curl_setopt($ch, CURLOPT_POSTFIELDS, array( // Data to POST
'url' => $url,
'keyword' => $keyword,
'format' => $format,
'action' => 'shorturl',
'username' => $username,
'password' => $password
));
// Fetch and return content
$data = curl_exec($ch);
curl_close($ch);
// Do something with the result. Here, we just echo it.
echo $data;
?>

View File

@ -1,9 +1,9 @@
User-agent: *
Disallow: /admin
Disallow: /css
Disallow: /images
Disallow: /includes
Disallow: /js
Disallow: /pages
Disallow: /user
User-agent: *
Disallow: /admin
Disallow: /css
Disallow: /images
Disallow: /includes
Disallow: /js
Disallow: /pages
Disallow: /user

View File

@ -1,85 +1,85 @@
<?php
/* This is a sample config file.
* Edit this file with your own settings and save it as "config.php"
*/
/*
** MySQL settings - You can get this info from your web host
*/
/** MySQL database username */
define( 'YOURLS_DB_USER', 'your db user name' );
/** MySQL database password */
define( 'YOURLS_DB_PASS', 'your db password' );
/** The name of the database for YOURLS */
define( 'YOURLS_DB_NAME', 'yourls' );
/** MySQL hostname */
define( 'YOURLS_DB_HOST', 'localhost' );
/** MySQL tables prefix */
define( 'YOURLS_DB_PREFIX', 'yourls_' );
/*
** Site options
*/
/** YOURLS installation URL -- all lowercase and with no trailing slash.
** If you define it to "http://site.com", don't use "http://www.site.com" in your browser (and vice-versa) */
define( 'YOURLS_SITE', 'http://site.com' );
/** Timezone GMT offset */
define( 'YOURLS_HOURS_OFFSET', 0 );
/** YOURLS language or "locale".
** Change this setting to "localize" YOURLS (use a translation instead of the default English). A corresponding .mo file
** must be installed in the user/language directory.
** See http://yourls.org/translations for more information */
define( 'YOURLS_LANG', '' );
/** Allow multiple short URLs for a same long URL
** Set to true to have only one pair of shortURL/longURL (default YOURLS behavior)
** Set to false to allow multiple short URLs pointing to the same long URL (bit.ly behavior) */
define( 'YOURLS_UNIQUE_URLS', true );
/** Private means the Admin area will be protected with login/pass as defined below.
** Set to false for public usage (eg on a restricted intranet or for test setups)
** Read http://yourls.org/privatepublic for more details if you're unsure */
define( 'YOURLS_PRIVATE', true );
/** A random secret hash used to encrypt cookies. You don't have to remember it, make it long and complicated. Hint: copy from http://yourls.org/cookie **/
define( 'YOURLS_COOKIEKEY', 'modify this text with something random' );
/** Username(s) and password(s) allowed to access the site. Passwords either in plain text or as salted hashes.
** Read http://yourls.org/userpassword for more information */
$yourls_user_passwords = array(
'username' => 'password',
'username2' => 'password2' // You can have one or more 'login'=>'password' lines
);
/*
** URL Shortening settings
*/
/** URL shortening method: 36 or 62 */
define( 'YOURLS_URL_CONVERT', 36 );
/*
* 36: generates all lowercase keywords (ie: 13jkm)
* 62: generates mixed case keywords (ie: 13jKm or 13JKm)
* Stick to one setting. It's best not to change after you've started creating links.
*/
/**
* Reserved keywords (so that generated URLs won't match them)
* Define here negative, unwanted or potentially misleading keywords.
*/
$yourls_reserved_URL = array(
'porn', 'faggot', 'sex', 'nigger', 'fuck', 'cunt', 'dick', 'gay',
);
/*
** Personal settings would go after here.
*/
<?php
/* This is a sample config file.
* Edit this file with your own settings and save it as "config.php"
*/
/*
** MySQL settings - You can get this info from your web host
*/
/** MySQL database username */
define( 'YOURLS_DB_USER', 'your db user name' );
/** MySQL database password */
define( 'YOURLS_DB_PASS', 'your db password' );
/** The name of the database for YOURLS */
define( 'YOURLS_DB_NAME', 'yourls' );
/** MySQL hostname */
define( 'YOURLS_DB_HOST', 'localhost' );
/** MySQL tables prefix */
define( 'YOURLS_DB_PREFIX', 'yourls_' );
/*
** Site options
*/
/** YOURLS installation URL -- all lowercase and with no trailing slash.
** If you define it to "http://site.com", don't use "http://www.site.com" in your browser (and vice-versa) */
define( 'YOURLS_SITE', 'http://site.com' );
/** Timezone GMT offset */
define( 'YOURLS_HOURS_OFFSET', 0 );
/** YOURLS language or "locale".
** Change this setting to "localize" YOURLS (use a translation instead of the default English). A corresponding .mo file
** must be installed in the user/language directory.
** See http://yourls.org/translations for more information */
define( 'YOURLS_LANG', '' );
/** Allow multiple short URLs for a same long URL
** Set to true to have only one pair of shortURL/longURL (default YOURLS behavior)
** Set to false to allow multiple short URLs pointing to the same long URL (bit.ly behavior) */
define( 'YOURLS_UNIQUE_URLS', true );
/** Private means the Admin area will be protected with login/pass as defined below.
** Set to false for public usage (eg on a restricted intranet or for test setups)
** Read http://yourls.org/privatepublic for more details if you're unsure */
define( 'YOURLS_PRIVATE', true );
/** A random secret hash used to encrypt cookies. You don't have to remember it, make it long and complicated. Hint: copy from http://yourls.org/cookie **/
define( 'YOURLS_COOKIEKEY', 'modify this text with something random' );
/** Username(s) and password(s) allowed to access the site. Passwords either in plain text or as salted hashes.
** Read http://yourls.org/userpassword for more information */
$yourls_user_passwords = array(
'username' => 'password',
'username2' => 'password2' // You can have one or more 'login'=>'password' lines
);
/*
** URL Shortening settings
*/
/** URL shortening method: 36 or 62 */
define( 'YOURLS_URL_CONVERT', 36 );
/*
* 36: generates all lowercase keywords (ie: 13jkm)
* 62: generates mixed case keywords (ie: 13jKm or 13JKm)
* Stick to one setting. It's best not to change after you've started creating links.
*/
/**
* Reserved keywords (so that generated URLs won't match them)
* Define here negative, unwanted or potentially misleading keywords.
*/
$yourls_reserved_URL = array(
'porn', 'faggot', 'sex', 'nigger', 'fuck', 'cunt', 'dick', 'gay',
);
/*
** Personal settings would go after here.
*/

View File

@ -1,4 +1,4 @@
This is a core plugin, bundled with YOURLS.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
This is a core plugin, bundled with YOURLS.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
be overwritten when you upgrade YOURLS.

View File

@ -1,19 +1,19 @@
<?php
/*
Plugin Name: Allow Hyphens in Short URLs
Plugin URI: http://yourls.org/
Description: Allow hyphens in short URLs (like <tt>http://sho.rt/hello-world</tt>)
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
yourls_add_filter( 'get_shorturl_charset', 'ozh_hyphen_in_charset' );
function ozh_hyphen_in_charset( $in ) {
return $in.'-';
}
<?php
/*
Plugin Name: Allow Hyphens in Short URLs
Plugin URI: http://yourls.org/
Description: Allow hyphens in short URLs (like <tt>http://sho.rt/hello-world</tt>)
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
yourls_add_filter( 'get_shorturl_charset', 'ozh_hyphen_in_charset' );
function ozh_hyphen_in_charset( $in ) {
return $in.'-';
}

View File

@ -1,4 +1,4 @@
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
be overwritten when you upgrade YOURLS.

View File

@ -1,27 +1,27 @@
<?php
/*
Plugin Name: Random Backgrounds
Plugin URI: http://yourls.org/
Description: Pretty random background patterns
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
// Add the inline style
yourls_add_action( 'html_head', 'ozh_yourls_randombg' );
function ozh_yourls_randombg() {
$bg = glob( dirname( __FILE__ ).'/img/*png' );
$url = yourls_plugin_url( dirname( __FILE__ ) );
$rnd = yourls_plugin_url( $bg[ mt_rand( 0, count( $bg ) - 1 ) ] );
echo <<<CSS
<style type="text/css">
body {background:#e3f3ff url($rnd) repeat;}
</style>
CSS;
}
<?php
/*
Plugin Name: Random Backgrounds
Plugin URI: http://yourls.org/
Description: Pretty random background patterns
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
// Add the inline style
yourls_add_action( 'html_head', 'ozh_yourls_randombg' );
function ozh_yourls_randombg() {
$bg = glob( dirname( __FILE__ ).'/img/*png' );
$url = yourls_plugin_url( dirname( __FILE__ ) );
$rnd = yourls_plugin_url( $bg[ mt_rand( 0, count( $bg ) - 1 ) ] );
echo <<<CSS
<style type="text/css">
body {background:#e3f3ff url($rnd) repeat;}
</style>
CSS;
}

View File

@ -1,4 +1,4 @@
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
be overwritten when you upgrade YOURLS.

View File

@ -1,63 +1,63 @@
<?php
/*
Plugin Name: Sample Admin Page
Plugin URI: http://yourls.org/
Description: A example of a plugin administration page to save user defined option
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
// Register our plugin admin page
yourls_add_action( 'plugins_loaded', 'ozh_yourls_samplepage_add_page' );
function ozh_yourls_samplepage_add_page() {
yourls_register_plugin_page( 'sample_page', 'Sample Admin Page', 'ozh_yourls_samplepage_do_page' );
// parameters: page slug, page title, and function that will display the page itself
}
// Display admin page
function ozh_yourls_samplepage_do_page() {
// Check if a form was submitted
if( isset( $_POST['test_option'] ) ) {
// Check nonce
yourls_verify_nonce( 'sample_page' );
// Process form
ozh_yourls_samplepage_update_option();
}
// Get value from database
$test_option = yourls_get_option( 'test_option' );
// Create nonce
$nonce = yourls_create_nonce( 'sample_page' );
echo <<<HTML
<h2>Sample Plugin Administration Page</h2>
<p>This plugin stores an integer in the option database</p>
<form method="post">
<input type="hidden" name="nonce" value="$nonce" />
<p><label for="test_option">Enter an integer</label> <input type="text" id="test_option" name="test_option" value="$test_option" /></p>
<p><input type="submit" value="Update value" /></p>
</form>
HTML;
}
// Update option in database
function ozh_yourls_samplepage_update_option() {
$in = $_POST['test_option'];
if( $in ) {
// Validate test_option. ALWAYS validate and sanitize user input.
// Here, we want an integer
$in = intval( $in);
// Update value in database
yourls_update_option( 'test_option', $in );
}
<?php
/*
Plugin Name: Sample Admin Page
Plugin URI: http://yourls.org/
Description: A example of a plugin administration page to save user defined option
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
// Register our plugin admin page
yourls_add_action( 'plugins_loaded', 'ozh_yourls_samplepage_add_page' );
function ozh_yourls_samplepage_add_page() {
yourls_register_plugin_page( 'sample_page', 'Sample Admin Page', 'ozh_yourls_samplepage_do_page' );
// parameters: page slug, page title, and function that will display the page itself
}
// Display admin page
function ozh_yourls_samplepage_do_page() {
// Check if a form was submitted
if( isset( $_POST['test_option'] ) ) {
// Check nonce
yourls_verify_nonce( 'sample_page' );
// Process form
ozh_yourls_samplepage_update_option();
}
// Get value from database
$test_option = yourls_get_option( 'test_option' );
// Create nonce
$nonce = yourls_create_nonce( 'sample_page' );
echo <<<HTML
<h2>Sample Plugin Administration Page</h2>
<p>This plugin stores an integer in the option database</p>
<form method="post">
<input type="hidden" name="nonce" value="$nonce" />
<p><label for="test_option">Enter an integer</label> <input type="text" id="test_option" name="test_option" value="$test_option" /></p>
<p><input type="submit" value="Update value" /></p>
</form>
HTML;
}
// Update option in database
function ozh_yourls_samplepage_update_option() {
$in = $_POST['test_option'];
if( $in ) {
// Validate test_option. ALWAYS validate and sanitize user input.
// Here, we want an integer
$in = intval( $in);
// Update value in database
yourls_update_option( 'test_option', $in );
}
}

View File

@ -1,4 +1,4 @@
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
be overwritten when you upgrade YOURLS.

View File

@ -1,61 +1,61 @@
<?php
/*
Plugin Name: Sample Plugin
Plugin URI: http://yourls.org/
Description: Sample plugin to illustrate how actions and filters work. Read its source. Refer to the <a href="http://yourls.org/pluginapi">Plugin API documentation</a> for more details.
Version: 0.1
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
/* Example of an action
*
* We're going to add an entry to the menu.
*
* The menu is drawn by function yourls_html_menu() in file includes/functions-html.php.
* Right before the function outputs the closing </ul>, notice the following function call:
* yourls_do_action( 'admin_menu' );
* This function says: "hey, for your information, I've just done something called 'admin menu', thought I'd let you know..."
*
* We're going to hook into this action and add our menu entry
*/
yourls_add_action( 'admin_menu', 'ozh_sample_add_menu' );
/* This says: when YOURLS does action 'admin_menu', call function 'ozh_sample_add_menu'
*/
function ozh_sample_add_menu() {
echo '<li><a href="http://ozh.org/">Ozh</a></li>';
}
/* And that's it. Activate the plugin and notice the new menu entry.
*/
/* Example of a filter
*
* We're going to modify the <title> of pages in the admin area
*
* The <title> tag is generated by function yourls_html_head() in includes/functions-html.php
* Notice the following function call:
* $title = yourls_apply_filter( 'html_title', 'YOURLS: Your Own URL Shortener' );
* This function means: give $title the value "YOURLS: Your Own URL Shortener", unless a
* filter modifies this value.
*
* We're going to hook into this filter and modify this value.
*/
yourls_add_filter( 'html_title', 'ozh_sample_change_title' );
/* This says: when filter 'html_title' is triggered, send its value to function 'ozh_sample_change_title'
* and use what this function will return.
*/
function ozh_sample_change_title( $value ) {
$value = $value . ' (we have hacked this title)';
return $value; // a filter *always* has to return a value
}
/* And that's it. Activate the plugin and notice how the page title changes */
<?php
/*
Plugin Name: Sample Plugin
Plugin URI: http://yourls.org/
Description: Sample plugin to illustrate how actions and filters work. Read its source. Refer to the <a href="http://yourls.org/pluginapi">Plugin API documentation</a> for more details.
Version: 0.1
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
/* Example of an action
*
* We're going to add an entry to the menu.
*
* The menu is drawn by function yourls_html_menu() in file includes/functions-html.php.
* Right before the function outputs the closing </ul>, notice the following function call:
* yourls_do_action( 'admin_menu' );
* This function says: "hey, for your information, I've just done something called 'admin menu', thought I'd let you know..."
*
* We're going to hook into this action and add our menu entry
*/
yourls_add_action( 'admin_menu', 'ozh_sample_add_menu' );
/* This says: when YOURLS does action 'admin_menu', call function 'ozh_sample_add_menu'
*/
function ozh_sample_add_menu() {
echo '<li><a href="http://ozh.org/">Ozh</a></li>';
}
/* And that's it. Activate the plugin and notice the new menu entry.
*/
/* Example of a filter
*
* We're going to modify the <title> of pages in the admin area
*
* The <title> tag is generated by function yourls_html_head() in includes/functions-html.php
* Notice the following function call:
* $title = yourls_apply_filter( 'html_title', 'YOURLS: Your Own URL Shortener' );
* This function means: give $title the value "YOURLS: Your Own URL Shortener", unless a
* filter modifies this value.
*
* We're going to hook into this filter and modify this value.
*/
yourls_add_filter( 'html_title', 'ozh_sample_change_title' );
/* This says: when filter 'html_title' is triggered, send its value to function 'ozh_sample_change_title'
* and use what this function will return.
*/
function ozh_sample_change_title( $value ) {
$value = $value . ' (we have hacked this title)';
return $value; // a filter *always* has to return a value
}
/* And that's it. Activate the plugin and notice how the page title changes */

View File

@ -1,4 +1,4 @@
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
This is a sample plugin, for illustration purpose.
Don't modify this plugin. Instead, copy its folder
and modify your own copy. This way, your code won't
be overwritten when you upgrade YOURLS.

View File

@ -1,79 +1,79 @@
body {
margin:0;
overflow:hidden;
background-color:#fff;
font-size:12px;
font-family: Verdana, Arial;
padding:35px 0 0;
}
#yourls-frame {
width: 100%;
height:100%;
z-index: 1;
}
#yourls-bar {
font-family: Verdana, Arial;
font-size: 12px;
position:absolute;
top:0;
height:35px;
width:100%;
background:#e3f3ff url(../img/toolbar_bg.png) repeat-x bottom center;
color:#2A85B3;
-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.5);
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
z-index: 900000;
}
#yourls-bar a {
text-decoration:none;
color:#2A85B3;
}
#yourls-bar a:hover {
text-decoration:underline;
}
#yourls-about, #yourls-topsy, #yourls-delicious, #yourls-selfclose {
margin-left:10px;
float:left;
display:block;
top:5px;
position:relative;
}
#yourls-about a {
background:transparent url(../img/favicon.gif) center left no-repeat;
padding-left:20px;
color:inherit;
font-weight:bold;
}
#yourls-topsy {
width:300px;
}
#yourls-selfclose {
float:right;
margin-right:10px;
}
#yourls-once {
display:block;
text-indent:-9999px;
background:transparent url(../img/close_button.gif) center center no-repeat;
width:20px;
height:20px;
float:left;
}
#yourls-always {
display:none;
text-indent:-9999px;
background:transparent url(../img/close_button_red.gif) center center no-repeat;
width:20px;
height:20px;
float:left;
}
body {
margin:0;
overflow:hidden;
background-color:#fff;
font-size:12px;
font-family: Verdana, Arial;
padding:35px 0 0;
}
#yourls-frame {
width: 100%;
height:100%;
z-index: 1;
}
#yourls-bar {
font-family: Verdana, Arial;
font-size: 12px;
position:absolute;
top:0;
height:35px;
width:100%;
background:#e3f3ff url(../img/toolbar_bg.png) repeat-x bottom center;
color:#2A85B3;
-moz-box-shadow: 0 1px 5px rgba(0,0,0,0.5);
-webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.5);
z-index: 900000;
}
#yourls-bar a {
text-decoration:none;
color:#2A85B3;
}
#yourls-bar a:hover {
text-decoration:underline;
}
#yourls-about, #yourls-topsy, #yourls-delicious, #yourls-selfclose {
margin-left:10px;
float:left;
display:block;
top:5px;
position:relative;
}
#yourls-about a {
background:transparent url(../img/favicon.gif) center left no-repeat;
padding-left:20px;
color:inherit;
font-weight:bold;
}
#yourls-topsy {
width:300px;
}
#yourls-selfclose {
float:right;
margin-right:10px;
}
#yourls-once {
display:block;
text-indent:-9999px;
background:transparent url(../img/close_button.gif) center center no-repeat;
width:20px;
height:20px;
float:left;
}
#yourls-always {
display:none;
text-indent:-9999px;
background:transparent url(../img/close_button_red.gif) center center no-repeat;
width:20px;
height:20px;
float:left;
}

View File

@ -1,22 +1,22 @@
// If javascript is enabled, display the button
document.getElementById('yourls-always').style.display = 'block';
// When button clicked, store a cookie that says the user doesn't want a toolbar
document.getElementById('yourls-always').onclick = yourls_cookie_no_toolbar_please;
function yourls_cookie_no_toolbar_please() {
var exdate=new Date();
exdate.setDate( exdate.getDate()+365 ); // store 365 days
document.cookie = "yourls_no_toolbar=1;expires="+exdate.toUTCString() ;
}
// Get the number of delicious bookmarks
function yourls_get_books(json) {
if( json.length ) {
var books = json[0].total_posts.toString();
if( books ) {
document.getElementById('yourls-delicious-link').innerHTML = ' <b>'+books+'</b> bookmarks';
}
}
}
// If javascript is enabled, display the button
document.getElementById('yourls-always').style.display = 'block';
// When button clicked, store a cookie that says the user doesn't want a toolbar
document.getElementById('yourls-always').onclick = yourls_cookie_no_toolbar_please;
function yourls_cookie_no_toolbar_please() {
var exdate=new Date();
exdate.setDate( exdate.getDate()+365 ); // store 365 days
document.cookie = "yourls_no_toolbar=1;expires="+exdate.toUTCString() ;
}
// Get the number of delicious bookmarks
function yourls_get_books(json) {
if( json.length ) {
var books = json[0].total_posts.toString();
if( books ) {
document.getElementById('yourls-delicious-link').innerHTML = ' <b>'+books+'</b> bookmarks';
}
}
}

View File

@ -1,126 +1,126 @@
<?php
/*
Plugin Name: YOURLS Toolbar
Plugin URI: http://yourls.org/
Description: Add a social toolbar to your redirected short URLs. Fork this plugin if you want to make your own toolbar.
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
Disclaimer: Toolbars ruin the user experience. Be warned.
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
global $ozh_toolbar;
$ozh_toolbar['do'] = false;
$ozh_toolbar['keyword'] = '';
// When a redirection to a shorturl is about to happen, register variables
yourls_add_action( 'redirect_shorturl', 'ozh_toolbar_add' );
function ozh_toolbar_add( $args ) {
global $ozh_toolbar;
$ozh_toolbar['do'] = true;
$ozh_toolbar['keyword'] = $args[1];
}
// On redirection, check if this is a toolbar and draw it if needed
yourls_add_action( 'pre_redirect', 'ozh_toolbar_do' );
function ozh_toolbar_do( $args ) {
global $ozh_toolbar;
// Does this redirection need a toolbar?
if( !$ozh_toolbar['do'] )
return;
// Do we have a cookie stating the user doesn't want a toolbar?
if( isset( $_COOKIE['yourls_no_toolbar'] ) && $_COOKIE['yourls_no_toolbar'] == 1 )
return;
// Get URL and page title
$url = $args[0];
$pagetitle = yourls_get_keyword_title( $ozh_toolbar['keyword'] );
// Update title if it hasn't been stored yet
if( $pagetitle == '' ) {
$pagetitle = yourls_get_remote_title( $url );
yourls_edit_link_title( $ozh_toolbar['keyword'], $pagetitle );
}
$_pagetitle = htmlentities( yourls_get_remote_title( $url ) );
$www = YOURLS_SITE;
$ver = YOURLS_VERSION;
$md5 = md5( $url );
$sql = yourls_get_num_queries();
// When was the link created (in days)
$diff = abs( time() - strtotime( yourls_get_keyword_timestamp( $ozh_toolbar['keyword'] ) ) );
$days = floor( $diff / (60*60*24) );
if( $days == 0 ) {
$created = 'today';
} else {
$created = $days.' '.yourls_plural( 'day', $days).' ago';
}
// How many hits on the page
$hits = 1 + yourls_get_keyword_clicks( $ozh_toolbar['keyword'] );
$hits = $hits.' '.yourls_plural( 'view', $hits);
// Plugin URL (no URL is hardcoded)
$pluginurl = YOURLS_PLUGINURL . '/'.yourls_plugin_basename( dirname(__FILE__) );
// All set. Draw the toolbar itself.
echo <<<PAGE
<html>
<head>
<title>$pagetitle &mdash; YOURLS</title>
<link rel="icon" type="image/gif" href="$www/images/favicon.gif" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE-9"/>
<meta name="generator" content="YOURLS v$ver" />
<meta name="ROBOTS" content="NOINDEX, FOLLOW" />
<link rel="stylesheet" href="$pluginurl/css/toolbar.css" type="text/css" media="all" />
</head>
<body>
<div id="yourls-bar">
<div id="yourls-about">
Short link powered by <a href="http://yourls.org/">YOURLS</a> and created $created. $hits.
<!-- $sql queries -->
</div>
<div id="yourls-delicious">
<img src="http://static.delicious.com/img/delicious.small.gif" height="10" width="10" alt="Delicious" />
<a id="yourls-delicious-link" title="Bookmark on delicious" href="http://delicious.com/save" onclick="window.open('http://delicious.com/save?v=5&noui&jump=close&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title), 'delicious','toolbar=no,width=550,height=550'); return false;"> Bookmark on Delicious</a>
</div>
<script type="text/javascript" id="topsy_global_settings">
var topsy_theme = "light-blue";
var topsy_nick = " ";
var topsy_style = "small";
var topsy_order = "count,retweet,badge";
</script>
<div id="yourls-topsy" class="topsy_widget_data">
<!--{
"url": "$www/{$ozh_toolbar['keyword']}",
"title": "$_pagetitle",
}-->
</div>
<div id="yourls-selfclose">
<a id="yourls-once" href="$url" title="Close this toolbar">close</a>
<a id="yourls-always" href="$url" title="Never show me this toolbar again">close</a>
</div>
</div>
<iframe id="yourls-frame" frameborder="0" noresize="noresize" src="$url" name="yourlsFrame"></iframe>
<script type="text/javascript" src="$pluginurl/js/toolbar.js"></script>
<script type="text/javascript" src="http://cdn.topsy.com/topsy.js?init=topsyWidgetCreator"></script>
<script type="text/javascript" src="http://feeds.delicious.com/v2/json/urlinfo/$md5?callback=yourls_get_books"></script>
</body>
</html>
PAGE;
// Don't forget to die, to interrupt the flow of normal events (ie redirecting to long URL)
die();
<?php
/*
Plugin Name: YOURLS Toolbar
Plugin URI: http://yourls.org/
Description: Add a social toolbar to your redirected short URLs. Fork this plugin if you want to make your own toolbar.
Version: 1.0
Author: Ozh
Author URI: http://ozh.org/
Disclaimer: Toolbars ruin the user experience. Be warned.
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
global $ozh_toolbar;
$ozh_toolbar['do'] = false;
$ozh_toolbar['keyword'] = '';
// When a redirection to a shorturl is about to happen, register variables
yourls_add_action( 'redirect_shorturl', 'ozh_toolbar_add' );
function ozh_toolbar_add( $args ) {
global $ozh_toolbar;
$ozh_toolbar['do'] = true;
$ozh_toolbar['keyword'] = $args[1];
}
// On redirection, check if this is a toolbar and draw it if needed
yourls_add_action( 'pre_redirect', 'ozh_toolbar_do' );
function ozh_toolbar_do( $args ) {
global $ozh_toolbar;
// Does this redirection need a toolbar?
if( !$ozh_toolbar['do'] )
return;
// Do we have a cookie stating the user doesn't want a toolbar?
if( isset( $_COOKIE['yourls_no_toolbar'] ) && $_COOKIE['yourls_no_toolbar'] == 1 )
return;
// Get URL and page title
$url = $args[0];
$pagetitle = yourls_get_keyword_title( $ozh_toolbar['keyword'] );
// Update title if it hasn't been stored yet
if( $pagetitle == '' ) {
$pagetitle = yourls_get_remote_title( $url );
yourls_edit_link_title( $ozh_toolbar['keyword'], $pagetitle );
}
$_pagetitle = htmlentities( yourls_get_remote_title( $url ) );
$www = YOURLS_SITE;
$ver = YOURLS_VERSION;
$md5 = md5( $url );
$sql = yourls_get_num_queries();
// When was the link created (in days)
$diff = abs( time() - strtotime( yourls_get_keyword_timestamp( $ozh_toolbar['keyword'] ) ) );
$days = floor( $diff / (60*60*24) );
if( $days == 0 ) {
$created = 'today';
} else {
$created = $days.' '.yourls_plural( 'day', $days).' ago';
}
// How many hits on the page
$hits = 1 + yourls_get_keyword_clicks( $ozh_toolbar['keyword'] );
$hits = $hits.' '.yourls_plural( 'view', $hits);
// Plugin URL (no URL is hardcoded)
$pluginurl = YOURLS_PLUGINURL . '/'.yourls_plugin_basename( dirname(__FILE__) );
// All set. Draw the toolbar itself.
echo <<<PAGE
<html>
<head>
<title>$pagetitle &mdash; YOURLS</title>
<link rel="icon" type="image/gif" href="$www/images/favicon.gif" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE-9"/>
<meta name="generator" content="YOURLS v$ver" />
<meta name="ROBOTS" content="NOINDEX, FOLLOW" />
<link rel="stylesheet" href="$pluginurl/css/toolbar.css" type="text/css" media="all" />
</head>
<body>
<div id="yourls-bar">
<div id="yourls-about">
Short link powered by <a href="http://yourls.org/">YOURLS</a> and created $created. $hits.
<!-- $sql queries -->
</div>
<div id="yourls-delicious">
<img src="http://static.delicious.com/img/delicious.small.gif" height="10" width="10" alt="Delicious" />
<a id="yourls-delicious-link" title="Bookmark on delicious" href="http://delicious.com/save" onclick="window.open('http://delicious.com/save?v=5&noui&jump=close&url='+encodeURIComponent(location.href)+'&title='+encodeURIComponent(document.title), 'delicious','toolbar=no,width=550,height=550'); return false;"> Bookmark on Delicious</a>
</div>
<script type="text/javascript" id="topsy_global_settings">
var topsy_theme = "light-blue";
var topsy_nick = " ";
var topsy_style = "small";
var topsy_order = "count,retweet,badge";
</script>
<div id="yourls-topsy" class="topsy_widget_data">
<!--{
"url": "$www/{$ozh_toolbar['keyword']}",
"title": "$_pagetitle",
}-->
</div>
<div id="yourls-selfclose">
<a id="yourls-once" href="$url" title="Close this toolbar">close</a>
<a id="yourls-always" href="$url" title="Never show me this toolbar again">close</a>
</div>
</div>
<iframe id="yourls-frame" frameborder="0" noresize="noresize" src="$url" name="yourlsFrame"></iframe>
<script type="text/javascript" src="$pluginurl/js/toolbar.js"></script>
<script type="text/javascript" src="http://cdn.topsy.com/topsy.js?init=topsyWidgetCreator"></script>
<script type="text/javascript" src="http://feeds.delicious.com/v2/json/urlinfo/$md5?callback=yourls_get_books"></script>
</body>
</html>
PAGE;
// Don't forget to die, to interrupt the flow of normal events (ie redirecting to long URL)
die();
}

View File

@ -1,51 +1,51 @@
<?php
/*
* YOURLS API
*
* Note about translation : this file should NOT be translation ready
* API messages and returns are supposed to be programmatically tested, so default English is expected
*
*/
define( 'YOURLS_API', true );
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
yourls_maybe_require_auth();
$action = ( isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : null );
yourls_do_action( 'api', $action );
// Define standard API actions
$api_actions = array(
'shorturl' => 'yourls_api_action_shorturl',
'stats' => 'yourls_api_action_stats',
'db-stats' => 'yourls_api_action_db_stats',
'url-stats' => 'yourls_api_action_url_stats',
'expand' => 'yourls_api_action_expand',
'version' => 'yourls_api_action_version',
);
$api_actions = yourls_apply_filters( 'api_actions', $api_actions );
// Register API actions
foreach( (array) $api_actions as $_action => $_callback ) {
yourls_add_filter( 'api_action_' . $_action, $_callback, 99 );
}
// Try requested API method. Properly registered actions should return an array.
$return = yourls_apply_filter( 'api_action_' . $action, false );
if ( false === $return ) {
$return = array(
'errorCode' => 400,
'message' => 'Unknown or missing "action" parameter',
'simple' => 'Unknown or missing "action" parameter',
);
}
if( isset( $_REQUEST['callback'] ) )
$return['callback'] = $_REQUEST['callback'];
$format = ( isset( $_REQUEST['format'] ) ? $_REQUEST['format'] : 'xml' );
yourls_api_output( $format, $return );
<?php
/*
* YOURLS API
*
* Note about translation : this file should NOT be translation ready
* API messages and returns are supposed to be programmatically tested, so default English is expected
*
*/
define( 'YOURLS_API', true );
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
yourls_maybe_require_auth();
$action = ( isset( $_REQUEST['action'] ) ? $_REQUEST['action'] : null );
yourls_do_action( 'api', $action );
// Define standard API actions
$api_actions = array(
'shorturl' => 'yourls_api_action_shorturl',
'stats' => 'yourls_api_action_stats',
'db-stats' => 'yourls_api_action_db_stats',
'url-stats' => 'yourls_api_action_url_stats',
'expand' => 'yourls_api_action_expand',
'version' => 'yourls_api_action_version',
);
$api_actions = yourls_apply_filters( 'api_actions', $api_actions );
// Register API actions
foreach( (array) $api_actions as $_action => $_callback ) {
yourls_add_filter( 'api_action_' . $_action, $_callback, 99 );
}
// Try requested API method. Properly registered actions should return an array.
$return = yourls_apply_filter( 'api_action_' . $action, false );
if ( false === $return ) {
$return = array(
'errorCode' => 400,
'message' => 'Unknown or missing "action" parameter',
'simple' => 'Unknown or missing "action" parameter',
);
}
if( isset( $_REQUEST['callback'] ) )
$return['callback'] = $_REQUEST['callback'];
$format = ( isset( $_REQUEST['format'] ) ? $_REQUEST['format'] : 'xml' );
yourls_api_output( $format, $return );
die();

View File

@ -1,45 +1,45 @@
<?php
define( 'YOURLS_GO', true );
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
// Variables should be defined in yourls-loader.php, if not try GET request (old behavior of yourls-go.php)
if( !isset( $keyword ) && isset( $_GET['id'] ) )
$keyword = $_GET['id'];
$keyword = yourls_sanitize_string( $keyword );
// First possible exit:
if ( !isset( $keyword ) ) {
yourls_do_action( 'redirect_no_keyword' );
yourls_redirect( YOURLS_SITE, 301 );
}
// Get URL From Database
$url = yourls_get_keyword_longurl( $keyword );
// URL found
if( !empty( $url ) ) {
yourls_do_action( 'redirect_shorturl', $url, $keyword );
// Update click count in main table
$update_clicks = yourls_update_clicks( $keyword );
// Update detailed log for stats
$log_redirect = yourls_log_redirect( $keyword );
yourls_redirect( $url, 301 );
// URL not found. Either reserved, or page, or doesn't exist
} else {
// Do we have a page?
if ( file_exists( YOURLS_PAGEDIR . "/$keyword.php" ) ) {
yourls_page( $keyword );
// Either reserved id, or no such id
} else {
yourls_do_action( 'redirect_keyword_not_found', $keyword );
yourls_redirect( YOURLS_SITE, 302 ); // no 404 to tell browser this might change, and also to not pollute logs
}
}
exit();
<?php
define( 'YOURLS_GO', true );
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
// Variables should be defined in yourls-loader.php, if not try GET request (old behavior of yourls-go.php)
if( !isset( $keyword ) && isset( $_GET['id'] ) )
$keyword = $_GET['id'];
$keyword = yourls_sanitize_string( $keyword );
// First possible exit:
if ( !isset( $keyword ) ) {
yourls_do_action( 'redirect_no_keyword' );
yourls_redirect( YOURLS_SITE, 301 );
}
// Get URL From Database
$url = yourls_get_keyword_longurl( $keyword );
// URL found
if( !empty( $url ) ) {
yourls_do_action( 'redirect_shorturl', $url, $keyword );
// Update click count in main table
$update_clicks = yourls_update_clicks( $keyword );
// Update detailed log for stats
$log_redirect = yourls_log_redirect( $keyword );
yourls_redirect( $url, 301 );
// URL not found. Either reserved, or page, or doesn't exist
} else {
// Do we have a page?
if ( file_exists( YOURLS_PAGEDIR . "/$keyword.php" ) ) {
yourls_page( $keyword );
// Either reserved id, or no such id
} else {
yourls_do_action( 'redirect_keyword_not_found', $keyword );
yourls_redirect( YOURLS_SITE, 302 ); // no 404 to tell browser this might change, and also to not pollute logs
}
}
exit();

File diff suppressed because it is too large Load Diff

View File

@ -1,62 +1,62 @@
<?php
// Handle inexistent root favicon requests and exit
if ( '/favicon.ico' == $_SERVER['REQUEST_URI'] ) {
header( 'Content-Type: image/gif' );
echo base64_decode( "R0lGODlhEAAQAJECAAAAzFZWzP///wAAACH5BAEAAAIALAAAAAAQABAAAAIplI+py+0PUQAgSGoNQFt0LWTVOE6GuX1H6onTVHaW2tEHnJ1YxPc+UwAAOw==" );
exit;
}
// Handle inexistent root robots.txt requests and exit
if ( '/robots.txt' == $_SERVER['REQUEST_URI'] ) {
header( 'Content-Type: text/plain; charset=utf-8' );
echo "User-agent: *\n";
echo "Disallow:\n";
exit;
}
// Start YOURLS
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
// Get request in YOURLS base (eg in 'http://site.com/yourls/abcd' get 'abdc')
$request = yourls_get_request();
// Make valid regexp pattern from authorized charset in keywords
$pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() );
// Now load required template and exit
yourls_do_action( 'pre_load_template', $request );
// At this point, $request is not sanitized. Sanitize in loaded template.
// Redirection:
if( preg_match( "@^([$pattern]+)/?$@", $request, $matches ) ) {
$keyword = isset( $matches[1] ) ? $matches[1] : '';
$keyword = yourls_sanitize_keyword( $keyword );
yourls_do_action( 'load_template_go', $keyword );
include( YOURLS_ABSPATH.'/yourls-go.php' );
exit;
}
// Stats:
if( preg_match( "@^([$pattern]+)\+(all)?/?$@", $request, $matches ) ) {
$keyword = isset( $matches[1] ) ? $matches[1] : '';
$keyword = yourls_sanitize_keyword( $keyword );
$aggregate = isset( $matches[2] ) ? (bool)$matches[2] && yourls_allow_duplicate_longurls() : false;
yourls_do_action( 'load_template_infos', $keyword );
include( YOURLS_ABSPATH.'/yourls-infos.php' );
exit;
}
// Prefix-n-Shorten sends to bookmarklet (doesn't work on Windows)
if( preg_match( "@^[a-zA-Z]+://.+@", $request, $matches ) ) {
$url = yourls_sanitize_url( $matches[0] );
yourls_do_action( 'load_template_redirect_admin', $url );
yourls_redirect( yourls_admin_url('index.php').'?u='.rawurlencode( $url ), 302 );
exit;
}
// Past this point this is a request the loader could not understand
yourls_do_action( 'loader_failed', $request );
yourls_redirect( YOURLS_SITE, 302 );
<?php
// Handle inexistent root favicon requests and exit
if ( '/favicon.ico' == $_SERVER['REQUEST_URI'] ) {
header( 'Content-Type: image/gif' );
echo base64_decode( "R0lGODlhEAAQAJECAAAAzFZWzP///wAAACH5BAEAAAIALAAAAAAQABAAAAIplI+py+0PUQAgSGoNQFt0LWTVOE6GuX1H6onTVHaW2tEHnJ1YxPc+UwAAOw==" );
exit;
}
// Handle inexistent root robots.txt requests and exit
if ( '/robots.txt' == $_SERVER['REQUEST_URI'] ) {
header( 'Content-Type: text/plain; charset=utf-8' );
echo "User-agent: *\n";
echo "Disallow:\n";
exit;
}
// Start YOURLS
require_once( dirname( __FILE__ ) . '/includes/load-yourls.php' );
// Get request in YOURLS base (eg in 'http://site.com/yourls/abcd' get 'abdc')
$request = yourls_get_request();
// Make valid regexp pattern from authorized charset in keywords
$pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() );
// Now load required template and exit
yourls_do_action( 'pre_load_template', $request );
// At this point, $request is not sanitized. Sanitize in loaded template.
// Redirection:
if( preg_match( "@^([$pattern]+)/?$@", $request, $matches ) ) {
$keyword = isset( $matches[1] ) ? $matches[1] : '';
$keyword = yourls_sanitize_keyword( $keyword );
yourls_do_action( 'load_template_go', $keyword );
include( YOURLS_ABSPATH.'/yourls-go.php' );
exit;
}
// Stats:
if( preg_match( "@^([$pattern]+)\+(all)?/?$@", $request, $matches ) ) {
$keyword = isset( $matches[1] ) ? $matches[1] : '';
$keyword = yourls_sanitize_keyword( $keyword );
$aggregate = isset( $matches[2] ) ? (bool)$matches[2] && yourls_allow_duplicate_longurls() : false;
yourls_do_action( 'load_template_infos', $keyword );
include( YOURLS_ABSPATH.'/yourls-infos.php' );
exit;
}
// Prefix-n-Shorten sends to bookmarklet (doesn't work on Windows)
if( preg_match( "@^[a-zA-Z]+://.+@", $request, $matches ) ) {
$url = yourls_sanitize_url( $matches[0] );
yourls_do_action( 'load_template_redirect_admin', $url );
yourls_redirect( yourls_admin_url('index.php').'?u='.rawurlencode( $url ), 302 );
exit;
}
// Past this point this is a request the loader could not understand
yourls_do_action( 'loader_failed', $request );
yourls_redirect( YOURLS_SITE, 302 );
exit;