Completed
Push — feature/code-analysis ( 5519b1...bdc52b )
by Jonathan
02:58
created

Functions::isEncryptionCompatible()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 3
eloc 2
nc 3
nop 0
1
<?php
2
/**
3
 * webtrees-lib: MyArtJaub library for webtrees
4
 *
5
 * @package MyArtJaub\Webtrees
6
 * @subpackage Functions
7
 * @author Jonathan Jaubart <[email protected]>
8
 * @copyright Copyright (c) 2009-2016, Jonathan Jaubart
9
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
10
 */
11
namespace MyArtJaub\Webtrees\Functions; 
12
13
use \Fisharebest\Webtrees as fw;
14
use Fisharebest\Webtrees\Filter;
15
16
/**
17
 * General functions.
18
 */
19
class Functions {
20
21
	/**
22
	 * Size of the initialisation vector for encryption
23
	 * @var integer $ENCRYPTION_IV_SIZE
24
	 */
25
	const ENCRYPTION_IV_SIZE = 16;
26
	
27
	/**
28
	 * This array contains the cached short month names, based on the cal_info functions.
29
	 * Retrieves the abbrevmonths values of months: Jan, Feb, Mar...
30
	 * 
31
	 * @uses cal_info
32
	 * @var array $calendarShortMonths Cached array of abbreviated short month names
33
	 */
34
	private static $calendarShortMonths = array();
35
	
36
	/**
37
	 * Debug tool: prompt a Javascript pop-up with a text
38
	 *
39
	 * @param string $text Text to display
40
	 */
41
	static public function promptAlert($text){
42
		echo '<script>';
43
		echo 'alert("',fw\Filter::escapeHtml($text),'")';
44
		echo '</script>';
45
	}
46
	
47
	/**
48
	 * Return the result of a division, and a default value if denomintaor is 0
49
	 * 
50
	 * @param integer $num Numerator
51
	 * @param integer $denom Denominator
52
	 * @param float $default Default value if denominator null or 0
53
	 * @return float Result of the safe division
54
	 */
55
	public static function safeDivision($num, $denom, $default = 0) {
56
		if($denom && $denom!=0){
57
			return $num / $denom;
58
		}
59
		return $default;
60
	}
61
	
62
	/**
63
	 * Returns the percentage of two numbers
64
	 *
65
	 * @param int $num Numerator
66
	 * @param int $denom Denominator
67
	 * @param float $default Default value if denominator null or 0
68
	 * @return float Percentage
69
	 */
70
	public static function getPercentage($num, $denom, $default = 0){
71
		return 100 * self::safeDivision($num, $denom, $default);
72
	}
73
	
74
	/**
75
	 * Get width and heigth of an image resized in order fit a target size.
76
	 *
77
	 * @param string $file The image to resize
78
	 * @param int $target	The final max width/height
79
	 * @return array array of ($width, $height). One of them must be $target
80
	 */
81
	static public function getResizedImageSize($file, $target=25){
82
		list($width, $height, , ) = getimagesize($file);
83
		$max = max($width, $height);
84
		$rapp = $target / $max;
85
		$width = intval($rapp * $width);
86
		$height = intval($rapp * $height);
87
		return array($width, $height);
88
	}
89
90
	
91
	/**
92
	 * Checks if a table exist in the DB schema
93
	 *
94
	 * @param string $table Name of the table to look for
95
	 * @return boolean Does the table exist
96
	 */
97
	public static function doesTableExist($table) {
98
		try {
99
			fw\Database::prepare("SELECT 1 FROM {$table}")->fetchOne();
100
			return true;
101
		} catch (\PDOException $ex) {
102
			return false;
103
		}
104
	}
105
	
106
	/**
107
	 * Returns a randomy generated token of a given size
108
	 *
109
	 * @param int $length Length of the token, default to 32
110
	 * @return string Random token
111
	 */
112
	public static function generateRandomToken($length=32) {
113
		$chars = str_split('abcdefghijkmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
114
		$len_chars = count($chars);
115
		$token = '';
116
		
117
		for ($i = 0; $i < $length; $i++)
118
			$token .= $chars[ mt_rand(0, $len_chars - 1) ];
119
		
120
		# Number of 32 char chunks
121
		$chunks = ceil( strlen($token) / 32 );
122
		$md5token = '';
123
		
124
		# Run each chunk through md5
125
		for ( $i=1; $i<=$chunks; $i++ )
126
			$md5token .= md5( substr($token, $i * 32 - 32, 32) );
127
		
128
			# Trim the token
129
		return substr($md5token, 0, $length);		
130
	} 
131
	
132
	/**
133
	 * Checks whether the installation meets the requirements for encryption/decryption.
134
	 * 
135
	 * @return boolean
136
	 */
137
	public static function isEncryptionCompatible() {
138
	    return function_exists('mcrypt_encrypt') && function_exists('mcrypt_encrypt') && function_exists('mcrypt_decrypt');
139
	}
140
	
141
	/**	  
142
	 * Encrypt a text, and encode it to base64 compatible with URL use
143
	 * 	(no +, no /, no =)
144
	 *
145
	 * @param string $data Text to encrypt
146
	 * @return string Encrypted and encoded text
147
	 */
148
	public static function encryptToSafeBase64($data){
149
	    if(!self::isEncryptionCompatible())
150
	        throw new \Exception('MCrypt PHP extension is required to use encryption.');
151
	    
152
		$key = 'STANDARDKEYIFNOSERVER';
153 View Code Duplication
		if(Filter::server('SERVER_NAME') && Filter::server('SERVER_SOFTWARE'))
0 ignored issues
show
Bug Best Practice introduced by
The expression \Fisharebest\Webtrees\Fi...::server('SERVER_NAME') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression \Fisharebest\Webtrees\Fi...rver('SERVER_SOFTWARE') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
			$key = md5(Filter::server('SERVER_NAME').Filter::server('SERVER_SOFTWARE'));
155
		$iv = mcrypt_create_iv(self::ENCRYPTION_IV_SIZE, MCRYPT_RAND);
156
		$id = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC,$iv);
157
		$encrypted = base64_encode($iv.$id);
158
		// +, / and = are not URL-compatible
159
		$encrypted = str_replace('+', '-', $encrypted);
160
		$encrypted = str_replace('/', '_', $encrypted);
161
		$encrypted = str_replace('=', '*', $encrypted);
162
		return $encrypted;
163
	}
164
	
165
	/**
166
	 * Decode and encrypt a text from base64 compatible with URL use
167
	 *
168
	 * @param string $encrypted Text to decrypt
169
	 * @return string Decrypted text
170
	 */
171
	public static function decryptFromSafeBase64($encrypted){
172
	    if(!self::isEncryptionCompatible())
173
	        throw new \Exception('MCrypt PHP extension is required to use encryption.');
174
	    
175
		$key = 'STANDARDKEYIFNOSERVER';
176 View Code Duplication
		if(Filter::server('SERVER_NAME') && Filter::server('SERVER_SOFTWARE'))
0 ignored issues
show
Bug Best Practice introduced by
The expression \Fisharebest\Webtrees\Fi...::server('SERVER_NAME') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Bug Best Practice introduced by
The expression \Fisharebest\Webtrees\Fi...rver('SERVER_SOFTWARE') of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
177
			$key = md5(Filter::server('SERVER_NAME').Filter::server('SERVER_SOFTWARE'));
178
		$encrypted = str_replace('-', '+', $encrypted);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $encrypted. This often makes code more readable.
Loading history...
179
		$encrypted = str_replace('_', '/', $encrypted);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $encrypted. This often makes code more readable.
Loading history...
180
		$encrypted = str_replace('*', '=', $encrypted);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $encrypted. This often makes code more readable.
Loading history...
181
		$encrypted = base64_decode($encrypted);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $encrypted. This often makes code more readable.
Loading history...
182
		if(!$encrypted)
183
			throw new \InvalidArgumentException('The encrypted value is not in correct base64 format.');
184
		if(strlen($encrypted) < self::ENCRYPTION_IV_SIZE) 
185
			throw new \InvalidArgumentException('The encrypted value does not contain enough characters for the key.');
186
		$iv_dec = substr($encrypted, 0, self::ENCRYPTION_IV_SIZE);
187
		$encrypted = substr($encrypted, self::ENCRYPTION_IV_SIZE);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $encrypted. This often makes code more readable.
Loading history...
188
		$decrypted = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $encrypted, MCRYPT_MODE_CBC, $iv_dec);
189
		return  preg_replace('~(?:\\000+)$~','',$decrypted);
190
	}
