Changeset 3368693
- Timestamp:
- 09/26/2025 08:08:08 PM (6 months ago)
- Location:
- safe-attachment-names/trunk
- Files:
-
- 2 added
- 6 edited
-
languages/safe-attachment-names-es_ES.mo (modified) (previous)
-
languages/safe-attachment-names-es_ES.po (modified) (4 diffs)
-
languages/safe-attachment-names-fr_FR.mo (modified) (previous)
-
languages/safe-attachment-names-fr_FR.po (modified) (3 diffs)
-
languages/safe-attachment-names-it_IT.mo (added)
-
languages/safe-attachment-names-it_IT.po (added)
-
readme.txt (modified) (1 diff)
-
safe-attachment-names.php (modified) (11 diffs)
Legend:
- Unmodified
- Added
- Removed
-
safe-attachment-names/trunk/languages/safe-attachment-names-es_ES.po
r1152900 r3368693 6 6 msgid "" 7 7 msgstr "" 8 "Project-Id-Version: Auto Domain Changer\n"8 "Project-Id-Version: Safe Attachment Names\n" 9 9 "Report-Msgid-Bugs-To: \n" 10 "POT-Creation-Date: 20 15-05-01 14:34-0500\n"11 "PO-Revision-Date: 20 15-05-01 14:35-0500\n"10 "POT-Creation-Date: 2025-09-26 16:01-0400\n" 11 "PO-Revision-Date: 2025-09-26 16:01-0400\n" 12 12 "Last-Translator: Tommy Lacroix <tlacroix@nuagelab.com>\n" 13 13 "Language-Team: NuageLab <wordpress-plugins@nuagelab.com>\n" … … 18 18 "Plural-Forms: nplurals=2; plural=(n>1);\n" 19 19 "X-Poedit-SourceCharset: UTF-8\n" 20 "X-Poedit-Bookmarks: -1,430,-1,-1,-1,-1,-1,-1,-1,-1\n" 21 "X-Generator: Poedit 1.7.4\n" 22 "X-Poedit-Basepath: ./\n" 20 "X-Generator: Poedit 3.1\n" 21 "X-Poedit-Basepath: .\n" 23 22 "X-Poedit-KeywordsList: __;_e;_n\n" 24 23 "X-Poedit-SearchPath-0: ..\n" 25 24 26 #: ../safe-attachment-name.php:101 25 #: ../safe-attachment-names.php:234 26 msgid "You do not have sufficient permissions to access this page." 27 msgstr "No tienes permisos suficientes para acceder a esta página." 28 29 #: ../safe-attachment-names.php:263 27 30 msgid "Sanitize Attachment Names" 28 31 msgstr "Limpiar nombres de adjuntos" 29 32 30 #: ../safe-attachment-name .php:11333 #: ../safe-attachment-names.php:276 31 34 msgid "" 32 35 "I have backed up my database and will assume the responsability of any data " … … 36 39 "responsabilidad por cualquier pérdida o corrupción de datos." 37 40 38 #: ../safe-attachment-name .php:11841 #: ../safe-attachment-names.php:281 39 42 msgid "Sanitize" 40 43 msgstr "Limpiar" 41 44 42 #: ../safe-attachment-name .php:180 ../safe-attachment-name.php:21245 #: ../safe-attachment-names.php:353 ../safe-attachment-names.php:388 43 46 msgid ": error, cannot find source file." 44 47 msgstr ": error, no puede encontrar el archivo de origen." 45 48 46 #: ../safe-attachment-name .php:184 ../safe-attachment-name.php:21649 #: ../safe-attachment-names.php:357 ../safe-attachment-names.php:392 47 50 msgid ": OK." 48 51 msgstr ": OK." 49 52 50 #: ../safe-attachment-name .php:24953 #: ../safe-attachment-names.php:452 51 54 msgid "Back" 52 55 msgstr "Volver" … … 1081 1084 #~ msgid "Show as link" 1082 1085 #~ msgstr "Lien court" 1083 1084 #, fuzzy1085 #~ msgid "You do not have sufficient permissions to access this page"1086 #~ msgstr ""1087 #~ "Vous n’avez pas les droits suffisants pour modérer les commentaires."1088 1086 1089 1087 #, fuzzy -
safe-attachment-names/trunk/languages/safe-attachment-names-fr_FR.po
r1152900 r3368693 6 6 msgid "" 7 7 msgstr "" 8 "Project-Id-Version: Auto Domain Changer\n"8 "Project-Id-Version: Safe Attachment Names\n" 9 9 "Report-Msgid-Bugs-To: \n" 10 "POT-Creation-Date: 20 15-05-01 14:28-0500\n"11 "PO-Revision-Date: 20 15-05-01 14:34-0500\n"10 "POT-Creation-Date: 2025-09-26 16:00-0400\n" 11 "PO-Revision-Date: 2025-09-26 16:01-0400\n" 12 12 "Last-Translator: Tommy Lacroix <tlacroix@nuagelab.com>\n" 13 13 "Language-Team: NuageLab <wordpress-plugins@nuagelab.com>\n" … … 18 18 "Plural-Forms: nplurals=2; plural=(n>1);\n" 19 19 "X-Poedit-SourceCharset: UTF-8\n" 20 "X-Poedit-Bookmarks: -1,430,-1,-1,-1,-1,-1,-1,-1,-1\n" 21 "X-Generator: Poedit 1.7.4\n" 22 "X-Poedit-Basepath: ./\n" 20 "X-Generator: Poedit 3.1\n" 21 "X-Poedit-Basepath: .\n" 23 22 "X-Poedit-KeywordsList: __;_e;_n\n" 24 23 "X-Poedit-SearchPath-0: ..\n" 25 24 26 #: ../safe-attachment-name .php:6927 msgid " Sanitize attachment names"28 msgstr " Assainir noms des pièces jointes"25 #: ../safe-attachment-names.php:234 26 msgid "You do not have sufficient permissions to access this page." 27 msgstr "" 29 28 30 #: ../safe-attachment-name .php:10129 #: ../safe-attachment-names.php:263 31 30 msgid "Sanitize Attachment Names" 32 31 msgstr "Assainir noms des pièces jointes" 33 32 34 #: ../safe-attachment-name .php:11333 #: ../safe-attachment-names.php:276 35 34 msgid "" 36 35 "I have backed up my database and will assume the responsability of any data " … … 40 39 "responsabilité en cas de perte ou de corruption de données." 41 40 42 #: ../safe-attachment-name .php:11841 #: ../safe-attachment-names.php:281 43 42 msgid "Sanitize" 44 43 msgstr "Assainir" 45 44 46 #: ../safe-attachment-name .php:179 ../safe-attachment-name.php:21045 #: ../safe-attachment-names.php:353 ../safe-attachment-names.php:388 47 46 msgid ": error, cannot find source file." 48 47 msgstr ": erreur, impossible de trouver la source" 49 48 50 #: ../safe-attachment-name .php:184 ../safe-attachment-name.php:22049 #: ../safe-attachment-names.php:357 ../safe-attachment-names.php:392 51 50 msgid ": OK." 52 51 msgstr ": OK." 53 52 54 #: ../safe-attachment-name .php:24553 #: ../safe-attachment-names.php:452 55 54 msgid "Back" 56 55 msgstr "Retour" 56 57 #~ msgid "Sanitize attachment names" 58 #~ msgstr "Assainir noms des pièces jointes" 57 59 58 60 #~ msgid "" -
safe-attachment-names/trunk/readme.txt
r3368671 r3368693 55 55 56 56 == Changelog == 57 = 1.1.0 = 58 * Reworked structure. 59 * Tested up to WordPress 6.8.2. More than 100+ stable active installs. 60 57 61 = 1.0.1 = 58 62 * Make filenames lowercase -
safe-attachment-names/trunk/safe-attachment-names.php
r3368671 r3368693 1 1 <?php 2 /*3 Plugin Name: Safe Attachment Names4 Plugin URI: http://www.nuagelab.com/wordpress-plugins/safe-attachment-names5 Description: Automatically detect and change the name of attachments containing special characters such as accented letters.6 Author: NuageLab <wordpress-plugins@nuagelab.com>7 Version: 1.0.18 License: GPLv2 or later9 Author URI: http://www.nuagelab.com/wordpress-plugins10 */11 12 // --13 14 2 /** 15 * Safe Attachment Name class 3 * Plugin Name: Safe Attachment Names 4 * Plugin URI: http://www.nuagelab.com/wordpress-plugins/safe-attachment-names 5 * Description: Automatically detect and change the name of attachments containing special characters such as accented letters. 6 * Version: 1.1.0 7 * Author: NuageLab <wordpress-plugins@nuagelab.com> 8 * Author URI: http://www.nuagelab.com/wordpress-plugins 9 * License: GPLv2 or later 10 * License URI: https://www.gnu.org/licenses/gpl-2.0.html 11 * Text Domain: safe-attachment-names 12 * Domain Path: /languages 13 * Requires at least: 5.0 14 * Tested up to: 6.8.2 15 * Requires PHP: 7.4 16 16 * 17 * @ author Tommy Lacroix <tlacroix@nuagelab.com>17 * @package SafeAttachmentNames 18 18 */ 19 class safe_attachment_names { 20 21 private static $_instance = null; 22 23 /** 24 * Bootstrap 19 20 // Prevent direct access 21 if (!defined('ABSPATH')) { 22 exit; 23 } 24 25 // Define plugin constants 26 define('SAFE_ATTACHMENT_NAMES_VERSION', '1.1.0'); 27 define('SAFE_ATTACHMENT_NAMES_PLUGIN_DIR', plugin_dir_path(__FILE__)); 28 define('SAFE_ATTACHMENT_NAMES_PLUGIN_URL', plugin_dir_url(__FILE__)); 29 30 /** 31 * Main Safe Attachment Names class 32 * 33 * @since 1.0.0 34 * @author Tommy Lacroix <tlacroix@nuagelab.com> 35 */ 36 class Safe_Attachment_Names { 37 38 /** 39 * Plugin instance 40 * 41 * @since 1.0.0 42 * @var Safe_Attachment_Names|null 43 */ 44 private static $instance = null; 45 46 /** 47 * Logger instance 48 * 49 * @since 1.1.0 50 * @var WP_Error|null 51 */ 52 private $logger = null; 53 54 55 /** 56 * Get plugin instance (singleton pattern) 57 * 58 * @since 1.0.0 59 * @return Safe_Attachment_Names 60 */ 61 public static function get_instance() { 62 if (null === self::$instance) { 63 self::$instance = new self(); 64 } 65 return self::$instance; 66 } 67 68 /** 69 * Initialize the plugin 70 * 71 * @since 1.0.0 72 * @return void 73 */ 74 public static function init() { 75 $instance = self::get_instance(); 76 $instance->setup(); 77 } 78 79 /** 80 * Private constructor to prevent direct instantiation 81 * 82 * @since 1.1.0 83 */ 84 private function __construct() { 85 $this->logger = new WP_Error(); 86 } 87 88 89 /** 90 * Setup plugin hooks and filters 91 * 92 * @since 1.0.0 93 * @return void 94 */ 95 private function setup() { 96 // Load text domain 97 add_action('plugins_loaded', array($this, 'load_textdomain')); 98 99 // Add admin menu 100 add_action('admin_menu', array($this, 'add_admin_menu')); 101 102 // Set upload prefilter 103 add_filter('wp_handle_upload_prefilter', array($this, 'upload_prefilter')); 104 105 // Add activation/deactivation hooks 106 register_activation_hook(__FILE__, array($this, 'activate')); 107 register_deactivation_hook(__FILE__, array($this, 'deactivate')); 108 } 109 110 /** 111 * Load plugin text domain for internationalization 112 * 113 * @since 1.1.0 114 * @return void 115 */ 116 public function load_textdomain() { 117 load_plugin_textdomain( 118 'safe-attachment-names', 119 false, 120 dirname(plugin_basename(__FILE__)) . '/languages/' 121 ); 122 } 123 124 /** 125 * Plugin activation hook 126 * 127 * @since 1.1.0 128 * @return void 129 */ 130 public function activate() { 131 // Set default options if needed 132 if (!get_option('safe_attachment_names_version')) { 133 add_option('safe_attachment_names_version', SAFE_ATTACHMENT_NAMES_VERSION); 134 } 135 136 $this->log_info('Plugin activated successfully'); 137 } 138 139 /** 140 * Plugin deactivation hook 141 * 142 * @since 1.1.0 143 * @return void 144 */ 145 public function deactivate() { 146 $this->log_info('Plugin deactivated'); 147 } 148 149 /** 150 * Log an informational message 151 * 152 * @since 1.1.0 153 * @param string $message The message to log 154 * @return void 155 */ 156 private function log_info($message) { 157 if (defined('WP_DEBUG') && WP_DEBUG) { 158 error_log(sprintf('[Safe Attachment Names] INFO: %s', $message)); 159 } 160 } 161 162 /** 163 * Log an error message 164 * 165 * @since 1.1.0 166 * @param string $message The error message 167 * @param string $context Additional context 168 * @return void 169 */ 170 private function log_error($message, $context = '') { 171 $log_message = sprintf('[Safe Attachment Names] ERROR: %s', $message); 172 if (!empty($context)) { 173 $log_message .= sprintf(' Context: %s', $context); 174 } 175 error_log($log_message); 176 177 // Store in WP_Error object for later retrieval 178 $this->logger->add('safe_attachment_error', $message, $context); 179 } 180 181 /** 182 * Log a warning message 183 * 184 * @since 1.1.0 185 * @param string $message The warning message 186 * @return void 187 */ 188 private function log_warning($message) { 189 if (defined('WP_DEBUG') && WP_DEBUG) { 190 error_log(sprintf('[Safe Attachment Names] WARNING: %s', $message)); 191 } 192 } 193 194 /** 195 * Get logged errors 196 * 197 * @since 1.1.0 198 * @return WP_Error 199 */ 200 public function get_errors() { 201 return $this->logger; 202 } 203 204 205 /** 206 * Add admin menu action; added by setup() 25 207 * 26 208 * @author Tommy Lacroix <tlacroix@nuagelab.com> 27 209 * @access public 28 210 */ 29 public static function boot() 30 { 31 if (self::$_instance === null) { 32 self::$_instance = new safe_attachment_names(); 33 self::$_instance->setup(); 34 return true; 35 } 36 return false; 37 } // boot() 38 39 40 /** 41 * Setup plugin 42 * 43 * @author Tommy Lacroix <tlacroix@nuagelab.com> 44 * @access public 45 */ 46 public function setup() 47 { 48 global $current_blog; 49 50 // Add admin menu 51 add_action('admin_menu', array(&$this, 'add_admin_menu')); 52 53 // Set wp_handle_upload_prefilter 54 add_filter('wp_handle_upload_prefilter', array($this, 'upload_prefilter')); 55 56 // Load text domain 57 load_plugin_textdomain('safe-attachment-name', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/'); 58 } // setup() 59 60 61 /** 62 * Add admin menu action; added by setup() 63 * 64 * @author Tommy Lacroix <tlacroix@nuagelab.com> 65 * @access public 66 */ 67 public function add_admin_menu() 68 { 211 public function add_admin_menu() { 69 212 // Check if user has proper capabilities 70 213 if (current_user_can('manage_options')) { 71 //add_management_page(__("Sanitize attachment names",'safe-attachment-name'), __("Sanitize attachment names",'safe-attachment-name'), 'manage_options', basename(__FILE__), array(&$this, 'admin_page')); 72 } 73 } // add_admin_menu() 74 75 76 /** 77 * Admin page action; added by add_admin_menu() 78 * 79 * @author Tommy Lacroix <tlacroix@nuagelab.com> 80 * @access public 81 */ 82 public function admin_page() 83 { 214 /*add_management_page( 215 __('Sanitize Attachment Names', 'safe-attachment-names'), 216 __('Sanitize Attachment Names', 'safe-attachment-names'), 217 'manage_options', 218 'safe-attachment-names', 219 array($this, 'admin_page') 220 );*/ 221 } 222 } 223 224 225 /** 226 * Render admin page 227 * 228 * @since 1.0.0 229 * @return void 230 */ 231 public function admin_page() { 84 232 // Security check: verify user capabilities 85 233 if (!current_user_can('manage_options')) { … … 113 261 114 262 echo '<div id="icon-tools" class="icon32"><br></div>'; 115 echo '<h2>'.__('Sanitize Attachment Names','safe-attachment-name ').'</h2>';263 echo '<h2>'.__('Sanitize Attachment Names','safe-attachment-names').'</h2>'; 116 264 echo '<form method="post">'; 117 265 … … 126 274 127 275 echo '<tr valign="top">'; 128 echo '<td colspan="2"><input type="checkbox" name="accept-terms" id="accept-terms" value="1" /> <label for="accept-terms"'.($error_terms?' style="color:red;font-weight:bold;"':'').'>'.__('I have backed up my database and will assume the respons ability of any data loss or corruption.','safe-attachment-name').'</label></td>';276 echo '<td colspan="2"><input type="checkbox" name="accept-terms" id="accept-terms" value="1" /> <label for="accept-terms"'.($error_terms?' style="color:red;font-weight:bold;"':'').'>'.__('I have backed up my database and will assume the responsibility of any data loss or corruption.','safe-attachment-names').'</label></td>'; 129 277 echo '</tr>'; 130 278 131 279 echo '</tbody></table>'; 132 280 133 echo '<p class="submit"><input type="submit" name="submit" id="submit" class="button-primary" value="'.esc_html(__('Sanitize','safe-attachment-name ')).'"></p>';281 echo '<p class="submit"><input type="submit" name="submit" id="submit" class="button-primary" value="'.esc_html(__('Sanitize','safe-attachment-names')).'"></p>'; 134 282 135 283 echo '</form>'; 136 284 137 285 echo '</div>'; 138 } // admin_page() 139 140 141 /** 142 * Change domain. This is where the magic happens. 286 } 287 288 289 /** 290 * Process attachment sanitization 291 * 292 * This method handles the bulk sanitization of existing attachments. 143 293 * Called by admin_page() upon form submission. 144 294 * 145 * @author Tommy Lacroix <tlacroix@nuagelab.com> 146 * @access private 147 */ 148 private function do_change() 149 { 295 * @since 1.0.0 296 * @return void 297 */ 298 private function do_change() { 150 299 global $wpdb; 151 300 152 @set_time_limit(0); 301 // Increase time limit for large operations 302 if (function_exists('set_time_limit')) { 303 set_time_limit(300); // 5 minutes 304 } 153 305 154 306 echo '<div class="wrap">'; … … 187 339 if ($fn1 != $fn2) { 188 340 $error = false; 189 $fn4 = $this->sanitize Filename($fn1);341 $fn4 = $this->sanitize_filename($fn1); 190 342 191 343 echo $fn1 . ' -> '.$fn4; 344 345 // Initialize WordPress filesystem API if needed 346 global $wp_filesystem; 347 if (empty($wp_filesystem)) { 348 require_once(ABSPATH . '/wp-admin/includes/file.php'); 349 WP_Filesystem(); 350 } 192 351 193 352 $fnx = false; 194 353 foreach ($fns as $x) { 195 if ( file_exists($upload_dir['basedir'].'/'.$x)) {354 if ($wp_filesystem->exists($upload_dir['basedir'].'/'.$x)) { 196 355 $fnx = $x; 197 356 break; … … 221 380 foreach ( $info['sizes'] as &$size ) { 222 381 $sf1 = dirname( $fn1 ) . '/' . $size['file']; 223 $sf4 = $this->sanitize Filename( $sf1 );382 $sf4 = $this->sanitize_filename( $sf1 ); 224 383 if ( $sf1 != $sf4 ) { 225 384 echo $sf1 . ' -> ' . $sf4; … … 228 387 $sfx = false; 229 388 foreach ( $fns as $x ) { 230 if ( file_exists( $upload_dir['basedir'] . '/' . $x ) ) {389 if ( $wp_filesystem->exists( $upload_dir['basedir'] . '/' . $x ) ) { 231 390 $sfx = $x; 232 391 break; … … 298 457 echo '</pre>'; 299 458 echo '<hr>'; 300 echo '<form method="post"><input type="submit" value="'.esc_html(__('Back','safe-attachment-name ')).'" />';301 } // do_change()459 echo '<form method="post"><input type="submit" value="'.esc_html(__('Back','safe-attachment-names')).'" />'; 460 } 302 461 303 462 … … 305 464 * Prefilter uploaded files to remove accents 306 465 * 466 * @since 1.0.0 307 467 * @param array $file The uploaded file array 308 468 * @return array Modified file array 309 469 */ 310 public function upload_prefilter($file) 311 { 470 public function upload_prefilter($file) { 312 471 // Validate file array structure 313 472 if (!is_array($file) || !isset($file['name'])) { 473 $this->log_warning('Invalid file array structure in upload_prefilter'); 314 474 return $file; 315 475 } 316 476 317 // Sanitize and process filename 318 $file['name'] = sanitize_file_name($this->sanitizeFilename($file['name'])); 477 try { 478 // Sanitize and process filename 479 $original_name = $file['name']; 480 $sanitized_name = $this->sanitize_filename($file['name']); 481 $file['name'] = sanitize_file_name($sanitized_name); 482 483 if ($original_name !== $file['name']) { 484 $this->log_info(sprintf('Filename sanitized: %s -> %s', $original_name, $file['name'])); 485 } 486 } catch (Exception $e) { 487 $this->log_error('Error sanitizing filename: ' . $e->getMessage(), $file['name']); 488 } 489 319 490 return $file; 320 } // upload_prefilter()491 } 321 492 322 493 … … 324 495 * Sanitize a file name 325 496 * 326 * @param string $fn1 File name 327 * @return string 328 */ 329 private function sanitizeFilename($fn1) { 497 * @since 1.0.0 498 * @param string $filename File name to sanitize 499 * @return string Sanitized filename 500 */ 501 private function sanitize_filename($filename) { 330 502 $upload_dir = wp_upload_dir(); 331 503 … … 337 509 } 338 510 339 $fn3 = strtolower($this->strip Accents($fn1));511 $fn3 = strtolower($this->strip_accents($filename)); 340 512 $parts = explode('/', $fn3); 341 513 foreach ($parts as &$part) { … … 357 529 358 530 /** 359 * Strip accents from string and replace by the unaccented letter 360 * 361 * @param $stripAccents 362 * @return string 363 */ 364 private function stripAccents($stripAccents){ 365 return utf8_encode(strtr(utf8_decode($stripAccents),utf8_decode('àáâãäçèéêëìíîïñòóôõöùúûüýÿÀÁÂÃÄÇÈÉÊËÌÍÎÏÑÒÓÔÕÖÙÚÛÜÝ'),'aaaaaceeeeiiiinooooouuuuyyAAAAACEEEEIIIINOOOOOUUUUY')); 366 } // stripAccents() 367 368 } // safe_attachment_names class 369 370 371 // Initialize 372 safe_attachment_names::boot(); 531 * Strip accents from string and replace with unaccented letters 532 * 533 * @since 1.0.0 534 * @param string $text Text to strip accents from 535 * @return string Text without accents 536 */ 537 private function strip_accents($text) { 538 // Use WordPress built-in function if available 539 if (function_exists('remove_accents')) { 540 return remove_accents($text); 541 } 542 543 // Fallback method 544 $accents = 'àáâãäåąćčđèéêëìíîïłñòóôõöøśšťùúûüýÿźžÀÁÂÃÄÅĄĆČĐÈÉÊËÌÍÎÏŁÑÒÓÔÕÖØŚŠŤÙÚÛÜÝŸŹŽ'; 545 $no_accents = 'aaaaaaalccdeeeeiiilnoooooosstuyyzAAAAAAACCDEEEEIIILNOOOOOOSSRUUUUYYZZ'; 546 547 return strtr($text, $accents, $no_accents); 548 } 549 550 } 551 552 /** 553 * Initialize the plugin 554 * 555 * @since 1.0.0 556 */ 557 function safe_attachment_names_init() { 558 Safe_Attachment_Names::init(); 559 } 560 561 // Hook into WordPress 562 add_action('init', 'safe_attachment_names_init'); 563 564 /** 565 * Get plugin instance 566 * 567 * @since 1.1.0 568 * @return Safe_Attachment_Names 569 */ 570 function safe_attachment_names() { 571 return Safe_Attachment_Names::get_instance(); 572 }
Note: See TracChangeset
for help on using the changeset viewer.