Plugin Directory

Changeset 3360649


Ignore:
Timestamp:
09/12/2025 04:17:37 PM (3 months ago)
Author:
andreamk
Message:

Staging version 1.5.13.3

Location:
duplicator
Files:
1160 added
10 edited

Legend:

Unmodified
Added
Removed
  • duplicator/trunk/assets/css/style.css

    r3343543 r3360649  
    525525
    526526.dup-btn-orange {
    527     background-color: #e27730;
     527    background-color: #fe4716;
    528528    color: white;
    529529}
  • duplicator/trunk/assets/js/one-click-upgrade.js

    r3254126 r3360649  
    1 var oneClickUpgradeRemoteEndpoint = "https://connect.duplicator.com/upgrade-free-to-pro";
     1// Endpoint to connect to Duplicator Pro
     2var remoteEndpoint = "https://connect.duplicator.com/get-remote-url";
    23
    34jQuery(document).ready(function ($) {
    4     if ($('#dup-settings-upgrade-license-key').length) {
    5         // Client-side redirect to oneClickUpgradeRemoteEndpoint
    6         function redirectToRemoteEndpoint(data) {
    7             $("#redirect-to-remote-upgrade-endpoint").attr("action", oneClickUpgradeRemoteEndpoint);
    8             $("#form-oth").attr("value", data["oth"]);
    9             $("#form-key").attr("value", data["license_key"]);
    10             $("#form-version").attr("value", data["version"]);
    11             $("#form-redirect").attr("value", data["redirect"]);
    12             $("#form-endpoint").attr("value", data["endpoint"]);
    13             $("#form-siteurl").attr("value", data["siteurl"]);
    14             $("#form-homeurl").attr("value", data["homeurl"]);
    15             $("#form-file").attr("value", data["file"]);
    16             $("#redirect-to-remote-upgrade-endpoint").submit();
    17         }
    18        
     5    if ($('#dup-settings-connect-btn').length) {
    196        $('#dup-settings-connect-btn').on('click', function (event) {
    207            event.stopPropagation();
    21             var license_key = $('#dup-settings-upgrade-license-key').eq(0).val();
     8
     9            // Generate OTH for secure redirect
    2210            Duplicator.Util.ajaxWrapper(
    2311                {
    24                     action: 'duplicator_one_click_upgrade_prepare',
    25                     nonce: dup_one_click_upgrade_script_data.nonce_one_click_upgrade,
    26                     license_key: license_key
     12                    action: 'duplicator_generate_connect_oth',
     13                    nonce: dup_one_click_upgrade_script_data.nonce_generate_connect_oth
    2714                },
    2815                function (result, data, funcData, textStatus, jqXHR) {
    29                     redirectToRemoteEndpoint(funcData);                       
     16                    var redirectUrl = remoteEndpoint + "?" + new URLSearchParams({
     17                        "oth": funcData.oth,
     18                        "homeurl": window.location.origin,
     19                        "redirect": funcData.redirect_url,
     20                        "origin": window.location.href,
     21                        "php_version": funcData.php_version,
     22                        "wp_version": funcData.wp_version
     23                    }).toString();
     24
     25                    window.location.href = redirectUrl;
    3026                },
    3127                function (result, data, funcData, textStatus, jqXHR) {
  • duplicator/trunk/define.php

    r3355474 r3360649  
    1212
    1313if (function_exists('plugin_dir_url')) {
    14     define('DUPLICATOR_VERSION', '1.5.13.2');
     14    define('DUPLICATOR_VERSION', '1.5.13.3');
    1515    define('DUPLICATOR_PLUGIN_URL', plugin_dir_url(__FILE__));
    1616    define('DUPLICATOR_SITE_URL', get_site_url());
  • duplicator/trunk/duplicator.php

    r3355474 r3360649  
    55 * Plugin URI: https://duplicator.com/
    66 * Description: Migrate and backup a copy of your WordPress files and database. Duplicate and move a site from one location to another quickly.
    7  * Version: 1.5.13.2
     7 * Version: 1.5.13.3
    88 * Requires at least: 5.3
    99 * Tested up to: 6.8
  • duplicator/trunk/installer/dup-installer/main.installer.php

    r3355474 r3360649  
    3939}
    4040
    41 define('DUPX_VERSION', '1.5.13.2');
     41define('DUPX_VERSION', '1.5.13.3');
    4242define('DUPX_INIT', str_replace('\\', '/', __DIR__));
    4343define('DUPX_ROOT', preg_match('/^[\\\\\/]?$/', dirname(DUPX_INIT)) ? '/' : dirname(DUPX_INIT));
  • duplicator/trunk/languages/duplicator.pot

    r3328201 r3360649  
    1010"Content-Type: text/plain; charset=UTF-8\n"
    1111"Content-Transfer-Encoding: 8bit\n"
    12 "POT-Creation-Date: 2025-07-14T10:19:53+00:00\n"
     12"POT-Creation-Date: 2025-09-12T15:30:32+00:00\n"
    1313"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
    1414"X-Generator: WP-CLI 2.12.0\n"
     
    4343
    4444#: assets/js/duplicator/dup.util.php:97
    45 #: template/admin_pages/settings/general/general.php:325
    46 #: template/admin_pages/settings/general/general.php:378
     45#: template/admin_pages/settings/general/general.php:201
     46#: template/admin_pages/settings/general/general.php:246
    4747msgid "RESPONSE ERROR!"
    4848msgstr ""
     
    279279
    280280#: classes/class.server.php:645
    281 #: template/admin_pages/settings/general/general.php:192
     281#: template/admin_pages/settings/misc/misc.php:168
    282282#: template/parts/DashboardWidget/sections-section.php:51
    283283#: views/packages/main/s2.scan3.php:46
     
    301301
    302302#: classes/class.server.php:669
    303 #: template/admin_pages/settings/general/general.php:114
     303#: template/admin_pages/settings/misc/misc.php:92
    304304#: views/packages/details/detail.php:130
    305305msgid "Version"
     
    604604msgstr ""
    605605
    606 #: src/Ajax/ServicesEducation.php:203
    607 msgid "Invalid license key."
    608 msgstr ""
    609 
    610 #: src/Ajax/ServicesEducation.php:280
    611 msgid "Invalid license JSON data."
     606#: src/Ajax/ServicesEducation.php:418
     607msgid "Upgrade installation failed: %s. Please try again or install manually."
    612608msgstr ""
    613609
     
    630626msgstr ""
    631627
    632 #: src/Controllers/AboutUsController.php:130
     628#: src/Controllers/AboutUsController.php:129
    633629msgid "Backup Files & Database"
    634630msgstr ""
    635631
    636 #: src/Controllers/AboutUsController.php:134
     632#: src/Controllers/AboutUsController.php:133
    637633#: src/Utils/Upsell.php:26
    638634#: src/Utils/Upsell.php:52
     
    641637msgstr ""
    642638
    643 #: src/Controllers/AboutUsController.php:138
     639#: src/Controllers/AboutUsController.php:137
    644640msgid "Migration Wizard"
    645641msgstr ""
    646642
    647 #: src/Controllers/AboutUsController.php:142
     643#: src/Controllers/AboutUsController.php:141
    648644msgid "Overwrite Live Site"
    649645msgstr ""
    650646
    651 #: src/Controllers/AboutUsController.php:146
     647#: src/Controllers/AboutUsController.php:145
    652648#: src/Utils/Upsell.php:32
    653649#: src/Utils/Upsell.php:55
     
    655651msgstr ""
    656652
     653#: src/Controllers/AboutUsController.php:147
     654msgid "Classic WordPress-less Installs Only"
     655msgstr ""
     656
    657657#: src/Controllers/AboutUsController.php:148
    658 msgid "Classic WordPress-less Installs Only"
    659 msgstr ""
    660 
    661 #: src/Controllers/AboutUsController.php:149
    662658msgid "Drag and Drop migrations and site restores! Simply drag the bundled site archive to the site you wish to overwrite."
    663659msgstr ""
    664660
    665 #: src/Controllers/AboutUsController.php:155
     661#: src/Controllers/AboutUsController.php:154
    666662#: src/Utils/Upsell.php:22
    667663#: src/Utils/Upsell.php:48
     
    670666msgstr ""
    671667
    672 #: src/Controllers/AboutUsController.php:157
     668#: src/Controllers/AboutUsController.php:156
    673669msgid "Ensure that your important data is regularly and consistently backed up, allowing for quick and efficient recovery in case of data loss."
    674670msgstr ""
    675671
    676 #: src/Controllers/AboutUsController.php:163
     672#: src/Controllers/AboutUsController.php:162
    677673#: src/Utils/Upsell.php:23
    678674#: src/Utils/Upsell.php:49
     
    681677msgstr ""
    682678
    683 #: src/Controllers/AboutUsController.php:165
     679#: src/Controllers/AboutUsController.php:164
    684680msgid "Recovery Points provide protection against mistakes and bad updates by letting you quickly rollback your system to a known, good state."
    685681msgstr ""
    686682
    687 #: src/Controllers/AboutUsController.php:171
     683#: src/Controllers/AboutUsController.php:170
    688684#: src/Utils/Upsell.php:53
    689685msgid "Cloud Storage"
    690686msgstr ""
    691687
    692 #: src/Controllers/AboutUsController.php:173
     688#: src/Controllers/AboutUsController.php:172
    693689msgid "Back up to Dropbox, FTP, Google Drive, OneDrive, Amazon S3 or any S3-compatible storage service for safe storage."
    694690msgstr ""
    695691
    696 #: src/Controllers/AboutUsController.php:179
     692#: src/Controllers/AboutUsController.php:178
    697693#: src/Utils/Upsell.php:33
    698694#: src/Utils/Upsell.php:59
     
    700696msgstr ""
    701697
    702 #: src/Controllers/AboutUsController.php:181
     698#: src/Controllers/AboutUsController.php:180
    703699msgid "We've developed a new way to package backups especially tailored for larger site. No server timeouts or other restrictions!"
    704700msgstr ""
    705701
    706 #: src/Controllers/AboutUsController.php:187
     702#: src/Controllers/AboutUsController.php:186
    707703msgid "Server-to-Server Import"
    708704msgstr ""
    709705
    710 #: src/Controllers/AboutUsController.php:189
     706#: src/Controllers/AboutUsController.php:188
    711707msgid "Direct Server Transfers allow you to build an archive, then directly transfer it from the source server to the destination server for a lightning fast migration!"
    712708msgstr ""
    713709
    714 #: src/Controllers/AboutUsController.php:196
     710#: src/Controllers/AboutUsController.php:195
    715711msgid "Multisite support"
    716712msgstr ""
    717713
    718 #: src/Controllers/AboutUsController.php:198
     714#: src/Controllers/AboutUsController.php:197
    719715msgid "Supports multisite network backup & migration. Subsite As Standalone Install, Standalone Import Into Multisite and Import Subsite Into Multisite"
    720716msgstr ""
    721717
    722 #: src/Controllers/AboutUsController.php:205
     718#: src/Controllers/AboutUsController.php:204
    723719#: src/Utils/Upsell.php:60
    724720msgid "Installer Branding"
    725721msgstr ""
    726722
    727 #: src/Controllers/AboutUsController.php:207
     723#: src/Controllers/AboutUsController.php:206
    728724msgid "Create your own custom-configured WordPress site and \"Brand\" the installer file with your look and feel."
    729725msgstr ""
    730726
    731 #: src/Controllers/AboutUsController.php:210
     727#: src/Controllers/AboutUsController.php:209
    732728msgid "Archive Encryption"
    733729msgstr ""
    734730
    735 #: src/Controllers/AboutUsController.php:212
     731#: src/Controllers/AboutUsController.php:211
    736732msgid "Protect and secure the archive file with industry-standard AES-256 encryption!"
    737733msgstr ""
    738734
    739 #: src/Controllers/AboutUsController.php:215
     735#: src/Controllers/AboutUsController.php:214
    740736#: src/Utils/Upsell.php:36
    741737#: src/Utils/Upsell.php:66
     
    744740msgstr ""
    745741
    746 #: src/Controllers/AboutUsController.php:217
     742#: src/Controllers/AboutUsController.php:216
    747743msgid "Enjoy granular access control to ensure only authorized users can perform these critical functions."
    748744msgstr ""
    749745
    750 #: src/Controllers/AboutUsController.php:223
     746#: src/Controllers/AboutUsController.php:222
    751747msgid "Enhanced Features"
    752748msgstr ""
    753749
    754 #: src/Controllers/AboutUsController.php:225
     750#: src/Controllers/AboutUsController.php:224
    755751msgid "Enhanced features include: Managed Hosting Support, Shared Database Support, Streamlined Installer, Email Alerts and more..."
    756752msgstr ""
    757753
    758 #: src/Controllers/AboutUsController.php:231
     754#: src/Controllers/AboutUsController.php:230
    759755msgid "Advanced Features"
    760756msgstr ""
    761757
    762 #: src/Controllers/AboutUsController.php:233
     758#: src/Controllers/AboutUsController.php:232
    763759msgid "Advanced features included: Hourly Schedules, Custom Search & Replace, Migrate Duplicator Settings, Regenerate Salts and Developer Hooks"
    764760msgstr ""
    765761
    766 #: src/Controllers/AboutUsController.php:239
     762#: src/Controllers/AboutUsController.php:238
    767763msgid "Customer Support"
    768764msgstr ""
    769765
     766#: src/Controllers/AboutUsController.php:240
     767msgid "Limited Support"
     768msgstr ""
     769
    770770#: src/Controllers/AboutUsController.php:241
    771 msgid "Limited Support"
    772 msgstr ""
    773 
    774 #: src/Controllers/AboutUsController.php:242
    775771msgid "Priority Support"
    776772msgstr ""
     
    853849msgstr ""
    854850
    855 #: src/Core/Bootstrap.php:267
    856 #: src/Core/Bootstrap.php:526
     851#: src/Core/Bootstrap.php:269
     852#: src/Core/Bootstrap.php:544
    857853msgid "Upgrade to Pro"
    858854msgstr ""
    859855
    860 #: src/Core/Bootstrap.php:268
     856#: src/Core/Bootstrap.php:270
    861857msgid "NEW!"
    862858msgstr ""
    863859
    864 #: src/Core/Bootstrap.php:272
    865 #: src/Core/Bootstrap.php:273
     860#: src/Core/Bootstrap.php:274
     861#: src/Core/Bootstrap.php:275
    866862#: template/mail/email_summary.php:130
    867863#: views/packages/details/controller.php:76
     
    871867msgstr ""
    872868
    873 #: src/Core/Bootstrap.php:282
    874 #: src/Core/Bootstrap.php:283
     869#: src/Core/Bootstrap.php:284
     870#: src/Core/Bootstrap.php:285
    875871msgid "Import Backups"
    876872msgstr ""
    877873
    878 #: src/Core/Bootstrap.php:293
    879 #: src/Core/Bootstrap.php:294
     874#: src/Core/Bootstrap.php:295
     875#: src/Core/Bootstrap.php:296
    880876msgid "Schedule Backups"
    881877msgstr ""
    882878
    883 #: src/Core/Bootstrap.php:304
    884 #: src/Core/Bootstrap.php:305
     879#: src/Core/Bootstrap.php:306
     880#: src/Core/Bootstrap.php:307
    885881#: template/mocks/storage/storage.php:59
    886882#: views/packages/details/detail.php:278
     
    890886msgstr ""
    891887
    892 #: src/Core/Bootstrap.php:313
    893 #: src/Core/Bootstrap.php:314
     888#: src/Core/Bootstrap.php:315
     889#: src/Core/Bootstrap.php:316
    894890msgid "Tools"
    895891msgstr ""
    896892
    897 #: src/Core/Bootstrap.php:324
    898 #: src/Core/Bootstrap.php:325
    899 #: template/admin_pages/settings/general/general.php:217
     893#: src/Core/Bootstrap.php:329
     894#: src/Core/Bootstrap.php:330
     895#: template/admin_pages/settings/general/general.php:91
    900896#: template/mocks/storage/storage.php:87
    901897#: views/settings/controller.php:23
     
    903899msgstr ""
    904900
    905 #: src/Core/Bootstrap.php:334
     901#: src/Core/Bootstrap.php:339
    906902msgid "About Duplicator"
    907903msgstr ""
    908904
    909 #: src/Core/Bootstrap.php:335
     905#: src/Core/Bootstrap.php:340
    910906#: template/admin_pages/about_us/tabs.php:17
    911907msgid "About Us"
    912908msgstr ""
    913909
    914 #: src/Core/Bootstrap.php:378
     910#: src/Core/Bootstrap.php:383
    915911#: template/parts/Education/subscribe-form.php:26
    916912msgid "Subscribe"
    917913msgstr ""
    918914
    919 #: src/Core/Bootstrap.php:379
     915#: src/Core/Bootstrap.php:384
    920916msgid "Subscribed &#10003"
    921917msgstr ""
    922918
    923 #: src/Core/Bootstrap.php:380
     919#: src/Core/Bootstrap.php:385
    924920msgid "Subscribing..."
    925921msgstr ""
    926922
    927 #: src/Core/Bootstrap.php:381
     923#: src/Core/Bootstrap.php:386
    928924msgid "Failed &#10007"
    929925msgstr ""
    930926
    931 #: src/Core/Bootstrap.php:382
     927#: src/Core/Bootstrap.php:387
    932928msgid "Email subscription failed with message: "
    933929msgstr ""
    934930
    935 #: src/Core/Bootstrap.php:393
    936 msgid "Failed to activate license for this website."
    937 msgstr ""
    938 
    939 #: src/Core/Bootstrap.php:394
     931#: src/Core/Bootstrap.php:398
     932msgid "Failed to connect to Duplicator Pro."
     933msgstr ""
     934
     935#: src/Core/Bootstrap.php:399
    940936msgid "Message: "
    941937msgstr ""
    942938
    943 #: src/Core/Bootstrap.php:395
    944 msgid "Check the license key and try again, if the error persists proceed with manual activation."
    945 msgstr ""
    946 
    947 #: src/Core/Bootstrap.php:404
     939#: src/Core/Bootstrap.php:400
     940msgid "Please try again or contact support if the issue persists."
     941msgstr ""
     942
     943#: src/Core/Bootstrap.php:409
    948944msgid "Failed to load help content!"
    949945msgstr ""
    950946
    951 #: src/Core/Bootstrap.php:413
     947#: src/Core/Bootstrap.php:418
    952948msgid "Copy to clipboard"
    953949msgstr ""
    954950
    955 #: src/Core/Bootstrap.php:414
     951#: src/Core/Bootstrap.php:419
    956952msgid "copied to clipboard"
    957953msgstr ""
    958954
    959 #: src/Core/Bootstrap.php:415
     955#: src/Core/Bootstrap.php:420
    960956msgid "Unable to copy"
    961957msgstr ""
    962958
    963 #: src/Core/Bootstrap.php:546
     959#: src/Core/Bootstrap.php:564
    964960msgid "Manage Backups"
    965961msgstr ""
    966962
    967 #: src/Core/Bootstrap.php:547
    968 #: views/settings/license.php:11
     963#: src/Core/Bootstrap.php:565
    969964msgid "Manage"
    970965msgstr ""
     
    10191014
    10201015#: src/Core/Notifications/Review.php:98
    1021 #: template/admin_pages/settings/general/general.php:301
     1016#: template/admin_pages/settings/general/general.php:177
    10221017msgid "Yes"
    10231018msgstr ""
     
    10641059msgstr ""
    10651060
    1066 #: src/Libs/OneClickUpgrade/ConnectSkin.php:35
    1067 msgid "There was an error installing Duplicator Pro. Please try again."
     1061#: src/Libs/OneClickUpgrade/UpgraderSkin.php:100
     1062msgid "There was an error installing the upgrade. Please try again."
    10681063msgstr ""
    10691064
     
    14261421msgstr ""
    14271422
     1423#: src/Utils/ExtraPlugins/ExtraPluginsMng.php:532
     1424msgid "Database Reset Pro"
     1425msgstr ""
     1426
     1427#: src/Utils/ExtraPlugins/ExtraPluginsMng.php:535
     1428msgid ""
     1429"Database Reset Pro is the safest and simplest way to reset your WordPress database to its default state. \n"
     1430"            Unlike reinstalling WordPress, this database reset plugin preserves your files, uploads, \n"
     1431"            and admin credentials while giving you a fresh start in seconds."
     1432msgstr ""
     1433
    14281434#: src/Utils/Support/SupportToolkit.php:60
    14291435msgid "Failed to create zip file"
     
    15871593#: src/Views/AdminNotices.php:410
    15881594msgid ""
    1589 "You created over %d backups with Duplicator. Great job! If you can spare a minute, \n"
     1595"You created over %d backups with Duplicator. Great job! If you can spare a minute,\n"
    15901596"                                please help us by leaving a five star review on WordPress.org."
    15911597msgstr ""
     
    16011607#: src/Views/AdminNotices.php:448
    16021608msgid ""
    1603 "<strong>Duplicator</strong><hr> Your logged-in user role does not have export \n"
     1609"<strong>Duplicator</strong><hr> Your logged-in user role does not have export\n"
    16041610"                capability so you don't have access to Duplicator functionality."
    16051611msgstr ""
     
    18081814msgstr ""
    18091815
     1816#: template/admin_pages/settings/general/general.php:87
     1817msgid "Advanced"
     1818msgstr ""
     1819
     1820#: template/admin_pages/settings/general/general.php:94
     1821msgid "Reset Backups"
     1822msgstr ""
     1823
     1824#: template/admin_pages/settings/general/general.php:98
     1825msgid "This process will reset all Backups by deleting those without a completed status, reset the active Backup id and perform a cleanup of the build tmp file."
     1826msgstr ""
     1827
     1828#: template/admin_pages/settings/general/general.php:102
     1829msgid "Reset Settings"
     1830msgstr ""
     1831
     1832#: template/admin_pages/settings/general/general.php:104
     1833msgid "This action should only be used if the Backups screen is having issues or a build is stuck."
     1834msgstr ""
     1835
    18101836#: template/admin_pages/settings/general/general.php:110
    1811 msgid "Plugin"
    1812 msgstr ""
    1813 
    1814 #: template/admin_pages/settings/general/general.php:122
    1815 msgid "Uninstall"
    1816 msgstr ""
    1817 
    1818 #: template/admin_pages/settings/general/general.php:126
    1819 msgid "Delete Plugin Settings"
    1820 msgstr ""
    1821 
    1822 #: template/admin_pages/settings/general/general.php:130
    1823 msgid "Delete Entire Storage Directory"
    1824 msgstr ""
    1825 
    1826 #: template/admin_pages/settings/general/general.php:135
    1827 msgid "Usage statistics"
    1828 msgstr ""
    1829 
    1830 #: template/admin_pages/settings/general/general.php:139
    1831 msgid "Usage statistics are hardcoded disallowed."
    1832 msgstr ""
    1833 
    1834 #: template/admin_pages/settings/general/general.php:149
    1835 msgid "Enable usage tracking"
    1836 msgstr ""
    1837 
    1838 #: template/admin_pages/settings/general/general.php:152
    1839 msgid "Usage Tracking"
    1840 msgstr ""
    1841 
    1842 #: template/admin_pages/settings/general/general.php:161
    1843 msgid "Hide Announcements"
    1844 msgstr ""
    1845 
    1846 #: template/admin_pages/settings/general/general.php:170
    1847 msgid "Check this option to hide plugin announcements and update details."
    1848 msgstr ""
    1849 
    1850 #: template/admin_pages/settings/general/general.php:178
    1851 msgid "Debug"
    1852 msgstr ""
    1853 
    1854 #: template/admin_pages/settings/general/general.php:182
    1855 msgid "Debugging"
    1856 msgstr ""
    1857 
    1858 #: template/admin_pages/settings/general/general.php:185
    1859 msgid "Enable debug options throughout user interface"
    1860 msgstr ""
    1861 
    1862 #: template/admin_pages/settings/general/general.php:189
    1863 msgid "Trace Log"
    1864 msgstr ""
    1865 
    1866 #: template/admin_pages/settings/general/general.php:195
    1867 msgid "Turns on detailed operation logging. Logging will occur in both PHP error and local trace logs."
    1868 msgstr ""
    1869 
    1870 #: template/admin_pages/settings/general/general.php:197
    1871 msgid "WARNING: Only turn on this setting when asked to by support as tracing will impact performance."
    1872 msgstr ""
    1873 
    1874 #: template/admin_pages/settings/general/general.php:205
    1875 msgid "Download Trace Log"
    1876 msgstr ""
    1877 
    1878 #: template/admin_pages/settings/general/general.php:213
    1879 msgid "Advanced"
    1880 msgstr ""
    1881 
    1882 #: template/admin_pages/settings/general/general.php:220
    1883 msgid "Reset Backups"
    1884 msgstr ""
    1885 
    1886 #: template/admin_pages/settings/general/general.php:224
    1887 msgid "This process will reset all Backups by deleting those without a completed status, reset the active Backup id and perform a cleanup of the build tmp file."
    1888 msgstr ""
    1889 
    1890 #: template/admin_pages/settings/general/general.php:228
    1891 msgid "Reset Settings"
    1892 msgstr ""
    1893 
    1894 #: template/admin_pages/settings/general/general.php:230
    1895 msgid "This action should only be used if the Backups screen is having issues or a build is stuck."
    1896 msgstr ""
    1897 
    1898 #: template/admin_pages/settings/general/general.php:236
    18991837msgid "Backup scan"
    19001838msgstr ""
    19011839
    1902 #: template/admin_pages/settings/general/general.php:239
     1840#: template/admin_pages/settings/general/general.php:113
    19031841#: template/admin_pages/welcome/intro.php:48
    19041842msgid "Skip"
    19051843msgstr ""
    19061844
    1907 #: template/admin_pages/settings/general/general.php:242
     1845#: template/admin_pages/settings/general/general.php:116
    19081846msgid "If enabled all files check on scan will be skipped before Backup creation.  In some cases, this option can be beneficial if the scan process is having issues running or returning errors."
    19091847msgstr ""
    19101848
    1911 #: template/admin_pages/settings/general/general.php:249
     1849#: template/admin_pages/settings/general/general.php:123
    19121850msgid "Foreign JavaScript"
    19131851msgstr ""
    19141852
    1915 #: template/admin_pages/settings/general/general.php:252
    1916 #: template/admin_pages/settings/general/general.php:266
     1853#: template/admin_pages/settings/general/general.php:126
     1854#: template/admin_pages/settings/general/general.php:140
    19171855msgid "Disable"
    19181856msgstr ""
    19191857
    1920 #: template/admin_pages/settings/general/general.php:255
     1858#: template/admin_pages/settings/general/general.php:129
    19211859msgid "Check this option if other plugins/themes JavaScript files are conflicting with Duplicator."
    19221860msgstr ""
    19231861
    1924 #: template/admin_pages/settings/general/general.php:257
    1925 #: template/admin_pages/settings/general/general.php:271
     1862#: template/admin_pages/settings/general/general.php:131
     1863#: template/admin_pages/settings/general/general.php:145
    19261864msgid "Do not modify this setting unless you know the expected result or have talked to support."
    19271865msgstr ""
    19281866
    1929 #: template/admin_pages/settings/general/general.php:263
     1867#: template/admin_pages/settings/general/general.php:137
    19301868msgid "Foreign CSS"
    19311869msgstr ""
    19321870
    1933 #: template/admin_pages/settings/general/general.php:269
     1871#: template/admin_pages/settings/general/general.php:143
    19341872msgid "Check this option if other plugins/themes CSS files are conflicting with Duplicator."
    19351873msgstr ""
    19361874
    1937 #: template/admin_pages/settings/general/general.php:285
     1875#: template/admin_pages/settings/general/general.php:159
    19381876msgid "Save General Settings"
    19391877msgstr ""
    19401878
    1941 #: template/admin_pages/settings/general/general.php:296
     1879#: template/admin_pages/settings/general/general.php:172
    19421880msgid "Reset Backups ?"
    19431881msgstr ""
    19441882
    1945 #: template/admin_pages/settings/general/general.php:297
     1883#: template/admin_pages/settings/general/general.php:173
    19461884msgid "This will clear and reset all of the current temporary Backups.  Would you like to continue?"
    19471885msgstr ""
    19481886
    1949 #: template/admin_pages/settings/general/general.php:298
     1887#: template/admin_pages/settings/general/general.php:174
    19501888msgid "Resetting settings, Please Wait..."
    19511889msgstr ""
    19521890
    1953 #: template/admin_pages/settings/general/general.php:302
     1891#: template/admin_pages/settings/general/general.php:178
    19541892msgid "No"
    19551893msgstr ""
    19561894
    1957 #: template/admin_pages/settings/general/general.php:308
     1895#: template/admin_pages/settings/general/general.php:184
    19581896msgid "AJAX Call Error!"
    19591897msgstr ""
    19601898
    1961 #: template/admin_pages/settings/general/general.php:310
     1899#: template/admin_pages/settings/general/general.php:186
    19621900msgctxt "1 and 2 are opening and closing <a> tags"
    19631901msgid "AJAX error encountered when resetting Backups. Please see %1$sthis FAQ entry%2$s for possible resolutions."
    19641902msgstr ""
    19651903
    1966 #: template/admin_pages/settings/general/general.php:368
     1904#: template/admin_pages/settings/general/general.php:236
    19671905msgid "Backups successfully reset"
     1906msgstr ""
     1907
     1908#: template/admin_pages/settings/general/license.php:16
     1909msgid "License"
     1910msgstr ""
     1911
     1912#: template/admin_pages/settings/general/license.php:20
     1913msgid "License Key"
     1914msgstr ""
     1915
     1916#: template/admin_pages/settings/general/license.php:23
     1917msgid "You're using Duplicator Lite - no license needed. Enjoy!"
     1918msgstr ""
     1919
     1920#: template/admin_pages/settings/general/license.php:27
     1921msgid ""
     1922"To unlock more features consider <strong><a href=\"%s\" target=\"_blank\"\n"
     1923"                            rel=\"noopener noreferrer\">upgrading to PRO</a></strong>."
     1924msgstr ""
     1925
     1926#: template/admin_pages/settings/general/license.php:45
     1927msgid "As a valued Duplicator Lite user you receive <strong>%1$d%% off</strong>, automatically applied at checkout!"
     1928msgstr ""
     1929
     1930#: template/admin_pages/settings/general/license.php:55
     1931msgid "Already purchased? Connect to unlock <b>Duplicator PRO!</b>"
     1932msgstr ""
     1933
     1934#: template/admin_pages/settings/general/license.php:58
     1935msgid "Connect to Duplicator Pro"
     1936msgstr ""
     1937
     1938#: template/admin_pages/settings/general/license.php:62
     1939msgid "This opens connect.duplicator.com where you'll securely connect to Duplicator Pro."
    19681940msgstr ""
    19691941
     
    20221994msgstr ""
    20231995
     1996#: template/admin_pages/settings/misc/misc.php:24
     1997msgid "Misc Settings Saved"
     1998msgstr ""
     1999
     2000#: template/admin_pages/settings/misc/misc.php:88
     2001msgid "Plugin"
     2002msgstr ""
     2003
     2004#: template/admin_pages/settings/misc/misc.php:100
     2005msgid "Uninstall"
     2006msgstr ""
     2007
     2008#: template/admin_pages/settings/misc/misc.php:104
     2009msgid "Delete Plugin Settings"
     2010msgstr ""
     2011
     2012#: template/admin_pages/settings/misc/misc.php:108
     2013msgid "Delete Entire Storage Directory"
     2014msgstr ""
     2015
     2016#: template/admin_pages/settings/misc/misc.php:113
     2017msgid "Usage statistics"
     2018msgstr ""
     2019
     2020#: template/admin_pages/settings/misc/misc.php:117
     2021msgid "Usage statistics are hardcoded disallowed."
     2022msgstr ""
     2023
     2024#: template/admin_pages/settings/misc/misc.php:127
     2025msgid "Enable usage tracking"
     2026msgstr ""
     2027
     2028#: template/admin_pages/settings/misc/misc.php:130
     2029msgid "Usage Tracking"
     2030msgstr ""
     2031
     2032#: template/admin_pages/settings/misc/misc.php:139
     2033msgid "Hide Announcements"
     2034msgstr ""
     2035
     2036#: template/admin_pages/settings/misc/misc.php:148
     2037msgid "Check this option to hide plugin announcements and update details."
     2038msgstr ""
     2039
     2040#: template/admin_pages/settings/misc/misc.php:154
     2041msgid "Debug"
     2042msgstr ""
     2043
     2044#: template/admin_pages/settings/misc/misc.php:158
     2045msgid "Debugging"
     2046msgstr ""
     2047
     2048#: template/admin_pages/settings/misc/misc.php:161
     2049msgid "Enable debug options throughout user interface"
     2050msgstr ""
     2051
     2052#: template/admin_pages/settings/misc/misc.php:165
     2053msgid "Trace Log"
     2054msgstr ""
     2055
     2056#: template/admin_pages/settings/misc/misc.php:171
     2057msgid "Turns on detailed operation logging. Logging will occur in both PHP error and local trace logs."
     2058msgstr ""
     2059
     2060#: template/admin_pages/settings/misc/misc.php:173
     2061msgid "WARNING: Only turn on this setting when asked to by support as tracing will impact performance."
     2062msgstr ""
     2063
     2064#: template/admin_pages/settings/misc/misc.php:181
     2065msgid "Download Trace Log"
     2066msgstr ""
     2067
     2068#: template/admin_pages/settings/misc/misc.php:194
     2069msgid "Save Misc Settings"
     2070msgstr ""
     2071
    20242072#: template/admin_pages/welcome/features.php:21
    20252073msgid "Duplicator Features"
     
    22282276msgctxt "%s is an <a> tag with a link to the current website."
    22292277msgid "This email was auto-generated and sent from %s."
     2278msgstr ""
     2279
     2280#: template/mocks/db_reset/db_reset.php:17
     2281msgid "Clean & Reset WordPress Database"
    22302282msgstr ""
    22312283
     
    24192471#: views/packages/details/detail.php:426
    24202472#: views/packages/main/s1.setup2.php:122
    2421 #: views/settings/license.php:23
    24222473msgid "Type"
    24232474msgstr ""
     
    27822833msgstr ""
    27832834
     2835#: template/parts/plugin-footer.php:28
     2836msgid "Support"
     2837msgstr ""
     2838
     2839#: template/parts/plugin-footer.php:32
     2840msgid "Docs"
     2841msgstr ""
     2842
     2843#: template/parts/plugin-footer.php:36
     2844msgid "Migration Services"
     2845msgstr ""
     2846
     2847#: template/parts/plugin-footer.php:40
     2848msgid "Free Plugins"
     2849msgstr ""
     2850
     2851#: template/parts/plugin-footer.php:48
     2852msgid "Made with ♥ by the Duplicator Team"
     2853msgstr ""
     2854
    27842855#: views/packages/details/controller.php:29
    27852856msgctxt "%1$s represents the Backup name"
     
    48394910msgstr ""
    48404911
    4841 #: views/settings/controller.php:54
    4842 msgid "License"
    4843 msgstr ""
    4844 
    4845 #: views/settings/license.php:7
    4846 msgid "Activation"
    4847 msgstr ""
    4848 
    4849 #: views/settings/license.php:15
    4850 msgid "%1$sManage Licenses%2$s"
    4851 msgstr ""
    4852 
    4853 #: views/settings/license.php:25
    4854 msgid "Duplicator Lite"
    4855 msgstr ""
    4856 
    4857 #: views/settings/license.php:27
    4858 msgid "Basic Features"
    4859 msgstr ""
    4860 
    4861 #: views/settings/license.php:32
    4862 msgid "Pro Features"
    4863 msgstr ""
    4864 
    4865 #: views/settings/license.php:38
    4866 msgid "License Key"
    4867 msgstr ""
    4868 
    4869 #: views/settings/license.php:41
    4870 msgid "You're using Duplicator Lite - no license needed. Enjoy!"
    4871 msgstr ""
    4872 
    4873 #: views/settings/license.php:45
    4874 msgid "To unlock more features consider <strong><a href=\"%s\" target=\"_blank\" rel=\"noopener noreferrer\">upgrading to PRO</a></strong>."
    4875 msgstr ""
    4876 
    4877 #: views/settings/license.php:62
    4878 msgid "As a valued Duplicator Lite user you receive <strong>%1$d%% off</strong>, automatically applied at checkout!"
    4879 msgstr ""
    4880 
    4881 #: views/settings/license.php:72
    4882 msgid "Already purchased? Simply enter your license key below to enable <b>Duplicator PRO!</b>"
    4883 msgstr ""
    4884 
    4885 #: views/settings/license.php:74
    4886 msgid "Paste license key here"
    4887 msgstr ""
    4888 
    4889 #: views/settings/license.php:75
    4890 msgid "One click Upgrade to Pro"
     4912#: views/settings/controller.php:55
     4913msgid "Misc"
    48914914msgstr ""
    48924915
  • duplicator/trunk/src/Ajax/ServicesEducation.php

    r3343543 r3360649  
    1616use DUP_Settings;
    1717use Duplicator\Core\Controllers\ControllersManager;
    18 use Duplicator\Libs\Snap\SnapJson;
     18use Duplicator\Core\Notifications\Notice;
    1919use Duplicator\Libs\Snap\SnapUtil;
    2020
    2121class ServicesEducation extends AbstractAjaxService
    2222{
    23     const OPTION_KEY_ONE_CLICK_UPGRADE_OTH = 'duplicator_one_click_upgrade_oth';
    24     const LICENSE_KEY_OPTION_AUTO_ACTIVE   = 'duplicator_pro_license_auto_active';
    25     const DUPLICATOR_STORE_URL             = "https://duplicator.com";
    26     const REMOTE_SUBSCRIBE_URL             = 'https://duplicator.com/?lite_email_signup=1';
     23    const OPTION_KEY_ONE_CLICK_UPGRADE_OTH  = 'duplicator_one_click_upgrade_oth';
     24    const AUTH_TOKEN_KEY_OPTION_AUTO_ACTIVE = 'duplicator_pro_auth_token_auto_active';
     25    const DUPLICATOR_STORE_URL              = "https://duplicator.com";
     26    const REMOTE_SUBSCRIBE_URL              = 'https://duplicator.com/?lite_email_signup=1';
    2727
    2828    /**
     
    3636        $this->addAjaxCall('wp_ajax_duplicator_packages_bottom_bar_dismiss', 'dismissBottomBar');
    3737        $this->addAjaxCall('wp_ajax_duplicator_email_subscribe', 'setEmailSubscribed');
    38         $this->addAjaxCall('wp_ajax_duplicator_one_click_upgrade_prepare', 'prepareForOneClickUpgrade');
    39         $this->addAjaxCall('wp_ajax_duplicator_finalize_oneclick_upr', 'finalizeOneClickUpgrade');
     38        $this->addAjaxCall('wp_ajax_duplicator_generate_connect_oth', 'generateConnectOTH');
    4039        $this->addAjaxCall('wp_ajax_nopriv_duplicator_lite_run_one_click_upgrade', 'oneClickUpgrade');
    4140        $this->addAjaxCall('wp_ajax_duplicator_lite_run_one_click_upgrade', 'oneClickUpgrade');
     
    141140
    142141    /**
    143      * Generate oth and save it into a db option, save also license key into a db option.
    144      * Returns all values necessary for creating a request to remote endpoint
    145      *
    146      * @throws Exception In case it failed to save data into db
    147      * @return array     Contains:
    148      */
    149     public static function prepareForOneClickUpgradeCallback()
    150     {
    151         $oth        = wp_generate_password(30, false, false); // Generate random oth
    152         $licenseKey = sanitize_text_field($_REQUEST["license_key"]);
     142     * Generate OTH for connect flow
     143     *
     144     * @return void
     145     */
     146    public function generateConnectOTH()
     147    {
     148        AjaxWrapper::json(
     149            array(__CLASS__, 'generateConnectOTHCallback'),
     150            'duplicator_generate_connect_oth',
     151            SnapUtil::sanitizeTextInput(INPUT_POST, 'nonce'),
     152            'export'
     153        );
     154    }
     155
     156    /**
     157     * Generate OTH for connect flow callback
     158     *
     159     * @return array
     160     * @throws Exception
     161     */
     162    public static function generateConnectOTHCallback()
     163    {
     164        $oth        = wp_generate_password(30, false, false);
     165        $hashed_oth = self::hashOth($oth);
     166
     167        // Save HASHED OTH with TTL for security
     168        $oth_data = array(
     169            'token' => $hashed_oth,  // Store hashed OTH for decryption
     170            'created_at' => time(),
     171            'expires_at' => time() + (10 * MINUTE_IN_SECONDS) // 10 minute expiration
     172        );
    153173
    154174        delete_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
    155         delete_option(self::LICENSE_KEY_OPTION_AUTO_ACTIVE);
    156         $ok1 = update_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH, $oth);
    157         $ok2 = update_option(self::LICENSE_KEY_OPTION_AUTO_ACTIVE, $licenseKey);
    158 
    159         if (!$ok1 || !$ok2) {
    160             throw new Exception("Problem saving new parameters into options table in prepareForOneClickUpgradeCallback.");
    161         }
    162         $returnData = array();
    163 
    164         $returnData["success"]   = true;
    165         $returnData["error_msg"] = "";
    166 
    167         $returnData["oth"]         = self::hashOth($oth);
    168         $returnData["license_key"] = $licenseKey;
    169         $returnData["version"]     = DUPLICATOR_VERSION;
    170         $returnData["redirect"]    = base64_encode(admin_url('admin-ajax.php?action=duplicator_finalize_oneclick_upr'));
    171         $returnData["endpoint"]    = admin_url('admin-ajax.php');
    172         $returnData["siteurl"]     = admin_url();
    173         $returnData["homeurl"]     = home_url();
    174 
    175         $returnData["response"] = ""; // Store response
    176         $returnData["file"]     = "";
    177 
    178         // Activate license for this home_url. We can't use download link
    179         // without first activating license.
    180         $api_params = array(
    181             'edd_action' => 'activate_license',
    182             'license'    => $licenseKey,
    183             'item_name'  => "Duplicator Pro", // the name of our product in EDD,
    184             'url'        => home_url()
    185         );
    186 
    187         global $wp_version;
    188         $agent_string = "WordPress/" . $wp_version;
    189         DUP_Log::trace("Wordpress agent string $agent_string");
    190 
    191         $requestParam = array(
    192             'timeout'    => 15,
    193             'sslverify'  => true,
    194             'user-agent' => $agent_string,
    195             'body'       => $api_params
    196         );
    197 
    198         if (($data = self::licenseUpgradeRequests($requestParam, $requestError)) === false) {
    199             throw new Exception($requestError['message']);
    200         } elseif (!isset($data->license) || $data->license != 'valid') {
    201             throw new Exception(__('Invalid license key.', 'duplicator'));
    202         }
    203 
    204         // Fetch direct url and set $returnData["file"]. It is a direct url to download the upgrade version.
    205         // It can be used only after license is activated for the given website.
    206         $api_params = array(
    207             'edd_action'  => 'get_version',
    208             'license'     => $licenseKey,
    209             'item_name'   => "Duplicator Pro",
    210             'slug'        => "duplicator-pro",
    211             'author'      => "Snap Creek Software",
    212             'url'         => home_url(),
    213             'beta'        => false,
     175        $ok = update_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH, $oth_data);
     176
     177        if (!$ok) {
     178            throw new Exception("Problem saving security token.");
     179        }
     180
     181        return array(
     182            'success' => true,
     183            'oth' => $hashed_oth,
    214184            'php_version' => phpversion(),
    215             'wp_version'  => get_bloginfo('version'),
    216         );
    217 
    218         $requestParam = array(
    219             'timeout'   => 15,
    220             'sslverify' => true,
    221             'body'      => $api_params,
    222         );
    223 
    224         if (($data = self::licenseUpgradeRequests($requestParam, $requestError)) === false) {
    225             throw new Exception($requestError['message']);
    226         } elseif (!isset($data->download_link) || empty($data->download_link)) {
    227             throw new Exception('License key download URL is invalid');
    228         }
    229 
    230         $returnData["file"] = base64_encode($data->download_link);
    231         return $returnData;
    232     }
     185            'wp_version' => get_bloginfo('version'),
     186            'redirect_url' => admin_url('admin-ajax.php?action=duplicator_lite_run_one_click_upgrade')
     187        );
     188    }
     189
    233190
    234191    /**
     
    245202
    246203    /**
    247      * License upgrade requests
    248      *
    249      * @param array $params       Parameters
    250      * @param array $requestError Request error
    251      *
    252      * @return false|object False on error, array data on success
    253      */
    254     protected static function licenseUpgradeRequests($params, &$requestError = array())
     204     * Decrypt data using OTH-based key.
     205     *
     206     * @param string $encryptedData Base64 encoded encrypted data
     207     * @param string $oth           The OTH token
     208     *
     209     * @return string|false Decrypted data or false on failure
     210     */
     211    protected static function decryptData($encryptedData, $oth)
    255212    {
    256213        try {
    257             $requestError = array(
    258                 'code'    => -1,
    259                 'message' => '',
    260                 'details' => '',
    261             );
    262 
    263             $response = wp_remote_post(self::DUPLICATOR_STORE_URL, $params);
    264             if (is_wp_error($response)) {
    265                 /** @var WP_Error  $response */
    266                 $requestError['code']    = $response->get_error_code();
    267                 $requestError['message'] = $response->get_error_message();
    268                 $requestError['details'] = SnapJson::jsonEncodePPrint($response->get_error_data());
    269             } elseif ($response['response']['code'] < 200 || $response['response']['code'] >= 300) {
    270                 $requestError['code']    = $response['response']['code'];
    271                 $requestError['message'] = $response['response']['message'];
    272                 $requestError['details'] = SnapJson::jsonEncodePPrint($response);
    273             } else {
    274                 $data = json_decode(wp_remote_retrieve_body($response));
    275                 if (!is_object($data)) {
    276                     $requestError['code']    = -1;
    277                     $requestError['message'] = __('Invalid license JSON data.', 'duplicator');
    278                     $requestError['details'] = 'Response: ' . wp_remote_retrieve_body($response);
    279                 } else {
    280                     return $data;
    281                 }
    282             }
     214            $encryption_key = substr(hash('sha256', $oth), 0, 32); // 32-byte key from OTH
     215            $iv             = substr($oth, 0, 16); // 16-byte IV from OTH
     216
     217            $encrypted = base64_decode($encryptedData);
     218            return openssl_decrypt($encrypted, 'AES-256-CBC', $encryption_key, 0, $iv);
    283219        } catch (Exception $e) {
    284             $requestError['code']    = -1;
    285             $requestError['message'] = 'Exception ' . $e->getMessage();
    286             $requestError['details'] = $e->getTraceAsString();
    287         }
    288 
    289         return false;
    290     }
     220            DUP_Log::trace("ERROR: Decryption failed: " . $e->getMessage());
     221            return false;
     222        }
     223    }
     224
     225    /**
     226     * Decrypt and parse encrypted package from service.
     227     *
     228     * @param string $encryptedPackage Base64 encoded encrypted package
     229     * @param string $oth              The OTH token
     230     *
     231     * @return array|false Parsed package data or false on failure
     232     */
     233    protected static function decryptPackage($encryptedPackage, $oth)
     234    {
     235        $decrypted = self::decryptData($encryptedPackage, $oth);
     236
     237        if ($decrypted === false) {
     238            return false;
     239        }
     240
     241        $package = json_decode($decrypted, true);
     242
     243        if (json_last_error() !== JSON_ERROR_NONE) {
     244            DUP_Log::trace("ERROR: Invalid JSON in decrypted package");
     245            return false;
     246        }
     247
     248        return $package;
     249    }
     250
    291251
    292252    /**
     
    321281    }
    322282
    323     /**
    324      * Prepare for One Click Upgrade from Lite to Pro
    325      *
    326      * @return void
    327      */
    328     public function prepareForOneClickUpgrade()
    329     {
    330         AjaxWrapper::json(
    331             array(__CLASS__, 'prepareForOneClickUpgradeCallback'),
    332             'duplicator_one_click_upgrade_prepare',
    333             $_POST['nonce'],
    334             'export'
    335         );
    336     }
    337 
    338     /**
    339      * Accepts oth and file from remote endpoint, installs Pro if it's not already installed.
    340      * Prints json with error=true or success=true.
     283
     284    /**
     285     * Accepts encrypted package from remote endpoint, after validating the OTH.
    341286     *
    342287     * @return void
     
    344289    public function oneClickUpgrade()
    345290    {
    346         $othReceived = sanitize_text_field($_REQUEST["oth"]);
    347         $oth         = get_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
    348         if (self::hashOth($oth) !== $othReceived) { // Verify that oth is fine
    349             DUP_Log::trace("ERROR: Wrong oth token.");
    350             wp_send_json_error(array('message' => 'Invalid security token'));
    351         }
    352 
    353         // Verify upgrade version is not installed
    354         if (!is_dir(WP_PLUGIN_DIR . "/duplicator-pro")) {
    355             DUP_Log::trace("There is no upgrade version in plugins directory, we need to download it!");
    356 
    357             // Prepare variables.
    358             $url = esc_url_raw(
     291        try {
     292            // Get encrypted package from service
     293            $encryptedPackage = sanitize_text_field($_REQUEST["package"] ?? '');
     294
     295            if (empty($encryptedPackage)) {
     296                DUP_Log::trace("ERROR: No encrypted package received from service.");
     297                throw new Exception("No encrypted package received from service");
     298            }
     299
     300            // Get OTH data for validation
     301            $oth_data = get_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
     302
     303            if (empty($oth_data) || !is_array($oth_data)) {
     304                DUP_Log::trace("ERROR: Invalid OTH data structure.");
     305                throw new Exception("Invalid security token");
     306            }
     307
     308            // Check TTL expiration
     309            if (time() > $oth_data['expires_at']) {
     310                DUP_Log::trace("ERROR: OTH token expired.");
     311                delete_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
     312                throw new Exception("Security token expired");
     313            }
     314
     315            // Decrypt package using OTH
     316            $package = self::decryptPackage($encryptedPackage, $oth_data['token']);
     317
     318            if ($package === false) {
     319                DUP_Log::trace("ERROR: Failed to decrypt package from service.");
     320                throw new Exception("Invalid encrypted data");
     321            }
     322
     323            // Extract data from decrypted package
     324            $download_url = $package['download_url'] ?? '';
     325            $auth_token   = $package['auth_token'] ?? '';
     326
     327            if (empty($download_url)) {
     328                DUP_Log::trace("ERROR: No download URL in decrypted package.");
     329                throw new Exception("No download URL provided");
     330            }
     331
     332            // Delete OTH so it cannot be replayed (single-use)
     333            delete_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
     334
     335            // Save authentication token for Pro to use
     336            if (!empty($auth_token)) {
     337                delete_option(self::AUTH_TOKEN_KEY_OPTION_AUTO_ACTIVE);
     338                update_option(self::AUTH_TOKEN_KEY_OPTION_AUTO_ACTIVE, $auth_token);
     339                DUP_Log::trace("Authentication token saved for Pro activation.");
     340            }
     341
     342            // Validate download origin
     343            $host = wp_parse_url($download_url, PHP_URL_HOST);
     344            if (!preg_match('/(^|\\.)duplicator\\.com$/i', $host)) {
     345                DUP_Log::trace("ERROR: Invalid download origin: " . $host);
     346                throw new Exception("Invalid download origin");
     347            }
     348
     349            // Install Pro if not already installed
     350            if (!is_dir(WP_PLUGIN_DIR . "/duplicator-pro")) {
     351                DUP_Log::trace("Installing Pro using service-provided URL: " . $download_url);
     352
     353                // Request filesystem credentials
     354                $url   = esc_url_raw(add_query_arg(array('page' => 'duplicator-settings'), admin_url('admin.php')));
     355                $creds = request_filesystem_credentials($url, '', false, false, null);
     356
     357                if (false === $creds || ! \WP_Filesystem($creds)) {
     358                    wp_send_json_error(array('message' => 'File system permissions error. Please check permissions and try again.'));
     359                }
     360
     361                // Install the plugin
     362                require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
     363                remove_action('upgrader_process_complete', array('Language_Pack_Upgrader', 'async_upgrade'), 20);
     364
     365                $installer = new Plugin_Upgrader(new UpgraderSkin());
     366                $result    = $installer->install($download_url);
     367
     368                if (is_wp_error($result)) {
     369                    DUP_Log::trace("ERROR: Plugin installation failed: " . $result->get_error_message());
     370                    throw new Exception('Plugin installation failed: ' . $result->get_error_message());
     371                }
     372
     373                wp_cache_flush();
     374                $plugin_basename = $installer->plugin_info();
     375
     376                if ($plugin_basename) {
     377                    $upgradeDir = dirname($plugin_basename);
     378                    if ($upgradeDir != "duplicator-pro" && !rename(WP_PLUGIN_DIR . "/" . $upgradeDir, WP_PLUGIN_DIR . "/duplicator-pro")) {
     379                        throw new Exception('Failed renaming plugin directory');
     380                    }
     381                } else {
     382                    throw new Exception('Installation of upgrade version failed');
     383                }
     384            }
     385
     386            $newFolder = WP_PLUGIN_DIR . "/duplicator-pro";
     387            if (!is_dir($newFolder)) {
     388                DUP_Log::trace("ERROR: Duplicator Pro folder not found after installation");
     389                throw new Exception('Pro plugin installation failed - folder not created');
     390            }
     391
     392            // Deactivate Lite FIRST (critical for avoiding conflicts)
     393            deactivate_plugins(DUPLICATOR_PLUGIN_PATH . "/duplicator.php");
     394
     395            // Create activation URL for Pro
     396            $plugin          = "duplicator-pro/duplicator-pro.php";
     397            $pluginsAdminUrl = is_multisite() ? network_admin_url('plugins.php') : admin_url('plugins.php');
     398            $activateProUrl  = esc_url_raw(
    359399                add_query_arg(
    360                     array( 'page' => 'duplicator-settings' ),
    361                     admin_url('admin.php')
     400                    array(
     401                        'action' => 'activate',
     402                        'plugin' => $plugin,
     403                        '_wpnonce' => wp_create_nonce("activate-plugin_$plugin")
     404                    ),
     405                    $pluginsAdminUrl
    362406                )
    363407            );
    364408
    365             $creds = request_filesystem_credentials($url, '', false, false, null);
    366 
    367             // Check for file system permissions.
    368             if (false === $creds || ! \WP_Filesystem($creds)) {
    369                 wp_send_json_error(array('message' => 'File system permissions error. Please check permissions and try again.'));
    370             }
    371             // We do not need any extra credentials if we have gotten this far, so let's install the plugin.
    372             require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
    373 
    374             // Do not allow WordPress to search/download translations, as this will break JS output.
    375             remove_action('upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20);
    376 
    377             // Get license key and fetch download URL
    378             $license_key = get_option(self::LICENSE_KEY_OPTION_AUTO_ACTIVE);
    379             if (empty($license_key)) {
    380                 DUP_Log::trace("ERROR: No license key found for upgrade.");
    381                 wp_send_json_error(array('message' => 'No license key found for upgrade'));
    382             }
    383 
    384             // Get download URL from license API
    385             $api_params = array(
    386                 'edd_action'  => 'get_version',
    387                 'license'     => $license_key,
    388                 'item_name'   => "Duplicator Pro",
    389                 'slug'        => "duplicator-pro",
    390                 'author'      => "Snap Creek Software",
    391                 'url'         => home_url(),
    392                 'beta'        => false,
    393                 'php_version' => phpversion(),
    394                 'wp_version'  => get_bloginfo('version'),
     409            // Redirect to WordPress activation URL
     410            DUP_Log::trace("Pro installation successful. Redirecting to activation URL: " . $activateProUrl);
     411            wp_safe_redirect($activateProUrl);
     412            exit;
     413        } catch (Exception $e) {
     414            DUP_Log::trace("ERROR in oneClickUpgrade: " . $e->getMessage());
     415
     416            // Add error notice and redirect to settings page
     417            Notice::error(
     418                sprintf(__('Upgrade installation failed: %s. Please try again or install manually.', 'duplicator'), $e->getMessage()),
     419                'one_click_upgrade_failed'
    395420            );
    396421
    397             global $wp_version;
    398             $agent_string = "WordPress/" . $wp_version;
    399 
    400             $requestParam = array(
    401                 'timeout'    => 15,
    402                 'sslverify'  => true,
    403                 'user-agent' => $agent_string,
    404                 'body'       => $api_params
    405             );
    406 
    407             if (($data = self::licenseUpgradeRequests($requestParam, $requestError)) === false) {
    408                 DUP_Log::trace("ERROR: Failed to get download URL: " . $requestError['message']);
    409                 wp_send_json_error(array('message' => 'Failed to get download URL: ' . $requestError['message']));
    410             }
    411 
    412             if (empty($data->download_link)) {
    413                 DUP_Log::trace("ERROR: No download link returned from license API.");
    414                 wp_send_json_error(array('message' => 'No download link returned from license API'));
    415             }
    416 
    417             $download_url = $data->download_link;
    418 
    419             // Create the plugin upgrader with custom skin.
    420             $installer = new Plugin_Upgrader(new UpgraderSkin());
    421             $installer->install($download_url); // Use validated download URL from license API
    422 
    423             // Flush the cache and return the newly installed plugin basename.
    424             wp_cache_flush();
    425             $plugin_basename = $installer->plugin_info();
    426 
    427             if ($plugin_basename) {
    428                 $upgradeDir = dirname($plugin_basename);
    429                 if (
    430                     $upgradeDir != "duplicator-pro" &&
    431                     !rename(WP_PLUGIN_DIR . "/" . $upgradeDir, WP_PLUGIN_DIR . "/duplicator-pro")
    432                 ) {
    433                     wp_send_json_error(array('message' => 'Failed renaming plugin directory'));
    434                 }
    435             } else {
    436                 wp_send_json_error(array('message' => 'Installation of upgrade version failed'));
    437             }
    438         }
    439 
    440         wp_send_json_success(array('message' => 'Plugin exists and is ready to be activated'));
    441     }
    442 
    443     /**
    444      * Checks if duplicator-pro exists. If it does not, then it redirects to Lite settings license page.
    445      * Otherwise deactivates Lite and redirects to upgrade plugin activation link.
    446      *
    447      * @return void
    448      */
    449     public function finalizeOneClickUpgrade()
    450     {
    451         $othReceived = sanitize_text_field($_REQUEST["oth"]);
    452         $oth         = get_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
    453         $newFolder   = WP_PLUGIN_DIR . "/duplicator-pro";
    454 
    455         if (!current_user_can('activate_plugins') || (self::hashOth($oth) !== $othReceived)) {
    456             $duplicatorPage = ControllersManager::getMenuLink(
    457                 ControllersManager::PACKAGES_SUBMENU_SLUG,
    458                 null,
    459                 null,
    460                 ['action' => 'upgrade_finalize_fail']
    461             );
    462             wp_safe_redirect($duplicatorPage);
    463             exit;
    464         }
    465         delete_option(self::OPTION_KEY_ONE_CLICK_UPGRADE_OTH);
    466 
    467         if (!is_dir($newFolder)) {
    468             $licensePageUrl = ControllersManager::getMenuLink(
     422            $settingsUrl = ControllersManager::getMenuLink(
    469423                ControllersManager::SETTINGS_SUBMENU_SLUG,
    470424                'general'
    471425            );
    472             header("Location: $licensePageUrl");
    473             die();
    474         }
    475         deactivate_plugins(DUPLICATOR_PLUGIN_PATH . "/duplicator.php");
    476 
    477         $plugin          = "duplicator-pro/duplicator-pro.php";
    478         $pluginsAdminUrl = is_multisite() ? network_admin_url('plugins.php') : admin_url('plugins.php');
    479         $activateProUrl  = esc_url_raw(
    480             add_query_arg(
    481                 array(
    482                     'action' => 'activate',
    483                     'plugin' => $plugin,
    484                     '_wpnonce' => wp_create_nonce("activate-plugin_$plugin")
    485                 ),
    486                 $pluginsAdminUrl
    487             )
    488         );
    489         header("Location: $activateProUrl");
    490         die();
    491         // $activated = activate_plugin($plugin, '', true, true); // This won't work
     426
     427            wp_safe_redirect($settingsUrl);
     428            exit;
     429        }
    492430    }
    493431}
  • duplicator/trunk/src/Core/Bootstrap.php

    r3343543 r3360649  
    394394            'dup_one_click_upgrade_script_data',
    395395            array(
    396                 'nonce_one_click_upgrade'   => wp_create_nonce('duplicator_one_click_upgrade_prepare'),
     396                'nonce_generate_connect_oth' => wp_create_nonce('duplicator_generate_connect_oth'),
    397397                'ajaxurl'                   => admin_url('admin-ajax.php'),
    398                 'fail_notice_title'         => __('Failed to activate license for this website.', 'duplicator'),
     398                'fail_notice_title'         => __('Failed to connect to Duplicator Pro.', 'duplicator'),
    399399                'fail_notice_message_label' => __('Message: ', 'duplicator'),
    400                 'fail_notice_suggestion'    => __('Check the license key and try again, if the error persists proceed with manual activation.', 'duplicator'),
     400                'fail_notice_suggestion'    => __('Please try again or contact support if the issue persists.', 'duplicator'),
    401401            )
    402402        );
  • duplicator/trunk/template/admin_pages/settings/general/license.php

    r3355474 r3360649  
    5353                <hr>
    5454                <p>
    55                     <?php _e('Already purchased? Simply enter your license key below to enable <b>Duplicator PRO!</b>', 'duplicator'); ?></p>
     55                    <?php _e('Already purchased? Connect to unlock <b>Duplicator PRO!</b>', 'duplicator'); ?></p>
    5656                <p>
    57                     <input
    58                        type="text"
    59                        id="dup-settings-upgrade-license-key"
    60                        placeholder="<?php echo esc_attr__('Paste license key here', 'duplicator'); ?>" value="">
    61                        <button type="button" class="dup-btn dup-btn-md dup-btn-orange" id="dup-settings-connect-btn">
    62                            <?php echo esc_html__('Connect to Duplicator Pro', 'duplicator'); ?>
    63                        </button>
     57                    <button type="button" class="dup-btn dup-btn-md dup-btn-orange" id="dup-settings-connect-btn">
     58                        <?php echo esc_html__('Connect to Duplicator Pro', 'duplicator'); ?>
     59                    </button>
     60                </p>
     61                <p>
     62                    <small><?php esc_html_e('This opens connect.duplicator.com where you\'ll securely connect to Duplicator Pro.', 'duplicator'); ?></small>
    6463                </p>
    6564            </div>
  • duplicator/trunk/template/parts/notices/drm_multisite_msg.php

    r3328201 r3360649  
    2323<div class="dup-sub-content">
    2424    <h3 class="margin-bottom-0 margin-top-0">
    25         <?php esc_html_e('Duplicator Lite does not officially support WordPress functionality', 'duplicator-pro');?>
     25        <?php esc_html_e('Duplicator Lite does not officially support WordPress multisite functionality', 'duplicator-pro');?>
    2626    </h3>
    2727    <p>
    28     <?php echo esc_html(
    29         sprintf(
    30             _x(
    31                 'By upgrading to the Elite or Pro plans you will unlock the ability to create backups and do advanced migrations on multi-site installations!',
    32                 '1: name of pro plan, 2: name of elite plan',
    33                 'duplicator-pro'
    34             )
    35         )
    36     ); ?>
     28    <?php
     29    echo esc_html_x(
     30        'By upgrading to the Elite or Pro plans you will unlock the ability to create backups and do advanced migrations on multi-site installations!',
     31        '1: name of pro plan, 2: name of elite plan',
     32        'duplicator-pro'
     33    );
     34    ?>
    3735    </p>
    3836    <a class="button primary small target="_blank" href="<?php echo esc_url($upgradeUrl); ?>"><?php esc_html_e('Upgrade Now!', 'duplicator-pro'); ?></a>
Note: See TracChangeset for help on using the changeset viewer.