191
	
192
	/**
193
	 * Encode a string from the file system encoding to UTF-8 (if necessary)
194
	 *
195
	 * @param string $string Filesystem encoded string to encode
196
	 * @return string UTF-8 encoded string
197
	 */
198
	public static function encodeFileSystemToUtf8($string){
199
		if (strtoupper(substr(php_uname('s'), 0, 7)) === 'WINDOWS') {
200
		    return iconv('cp1252', 'utf-8//IGNORE',$string);
201
		}
202
		return $string;
203
	}
204
	
205
	/**
206
	 * Encode a string from UTF-8 to the file system encoding (if necessary)
207
	 *
208
	 * @param string $string UTF-8 encoded string to encode
209
	 * @return string Filesystem encoded string
210
	 */
211
	public static function encodeUtf8ToFileSystem($string){
212
		if (preg_match('//u', $string) && strtoupper(substr(php_uname('s'), 0, 7)) === 'WINDOWS') {
213
			return iconv('utf-8', 'cp1252//IGNORE' ,  $string);
214
		}
215
		return $string;
216
	}
217
	
218
	/**
219
	 * Check whether a path is under a valid form.
220
	 * 
221
	 * @param string $filename Filename path to check
222
	 * @param boolean $acceptfolder Should folders be accepted?
223
	 * @return boolean True if path valid
224
	 */
