Completed
Pull Request — master (#2282)
by ྅༻ Ǭɀħ
01:35
created

functions-install.php ➔ yourls_check_PDO()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * Check if we have PDO installed, returns bool
5
 *
6
 * @since 1.7.3
7
 * @return bool
8
 */
9
function yourls_check_PDO() {
10
    return extension_loaded('pdo');
11
}
12
13
/**
14
 * Check if server has MySQL 5.0+
15
 *
16
 */
17
function 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
 */
27
function 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
	global $ydb;
34
35
	return yourls_sanitize_version($ydb->mysql_version());
36
}
37
38
/**
39
 * Check if PHP > 5.3
40
 *
41
 */
42
function yourls_check_php_version() {
43
    return(defined('PHP_VERSION_ID') && PHP_VERSION_ID > 50300);
44
}
45
46
/**
47
 * Check if server is an Apache
48
 *
49
 */
50
function yourls_is_apache() {
51
	if( !array_key_exists( 'SERVER_SOFTWARE', $_SERVER ) )
52
		return false;
53
	return (
54
	   strpos( $_SERVER['SERVER_SOFTWARE'], 'Apache' ) !== false
55
	|| strpos( $_SERVER['SERVER_SOFTWARE'], 'LiteSpeed' ) !== false
56
	);
57
}
58
59
/**
60
 * Check if server is running IIS
61
 *
62
 */
63
function yourls_is_iis() {
64
	return ( array_key_exists( 'SERVER_SOFTWARE', $_SERVER ) ? ( strpos( $_SERVER['SERVER_SOFTWARE'], 'IIS' ) !== false ) : false );
65
}
66
67
68
/**
69
 * Create .htaccess or web.config. Returns boolean
70
 *
71
 */
72
function yourls_create_htaccess() {
73
	$host = parse_url( YOURLS_SITE );
74
	$path = ( isset( $host['path'] ) ? $host['path'] : '' );
75
76
	if ( yourls_is_iis() ) {
77
		// Prepare content for a web.config file
78
		$content = array(
79
			'<?'.'xml version="1.0" encoding="UTF-8"?>',
80
			'<configuration>',
81
			'    <system.webServer>',
82
			'        <security>',
83
			'            <requestFiltering allowDoubleEscaping="true" />',
84
			'        </security>',
85
			'        <rewrite>',
86
			'            <rules>',
87
			'                <rule name="YOURLS" stopProcessing="true">',
88
			'                    <match url="^(.*)$" ignoreCase="false" />',
89
			'                    <conditions>',
90
			'                        <add input="{REQUEST_FILENAME}" matchType="IsFile" ignoreCase="false" negate="true" />',
91
			'                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" ignoreCase="false" negate="true" />',
92
			'                    </conditions>',
93
			'                    <action type="Rewrite" url="'.$path.'/yourls-loader.php" appendQueryString="true" />',
94
			'                </rule>',
95
			'            </rules>',
96
			'        </rewrite>',
97
			'    </system.webServer>',
98
			'</configuration>',
99
		);
100
101
		$filename = YOURLS_ABSPATH.'/web.config';
102
		$marker = 'none';
103
104
	} else {
105
		// Prepare content for a .htaccess file
106
		$content = array(
107
			'<IfModule mod_rewrite.c>',
108
			'RewriteEngine On',
109
			'RewriteBase '.$path.'/',
110
			'RewriteCond %{REQUEST_FILENAME} !-f',
111
			'RewriteCond %{REQUEST_FILENAME} !-d',
112
			'RewriteRule ^.*$ '.$path.'/yourls-loader.php [L]',
113
			'</IfModule>',
114
		);
115
116
		$filename = YOURLS_ABSPATH.'/.htaccess';
117
		$marker = 'YOURLS';
118
119
	}
120
121
	return ( yourls_insert_with_markers( $filename, $marker, $content ) );
122
}
123
124
/**
125
 * Insert text into a file between BEGIN/END markers, return bool. Stolen from WP
126
 *
127
 * Inserts an array of strings into a file (eg .htaccess ), placing it between
128
 * BEGIN and END markers. Replaces existing marked info. Retains surrounding
129
 * data. Creates file if none exists.
130
 *
131
 * @since 1.3
132
 *
133
 * @param string $filename
134
 * @param string $marker
135
 * @param array  $insertion
136
 * @return bool True on write success, false on failure.
137
 */
