PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 2.4.2
WP 2FA – Two-factor authentication for WordPress v2.4.2
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 / vendor / endroid / qr-code / src / Writer / SvgWriter.php
wp-2fa / vendor / endroid / qr-code / src / Writer Last commit date
AbstractWriter.php 3 years ago BinaryWriter.php 3 years ago DebugWriter.php 3 years ago EpsWriter.php 3 years ago FpdfWriter.php 3 years ago PngWriter.php 3 years ago SvgWriter.php 3 years ago WriterInterface.php 3 years ago
SvgWriter.php
138 lines
1 <?php
2
3 declare (strict_types=1);
4 /*
5 * (c) Jeroen van den Enden <info@endroid.nl>
6 *
7 * This source file is subject to the MIT license that is bundled
8 * with this source code in the file LICENSE.
9 */
10 namespace WP2FA_Vendor\Endroid\QrCode\Writer;
11
12 use WP2FA_Vendor\Endroid\QrCode\Exception\GenerateImageException;
13 use WP2FA_Vendor\Endroid\QrCode\Exception\MissingLogoHeightException;
14 use WP2FA_Vendor\Endroid\QrCode\Exception\ValidationException;
15 use WP2FA_Vendor\Endroid\QrCode\QrCodeInterface;
16 use SimpleXMLElement;
17 class SvgWriter extends AbstractWriter
18 {
19 public function writeString(QrCodeInterface $qrCode) : string
20 {
21 $options = $qrCode->getWriterOptions();
22 if ($qrCode->getValidateResult()) {
23 throw new ValidationException('Built-in validation reader can not check SVG images: please disable via setValidateResult(false)');
24 }
25 $data = $qrCode->getData();
26 $svg = new SimpleXMLElement('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"/>');
27 $svg->addAttribute('version', '1.1');
28 $svg->addAttribute('width', $data['outer_width'] . 'px');
29 $svg->addAttribute('height', $data['outer_height'] . 'px');
30 $svg->addAttribute('viewBox', '0 0 ' . $data['outer_width'] . ' ' . $data['outer_height']);
31 $svg->addChild('defs');
32 // Block definition
33 $block_id = isset($options['rect_id']) && $options['rect_id'] ? $options['rect_id'] : 'block';
34 $blockDefinition = $svg->defs->addChild('rect');
35 $blockDefinition->addAttribute('id', $block_id);
36 $blockDefinition->addAttribute('width', \strval($data['block_size']));
37 $blockDefinition->addAttribute('height', \strval($data['block_size']));
38 $blockDefinition->addAttribute('fill', '#' . \sprintf('%02x%02x%02x', $qrCode->getForegroundColor()['r'], $qrCode->getForegroundColor()['g'], $qrCode->getForegroundColor()['b']));
39 $blockDefinition->addAttribute('fill-opacity', \strval($this->getOpacity($qrCode->getForegroundColor()['a'])));
40 // Background
41 $background = $svg->addChild('rect');
42 $background->addAttribute('x', '0');
43 $background->addAttribute('y', '0');
44 $background->addAttribute('width', \strval($data['outer_width']));
45 $background->addAttribute('height', \strval($data['outer_height']));
46 $background->addAttribute('fill', '#' . \sprintf('%02x%02x%02x', $qrCode->getBackgroundColor()['r'], $qrCode->getBackgroundColor()['g'], $qrCode->getBackgroundColor()['b']));
47 $background->addAttribute('fill-opacity', \strval($this->getOpacity($qrCode->getBackgroundColor()['a'])));
48 foreach ($data['matrix'] as $row => $values) {
49 foreach ($values as $column => $value) {
50 if (1 === $value) {
51 $block = $svg->addChild('use');
52 $block->addAttribute('x', \strval($data['margin_left'] + $data['block_size'] * $column));
53 $block->addAttribute('y', \strval($data['margin_left'] + $data['block_size'] * $row));
54 $block->addAttribute('xlink:href', '#' . $block_id, 'http://www.w3.org/1999/xlink');
55 }
56 }
57 }
58 $logoPath = $qrCode->getLogoPath();
59 if (\is_string($logoPath)) {
60 $forceXlinkHref = \false;
61 if (isset($options['force_xlink_href']) && $options['force_xlink_href']) {
62 $forceXlinkHref = \true;
63 }
64 $this->addLogo($svg, $data['outer_width'], $data['outer_height'], $logoPath, $qrCode->getLogoWidth(), $qrCode->getLogoHeight(), $forceXlinkHref);
65 }
66 $xml = $svg->asXML();
67 if (!\is_string($xml)) {
68 throw new GenerateImageException('Unable to save SVG XML');
69 }
70 if (isset($options['exclude_xml_declaration']) && $options['exclude_xml_declaration']) {
71 $xml = \str_replace("<?xml version=\"1.0\"?>\n", '', $xml);
72 }
73 return $xml;
74 }
75 private function addLogo(SimpleXMLElement $svg, int $imageWidth, int $imageHeight, string $logoPath, int $logoWidth = null, int $logoHeight = null, bool $forceXlinkHref = \false) : void
76 {
77 $mimeType = $this->getMimeType($logoPath);
78 $imageData = \file_get_contents($logoPath);
79 if (!\is_string($imageData)) {
80 throw new GenerateImageException('Unable to read image data: check your logo path');
81 }
82 if ('image/svg+xml' === $mimeType && (null === $logoHeight || null === $logoWidth)) {
83 throw new MissingLogoHeightException('SVG Logos require an explicit height set via setLogoSize($width, $height)');
84 }
85 if (null === $logoHeight || null === $logoWidth) {
86 $logoImage = \imagecreatefromstring(\strval($imageData));
87 if (!$logoImage) {
88 throw new GenerateImageException('Unable to generate image: check your GD installation or logo path');
89 }
90 /** @var mixed $logoImage */
91 $logoSourceWidth = \imagesx($logoImage);
92 $logoSourceHeight = \imagesy($logoImage);
93 if (\PHP_VERSION_ID < 80000) {
94 \imagedestroy($logoImage);
95 }
96 if (null === $logoWidth) {
97 $logoWidth = $logoSourceWidth;
98 }
99 if (null === $logoHeight) {
100 $aspectRatio = $logoWidth / $logoSourceWidth;
101 $logoHeight = \intval($logoSourceHeight * $aspectRatio);
102 }
103 }
104 $logoX = $imageWidth / 2 - $logoWidth / 2;
105 $logoY = $imageHeight / 2 - $logoHeight / 2;
106 $imageDefinition = $svg->addChild('image');
107 $imageDefinition->addAttribute('x', \strval($logoX));
108 $imageDefinition->addAttribute('y', \strval($logoY));
109 $imageDefinition->addAttribute('width', \strval($logoWidth));
110 $imageDefinition->addAttribute('height', \strval($logoHeight));
111 $imageDefinition->addAttribute('preserveAspectRatio', 'none');
112 // xlink:href is actually deprecated, but still required when placing the qr code in a pdf.
113 // SimpleXML strips out the xlink part by using addAttribute(), so it must be set directly.
114 if ($forceXlinkHref) {
115 $imageDefinition['xlink:href'] = 'data:' . $mimeType . ';base64,' . \base64_encode($imageData);
116 } else {
117 $imageDefinition->addAttribute('href', 'data:' . $mimeType . ';base64,' . \base64_encode($imageData));
118 }
119 }
120 private function getOpacity(int $alpha) : float
121 {
122 $opacity = 1 - $alpha / 127;
123 return $opacity;
124 }
125 public static function getContentType() : string
126 {
127 return 'image/svg+xml';
128 }
129 public static function getSupportedExtensions() : array
130 {
131 return ['svg'];
132 }
133 public function getName() : string
134 {
135 return 'svg';
136 }
137 }
138