225
	public static function isValidPath($filename, $acceptfolder = FALSE) {		
226
		if(strpbrk($filename, $acceptfolder ? '?%*:|"<>' : '\\/?%*:|"<>') === FALSE) return true;
227
		return false;
228
	}
229
	
230
	/**
231
	 * Return short names for the months of the specific calendar.
232
	 * 
233
	 * @see \cal_info()
234
	 * @param integer $calendarId Calendar ID (according to PHP cal_info)
235
	 * @return array Array of month short names
236
	 */
237
	public static function getCalendarShortMonths($calendarId = 0) {
238
		if(!isset(self::$calendarShortMonths[$calendarId])) {
239
			$calendar_info = cal_info($calendarId);
240
			self::$calendarShortMonths[$calendarId] = $calendar_info['abbrevmonths'];
241
		}		
242
		return self::$calendarShortMonths[$calendarId];
243
	}
244
	
245
	/**
246
	 * Returns the generation associated with a Sosa number
247
	 *
248
	 * @param int $sosa Sosa number
249
	 * @return number
250
	 */
251
	public static function getGeneration($sosa){
252
		return(int)log($sosa, 2)+1;
253
	}
254
	
255
	
256
257
258
	/**
259
	 * Returns whether the image type is supported by the system, and if so, return the standardised type
260
	 *
261
	 * @param string $reqtype Extension to test
262
	 * @return boolean|string Is supported?
263
	 */
264
	public static function isImageTypeSupported($reqtype) {
265
	    $supportByGD = array('jpg'=>'jpeg', 'jpeg'=>'jpeg', 'gif'=>'gif', 'png'=>'png');
266
	    $reqtype = strtolower($reqtype);
0 ignored issues
show
Coding Style introduced by
Consider using a different name than the parameter $reqtype. This often makes code more readable.
Loading history...
267
	
268
	    if (empty($supportByGD[$reqtype])) {
269
	        return false;
270
	    }
271
	
272
	    $type = $supportByGD[$reqtype];
273
	
274
	    if (function_exists('imagecreatefrom'.$type) && function_exists('image'.$type)) {
275
	        return $type;
276
	    }
277
	
278
	    return false;
279
	}
280
		
281
}
282