138
function yourls_insert_with_markers( $filename, $marker, $insertion ) {
139
	if ( !file_exists( $filename ) || is_writeable( $filename ) ) {
140
		if ( !file_exists( $filename ) ) {
141
			$markerdata = '';
142
		} else {
143
			$markerdata = explode( "\n", implode( '', file( $filename ) ) );
144
		}
145
146
		if ( !$f = @fopen( $filename, 'w' ) )
147
			return false;
148
149
		$foundit = false;
150
		if ( $markerdata ) {
151
			$state = true;
152
			foreach ( $markerdata as $n => $markerline ) {
0 ignored issues
show
Bug introduced by
The expression $markerdata of type string|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
153
				if ( strpos( $markerline, '# BEGIN ' . $marker ) !== false )
154
					$state = false;
155
				if ( $state ) {
156
					if ( $n + 1 < count( $markerdata ) )
157
						fwrite( $f, "{$markerline}\n" );
158
					else
159
						fwrite( $f, "{$markerline}" );
160
				}
161
				if ( strpos( $markerline, '# END ' . $marker ) !== false ) {
162
					if ( $marker != 'none' )
163
						fwrite( $f, "# BEGIN {$marker}\n" );
164
					if ( is_array( $insertion ) )
165
						foreach ( $insertion as $insertline )
166
							fwrite( $f, "{$insertline}\n" );
167
					if ( $marker != 'none' )
168
						fwrite( $f, "# END {$marker}\n" );
169
					$state = true;
170
					$foundit = true;
171
				}
172
			}
173
		}
174
		if ( !$foundit ) {
175
			if ( $marker != 'none' )
176
				fwrite( $f, "\n\n# BEGIN {$marker}\n" );
177
			foreach ( $insertion as $insertline )
178
				fwrite( $f, "{$insertline}\n" );
179
			if ( $marker != 'none' )
180
				fwrite( $f, "# END {$marker}\n\n" );
181
		}
182
		fclose( $f );
183
		return true;
184
	} else {
185
		return false;
186
	}
187
}
188
189
/**
190
 * Create MySQL tables. Return array( 'success' => array of success strings, 'errors' => array of error strings )
191
 *
192
 * @since 1.3
193
 * @return array  An array like array( 'success' => array of success strings, 'errors' => array of error strings )
194
 */
