1<?php 2 3/** 4 * Check if we have PDO installed, returns bool 5 * 6 * @since 1.7.3 7 * @return bool 8 */ 9function yourls_check_PDO() { 10 return extension_loaded('pdo'); 11} 12 13/** 14 * Check if server has MySQL 5.0+ 15 * 16 */ 17function yourls_check_database_version() { 18 return ( version_compare( '5.0', yourls_get_database_version() ) <= 0 ); 19} 20 21/** 22 * Get DB version 23 * 24 * @since 1.7 25 * @return string sanitized DB version 26 */ 27function yourls_get_database_version() { 28 // Allow plugins to short-circuit the whole function 29 $pre = yourls_apply_filter( 'shunt_get_database_version', false ); 30 if ( false !== $pre ) { 31 return $pre; 32 } 33 34 return yourls_sanitize_version(yourls_get_db()->mysql_version()); 35} 36 37/** 38 * Check if PHP > 7.2 39 * 40 * As of 1.8 we advertise YOURLS as being 7.4+ but it should work on 7.2 (although untested) 41 * so we don't want to strictly enforce a limitation that may not be necessary. 42 * 43 */ 44function yourls_check_php_version() { 45 return version_compare( PHP_VERSION, '7.2.0', '>=' ); 46} 47 48/** 49 * Check if server is an Apache 50 * 51 */ 52function yourls_is_apache() { 53 if( !array_key_exists( 'SERVER_SOFTWARE', $_SERVER ) ) 54 return false; 55 return ( 56 strpos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) !== false 57 || strpos( $_SERVER['SERVER_SOFTWARE'], 'LiteSpeed' ) !== false 58 ); 59} 60 61/** 62 * Check if server is running IIS 63 * 64 */ 65function yourls_is_iis() { 66 return ( array_key_exists( 'SERVER_SOFTWARE', $_SERVER ) ? ( strpos( $_SERVER['SERVER_SOFTWARE'], 'IIS' ) !== false ) : false ); 67} 68 69 70/** 71 * Create .htaccess or web.config. Returns boolean 72 * 73 */ 74function yourls_create_htaccess() { 75 $host = parse_url( yourls_get_yourls_site() ); 76 $path = ( isset( $host['path'] ) ? $host['path'] : '' ); 77 78 if ( yourls_is_iis() ) { 79 // Prepare content for a web.config file 80 $content = array( 81 '<?'.'xml version="1.0" encoding="UTF-8"?>', 82 '<configuration>', 83 ' <system.webServer>', 84 ' <security>', 85 ' <requestFiltering allowDoubleEscaping="true" />', 86 ' </security>', 87 ' <rewrite>', 88 ' <rules>', 89 ' <rule name="YOURLS" stopProcessing="true">', 90 ' <match url="^(.*)$" ignoreCase="false" />', 91 ' <conditions>', 92 ' <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />', 93 ' <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />', 94 ' </conditions>', 95 ' <action type="Rewrite" url="'.$path.'/yourls-loader.php" appendQueryString="true" />', 96 ' </rule>', 97 ' </rules>', 98 ' </rewrite>', 99 ' </system.webServer>', 100 '</configuration>', 101 ); 102 103 $filename = YOURLS_ABSPATH.'/web.config'; 104 $marker = 'none'; 105 106 } else { 107 // Prepare content for a .htaccess file 108 $content = array( 109 '<IfModule mod_rewrite.c>', 110 'RewriteEngine On', 111 'RewriteBase '.$path.'/', 112 'RewriteCond %{REQUEST_FILENAME} !-f', 113 'RewriteCond %{REQUEST_FILENAME} !-d', 114 'RewriteRule ^.*$ '.$path.'/yourls-loader.php [L]', 115 '</IfModule>', 116 ); 117 118 $filename = YOURLS_ABSPATH.'/.htaccess'; 119 $marker = 'YOURLS'; 120 121 } 122 123 return ( yourls_insert_with_markers( $filename, $marker, $content ) ); 124} 125 126/** 127 * Insert text into a file between BEGIN/END markers, return bool. Stolen from WP 128 * 129 * Inserts an array of strings into a file (eg .htaccess ), placing it between 130 * BEGIN and END markers. Replaces existing marked info. Retains surrounding 131 * data. Creates file if none exists. 132 * 133 * @since 1.3 134 * 135 * @param string $filename 136 * @param string $marker 137 * @param array $insertion 138 * @return bool True on write success, false on failure. 139 */ 140function yourls_insert_with_markers( $filename, $marker, $insertion ) { 141 if ( !file_exists( $filename ) || is_writeable( $filename ) ) { 142 if ( !file_exists( $filename ) ) { 143 $markerdata = ''; 144 } else { 145 $markerdata = explode( "\n", implode( '', file( $filename ) ) ); 146 } 147 148 if ( !$f = @fopen( $filename, 'w' ) ) 149 return false; 150 151 $foundit = false; 152 if ( $markerdata ) { 153 $state = true; 154 foreach ( $markerdata as $n => $markerline ) { 155 if ( strpos( $markerline, '# BEGIN ' . $marker ) !== false ) 156 $state = false; 157 if ( $state ) { 158 if ( $n + 1 < count( $markerdata ) ) 159 fwrite( $f, "{$markerline}\n" ); 160 else 161 fwrite( $f, "{$markerline}" ); 162 } 163 if ( strpos( $markerline, '# END ' . $marker ) !== false ) { 164 if ( $marker != 'none' ) 165 fwrite( $f, "# BEGIN {$marker}\n" ); 166 if ( is_array( $insertion ) ) 167 foreach ( $insertion as $insertline ) 168 fwrite( $f, "{$insertline}\n" ); 169 if ( $marker != 'none' ) 170 fwrite( $f, "# END {$marker}\n" ); 171 $state = true; 172 $foundit = true; 173 } 174 } 175 } 176 if ( !$foundit ) { 177 if ( $marker != 'none' ) 178 fwrite( $f, "\n\n# BEGIN {$marker}\n" ); 179 foreach ( $insertion as $insertline ) 180 fwrite( $f, "{$insertline}\n" ); 181 if ( $marker != 'none' ) 182 fwrite( $f, "# END {$marker}\n\n" ); 183 } 184 fclose( $f ); 185 return true; 186 } else { 187 return false; 188 } 189} 190 191/** 192 * Create MySQL tables. Return array( 'success' => array of success strings, 'errors' => array of error strings ) 193 * 194 * @since 1.3 195 * @return array An array like array( 'success' => array of success strings, 'errors' => array of error strings ) 196 */ 197function yourls_create_sql_tables() { 198 // Allow plugins (most likely a custom db.php layer in user dir) to short-circuit the whole function 199 $pre = yourls_apply_filter( 'shunt_yourls_create_sql_tables', null ); 200 // your filter function should return an array of ( 'success' => $success_msg, 'error' => $error_msg ), see below 201 if ( null !== $pre ) { 202 return $pre; 203 } 204 205 $ydb = yourls_get_db(); 206 207 $error_msg = array(); 208 $success_msg = array(); 209 210 // Create Table Query 211 $create_tables = array(); 212 $create_tables[YOURLS_DB_TABLE_URL] = 213 'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_URL.'` ('. 214 '`keyword` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL DEFAULT "",'. 215 '`url` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,'. 216 '`title` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,'. 217 '`timestamp` timestamp NOT NULL DEFAULT current_timestamp(),'. 218 '`ip` varchar(41) COLLATE utf8mb4_unicode_ci NOT NULL,'. 219 '`clicks` int(10) unsigned NOT NULL,'. 220 'PRIMARY KEY (`keyword`),'. 221 'KEY `ip` (`ip`),'. 222 'KEY `timestamp` (`timestamp`)'. 223 ') DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;'; 224 225 $create_tables[YOURLS_DB_TABLE_OPTIONS] = 226 'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('. 227 '`option_id` bigint(20) unsigned NOT NULL auto_increment,'. 228 '`option_name` varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL default "",'. 229 '`option_value` longtext COLLATE utf8mb4_unicode_ci NOT NULL,'. 230 'PRIMARY KEY (`option_id`,`option_name`),'. 231 'KEY `option_name` (`option_name`)'. 232 ') AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;'; 233 234 $create_tables[YOURLS_DB_TABLE_LOG] = 235 'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('. 236 '`click_id` int(11) NOT NULL auto_increment,'. 237 '`click_time` datetime NOT NULL,'. 238 '`shorturl` varchar(100) BINARY NOT NULL,'. 239 '`referrer` varchar(200) NOT NULL,'. 240 '`user_agent` varchar(255) NOT NULL,'. 241 '`ip_address` varchar(41) NOT NULL,'. 242 '`country_code` char(2) NOT NULL,'. 243 'PRIMARY KEY (`click_id`),'. 244 'KEY `shorturl` (`shorturl`)'. 245 ') AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;'; 246 247 248 $create_table_count = 0; 249 250 yourls_debug_mode(true); 251 252 // Create tables 253 foreach ( $create_tables as $table_name => $table_query ) { 254 $ydb->perform( $table_query ); 255 $create_success = $ydb->fetchAffected( "SHOW TABLES LIKE '$table_name'" ); 256 if( $create_success ) { 257 $create_table_count++; 258 $success_msg[] = yourls_s( "Table '%s' created.", $table_name ); 259 } else { 260 $error_msg[] = yourls_s( "Error creating table '%s'.", $table_name ); 261 } 262 } 263 264 // Initializes the option table 265 if( !yourls_initialize_options() ) 266 $error_msg[] = yourls__( 'Could not initialize options' ); 267 268 // Insert sample links 269 if( !yourls_insert_sample_links() ) 270 $error_msg[] = yourls__( 'Could not insert sample short URLs' ); 271 272 // Check results of operations 273 if ( sizeof( $create_tables ) == $create_table_count ) { 274 $success_msg[] = yourls__( 'YOURLS tables successfully created.' ); 275 } else { 276 $error_msg[] = yourls__( 'Error creating YOURLS tables.' ); 277 } 278 279 return array( 'success' => $success_msg, 'error' => $error_msg ); 280} 281 282/** 283 * Initializes the option table 284 * 285 * Each yourls_update_option() returns either true on success (option updated) or false on failure (new value == old value, or 286 * for some reason it could not save to DB). 287 * Since true & true & true = 1, we cast it to boolean type to return true (or false) 288 * 289 * @since 1.7 290 * @return bool 291 */ 292function yourls_initialize_options() { 293 return ( bool ) ( 294 yourls_update_option( 'version', YOURLS_VERSION ) 295 & yourls_update_option( 'db_version', YOURLS_DB_VERSION ) 296 & yourls_update_option( 'next_id', 1 ) 297 & yourls_update_option( 'active_plugins', array() ) 298 ); 299} 300 301/** 302 * Populates the URL table with a few sample links 303 * 304 * @since 1.7 305 * @return bool 306 */ 307function yourls_insert_sample_links() { 308 $link1 = yourls_add_new_link( 'http://blog.yourls.org/', 'yourlsblog', 'YOURLS\' Blog' ); 309 $link2 = yourls_add_new_link( 'http://yourls.org/', 'yourls', 'YOURLS: Your Own URL Shortener' ); 310 $link3 = yourls_add_new_link( 'http://ozh.org/', 'ozh', 'ozh.org' ); 311 return ( bool ) ( 312 $link1['status'] == 'success' 313 & $link2['status'] == 'success' 314 & $link3['status'] == 'success' 315 ); 316} 317 318 319/** 320 * Toggle maintenance mode. Inspired from WP. Returns true for success, false otherwise 321 * 322 */ 323function yourls_maintenance_mode( $maintenance = true ) { 324 325 $file = YOURLS_ABSPATH . '/.maintenance' ; 326 327 // Turn maintenance mode on : create .maintenance file 328 if ( (bool)$maintenance ) { 329 if ( ! ( $fp = @fopen( $file, 'w' ) ) ) 330 return false; 331 332 $maintenance_string = '<?php $maintenance_start = ' . time() . '; ?>'; 333 @fwrite( $fp, $maintenance_string ); 334 @fclose( $fp ); 335 @chmod( $file, 0644 ); // Read and write for owner, read for everybody else 336 337 // Not sure why the fwrite would fail if the fopen worked... Just in case 338 return( is_readable( $file ) ); 339 340 // Turn maintenance mode off : delete the .maintenance file 341 } else { 342 return @unlink($file); 343 } 344} 345 346