Updated to reflect live site

Signed-off-by: Sophia Atkinson <sophialul@protonmail.com>
This commit is contained in:
2023-01-21 05:10:16 -08:00
parent 3cf824cc5c
commit af6f76fbcb
163 changed files with 1471 additions and 12177 deletions

View File

@ -65,7 +65,7 @@ function ludo_blacklist_ip_form () {
<input type="hidden" name="nonce" value="$nonce" />
<p>Blacklist following IPs (one range or IP per line, no wildcards allowed) :</p>
<p><textarea cols="50" rows="10" name="blacklist_form">$liste_ip_display</textarea></p>
<p><textarea class="blacklist-ips" cols="50" rows="10" name="blacklist_form">$liste_ip_display</textarea></p>
<p><input type="submit" value="Save" /></p>
<p>I suggest to add here IPs that you saw adding bulk URL. It is your own responsibility to check the use of the IPs you block. WARNING : erroneous entries may create unexpected behaviours, please double-check before validation.</p>

View File

@ -65,8 +65,12 @@ function apelly_blacklist_domain_root ( $bol, $url ) {
// stop
//yourls_die( 'Blacklisted domain', 'Forbidden', 403 );
"<center>Blacklisted domain.</center>";
die();
return array(
'status' => 'fail',
'code' => 'error:url',
'message' => 'Blacklisted domain',
'errorCode' => '403',
);
}
}
}
@ -104,7 +108,7 @@ function apelly_blacklist_domain_form () {
<input type="hidden" name="nonce" value="$nonce" />
<p>Blacklist following domains</p>
<p><textarea cols="60" rows="15" name="blacklist_form">$domain_list_display</textarea></p>
<p><textarea class="blacklist-domains" cols="60" rows="15" name="blacklist_form">$domain_list_display</textarea></p>
<p><input type="submit" value="Save" /></p>
</form>

View File

@ -1,104 +0,0 @@
<?php
/*
Plugin Name: Anti spam
Plugin URI: http://yourls.org/
Description: Absolute anti-spam plugin. Checks URL against major black lists and removes all crap. Might OR MIGHT NOT work for you. Read the readme.
Version: 1.0.4
Author: Ozh
Author URI: http://ozh.org/
*/
// Check for spam when someone adds a new link
yourls_add_filter( 'shunt_add_new_link', 'ozh_yourls_antispam_check_add' );
function ozh_yourls_antispam_check_add( $false, $url ) {
// Sanitize URL and make sure there's a protocol
$url = yourls_sanitize_url( $url );
// only check for 'http(s)'
if( !in_array( yourls_get_protocol( $url ), array( 'http://', 'https://' ) ) )
return $false;
if ( ozh_yourls_antispam_is_blacklisted( $url ) === yourls_apply_filter( 'ozh_yourls_antispam_malformed', 'malformed' ) ) {
return array(
'status' => 'fail',
'code' => 'error:nourl',
'message' => yourls__( 'Missing or malformed URL' ),
'errorCode' => '400',
);
}
if ( ozh_yourls_antispam_is_blacklisted( $url ) != false ) {
return array(
'status' => 'fail',
'code' => 'error:spam',
'message' => 'This domain is blacklisted',
'errorCode' => '403',
);
}
// All clear, not interrupting the normal flow of events
return $false;
}
// Has the remote link become compromised lately? Check on redirection
yourls_add_action( 'redirect_shorturl', 'ozh_yourls_antispam_check_redirect' );
function ozh_yourls_antispam_check_redirect( $url, $keyword = false ) {
if( is_array( $url ) && $keyword == false ) {
$keyword = $url[1];
$url = $url[0];
}
// Check when the link was added
// If shorturl is fresh (ie probably clicked more often?) check once every 15 times, otherwise once every 5 times
// Define fresh = 3 days = 259200 secondes
// TODO: when there's a shorturl_meta table, store last check date to allow checking every 2 or 3 days
$now = date( 'U' );
$then = date( 'U', strtotime( yourls_get_keyword_timestamp( $keyword ) ) );
$chances = ( ( $now - $then ) > 259200 ? 15 : 5 );
if( $chances == mt_rand( 1, $chances ) ) {
if( ozh_yourls_antispam_is_blacklisted( $url ) != false ) {
// Delete link & die
yourls_delete_link_by_keyword( $keyword );
yourls_die( 'This domain has been blacklisted. This short URL has been deleted from our record.', 'Domain blacklisted', '403' );
}
}
// Nothing, move along
}
// Is the link spam? true for "yes it's shit", false for "nope, safe"
function ozh_yourls_antispam_is_blacklisted( $url ) {
$parsed = parse_url( $url );
if( !isset( $parsed['host'] ) )
return yourls_apply_filter( 'ozh_yourls_antispam_malformed', 'malformed' );
// Remove www. from domain (but not from www.com)
$parsed['host'] = preg_replace( '/^www\.(.+\.)/i', '$1', $parsed['host'] );
// Major blacklists. There's a filter if you want to manipulate this.
$blacklists = yourls_apply_filter( 'ozh_yourls_antispam_list',
array(
'dbl.spamhaus.org',
'multi.surbl.org',
)
);
// Check against each blacklist, exit if blacklisted
foreach( $blacklists as $blacklist ) {
$domain = $parsed['host'] . '.' . $blacklist . '.';
$record = @dns_get_record( $domain );
if( $record && count( $record ) > 0 )
return yourls_apply_filter( 'ozh_yourls_antispam_blacklisted', true );
}
// All clear, probably not spam
return yourls_apply_filter( 'ozh_yourls_antispam_clean', false );
}

View File

@ -1,19 +0,0 @@
Plugin for YOURLS 1.5+: Antispam
# What for
This is a __merciless__ __antispam__ plugin that uses the three major blacklists (<a href="http://spamhaus.org">Spamhaus</a>, <a href="http://uribl.com/">URIBL</a> and <a href="http://surbl.org/">SURBL</a>).
URL are checked against the blacklist when short urls are created. They are also randomly checked when someone follows a short
URL and if the link has been compromised recently, the short URL is deleted.
# How to
* In `/user/plugins`, create a new folder named `antispam`
* Drop these files in that directory
* Go to the Plugins administration page and activate the plugin
* Have fun
# Disclaimer
Checking against blacklists may or may not work for you, this may depend on the type of spam you are getting and on other factors such as your server IP, your server ISP, the DNS you are using. It may even result in all domains being blacklisted from your server. Try and see.

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ $theme: "dark";
$lightest: #464646;
$light: #313131;
$default: #232323;
$darker: #1d1d1d;
$darker: #121212;
$darkest: #161616;
// Accents

View File

@ -1,10 +1,10 @@
<div class="top" id="add">
<form id="new_url_form" action="javascript:add_link();" method="get">
<label>Link</label>
<input type="url" id="add-url" name="url" value="" class="text" placeholder="e.g. sleeky.flynntes.com" required>
<input type="url" id="add-url" name="url" value="" class="text" placeholder="e.g. a.domain.com" required autocomplete="off">
<label class="short">Short URL</label>
<input type="text" id="add-keyword" name="keyword" value="" class="text" placeholder="e.g. theme">
<input type="hidden" id="nonce-add" name="nonce-add" value="">
<input type="button" id="add-button" name="add-button" value="Shorten" class="button" onclick="add_link();">
<input type="text" id="add-keyword" name="keyword" value="" class="text" placeholder="e.g. theme" autocomplete="off">
<input type="hidden" id="nonce-add" name="nonce-add" value="" autocomplete="off">
<input type="button" id="add-button" name="add-button" value="Shorten" class="button" autocomplete="off" onclick="add_link();">
</form>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg class="iconLeft" data-v-423bf9ae="" viewBox="0 0 416 90" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(4.6332 0 0 4.6332 144.49 -1.8649)" data-v-423bf9ae="">
<path d="m4.24 13.92q-0.71 0-1.39-0.35-0.68-0.34-1.16-0.9l0.69-0.6q0.85 0.98 1.95 0.98 0.64 0 1.06-0.27 0.42-0.28 0.42-0.77 0-0.31-0.15-0.55-0.14-0.25-0.46-0.45-0.31-0.2-0.56-0.31-0.24-0.12-0.69-0.28-0.53-0.21-0.86-0.38t-0.68-0.42-0.52-0.6q-0.17-0.34-0.17-0.77 0-0.82 0.67-1.32 0.68-0.5 1.73-0.5 1.47 0 2.4 1.09l-0.64 0.54q-0.8-0.77-1.79-0.77-0.66 0-1.05 0.26-0.39 0.25-0.39 0.68 0 0.21 0.1 0.39 0.11 0.19 0.23 0.31 0.13 0.11 0.41 0.26t0.45 0.21q0.16 0.06 0.53 0.2 0.56 0.21 0.86 0.36t0.71 0.43q0.42 0.28 0.6 0.66 0.19 0.39 0.19 0.91 0 0.89-0.67 1.42-0.67 0.54-1.82 0.54zm11.1-1q-0.91 1-2.4 1-1.5 0-2.4-0.99-0.91-0.99-0.91-2.75 0-1.75 0.91-2.75 0.9-1 2.4-1 1.49 0 2.4 0.98 0.9 0.99 0.9 2.75 0 1.75-0.9 2.76zm-2.4 0.11q1.07 0 1.68-0.76 0.6-0.76 0.6-2.11t-0.59-2.1-1.69-0.75q-1.12 0-1.7 0.73-0.59 0.74-0.59 2.14 0 1.36 0.59 2.11 0.59 0.74 1.7 0.74zm6.83 3.07-0.98 0.49v-10h0.98v0.65q0.42-0.39 0.87-0.6 0.44-0.21 1.13-0.21 1.44 0 2.28 1.01 0.83 1.02 0.83 2.72 0 1.77-0.85 2.76-0.85 1-2.2 1-1.29 0-2.06-0.9v3.08zm1.94-3.07q1.03 0 1.59-0.74t0.56-2.13q0-1.31-0.58-2.08-0.59-0.77-1.62-0.77-1.28 0-1.89 1.1v3.52q0.85 1.1 1.94 1.1zm9.1 0.65q-0.26 0.26-0.63 0.26-0.36 0-0.62-0.26-0.26-0.27-0.26-0.62t0.26-0.61q0.26-0.27 0.62-0.27 0.37 0 0.63 0.27 0.26 0.26 0.26 0.61t-0.26 0.62zm6.79 0.07h-0.92l-1.76-7.16h1l1.17 5.13q0.07 0.39 0.09 0.53 0.02-0.06 0.05-0.26 0.04-0.2 0.07-0.31l1.1-5.09h0.81l1.12 5.1q0.03 0.13 0.13 0.63 0.03-0.25 0.11-0.63l1.12-5.1h1.01l-1.76 7.16h-0.91l-1.11-4.87q-0.06-0.2-0.13-0.63-0.07 0.46-0.11 0.6l-1.08 4.9zm10.48 0.17q-1.7 0-1.7-1.71v-4.73h-1.69v-0.89h1.69v-2.46l0.98-0.49v2.95h2.4v0.89h-2.4v4.31q0 0.6 0.21 0.9 0.2 0.3 0.84 0.3 0.74 0 1.36-0.42l-0.11 1.02q-0.6 0.33-1.58 0.33zm9.1-9.23q-0.37 0-0.58 0.07-0.22 0.07-0.31 0.23t-0.11 0.3q-0.03 0.13-0.03 0.38v0.92h1.91v0.89h-1.91v5.39h1.91v0.88h-4.37v-0.88h1.48v-5.39h-1.48v-0.89h1.48v-1.07q0-0.93 0.53-1.33 0.52-0.41 1.38-0.41 0.74 0 1.5 0.34v0.88q-0.65-0.31-1.4-0.31z"/>
</g>
<g transform="matrix(1.4702 0 0 1.4702 -6.5121 -28.119)" data-v-423bf9ae="">
<path d="M76.31 35.389H47.45c-9.202 0-16.853 6.692-18.39 15.46h10.653c1.267-3.025 4.257-5.156 7.737-5.156h28.86c4.625 0 8.389 3.76 8.389 8.385v7.838c0 4.625-3.764 8.387-8.389 8.387H47.45c-.062 0-.12-.017-.182-.018H30.764c3.077 6.111 9.392 10.322 16.687 10.322h28.86c10.306 0 18.69-8.385 18.69-18.691v-7.838C95 43.774 86.616 35.389 76.31 35.389z"/>
<path d="M29.527 64.611l.001.004H40.97l-.004-.004H52.55c9.234 0 16.904-6.739 18.404-15.553H60.315c-1.246 3.072-4.252 5.249-7.766 5.249h-9.538v.004h-19.18v-.004h-.141a8.304 8.304 0 0 1-1.917-.242c-3.7-.872-6.471-4.183-6.471-8.146v-7.838c0-4.625 3.764-8.385 8.389-8.385h28.86c.059 0 .114.016.173.017h16.514c-3.077-6.11-9.392-10.321-16.687-10.321H23.69C13.384 19.394 5 27.779 5 38.082v7.838c0 9.778 7.55 17.812 17.124 18.612.518.043 1.037.079 1.566.079h5.837z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg class="iconLeft" data-v-423bf9ae="" viewBox="0 0 416 90" xmlns="http://www.w3.org/2000/svg">
<g transform="matrix(4.6332 0 0 4.6332 144.49 -1.8649)" fill="#fff" data-v-423bf9ae="">
<path d="m4.24 13.92q-0.71 0-1.39-0.35-0.68-0.34-1.16-0.9l0.69-0.6q0.85 0.98 1.95 0.98 0.64 0 1.06-0.27 0.42-0.28 0.42-0.77 0-0.31-0.15-0.55-0.14-0.25-0.46-0.45-0.31-0.2-0.56-0.31-0.24-0.12-0.69-0.28-0.53-0.21-0.86-0.38t-0.68-0.42-0.52-0.6q-0.17-0.34-0.17-0.77 0-0.82 0.67-1.32 0.68-0.5 1.73-0.5 1.47 0 2.4 1.09l-0.64 0.54q-0.8-0.77-1.79-0.77-0.66 0-1.05 0.26-0.39 0.25-0.39 0.68 0 0.21 0.1 0.39 0.11 0.19 0.23 0.31 0.13 0.11 0.41 0.26t0.45 0.21q0.16 0.06 0.53 0.2 0.56 0.21 0.86 0.36t0.71 0.43q0.42 0.28 0.6 0.66 0.19 0.39 0.19 0.91 0 0.89-0.67 1.42-0.67 0.54-1.82 0.54zm11.1-1q-0.91 1-2.4 1-1.5 0-2.4-0.99-0.91-0.99-0.91-2.75 0-1.75 0.91-2.75 0.9-1 2.4-1 1.49 0 2.4 0.98 0.9 0.99 0.9 2.75 0 1.75-0.9 2.76zm-2.4 0.11q1.07 0 1.68-0.76 0.6-0.76 0.6-2.11t-0.59-2.1-1.69-0.75q-1.12 0-1.7 0.73-0.59 0.74-0.59 2.14 0 1.36 0.59 2.11 0.59 0.74 1.7 0.74zm6.83 3.07-0.98 0.49v-10h0.98v0.65q0.42-0.39 0.87-0.6 0.44-0.21 1.13-0.21 1.44 0 2.28 1.01 0.83 1.02 0.83 2.72 0 1.77-0.85 2.76-0.85 1-2.2 1-1.29 0-2.06-0.9v3.08zm1.94-3.07q1.03 0 1.59-0.74t0.56-2.13q0-1.31-0.58-2.08-0.59-0.77-1.62-0.77-1.28 0-1.89 1.1v3.52q0.85 1.1 1.94 1.1zm9.1 0.65q-0.26 0.26-0.63 0.26-0.36 0-0.62-0.26-0.26-0.27-0.26-0.62t0.26-0.61q0.26-0.27 0.62-0.27 0.37 0 0.63 0.27 0.26 0.26 0.26 0.61t-0.26 0.62zm6.79 0.07h-0.92l-1.76-7.16h1l1.17 5.13q0.07 0.39 0.09 0.53 0.02-0.06 0.05-0.26 0.04-0.2 0.07-0.31l1.1-5.09h0.81l1.12 5.1q0.03 0.13 0.13 0.63 0.03-0.25 0.11-0.63l1.12-5.1h1.01l-1.76 7.16h-0.91l-1.11-4.87q-0.06-0.2-0.13-0.63-0.07 0.46-0.11 0.6l-1.08 4.9zm10.48 0.17q-1.7 0-1.7-1.71v-4.73h-1.69v-0.89h1.69v-2.46l0.98-0.49v2.95h2.4v0.89h-2.4v4.31q0 0.6 0.21 0.9 0.2 0.3 0.84 0.3 0.74 0 1.36-0.42l-0.11 1.02q-0.6 0.33-1.58 0.33zm9.1-9.23q-0.37 0-0.58 0.07-0.22 0.07-0.31 0.23t-0.11 0.3q-0.03 0.13-0.03 0.38v0.92h1.91v0.89h-1.91v5.39h1.91v0.88h-4.37v-0.88h1.48v-5.39h-1.48v-0.89h1.48v-1.07q0-0.93 0.53-1.33 0.52-0.41 1.38-0.41 0.74 0 1.5 0.34v0.88q-0.65-0.31-1.4-0.31z"/>
</g>
<g transform="matrix(1.4702 0 0 1.4702 -6.5121 -28.119)" fill="#fff" data-v-423bf9ae="">
<path d="M76.31 35.389H47.45c-9.202 0-16.853 6.692-18.39 15.46h10.653c1.267-3.025 4.257-5.156 7.737-5.156h28.86c4.625 0 8.389 3.76 8.389 8.385v7.838c0 4.625-3.764 8.387-8.389 8.387H47.45c-.062 0-.12-.017-.182-.018H30.764c3.077 6.111 9.392 10.322 16.687 10.322h28.86c10.306 0 18.69-8.385 18.69-18.691v-7.838C95 43.774 86.616 35.389 76.31 35.389z"/>
<path d="M29.527 64.611l.001.004H40.97l-.004-.004H52.55c9.234 0 16.904-6.739 18.404-15.553H60.315c-1.246 3.072-4.252 5.249-7.766 5.249h-9.538v.004h-19.18v-.004h-.141a8.304 8.304 0 0 1-1.917-.242c-3.7-.872-6.471-4.183-6.471-8.146v-7.838c0-4.625 3.764-8.385 8.389-8.385h28.86c.059 0 .114.016.173.017h16.514c-3.077-6.11-9.392-10.321-16.687-10.321H23.69C13.384 19.394 5 27.779 5 38.082v7.838c0 9.778 7.55 17.812 17.124 18.612.518.043 1.037.079 1.566.079h5.837z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@ -1,60 +0,0 @@
<?php
/**
* Google Safe Browsing Lookup admin page
*
*/
// Display admin page
function ozh_yourls_gsb_display_page() {
// Check if a form was submitted
if( isset( $_POST['ozh_yourls_gsb'] ) ) {
// Check nonce
yourls_verify_nonce( 'gsb_page' );
// Process form
ozh_yourls_gsb_update_option();
}
// Get value from database
$ozh_yourls_gsb = yourls_get_option( 'ozh_yourls_gsb' );
// Create nonce
$nonce = yourls_create_nonce( 'gsb_page' );
echo <<<HTML
<h2>Google Safe Browsing API Key</h2>
<p>Google requires you to have a <strong>Google account</strong> and a Safe Browsing <strong>API key</strong>
to use their <a href="https://developers.google.com/safe-browsing/lookup_guide">Safe Browsing Lookup Service</a>.</p>
<p>Get your API key here: <a href="https://developers.google.com/safe-browsing/key_signup">https://developers.google.com/safe-browsing/key_signup</a></p>
<h3>Disclaimer from Google</h3>
<p>Google works to provide the most accurate and up-to-date phishing and malware information. However, it cannot
guarantee that its information is comprehensive and error-free: some risky sites may not be identified, and some safe
sites may be identified in error.</p>
<h3>Configure the plugin</h3>
<form method="post">
<input type="hidden" name="nonce" value="$nonce" />
<p><label for="ozh_yourls_gsb">API Key</label> <input type="text" id="ozh_yourls_gsb" name="ozh_yourls_gsb" value="$ozh_yourls_gsb" size="70" /></p>
<p><input type="submit" value="Update value" /></p>
</form>
HTML;
}
// Update option in database
function ozh_yourls_gsb_update_option() {
$in = $_POST['ozh_yourls_gsb'];
if( $in ) {
// Validate ozh_yourls_gsb: alpha & digits
$in = preg_replace( '/[^a-zA-Z0-9-_]/', '', $in );
// Update value in database
yourls_update_option( 'ozh_yourls_gsb', $in );
yourls_redirect( yourls_admin_url( 'plugins.php?page=ozh_yourls_gsb' ) );
}
}

View File

@ -1,106 +0,0 @@
<?php
/**
* Google Safe Browsing Lookup client for YOURLS
*
*/
class ozh_yourls_GSB {
const PROTOCOL_VER = '4.0';
const CLIENT = 'yourls-plugin-gsb';
const APP_VER = '1.0';
private $url = '';
private $api_key = false;
/**
* Constructor : checks that plugin is properly configured
*
*/
public function __construct( $api_key ) {
$this->api_key = $api_key;
}
/**
* Check if a URL is blacklisted against GSB Lookup API
*
* The function returns an array of a boolean and a string.
* The boolean indicates whether $this->url is blacklisted (true) or not blacklisted (false)
* The string gives diagnosis details: reason of blacklisting, null if clear, or an error message if applicable
*
* @return array array of boolean ( is blacklisted, description )
*/
public function is_blacklisted( $url ) {
if( !$this->api_key ) {
return false;
}
$this->url = urlencode( yourls_sanitize_url( $url ) );
if( !$this->url ) {
return false;
}
$request = $this->request();
switch( $request->status_code ) {
case 200:
$response = json_decode($request->body);
$blacklisted = true;
if (!isset($response->matches))
$blacklisted = false;
return array($blacklisted, ($blacklisted ? $response->matches[0]->threatType : null));
case 400:
return array( false, 'Could not check Google Safe Browsing: Bad Request' );
case 403:
return array( false, 'Could not check Google Safe Browsing: API key not authorized' );
case 503:
return array( false, 'Could not check Google Safe Browsing: service unavailable' );
}
}
/**
* HTTP request wrapper
*
* @return Request request object
*/
private function request() {
$api_url = sprintf( 'https://safebrowsing.googleapis.com/v4/threatMatches:find?key=%s',
$this->api_key
);
// Request headers
$headers = array(
'Content-Type' => 'application/json'
);
// Request data
$data = array(
'client' => array(
'clientId' => self::CLIENT,
'clientVersion' => self::APP_VER
),
'threatInfo' => array(
'threatTypes' => array('MALWARE', 'SOCIAL_ENGINEERING', 'POTENTIALLY_HARMFUL_APPLICATION', 'UNWANTED_SOFTWARE'),
'platformTypes' => array('ANY_PLATFORM'),
'threatEntryTypes' => array('URL'),
'threatEntries' => array(
array(
'url' => $this->url
)
)
)
);
// Request options ?
$options = array(
);
return yourls_http_post( $api_url, $headers, json_encode($data), $options );
}
}

View File

@ -1,112 +0,0 @@
<?php
/*
Plugin Name: Google Safe Browsing
Plugin URI: https://github.com/yourls/google-safe-browsing/
Description: Check new links against Google's Safe Browsing service
Version: 1.1
Author: Ozh
Author URI: http://ozh.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
yourls_add_filter( 'shunt_add_new_link', 'ozh_yourls_gsb_check_add' );
/**
* Check for spam when someone adds a new link
*
* The filter used here is 'shunt_add_new_link', which passes in false as first argument. See
* https://github.com/YOURLS/YOURLS/blob/1.7/includes/functions.php#L192-L194
*
* @param bool $false bool false is passed in by the filter 'shunt_add_new_link'
* @param string $url URL to check, as passed in by the filter
* @return mixed false if nothing to do, anything else will interrupt the flow of events
*/
function ozh_yourls_gsb_check_add( $false, $url ) {
list( $blacklisted, $desc ) = ozh_yourls_gsb_is_blacklisted( $url );
// If blacklisted, halt here
if ( $blacklisted ) {
return array(
'status' => 'fail',
'code' => 'error:' . $desc,
'message' => 'This domain is blacklisted by Google Safe Browsing because of ' . $desc . ' suspicion. <a href="http://code.google.com/apis/safebrowsing/safebrowsing_faq.html#whyAdvisory" target="_blank">Read more</a>.',
'errorCode' => '403',
);
}
// If not blacklisted but still unsure (error message), we should warn the user
if( $desc ) {
define( 'OZH_YOURLS_GSB_EXTRA_INFO', $desc );
yourls_add_filter( 'add_new_link', 'ozh_yourls_gsb_extra_info' );
}
// All clear, don't interrupt the normal flow of events
return $false;
}
yourls_add_action( 'plugins_loaded', 'ozh_yourls_gsb_add_page' );
/**
* Register our plugin admin page
*/
function ozh_yourls_gsb_add_page() {
yourls_register_plugin_page( 'ozh_yourls_gsb', 'Google Safe Browsing', 'ozh_yourls_gsb_admin_page' );
if( ! yourls_get_option( 'ozh_yourls_gsb' ) ) {
ozh_yourls_gsb_please_configure();
}
}
/**
* Add extra information to the notification when a link has been added
*
* @param array Array passed in by filter 'add_new_link'
* @return array
*/
function ozh_yourls_gsb_extra_info( $return ) {
$return['message'] .= '<br/>(' . OZH_YOURLS_GSB_EXTRA_INFO . ')';
$return['status'] = 'error';
return $return;
}
/**
* Check if a URL is blacklisted by Google Safe Browsing
*
* @param string $url URL to check
* @return array array( (boolean)is_blacklisted, (string)description )
*/
function ozh_yourls_gsb_is_blacklisted( $url ) {
include_once dirname( __FILE__ ) . '/includes/class-gsb.php';
$api_key = yourls_get_option( 'ozh_yourls_gsb' );
if( !$api_key ) {
ozh_yourls_gsb_please_configure();
return false;
}
$gsb = new ozh_yourls_GSB( $api_key );
return $gsb->is_blacklisted( $url );
}
/**
* Display the admin page
*
*/
function ozh_yourls_gsb_admin_page() {
include_once dirname( __FILE__ ) . '/includes/admin-page.php';
ozh_yourls_gsb_display_page();
}
/**
* Nag user about missing configuration
*
*/
function ozh_yourls_gsb_please_configure() {
yourls_add_notice( 'Plugin <strong>Google Safe Browsing</strong> is not configured' );
}

View File

@ -1,22 +0,0 @@
Plugin for YOURLS 1.7+: Google Safe Browsing
# What for
Check every new URL against Google's Safe Browsing Lookup service, reject those who are identified as malware or phishing
# How to
* In `/user/plugins`, create a new folder named `google-safe-browsing`
* Drop these files in that directory
* Go to the Plugins administration page and activate the plugin
* Follow on-screen instructions
* Have fun
# Disclaimer
Using this plugin requires you to understand Google's Safe Browsing TOS. In short:
* you need a Google account
* you are limited to a certain amount of queries per day (10,000 as of writing this)
* you must understand that the service is not perfect.
[Read more](https://developers.google.com/safe-browsing/lookup_guide#AcceptableUsage)

View File

@ -1,71 +0,0 @@
<?php
// Project Honeypot http:BL plugin for Yourls - URL Shortener ~ Block Page Template
// Copyright (c) 2016, Josh Panter
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
header('HTTP/1.0 403 Forbidden');
?>
<html lang="en">
<head>
<meta charset="utf-8">
<title>ALERT!</title>
<link rel="icon" href="%img%" type="image/png" />
<!-- Bootstrap core CSS -- USE LOCAL CACHE
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/spacelab/bootstrap.min.css" rel="stylesheet" integrity="sha384-L/tgI3wSsbb3f/nW9V6Yqlaw3Gj7mpE56LWrhew/c8MIhAYWZ/FNirA64AVkB5pI" crossorigin="anonymous"> -->
<!-- Bootstrap core CSS -- LOCAL CACHE -->
<link href="%css%" rel="stylesheet" integrity="sha384-L/tgI3wSsbb3f/nW9V6Yqlaw3Gj7mpE56LWrhew/c8MIhAYWZ/FNirA64AVkB5pI" crossorigin="anonymous">
<!-- Add extra support of older browsers -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<div style="padding:15px 0px 0px 0px;" class="col-md-6 col-md-offset-3">
<div style="text-align: center;" class="well well-lg">
<div style="display: inline-block; text-align: left">
<h2 class="text-danger" style="text-align:center;"><img src="%img%" width="30" height="30"/> Forbidden: Access Denied <img src="%img%" width="30" height="30"/></h2>
</br>
<p>Your IP: <strong>%ip%</strong>, has been flagged by <a href='https://www.projecthoneypot.org' target='_blank'>Project Honey Pot</a> due to the following:
<ul>
<li>Behavior Type: <strong>%typemeaning%</strong></li>
<li>Threat Level: <strong>%threat%</strong></li>
</ul>
<p>Information regarding threat levels can be found <a href="https://www.projecthoneypot.org/threat_info.php" target="_blank">here</a>.</p>
%greyList%
<p style="display:none;">Otherwise, please have fun with <a href="http://planetozh.com/smelly.php">this page</a></p>
<p>Thank you.</p>
</div>
</div>
</div>
</body>
<footer>
<script type="text/javascript">
function setcookie( name, value, expires, path, domain, secure ) {
// set time, it's in milliseconds
var today = new Date();
today.setTime( today.getTime() );
if ( expires ) {
expires = expires * 1000 * 60 * 60 * 24;
}
var expires_date = new Date( today.getTime() + (expires) );
document.cookie = name + "=" +escape( value ) +
( ( expires ) ? ";expires=" + expires_date.toGMTString() : "" ) +
( ( path ) ? ";path=" + path : "" ) +
( ( domain ) ? ";domain=" + domain : "" ) +
( ( secure ) ? ";secure" : "" );
}
function letmein() {
setcookie('notabot','true',1,'/', '', '');
location.reload(true);
}
</script>
</footer>
</html>

File diff suppressed because one or more lines are too long

View File

@ -1,18 +0,0 @@
CREATE TABLE IF NOT EXISTS `httpBL_log` (
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
`action` varchar(9) NOT NULL,
`ip` varchar(255) NOT NULL,
`type` varchar(50) NOT NULL,
`threat` varchar(3) NOT NULL,
`activity` varchar(255) NOT NULL,
`page` varchar(255) NOT NULL,
`ua` varchar(255) NOT NULL,
PRIMARY KEY (`timestamp`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `httpBL_wl` (
`timestamp` timestamp NOT NULL default CURRENT_TIMESTAMP,
`ip` varchar(255) NOT NULL,
`notes` varchar(255) NOT NULL,
PRIMARY KEY (`timestamp`)
) ENGINE=INNODB DEFAULT CHARSET=latin1;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1,129 +0,0 @@
# Contributing
Please take a moment to review this document in order to make the contribution
process easy and effective for everyone involved.
Submitting an issue that is improperly or incompletely written is a waste of time for everybody.
Following these guidelines helps to communicate that you respect the time of
the developers managing and developing this open source project. In return,
they should reciprocate that respect in addressing your issue or assessing
patches and features.
## Using the issue tracker
The issue tracker is the preferred channel for [bug reports](#bug-reports),
[feature requests](#feature-requests) and [submitting pull
requests](#pull-requests), but please respect the following restrictions:
* Please **do not** use the issue tracker for personal support requests.
Use [discussions](https://github.com/telepathics/yourls-emojis/discussions) instead to ask the community for help.
* Please **do not** derail or troll issues.
Keep the discussion on topic and respect the opinions of others.
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
Good bug reports are extremely helpful - thank you!
Guidelines for bug reports:
1. **Use the GitHub issue search**
Check if the issue has already been reported. Reporting duplicates is a waste of
time for everyone. Search in **all issues**, open and closed.
2. **Check if the issue has been fixed**
Try to reproduce it using the latest `master` or development branch in the repository.
Maybe it has been fixed since the last stable release.
3. **Give details**
A good bug report shouldn't leave others needing to chase you up for more
information. Please try to be as detailed as possible in your report.
Give any information that is relevant to the bug:
* YOURLS & MySQL & PHP versions
* Server Software
* Browser name & version
What is the expected output? What do you see instead? See the report example below.
7. **Isolate the problem**
Isolate the problem as much as you can, reduce to the bare minimum required to reproduce the issue.
Don't describe a general situation that doesn't work as expected and just count on us to pin
point the problem.
## Feature requests
Feature requests are welcome. But take a moment to find out whether your idea
fits with the scope and aims of the project. It's up to *you* to make a strong
case to convince the YOURLS developers of the merits of this feature. Please
provide as much detail and context as possible.
## Pull requests
Good pull requests - patches, improvements, new features - are a fantastic
help. They should remain focused in scope and avoid containing unrelated
commits.
1. **Please ask first**
Before embarking on any significant pull request (e.g. implementing features,
refactoring code), otherwise you risk spending a lot of time working on
something that the developers might not want to merge into the project.
2. **Licensing**
By submitting a patch, you agree that your code will be licensed under the
[MIT License](https://github.com/telepathics/yourls-emojis/blob/master/LICENSE) terms.
3. **Coding Standards**
Please adhere to the coding conventions used throughout the project (indentation,
comments, etc.). Make sure you've tested your patch under
different scenarios (various browsers, non default installation path, etc.).
Adhering to the following this process is the best way to get your work
merged:
1. [Fork the repo](https://docs.github.com/en/github/getting-started-with-github/fork-a-repo), clone your fork,
and configure the remotes.
```bash
# Clone your fork of the repo into the current directory
git clone https://github.com/<your-username>/<repo-name>
# Navigate to the newly cloned directory
cd <repo-name>
# Assign the original repo to a remote called "upstream"
git remote add upstream https://github.com/<upsteam-owner>/<repo-name>
```
2. If you cloned a while ago, get the latest changes from upstream.
```bash
git checkout <dev-branch>
git pull upstream <dev-branch>
```
3. Create a new topic branch (off the main project development branch) to
contain your feature, change, or fix.
```bash
git checkout -b <topic-branch-name>
```
4. Commit your changes in logical chunks. Please adhere to these [git commit
message guidelines](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
or your code is unlikely be merged into the main project. Use Git's
[interactive rebase](https://docs.github.com/en/github/using-git/about-git-rebase)
feature to tidy up your commits before making them public.
5. Locally merge (or rebase) the upstream development branch into your topic branch:
```bash
git pull [--rebase] upstream <dev-branch>
```
6. Push your topic branch up to your fork:
```bash
git push origin <topic-branch-name>
```
10. [Open a Pull Request](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
with a clear title and description.

View File

@ -1,3 +0,0 @@
# These are supported funding model platforms
github: telepathics

View File

@ -1,36 +0,0 @@
name: PHP Composer
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Validate composer.json and composer.lock
run: composer validate --strict
- name: Cache Composer packages
id: composer-cache
uses: actions/cache@v2
with:
path: vendor
key: ${{ runner.os }}-php-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-php-
- name: Install dependencies
run: composer install --prefer-dist --no-progress
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
# Docs: https://getcomposer.org/doc/articles/scripts.md
# - name: Run test suite
# run: composer run-script test

View File

@ -1,3 +0,0 @@
.DS_Store
/vendor/
/build/

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2021 telepathics
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,34 +0,0 @@
# YOURLS Emojis
A YOURLS plugin that allows emojis in the custom short URLs.
## Description
Emojis in domain names and URLs are becoming increasingly popular, so I thought it would be fun to be able to include them in your YOURLS short codes.
[![Mentioned in Awesome YOURLS](https://awesome.re/mentioned-badge.svg)](https://github.com/YOURLS/awesome-yourls/)
[![Github Sponsors](https://img.shields.io/badge/sponsors-4-green.svg)](https://github.com/sponsors/telepathics)
[![PHP Composer](https://github.com/telepathics/yourls-emojis/actions/workflows/php.yml/badge.svg?branch=main)](https://github.com/telepathics/yourls-emojis/actions/workflows/php.yml)
## Installation
1. Unzip the [latest release](https://github.com/telepathics/yourls-emojis/releases) and move it into your YOURLS `/user/plugins` folder
2. Visit your plugins page (e.g. https://sho.rt/admin/plugins.php)
3. Activate the "Emojis" plugin by telepathics
4. Have fun!
### Upgrading
1. Delete (or replace) the old folder
2. Follow aforementioned installation instructions
## Contributing
Feature suggestion? Bug to report?
__Before opening any issue, please search for existing [issues](https://github.com/telepathics/yourls-emojis/issues) (open and closed) and read the [Contributing Guidelines](https://github.com/telepathics/yourls-emojis/blob/main/.github/CONTRIBUTING.md).__
Also visit the living [to do](https://github.com/telepathics/yourls-emojis/projects/1) kanban board and [discussions](https://github.com/telepathics/yourls-emojis/discussions) page.
## License
Released under the [MIT License](https://opensource.org/licenses/MIT).
See also:
[YOURLS](https://github.com/YOURLS/YOURLS) ♡
[SteppingHat/php-emoji-detector](https://github.com/SteppingHat/php-emoji-detector) ♡ [unicode.org](https://unicode.org/Public/emoji/13.1/emoji-test.txt)

View File

@ -1,10 +0,0 @@
{
"name": "telepathics/yourls-emojis",
"description": "A YOURLS plugin that allows emojis in the custom short URLs",
"license": "MIT",
"homepage": "https://github.com/telepathics/yourls-emojis",
"require": {
"php": ">=7.2",
"steppinghat/emoji-detector": "^1.1"
}
}

View File

@ -1,63 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "d8ae5b9fddab58bd68089f83a8564e1e",
"packages": [
{
"name": "steppinghat/emoji-detector",
"version": "1.1.0",
"source": {
"type": "git",
"url": "https://github.com/SteppingHat/php-emoji-detector.git",
"reference": "d2301e9553795e1ac2f3f2638438b3808654c57f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/SteppingHat/php-emoji-detector/zipball/d2301e9553795e1ac2f3f2638438b3808654c57f",
"reference": "d2301e9553795e1ac2f3f2638438b3808654c57f",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"php": ">=7.1"
},
"require-dev": {
"symfony/phpunit-bridge": "^5.0@dev"
},
"type": "library",
"autoload": {
"psr-4": {
"SteppingHat\\EmojiDetector\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Javan Eskander",
"homepage": "https://javaneskander.com"
}
],
"description": "Detect and validate emoji in an input string",
"homepage": "https://github.com/steppinghat/emoji-detector",
"time": "2021-03-18T06:03:22+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=7.2"
},
"platform-dev": [],
"plugin-api-version": "1.1.0"
}

View File

@ -1,50 +0,0 @@
<?php
/*
Plugin Name: Emojis
Description: Create an emoji-only short link, like http://sho.rt/✨ or http://sho.rt/😎🆒🔗
Version: 1.0
Author: telepathics
Author URI: https://telepathics.xyz
*/
if( !defined( 'YOURLS_ABSPATH' ) ) die();
require_once(__DIR__ . '/vendor/autoload.php');
use SteppingHat\EmojiDetector;
/*
* Accept detected emojis
*/
yourls_add_filter( 'get_shorturl_charset', 'path_emojis_in_charset');
function path_emojis_in_charset($in) {
return $in . file_get_contents(__DIR__ . '/util/emojis.txt');
}
/*
* Accepts URLs that are ONLY emojis
*/
yourls_add_filter( 'sanitize_url', 'path_emojis_sanitize_url' );
function path_emojis_sanitize_url($unsafe_url) {
$clean_url = '';
$detector = new SteppingHat\EmojiDetector\EmojiDetector();
$detect_emoji = $detector->detect(urldecode($unsafe_url));
if( sizeof($detect_emoji) > 0 ) {
foreach ($detect_emoji as $emoji) {
$clean_url .= $emoji->getEmoji();
}
return $clean_url;
}
return $unsafe_url;
}
/*
* filter wrong spacing whoopsies
* see @link https://github.com/YOURLS/YOURLS/issues/1303
*/
yourls_add_filter( 'sanitize_url', 'fix_long_url' );
function fix_long_url( $url, $unsafe_url ) {
$search = array ( '%2520', '%2521', '%2522', '%2523', '%2524', '%2525', '%2526', '%2527', '%2528', '%2529', '%252A', '%252B', '%252C', '%252D', '%252E', '%252F', '%253D', '%253F', '%255C', '%255F' );
$replace = array ( '%20', '%21', '%22', '%23', '%24', '%25', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%2D', '%2E', '%2F', '%3D', '%3F', '%5C', '%5F' );
$url = str_ireplace ( $search, $replace ,$url );
return yourls_apply_filter( 'after_fix_long_url', $url, $unsafe_url );
}

File diff suppressed because one or more lines are too long

View File

@ -1,24 +0,0 @@
<?php
/*
* you can update the emoji list by changing the unicode link below
* then, visit your site's /user/plugins/yourls-emojis/util/get_emojis.php page to run the script
*
* most recent 13.1 https://www.unicode.org/emoji/charts/full-emoji-list.html
*/
if( !defined( 'YOURLS_ABSPATH' ) ) die();
require_once __DIR__ . '/../vendor/autoload.php';
/*
* Last retrieved: April 11, 2021
*/
function get_emojis() {
$detect_emoji = Emoji\detect_emoji(file_get_contents('https://unicode.org/Public/emoji/13.1/emoji-test.txt'));
$file = fopen(__DIR__ . '/emojis.txt', 'w+');
if ( sizeof($detect_emoji) > 0 ) {
foreach ( $detect_emoji as $emoji ) {
fwrite($file, $emoji['emoji']);
}
}
}
get_emojis();

View File

@ -0,0 +1,22 @@
# Timezones [![Listed in Awesome YOURLS!](https://img.shields.io/badge/Awesome-YOURLS-C5A3BE)](https://github.com/YOURLS/awesome-yourls/)
A plugin to tell YOURLS your time zone and how you'd like times and dates displayed
Require [YOURLS](https://yourls.org) `1.7.10` and above.
## Usage
<kbd>
<img src="https://user-images.githubusercontent.com/223647/81840321-1ecb1b80-9549-11ea-9c5f-aae25bc2f944.png" />
</kbd>
## Installation
1. In `/user/plugins`, create a new folder named `timezones`.
2. Drop these files in that directory.
3. Go to the Plugins administration page (eg. `http://sho.rt/admin/plugins.php`) and activate the plugin.
4. Have fun!
## License
Do whatever the hell you want with it

View File

@ -0,0 +1,273 @@
<?php
/**
* Time Zone plugin admin page
*/
/**
* Display time zone configuration page
*/
function yourls_tzp_admin_page() {
// Check if a form was submitted
if( isset( $_POST['time_zone'] ) ) {
// Check nonce and process form
yourls_verify_nonce( 'time_zone_config' );
$options = yourls_tzp_config_update_settings();
echo yourls_notice_box('Timezone settings updated');
} else {
$options = (array)yourls_get_option( 'timezone' );
}
$user_time_zone = yourls_tzp_get_value($options, 'time_zone', 'UTC');
$user_time_zone_display = $user_time_zone;
if (substr($user_time_zone, 0, 1) == '+' or substr($user_time_zone, 0, 1) == '-') {
$user_time_zone_display = 'UTC' . $user_time_zone_display;
}
$user_date_format = yourls_tzp_get_value($options, 'date_format', 'Y/m/d');
$user_date_format_custom = yourls_tzp_get_value($options, 'date_format_custom', 'Y/m/d');
$user_time_format = yourls_tzp_get_value($options, 'time_format', 'H:i');
$user_time_format_custom = yourls_tzp_get_value($options, 'time_format_custom', 'H:i');
// Draw page
yourls_tzp_js_css();
print '<h2>Time Zone Configuration</h2>
<p>This plugin allows to specify a time zone and to format time/date display</p>';
if( defined('YOURLS_HOURS_OFFSET') ) {
print '<p><strong>Note:</strong> you have <code>YOURLS_HOURS_OFFSET</code> defined in your config.php. This plugin will override this setting.</p>';
}
print '<form method="post">
<input type="hidden" name="nonce" value="' . yourls_create_nonce( 'time_zone_config' ) . '" />';
// Time zones drop down
print '<h3>Time zone: </h3>
<div class="settings">
<p>Choose a city near your location, in the same timezone as you, or a UTC time offset.</p>';
yourls_tzp_tz_dropdown( $user_time_zone );
print '<p>Universal time (<code>UTC</code>) time is: <tt id="utc_time">' . date( 'Y-m-d H:i:s', yourls_tzp_timezoned_timestamp( time(), 'UTC' ) ). '</tt></p>';
if($user_time_zone) {
print "<p>Time in <code>$user_time_zone_display</code> is: <tt id='local_time'>" . date( 'Y-m-d H:i:s', yourls_tzp_timezoned_timestamp( time(), $user_time_zone) ) . '</tt></p>';
}
print '</div>';
// Display radio button for date format
$choices = array(
'j F Y', // 13 April 2020
'F j, Y', // May 10, 2020
'd/m/Y', // 20/10/2020
'm/d/Y', // 10/20/2020
'Y/m/d', // 2020/10/20
);
yourls_tzp_format_radio( 'Date Format', 'date_format', $choices, $user_time_zone, $user_date_format, $user_date_format_custom );
// Display radio button for date format
$choices = array(
'H:i', // 21:23
'g:i a', // 9:23 pm
'g:i A', // 9:23 PM
);
yourls_tzp_format_radio( 'Time Format', 'time_format', $choices, $user_time_zone, $user_time_format, $user_time_format_custom );
print '<p><input type="submit" class="button primary" value="Update configuration" /></p>
</form>
<p><strong>Note:</strong> custom formats need a PHP <code><a href="https://php.net/date">date()</a></code> string.';
}
/**
* Output CSS & JS
*/
function yourls_tzp_js_css() {
$plugin_url = yourls_plugin_url( __DIR__ );
print <<<JSCSS
<link href='$plugin_url/assets/select2.min.css' rel='stylesheet' />
<script src='$plugin_url/assets/select2.min.js'></script>
<script src='$plugin_url/assets/php-date-formatter.min.js'></script>
<script>
jQuery( document ).ready(function() {
// auto select radio when custom input field is focused
$('.custom :input').focusin(function() {
$(this).prev().click();
});
// easy selector on timezones
$('#time_zone').select2({
templateResult: format_region,
placeholder:'Choose a time zone'
});
// Real time date format preview
$(".custom_format").on("keyup", function() {
format_preview($(this).attr('id'), $(this).val());
});
// Click a radio to change custom format accordingly
$('.radio_format').change(
function(){
if (this.checked) {
name = $(this).attr('name');
value = $(this).attr('value');
$('#'+name+'_custom_value').val(value).trigger($.Event("keyup"));
}
}
);
})
// Real time preview of date/time format
function format_preview(id, value) {
if($('#local_time')) {
time = $('#local_time').text();
} else {
time = $('#utc_time').text();
}
id = id.replace('_custom_value', '');
fmt = new DateFormatter();
parse = fmt.parseDate(time, 'Y-m-d H:i:s');
format = fmt.formatDate(parse, value );
$('#tz_test_' + id).text(format);
}
// modify dropdown list
function format_region(item) {
if (!item.id) {
return item.text;
}
var text = item.text.split('/');
var region=text[0];
var city=text[1];
return $('<span class="region">'+region+'</span> '+city+'</span>');
}
</script>
<style>
body {
text-align:left;
}
h3 {
border-bottom:1px solid #ccc;
}
div.settings {
padding-bottom:1em;
}
.region{
color:#aaa;
font-style:italic;
}
</style>
JSCSS;
}
/**
* Draw the time zone drop down
*
* @param string $user_time_zone Timezone to be marked as "selected" in the dropdown
*/
function yourls_tzp_tz_dropdown( $user_time_zone ) {
// Continent list
$continent = array(
'Africa' => DateTimeZone::AFRICA,
'America' => DateTimeZone::AMERICA,
'Antarctica' => DateTimeZone::ANTARCTICA,
'Asia' => DateTimeZone::ASIA,
'Atlantic' => DateTimeZone::ATLANTIC,
'Australia' => DateTimeZone::AUSTRALIA,
'Europe' => DateTimeZone::EUROPE,
'Indian' => DateTimeZone::INDIAN,
'Pacific' => DateTimeZone::PACIFIC,
);
// Timezones per continents
$timezones = array();
foreach ($continent as $name => $mask) {
$zones = DateTimeZone::listIdentifiers($mask);
foreach($zones as $timezone) {
// Remove region name
$timezones[$name][$timezone] = substr($timezone, strlen($name) +1);
}
}
// Manual UTC offset
$offset_range = array(
'-12', '-11:30', '-11', '-10:30', '-10', '-9.5', '-9',
'-8:30', '-8', '-7:30', '-7', '-6:30', '-6', '-5:30',
'-5', '-4:30', '-4', '-3:30', '-3', '-2:30', '-2',
'-1:30', '-1', '-0:30', 'UTC', '+0:30', '+1', '+1:30',
'+2', '+2:30', '+3', '+3:30', '+4', '+4:30', '+5',
'+5:30', '+5:45', '+6', '+6:30', '+7', '+7:30', '+8',
'+8:30', '+8:45', '+9', '+9:30', '+10', '+10:30', '+11',
'+11:30', '+12', '+12:45', '+13', '+13:45', '+14'
);
foreach( $offset_range as $offset_name ) {
$offset_value = $offset_name;
$offset_name = str_replace( array( '.25', '.5', '.75' ), array( ':15', ':30', ':45' ), $offset_name );
if ($offset_name != 'UTC') {
$offset_name = 'UTC' . $offset_name;
}
// $offset_value = 'UTC' . $offset_value;
$timezones['UTC'][$offset_value] = $offset_name;
}
print '<select name="time_zone" id="time_zone">';
print '<option value="" dzisabled="dzisabled">Choose a time zone</option>';
foreach($timezones as $region => $list) {
print '<optgroup label="' . $region . '">' . "\n";
foreach($list as $timezone => $name) {
print '<option value="' . $timezone . '" ' . (($timezone == $user_time_zone) ? "selected='selected'":"") . '>' . "$region/$name" . '</option>' . "\n";
}
print '<optgroup>' . "\n";
}
print '</select>';
}
/**
* Output radio button list
*
* @param string $title Dropdown title
* @param string $input_name Dropdown 'radio' name
* @param array $formats List of available choices, to which 'custom' will be appended
* @param string $tz Time zone
* @param string $selected Checked radio value
* @param string $custom Custom format value
*/
function yourls_tzp_format_radio( $title, $input_name, $formats, $tz, $selected, $custom ) {
print "<h3>$title:</h3>
<div class='settings'>";
foreach ($formats as $format) {
$checked = ( $format === $selected ) ? 'checked="checked"' : '' ;
print "<p><label><input type='radio' class='radio_format radio_$input_name' name='$input_name' value='$format' $checked >";
print yourls_date_i18n( $format, yourls_tzp_timezoned_timestamp( time(), $tz ), true );
print "</label></p>\n";
}
$checked = ( 'custom' === $selected ) ? 'checked="checked"' : '' ;
$preview = date( $custom, yourls_tzp_timezoned_timestamp( time(), $tz ) );
print "<label class='custom'><input type='radio' id='${input_name}_custom' name='$input_name' value='custom' $checked >
Custom: <input type='text' class='text custom_format' id='${input_name}_custom_value' name='${input_name}_custom_value' value='$custom' />
<span class='tz_test' id='tz_test_$input_name'>$preview</span>
</label>\n";
print '</div>';
}
/**
* Update time zone in database
*/
function yourls_tzp_config_update_settings() {
$settings = array(
'time_zone' => yourls_tzp_get_value($_POST, 'time_zone', 'UTC'),
'date_format' => yourls_tzp_get_value($_POST, 'date_format', 'Y/m/d'),
'date_format_custom' => yourls_tzp_get_value($_POST, 'date_format_custom_value', 'Y/m/d'),
'time_format' => yourls_tzp_get_value($_POST, 'time_format', 'H:i'),
'time_format_custom' => yourls_tzp_get_value($_POST, 'time_format_custom_value', 'H:i'),
);
yourls_update_option( 'timezone', $settings );
return $settings;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,124 @@
<?php
/*
Plugin Name: Time Zones ⏰
Plugin URI: https://github.com/YOURLS/timezones
Description: Tell YOURLS what timezone you are in
Version: 1.3
Author: YOURLS contributors
Author URI: https://yourls.org/
*/
// No direct call
if( !defined( 'YOURLS_ABSPATH' ) ) die();
/**
* Register plugin admin page
*/
yourls_add_action( 'plugins_loaded', 'yourls_tzp_config' );
function yourls_tzp_config() {
if( yourls_is_admin() ) {
require_once __DIR__ . '/admin.php';
}
yourls_register_plugin_page( 'time_zone_config', 'Time Zone Configuration', 'yourls_tzp_admin_page' );
}
/**
* Filter for time offset
*/
yourls_add_filter( 'get_time_offset', 'yourls_tzp_get_time_offset' );
function yourls_tzp_get_time_offset() {
return yourls_tzp_timezoned_offset( yourls_tzp_read_options( 'time_zone', 'UTC' ) );
}
/**
* Filter for timestamps
*/
yourls_add_filter( 'get_timestamp', 'yourls_tzp_get_timestamp' );
function yourls_tzp_get_timestamp($timestamp_offset, $timestamp, $offset) {
return yourls_tzp_timezoned_timestamp( $timestamp, yourls_tzp_read_options( 'time_zone', 'UTC' ) );
}
/**
* Filter for date + time format
*/
yourls_add_filter( 'get_datetime_format', 'yourls_tzp_get_datetime_format' );
function yourls_tzp_get_datetime_format() {
return yourls_tzp_get_date_format() . ' ' . yourls_tzp_get_time_format();
}
/**
* Filter for date (no time) format
*/
yourls_add_filter( 'get_date_format', 'yourls_tzp_get_date_format' );
function yourls_tzp_get_date_format() {
$date_format = yourls_tzp_read_options('date_format', 'Y/m/d');
if( $date_format == 'custom' ) {
$date_format = yourls_tzp_read_options('date_format_custom', 'Y/m/d');
}
return $date_format;
}
/**
* Filter for time (no date) format
*/
yourls_add_filter( 'get_time_format', 'yourls_tzp_get_time_format' );
function yourls_tzp_get_time_format() {
$time_format = yourls_tzp_read_options('time_format', 'H:i');
if( $time_format == 'custom' ) {
$time_format = yourls_tzp_read_options('time_format_custom', 'H:i');
}
return $time_format;
}
/**
* Return time offset of a timezone from UTC
*
* @param string $timezone Optional timezone (eg "Europe/Paris"). Default is UTC
* @return int Timezoned time offset
*/
function yourls_tzp_timezoned_offset($timezone = 'UTC') {
$tz = new DateTime('now', new DateTimeZone($timezone));
return $tz->getOffset()/3600;
}
/**
* Return timezoned and formatted time
*
* @param int $timestamp Optional timestamp. If omitted, function will use time()
* @param string $timezone Optional timezone (eg "Europe/Paris"). Default is UTC
* @param string $format Optional format as what PHP's date() needs. Default it 'U' (epoch)
* @return string Timezoned and formatted time
*/
function yourls_tzp_timezoned_timestamp($timestamp = false, $timezone = 'UTC') {
$timestamp = $timestamp ? $timestamp : time();
$offset = yourls_tzp_timezoned_offset($timezone);
return $timestamp + $offset * 3600;
}
/**
* Get (string)key from array, or return false if not defined
*
* @param array $array Array
* @param string $key Key
* @return string Value of (string)$array[$key], or false
*/
function yourls_tzp_get_value( $array, $key, $default ) {
return isset ( $array[$key] ) ? (string)($array[$key]) : $default ;
}
/**
* Read timezone options from the DB, and return all keys or specified key
*
* @param string $key Key of timezone option array
* @return array|mixed Array of options, or value for specified key if exists (false otherwise)
*/
function yourls_tzp_read_options( $key = false, $default = false ) {
$options = (array)yourls_get_option( 'timezone' );
if( $key !== false ) {
$options = array_key_exists($key, $options) ? $options[$key] : $default ;
}
return $options;
}

View File

@ -42,12 +42,17 @@ function dd_preview_show( $keyword ) {
$qrcode = 'https://api.qrserver.com/v1/create-qr-code/?size=256x256&format=svg&bgcolor=1D1D1D&color=fff&charset-source=UTF-8&ecc=H&data='.YOURLS_SITE.'/'.$keyword;
echo <<<HTML
<h2>Link Preview</h2>
<style>
div.nav-open#navOpen{
display: none
}
</style>
<h2 class="linkpre">Link Preview</h2>
<p>You requested the short URL <strong><a href="$base/$keyword">$base/$keyword</a></strong></p>
<p>This short URL points to:</p>
<ul>
<li>Long URL: <strong><a href="$base/$keyword">$url</a></strong></li>
<li>Page title: <strong>$title</strong></li>
<li>Long URL: <strong class="qrurl"><a href="$base/$keyword">$url</a></strong></li>
<li>Page title: <strong class="qrurl">$title</strong></li>
<li>QR Code: <br><img src="$qrcode"></li>
</ul>
<p>If you still want to visit this link, please <strong><a href="$base/$keyword">click here</a></strong>.</p>