195
function yourls_create_sql_tables() {
196
    // Allow plugins (most likely a custom db.php layer in user dir) to short-circuit the whole function
197
    $pre = yourls_apply_filter( 'shunt_yourls_create_sql_tables', null );
198
    // your filter function should return an array of ( 'success' => $success_msg, 'error' => $error_msg ), see below
199
    if ( null !== $pre ) {
200
        return $pre;
201
    }
202
203
	global $ydb;
204
205
	$error_msg = array();
206
	$success_msg = array();
207
208
	// Create Table Query
209
	$create_tables = array();
210
	$create_tables[YOURLS_DB_TABLE_URL] =
211
		'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_URL.'` ('.
212
		'`keyword` varchar(200) BINARY NOT NULL,'.
213
		'`url` text BINARY NOT NULL,'.
214
		'`title` text CHARACTER SET utf8,'.
215
		'`timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,'.
216
		'`ip` VARCHAR(41) NOT NULL,'.
217
		'`clicks` INT(10) UNSIGNED NOT NULL,'.
218
		' PRIMARY KEY  (`keyword`),'.
219
		' KEY `timestamp` (`timestamp`),'.
220
		' KEY `ip` (`ip`)'.
221
		');';
222
223
	$create_tables[YOURLS_DB_TABLE_OPTIONS] =
224
		'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_OPTIONS.'` ('.
225
		'`option_id` bigint(20) unsigned NOT NULL auto_increment,'.
226
		'`option_name` varchar(64) NOT NULL default "",'.
227
		'`option_value` longtext NOT NULL,'.
228
		'PRIMARY KEY  (`option_id`,`option_name`),'.
229
		'KEY `option_name` (`option_name`)'.
230
		') AUTO_INCREMENT=1 ;';
231
232
	$create_tables[YOURLS_DB_TABLE_LOG] =
233
		'CREATE TABLE IF NOT EXISTS `'.YOURLS_DB_TABLE_LOG.'` ('.
234
		'`click_id` int(11) NOT NULL auto_increment,'.
235
		'`click_time` datetime NOT NULL,'.
236
		'`shorturl` varchar(200) BINARY NOT NULL,'.
237
		'`referrer` varchar(200) NOT NULL,'.
238
		'`user_agent` varchar(255) NOT NULL,'.
239
		'`ip_address` varchar(41) NOT NULL,'.
240
		'`country_code` char(2) NOT NULL,'.
241
		'PRIMARY KEY  (`click_id`),'.
242
		'KEY `shorturl` (`shorturl`)'.
243
		') AUTO_INCREMENT=1 ;';
244
245
246
	$create_table_count = 0;
247
248
    yourls_debug_mode(true);
249
250
	// Create tables
251
	foreach ( $create_tables as $table_name => $table_query ) {
252
		$ydb->perform( $table_query );
253
		$create_success = $ydb->fetchAffected( "SHOW TABLES LIKE '$table_name'" );
254
		if( $create_success ) {
255
			$create_table_count++;
256
			$success_msg[] = yourls_s( "Table '%s' created.", $table_name );
257
		} else {
258
			$error_msg[] = yourls_s( "Error creating table '%s'.", $table_name );
259
		}
260
	}
261
262
	// Initializes the option table
263
	if( !yourls_initialize_options() )
264
		$error_msg[] = yourls__( 'Could not initialize options' );
265
266
	// Insert sample links
267
	if( !yourls_insert_sample_links() )
268
		$error_msg[] = yourls__( 'Could not insert sample short URLs' );
269
270
	// Check results of operations
271
	if ( sizeof( $create_tables ) == $create_table_count ) {
272
		$success_msg[] = yourls__( 'YOURLS tables successfully created.' );
273
	} else {
274
		$error_msg[] = yourls__( 'Error creating YOURLS tables.' );
275
	}
276
277
	return array( 'success' => $success_msg, 'error' => $error_msg );
278
}
279
280
/**
281
 * Initializes the option table
282
 *
283
 * Each yourls_update_option() returns either true on success (option updated) or false on failure (new value == old value, or
284
 * for some reason it could not save to DB).
285
 * Since true & true & true = 1, we cast it to boolean type to return true (or false)
286
 *
287
 * @since 1.7
288
 * @return bool
289
 */
290
function yourls_initialize_options() {
291
	return ( bool ) (
292
		  yourls_update_option( 'version', YOURLS_VERSION )
293
		& yourls_update_option( 'db_version', YOURLS_DB_VERSION )
294
		& yourls_update_option( 'next_id', 1 )
295
        & yourls_update_option( 'active_plugins', array() )
296
	);
297
}
298
299
/**
300
 * Populates the URL table with a few sample links
301
 *
302
 * @since 1.7
303
 * @return bool
304
 */
305
function yourls_insert_sample_links() {
306
	$link1 = yourls_add_new_link( 'http://blog.yourls.org/', 'yourlsblog', 'YOURLS\' Blog' );
307
	$link2 = yourls_add_new_link( 'http://yourls.org/',      'yourls',     'YOURLS: Your Own URL Shortener' );
308
	$link3 = yourls_add_new_link( 'http://ozh.org/',         'ozh',        'ozh.org' );
309
	return ( bool ) (
310
		  $link1['status'] == 'success'
0 ignored issues
show
Comprehensibility introduced by
Consider adding parentheses for clarity. Current Interpretation: ($link1['status'] == 'su...['status'] == 'success', Probably Intended Meaning: $link1['status'] == ('su...'status'] == 'success')

When comparing the result of a bit operation, we suggest to add explicit parenthesis and not to rely on PHP’s built-in operator precedence to ensure the code behaves as intended and to make it more readable.

Let’s take a look at these examples:

// Returns always int(0).
return 0 === $foo & 4;
return (0 === $foo) & 4;

// More likely intended return: true/false
return 0 === ($foo & 4);
Loading history...
311
		& $link2['status'] == 'success'
312
		& $link3['status'] == 'success'
313
	);
314
}
315
316
317
/**
318
 * Toggle maintenance mode. Inspired from WP. Returns true for success, false otherwise
319
 *
320
 */
321
function yourls_maintenance_mode( $maintenance = true ) {
322
323
	$file = YOURLS_ABSPATH . '/.maintenance' ;
324
325
	// Turn maintenance mode on : create .maintenance file
326
	if ( (bool)$maintenance ) {
327
		if ( ! ( $fp = @fopen( $file, 'w' ) ) )
328
			return false;
329
330
		$maintenance_string = '<?php $maintenance_start = ' . time() . '; ?>';
331
		@fwrite( $fp, $maintenance_string );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
332
		@fclose( $fp );
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
333
		@chmod( $file, 0644 ); // Read and write for owner, read for everybody else
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
334
335
		// Not sure why the fwrite would fail if the fopen worked... Just in case
336
		return( is_readable( $file ) );
337
338
	// Turn maintenance mode off : delete the .maintenance file
339
	} else {
340
		return @unlink($file);
341
	}
342
}
343
344