Why is the colon so special? Read here: https://planetozh.com/blog/2026/06/allowing-weird-characters-in-yourls-short-urls/
Last active
June 23, 2026 09:12
-
-
Save ozh/ff7c454ce3fa9ce8ffeaba07f8324caa to your computer and use it in GitHub Desktop.
Colon in YOURLS short URL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| /** | |
| * Plugin Name: Allow Colon in Short URLs | |
| * Plugin URI: https://ozh.in/10i | |
| * Description: Allow the colon ":" in short URLs (like <tt>http://sho.rt/foo:bar</tt>) | |
| * Version: 1.0 | |
| * Author: Ozh | |
| * Author URI: http://ozh.org/ | |
| */ | |
| // No direct call | |
| if( !defined( 'YOURLS_ABSPATH' ) ) die(); | |
| // Add the colon to the allowed short URL character set... | |
| yourls_add_filter( 'get_shorturl_charset', 'ozh_colon_in_charset' ); | |
| function ozh_colon_in_charset( $charset ) { | |
| return $charset . ':'; | |
| } | |
| // ...unless we are crafting a random keyword, to keep auto-generated keywords colon-free | |
| yourls_add_action( 'add_new_link_create_keyword', function() { | |
| yourls_remove_filter( 'get_shorturl_charset', 'ozh_colon_in_charset' ); | |
| } ); | |
| // Don't let a keyword that contains a colon be mistaken for a URI scheme | |
| yourls_add_filter( 'get_protocol', 'ozh_colon_get_protocol', 10, 2 ); | |
| function ozh_colon_get_protocol( $protocol, $url ) { | |
| // Nothing was detected as a protocol: leave as is | |
| if ( $protocol === '' ) { | |
| return $protocol; | |
| } | |
| // A genuine "scheme://..." URL (eg a bookmarklet target): leave as is | |
| if ( str_contains( $protocol, '/' ) ) { | |
| return $protocol; | |
| } | |
| // Here $protocol is a bare "scheme:" with no slashes. If the whole candidate | |
| // string consists only of valid short URL charset characters, it's one of our | |
| // keywords (eg "foo:bar"), not a URL: don't treat the colon as a scheme. | |
| $pattern = yourls_make_regexp_pattern( yourls_get_shorturl_charset() ); | |
| if ( ! preg_match( '@[^' . $pattern . ']@', $url ) ) { | |
| return ''; | |
| } | |
| return $protocol; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment