PluginProbe
PDF Ink Lite – Free PDF Watermark & Password Protection / trunk
PDF Ink Lite – Free PDF Watermark & Password Protection vtrunk
4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 trunk 4.0.10 4.0.11 4.0.12 4.0.13 4.0.6 4.0.7 4.0.8 4.0.9
waterwoo-pdf / waterwoo-pdf.php

waterwoo-pdf.php in PDF Ink Lite – Free PDF Watermark & Password Protection trunk, at waterwoo-pdf.php

490 lines 17.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Plugin Name: PDF Ink Lite
4 * Plugin URI: https://wordpress.org/plugins/waterwoo-pdf/
5 * Description: Custom watermark your PDF files upon WooCommerce, Download Monitor, and Easy Digital Download customer download. Since 2014. FKA "WaterWoo"
6 * Version: 4.1.4
7 * Author: Canyon Webworks
8 * Author URI: https://pdfink.com/
9 * Donate link: https://paypal.me/canyonwebworks
10 * WC requires at least: 8.2
11 * WC tested up to: 11.1
12 *
13 * License: GPLv3 or later
14 * License URI: https://www.gnu.org/licenses/gpl-3.0.html
15 *
16 * Text Domain: waterwoo-pdf
17 * Domain path: /lang
18 *
19 * Copyright 2013-2026 Canyon Webworks
20 *
21 * This file is part of PDF Ink Lite, a plugin for WordPress. If
22 * it benefits you, please support my volunteer work
23 *
24 * https://paypal.me/canyonwebworks or/and venmo.com/canyonwebworks
25 *
26 * leave a nice review at:
27 *
28 * https://wordpress.org/support/view/plugin-reviews/waterwoo-pdf?filter=5
29 *
30 * Thank you. 😊
31 *
32 * PDF Ink Lite is free software: You can redistribute it and/or modify
33 * it under the terms of the GNU General Public
34 * License as published by the Free Software Foundation, either
35 * version 3 of the License, or (at your option) any later version.
36 *
37 * PDF Ink Lite is distributed in the hope that it will
38 * be useful, but WITHOUT ANY WARRANTY; without even the
39 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
40 * PURPOSE. See the GNU General Public License for more details.
41 *
42 * You should have received a copy of the GNU General Public License
43 * along with WordPress. If not, see <http://www.gnu.org/licenses/>.
44 *
45 * @todo maybe remove deprecated filters
46 * @todo regenerate lang files
47 *
48 */
49 defined( 'ABSPATH' ) || exit;
50
51 if ( ! defined( 'WWPDF_FREE_VERSION' ) ) {
52 define( 'WWPDF_FREE_VERSION', '4.1.4' );
53 }
54
55 if ( ! defined( 'WWPDF_FREE_MIN_PHP' ) ) {
56 define( 'WWPDF_FREE_MIN_PHP', '7.4' );
57 }
58
59 if ( ! defined( 'WWPDF_FREE_MIN_WP' ) ) {
60 define( 'WWPDF_FREE_MIN_WP', '7.0' );
61 }
62
63 if ( ! defined( 'WWPDF_FREE_MIN_WC' ) ) {
64 define( 'WWPDF_FREE_MIN_WC', '8.2' );
65 }
66
67 if ( ! defined( 'WWPDF_FILE' ) ) {
68 define( 'WWPDF_FILE', __FILE__ );
69 }
70
71 if ( ! defined( 'WWPDF_PATH' ) ) {
72 define( 'WWPDF_PATH', plugin_dir_path( __FILE__ ) );
73 }
74
75 if ( ! defined( 'PDFINK_LITE_UPLOADS_PATH' ) ) {
76 $upload_dir = wp_upload_dir();
77 $new_path = trailingslashit( $upload_dir['basedir'] ) . 'pdf-ink';
78 $old_path = trailingslashit( WP_CONTENT_DIR ) . 'uploads/pdf-ink';
79 if ( ! is_dir( $new_path ) && is_dir( $old_path ) ) {
80 $final_path = $old_path;
81 } else {
82 $final_path = $new_path;
83 }
84 define( 'PDFINK_LITE_UPLOADS_PATH', trailingslashit( $final_path ) );
85 if ( ! wp_mkdir_p( PDFINK_LITE_UPLOADS_PATH ) ) {
86 add_action( 'admin_notices', 'pdfink_lite_need_wp_content_dir_access_notice' );
87 }
88 }
89
90 class WaterWooPDF {
91
92 private static $instance = false;
93
94 /**
95 * @return bool|WaterWooPDF
96 */
97 public static function get_instance() {
98 if ( ! self::$instance ) {
99 self::$instance = new self();
100 }
101 return self::$instance;
102 }
103
104 /**
105 * Constructor
106 */
107 public function __construct() {
108
109 $this->update_db();
110 $this->includes();
111
112 if ( is_admin() ) {
113 // Backend settings
114 new WWPDF_Settings();
115
116 // Check if WooCommerce is enabled
117 if ( class_exists( 'WooCommerce' ) ) {
118 // Check WooCommerce version
119 if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, WWPDF_FREE_MIN_WC, '<' ) ) {
120 add_action( 'admin_notices', 'wwpdf_old_woo_notice' );
121 } else {
122 // Add a tab to the WooCommerce settings page
123 add_filter( 'woocommerce_get_settings_pages', function( $s ) {
124 $s[] = include WWPDF_PATH . 'classes/wwpdf-settings-woo.php';
125 return $s;
126 }, 10, 1 );
127 }
128
129 }
130
131 if ( class_exists( 'Easy_Digital_Downloads' ) ) {
132 new WWPDF_Settings_EDD();
133 }
134
135 if ( class_exists( 'WP_DLM' ) ) {
136 new WWPDF_Settings_DLM();
137 }
138
139 }
140
141 // Download/error logging
142 $GLOBALS['wwpdf_logs'] = new WWPDF_Logging();
143
144 // Only run when downloading
145 if ( ! is_admin() ) {
146 new WWPDF_Free_File_Handler();
147 }
148
149 }
150
151 /**
152 * Cloning is forbidden.
153 */
154 public function __clone() {
155 _doing_it_wrong( __FUNCTION__, __( 'Cloning is forbidden.', 'waterwoo-pdf' ), WWPDF_FREE_VERSION );
156 }
157
158 /**
159 * Unserializing instances of this class is forbidden.
160 */
161 public function __wakeup() {
162 _doing_it_wrong( __FUNCTION__, __( 'Unserializing instances of this class is forbidden.', 'waterwoo-pdf' ), WWPDF_FREE_VERSION );
163 }
164
165 /**
166 * Import and convert PDF Ink settings to match paid plugin setting names
167 *
168 * @return void
169 */
170 private function update_db() {
171
172 delete_option( 'wwpdf_donate_dismiss_08-28' );
173
174 if ( 'dejavu' === get_option( 'wwpdf_font_premium' ) ) {
175 update_option( 'wwpdf_font_premium', 'dejavusanscondensed' );
176 }
177 if ( $global = get_option( 'wwpdf_enable' ) ) {
178 update_option( 'wwpdf_global', $global );
179 delete_option( 'wwpdf_enable' );
180 }
181 if ( $footer_input = get_option( 'wwpdf_footer_input' ) ) {
182 update_option( 'wwpdf_footer_input_premium', $footer_input );
183 delete_option( 'wwpdf_footer_input' );
184 }
185
186 if ( $font = get_option( 'wwpdf_font' ) ) {
187 update_option( 'wwpdf_font_premium', $font );
188 delete_option( 'wwpdf_font' );
189 }
190
191 if ( $footer_size = get_option( 'wwpdf_footer_size' ) ) {
192 update_option( 'wwpdf_footer_size_premium', $footer_size );
193 delete_option( 'wwpdf_footer_size' );
194 }
195
196 if ( $footer_color = get_option( 'wwpdf_footer_color' ) ) {
197 update_option( 'wwpdf_footer_color_premium', $footer_color );
198 delete_option( 'wwpdf_footer_color' );
199 }
200 if ( $footer_y = get_option( 'wwpdf_footer_y' ) ) {
201 update_option( 'wwpdf_footer_finetune_Y_premium', $footer_y );
202 delete_option( 'wwpdf_footer_y' );
203 }
204
205 }
206
207 /**
208 * @return void
209 */
210 public function includes() {
211
212 include_once WWPDF_PATH . 'classes/wwpdf-logging.php';
213 include_once WWPDF_PATH . 'classes/wwpdf-settings.php';
214 include_once WWPDF_PATH . 'classes/wwpdf-settings-dlm.php';
215 include_once WWPDF_PATH . 'classes/wwpdf-settings-edd.php';
216 include_once WWPDF_PATH . 'classes/wwpdf-file-handler.php';
217 include_once WWPDF_PATH . 'classes/wwpdf-watermark.php';
218
219 }
220
221 }
222
223 if ( function_exists('is_plugin_active' ) ) {
224 if ( is_plugin_active( 'waterwoo-pdf-premium/waterwoo-pdf-premium.php' )
225 || is_plugin_active( 'pdf-ink/pdf-ink.php' ) ) {
226 wp_die( 'Before activating PDF Ink Lite, please deactivate WaterWoo PDF Premium, or PDF Ink if active. Use one or the other.', 'ERROR', [ 'back_link' => true ] );
227 }
228 if ( is_plugin_active( 'woocommerce-pdf-watermark/woocommerce-pdf-watermark.php' ) ) {
229 wp_die( 'Before activating PDF Ink Lite, please deactivate WooCommerce PDF Watermark. Unfortunately, WooCommerce created a clash by using our namespaced TCPDF code.', 'ERROR', [ 'back_link' => true ] );
230 }
231 }
232
233 function WWPDF_Free() {
234 return WaterWooPDF::get_instance();
235 }
236
237 function wwpdf_old_php_notice() {
238 echo '<div class="error"><p>' . sprintf( __( 'PDF Ink Lite supports PHP %s or later. Please update PHP on your server for better overall results.', 'waterwoo-pdf' ), WWPDF_FREE_MIN_PHP ) . '</p></div>';
239 }
240
241 function wwpdf_old_wp_notice() {
242 echo '<div class="error"><p>' . sprintf( __( 'PDF Ink Lite supports WordPress version %s or later. Please update WordPress to use this plugin.', 'waterwoo-pdf' ), WWPDF_FREE_MIN_WP ) . '</p></div>';
243 }
244
245 function wwpdf_old_woo_notice() {
246 echo '<div class="error"><p>' . sprintf( __( 'Sorry, PDF Ink Lite supports WooCommerce version %s or newer, for security reasons.', 'waterwoo-pdf' ), WWPDF_FREE_MIN_WC ) . '</p></div>';
247 }
248
249 function pdfink_lite_need_wp_content_dir_access_notice() {
250 echo '<div class="error"><p>' . __( 'PDF Ink Lite requires that the directory defined by <code>PDFINK_LITE_UPLOADS_PATH</code> (usually `<strong>wp-content/uploads/pdf-ink/</strong>`) is writable.', 'waterwoo-pdf' ) . '</p></div>';
251 }
252
253 function pdfink_cta_tb( $value ) {
254
255 add_thickbox();
256 $svg_url = plugins_url('assets/svg/pdfink-lite-sprite.svg#pdf-lover', __FILE__ );
257 echo '<style>.wc-settings-row-muted,.settings-row-muted{opacity:50%;}</style>
258 <div id="pdfink-upgrade-tb" style="display:none;">
259 <div style="display:flex;align-items:center;justify-content:space-between;padding:1.5em;gap:20px;">
260 <div>
261 <a href="https://pdfink.com/?source=wordpress" rel="noopener" target="_blank"><svg width="300px" height="225px"><use href="' . esc_url( $svg_url ) . '" /></svg></a>
262 </div>
263 <div style="text-align:center">
264 <h2>Unlock the full potential of PDF Ink</h2>
265 <p style="font-size:1.25em;">
266 Settings marked with a key &nbsp;<span class="dashicons dashicons-admin-network pdfink-upgrade" style="vertical-align:middle;"></span> are available in the full (paid) version of PDF Ink.
267 </p>
268 <p style="font-size:1.5em;font-weight:700;">
269 Visit <a href="https://pdfink.com/?source=wordpress" rel="noopener" target="_blank">pdfink.com</a> to upgrade!
270 </p>
271 </div>
272 </div>
273 </div>';
274
275 }
276
277 /**
278 * Logs a message to the debug log file
279 *
280 * @since 2.8.7
281 * @since 2.9.4 Added the 'force' option.
282 *
283 * @param string $message
284 * @global $wwpdf_logs WWPDF_Logging Object
285 * @return void
286 */
287 function wwpdf_debug_log( string $message = '' ) {
288
289 if ( 'no' === get_option( 'wwpdf_debug_mode', 'no' ) ) {
290 return;
291 }
292
293 global $wwpdf_logs;
294 if ( function_exists( 'mb_convert_encoding' ) ) {
295 $message = mb_convert_encoding( $message, 'UTF-8' );
296 }
297 $wwpdf_logs->log_to_file( $message );
298
299 }
300
301 function pdfink_log_output() { ?>
302
303 <p>
304 <?php esc_html_e( 'Watermarking events and errors will be saved to a file in your /wp-content/ folder. You can view the contents below.', 'waterwoo-pdf' ); ?>
305 <br>
306 <?php esc_html_e( 'Maybe only turn this on for troubleshooting because this file can get large.', 'waterwoo-pdf' ); ?>
307 </p>
308 <?php $debug_on = get_option( 'wwpdf_debug_mode', 'no' );
309 if ( '1' !== $debug_on && 'yes' !== $debug_on ) {
310 return;
311 }
312 global $wwpdf_logs; ?>
313
314 <div class="wrap">
315 <h3><span><?php esc_html_e( 'Logs', 'waterwoo-pdf' ); ?></span></h3>
316 <label for="wwpdf-log-textarea"><?php esc_html_e( 'Use this tool to help debug TCPDI/TCPDF and PDF Ink functionality.', 'waterwoo-pdf' ); ?></label>
317 <textarea readonly="readonly" id="wwpdf-log-textarea" class="large-text" rows="16" name="wwpdf-debug-log-contents"><?php echo esc_textarea( $wwpdf_logs->get_file_contents() ); ?></textarea>
318 <input type="hidden" name="wwpdf_action" value="submit_debug_log">
319 <?php wp_nonce_field( 'wwpdf-logging-nonce', 'wwpdf_logging_nonce' ); ?>
320 <p class="submit">
321 <?php
322 submit_button( __( 'Download Debug Log File', 'waterwoo-pdf' ), 'primary', 'wwpdf-download-debug-log', false ); ?> &nbsp; <?php
323 submit_button( __( 'Clear Log', 'waterwoo-pdf' ), 'secondary', 'wwpdf-clear-debug-log', false ); ?> &nbsp; <?php
324 submit_button( __( 'Copy Entire Log', 'waterwoo-pdf' ), 'secondary', 'wwpdf-copy-debug-log', false, [ 'onclick' => "this.form['wwpdf-debug-log-contents'].focus();this.form['wwpdf-debug-log-contents'].select();document.execCommand('copy');return false;" ] );
325 ?>
326 </p>
327 <p>
328 <?php _e( 'Log file', 'waterwoo-pdf' ); ?>: <code><?php echo esc_html( $wwpdf_logs->get_log_file_path() ); ?></code>
329 </p>
330 </div>
331
332 <?php
333
334 }
335
336 /**
337 * Get "more info" section settings array
338 *
339 * @return void
340 */
341 function pdfink_more_info_screen() {
342 $svg_url = plugins_url('assets/svg/pdfink-lite-sprite.svg#pdf-download', __FILE__ ); ?>
343
344 <div style="margin:3em">
345 <p style="font-size: 2em;">
346 <?php _e( 'Hi, I\'m Caroline.', 'waterwoo-pdf' ); ?> 🖖🏼
347 </p>
348 <p style="font-size: 1.75em;">
349 <?php _e( 'I\'ve kept the PDF Ink Lite plugin in active development since 2014 as an unpaid volunteer.', 'waterwoo-pdf' ); ?>
350 <br>
351 <?php echo sprintf( __( 'If you enjoy the free version, <a href="%s" target="_blank" rel="noopener">upgrade to the full version of PDF Ink</a> for even more great features!', 'waterwoo-pdf' ), 'https://pdfink.com/?source=wordpress' ); ?>
352 </p>
353 <h2 style="font-size:3em;margin-bottom:0"><?php _e( 'Upgrade Features:', 'waterwoo-pdf' ); ?></h2>
354 <div style="display:flex;align-items:center;justify-content:space-between;padding:1.5em;gap:20px;">
355 <div>
356 <ul style="list-style:circle;margin-left:30px;margin-top:0;font-size: 1.33em;">
357 <li>Works with <strong>any</strong> PDF
358 <li>Full watermark page and position control
359 <li>More watermark positions, anywhere on the page, more than one
360 <li>Upload your own TTF <strong>fonts</strong>
361 <li>RTL
362 <li>Watermark <strong>opacity</strong> control
363 <li>Extended magic <strong>shortcodes</strong> for customized marks, including billing address
364 information, order number, product name, future dates, and copies purchased
365 <li>Full PDF <strong>password</strong> protection, encryption & permissions control
366 <li>Add <strong>barcodes</strong> and QR codes to PDFs
367 <li>Backend <strong>test watermarking</strong> of PDFs on-the-fly
368 <li><strong>Per-product</strong> and variable product watermarking settings
369 <li>Embed customized/encrypted PDF files on the page
370 <li>Unzip archives and mark chosen PDFs inside
371 <li>Automatic, scheduled file cleanup
372 <li>Support for <strong>externally hosted files (like Amazon S3)</strong>
373 <li>Compatible with FPDI PDF-Parser and SetaPDF-Stamper from SetaSign
374 <li>Compatibility with <strong>Free Downloads WooCommerce</strong>, <strong>WooCommerce Bulk
375 Downloads</strong>, and <strong>EDD Free Downloads</strong>
376 <li>PDF Ink works even without WordPress, allowing you to easily integrate
377 <strong>SetaPDF-Stamper</strong> or <strong>FPDI PDF-Parser</strong> and FPDF/TCPDF into any
378 PHP-based website!
379 <li><?php echo sprintf( __( 'Priority email support, <a href="%s" target="_blank" rel="noopener">and more!</a>', 'waterwoo-pdf' ), 'https://pdfink.com/#features' ) ?>
380 </ul>
381 </div>
382 <div>
383 <a href="https://pdfink.com/?source=wordpress" rel="noopener" target="_blank">
384 <svg width="300px" height="210px">
385 <use href="<?php echo esc_url( $svg_url ); ?>"/>
386 </svg>
387 </a>
388 </div>
389 </div>
390 <h2 style="font-size:3em;margin-bottom:0"><?php esc_html_e( 'Can\'t Upgrade? Support My Work Another Way!', 'waterwoo-pdf' ); ?></h2>
391
392 <p style="font-size: 1.5em;">
393 <?php echo sprintf( __( 'If PDF Ink is not in your budget, please take a moment to write <a href="%s" target="_blank" rel="noopener">an encouraging review</a>, or <a href="%s" target="_blank" rel="noopener noreferrer">donate a couple dollars using PayPal</a> or <a href="%s" target="_blank" rel="noopener noreferrer">Venmo</a> to cover my coffee today.', 'waterwoo-pdf' ), 'https://wordpress.org/support/plugin/waterwoo-pdf/reviews/',
394 'https://www.paypal.com/paypalme/canyonwebworks',
395 'https://www.venmo.com/canyonwebworks'); ?>
396 ☕️
397 😋️ <br><?php esc_html_e( 'Your kindness and enthusiasm makes donating my time to this open-source project worthwhile!', 'waterwoo-pdf' ); ?>
398 </p>
399 <h2 style="font-size:3em;margin-bottom:0"><?php esc_html_e( 'Need help?', 'waterwoo-pdf' ); ?></h2>
400 <p style="font-size: 2em;">
401 <?php echo sprintf( __( 'Please refer to the <a href="%s" target="_blank" rel="noopener">FAQ</a> and <a href="%s" target="_blank" rel="noopener nofollow">support forum</a> where your question might already be answered. <a href="%s" rel="noopener" target="_blank">Read this before posting</a>.', 'waterwoo-pdf' ), 'https://wordpress.org/plugins/waterwoo-pdf/#faq-header', 'https://wordpress.org/support/plugin/waterwoo-pdf/', 'https://wordpress.org/support/topic/before-you-post-2026-support-tips-please-read/' ); ?> <?php esc_html_e( 'I only provide email support for paying customers. Thank you!', 'waterwoo-pdf' ); ?>
402 ✌️
403 </p>
404 </div>
405
406 <?php }
407
408
409 /**
410 * Checks for compatibility and maybe fires up the plugin
411 *
412 * @return void
413 */
414 function wwpdf_plugins_loaded() {
415
416 // Check PHP version
417 if ( version_compare( PHP_VERSION, WWPDF_FREE_MIN_PHP, '<' ) ) {
418 add_action( 'admin_notices', 'wwpdf_old_php_notice' );
419 return;
420 }
421 // Check WordPress version
422 if ( version_compare( get_bloginfo( 'version' ), WWPDF_FREE_MIN_WP, '<' ) ) {
423 add_action( 'admin_notices', 'wwpdf_old_wp_notice' );
424 return;
425 }
426
427 /**
428 * Declare compatibility with HPOS
429 * @return void
430 */
431 add_action( 'before_woocommerce_init', function() {
432 if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
433 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
434 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'cart_checkout_blocks', __FILE__, true );
435 }
436 } );
437
438 WWPDF_Free();
439
440 }
441 add_action( 'plugins_loaded', 'wwpdf_plugins_loaded', 1 );
442
443 function wwpdf_init() {
444
445 load_plugin_textdomain( 'waterwoo-pdf', false, dirname( plugin_basename( __FILE__ ) ) . '/lang/' );
446
447 }
448 add_action( 'init', 'wwpdf_init', 1 );
449
450 function pdfink_fix_edd_nl_corruption() {
451
452 if ( get_option( 'eddimark_textarea_fixed', false ) ) {
453 return;
454 }
455
456 global $wpdb;
457 $raw_settings = $wpdb->get_var( "SELECT option_value FROM $wpdb->options WHERE option_name = 'edd_settings'" );
458
459 if ( ! $raw_settings || ! is_serialized( $raw_settings ) ) {
460 return;
461 }
462
463 // If unserialization fails, fix it
464 if ( @unserialize( $raw_settings ) === false ) {
465
466 $fixed_settings_string = preg_replace_callback(
467 '/s:(14|16):"(eddimark_files|eddimark_f_input)";s:(\d+):"(.*?)";/s',
468 function ( $matches ) {
469 $key_length = $matches[1];
470 $key_name = $matches[2];
471 $textarea_content = $matches[4];
472 $clean_content = str_replace( array( "\\r\\n", "\\r", "\r\n", "\r" ), "\n", $textarea_content );
473 $new_length = strlen( $clean_content );
474 return 's:' . $key_length . ':"' . $key_name . '";s:' . $new_length . ':"' . $clean_content . '";';
475 },
476 $raw_settings
477 );
478
479 $fixed_array = unserialize( $fixed_settings_string );
480
481 if ( is_array( $fixed_array ) ) {
482 update_option( 'edd_settings', $fixed_array );
483 wp_cache_set( 'edd_settings', $fixed_array, 'options' );
484 $GLOBALS['edd_options'] = $fixed_array;
485 update_option( 'eddimark_textarea_fixed', '1' );
486 }
487 }
488 }
489 add_action( 'plugins_loaded', 'pdfink_fix_edd_nl_corruption', -1 );
490