diff --git a/chinese/wordpress-zh_CN/distinfo b/chinese/wordpress-zh_CN/distinfo
index 38d453b60e58..f5b8fa911482 100644
--- a/chinese/wordpress-zh_CN/distinfo
+++ b/chinese/wordpress-zh_CN/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1786171653
-SHA256 (wordpress-7.0.3-zh_CN.tar.gz) = e3795f01d24c5a24de15544691bd8bfed3eb550ee7d43ff49bf0582307f0c754
-SIZE (wordpress-7.0.3-zh_CN.tar.gz) = 36877403
+TIMESTAMP = 1787365112
+SHA256 (wordpress-7.1-zh_CN.tar.gz) = c144164530ea5e32e47668e3fa97c69165214652d52b72d53d507b3e18563d9c
+SIZE (wordpress-7.1-zh_CN.tar.gz) = 42783603
diff --git a/chinese/wordpress-zh_TW/Makefile b/chinese/wordpress-zh_TW/Makefile
index 7969fe8e6bdf..aa33ab31aa6a 100644
--- a/chinese/wordpress-zh_TW/Makefile
+++ b/chinese/wordpress-zh_TW/Makefile
@@ -1,11 +1,12 @@
+IGNORE= localized distfile not yet available upstream
CATEGORIES= chinese
-MASTER_SITES= https://cn.wordpress.org/
+MASTER_SITES= https://tw.wordpress.org/
MASTERDIR= ${.CURDIR}/../../www/wordpress
WWWDIR= ${PREFIX}/www/${PORTNAME}${PKGNAMESUFFIX}
DISTINFO_FILE= ${.CURDIR}/distinfo
WORDPRESS_LANG= zh_TW
.include "${MASTERDIR}/Makefile"
diff --git a/french/wordpress/distinfo b/french/wordpress/distinfo
index 1232aef2b3e7..71867091a04b 100644
--- a/french/wordpress/distinfo
+++ b/french/wordpress/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1786171739
-SHA256 (wordpress-7.0.3-fr_FR.tar.gz) = 4a7e3621de00bbc9d6b886526e17f5eae1d83c11f4036367ed81c5bf34d5959a
-SIZE (wordpress-7.0.3-fr_FR.tar.gz) = 36903343
+TIMESTAMP = 1787367948
+SHA256 (wordpress-7.1-fr_FR.tar.gz) = 747581bc066109a6080e9d519e5435f0478403a223d0106ef88764b4591d8009
+SIZE (wordpress-7.1-fr_FR.tar.gz) = 42808472
diff --git a/german/wordpress/distinfo b/german/wordpress/distinfo
index a401756f6007..3f22c5fb279d 100644
--- a/german/wordpress/distinfo
+++ b/german/wordpress/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1786171742
-SHA256 (wordpress-7.0.3-de_DE.tar.gz) = 0b83c9d30f9ea73ab5afa450c50f4e354fd39b1b6775c9664f75b24b71415bbd
-SIZE (wordpress-7.0.3-de_DE.tar.gz) = 36914813
+TIMESTAMP = 1787367953
+SHA256 (wordpress-7.1-de_DE.tar.gz) = 37ae10dce083cd46ec5f150a3def49472e32dfc7fa126192fcf6ea1a1691a690
+SIZE (wordpress-7.1-de_DE.tar.gz) = 42819668
diff --git a/japanese/wordpress/distinfo b/japanese/wordpress/distinfo
index 981b247da2d5..d74abcad8703 100644
--- a/japanese/wordpress/distinfo
+++ b/japanese/wordpress/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1786171744
-SHA256 (wordpress-7.0.3-ja.tar.gz) = e167023f8c31dedca20667c8988062912fdd45144dfe85ca5ccc3b4aeed7366b
-SIZE (wordpress-7.0.3-ja.tar.gz) = 36915323
+TIMESTAMP = 1787367957
+SHA256 (wordpress-7.1-ja.tar.gz) = d876264f0b3591fc19a94edc344bdd5e72c0d2472a89742fd24421b96c741a47
+SIZE (wordpress-7.1-ja.tar.gz) = 42832286
diff --git a/russian/wordpress/distinfo b/russian/wordpress/distinfo
index 163eb1927af9..f33713ca1346 100644
--- a/russian/wordpress/distinfo
+++ b/russian/wordpress/distinfo
@@ -1,3 +1,3 @@
-TIMESTAMP = 1786171747
-SHA256 (wordpress-7.0.3-ru_RU.tar.gz) = c63de80fcf2513263a806bf4710e28445c1362fcb1a47b9a9187a0baf582a7b5
-SIZE (wordpress-7.0.3-ru_RU.tar.gz) = 37064815
+TIMESTAMP = 1787367961
+SHA256 (wordpress-7.1-ru_RU.tar.gz) = f43adbde25b9d3ae12a15a6a24584b9c853166c3de6336de82537685a8cfee0f
+SIZE (wordpress-7.1-ru_RU.tar.gz) = 42989231
diff --git a/www/wordpress/Makefile b/www/wordpress/Makefile
index fff85df1f8f1..f25a21e09ef2 100644
--- a/www/wordpress/Makefile
+++ b/www/wordpress/Makefile
@@ -1,73 +1,75 @@
PORTNAME= wordpress
-PORTVERSION= 7.0.4
+DISTVERSION= 7.1
+.ifdef WORDPRESS_LANG
+DISTVERSIONSUFFIX= -${WORDPRESS_LANG}
+.endif
PORTREVISION?= 0
.ifndef WORDPRESS_LANG
PORTEPOCH= 1
.endif
CATEGORIES+= www
.ifndef WORDPRESS_LANG
MASTER_SITES= https://wordpress.org/
.else
MASTER_SITES?= https://${WORDPRESS_LANG}.wordpress.org/
.endif
.ifdef WORDPRESS_LANG
PKGNAMESUFFIX= -${WORDPRESS_LANG}
.endif
-DISTNAME= wordpress-7.0.3${PKGNAMESUFFIX}
MAINTAINER= delphij@FreeBSD.org
COMMENT= State-of-the-art semantic personal publishing platform
WWW= ${MASTER_SITES}
LICENSE= GPLv2+
LICENSE_FILE= ${WRKSRC}/license.txt
RUN_DEPENDS= ${PECL_PKGNAMEPREFIX}imagick>=2.2.2:graphics/pecl-imagick@${PHP_FLAVOR}
USES= cpe php:web
-.if ${PORTVERSION:N*.*.*}
-CPE_VERSION= ${PORTVERSION}.0
+.if ${DISTVERSION:N*.*.*}
+CPE_VERSION= ${DISTVERSION}.0
.endif
.ifdef WORDPRESS_LANG
CPE_LANG= ${WORDPRESS_LANG}
.endif
USE_PHP= curl exif fileinfo filter ftp gd mysqli tokenizer xml zip zlib
IGNORE_WITH_PHP= 86
CONFLICTS_INSTALL= ??-wordpress
NO_ARCH= yes
NO_BUILD= yes
SUB_FILES= pkg-message
WRKSRC= ${WRKDIR}/${PORTNAME}
PLIST= ${WRKDIR}/pkg-plist
PORTDOCS= readme.html
OPTIONS_DEFINE= DOCS
.include
-+ Version %s addressed some security issues.' ), - '7.0.3' - ); - ?> ---- wp-includes/class-wp-image-editor-imagick.php.orig 2025-08-26 14:05:30.223429000 -0700 -+++ wp-includes/class-wp-image-editor-imagick.php 2026-08-12 05:21:59.983819000 -0700 -@@ -21,6 +21,28 @@ - */ - protected $image; - -+ /** -+ * Temporarily stores stream image data while processing internally. -+ * -+ * @see self::pdf_load_source() -+ * -+ * @since 7.0.4 -+ * -+ * @var string|null -+ */ -+ private $stream_file_data = null; -+ -+ /** -+ * Temporarily stores the parsed given name for an image while processing internally. -+ * -+ * @see self::pdf_load_source() -+ * -+ * @since 7.0.4 -+ * -+ * @var string|null -+ */ -+ private $image_given_name = null; -+ - public function __destruct() { - if ( $this->image instanceof Imagick ) { - // We don't need the original in memory anymore. -@@ -130,30 +152,208 @@ - return true; - } - -- if ( ! is_file( $this->file ) && ! wp_is_stream( $this->file ) ) { -+ $is_stream = wp_is_stream( $this->file ); -+ $is_file = ! $is_stream && is_file( $this->file ); -+ -+ // Only allow loading files or streams. -+ if ( ! $is_file && ! $is_stream ) { - return new WP_Error( 'error_loading_image', __( 'File does not exist?' ), $this->file ); - } - -+ // Establish the provided filename based on the kind of resource being loaded. -+ $given_filename = $this->file; -+ if ( 0 === strncasecmp( $given_filename, 'file://', 7 ) ) { -+ $given_filename = basename( substr( $given_filename, 7 ) ); // 7 is the strlen of 'file://'. -+ } elseif ( 1 === preg_match( '~^https?://~i', $this->file ) ) { -+ /* -+ * For URLs, it will be the final path segment. -+ * -+ * Example: -+ * -+ * https://wordpress.org/i/happy.png?size=40px -+ * ╰───────╯ -+ * this is the given filename -+ * -+ * If the stream returns a `Content-Disposition` header it would -+ * provide an alternative name, but this is used as a reasonable -+ * proxy to avoid adding the additional complexity of reading and -+ * parsing the returned HTTP headers. -+ */ -+ $url_path = wp_parse_url( $this->file, PHP_URL_PATH ); -+ -+ // This URL can not be parsed, so it is not a valid image resource. -+ if ( false === $url_path ) { -+ return new WP_Error( 'error_loading_image', __( 'File is not an image.' ), $this->file ); -+ } -+ -+ /** -+ * The URL has an empty path, so continue with an empty string. -+ * -+ * This is the case with a URL such as `https://example.com?file_id=123` -+ */ -+ if ( null === $url_path ) { -+ $url_path = ''; -+ } -+ -+ $last_path_at = strrpos( $url_path, '/' ); -+ $given_filename = is_int( $last_path_at ) ? substr( $url_path, $last_path_at + 1 ) : $url_path; -+ $given_filename = rawurldecode( $given_filename ); -+ } -+ - /* -+ * Strip off any potential `Imagick` format specifiers. -+ * -+ * If a real file exists with the identified format specifier, then -+ * `Imagick` may not treat it as a format, but WordPress will reject -+ * it anyway to avoid adding more complexity into this detection. -+ * -+ * `Imagick` reads only the first `FORMAT:` specifier on a name, but -+ * stripping a segment would promote a second specifier to the front -+ * of the name handed to `Imagick`, which would then honor it. -+ * -+ * Loop to capture all format specifiers for comparison. -+ * -+ * Exclude Windows drive-letter prefixes from here. -+ */ -+ $imagick_formats = array(); -+ while ( -+ false !== ( $format_ends_at = strpos( $given_filename, ':' ) ) && -+ 1 !== preg_match( '~^[a-z]:~i', $given_filename ) -+ ) { -+ $imagick_formats[] = strtoupper( substr( $given_filename, 0, $format_ends_at ) ); -+ $given_filename = substr( $given_filename, $format_ends_at + 1 ); -+ } -+ -+ $file_extension = strtolower( pathinfo( $given_filename, PATHINFO_EXTENSION ) ); -+ -+ /* - * Even though Imagick uses less PHP memory than GD, set higher limit - * for users that have low PHP.ini limits. - */ - wp_raise_memory_limit( 'image' ); - -+ /** -+ * Read the resource header for MIME sniffing. -+ * -+ * For files, which will be passed into Imagick by their file names, avoid -+ * eagerly loading the entire contents into PHP memory. For streams, however, -+ * it’s more important to avoid validating a separate copy of the file data -+ * than is later fetched by Imagick, so go ahead and load the entire payload, -+ * then pass it to Imagick as the data blob itself. -+ * -+ * @link https://mimesniff.spec.whatwg.org/#reading-the-resource-header -+ */ - try { -- $this->image = new Imagick(); -- $file_extension = strtolower( pathinfo( $this->file, PATHINFO_EXTENSION ) ); -+ if ( $is_file ) { -+ $file_data = file_get_contents( $this->file, false, null, 0, 1445 ); -+ } else { -+ $file_data = file_get_contents( $this->file ); -+ } -+ } catch ( Exception $e ) { -+ $file_data = false; -+ } -+ if ( false === $file_data ) { -+ return new WP_Error( 'error_loading_image', __( 'File does not exist?' ), $this->file ); -+ } - -- if ( 'pdf' === $file_extension ) { -- $pdf_loaded = $this->pdf_load_source(); -+ $pdf_extensions = array( -+ 'ai', -+ 'epdf', -+ 'pdf', -+ 'pdfa', -+ 'pocketmod', -+ ); - -+ // Reject files claiming to be PDFs which lack the required signature. -+ $has_pdf_extension = in_array( $file_extension, $pdf_extensions, true ); -+ $has_pdf_signature = str_starts_with( $file_data, '%PDF-' ); -+ if ( $has_pdf_extension && ! $has_pdf_signature ) { -+ return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); -+ } -+ -+ $ps_formats = array( -+ 'DPS', -+ 'EPI', -+ 'EPS', -+ 'EPSF', -+ 'EPSI', -+ 'PS', -+ 'WPG', -+ ); -+ -+ $ps_extensions = array( -+ 'dps', -+ 'epi', -+ 'eps', -+ 'eps2', -+ 'eps3', -+ 'epsf', -+ 'epsi', -+ 'ept', -+ 'ept2', -+ 'ept3', -+ 'ps', -+ 'ps2', -+ 'ps3', -+ 'wpg', -+ ); -+ -+ // Reject files which Imagick will parse as PostScript. -+ if ( -+ array() !== array_intersect( $imagick_formats, $ps_formats ) || -+ in_array( $file_extension, $ps_extensions, true ) || -+ str_starts_with( $file_data, '%!' ) || -+ str_starts_with( $file_data, "\x04%!" ) || -+ str_starts_with( $file_data, "\xC5\xD0\xD3\xC6" ) || -+ str_starts_with( $file_data, "\xFFWPC" ) -+ ) { -+ return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); -+ } -+ -+ $compressed_extensions = array( -+ 'gz', -+ 'bz2', -+ 'svgz', -+ 'z', -+ 'wmz', -+ ); -+ -+ /* -+ * Reject compressed archives that Imagick will transparently decompress. -+ * Unfortunately this rejects `.svgz` because there’s no intermediate step -+ * in the loading process. `Imagick` would decompress the file, then look -+ * to see what kind of content was decompressed instead of asserting SVG. -+ */ -+ if ( -+ in_array( $file_extension, $compressed_extensions, true ) || -+ str_starts_with( $file_data, "\x1F\x8B\x08" ) || // gzip -+ str_starts_with( $file_data, 'BZh' ) || // bzip2 -+ str_starts_with( $file_data, "\x1F\x9D" ) // compress -+ ) { -+ return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); -+ } -+ -+ try { -+ $this->image = new Imagick(); -+ -+ if ( $has_pdf_signature ) { -+ /* -+ * Load these values for use in the helper method without forcing a change -+ * of its expected arguments, but then free them after calling to prevent -+ * keeping them around in memory and bloating the app. -+ */ -+ $this->stream_file_data = $is_stream ? $file_data : null; -+ $this->image_given_name = $given_filename; -+ $pdf_loaded = $this->pdf_load_source(); -+ $this->stream_file_data = null; -+ $this->image_given_name = null; -+ - if ( is_wp_error( $pdf_loaded ) ) { - return $pdf_loaded; - } - } else { -- if ( wp_is_stream( $this->file ) ) { -- // Due to reports of issues with streams with `Imagick::readImageFile()`, uses `Imagick::readImageBlob()` instead. -- $this->image->readImageBlob( file_get_contents( $this->file ), $this->file ); -+ if ( $is_stream ) { -+ $this->image->readImageBlob( $file_data, $given_filename ); - } else { - $this->image->readImage( $this->file ); - } -@@ -168,7 +368,7 @@ - $this->image->setIteratorIndex( 0 ); - } - -- if ( 'pdf' === $file_extension ) { -+ if ( $has_pdf_signature ) { - $this->remove_pdf_alpha_channel(); - } - -@@ -1158,25 +1358,35 @@ - return $filename; - } - -- try { -- /* -- * When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped -- * area (resulting in unnecessary whitespace) unless the following option is set. -- */ -- $this->image->setOption( 'pdf:use-cropbox', true ); -+ foreach ( array( 'true', 'false' ) as $use_cropbox ) { -+ try { -+ /** -+ * When generating thumbnails from cropped PDF pages, Imagemagick uses the uncropped -+ * area (resulting in unnecessary whitespace) unless the following option is set. -+ * -+ * However, it sometimes fails, so if that happens, run it without the option. -+ * -+ * @ticket 48853 -+ */ -+ $this->image->setOption( 'pdf:use-cropbox', $use_cropbox ); - -- /* -- * Reading image after Imagick instantiation because `setResolution` -- * only applies correctly before the image is read. -- */ -- $this->image->readImage( $filename ); -- } catch ( Exception $e ) { -- // Attempt to run `gs` without the `use-cropbox` option. See #48853. -- $this->image->setOption( 'pdf:use-cropbox', false ); -+ /* -+ * Reading image after Imagick instantiation because `setResolution` -+ * only applies correctly before the image is read. -+ */ -+ if ( is_string( $this->stream_file_data ) ) { -+ $this->image->setFilename( 'PDF:unknown.pdf[0]' ); -+ $this->image->readImageBlob( $this->stream_file_data, $this->image_given_name ); -+ } else { -+ $this->image->readImage( $filename ); -+ } - -- $this->image->readImage( $filename ); -+ return true; -+ } catch ( Exception $e ) { -+ continue; -+ } - } - -- return true; -+ return new WP_Error( 'invalid_image', __( 'File is not an image.' ), $this->file ); - } - } ---- wp-includes/version.php.orig 2026-08-06 11:04:54.000000000 -0700 -+++ wp-includes/version.php 2026-08-12 06:12:50.000000000 -0700 -@@ -16,7 +16,7 @@ - * - * @global string $wp_version - */ --$wp_version = '7.0.3'; -+$wp_version = '7.0.4'; - - /** - * Holds the WordPress DB revision, increments when changes are made to the WordPress DB schema.