diff --git a/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload.php b/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload.php
index ea5d8acb0e..b32845c127 100644
--- a/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload.php
+++ b/wordpress.org/public_html/wp-content/plugins/plugin-directory/shortcodes/class-upload.php
@@ -97,8 +97,19 @@ public static function display() {
wp_verify_nonce( $_POST['_wpnonce'], 'wporg-plugins-upload-' . $_POST['plugin_id'] )
)
) {
- $for_plugin = absint( $_POST['plugin_id'] ?? 0 );
- $upload_result = $uploader->process_upload( $for_plugin );
+ $for_plugin = absint( $_POST['plugin_id'] ?? 0 );
+
+ // Lock to prevent duplicate submissions from double-clicks or page reloads
+ $lock_key = 'plugin_upload_lock_' . get_current_user_id() . '_' . $for_plugin;
+ if ( false === wp_cache_add( $lock_key, time(), 'wporg-plugins', 5 * MINUTE_IN_SECONDS ) ) {
+ $upload_result = new \WP_Error(
+ 'upload_in_progress',
+ __( 'Your previous upload is still being processed. Please wait a moment before trying again.', 'wporg-plugins' )
+ );
+ } else {
+ $upload_result = $uploader->process_upload( $for_plugin );
+ wp_cache_delete( $lock_key, 'wporg-plugins' );
+ }
if ( is_wp_error( $upload_result ) ) {
$type = 'error';
diff --git a/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/functions.php b/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/functions.php
index e798728a31..b988f44eef 100644
--- a/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/functions.php
+++ b/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/functions.php
@@ -137,6 +137,16 @@ function scripts() {
// The plugin submission page: /developers/add/
if ( is_page( 'add' ) ) {
wp_enqueue_script( 'wporg-plugins-upload', get_stylesheet_directory_uri() . '/js/upload.js', array( 'wp-api', 'jquery' ), filemtime( __DIR__ . '/js/upload.js' ), true );
+
+ wp_localize_script(
+ 'wporg-plugins-upload',
+ 'pluginUpload',
+ array(
+ 'l10n' => array(
+ 'uploading' => __( 'Uploading…', 'wporg-plugins' ),
+ ),
+ )
+ );
}
// No Jetpack scripts needed.
diff --git a/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/js/upload.js b/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/js/upload.js
index 3212ec6a3f..cbd3028c3c 100644
--- a/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/js/upload.js
+++ b/wordpress.org/public_html/wp-content/themes/pub/wporg-plugins-2024/js/upload.js
@@ -49,4 +49,19 @@
$(this).hide().parents('ul').find('.plugin-upload-form.hidden').removeClass( 'hidden' );
} );
+ // Prevent duplicate submissions by disabling the submit button
+ $( 'form.plugin-upload-form' ).on( 'submit', function() {
+ var $button = $(this).find( 'input[type="submit"]' );
+
+ $button.prop( 'disabled', true );
+
+ if ( ! $button.data( 'defaultValue' ) ) {
+ $button.data( 'defaultValue', $button.val() );
+ }
+
+ if ( 'undefined' !== typeof pluginUpload && pluginUpload.l10n && pluginUpload.l10n.uploading ) {
+ $button.val( pluginUpload.l10n.uploading );
+ }
+ } );
+
})( jQuery );