diff --git a/includes/class-style-package.php b/includes/class-style-package.php index 0464b20..8d829dc 100644 --- a/includes/class-style-package.php +++ b/includes/class-style-package.php @@ -151,7 +151,7 @@ private static function scan_entries( $zip ) { sprintf( /* translators: %s: offending entry name. */ __( 'Rejected unsafe archive entry: %s', 'exelearning' ), - $name + esc_html( $name ) ) ); } @@ -192,24 +192,23 @@ private static function scan_entries( $zip ) { */ private static function verify_entries( array $entries, $prefix ) { foreach ( $entries as $entry ) { - if ( '' === $prefix ) { - // Subdirectories at the root are allowed when config.xml is at the root. - if ( false !== strpos( $entry['name'], '/' ) ) { - continue; - } - } elseif ( 0 !== strpos( $entry['name'], $prefix ) ) { + if ( '' !== $prefix && 0 !== strpos( $entry['name'], $prefix ) ) { return new WP_Error( 'zip_mixed_roots', __( 'The archive must contain a single root folder or place all files at the root.', 'exelearning' ) ); } + // Directory entries carry no file type; every file below is still checked. + if ( '/' === substr( $entry['name'], -1 ) ) { + continue; + } if ( ! self::is_allowed_filename( $entry['name'] ) ) { return new WP_Error( 'zip_bad_extension', sprintf( /* translators: %s: offending filename. */ __( 'File type not allowed in style package: %s', 'exelearning' ), - $entry['name'] + esc_html( $entry['name'] ) ) ); } diff --git a/languages/exelearning-ca.po b/languages/exelearning-ca.po index 2e8e389..10b1c7b 100644 --- a/languages/exelearning-ca.po +++ b/languages/exelearning-ca.po @@ -635,46 +635,46 @@ msgstr "L'arxiu conté més d'un config.xml." msgid "The style package is missing config.xml." msgstr "Al paquet d'estil li falta config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "L'arxiu ha de contenir una única carpeta arrel o situar tots els fitxers a l'arrel." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipus de fitxer no permès al paquet d'estil: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "No s'ha pogut tornar a obrir l'arxiu ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "S'ha rebutjat una entrada d'arxiu insegura durant l'extracció." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "S'ha rebutjat un salt de ruta durant l'extracció." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "No s'ha pogut crear un directori de l'arxiu." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "No s'ha pogut llegir un fitxer de l'arxiu." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "No s'ha pogut escriure un fitxer extret." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml no és XML vàlid." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml ha de declarar un element ." diff --git a/languages/exelearning-ca_valencia.po b/languages/exelearning-ca_valencia.po index 66eb4fd..f883f03 100644 --- a/languages/exelearning-ca_valencia.po +++ b/languages/exelearning-ca_valencia.po @@ -635,46 +635,46 @@ msgstr "L'arxiu conté més d'un config.xml." msgid "The style package is missing config.xml." msgstr "Al paquet d'estil li falta config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "L'arxiu ha de contenir una única carpeta arrel o situar tots els fitxers a l'arrel." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipus de fitxer no permès al paquet d'estil: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "No s'ha pogut tornar a obrir l'arxiu ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "S'ha rebutjat una entrada d'arxiu insegura durant l'extracció." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "S'ha rebutjat un salt de ruta durant l'extracció." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "No s'ha pogut crear un directori de l'arxiu." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "No s'ha pogut llegir un fitxer de l'arxiu." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "No s'ha pogut escriure un fitxer extret." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml no és XML vàlid." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml ha de declarar un element ." diff --git a/languages/exelearning-de_DE.po b/languages/exelearning-de_DE.po index fe59264..6f58010 100644 --- a/languages/exelearning-de_DE.po +++ b/languages/exelearning-de_DE.po @@ -635,46 +635,46 @@ msgstr "Das Archiv enthält mehr als eine config.xml." msgid "The style package is missing config.xml." msgstr "Im Stilpaket fehlt die config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "Das Archiv muss einen einzigen Stammordner enthalten oder alle Dateien im Stammverzeichnis ablegen." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Dateityp im Stilpaket nicht zulässig: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "ZIP-Archiv konnte nicht erneut geöffnet werden." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Unsicherer Archiveintrag bei der Extraktion abgelehnt." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Pfad-Traversal bei der Extraktion abgelehnt." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Verzeichnis konnte nicht aus dem Archiv erstellt werden." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Datei konnte nicht aus dem Archiv gelesen werden." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Eine extrahierte Datei konnte nicht geschrieben werden." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml ist kein gültiges XML." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml muss ein -Element deklarieren." diff --git a/languages/exelearning-eo.po b/languages/exelearning-eo.po index c22e3ff..c4bfa32 100644 --- a/languages/exelearning-eo.po +++ b/languages/exelearning-eo.po @@ -635,46 +635,46 @@ msgstr "La arkivo enhavas pli ol unu config.xml." msgid "The style package is missing config.xml." msgstr "En la stilpakaĵo mankas config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "La arkivo devas enhavi ununuran radikan dosierujon aŭ meti ĉiujn dosierojn en la radikon." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Dosiertipo ne permesata en la stilpakaĵo: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Ne eblis remalfermi la ZIP-arkivon." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Malsekura arkiverero malakceptita dum la malpakado." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Vojtravado malakceptita dum la malpakado." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Ne eblis krei dosierujon el la arkivo." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Ne eblis legi dosieron el la arkivo." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Ne eblis skribi malpakitan dosieron." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml ne estas valida XML." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml devas deklari elementon ." diff --git a/languages/exelearning-es_ES.po b/languages/exelearning-es_ES.po index 1751dbe..421c60c 100644 --- a/languages/exelearning-es_ES.po +++ b/languages/exelearning-es_ES.po @@ -635,46 +635,46 @@ msgstr "El archivo contiene más de un config.xml." msgid "The style package is missing config.xml." msgstr "Al paquete de estilo le falta config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "El archivo debe contener una única carpeta raíz o tener todos los ficheros en la raíz." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipo de archivo no permitido en el paquete de estilo: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "No se pudo reabrir el archivo ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Se rechazó una entrada no segura del archivo durante la extracción." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Se rechazó un intento de escape de ruta durante la extracción." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "No se pudo crear un directorio del archivo." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "No se pudo leer un archivo del archivo comprimido." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "No se pudo escribir un archivo extraído." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml no es XML válido." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml debe declarar un elemento ." diff --git a/languages/exelearning-eu.po b/languages/exelearning-eu.po index 53b808d..e40fffb 100644 --- a/languages/exelearning-eu.po +++ b/languages/exelearning-eu.po @@ -635,46 +635,46 @@ msgstr "Artxiboak config.xml bat baino gehiago ditu." msgid "The style package is missing config.xml." msgstr "Estilo-paketeari config.xml falta zaio." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "Artxiboak erro-karpeta bakar bat izan behar du edo fitxategi guztiak erroan jarri." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Estilo-paketean onartzen ez den fitxategi mota: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Ezin izan da ZIP artxiboa berriro ireki." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Erauzketa garaian artxibo-sarrera ez segurua baztertu da." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Erauzketa garaian bide-zeharkatzea baztertu da." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Ezin izan da artxibotik direktorio bat sortu." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Ezin izan da artxibotik fitxategi bat irakurri." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Ezin izan da erauzitako fitxategi bat idatzi." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml ez da baliozko XML." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml-ek elementu bat deklaratu behar du." diff --git a/languages/exelearning-gl_ES.po b/languages/exelearning-gl_ES.po index b388104..f74a98e 100644 --- a/languages/exelearning-gl_ES.po +++ b/languages/exelearning-gl_ES.po @@ -635,46 +635,46 @@ msgstr "O arquivo contén máis dun config.xml." msgid "The style package is missing config.xml." msgstr "Ao paquete de estilo fáltalle config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "O arquivo debe conter unha única carpeta raíz ou situar todos os ficheiros na raíz." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipo de ficheiro non permitido no paquete de estilo: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Non se puido reabrir o arquivo ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Rexeitouse unha entrada de arquivo insegura durante a extracción." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Rexeitouse un salto de ruta durante a extracción." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Non se puido crear un directorio do arquivo." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Non se puido ler un ficheiro do arquivo." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Non se puido escribir un ficheiro extraído." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml non é XML válido." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml debe declarar un elemento ." diff --git a/languages/exelearning-it_IT.po b/languages/exelearning-it_IT.po index 9650c3f..87da2ef 100644 --- a/languages/exelearning-it_IT.po +++ b/languages/exelearning-it_IT.po @@ -635,46 +635,46 @@ msgstr "L'archivio contiene più di un config.xml." msgid "The style package is missing config.xml." msgstr "Nel pacchetto di stile manca config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "L'archivio deve contenere un'unica cartella radice o collocare tutti i file nella radice." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipo di file non consentito nel pacchetto di stile: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Impossibile riaprire l'archivio ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Voce di archivio non sicura rifiutata durante l'estrazione." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Attraversamento di percorso rifiutato durante l'estrazione." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Impossibile creare una directory dall'archivio." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Impossibile leggere un file dall'archivio." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Impossibile scrivere un file estratto." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml non è XML valido." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml deve dichiarare un elemento ." diff --git a/languages/exelearning-pt_PT.po b/languages/exelearning-pt_PT.po index 7ad27ab..013ceb5 100644 --- a/languages/exelearning-pt_PT.po +++ b/languages/exelearning-pt_PT.po @@ -635,46 +635,46 @@ msgstr "O arquivo contém mais do que um config.xml." msgid "The style package is missing config.xml." msgstr "Falta config.xml no pacote de estilo." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "O arquivo deve conter uma única pasta raiz ou colocar todos os ficheiros na raiz." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tipo de ficheiro não permitido no pacote de estilo: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Falha ao reabrir o arquivo ZIP." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Entrada de arquivo insegura recusada durante a extração." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Travessia de caminho recusada durante a extração." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Falha ao criar um diretório a partir do arquivo." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Falha ao ler um ficheiro do arquivo." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Falha ao escrever um ficheiro extraído." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml não é XML válido." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml deve declarar um elemento ." diff --git a/languages/exelearning-ro_RO.po b/languages/exelearning-ro_RO.po index 5f43771..4334107 100644 --- a/languages/exelearning-ro_RO.po +++ b/languages/exelearning-ro_RO.po @@ -636,46 +636,46 @@ msgstr "Arhiva conține mai mult de un config.xml." msgid "The style package is missing config.xml." msgstr "Pachetului de stil îi lipsește config.xml." -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "Arhiva trebuie să conțină un singur folder rădăcină sau să plaseze toate fișierele în rădăcină." #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "Tip de fișier nepermis în pachetul de stil: %s" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "Redeschiderea arhivei ZIP a eșuat." -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "Intrare de arhivă nesigură refuzată în timpul extragerii." -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "Traversare de cale refuzată în timpul extragerii." -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "Crearea unui director din arhivă a eșuat." -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "Citirea unui fișier din arhivă a eșuat." -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "Scrierea unui fișier extras a eșuat." -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "config.xml nu este XML valid." -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "config.xml trebuie să declare un element ." diff --git a/languages/exelearning.pot b/languages/exelearning.pot index 1a07742..8afe3ac 100644 --- a/languages/exelearning.pot +++ b/languages/exelearning.pot @@ -634,46 +634,46 @@ msgstr "" msgid "The style package is missing config.xml." msgstr "" -#: includes/class-style-package.php:203 +#: includes/class-style-package.php:198 msgid "The archive must contain a single root folder or place all files at the root." msgstr "" #. translators: %s: offending filename. -#: includes/class-style-package.php:211 +#: includes/class-style-package.php:210 #, php-format msgid "File type not allowed in style package: %s" msgstr "" -#: includes/class-style-package.php:232 +#: includes/class-style-package.php:231 msgid "Failed to reopen ZIP archive." msgstr "" -#: includes/class-style-package.php:243 +#: includes/class-style-package.php:242 msgid "Refused unsafe archive entry during extraction." msgstr "" -#: includes/class-style-package.php:290 +#: includes/class-style-package.php:289 msgid "Refused path traversal during extraction." msgstr "" -#: includes/class-style-package.php:297 -#: includes/class-style-package.php:301 +#: includes/class-style-package.php:296 +#: includes/class-style-package.php:300 msgid "Failed to create a directory from the archive." msgstr "" -#: includes/class-style-package.php:306 +#: includes/class-style-package.php:305 msgid "Failed to read a file from the archive." msgstr "" -#: includes/class-style-package.php:310 +#: includes/class-style-package.php:309 msgid "Failed to write an extracted file." msgstr "" -#: includes/class-style-package.php:396 +#: includes/class-style-package.php:395 msgid "config.xml is not valid XML." msgstr "" -#: includes/class-style-package.php:401 +#: includes/class-style-package.php:400 msgid "config.xml must declare a element." msgstr "" diff --git a/tests/unit/StylePackageTest.php b/tests/unit/StylePackageTest.php index 34d39f9..b8b3e3f 100644 --- a/tests/unit/StylePackageTest.php +++ b/tests/unit/StylePackageTest.php @@ -139,6 +139,104 @@ public function test_validate_bad_extension() { wp_delete_file( $zip_path ); } + /** + * A root-level config.xml must not exempt nested files from the extension + * allowlist: server-executable or server-config files are refused at any depth. + * + * @dataProvider nested_forbidden_entry_provider + * + * @param string $entry Nested entry name. + */ + public function test_validate_rejects_nested_forbidden_file_when_config_sits_at_the_root( $entry ) { + $zip_path = $this->make_zip( + array( + 'config.xml' => $this->sample_config_xml( 'acme' ), + 'style.css' => 'body{}', + $entry => 'payload', + ) + ); + $result = ExeLearning_Style_Package::validate( $zip_path, self::MAX ); + wp_delete_file( $zip_path ); + $this->assertInstanceOf( 'WP_Error', $result ); + $this->assertSame( 'zip_bad_extension', $result->get_error_code() ); + } + + public function nested_forbidden_entry_provider() { + return array( + 'php' => array( 'x/shell.php' ), + 'htaccess' => array( 'x/.htaccess' ), + 'user.ini' => array( 'x/.user.ini' ), + 'phtml' => array( 'deep/er/a.phtml' ), + 'no suffix' => array( 'fonts/LICENSE' ), + ); + } + + /** + * Directory entries carry no file type: archives made by tools that store + * them (most do) validate, with or without a root folder. + */ + public function test_validate_accepts_directory_entries() { + $rooted = $this->make_zip( + array( + 'config.xml' => $this->sample_config_xml( 'acme' ), + 'img/' => null, + 'img/logo.png' => 'binary', + ) + ); + $folder = $this->make_zip( + array( + 'acme/' => null, + 'acme/config.xml' => $this->sample_config_xml( 'acme' ), + 'acme/img/' => null, + 'acme/img/logo.png' => 'binary', + ) + ); + $rooted_result = ExeLearning_Style_Package::validate( $rooted, self::MAX ); + $folder_result = ExeLearning_Style_Package::validate( $folder, self::MAX ); + wp_delete_file( $rooted ); + wp_delete_file( $folder ); + $this->assertIsArray( $rooted_result ); + $this->assertIsArray( $folder_result ); + $this->assertSame( 'acme/', $folder_result['prefix'] ); + } + + /** + * A directory outside the package's root folder still breaks the single-root + * rule, even though directories carry no file type. + */ + public function test_validate_rejects_a_directory_outside_the_root_folder() { + $zip_path = $this->make_zip( + array( + 'acme/' => null, + 'acme/config.xml' => $this->sample_config_xml( 'acme' ), + 'acme/style.css' => 'body{}', + 'evil/' => null, + ) + ); + $result = ExeLearning_Style_Package::validate( $zip_path, self::MAX ); + wp_delete_file( $zip_path ); + $this->assertInstanceOf( 'WP_Error', $result ); + $this->assertSame( 'zip_mixed_roots', $result->get_error_code() ); + } + + /** + * Rejection messages quote the entry name escaped, since core prints + * settings errors without escaping. + */ + public function test_validate_escapes_entry_name_in_error_message() { + $zip_path = $this->make_zip( + array( + 'config.xml' => $this->sample_config_xml( 'acme' ), + '.x' => 'x', + ) + ); + $result = ExeLearning_Style_Package::validate( $zip_path, self::MAX ); + wp_delete_file( $zip_path ); + $this->assertInstanceOf( 'WP_Error', $result ); + $this->assertStringNotContainsString( 'get_error_message() ); + $this->assertStringContainsString( '<img', $result->get_error_message() ); + } + public function test_validate_accepts_root_package() { $zip_path = $this->make_zip( array( @@ -294,6 +392,8 @@ public function allowed_filename_provider() { 'css' => array( 'style.css', true ), 'svg nested' => array( 'icons/a.svg', true ), 'php' => array( 'evil.php', false ), + 'php upper' => array( 'x/SHELL.PHP', false ), + 'htaccess' => array( 'x/.htaccess', false ), 'no extension' => array( 'Makefile', false ), 'directory' => array( 'assets/', false ), 'empty' => array( '', false ), @@ -423,6 +523,10 @@ private function make_zip( array $entries ) { $zip = new ZipArchive(); $this->assertTrue( true === $zip->open( $path, ZipArchive::CREATE ) ); foreach ( $entries as $name => $contents ) { + if ( '/' === substr( $name, -1 ) ) { + $zip->addEmptyDir( rtrim( $name, '/' ) ); + continue; + } $zip->addFromString( $name, $contents ); } $zip->close(); diff --git a/tests/unit/StylesServiceTest.php b/tests/unit/StylesServiceTest.php index e34ebd8..5bd1185 100644 --- a/tests/unit/StylesServiceTest.php +++ b/tests/unit/StylesServiceTest.php @@ -509,7 +509,6 @@ public function test_build_theme_registry_override_publishes_icons_from_icons_fo 'icons/alert.svg' => '', 'icons/photo.JPG' => 'JPEG', 'icons/readme.txt' => 'ignore', - 'icons/no-extension' => 'ignore', ) ); $this->assertIsArray( ExeLearning_Styles_Service::install_from_zip( $zip_path ) );