1 | <?php |
||||
2 | |||||
3 | namespace Firesphere\HaveIBeenPwned\Services; |
||||
4 | |||||
5 | use GuzzleHttp\Client; |
||||
6 | use GuzzleHttp\Exception\GuzzleException; |
||||
7 | use Psr\Http\Message\ResponseInterface; |
||||
8 | use SilverStripe\Core\Config\Configurable; |
||||
9 | use SilverStripe\Core\Convert; |
||||
10 | use SilverStripe\Core\Injector\Injector; |
||||
11 | use SilverStripe\Security\Member; |
||||
12 | |||||
13 | /** |
||||
14 | * Class HaveIBeenPwnedService |
||||
15 | * @package Firesphere\HaveIBeenPwned\Services |
||||
16 | */ |
||||
17 | class HaveIBeenPwnedService |
||||
18 | { |
||||
19 | use Configurable; |
||||
20 | |||||
21 | /** |
||||
22 | * Api endpoint emails |
||||
23 | */ |
||||
24 | const PWND_URL = 'https://haveibeenpwned.com/api/v3'; |
||||
25 | |||||
26 | /** |
||||
27 | * API endpoint passwords |
||||
28 | */ |
||||
29 | const PWND_API_URL = 'https://api.pwnedpasswords.com/'; |
||||
30 | |||||
31 | /** |
||||
32 | * API Version |
||||
33 | */ |
||||
34 | const API_VERSION = '3'; |
||||
35 | |||||
36 | /** |
||||
37 | * Useragent |
||||
38 | */ |
||||
39 | const USER_AGENT = 'Firesphere-HaveIBeenPwned-checker/1.0'; |
||||
40 | |||||
41 | /** |
||||
42 | * @config |
||||
43 | * @var bool |
||||
44 | */ |
||||
45 | private static $allow_pwnd = false; |
||||
46 | |||||
47 | /** |
||||
48 | * @config |
||||
49 | * @var bool |
||||
50 | */ |
||||
51 | private static $save_pwnd = true; |
||||
52 | |||||
53 | /** |
||||
54 | * @var array |
||||
55 | */ |
||||
56 | protected $args; |
||||
57 | |||||
58 | /** |
||||
59 | * HaveIBeenPwnedService constructor. |
||||
60 | * @param array $args |
||||
61 | */ |
||||
62 | public function __construct($args = []) |
||||
63 | { |
||||
64 | $this->args = $args; |
||||
65 | } |
||||
66 | |||||
67 | /** |
||||
68 | * @param string $pwd |
||||
69 | * @return int |
||||
70 | * @throws GuzzleException |
||||
71 | */ |
||||
72 | public function checkPwnedPassword($pwd) |
||||
73 | { |
||||
74 | $this->args['base_uri'] = static::PWND_API_URL; |
||||
75 | |||||
76 | $sha = sha1($pwd); |
||||
77 | $shaStart = substr($sha, 0, 5); |
||||
78 | $shaEnd = substr($sha, 5); |
||||
79 | /** @var Client $client */ |
||||
80 | $client = Injector::inst()->createWithArgs(Client::class, [$this->args]); |
||||
81 | $result = $client->request( |
||||
82 | 'GET', |
||||
83 | 'range/' . $shaStart, |
||||
84 | [ |
||||
85 | 'headers' => [ |
||||
86 | 'user-agent' => static::USER_AGENT, |
||||
87 | 'api-version' => static::API_VERSION |
||||
88 | ] |
||||
89 | ] |
||||
90 | ); |
||||
91 | |||||
92 | return $this->checkList($result, $shaEnd); |
||||
93 | } |
||||
94 | |||||
95 | /** |
||||
96 | * @param ResponseInterface $result |
||||
97 | * @param $shaEnd |
||||
98 | * @return int |
||||
99 | */ |
||||
100 | private function checkList($result, $shaEnd) |
||||
101 | { |
||||
102 | $count = 0; |
||||
103 | $shaEnd = strtoupper($shaEnd); |
||||
104 | $suffixes = explode("\n", $result->getBody()); |
||||
105 | foreach ($suffixes as $suffix) { |
||||
106 | list($suffix, $pwnCount) = explode(':', trim($suffix)); |
||||
107 | if ($suffix === $shaEnd) { |
||||
108 | $count += (int)$pwnCount; |
||||
109 | break; |
||||
110 | } |
||||
111 | } |
||||
112 | |||||
113 | return $count; |
||||
114 | } |
||||
115 | |||||
116 | /** |
||||
117 | * @param Member $member |
||||
118 | * @return string |
||||
119 | * @throws GuzzleException |
||||
120 | */ |
||||
121 | public function checkPwnedEmail($member) |
||||
122 | { |
||||
123 | $this->args['base_uri'] = static::PWND_URL; |
||||
124 | $api_key = $this->hibp_api_key; |
||||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||||
125 | $uniqueField = Member::config()->get('unique_identifier_field'); |
||||
126 | $account = $member->{$uniqueField}; |
||||
127 | |||||
128 | /** @var Client $client */ |
||||
129 | $client = Injector::inst()->createWithArgs(Client::class, [$this->args]); |
||||
130 | |||||
131 | $result = $client->request( |
||||
132 | 'GET', |
||||
133 | 'breachedaccount/' . $account . '?truncateResponse=true', |
||||
134 | [ |
||||
135 | 'headers' => [ |
||||
136 | 'user-agent' => static::USER_AGENT, |
||||
137 | 'api-version' => static::API_VERSION, |
||||
138 | 'hibp-api-key' => $api_key |
||||
139 | ] |
||||
140 | ] |
||||
141 | ); |
||||
142 | |||||
143 | return $this->checkBreaches($result); |
||||
144 | } |
||||
145 | |||||
146 | /** |
||||
147 | * @param ResponseInterface $result |
||||
148 | * @return string |
||||
149 | */ |
||||
150 | private function checkBreaches($result) |
||||
151 | { |
||||
152 | $body = $result->getBody(); |
||||
153 | |||||
154 | $sites = []; |
||||
155 | |||||
156 | $breaches = Convert::json2array($body); |
||||
0 ignored issues
–
show
The function
SilverStripe\Core\Convert::json2array() has been deprecated: 4.4.0:5.0.0 Use json_decode() instead
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This function has been deprecated. The supplier of the function has supplied an explanatory message. The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead. ![]() |
|||||
157 | foreach ($breaches as $breach) { |
||||
158 | if (!empty($breach['Name'])) { |
||||
159 | $sites[] = $breach['Name']; |
||||
160 | } |
||||
161 | } |
||||
162 | |||||
163 | if (count($sites)) { |
||||
164 | return implode(', ', $sites); |
||||
165 | } |
||||
166 | |||||
167 | return ''; |
||||
168 | } |
||||
169 | |||||
170 | /** |
||||
171 | * @return array |
||||
172 | */ |
||||
173 | public function getArgs() |
||||
174 | { |
||||
175 | return $this->args; |
||||
176 | } |
||||
177 | |||||
178 | /** |
||||
179 | * @param array $args |
||||
180 | */ |
||||
181 | public function setArgs($args) |
||||
182 | { |
||||
183 | $this->args = $args; |
||||
184 | } |
||||
185 | } |
||||
186 |