PluginProbe
Ebook Store / trunk
Ebook Store vtrunk
6.25 6.24 6.23 6.22 6.21 6.20 trunk
ebook-store / fpdi / qrcode.class.php

qrcode.class.php in Ebook Store trunk, at fpdi/qrcode.class.php

389 lines 10.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 use setasign\FpdiProtection\FpdiProtection;
3
4 require_once __DIR__ . '/bootstrap.php';
5
6 if (!function_exists('ebook_store_rc4_supported')) {
7 function ebook_store_rc4_supported() {
8 if (!function_exists('openssl_encrypt') || !function_exists('openssl_get_cipher_methods')) {
9 return false;
10 }
11 $methods = array_map('strtolower', openssl_get_cipher_methods());
12 if (!in_array('rc4-40', $methods, true) && !in_array('rc4', $methods, true)) {
13 return false;
14 }
15 if (defined('OPENSSL_VERSION_NUMBER') && OPENSSL_VERSION_NUMBER >= 0x30000000 && PHP_VERSION_ID < 80100) {
16 $out = @openssl_encrypt('SetaPDF', 'rc4-40', 'check-for-support-key', OPENSSL_RAW_DATA, '');
17 if ($out === false) {
18 return false;
19 }
20 }
21 return true;
22 }
23 }
24
25 if (!function_exists('ebook_store_should_use_arcfour_fallback')) {
26 function ebook_store_should_use_arcfour_fallback() {
27 static $fallback = null;
28 if ($fallback === null) {
29 $fallback = !ebook_store_rc4_supported();
30 if ($fallback) {
31 error_log('Ebook Store: Falling back to internal RC4 implementation for PDF encryption (OpenSSL RC4 unavailable).');
32 }
33 }
34 return $fallback;
35 }
36 }
37
38
39 global $ebook_store_page_counter;
40 $ebook_store_page_counter = 0;
41
42 if (!function_exists('ebook_store_raise_pdf_memory')) {
43 /**
44 * Make sure there is enough memory to load and re-write a PDF before TCPDF
45 * pulls the whole source into memory. Watermarking a large (multi-MB) book
46 * can peak well above the default front-end limit, so raise it toward a safe
47 * floor — but only ever upward, never lowering a host that already allows more.
48 *
49 * @param int $floor_mb Minimum megabytes the encryption pass should have.
50 */
51 function ebook_store_raise_pdf_memory($floor_mb = 256) {
52 $current = trim((string) @ini_get('memory_limit'));
53 if ($current === '' || $current === '-1') {
54 return; // Unlimited already.
55 }
56 $unit = strtolower(substr($current, -1));
57 $value = (int) $current;
58 if ($unit === 'g') {
59 $bytes = $value * 1024 * 1024 * 1024;
60 } elseif ($unit === 'm') {
61 $bytes = $value * 1024 * 1024;
62 } elseif ($unit === 'k') {
63 $bytes = $value * 1024;
64 } else {
65 $bytes = $value;
66 }
67 if ($bytes < $floor_mb * 1024 * 1024) {
68 @ini_set('memory_limit', $floor_mb . 'M');
69 }
70 }
71 }
72
73 if (!function_exists('ebook_store_text_is_rtl')) {
74 /**
75 * Does this text contain right-to-left script (Hebrew or Arabic)?
76 *
77 * @param string $text UTF-8 text.
78 * @return bool
79 */
80 function ebook_store_text_is_rtl($text) {
81 return (bool) preg_match('/[\x{0590}-\x{05FF}\x{0600}-\x{06FF}\x{0700}-\x{074F}\x{0750}-\x{077F}\x{08A0}-\x{08FF}\x{FB1D}-\x{FDFF}\x{FE70}-\x{FEFF}]/u', (string) $text);
82 }
83 }
84
85 if (!function_exists('ebook_store_pdf_watermark_font')) {
86 /**
87 * Pick a bundled Unicode font that covers the watermark text.
88 *
89 * DejaVu Sans covers Latin, Cyrillic, Greek and Hebrew; FreeSerif adds
90 * Arabic (with joining/shaping), so it is used when Arabic is present.
91 *
92 * @param string $text UTF-8 text.
93 * @return string TCPDF font family.
94 */
95 function ebook_store_pdf_watermark_font($text) {
96 if (preg_match('/[\x{0600}-\x{06FF}\x{0750}-\x{077F}\x{08A0}-\x{08FF}\x{FB50}-\x{FDFF}\x{FE70}-\x{FEFF}]/u', (string) $text)) {
97 return 'freeserif';
98 }
99 return 'dejavusans';
100 }
101 }
102
103 /**
104 * Watermark + encryption document, built on TCPDF (via its FPDI adapter).
105 *
106 * TCPDF replaces the old FPDF core-font engine so the buyer watermark can be
107 * drawn in any script — Cyrillic, Hebrew, Arabic, CJK — with an embedded
108 * Unicode font and proper right-to-left ordering. The QR code is drawn natively
109 * as vectors (no external QR service, no GD, no allow_url_fopen), and TCPDF's
110 * own SetProtection() handles encryption, so fpdi-protection is no longer used.
111 */
112 class QRPDF extends \setasign\Fpdi\Tcpdf\Fpdi {
113
114 /** @var string UTF-8 watermark line, already merged with buyer data. */
115 public $watermarkText = '';
116
117 /** @var string URL the QR code should point at. */
118 public $qrText = '';
119
120 /** @var int How many pages have been stamped so far. */
121 public $stampCount = 0;
122
123 public function __construct($orientation = 'P', $unit = 'mm', $size = 'A4') {
124 parent::__construct($orientation, $unit, $size, true, 'UTF-8', false);
125 $this->setPrintHeader(false);
126 $this->setPrintFooter(false);
127 $this->SetAutoPageBreak(false, 0);
128 $this->SetMargins(0, 0, 0);
129 $this->setCellPaddings(0, 0, 0, 0);
130 $this->setCellMargins(0, 0, 0, 0);
131 // Keep imported pages pixel-faithful.
132 $this->setImageScale(1);
133 // Embed only the glyphs actually used in the watermark, so a delivered
134 // PDF grows by a few KB rather than the whole ~600 KB Unicode font.
135 $this->setFontSubsetting(true);
136 }
137
138 /**
139 * Draw the QR code and buyer watermark onto the current (already-imported)
140 * page. Call once per page, right after useTemplate().
141 */
142 public function stampCurrentPage() {
143 // "First page only" mode: skip everything after the first stamp.
144 if (get_option('ebook_store_watermark_mode', 'every') === 'first' && $this->stampCount >= 1) {
145 $this->stampCount++;
146 return;
147 }
148
149 $pw = $this->getPageWidth();
150 $ph = $this->getPageHeight();
151
152 if (get_option('qr_code') && $this->qrText !== '') {
153 $box = 18;
154 $style = array(
155 'border' => 0,
156 'vpadding' => 0,
157 'hpadding' => 0,
158 'fgcolor' => array(0, 0, 0),
159 'bgcolor' => false,
160 'module_width' => 1,
161 'module_height' => 1,
162 );
163 $this->write2DBarcode($this->qrText, 'QRCODE,M', $pw - $box - 4, $ph - $box - 4, $box, $box, $style, 'N');
164 }
165
166 if (get_option('buyer_info') && $this->watermarkText !== '') {
167 $this->SetFont(ebook_store_pdf_watermark_font($this->watermarkText), '', 11);
168
169 $rgb = sscanf((string) get_option('ebook_store_watermark_color_hex', '#FF0000'), '#%02x%02x%02x');
170 $this->SetTextColor((int) $rgb[0], (int) $rgb[1], (int) $rgb[2]);
171
172 // TCPDF re-orders right-to-left text correctly when RTL mode is on.
173 $this->setRTL(ebook_store_text_is_rtl($this->watermarkText));
174
175 $position = get_option('ebook_store_buyer_info_position', 'top');
176 if ($position === 'bottom') {
177 $y = $ph - 12;
178 } elseif ($position === 'middle') {
179 $y = ($ph / 2) - 4;
180 } else {
181 $y = 4;
182 }
183
184 $this->SetXY(0, $y);
185 $this->Cell(0, 8, $this->watermarkText, 0, 0, 'C');
186 $this->setRTL(false);
187 }
188
189 $this->stampCount++;
190 }
191
192 /**
193 * Apply the reader restrictions and passwords, mapping the plugin's options
194 * to TCPDF's permission model (a list of GRANTED permissions).
195 *
196 * @param string $user_password Password the reader types to open the file.
197 * @param string $owner_password Password that can change the restrictions.
198 */
199 public function applyProtection($user_password, $owner_password) {
200 $granted = array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high');
201
202 if (get_option('disable_pdf_printing') == 1) {
203 $granted = array_diff($granted, array('print', 'print-high'));
204 }
205 if (get_option('disable_pdf_copy') == 1) {
206 $granted = array_diff($granted, array('copy', 'extract'));
207 }
208 if (get_option('disable_pdf_modify') == 1) {
209 $granted = array_diff($granted, array('modify', 'assemble'));
210 }
211 if (get_option('disable_annot-forms') == 1) {
212 $granted = array_diff($granted, array('annot-forms', 'fill-forms'));
213 }
214
215 // TCPDF: SetProtection(permissions_granted, user_pass, owner_pass).
216 // An owner password is required for the restrictions to be enforceable.
217 $this->SetProtection(
218 array_values($granted),
219 (string) $user_password,
220 $owner_password !== '' ? (string) $owner_password : null
221 );
222 }
223 }
224
225 class QRClass{
226
227
228
229 /* Plain text */
230
231
232
233 public function text($text, $size_h = 350, $size_w = 350) {
234
235
236
237 // return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl='.urlencode($text);
238 return 'https://api.qrserver.com/v1/create-qr-code/?size='.$size_w.'x'.$size_h.'&data='.urlencode($text);
239
240
241
242 }
243
244
245
246 /* E-mail addresses */
247
248
249
250 function email($email, $size_h = 350, $size_w = 350) {
251
252
253
254 //return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl=mailto%3A'.urlencode($email);
255 return 'https://api.qrserver.com/v1/create-qr-code/?size='.$size_w.'x'.$size_h.'&data='.urlencode($text);
256
257
258
259 }
260
261
262
263 /* Phone numbers */
264
265
266
267 function phone_numbers($number, $size_h = 350, $size_w = 350) {
268
269
270
271 return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl=tel%3A'.urlencode($number);
272
273
274
275 }
276
277
278
279 /* URL */
280
281
282
283 function url($url, $size_h = 350, $size_w = 350) {
284
285
286
287 return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl='.urlencode($url);
288
289
290
291 }
292
293
294
295 /* SMS */
296
297
298
299 function sms($receiver, $message, $size_h = 350, $size_w = 350) {
300
301
302
303 return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl=smsto%3A'.urlencode($receiver).'%3A'.urlencode($message);
304
305
306
307 }
308
309
310
311 /* Wifi network */
312
313
314
315 function wifi($ssid, $password, $type, $size_h = 350, $size_w = 350) {
316
317
318
319 return 'http://chart.apis.google.com/chart?cht=qr&chs='.$size_w.'x'.$size_h.'&chl=WIFI%3AS%3A'.$ssid.'%3BT%3A'.$type.'%3BP%3A'.$password.'%3B%3B';
320
321
322
323 }
324
325
326
327 /* Save image */
328
329
330
331 function save($image, $destination) {
332
333
334
335 if(file_exists($destination)) {
336
337
338
339 return FALSE;
340
341
342
343 } else {
344
345
346 //wp_die(' IMG PATH ' . $image);
347
348
349 $fp = fopen ($destination, 'w+'); // open file handle
350
351 $ch = curl_init($image);
352 // curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // enable if you want
353 curl_setopt($ch, CURLOPT_FILE, $fp); // output to file
354 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
355 curl_setopt($ch, CURLOPT_TIMEOUT, 1000); // some large value to allow curl to run for a long time
356 curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36');
357 // curl_setopt($ch, CURLOPT_VERBOSE, true); // Enable this line to see debug prints
358 curl_exec($ch);
359
360 curl_close($ch); // closing curl handle
361 fclose($fp);
362
363
364 //$img = imagecreatefrompng($image);
365
366 //imagepng($img, $destination);
367
368 //file_put_contents($destination,file_get_contents($image));
369
370 return TRUE;
371
372
373
374 }
375
376
377
378 }
379
380
381
382
383
384 }
385
386
387
388 ?>
389