Plugin Directory

Changeset 3658562


Ignore:
Timestamp:
08/21/2026 08:33:53 AM (2 months ago)
Author:
davegerrits389
Message:

Release version 1.0.3 - improved download reliability, binary-safe database migration and error diagnostics

Location:
dave-gerrits-site-migrator/trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • dave-gerrits-site-migrator/trunk/admin/class-wmig-admin.php

    r3638793 r3658562  
    226226
    227227        $config = array(
    228             'ajaxUrl' => admin_url( 'admin-ajax.php' ),
    229             'nonce'   => $this->nonce(),
     228            'ajaxUrl'          => admin_url( 'admin-ajax.php' ),
     229            'nonce'            => $this->nonce(),
     230            'invalidResponse'  => $this->tr(
     231                'De server gaf geen geldig antwoord terug.',
     232                'The server returned an invalid response.'
     233            ),
    230234        );
    231235        if ( 'import' === $script ) {
    … …  
    565569            'size' => (int) filesize( $path ),
    566570            'chunk_size' => 16 * 1024 * 1024,
    567             'fallback_url' => wp_nonce_url( admin_url( 'admin-post.php?action=wmig_download&token=' . rawurlencode( $token ) ), 'wmig_download_' . $token, '_wmig_download_nonce' ),
     571            'fallback_url' => add_query_arg(
     572                array(
     573                    'action'                 => 'wmig_download',
     574                    'token'                  => $token,
     575                    '_wmig_download_nonce'   => wp_create_nonce( 'wmig_download_' . $token ),
     576                ),
     577                admin_url( 'admin-post.php' )
     578            ),
    568579        ) );
    569580    }
  • dave-gerrits-site-migrator/trunk/assets/export.js

    r3637551 r3658562  
    55(() => {
    66    const ajaxUrl = window.WMIG_ADMIN.ajaxUrl, nonce = window.WMIG_ADMIN.nonce;
     7    const invalidResponse = window.WMIG_ADMIN.invalidResponse || "De server gaf geen geldig antwoord terug.";
    78    const $ = id => document.getElementById(id);
    89    const start = $("wmig-export-start"), discard = $("wmig-export-discard"), stop = $("wmig-export-stop"), progress = $("wmig-export-progress"), bar = $("wmig-export-bar"), pct = $("wmig-export-percent"), status = $("wmig-export-status"), sub = $("wmig-export-sub"), error = $("wmig-export-error"), success = $("wmig-export-success"), meta = $("wmig-export-meta"), download = $("wmig-download"), delpkg = $("wmig-delete-package"), dstatus = $("wmig-download-status"), message = $("wmig-export-message");
    … …  
    2324        }
    2425        catch (e) {
    25             throw new Error("De server gaf geen geldig antwoord terug.");
     26            const preview = text
     27                ? text.replace(/<[^>]*>/g, " ").replace(/\s+/g, " ").trim().slice(0, 180)
     28                : "";
     29            throw new Error(
     30                invalidResponse +
     31                " HTTP " + r.status +
     32                (preview ? ": " + preview : "")
     33            );
    2634        }
    2735        return j;
  • dave-gerrits-site-migrator/trunk/dave-gerrits-site-migrator.php

    r3650920 r3658562  
    33 * Plugin Name: Dave Gerrits Site Migrator
    44 * Description: Export a complete WordPress website to one migration package and import it into a clean WordPress installation.
    5  * Version: 1.0.2
     5 * Version: 1.0.3
    66 * Author: Dave Gerrits
    77 * Author URI: https://davegerrits.nl/
    88 * Requires at least: 6.0
    9  * Tested up to: 7.0
     9 * Tested up to: 7.1
    1010 * Requires PHP: 7.4
    1111 * License: GPLv2 or later
    … …  
    1818}
    1919
    20 define( 'WMIG_VERSION', '1.0.2' );
     20define( 'WMIG_VERSION', '1.0.3' );
    2121define( 'WMIG_FILE', __FILE__ );
    2222define( 'WMIG_DIR', plugin_dir_path( __FILE__ ) );
  • dave-gerrits-site-migrator/trunk/includes/class-wmig-exporter.php

    r3650920 r3658562  
    338338    }
    339339
     340    /**
     341     * Preserve arbitrary database bytes without forcing them through UTF-8 JSON.
     342     *
     343     * WordPress tables are usually textual, but plugins may use BINARY/VARBINARY
     344     * columns (including primary keys). Invalid UTF-8 bytes must round-trip
     345     * exactly; replacing them would corrupt keys and can create duplicates.
     346     *
     347     * @param mixed $value Database value.
     348     * @return mixed Portable JSON-safe value.
     349     */
     350    private function encode_database_value( $value ) {
     351        if ( ! is_string( $value ) ) {
     352            return $value;
     353        }
     354
     355        if ( 1 === preg_match( '//u', $value ) ) {
     356            return $value;
     357        }
     358
     359        return array(
     360            '__wmig_binary_b64_v1' => base64_encode( $value ),
     361        );
     362    }
     363
    340364    private function process_database( $state ) {
    341365        global $wpdb;
    … …  
    399423                $sql = "SELECT * FROM `" . esc_sql( $table ) . "` ORDER BY {$pk_sql} ASC LIMIT {$batch}";
    400424            } else {
     425                $cursor_value = $state['table_cursor'];
     426                if (
     427                    is_array( $cursor_value ) &&
     428                    isset( $cursor_value['__wmig_binary_b64_v1'] ) &&
     429                    is_string( $cursor_value['__wmig_binary_b64_v1'] )
     430                ) {
     431                    $decoded_cursor = base64_decode( $cursor_value['__wmig_binary_b64_v1'], true );
     432                    if ( false === $decoded_cursor ) {
     433                        fclose( $handle );
     434                        return $this->fail( $state, 'Binaire databasecursor kon niet veilig worden hervat voor ' . $table . '.', false );
     435                    }
     436                    $cursor_value = $decoded_cursor;
     437                }
     438
    401439                $sql = $wpdb->prepare(
    402440                    "SELECT * FROM `" . esc_sql( $table ) . "` WHERE {$pk_sql} > %s ORDER BY {$pk_sql} ASC LIMIT {$batch}",
    403                     (string) $state['table_cursor']
     441                    (string) $cursor_value
    404442                );
    405443            }
    … …  
    438476            }
    439477
     478            $portable_row = array();
     479            foreach ( $row as $column_name => $column_value ) {
     480                $portable_row[ $column_name ] = $this->encode_database_value( $column_value );
     481            }
     482
    440483            $encoded = wp_json_encode(
    441                 array( 'type' => 'row', 'data' => $row ),
    442                 JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE
     484                array( 'type' => 'row', 'data' => $portable_row ),
     485                JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
    443486            );
    444487            if ( false === $encoded ) {
    … …  
    460503            $last = end( $rows );
    461504            if ( is_array( $last ) && array_key_exists( $pk, $last ) ) {
    462                 $state['table_cursor'] = $last[ $pk ];
     505                $state['table_cursor'] = $this->encode_database_value( $last[ $pk ] );
    463506            }
    464507        }
    … …  
    16401683            'progress'      => 100,
    16411684            'message'       => 'Export gereed. Het migratiepakket kan worden gedownload.',
    1642             'download_url'  => wp_nonce_url(
    1643                 admin_url( 'admin-post.php?action=wmig_download&token=' . rawurlencode( $token ) ),
    1644                 'wmig_download_' . $token,
    1645                 '_wmig_download_nonce'
     1685            'download_url'  => add_query_arg(
     1686                array(
     1687                    'action'               => 'wmig_download',
     1688                    'token'                => $token,
     1689                    '_wmig_download_nonce' => wp_create_nonce( 'wmig_download_' . $token ),
     1690                ),
     1691                admin_url( 'admin-post.php' )
    16461692            ),
    16471693            'package_token' => $token,
  • dave-gerrits-site-migrator/trunk/includes/class-wmig-importer.php

    r3637551 r3658562  
    710710    }
    711711
     712    /**
     713     * Restore a database value encoded by encode_database_value().
     714     *
     715     * @param mixed  $value  Portable value from the migration package.
     716     * @param string $table  Current table, used in diagnostics.
     717     * @param string $column Current column, used in diagnostics.
     718     * @return mixed|WP_Error Restored database value.
     719     */
     720    private function decode_database_value( $value, $table, $column ) {
     721        if (
     722            is_array( $value ) &&
     723            array_key_exists( '__wmig_binary_b64_v1', $value )
     724        ) {
     725            $encoded = $value['__wmig_binary_b64_v1'];
     726            if ( ! is_string( $encoded ) ) {
     727                return new WP_Error(
     728                    'wmig_db_binary_format',
     729                    sprintf( 'Ongeldige binaire databasewaarde in %s.%s.', $table, $column )
     730                );
     731            }
     732
     733            $decoded = base64_decode( $encoded, true );
     734            if ( false === $decoded ) {
     735                return new WP_Error(
     736                    'wmig_db_binary_decode',
     737                    sprintf( 'Binaire databasewaarde kon niet worden hersteld in %s.%s.', $table, $column )
     738                );
     739            }
     740
     741            return $decoded;
     742        }
     743
     744        return $value;
     745    }
     746
    712747    private function process_database( $state ) {
    713748        global $wpdb;
    … …  
    813848            $row=array();
    814849            foreach($record['data'] as $col=>$value){
    815                 if(is_string($value)){
     850                $value = $this->decode_database_value(
     851                    $value,
     852                    (string) $state['db_target_table'],
     853                    (string) $col
     854                );
     855                if ( is_wp_error( $value ) ) {
     856                    fclose( $h );
     857                    return $value;
     858                }
     859
     860                if(is_string($value) && 1 === preg_match('//u', $value)){
    816861                    $value=WMIG_Utils::recursive_replace($value,$old_siteurl,$new_siteurl);
    817862                    $value=WMIG_Utils::recursive_replace($value,$old_url,$new_url);
    … …  
    865910
    866911            $wpdb->insert($state['db_active_table'],$row);
    867             if($wpdb->last_error){fclose($h);return new WP_Error('wmp_db_insert',$wpdb->last_error);}
     912            if($wpdb->last_error){
     913                $db_error = $wpdb->last_error;
     914                fclose($h);
     915                return new WP_Error(
     916                    'wmp_db_insert',
     917                    'Databasefout bij tabel ' . (string) $state['db_target_table'] . ': ' . $db_error
     918                );
     919            }
    868920            $rows++;
    869921        }
  • dave-gerrits-site-migrator/trunk/readme.txt

    r3650920 r3658562  
    33Tags: migration, wordpress migration, site migration, backup, migrate
    44Requires at least: 6.0
    5 Tested up to: 7.0
    6 Stable tag: 1.0.2
     5Tested up to: 7.1
     6Stable tag: 1.0.3
    77Requires PHP: 7.4
    88License: GPLv2 or later
    … …  
    122122== Changelog ==
    123123
     124= 1.0.3 =
     125* Improved secure migration package download URLs for broader hosting/browser compatibility.
     126* Database export/import is now binary-safe for plugin tables using binary values or primary keys.
     127* Improved export and database error diagnostics for easier troubleshooting.
     128
    124129= 1.0.2 =
    125130* Fixed the secure migration package download link after a completed export.
Note: See TracChangeset for help on using the changeset viewer.