1 <?php 2 3 declare(strict_types=1); 4 5 /* 6 * The MIT License (MIT) 7 * 8 * Copyright (c) 2014-2018 Spomky-Labs 9 * 10 * This software may be modified and distributed under the terms 11 * of the MIT license. See the LICENSE file for details. 12 */ 13 14 namespace OTPHP; 15 16 use Assert\Assertion; 17 use ParagonIE\ConstantTime\Base32; 18 19 trait ParameterTrait 20 { 21 /** 22 * @var array 23 */ 24 private $parameters = []; 25 26 /** 27 * @var string|null 28 */ 29 private $issuer = null; 30 31 /** 32 * @var string|null 33 */ 34 private $label = null; 35 36 /** 37 * @var bool 38 */ 39 private $issuer_included_as_parameter = true; 40 41 /** 42 * @return array 43 */ 44 public function getParameters(): array 45 { 46 $parameters = $this->parameters; 47 48 if (null !== $this->getIssuer() && $this->isIssuerIncludedAsParameter() === true) { 49 $parameters['issuer'] = $this->getIssuer(); 50 } 51 52 return $parameters; 53 } 54 55 /** 56 * @return string 57 */ 58 public function getSecret(): string 59 { 60 return $this->getParameter('secret'); 61 } 62 63 /** 64 * @param string|null $secret 65 */ 66 private function setSecret($secret) 67 { 68 $this->setParameter('secret', $secret); 69 } 70 71 /** 72 * @return string|null 73 */ 74 public function getLabel() 75 { 76 return $this->label; 77 } 78 79 /** 80 * @param string $label 81 */ 82 public function setLabel(string $label) 83 { 84 $this->setParameter('label', $label); 85 } 86 87 /** 88 * @return string|null 89 */ 90 public function getIssuer() 91 { 92 return $this->issuer; 93 } 94 95 /** 96 * @param string $issuer 97 */ 98 public function setIssuer(string $issuer) 99 { 100 $this->setParameter('issuer', $issuer); 101 } 102 103 /** 104 * @return bool 105 */ 106 public function isIssuerIncludedAsParameter(): bool 107 { 108 return $this->issuer_included_as_parameter; 109 } 110 111 /** 112 * @param bool $issuer_included_as_parameter 113 */ 114 public function setIssuerIncludedAsParameter(bool $issuer_included_as_parameter) 115 { 116 $this->issuer_included_as_parameter = $issuer_included_as_parameter; 117 } 118 119 /** 120 * @return int 121 */ 122 public function getDigits(): int 123 { 124 return $this->getParameter('digits'); 125 } 126 127 /** 128 * @param int $digits 129 */ 130 private function setDigits(int $digits) 131 { 132 $this->setParameter('digits', $digits); 133 } 134 135 /** 136 * @return string 137 */ 138 public function getDigest(): string 139 { 140 return $this->getParameter('algorithm'); 141 } 142 143 /** 144 * @param string $digest 145 */ 146 private function setDigest(string $digest) 147 { 148 $this->setParameter('algorithm', $digest); 149 } 150 151 /** 152 * @param string $parameter 153 * 154 * @return bool 155 */ 156 public function hasParameter(string $parameter): bool 157 { 158 return array_key_exists($parameter, $this->parameters); 159 } 160 161 /** 162 * @param string $parameter 163 * 164 * @return mixed 165 */ 166 public function getParameter(string $parameter) 167 { 168 if ($this->hasParameter($parameter)) { 169 return $this->getParameters()[$parameter]; 170 } 171 172 throw new \InvalidArgumentException(sprintf('Parameter "%s" does not exist', $parameter)); 173 } 174 175 /** 176 * @param string $parameter 177 * @param mixed $value 178 */ 179 public function setParameter(string $parameter, $value) 180 { 181 $map = $this->getParameterMap(); 182 183 if (true === array_key_exists($parameter, $map)) { 184 $callback = $map[$parameter]; 185 $value = $callback($value); 186 } 187 188 if (property_exists($this, $parameter)) { 189 $this->$parameter = $value; 190 } else { 191 $this->parameters[$parameter] = $value; 192 } 193 } 194 195 /** 196 * @return array 197 */ 198 protected function getParameterMap(): array 199 { 200 return [ 201 'label' => function ($value) { 202 Assertion::false($this->hasColon($value), 'Label must not contain a colon.'); 203 204 return $value; 205 }, 206 'secret' => function ($value) { 207 if (null === $value) { 208 $value = Base32::encodeUpper(random_bytes(64)); 209 } 210 $value = trim(strtoupper($value), '='); 211 212 return $value; 213 }, 214 'algorithm' => function ($value) { 215 $value = strtolower($value); 216 Assertion::inArray($value, hash_algos(), sprintf('The "%s" digest is not supported.', $value)); 217 218 return $value; 219 }, 220 'digits' => function ($value) { 221 Assertion::greaterThan($value, 0, 'Digits must be at least 1.'); 222 223 return (int) $value; 224 }, 225 'issuer' => function ($value) { 226 Assertion::false($this->hasColon($value), 'Issuer must not contain a colon.'); 227 228 return $value; 229 }, 230 ]; 231 } 232 233 /** 234 * @param string $value 235 * 236 * @return bool 237 */ 238 private function hasColon($value) 239 { 240 $colons = [':', '%3A', '%3a']; 241 foreach ($colons as $colon) { 242 if (false !== strpos($value, $colon)) { 243 return true; 244 } 245 } 246 247 return false; 248 } 249 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body