PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.9.0
WP 2FA – Two-factor authentication for WordPress v2.9.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / bacon / bacon-qr-code / src / Encoder / MaskUtil.php
wp-2fa / includes / classes / bacon / bacon-qr-code / src / Encoder Last commit date
BlockPair.php 11 months ago ByteMatrix.php 11 months ago Encoder.php 11 months ago MaskUtil.php 11 months ago MatrixUtil.php 11 months ago QrCode.php 11 months ago
MaskUtil.php
184 lines
1 <?php
2
3 declare (strict_types=1);
4 namespace WP2FA_Vendor\BaconQrCode\Encoder;
5
6 use WP2FA_Vendor\BaconQrCode\Common\BitUtils;
7 use WP2FA_Vendor\BaconQrCode\Exception\InvalidArgumentException;
8 /**
9 * Mask utility.
10 */
11 final class MaskUtil
12 {
13 /**#@+
14 * Penalty weights from section 6.8.2.1
15 */
16 const N1 = 3;
17 const N2 = 3;
18 const N3 = 40;
19 const N4 = 10;
20 /**#@-*/
21 private function __construct()
22 {
23 }
24 /**
25 * Applies mask penalty rule 1 and returns the penalty.
26 *
27 * Finds repetitive cells with the same color and gives penalty to them.
28 * Example: 00000 or 11111.
29 */
30 public static function applyMaskPenaltyRule1(ByteMatrix $matrix) : int
31 {
32 return self::applyMaskPenaltyRule1Internal($matrix, \true) + self::applyMaskPenaltyRule1Internal($matrix, \false);
33 }
34 /**
35 * Applies mask penalty rule 2 and returns the penalty.
36 *
37 * Finds 2x2 blocks with the same color and gives penalty to them. This is
38 * actually equivalent to the spec's rule, which is to find MxN blocks and
39 * give a penalty proportional to (M-1)x(N-1), because this is the number of
40 * 2x2 blocks inside such a block.
41 */
42 public static function applyMaskPenaltyRule2(ByteMatrix $matrix) : int
43 {
44 $penalty = 0;
45 $array = $matrix->getArray();
46 $width = $matrix->getWidth();
47 $height = $matrix->getHeight();
48 for ($y = 0; $y < $height - 1; ++$y) {
49 for ($x = 0; $x < $width - 1; ++$x) {
50 $value = $array[$y][$x];
51 if ($value === $array[$y][$x + 1] && $value === $array[$y + 1][$x] && $value === $array[$y + 1][$x + 1]) {
52 ++$penalty;
53 }
54 }
55 }
56 return self::N2 * $penalty;
57 }
58 /**
59 * Applies mask penalty rule 3 and returns the penalty.
60 *
61 * Finds consecutive cells of 00001011101 or 10111010000, and gives penalty
62 * to them. If we find patterns like 000010111010000, we give penalties
63 * twice (i.e. 40 * 2).
64 */
65 public static function applyMaskPenaltyRule3(ByteMatrix $matrix) : int
66 {
67 $penalty = 0;
68 $array = $matrix->getArray();
69 $width = $matrix->getWidth();
70 $height = $matrix->getHeight();
71 for ($y = 0; $y < $height; ++$y) {
72 for ($x = 0; $x < $width; ++$x) {
73 if ($x + 6 < $width && 1 === $array[$y][$x] && 0 === $array[$y][$x + 1] && 1 === $array[$y][$x + 2] && 1 === $array[$y][$x + 3] && 1 === $array[$y][$x + 4] && 0 === $array[$y][$x + 5] && 1 === $array[$y][$x + 6] && ($x + 10 < $width && 0 === $array[$y][$x + 7] && 0 === $array[$y][$x + 8] && 0 === $array[$y][$x + 9] && 0 === $array[$y][$x + 10] || $x - 4 >= 0 && 0 === $array[$y][$x - 1] && 0 === $array[$y][$x - 2] && 0 === $array[$y][$x - 3] && 0 === $array[$y][$x - 4])) {
74 $penalty += self::N3;
75 }
76 if ($y + 6 < $height && 1 === $array[$y][$x] && 0 === $array[$y + 1][$x] && 1 === $array[$y + 2][$x] && 1 === $array[$y + 3][$x] && 1 === $array[$y + 4][$x] && 0 === $array[$y + 5][$x] && 1 === $array[$y + 6][$x] && ($y + 10 < $height && 0 === $array[$y + 7][$x] && 0 === $array[$y + 8][$x] && 0 === $array[$y + 9][$x] && 0 === $array[$y + 10][$x] || $y - 4 >= 0 && 0 === $array[$y - 1][$x] && 0 === $array[$y - 2][$x] && 0 === $array[$y - 3][$x] && 0 === $array[$y - 4][$x])) {
77 $penalty += self::N3;
78 }
79 }
80 }
81 return $penalty;
82 }
83 /**
84 * Applies mask penalty rule 4 and returns the penalty.
85 *
86 * Calculates the ratio of dark cells and gives penalty if the ratio is far
87 * from 50%. It gives 10 penalty for 5% distance.
88 */
89 public static function applyMaskPenaltyRule4(ByteMatrix $matrix) : int
90 {
91 $numDarkCells = 0;
92 $array = $matrix->getArray();
93 $width = $matrix->getWidth();
94 $height = $matrix->getHeight();
95 for ($y = 0; $y < $height; ++$y) {
96 $arrayY = $array[$y];
97 for ($x = 0; $x < $width; ++$x) {
98 if (1 === $arrayY[$x]) {
99 ++$numDarkCells;
100 }
101 }
102 }
103 $numTotalCells = $height * $width;
104 $darkRatio = $numDarkCells / $numTotalCells;
105 $fixedPercentVariances = (int) (\abs($darkRatio - 0.5) * 20);
106 return $fixedPercentVariances * self::N4;
107 }
108 /**
109 * Returns the mask bit for "getMaskPattern" at "x" and "y".
110 *
111 * See 8.8 of JISX0510:2004 for mask pattern conditions.
112 *
113 * @throws InvalidArgumentException if an invalid mask pattern was supplied
114 */
115 public static function getDataMaskBit(int $maskPattern, int $x, int $y) : bool
116 {
117 switch ($maskPattern) {
118 case 0:
119 $intermediate = $y + $x & 0x1;
120 break;
121 case 1:
122 $intermediate = $y & 0x1;
123 break;
124 case 2:
125 $intermediate = $x % 3;
126 break;
127 case 3:
128 $intermediate = ($y + $x) % 3;
129 break;
130 case 4:
131 $intermediate = BitUtils::unsignedRightShift($y, 1) + (int) ($x / 3) & 0x1;
132 break;
133 case 5:
134 $temp = $y * $x;
135 $intermediate = ($temp & 0x1) + $temp % 3;
136 break;
137 case 6:
138 $temp = $y * $x;
139 $intermediate = ($temp & 0x1) + $temp % 3 & 0x1;
140 break;
141 case 7:
142 $temp = $y * $x;
143 $intermediate = $temp % 3 + ($y + $x & 0x1) & 0x1;
144 break;
145 default:
146 throw new InvalidArgumentException('Invalid mask pattern: ' . $maskPattern);
147 }
148 return 0 == $intermediate;
149 }
150 /**
151 * Helper function for applyMaskPenaltyRule1.
152 *
153 * We need this for doing this calculation in both vertical and horizontal
154 * orders respectively.
155 */
156 private static function applyMaskPenaltyRule1Internal(ByteMatrix $matrix, bool $isHorizontal) : int
157 {
158 $penalty = 0;
159 $iLimit = $isHorizontal ? $matrix->getHeight() : $matrix->getWidth();
160 $jLimit = $isHorizontal ? $matrix->getWidth() : $matrix->getHeight();
161 $array = $matrix->getArray();
162 for ($i = 0; $i < $iLimit; ++$i) {
163 $numSameBitCells = 0;
164 $prevBit = -1;
165 for ($j = 0; $j < $jLimit; $j++) {
166 $bit = $isHorizontal ? $array[$i][$j] : $array[$j][$i];
167 if ($bit === $prevBit) {
168 ++$numSameBitCells;
169 } else {
170 if ($numSameBitCells >= 5) {
171 $penalty += self::N1 + ($numSameBitCells - 5);
172 }
173 $numSameBitCells = 1;
174 $prevBit = $bit;
175 }
176 }
177 if ($numSameBitCells >= 5) {
178 $penalty += self::N1 + ($numSameBitCells - 5);
179 }
180 }
181 return $penalty;
182 }
183 }
184