Completed
Push — master ( 71718d...90a3d2 )
by Rain
04:31
created

ChangePasswordPostfixAdminDriver::cryptPassword()   C

Complexity

Conditions 12
Paths 11

Size

Total Lines 48
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
eloc 33
nc 11
nop 2
dl 0
loc 48
rs 5.1266
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
class ChangePasswordPostfixAdminDriver implements \RainLoop\Providers\ChangePassword\ChangePasswordInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
4
{
5
	/**
6
	 * @var string
7
	 */
8
	private $sHost = '127.0.0.1';
9
10
	/**
11
	 * @var int
12
	 */
13
	private $iPort = 3306;
14
15
	/**
16
	 * @var string
17
	 */
18
	private $sDatabase = 'postfixadmin';
19
20
	/**
21
	* @var string
22
	*/
23
	private $sTable = 'mailbox';
24
25
	/**
26
	* @var string
27
	*/
28
	private $sUsercol = 'username';
29
30
	/**
31
	* @var string
32
	*/
33
	private $sPasscol = 'password';
34
35
	/**
36
	 * @var string
37
	 */
38
	private $sUser = 'postfixadmin';
39
40
	/**
41
	 * @var string
42
	 */
43
	private $sPassword = '';
44
45
	/**
46
	 * @var string
47
	 */
48
	private $sEncrypt = '';
49
50
	/**
51
	 * @var string
52
	 */
53
	private $sAllowedEmails = '';
54
55
	/**
56
	 * @var \MailSo\Log\Logger
57
	 */
58
	private $oLogger = null;
59
60
	/**
61
	 * @param string $sHost
62
	 *
63
	 * @return \ChangePasswordPostfixAdminDriver
64
	 */
65
	public function SetHost($sHost)
66
	{
67
		$this->sHost = $sHost;
68
		return $this;
69
	}
70
71
	/**
72
	 * @param int $iPort
73
	 *
74
	 * @return \ChangePasswordPostfixAdminDriver
75
	 */
76
	public function SetPort($iPort)
77
	{
78
		$this->iPort = (int) $iPort;
79
		return $this;
80
	}
81
82
	/**
83
	 * @param string $sDatabase
84
	 *
85
	 * @return \ChangePasswordPostfixAdminDriver
86
	 */
87
	public function SetDatabase($sDatabase)
88
	{
89
		$this->sDatabase = $sDatabase;
90
		return $this;
91
	}
92
93
	/**
94
	* @param string $sTable
95
	*
96
	* @return \ChangePasswordPostfixAdminDriver
97
	*/
98
	public function SetTable($sTable)
99
	{
100
		$this->sTable = $sTable;
101
		return $this;
102
	}
103
104
	/**
105
	* @param string $sUsercol
106
	*
107
	* @return \ChangePasswordPostfixAdminDriver
108
	*/
109
	public function SetUserColumn($sUsercol)
110
	{
111
		$this->sUsercol = $sUsercol;
112
		return $this;
113
	}
114
115
	/**
116
	* @param string $sPasscol
117
	*
118
	* @return \ChangePasswordPostfixAdminDriver
119
	*/
120
	public function SetPasswordColumn($sPasscol)
121
	{
122
		$this->sPasscol = $sPasscol;
123
		return $this;
124
	}
125
126
	/**
127
	 * @param string $sUser
128
	 *
129
	 * @return \ChangePasswordPostfixAdminDriver
130
	 */
131
	public function SetUser($sUser)
132
	{
133
		$this->sUser = $sUser;
134
		return $this;
135
	}
136
137
	/**
138
	 * @param string $sPassword
139
	 *
140
	 * @return \ChangePasswordPostfixAdminDriver
141
	 */
142
	public function SetPassword($sPassword)
143
	{
144
		$this->sPassword = $sPassword;
145
		return $this;
146
	}
147
148
	/**
149
	 * @param string $sEncrypt
150
	 *
151
	 * @return \ChangePasswordPostfixAdminDriver
152
	 */
153
	public function SetEncrypt($sEncrypt)
154
	{
155
		$this->sEncrypt = $sEncrypt;
156
		return $this;
157
	}
158
159
	/**
160
	 * @param string $sAllowedEmails
161
	 *
162
	 * @return \ChangePasswordPostfixAdminDriver
163
	 */
164
	public function SetAllowedEmails($sAllowedEmails)
165
	{
166
		$this->sAllowedEmails = $sAllowedEmails;
167
		return $this;
168
	}
169
170
	/**
171
	 * @param \MailSo\Log\Logger $oLogger
172
	 *
173
	 * @return \ChangePasswordPostfixAdminDriver
174
	 */
175
	public function SetLogger($oLogger)
176
	{
177
		if ($oLogger instanceof \MailSo\Log\Logger)
0 ignored issues
show
Bug introduced by
The class MailSo\Log\Logger does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
178
		{
179
			$this->oLogger = $oLogger;
180
		}
181
182
		return $this;
183
	}
184
185
	/**
186
	 * @param \RainLoop\Model\Account $oAccount
187
	 *
188
	 * @return bool
189
	 */
190
	public function PasswordChangePossibility($oAccount)
191
	{
192
		return $oAccount && $oAccount->Email() &&
193
			\RainLoop\Plugins\Helper::ValidateWildcardValues($oAccount->Email(), $this->sAllowedEmails);
194
	}
195
196
	/**
197
	 * @param \RainLoop\Model\Account $oAccount
198
	 * @param string $sPrevPassword
199
	 * @param string $sNewPassword
200
	 *
201
	 * @return bool
202
	 */
203 View Code Duplication
	public function ChangePassword(\RainLoop\Account $oAccount, $sPrevPassword, $sNewPassword)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
204
	{
205
		if ($this->oLogger)
206
		{
207
			$this->oLogger->Write('Postfix: Try to change password for '.$oAccount->Email());
208
		}
209
210
		unset($sPrevPassword);
211
212
		$bResult = false;
213
214
		if (0 < \strlen($sNewPassword))
215
		{
216
			try
217
			{
218
				$sDsn = 'mysql:host='.$this->sHost.';port='.$this->iPort.';dbname='.$this->sDatabase;
219
220
				$oPdo = new \PDO($sDsn, $this->sUser, $this->sPassword);
221
				$oPdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
222
223
				$sUpdatePassword = $this->cryptPassword($sNewPassword, $oPdo);
224
				if (0 < \strlen($sUpdatePassword))
225
				{
226
					$oStmt = $oPdo->prepare("UPDATE {$this->sTable} SET {$this->sPasscol} = ? WHERE {$this->sUsercol} = ?");
227
					$bResult = (bool) $oStmt->execute(array($sUpdatePassword, $oAccount->Email()));
228
				}
229
				else
230
				{
231
					if ($this->oLogger)
232
					{
233
						$this->oLogger->Write('Postfix: Encrypted password is empty',
234
							\MailSo\Log\Enumerations\Type::ERROR);
235
					}
236
				}
237
238
				$oPdo = null;
0 ignored issues
show
Unused Code introduced by
$oPdo is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
239
			}
240
			catch (\Exception $oException)
241
			{
242
				if ($this->oLogger)
243
				{
244
					$this->oLogger->WriteException($oException);
245
				}
246
			}
247
		}
248
249
		return $bResult;
250
	}
251
252
	/**
253
	 * @param string $sPassword
254
	 * @param \PDO $oPdo
255
	 *
256
	 * @return string
257
	 */
258
	private function cryptPassword($sPassword, $oPdo)
259
	{
260
		$sResult = '';
261
		$sSalt = substr(str_shuffle('./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'), 0, 16);
262
		switch (strtolower($this->sEncrypt))
263
		{
264
			default:
265
			case 'plain':
266
			case 'cleartext':
267
				$sResult = '{PLAIN}' . $sPassword;
268
				break;
269
270
			case 'md5crypt':
271
				include_once __DIR__.'/md5crypt.php';
272
				$sResult = '{MD5-CRYPT}' . md5crypt($sPassword);
273
				break;
274
275
			case 'md5':
276
				$sResult = '{PLAIN-MD5}' . md5($sPassword);
277
				break;
278
279
			case 'system':
280
				$sResult = '{CRYPT}' . crypt($sPassword);
281
				break;
282
283
			case 'sha256-crypt':
284
				$sResult = '{SHA256-CRYPT}' . crypt($sPassword,'$5$'.$sSalt);
285
				break;
286
287
			case 'sha512-crypt':
288
				$sResult = '{SHA512-CRYPT}' . crypt($sPassword,'$6$'.$sSalt);
289
				break;
290
291
			case 'mysql_encrypt':
292
				$oStmt = $oPdo->prepare('SELECT ENCRYPT(?) AS encpass');
293
				if ($oStmt->execute(array($sPassword)))
294
				{
295
					$aFetchResult = $oStmt->fetchAll(\PDO::FETCH_ASSOC);
296
					if (\is_array($aFetchResult) && isset($aFetchResult[0]['encpass']))
297
					{
298
						$sResult = $aFetchResult[0]['encpass'];
299
					}
300
				}
301
				break;
302
		}
303
304
		return $sResult;
305
	}
306
}
307