PluginProbe ʕ •ᴥ•ʔ
UpdraftPlus: WP Backup & Migration Plugin / 1.26.4
UpdraftPlus: WP Backup & Migration Plugin v1.26.4
1.26.4 1.26.3 1.9.19 1.9.25 1.9.26 1.9.30 1.9.31 1.9.32 1.9.4 1.9.40 1.9.41 1.9.42 1.9.43 1.9.44 1.9.45 1.9.46 1.9.5 1.9.50 1.9.51 1.9.60 1.9.62 1.9.63 1.9.64 1.11.12 1.4.8 1.11.15 1.4.9 1.11.17 1.5.16 1.11.18 1.5.20 1.11.2 1.5.21 1.11.20 1.5.22 1.11.23 1.5.5 1.11.24 1.5.6 1.11.25 1.5.7 1.11.26 1.5.8 1.11.27 1.5.9 1.11.28 1.6.1 1.11.3 1.6.17 1.11.4 1.6.2 1.11.5 1.6.46 1.11.8 1.7.0 1.11.9 1.7.1 1.12.0 1.7.18 1.12.1 1.7.20 1.12.12 1.7.3 1.12.13 1.7.34 1.12.15 1.7.35 1.12.17 1.7.39 1.12.2 1.7.40 1.12.20 1.7.41 1.12.23 1.8.1 1.12.24 1.8.11 1.12.25 1.8.12 1.12.28 1.8.13 1.12.29 1.8.2 1.12.30 1.8.5 1.12.32 1.8.8 1.12.34 1.9.0 1.12.35 1.9.13 1.12.37 1.9.15 1.12.39 1.9.17 1.12.4 1.12.40 1.12.6 1.13.1 1.13.11 1.13.12 1.13.15 1.13.16 1.13.2 1.13.3 1.13.4 1.13.5 1.13.6 1.13.7 1.13.8 1.13.9 1.14.10 1.14.11 1.14.12 1.14.13 1.14.2 1.14.3 1.14.4 1.14.5 1.14.7 1.14.9 1.15.0 1.15.2 1.15.3 1.15.5 1.15.6 1.15.7 1.16.0 1.16.10 1.16.11 1.16.12 1.16.13 1.16.14 1.16.15 1.16.16 1.16.17 1.16.20 1.16.21 1.16.22 1.16.23 1.16.24 1.16.25 1.16.26 1.16.28 1.16.29 1.16.32 1.16.34 1.16.35 1.16.36 1.16.37 1.16.4 1.16.40 1.16.41 1.16.42 1.16.43 1.16.44 1.16.45 1.16.46 1.16.47 1.16.48 1.16.49 1.16.5 1.16.50 1.16.51 1.16.53 1.16.55 1.16.56 1.16.59 1.16.6 1.16.60 1.16.61 1.16.62 1.16.63 1.16.64 1.16.65 1.16.66 1.16.67 1.16.68 1.16.69 1.16.7 1.16.8 1.16.9 1.2.0 1.2.1 1.2.10 1.2.11 1.2.12 1.2.14 1.2.15 1.2.16 1.2.17 1.2.19 1.2.2 1.2.20 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.33 1.2.35 1.2.36 1.2.38 1.2.39 1.2.4 1.2.40 1.2.41 1.2.42 1.2.43 1.2.44 1.2.45 1.2.46 1.2.5 1.2.7 1.2.8 1.2.9 1.22.1 1.22.10 1.22.11 1.22.12 1.22.14 1.22.15 1.22.16 1.22.17 1.22.18 1.22.19 1.22.20 1.22.21 1.22.22 1.22.23 1.22.24 1.22.3 1.22.4 1.22.5 1.22.6 1.22.7 1.22.8 1.22.9 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.15 1.23.16 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.1 1.24.10 1.24.11 1.24.12 1.24.2 trunk 1.24.3 0.7.4 1.24.4 0.7.7 1.24.5 0.8.28 1.24.6 0.8.29 1.24.7 0.8.30 1.24.8 0.8.31 1.24.9 0.8.32 1.25.1 0.8.33 1.25.2 0.8.36 1.25.3 0.8.37 1.25.5 0.8.50 1.25.6 0.8.51 1.25.7 0.9.1 1.25.8 0.9.10 1.25.9 0.9.11 1.26.1 0.9.12 1.26.2 0.9.2 1.3.10 0.9.20 1.3.12 0.9.21 1.3.14 0.9.22 1.3.15 1.0.10 1.3.17 1.0.11 1.3.18 1.0.12 1.3.19 1.0.15 1.3.2 1.0.16 1.3.20 1.0.18 1.3.22 1.0.20 1.3.23 1.0.3 1.3.24 1.0.4 1.3.25 1.0.5 1.3.3 1.0.6 1.3.4 1.0.7 1.3.6 1.0.8 1.3.7 1.0.9 1.3.8 1.1.0 1.3.9 1.1.10 1.4.0 1.1.11 1.4.10 1.1.12 1.4.11 1.1.13 1.4.12 1.1.14 1.4.13 1.1.15 1.4.14 1.1.16 1.4.15 1.1.17 1.4.2 1.1.2 1.4.27 1.1.3 1.4.28 1.1.5 1.4.29 1.1.6 1.4.30 1.1.8 1.4.4 1.1.9 1.4.48 1.10.1 1.4.5 1.10.3 1.4.6 1.11.1 1.4.7
updraftplus / includes / updraft-admin-common.js
updraftplus / includes Last commit date
Dropbox2 3 weeks ago Google 3 weeks ago blockui 3 weeks ago checkout-embed 3 weeks ago cloudfiles 3 weeks ago handlebars 1 month ago images 9 years ago jquery-ui.dialog.extended 3 weeks ago jquery.serializeJSON 5 years ago jstree 1 year ago labelauty 3 weeks ago pcloud 3 weeks ago select2 1 year ago tether 6 years ago tether-shepherd 7 years ago updraftclone 3 weeks ago S3.php 3 weeks ago S3compat.php 3 weeks ago cacert.pem 2 years ago class-backup-history.php 1 month ago class-commands.php 3 weeks ago class-database-utility.php 1 month ago class-filesystem-functions.php 1 month ago class-http-error-descriptions.php 2 years ago class-job-scheduler.php 3 years ago class-manipulation-functions.php 1 month ago class-partialfileservlet.php 3 weeks ago class-remote-send.php 3 weeks ago class-search-replace.php 1 month ago class-semaphore.php 3 weeks ago class-storage-methods-interface.php 1 month ago class-updraft-dashboard-news.php 1 month ago class-updraft-semaphore.php 4 years ago class-updraftcentral-updraftplus-commands.php 3 years ago class-updraftplus-deactivation.php 1 month ago class-updraftplus-encryption.php 1 month ago class-wpadmin-commands.php 1 month ago class-zip.php 1 month ago ftp.class.php 2 months ago get-cpanel-quota-usage.pl 12 years ago google-extensions.php 1 month ago jquery-ui.custom-v1.11.4-1-26-4.min.css 3 weeks ago jquery-ui.custom-v1.11.4-1-26-4.min.css.map 3 weeks ago jquery-ui.custom-v1.11.4.css 3 years ago jquery-ui.custom-v1.12.1-1-26-4.min.css 3 weeks ago jquery-ui.custom-v1.12.1-1-26-4.min.css.map 3 weeks ago jquery-ui.custom-v1.12.1.css 3 years ago migrator-lite.php 1 month ago updraft-admin-common-1-26-4.min.js 3 weeks ago updraft-admin-common.js 3 weeks ago updraft-restorer-skin-compatibility.php 6 years ago updraft-restorer-skin.php 3 years ago updraftcentral.php 1 year ago updraftplus-clone.php 1 year ago updraftplus-login.php 7 months ago updraftplus-notices.php 1 month ago updraftplus-tour.php 1 month ago updraftvault.php 3 years ago
updraft-admin-common.js
6503 lines
1 /**
2 * Send an action over AJAX. A wrapper around jQuery.ajax. In future, all consumers can be reviewed to simplify some of the options, where there is historical cruft.
3 * N.B. updraft_iframe_modal() below uses the AJAX URL for the iframe's src attribute
4 *
5 * @param {string} action - the action to send
6 * @param {*} data - data to send
7 * @param {Function} callback - if specified, will be called with the results
8 * @param {object} options -further options. Relevant properties include:
9 * - [json_parse=true] - whether to JSON parse the results
10 * - [alert_on_error=true] - whether to show an alert box if there was a problem (otherwise, suppress it)
11 * - [action='updraft_ajax'] - what to send as the action parameter on the AJAX request (N.B. action parameter to this function goes as the 'subaction' parameter on the AJAX request)
12 * - [nonce=updraft_credentialtest_nonce] - the nonce value to send.
13 * - [nonce_key='nonce'] - the key value for the nonce field
14 * - [timeout=null] - set a timeout after this number of seconds (or if null, none is set)
15 * - [async=true] - control whether the request is asynchronous (almost always wanted) or blocking (would need to have a specific reason)
16 * - [type='POST'] - GET or POST
17 */
18 function updraft_send_command(action, data, callback, options) {
19
20 default_options = {
21 json_parse: true,
22 alert_on_error: true,
23 action: 'updraft_ajax',
24 nonce: updraft_credentialtest_nonce,
25 nonce_key: 'nonce',
26 timeout: null,
27 async: true,
28 type: 'POST'
29 }
30
31 if ('undefined' === typeof options) options = {};
32
33 for (var opt in default_options) {
34 if (!options.hasOwnProperty(opt)) { options[opt] = default_options[opt]; }
35 }
36
37 var ajax_data = {
38 action: options.action,
39 subaction: action,
40 };
41
42 ajax_data[options.nonce_key] = options.nonce;
43
44 // TODO: Once all calls are routed through here, change the listener in admin.php to always take the data from the 'data' attribute, instead of in the naked $_POST/$_GET
45 if (typeof data == 'object') {
46 for (var attrname in data) { ajax_data[attrname] = data[attrname]; }
47 } else {
48 ajax_data.action_data = data;
49 }
50
51 var ajax_opts = {
52 type: options.type,
53 url: ajaxurl,
54 data: ajax_data,
55 success: function(response, status) {
56 if (options.json_parse) {
57 try {
58 var resp = ud_parse_json(response);
59 } catch (e) {
60 if ('function' == typeof options.error_callback) {
61 return options.error_callback(response, e, 502, resp);
62 } else {
63 console.log(e);
64 console.log(response);
65 if (options.alert_on_error) {
66 if ('string' === typeof response && response.match(/security\scheck\s?/i)) response += ' (' + updraftlion.expired_tokens + ' ' + updraftlion.reload_page + ')';
67 alert(updraftlion.unexpectedresponse+' '+response);
68 }
69 return;
70 }
71 }
72 if (resp.hasOwnProperty('fatal_error')) {
73 if ('function' == typeof options.error_callback) {
74 // 500 is internal server error code
75 return options.error_callback(response, status, 500, resp);
76 } else {
77 console.error(resp.fatal_error_message);
78 if (options.alert_on_error) { alert(resp.fatal_error_message); }
79 return false;
80 }
81 }
82 if ('function' == typeof callback) callback(resp, status, response);
83 } else {
84 if ('function' == typeof callback) callback(response, status);
85 }
86 },
87 error: function(response, status, error_code) {
88 if ('function' == typeof options.error_callback) {
89 options.error_callback(response, status, error_code);
90 } else {
91 console.log("updraft_send_command: error: "+status+" ("+error_code+")");
92 console.log(response);
93 }
94 },
95 dataType: 'text',
96 async: options.async
97 };
98
99 if (null != options.timeout) { ajax_opts.timeout = options.timeout; }
100
101 jQuery.ajax(ajax_opts);
102
103 }
104
105 /**
106 * Opens the dialog box for confirmation of whether to delete a backup, plus options if relevant
107 *
108 * @param {string} key - The UNIX timestamp of the backup
109 * @param {string} nonce - The backup job ID
110 * @param {boolean} showremote - Whether or not to show the "also delete from remote storage?" checkbox
111 */
112 function updraft_delete(key, nonce, showremote) {
113 jQuery('#updraft_delete_timestamp').val(key);
114 jQuery('#updraft_delete_nonce').val(nonce);
115 if (showremote) {
116 jQuery('#updraft-delete-remote-section, #updraft_delete_remote').prop('disabled', false).show();
117 } else {
118 jQuery('#updraft-delete-remote-section, #updraft_delete_remote').hide().attr('disabled','disabled');
119 }
120 if (key.indexOf(',') > -1) {
121 jQuery('#updraft_delete_question_singular').hide();
122 jQuery('#updraft_delete_question_plural').show();
123 } else {
124 jQuery('#updraft_delete_question_plural').hide();
125 jQuery('#updraft_delete_question_singular').show();
126 }
127 jQuery('#updraft-delete-modal').dialog('open');
128 }
129
130 function updraft_remote_storage_tab_activation(the_method){
131 jQuery('.updraftplusmethod').not('.error').hide();
132 jQuery('.remote-tab').data('active', false);
133 jQuery('.remote-tab').removeClass('nav-tab-active');
134 jQuery('.updraftplusmethod.'+the_method).show();
135 jQuery('.remote-tab-'+the_method).data('active', true);
136 jQuery('.remote-tab-'+the_method).addClass('nav-tab-active');
137 }
138
139 /**
140 * Scroll to a specific remote storage configuration by adding the #remote-storage-{method_name} anchor hash to the URL.
141 */
142 function updraft_scroll_to_remote_storage_config() {
143 var url_hash_match = window.location.hash.match(/#remote-storage-([A-Za-z]+)/);
144 if (url_hash_match && updraftlion.remote_storage_methods[url_hash_match[1]]) {
145 if (jQuery('.updraft_servicecheckbox').hasClass('multi')) {
146 updraft_remote_storage_tab_activation(url_hash_match[1]);
147 }
148
149 document.getElementById('remote-storage-'+url_hash_match[1]).scrollIntoView();
150 }
151 }
152
153 /**
154 * Set up the remote storage configuration link to handle the click event. When it is clicked from the UDP settings page, we need to reopen the settings tab before scrolling to the remote storage configuration section.
155 */
156 function updraft_setup_remote_storage_config_link() {
157 jQuery('.updraftplus-remote-storage-link').on('click', function(e) {
158 if ('settings' == updraftlion.tab) {
159 e.preventDefault();
160 updraft_open_main_tab('settings');
161 window.location.href = jQuery(this).attr('href');
162 updraft_scroll_to_remote_storage_config();
163 }
164 });
165 }
166
167 /**
168 * Set the email report's setting to a different interface when email storage is selected
169 *
170 * @param {boolean} value True to set the email report setting to another interface, false otherwise
171 */
172 function set_email_report_storage_interface(value) {
173 jQuery('#cb_not_email_storage_label').css('display', true === value ? 'none' : 'inline');
174 jQuery('#cb_email_storage_label').css('display', true === value ? 'inline' : 'none');
175 if (true === value) {
176 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').on('click', function(e) {
177 return false;
178 });
179 } else {
180 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').prop("onclick", null).off("click");
181 }
182 if (!jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').is(':checked')) {
183 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').prop('checked', value);
184 }
185 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').prop('disabled', value);
186
187 var updraft_email = jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon input#updraft_email').val();
188
189 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon label.email_report input[type="hidden"]').remove();
190 if (true === value) {
191 jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon label.email_report input#updraft_email').after('<input type="hidden" name="updraft_email" value="'+updraft_email+'">');
192 }
193 }
194
195 /**
196 * Check how many cron jobs are overdue, and display a message if it is several (as determined by the back-end)
197 */
198 function updraft_check_overduecrons() {
199 updraft_send_command('check_overdue_crons', null, function(response) {
200 if (response && response.hasOwnProperty('m') && Array.isArray(response.m)) {
201 for (var i in response.m) {
202 jQuery('#updraft-insert-admin-warning').append(response.m[i]);
203 }
204 }
205 }, { alert_on_error: false });
206 }
207
208 function updraft_remote_storage_tabs_setup() {
209
210 var anychecked = 0;
211 var set = jQuery('.updraft_servicecheckbox:checked');
212
213 jQuery(set).each(function(ind, obj) {
214 var ser = jQuery(obj).val();
215
216 jQuery('.error.updraftplusmethod.'+ser).show();
217
218 if (jQuery(obj).attr('id') != 'updraft_servicecheckbox_none') {
219 anychecked++;
220 }
221
222 jQuery('.remote-tab-'+ser).show();
223 if (ind == jQuery(set).length-1) {
224 updraft_remote_storage_tab_activation(ser);
225 }
226 });
227
228 if (anychecked > 0) {
229 jQuery('.updraftplusmethod.none').hide();
230 jQuery('#remote_storage_tabs').show();
231 } else {
232 jQuery('#remote_storage_tabs').hide();
233 }
234
235 // To allow labelauty remote storage buttons to be used with keyboard
236 jQuery(document).on('keyup', function(event) {
237 if (32 === event.keyCode || 13 === event.keyCode) {
238 if (jQuery(document.activeElement).is("input.labelauty + label")) {
239 var for_box = jQuery(document.activeElement).attr("for");
240 if (for_box) {
241 jQuery("#"+for_box).trigger('change');
242 }
243 }
244 }
245 });
246
247 jQuery('.updraft_servicecheckbox').on('change', function() {
248 var sclass = jQuery(this).attr('id');
249 if ('updraft_servicecheckbox_' == sclass.substring(0,24)) {
250 var serv = sclass.substring(24);
251 if (null != serv && '' != serv) {
252 if (jQuery(this).is(':checked')) {
253 anychecked++;
254 jQuery('.error.updraftplusmethod.'+serv).show();
255 jQuery('.remote-tab-'+serv).fadeIn();
256 updraft_remote_storage_tab_activation(serv);
257 if (jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon').length && 'email' === serv) set_email_report_storage_interface(true);
258 } else {
259 anychecked--;
260 jQuery('.error.updraftplusmethod.'+serv).hide();
261 jQuery('.remote-tab-'+serv).hide();
262 // Check if this was the active tab, if yes, switch to another
263 if (jQuery('.remote-tab-'+serv).data('active') == true) {
264 updraft_remote_storage_tab_activation(jQuery('.remote-tab:visible').last().attr('name'));
265 }
266 if (jQuery('#updraft-navtab-settings-content #updraft_report_row_no_addon').length && 'email' === serv) set_email_report_storage_interface(false);
267 }
268 }
269 }
270
271 if (anychecked <= 0) {
272 jQuery('.updraftplusmethod.none').fadeIn();
273 jQuery('#remote_storage_tabs').hide();
274 } else {
275 jQuery('.updraftplusmethod.none').hide();
276 jQuery('#remote_storage_tabs').show();
277 }
278 });
279
280 // Add stuff for free version
281 jQuery('.updraft_servicecheckbox:not(.multi)').on('change', function() {
282 set_email_report_storage_interface(false);
283 var svalue = jQuery(this).attr('value');
284 if (jQuery(this).is(':not(:checked)')) {
285 jQuery('.updraftplusmethod.'+svalue).hide();
286 jQuery('.updraftplusmethod.none').fadeIn();
287 } else {
288 jQuery('.updraft_servicecheckbox').not(this).prop('checked', false);
289 if ('email' === svalue) {
290 set_email_report_storage_interface(true);
291 }
292 }
293 });
294
295 var servicecheckbox = jQuery('.updraft_servicecheckbox');
296 if (typeof servicecheckbox.labelauty === 'function') {
297 servicecheckbox.labelauty();
298 var $vault_label = jQuery('label[for=updraft_servicecheckbox_updraftvault]');
299 var $vault_info = jQuery('<div class="udp-info"><span class="info-trigger">?</span><div class="info-content-wrapper"><div class="info-content">'+updraftlion.updraftvault_info+'</div></div></div>');
300 $vault_label.append($vault_info);
301 }
302
303 }
304
305 /**
306 * Carries out a remote storage test
307 *
308 * @param {string} method - The identifier for the remote storage
309 * @param {callback} result_callback - A callback function to be called with the result
310 * @param {string} instance_id - The particular instance (if any) of the remote storage to be tested (for methods supporting multiple instances)
311 */
312 function updraft_remote_storage_test(method, result_callback, instance_id) {
313
314 var $the_button;
315 var settings_selector;
316
317 if (instance_id) {
318 $the_button = jQuery('#updraft-'+method+'-test-'+instance_id);
319 settings_selector = '.updraftplusmethod.'+method+'-'+instance_id;
320 } else {
321 $the_button = jQuery('#updraft-'+method+'-test');
322 settings_selector = '.updraftplusmethod.'+method;
323 }
324
325 var method_label = $the_button.data('method_label');
326
327 $the_button.html(updraftlion.testing_settings.replace('%s', method_label));
328
329 var data = {
330 method: method
331 };
332
333 // Add the other items to the data object. The expert mode settings are for the generic SSL options.
334 jQuery('#updraft-navtab-settings-content '+settings_selector+' input[data-updraft_settings_test], #updraft-navtab-settings-content .expertmode input[data-updraft_settings_test]').each(function(index, item) {
335 var item_key = jQuery(item).data('updraft_settings_test');
336 var input_type = jQuery(item).attr('type');
337 if (!item_key) { return; }
338 if (!input_type) {
339 console.log("UpdraftPlus: settings test input item with no type found");
340 console.log(item);
341 // A default
342 input_type = 'text';
343 }
344 var value = null;
345 if ('checkbox' == input_type) {
346 value = jQuery(item).is(':checked') ? 1 : 0;
347 } else if ('text' == input_type || 'password' == input_type || 'hidden' == input_type) {
348 value = jQuery(item).val();
349 } else {
350 console.log("UpdraftPlus: settings test input item with unrecognised type ("+input_type+") found");
351 console.log(item);
352 }
353 data[item_key] = value;
354 });
355 // Data from any text areas or select drop-downs
356 jQuery('#updraft-navtab-settings-content '+settings_selector+' textarea[data-updraft_settings_test], #updraft-navtab-settings-content '+settings_selector+' select[data-updraft_settings_test]').each(function(index, item) {
357 var item_key = jQuery(item).data('updraft_settings_test');
358 data[item_key] = jQuery(item).val();
359 });
360
361 updraft_send_command('test_storage_settings', data, function(response, status) {
362 $the_button.html(updraftlion.test_settings.replace('%s', method_label));
363 if ('undefined' !== typeof result_callback && false != result_callback) {
364 result_callback = result_callback.call(this, response, status, data);
365 }
366 if ('undefined' !== typeof result_callback && false === result_callback) {
367 response.output = response.output.replaceAll('&quot;', '"');
368 alert(updraftlion.settings_test_result.replace('%s', method_label)+' '+response.output);
369 if (response.hasOwnProperty('data')) {
370 console.log(response.data);
371 }
372 }
373 }, { error_callback: function(response, status, error_code, resp) {
374 $the_button.html(updraftlion.test_settings.replace('%s', method_label));
375 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
376 console.error(resp.fatal_error_message);
377 alert(resp.fatal_error_message);
378 } else {
379 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
380 console.log(error_message);
381 alert(error_message);
382 console.log(response);
383 }
384 }
385 });
386 }
387
388 function backupnow_whichfiles_checked(onlythesefileentities){
389 jQuery('#backupnow_includefiles_moreoptions input[type="checkbox"]').each(function(index) {
390 if (!jQuery(this).is(':checked')) { return; }
391 var name = jQuery(this).attr('name');
392 if (name.substring(0, 16) != 'updraft_include_') { return; }
393 var entity = name.substring(16);
394 if (onlythesefileentities != '') { onlythesefileentities += ','; }
395 onlythesefileentities += entity;
396 });
397 // console.log(onlythesefileentities);
398 return onlythesefileentities;
399 }
400
401 /**
402 * A method to get all the selected table values from the backup now modal
403 *
404 * @param {string} onlythesetableentities an empty string to append values to
405 *
406 * @return {string} a string that contains the values of all selected table entities and the database the belong to
407 */
408 function backupnow_whichtables_checked(onlythesetableentities){
409 var send_list = false;
410 jQuery('#backupnow_database_moreoptions .updraft_db_entity').each(function(index) {
411 if (!jQuery(this).is(':checked')) { send_list = true; return; }
412 if (jQuery(this).is(':checked') && jQuery(this).data('non_wp_table')) { send_list = true; return; }
413 });
414
415 onlythesetableentities = jQuery("input[name^='updraft_include_tables_']").serializeArray();
416
417 if (send_list) {
418 return onlythesetableentities;
419 } else {
420 return true;
421 }
422 }
423
424 function updraft_deleteallselected() {
425 var howmany = 0;
426 var remote_exists = 0;
427 var key_all = '';
428 var nonce_all = '';
429 var remote_all = 0;
430 jQuery('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row.backuprowselected').each(function(index) {
431 howmany++;
432 var nonce = jQuery(this).data('nonce');
433 if (nonce_all) { nonce_all += ','; }
434 nonce_all += nonce;
435 var key = jQuery(this).data('key');
436 if (key_all) { key_all += ','; }
437 key_all += key;
438 var has_remote = jQuery(this).find('.updraftplus-remove').data('hasremote');
439 if (has_remote) remote_all++;
440 });
441 updraft_delete(key_all, nonce_all, remote_all);
442 }
443
444 /**
445 * Open main tab which is given as argument
446 *
447 * @param {string} active_tab_key A tab key which you would like to open
448 */
449 function updraft_open_main_tab(active_tab_key) {
450 updraftlion.main_tabs_keys.forEach(function(tab_key) {
451 if (active_tab_key == tab_key) {
452 jQuery('#updraft-navtab-' + tab_key + '-content').show();
453 jQuery('#updraft-navtab-' + tab_key).addClass('nav-tab-active');
454 } else {
455 jQuery('#updraft-navtab-' + tab_key + '-content').hide();
456 jQuery('#updraft-navtab-' + tab_key).removeClass('nav-tab-active');
457 }
458 updraft_console_focussed_tab = active_tab_key;
459 });
460 }
461
462 /**
463 * Open an existing backups tab
464 *
465 * @param {Boolean} toggly Whether switch on updraft_historytimer or not
466 */
467 function updraft_openrestorepanel(toggly) {
468 // jQuery('.download-backups').slideDown(); updraft_historytimertoggle(1); jQuery('html,body').animate({scrollTop: jQuery('#updraft_lastlogcontainer').offset().top},'slow');
469 updraft_historytimertoggle(toggly);
470 updraft_open_main_tab('backups');
471 }
472
473 function updraft_delete_old_dirs() {
474 return true;
475 }
476
477 function updraft_initiate_restore(whichset) {
478 jQuery('#updraft-navtab-backups-content .updraft_existing_backups .restore-button button[data-backup_timestamp="'+whichset+'"]').trigger('click');
479 }
480
481 function updraft_restore_setoptions(entities) {
482 var howmany = 0;
483 jQuery('input[name="updraft_restore[]"]').each(function(x,y) {
484 var entity = jQuery(y).val();
485 var epat = '\/'+entity+'=([0-9,]+)';
486 var eregex = new RegExp(epat);
487 var ematch = entities.match(eregex);
488 if (ematch) {
489 jQuery(y).prop('disabled', false).data('howmany', ematch[1]).parent().show();
490 howmany++;
491 if ('db' == entity) { howmany += 4.5;}
492 if (jQuery(y).is(':checked')) {
493 // This element may or may not exist. The purpose of explicitly calling show() is that Firefox, when reloading (including via forwards/backwards navigation) will remember checkbox states, but not which DOM elements were showing/hidden - which can result in some being hidden when they should be shown, and the user not seeing the options that are/are not checked.
494 jQuery('#updraft_restorer_'+entity+'options').show();
495 }
496 } else {
497 jQuery(y).attr('disabled','disabled').parent().hide();
498 }
499 });
500 var cryptmatch = entities.match(/dbcrypted=1/);
501 if (cryptmatch) {
502 jQuery('#updraft_restore_db').data('encrypted', 1);
503 jQuery('.updraft_restore_crypteddb').show();
504 } else {
505 jQuery('#updraft_restore_db').data('encrypted', 0);
506 jQuery('.updraft_restore_crypteddb').hide();
507 }
508 jQuery('#updraft_restore_db').trigger('change');
509 var dmatch = entities.match(/meta_foreign=([12])/);
510 if (dmatch) {
511 jQuery('#updraft_restore_meta_foreign').val(dmatch[1]);
512 } else {
513 jQuery('#updraft_restore_meta_foreign').val('0');
514 }
515 }
516
517 /**
518 * Open the 'Backup Now' dialog box
519 *
520 * @param {string} type - the backup type; either "new" or "incremental"
521 */
522 function updraft_backup_dialog_open(type) {
523
524 type = ('undefined' === typeof type) ? 'new' : type;
525
526 if (0 == jQuery('#updraftplus_incremental_backup_link').data('incremental') && 'incremental' == type) {
527 jQuery('#updraft-backupnow-modal .incremental-free-only').show();
528 type = 'new';
529 } else {
530 jQuery('#updraft-backupnow-modal .incremental-backups-only, #updraft-backupnow-modal .incremental-free-only').hide();
531 }
532
533 jQuery('#backupnow_includefiles_moreoptions').hide();
534 if (!updraft_settings_form_changed || window.confirm(updraftlion.unsavedsettingsbackup)) {
535 jQuery('#backupnow_label').val('');
536 if ('incremental' == type) {
537 update_file_entities_checkboxes(true, impossible_increment_entities);
538 jQuery('#backupnow_includedb').prop('checked', false);
539 jQuery('#backupnow_includefiles').prop('checked', true);
540 jQuery('#backupnow_includefiles_label').text(updraftlion.files_incremental_backup);
541 jQuery('#updraft-backupnow-modal .new-backups-only').hide();
542 jQuery('#updraft-backupnow-modal .incremental-backups-only').show();
543 } else {
544 update_file_entities_checkboxes(false, impossible_increment_entities);
545 jQuery('#backupnow_includedb').prop('checked', true);
546 jQuery('#backupnow_includefiles_label').text(updraftlion.files_new_backup);
547 jQuery('#updraft-backupnow-modal .new-backups-only').show();
548 jQuery('#updraft-backupnow-modal .incremental-backups-only').hide();
549 }
550 jQuery('#updraft-backupnow-modal').data('backup-type', type);
551 jQuery('#updraft-backupnow-modal').dialog('open');
552 }
553 }
554 /**
555 * Open the 'Backup Now' dialog box
556 *
557 * @param {string} type - the backup type; either "new" or "incremental"
558 */
559 /**
560 * This function will enable and disable the file entity options depending on what entities increments can be added to and if this is a new backup or not.
561 *
562 * @param {boolean} incremental - a boolean to indicate if this is an incremental backup or not
563 * @param {array} entities - an array of entities to disable
564 */
565 function update_file_entities_checkboxes(incremental, entities) {
566 if (incremental) {
567 jQuery(entities).each(function (index, entity) {
568 jQuery('#backupnow_files_updraft_include_' + entity).prop('checked', false);
569 jQuery('#backupnow_files_updraft_include_' + entity).prop('disabled', true);
570 });
571 } else {
572 jQuery('#backupnow_includefiles_moreoptions input[type="checkbox"]').each(function (index) {
573 var name = jQuery(this).attr('name');
574 if (name.substring(0, 16) != 'updraft_include_') { return; }
575 var entity = name.substring(16);
576 if (typeof jQuery('#backupnow_files_updraft_include_' + entity).data('force_disabled') == 'undefined') {
577 jQuery('#backupnow_files_updraft_include_' + entity).prop('disabled', false);
578 if (jQuery('#updraft_include_' + entity).is(':checked')) {
579 jQuery('#backupnow_files_updraft_include_' + entity).prop('checked', true);
580 }
581 } else {
582 jQuery('#backupnow_files_updraft_include_' + entity).prop('disabled', true);
583 jQuery('#backupnow_files_updraft_include_' + entity).prop('checked', false);
584 }
585 });
586 }
587 }
588
589 var onlythesefileentities = backupnow_whichfiles_checked('');
590 if ('' == onlythesefileentities) {
591 jQuery("#backupnow_includefiles_moreoptions").show();
592 } else {
593 jQuery("#backupnow_includefiles_moreoptions").hide();
594 }
595
596 var impossible_increment_entities;
597 var updraft_restore_stage = 1;
598 var lastlog_lastmessage = "";
599 var lastlog_lastdata = "";
600 var lastlog_jobs = "";
601 // var lastlog_sdata = { action: 'updraft_ajax', subaction: 'lastlog' };
602 var updraft_activejobs_nextupdate = (new Date).getTime() + 1000;
603 // Bits: main tab displayed (1); restore dialog open (uses downloader) (2); tab not visible (4)
604 var updraft_page_is_visible = 1;
605 var updraft_console_focussed_tab = updraftlion.tab;
606 var php_max_input_vars = 0;
607 var skipped_db_scan = 0;
608
609 var updraft_settings_form_changed = false;
610 var save_button_added = false;
611
612 function load_save_button() {
613 if (updraft_settings_form_changed && !save_button_added) {
614 save_button_added = true;
615 jQuery('#updraft-navtab-settings-content').prepend('<input style="position:fixed;top:46px; right:20px;z-index: 999999;" type="button" class="button-primary" id="updraftplus-floating-settings-save" value="'+updraftlion.save_changes+'">');
616
617 // The click event for the save button will be registered every time the button is created. We need to use the 'one' method instead of the 'on' method to make sure the click event is executed only once.
618 jQuery("#updraft-navtab-settings-content").one('click', '#updraftplus-floating-settings-save', function() {
619 jQuery("#updraftplus-settings-save").trigger('click');
620 jQuery("#updraftplus-floating-settings-save").remove();
621 save_button_added = false;
622 });
623
624 jQuery("#updraftplus-settings-save").one('click', function() {
625 jQuery("#updraftplus-floating-settings-save").remove();
626 save_button_added = false;
627 });
628
629 }
630 }
631 window.onbeforeunload = function(e) {
632 if (updraft_settings_form_changed) return updraftlion.unsavedsettings;
633 }
634
635 /**
636 * N.B. This function works on both the UD settings page and elsewhere
637 *
638 * @param {boolean} firstload Check if this is first load
639 */
640 function updraft_check_page_visibility(firstload) {
641 if ('hidden' == document["visibilityState"]) {
642 updraft_page_is_visible = 0;
643 } else {
644 updraft_page_is_visible = 1;
645 if (1 !== firstload) {
646 if (jQuery('#updraft-navtab-backups-content').length) {
647 updraft_activejobs_update(true);
648 }
649 }
650 };
651 }
652
653 // See http://caniuse.com/#feat=pagevisibility for compatibility (we don't bother with prefixes)
654 if (typeof document.hidden !== "undefined") {
655 document.addEventListener('visibilitychange', function() {
656 updraft_check_page_visibility(0);}, false);
657 }
658
659 updraft_check_page_visibility(1);
660
661 var updraft_poplog_log_nonce;
662 var updraft_poplog_log_pointer = 0;
663 var updraft_poplog_lastscroll = -1;
664 var updraft_last_forced_jobid = -1;
665 var updraft_last_forced_resumption = -1;
666 var updraft_last_forced_when = -1;
667
668 var updraft_backupnow_nonce = '';
669 var updraft_activejobslist_backupnownonce_only = 0;
670 var updraft_inpage_hasbegun = 0;
671 var updraft_activejobs_update_timer;
672 var updraft_aborted_jobs = [];
673 var updraft_clone_jobs = [];
674 var temporary_clone_timeout;
675
676 // Manage backups table selection
677 var updraft_backups_selection = {};
678
679 // @codingStandardsIgnoreStart - to keep the doc blocks, as they're considered block comments by phpcs
680 (function($) {
681 /**
682 * Toggle row seletion
683 *
684 * @param {HTMLDomElement|jQuery} el - row element
685 */
686 updraft_backups_selection.toggle = function(el) {
687 var $el = $(el);
688 if ($el.is('.backuprowselected')) {
689 this.deselect(el);
690 } else {
691 this.select(el);
692 }
693 };
694
695 /**
696 * Select row
697 *
698 * @param {HTMLDomElement|jQuery} el - row element
699 */
700 updraft_backups_selection.select = function(el) {
701 $(el).addClass('backuprowselected');
702 $(el).find('.backup-select input').prop('checked', true);
703 this.checkSelectionStatus();
704 };
705
706 /**
707 * Deselect row
708 *
709 * @param {HTMLDomElement|jQuery} el - row element
710 */
711 updraft_backups_selection.deselect = function(el) {
712 $(el).removeClass('backuprowselected');
713 $(el).find('.backup-select input').prop('checked', false);
714 this.checkSelectionStatus();
715 };
716
717 /**
718 * Select all rows
719 */
720 updraft_backups_selection.selectAll = function() {
721 $('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').each(function(index, el) {
722 updraft_backups_selection.select(el);
723 })
724 };
725
726 /**
727 * Deselect all rows
728 */
729 updraft_backups_selection.deselectAll = function() {
730 $('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').each(function(index, el) {
731 updraft_backups_selection.deselect(el);
732 })
733 };
734
735 /**
736 * Actions after a row selection/deselection
737 */
738 updraft_backups_selection.checkSelectionStatus = function() {
739 var num_rows = $('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').length;
740 var num_selected = $('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row.backuprowselected').length;
741 // toggles actions upon seleted items
742 if (num_selected > 0) {
743 $('#ud_massactions').addClass('active');
744 $('.js--deselect-all-backups, .js--delete-selected-backups').prop('disabled', false);
745 } else {
746 $('#ud_massactions').removeClass('active');
747 $('.js--deselect-all-backups, .js--delete-selected-backups').prop('disabled', true);
748 }
749 // if all rows are selected, check the headind's checkbox
750 if (num_rows === num_selected) {
751 $('#cb-select-all').prop('checked', true);
752 } else {
753 $('#cb-select-all').prop('checked', false);
754 }
755 // if no backups, hide massaction
756 if (!num_rows) {
757 $('#ud_massactions').hide();
758 } else {
759 $('#ud_massactions').show();
760 }
761 }
762
763 /**
764 * Multiple range selection
765 *
766 * @param {HTMLDomElement|jQuery} el - row element
767 */
768 updraft_backups_selection.selectAllInBetween = function(el) {
769 var idx_start = this.firstMultipleSelectionIndex, idx_end = el.rowIndex-1;
770 if (this.firstMultipleSelectionIndex > el.rowIndex-1) {
771 idx_start = el.rowIndex-1; idx_end = this.firstMultipleSelectionIndex;
772 }
773 for (var i=idx_start; i<=idx_end; i++) {
774 this.select($('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').eq(i));
775 }
776 }
777
778 /**
779 * Multiple range selection event handler that gets executed when hovering the mouse over the row of existing backups. This function highlights the rows with color
780 */
781 updraft_backups_selection.highlight_backup_rows = function() {
782 if ("undefined" === typeof updraft_backups_selection.firstMultipleSelectionIndex) return;
783 if (!$(this).hasClass('range-selection') && !$(this).hasClass('backuprowselected')) $(this).addClass('range-selection');
784 $(this).siblings().removeClass('range-selection');
785 if (updraft_backups_selection.firstMultipleSelectionIndex+1 > this.rowIndex) {
786 $(this).nextUntil('.updraft_existing_backups_row.range-selection-start').addClass('range-selection');
787 } else if (updraft_backups_selection.firstMultipleSelectionIndex+1 < this.rowIndex) {
788 $(this).prevUntil('.updraft_existing_backups_row.range-selection-start').addClass('range-selection');
789 }
790 }
791
792 /**
793 * Multiple range selection event handler that gets executed when the user releases the ctrl+shift button, it also gets executed when the mouse pointer is moved out from the browser page
794 * This function clears all the highlighted rows and removes hover and mouseleave event handlers
795 */
796 updraft_backups_selection.unregister_highlight_mode = function() {
797 if ("undefined" === typeof updraft_backups_selection.firstMultipleSelectionIndex) return;
798 delete updraft_backups_selection.firstMultipleSelectionIndex;
799 $('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').removeClass('range-selection range-selection-start');
800 $('#updraft-navtab-backups-content').off('mouseenter', '.updraft_existing_backups .updraft_existing_backups_row', this.highlight_backup_rows);
801 $('#updraft-navtab-backups-content').off('mouseleave', '.updraft_existing_backups .updraft_existing_backups_row', this.highlight_backup_rows);
802 $(document).off('mouseleave', this.unregister_highlight_mode);
803 }
804
805 /**
806 * Register mouseleave and hover event handlers for highlighting purposes
807 */
808 updraft_backups_selection.register_highlight_mode = function() {
809 $(document).on('mouseleave', updraft_backups_selection.unregister_highlight_mode);
810 $('#updraft-navtab-backups-content').on('mouseenter', '.updraft_existing_backups .updraft_existing_backups_row', updraft_backups_selection.highlight_backup_rows);
811 $('#updraft-navtab-backups-content').on('mouseleave', '.updraft_existing_backups .updraft_existing_backups_row', updraft_backups_selection.highlight_backup_rows);
812 }
813 })(jQuery);
814 // @codingStandardsIgnoreEnd
815
816 /**
817 * Setup migration sections
818 */
819 function setup_migrate_tabs() {
820 // sets up the section buttons
821 jQuery('#updraft_migrate .updraft_migrate_widget_module_content').each(function(ind, el) {
822 var title = jQuery(el).find('h3').first().html();
823 var intro_container = jQuery('.updraft_migrate_intro');
824 var button = jQuery('<button class="button button-primary button-hero" />').html(title).appendTo(intro_container);
825 button.on('click', function(e) {
826 e.preventDefault();
827 jQuery(el).show();
828 intro_container.hide();
829 });
830 });
831 }
832
833 /**
834 * Run a backup with show modal with progress.
835 *
836 * @param {Function} success_callback callback function after backup
837 * @param {String} onlythisfileentity csv list of file entities to be backed up
838 * @param {Array} extradata any extra data to be added
839 * @param {Integer} backupnow_nodb Indicate whether the database should be backed up. Valid values: 0, 1
840 * @param {Integer} backupnow_nofiles Indicate whether any files should be backed up. Valid values: 0, 1
841 * @param {Integer} backupnow_nocloud Indicate whether the backup should be uploaded to cloud storage. Valid values: 0, 1
842 * @param {String} label An optional label to be added to a backup
843 */
844 function updraft_backupnow_inpage_go(success_callback, onlythisfileentity, extradata, backupnow_nodb, backupnow_nofiles, backupnow_nocloud, label) {
845
846 backupnow_nodb = ('undefined' === typeof backupnow_nodb) ? 0 : backupnow_nodb;
847 backupnow_nofiles = ('undefined' === typeof backupnow_nofiles) ? 0 : backupnow_nofiles;
848 backupnow_nocloud = ('undefined' === typeof backupnow_nocloud) ? 0 : backupnow_nocloud;
849 label = ('undefined' === typeof label) ? updraftlion.automaticbackupbeforeupdate : label;
850
851 // N.B. This function should never be called on the UpdraftPlus settings page - it is assumed we are elsewhere. So, it is safe to fake the console-focussing parameter.
852 updraft_console_focussed_tab = 'backups';
853 updraft_inpage_success_callback = success_callback;
854 updraft_activejobs_update_timer = setInterval(function () {
855 updraft_activejobs_update(false);
856 }, 1250);
857 var updraft_inpage_modal_buttons = {};
858 var inpage_modal_exists = jQuery('#updraft-backupnow-inpage-modal').length;
859 if (inpage_modal_exists) {
860 jQuery('#updraft-backupnow-inpage-modal').dialog('option', 'buttons', updraft_inpage_modal_buttons);
861 }
862 jQuery('#updraft_inpage_prebackup').hide();
863 if (inpage_modal_exists) {
864 jQuery('#updraft-backupnow-inpage-modal').dialog('open');
865 }
866 jQuery('#updraft_inpage_backup').show();
867 updraft_activejobslist_backupnownonce_only = 1;
868 updraft_inpage_hasbegun = 0;
869 updraft_backupnow_go(backupnow_nodb, backupnow_nofiles, backupnow_nocloud, onlythisfileentity, extradata, label, '');
870 }
871
872 function updraft_get_downloaders() {
873 var downloaders = '';
874 jQuery('.ud_downloadstatus .updraftplus_downloader, #ud_downloadstatus2 .updraftplus_downloader, #ud_downloadstatus3 .updraftplus_downloader').each(function(x,y) {
875 var dat = jQuery(y).data('downloaderfor');
876 if (typeof dat == 'object') {
877 if (downloaders != '') { downloaders = downloaders + ':'; }
878 downloaders = downloaders + dat.base + ',' + dat.nonce + ',' + dat.what + ',' + dat.index;
879 }
880 });
881 return downloaders;
882 }
883
884 function updraft_poll_get_parameters() {
885
886 var gdata = {
887 downloaders: updraft_get_downloaders()
888 }
889
890 try {
891 if (jQuery('#updraft-poplog').dialog('isOpen')) {
892 gdata.log_fetch = 1;
893 gdata.log_nonce = updraft_poplog_log_nonce;
894 gdata.log_pointer = updraft_poplog_log_pointer
895 }
896 } catch (err) {
897 console.log(err);
898 }
899
900 if (updraft_activejobslist_backupnownonce_only && typeof updraft_backupnow_nonce !== 'undefined' && '' != updraft_backupnow_nonce) {
901 gdata.thisjobonly = updraft_backupnow_nonce;
902 }
903
904 if (0 !== jQuery('#updraftplus_ajax_restore_job_id').length) gdata.updraft_credentialtest_nonce = updraft_credentialtest_nonce;
905
906 return gdata;
907 }
908
909 var updraftplus_activejobs_list_fatal_error_alert = true;
910 function updraft_activejobs_update(force) {
911
912 var $ = jQuery;
913
914 var timenow = (new Date).getTime();
915 if (false == force && timenow < updraft_activejobs_nextupdate) { return; }
916 updraft_activejobs_nextupdate = timenow + 5500;
917
918 var gdata = updraft_poll_get_parameters();
919
920 updraft_send_command('activejobs_list', gdata, function(resp, status, response_raw) {
921 updraft_process_status_check(resp, response_raw, gdata);
922 }, {
923 type: 'GET',
924 error_callback: function(response, status, error_code, resp) {
925 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
926 console.error(resp.fatal_error_message);
927 if (true === updraftplus_activejobs_list_fatal_error_alert) {
928 updraftplus_activejobs_list_fatal_error_alert = false;
929 alert(this.alert_done + ' ' +resp.fatal_error_message);
930 }
931 } else {
932 var msg = (status == error_code) ? error_code : error_code+" ("+status+")";
933 console.error(msg);
934 console.log(response);
935 }
936 return false;
937 }
938 });
939 }
940
941 /**
942 * Shows a modal on success
943 *
944 * @param {string|obj} args The message to display or an object of parameters
945 */
946 function updraft_show_success_modal(args) {
947 if ('string' == typeof args) {
948 args = {
949 message: args
950 };
951 }
952 var data = jQuery.extend(
953 {
954 icon: 'yes',
955 close: updraftlion.close,
956 message: '',
957 classes: 'success'
958 },
959 args
960 );
961 jQuery.blockUI({
962 css: {
963 width: '300px',
964 border: 'none',
965 'border-radius': '10px',
966 left: 'calc(50% - 150px)'
967 },
968 message: '<div class="updraft_success_popup '+data.classes+'"><span class="dashicons udp-dashicons-'+data.icon+'"></span><div class="updraft_success_popup--message">'+data.message+'</div><button class="udp-button updraft-close-overlay"><span class="udp-dashicons udp-dashicons-no-alt"></span>'+data.close+'</button></div>'
969 });
970 // close success popup
971 setTimeout(jQuery.unblockUI, 5000);
972 jQuery('.blockUI .updraft-close-overlay').on('click', function() {
973 jQuery.unblockUI();
974 })
975 }
976
977 /**
978 * Opens a dialog window showing the requested (or latest) log file, plus an option to download it
979 *
980 * @param {string} backup_nonce - the nonce of the log to display, or empty for the latest one
981 */
982 function updraft_popuplog(backup_nonce) {
983
984 var loading_message = updraftlion.loading_log_file;
985
986 if (backup_nonce) { loading_message += ' (log.'+backup_nonce+'.txt)'; }
987
988 jQuery('#updraft-poplog').dialog("option", "title", loading_message);
989 jQuery('#updraft-poplog-content').html('<em>'+loading_message+' ...</em> ');
990 jQuery('#updraft-poplog').dialog("open");
991
992 updraft_send_command('get_log', backup_nonce, function(resp) {
993
994 updraft_poplog_log_pointer = resp.pointer;
995 updraft_poplog_log_nonce = resp.nonce;
996
997 var download_url = '?page=updraftplus&action=downloadlog&force_download=1&updraftplus_backup_nonce='+resp.nonce;
998
999 jQuery('#updraft-poplog-content').html(resp.log);
1000
1001 var log_popup_buttons = {};
1002 log_popup_buttons[updraftlion.downloadlogfile] = function() {
1003 window.location.href = download_url; };
1004 log_popup_buttons[updraftlion.close] = function() {
1005 jQuery(this).dialog("close"); };
1006
1007 // Set the dialog buttons: Download log, Close log
1008 jQuery('#updraft-poplog').dialog("option", "buttons", log_popup_buttons);
1009 jQuery('#updraft-poplog').dialog("option", "title", 'log.'+resp.nonce+'.txt');
1010
1011 updraft_poplog_lastscroll = -1;
1012
1013 }, { type: 'GET', timeout: 60000, error_callback: function(response, status, error_code, resp) {
1014 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
1015 console.error(resp.fatal_error_message);
1016 jQuery('#updraft-poplog-content').append(resp.fatal_error_message);
1017 } else {
1018 var msg = (status == error_code) ? error_code : error_code+" ("+status+")";
1019 jQuery('#updraft-poplog-content').append(msg);
1020 console.log(response);
1021 }
1022 }
1023 });
1024 }
1025
1026 function updraft_showlastbackup() {
1027
1028 updraft_send_command('get_fragment', 'last_backup_html', function(resp) {
1029
1030 response = resp.output;
1031
1032 if (lastbackup_laststatus == response) {
1033 setTimeout(function() {
1034 updraft_showlastbackup(); }, 7000);
1035 } else {
1036 jQuery('#updraft_last_backup').html(response);
1037 }
1038 lastbackup_laststatus = response;
1039
1040 }, { type: 'GET' });
1041
1042 }
1043
1044 var updraft_historytimer = 0;
1045 var calculated_diskspace = 0;
1046 var updraft_historytimer_notbefore = 0;
1047 var updraft_history_lastchecksum = false;
1048
1049 function updraft_historytimertoggle(forceon) {
1050 if (!updraft_historytimer || forceon == 1) {
1051 updraft_updatehistory(0, 0);
1052 updraft_historytimer = setInterval(function() {
1053 updraft_updatehistory(0, 0);}, 30000);
1054 if (!calculated_diskspace) {
1055 updraftplus_diskspace();
1056 calculated_diskspace = 1;
1057 }
1058 } else {
1059 clearTimeout(updraft_historytimer);
1060 updraft_historytimer = 0;
1061 }
1062 }
1063
1064 /**
1065 * Update the HTML for the 'existing backups' table; optionally, after local/remote re-scanning.
1066 * Nothing is returned; any update necessary is performed directly on the DOM.
1067 *
1068 * @param {Integer} rescan - first, re-scan the local storage (0 or 1)
1069 * @param {Integer} remotescan - first, re-scan the remote storage (you must also set rescan to 1 to use this)
1070 * @param {Integer} debug - if 1, then also request debugging information and log it to the console
1071 * @param {Integer} backup_count - the amount of backups we want to display
1072 */
1073 function updraft_updatehistory(rescan, remotescan, debug, backup_count) {
1074
1075 if ('undefined' != typeof updraft_restore_screen && updraft_restore_screen) return;
1076
1077 if ('undefined' === typeof debug) {
1078 debug = jQuery('#updraft_debug_mode').is(':checked') ? 1 : 0;
1079 }
1080
1081 var unixtime = Math.round(new Date().getTime() / 1000);
1082
1083 if (1 == rescan || 1 == remotescan) {
1084 updraft_historytimer_notbefore = unixtime + 30;
1085 } else {
1086 if (unixtime < updraft_historytimer_notbefore && 'undefined' === typeof backup_count) {
1087 console.log("Update history skipped: "+unixtime.toString()+" < "+updraft_historytimer_notbefore.toString());
1088 return;
1089 }
1090 }
1091
1092 if ('undefined' === typeof backup_count) {
1093 backup_count = 0;
1094 }
1095
1096
1097 if (rescan == 1) {
1098 if (remotescan == 1) {
1099 updraft_history_lastchecksum = false;
1100 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').html('<p style="text-align:center;"><em>'+updraftlion.rescanningremote+'</em></p>');
1101 } else {
1102 updraft_history_lastchecksum = false;
1103 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').html('<p style="text-align:center;"><em>'+updraftlion.rescanning+'</em></p>');
1104 }
1105 }
1106
1107 var what_op = remotescan ? 'remotescan' : (rescan ? 'rescan' : false);
1108
1109 var data = {
1110 operation: what_op,
1111 debug: debug,
1112 backup_count: backup_count,
1113 }
1114
1115 updraft_send_command('rescan', data, function(resp) {
1116 if (resp.hasOwnProperty('logs_exist') && resp.logs_exist) {
1117 // Show the "most recently modified log" link, in case it was previously hidden (if there were no logs until now)
1118 jQuery('#updraft_lastlogmessagerow .updraft-log-link').show();
1119 }
1120
1121 if (resp.hasOwnProperty('migrate_tab') && resp.migrate_tab) {
1122 if (!jQuery('#updraft-navtab-migrate').hasClass('nav-tab-active')) {
1123 jQuery('#updraft_migrate_tab_alt').html('');
1124 jQuery('#updraft_migrate').replaceWith(jQuery(resp.migrate_tab).find('#updraft_migrate'));
1125 setup_migrate_tabs();
1126 }
1127 }
1128
1129 if (resp.hasOwnProperty('web_server_disk_space')) {
1130 if ('' == resp.web_server_disk_space) {
1131 console.log("UpdraftPlus: web_server_disk_space is empty");
1132 if (jQuery('#updraft-navtab-backups-content .updraft-server-disk-space').length) {
1133 jQuery('#updraft-navtab-backups-content .updraft-server-disk-space').slideUp('slow', function() {
1134 jQuery(this).remove();
1135 });
1136 }
1137 } else {
1138 if (jQuery('#updraft-navtab-backups-content .updraft-server-disk-space').length) {
1139 jQuery('#updraft-navtab-backups-content .updraft-server-disk-space').replaceWith(resp.web_server_disk_space);
1140 } else {
1141 jQuery('#updraft-navtab-backups-content .updraft-disk-space-actions').prepend(resp.web_server_disk_space);
1142 }
1143 }
1144 }
1145
1146 update_backupnow_modal(resp);
1147
1148 if (resp.hasOwnProperty('backupnow_file_entities')) {
1149 impossible_increment_entities = resp.backupnow_file_entities;
1150 }
1151
1152 if (resp.n != null) { jQuery('#updraft-existing-backups-heading').html(resp.n); }
1153
1154 if (resp.t != null) {
1155 if (resp.cksum != null) {
1156 if (resp.cksum == updraft_history_lastchecksum) {
1157 // Avoid unnecessarily refreshing the HTML if the data is the same. This helps avoid resetting the DOM (annoying when debugging), and keeps user row selections.
1158 return;
1159 }
1160 updraft_history_lastchecksum = resp.cksum;
1161 }
1162 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').html(resp.t);
1163 updraft_backups_selection.checkSelectionStatus();
1164 if (resp.data) {
1165 console.log(resp.data);
1166 }
1167 }
1168 });
1169 }
1170
1171 /**
1172 * This function will check if the passed in response contains content for the backup now modal that needs updating on page
1173 *
1174 * @param {array} response - an array that may contain backupnow_modal content that needs updating
1175 */
1176 function update_backupnow_modal(response) {
1177 if (response.hasOwnProperty('modal_afterfileoptions')) {
1178 jQuery('.backupnow_modal_afterfileoptions').html(response.modal_afterfileoptions);
1179 }
1180 }
1181
1182 /**
1183 * Exclude entities hidden input field update
1184 *
1185 * @param {string} include_entity_name - backup entity name
1186 */
1187 function updraft_exclude_entity_update(include_entity_name) {
1188 var exclude_entities = [];
1189 jQuery('#updraft_include_'+include_entity_name+'_exclude_container .updraft_exclude_entity_wrapper .updraft_exclude_entity_field').each(function() {
1190 var data_val = jQuery(this).data('val').toString().trim();
1191 if ('' != data_val) {
1192 exclude_entities.push(data_val);
1193 }
1194 });
1195 jQuery('#updraft_include_'+include_entity_name+'_exclude').val(exclude_entities.join(','));
1196 }
1197
1198 /**
1199 * Check uniqueness of exclude rule in include_backup_file
1200 *
1201 * @param {string} exclude_rule - exclude rule
1202 * @param {string} include_backup_file - the backup file type on which the exclude_rule will be applied
1203 *
1204 * @return {boolean} true if exclude_rule is unique otherwise false
1205 */
1206 function updraft_is_unique_exclude_rule(exclude_rule, include_backup_file) {
1207 existing_exclude_rules_str = jQuery('#updraft_include_'+include_backup_file+'_exclude').val();
1208 existing_exclude_rules = existing_exclude_rules_str.split(',');
1209
1210 if (jQuery.inArray(exclude_rule, existing_exclude_rules) > -1) {
1211 alert(updraftlion.duplicate_exclude_rule_error_msg)
1212 return false;
1213 } else {
1214 return true;
1215 }
1216 }
1217
1218
1219 var updraft_interval_week_val = false;
1220 var updraft_interval_month_val = false;
1221
1222 function updraft_intervals_monthly_or_not(selector_id, now_showing) {
1223 var selector = '#updraft-navtab-settings-content #'+selector_id;
1224 var current_length = jQuery(selector+' option').length;
1225 var is_monthly = ('monthly' == now_showing) ? true : false;
1226 var existing_is_monthly = false;
1227 if (current_length > 10) { existing_is_monthly = true; }
1228 if (!is_monthly && !existing_is_monthly) {
1229 return;
1230 }
1231 if (is_monthly && existing_is_monthly) {
1232 if ('monthly' == now_showing) {
1233 // existing_is_monthly does not mean the same as now_showing=='monthly'. existing_is_monthly refers to the drop-down, not whether the drop-down is being displayed. We may need to add these words back.
1234 jQuery('.updraft_monthly_extra_words_'+selector_id).remove();
1235 jQuery(selector).before('<span class="updraft_monthly_extra_words_'+selector_id+'">'+updraftlion.day+' </span>').after('<span class="updraft_monthly_extra_words_'+selector_id+'"> '+updraftlion.inthemonth+' </span>');
1236 }
1237 return;
1238 }
1239 jQuery('.updraft_monthly_extra_words_'+selector_id).remove();
1240 if (is_monthly) {
1241 // Save the old value
1242 updraft_interval_week_val = jQuery(selector+' option:selected').val();
1243 jQuery(selector).html(updraftlion.mdayselector).before('<span class="updraft_monthly_extra_words_'+selector_id+'">'+updraftlion.day+' </span>').after('<span class="updraft_monthly_extra_words_'+selector_id+'"> '+updraftlion.inthemonth+' </span>');
1244 var select_mday = (updraft_interval_month_val === false) ? 1 : updraft_interval_month_val;
1245 // Convert from day of the month (ordinal) to option index (starts at 0)
1246 select_mday = select_mday - 1;
1247 jQuery(selector+" option").eq(select_mday).prop('selected', true);
1248 } else {
1249 // Save the old value
1250 updraft_interval_month_val = jQuery(selector+' option:selected').val();
1251 jQuery(selector).html(updraftlion.dayselector);
1252 var select_day = (updraft_interval_week_val === false) ? 1 : updraft_interval_week_val;
1253 jQuery(selector+" option").eq(select_day).prop('selected', true);
1254 }
1255 }
1256
1257 function updraft_check_same_times() {
1258 var dbmanual = 0;
1259 var file_interval = jQuery('#updraft-navtab-settings-content .updraft_interval').val();
1260 if (file_interval == 'manual') {
1261 // jQuery('#updraft_files_timings').css('opacity', '0.25');
1262 jQuery('#updraft-navtab-settings-content .updraft_files_timings').hide();
1263 } else {
1264 // jQuery('#updraft_files_timings').css('opacity', 1);
1265 jQuery('#updraft-navtab-settings-content .updraft_files_timings').show();
1266 }
1267
1268 if ('weekly' == file_interval || 'fortnightly' == file_interval || 'monthly' == file_interval) {
1269 updraft_intervals_monthly_or_not('updraft_startday_files', file_interval);
1270 jQuery('#updraft-navtab-settings-content #updraft_startday_files').show();
1271 } else {
1272 jQuery('.updraft_monthly_extra_words_updraft_startday_files').remove();
1273 jQuery('#updraft-navtab-settings-content #updraft_startday_files').hide();
1274 }
1275
1276 var db_interval = jQuery('#updraft-navtab-settings-content .updraft_interval_database').val();
1277 if (db_interval == 'manual') {
1278 dbmanual = 1;
1279 // jQuery('#updraft_db_timings').css('opacity', '0.25');
1280 jQuery('#updraft-navtab-settings-content .updraft_db_timings').hide();
1281 }
1282
1283 if ('weekly' == db_interval || 'fortnightly' == db_interval || 'monthly' == db_interval) {
1284 updraft_intervals_monthly_or_not('updraft_startday_db', db_interval);
1285 jQuery('#updraft-navtab-settings-content #updraft_startday_db').show();
1286 } else {
1287 jQuery('.updraft_monthly_extra_words_updraft_startday_db').remove();
1288 jQuery('#updraft-navtab-settings-content #updraft_startday_db').hide();
1289 }
1290
1291 if (db_interval == file_interval) {
1292 // jQuery('#updraft_db_timings').css('opacity','0.25');
1293 jQuery('#updraft-navtab-settings-content .updraft_db_timings').hide();
1294 // jQuery('#updraft_same_schedules_message').show();
1295 if (0 == dbmanual) {
1296 jQuery('#updraft-navtab-settings-content .updraft_same_schedules_message').show();
1297 } else {
1298 jQuery('#updraft-navtab-settings-content .updraft_same_schedules_message').hide();
1299 }
1300 } else {
1301 jQuery('#updraft-navtab-settings-content .updraft_same_schedules_message').hide();
1302 if (0 == dbmanual) {
1303 // jQuery('#updraft_db_timings').css('opacity', '1');
1304 jQuery('#updraft-navtab-settings-content .updraft_db_timings').show();
1305 }
1306 }
1307 }
1308
1309 // Visit the site in the background every 3.5 minutes - ensures that backups can progress if you've got the UD settings page open
1310 if ('undefined' !== typeof updraft_siteurl) {
1311 setInterval(function() {
1312 jQuery.get(updraft_siteurl+'/wp-cron.php');}, 210000);
1313 }
1314
1315 function updraft_activejobs_delete(jobid) {
1316 updraft_aborted_jobs[jobid] = 1;
1317 jQuery('#updraft-jobid-'+jobid).closest('.updraft_row').addClass('deleting');
1318 updraft_send_command('activejobs_delete', jobid, function(resp) {
1319 var job_row = jQuery('#updraft-jobid-'+jobid).closest('.updraft_row');
1320 job_row.addClass('deleting');
1321
1322 if (resp.ok == 'Y') {
1323 jQuery('#updraft-jobid-'+jobid).html(resp.m);
1324 job_row.remove();
1325
1326 // inpage backup - Close modal if canceling backup
1327 if (jQuery('#updraft-backupnow-inpage-modal').dialog('isOpen')) jQuery('#updraft-backupnow-inpage-modal').dialog('close');
1328
1329 updraft_show_success_modal({
1330 message: updraft_active_job_is_clone(jobid) ? updraftlion.clone_backup_aborted : updraftlion.backup_aborted,
1331 icon: 'no-alt',
1332 classes: 'warning'
1333 });
1334 } else if ('N' == resp.ok) {
1335 job_row.removeClass('deleting');
1336 alert(resp.m);
1337 } else {
1338 job_row.removeClass('deleting');
1339 alert(updraftlion.unexpectedresponse);
1340 console.log(resp);
1341 }
1342 });
1343 }
1344
1345 function updraftplus_diskspace_entity(key) {
1346 jQuery('#updraft_diskspaceused_'+key).html('<em>'+updraftlion.calculating+'</em>');
1347 updraft_send_command('get_fragment', { fragment: 'disk_usage', data: key }, function(response) {
1348 jQuery('#updraft_diskspaceused_'+key).html(response.output);
1349 }, { type: 'GET' });
1350 }
1351
1352 /**
1353 * Checks if the specified job is a clone
1354 *
1355 * @param {string} job_id The job ID
1356 *
1357 * @return {int}
1358 */
1359 function updraft_active_job_is_clone(job_id) {
1360 return updraft_clone_jobs.filter(function(val) {
1361 return val == job_id;
1362 }).length;
1363 }
1364
1365 /**
1366 * Open a modal with content fetched from an iframe
1367 *
1368 * @param {String} getwhat - the subaction parameter to pass to UD's AJAX handler
1369 * @param {String} title - the title for the modal
1370 */
1371 function updraft_iframe_modal(getwhat, title) {
1372 var width = 780;
1373 var height = 500;
1374 jQuery('#updraft-iframe-modal-innards').html('<iframe width="100%" height="430px" src="'+ajaxurl+'?action=updraft_ajax&subaction='+getwhat+'&nonce='+updraft_credentialtest_nonce+'"></iframe>');
1375 jQuery('#updraft-iframe-modal').dialog({
1376 title: title, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
1377 open: function(event, ui) {
1378 jQuery(this).dialog('option', 'width', width),
1379 jQuery(this).dialog('option', 'minHeight', 260);
1380 if (jQuery(window).height() > height) {
1381 jQuery(this).dialog('option', 'height', height);
1382 } else {
1383 jQuery(this).dialog('option', 'height', jQuery(window).height()-30);
1384 }
1385 }
1386 }).dialog('open');
1387 }
1388
1389 function updraft_html_modal(showwhat, title, width, height) {
1390 jQuery('#updraft-iframe-modal-innards').html(showwhat);
1391 var updraft_html_modal_buttons = {};
1392 if (width < 450) {
1393 updraft_html_modal_buttons[updraftlion.close] = function() {
1394 jQuery(this).dialog("close"); };
1395 }
1396 jQuery('#updraft-iframe-modal').dialog({
1397 title: title, buttons: updraft_html_modal_buttons, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
1398 open: function(event, ui) {
1399 jQuery(this).dialog('option', 'width', width),
1400 jQuery(this).dialog('option', 'minHeight', 260);
1401 if (jQuery(window).height() > height) {
1402 jQuery(this).dialog('option', 'height', height);
1403 } else {
1404 jQuery(this).dialog('option', 'height', jQuery(window).height()-30);
1405 }
1406 }
1407 }).dialog('open');
1408 }
1409
1410 function updraftplus_diskspace() {
1411 jQuery('#updraft-navtab-backups-content .updraft_diskspaceused').html('<em>'+updraftlion.calculating+'</em>');
1412 updraft_send_command('get_fragment', { fragment: 'disk_usage', data: 'updraft' }, function(response) {
1413 jQuery('#updraft-navtab-backups-content .updraft_diskspaceused').html(response.output);
1414 }, { type: 'GET' });
1415 }
1416 var lastlog_lastmessage = "";
1417 function updraftplus_deletefromserver(timestamp, type, findex) {
1418 if (!findex) findex=0;
1419 var pdata = {
1420 stage: 'delete',
1421 timestamp: timestamp,
1422 type: type,
1423 findex: findex
1424 };
1425 updraft_send_command('updraft_download_backup', pdata, null, { action: 'updraft_download_backup', nonce: updraft_download_nonce, nonce_key: '_wpnonce' });
1426 }
1427
1428 function updraftplus_downloadstage2(timestamp, type, findex) {
1429 location.href =ajaxurl+'?_wpnonce='+updraft_download_nonce+'&timestamp='+timestamp+'&type='+type+'&stage=2&findex='+findex+'&action=updraft_download_backup';
1430 }
1431
1432 function updraftplus_show_contents(timestamp, type, findex) {
1433 var modal_content = '<div id="updraft_zip_files_container" class="hidden-in-updraftcentral" style="clear:left;"><div id="updraft_zip_info_container" class="updraft_jstree_info_container"><p><span id="updraft_zip_path_text">' + updraftlion.zip_file_contents_info + '</span> - <span id="updraft_zip_size_text"></span></p>'+updraftlion.browse_download_link+'</div><div id="updraft_zip_files_jstree_container"><input type="search" id="zip_files_jstree_search" name="zip_files_jstree_search" placeholder="' + updraftlion.search + '"><div id="updraft_zip_files_jstree" class="updraft_jstree"></div></div></div>';
1434
1435 updraft_html_modal(modal_content, updraftlion.zip_file_contents, 780, 500);
1436
1437 zip_files_jstree('zipbrowser', timestamp, type, findex);
1438 }
1439
1440 /**
1441 * Creates the jstree and makes a call to the backend to dynamically get the tree nodes
1442 *
1443 * @param {string} entity Entity for the jstree
1444 * @param {integer} timestamp Timestamp of the jstree
1445 * @param {string} type Type of file to display in the JS tree
1446 * @param {array} findex Index of Zip
1447 */
1448 function zip_files_jstree(entity, timestamp, type, findex) {
1449
1450 jQuery('#updraft_zip_files_jstree').jstree({
1451 "core": {
1452 "multiple": false,
1453 "data": function (nodeid, callback) {
1454 updraft_send_command('get_jstree_directory_nodes', {entity:entity, node:nodeid, timestamp:timestamp, type:type, findex:findex}, function(response) {
1455 if (response.hasOwnProperty('error')) {
1456 alert(response.error);
1457 } else {
1458 callback.call(this, response.nodes);
1459 }
1460 }, { error_callback: function(response, status, error_code, resp) {
1461 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
1462 console.error(resp.fatal_error_message);
1463 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+resp.fatal_error_message+'</p>');
1464 alert(resp.fatal_error_message);
1465 } else {
1466 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
1467 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+error_message+'</p>');
1468 console.log(error_message);
1469 alert(error_message);
1470 console.log(response);
1471 }
1472 }
1473 });
1474 },
1475 "error": function(error) {
1476 alert(error);
1477 console.log(error);
1478 },
1479 },
1480 "search": {
1481 "show_only_matches": true
1482 },
1483 "plugins": ["search", "sort"],
1484 });
1485
1486 // Update modal title once tree loads
1487 jQuery('#updraft_zip_files_jstree').on('ready.jstree', function(e, data) {
1488 jQuery('#updraft-iframe-modal').dialog('option', 'title', updraftlion.zip_file_contents + ': ' + data.instance.get_node('#').children[0])
1489 });
1490
1491 // Search function for jstree, this will hide nodes that don't match the search
1492 var timeout = false;
1493 jQuery('#zip_files_jstree_search').on('keyup', function () {
1494 if (timeout) { clearTimeout(timeout); }
1495 timeout = setTimeout(function () {
1496 var value = jQuery('#zip_files_jstree_search').val();
1497 jQuery('#updraft_zip_files_jstree').jstree(true).search(value);
1498 }, 250);
1499 });
1500
1501 // Detect change on the tree and update the input that has been marked as editing
1502 jQuery('#updraft_zip_files_jstree').on("changed.jstree", function (e, data) {
1503 jQuery('#updraft_zip_path_text').text(data.node.li_attr.path);
1504
1505 if (data.node.li_attr.size) {
1506 jQuery('#updraft_zip_size_text').text(data.node.li_attr.size);
1507 jQuery('#updraft_zip_download_item').show();
1508 } else {
1509 jQuery('#updraft_zip_size_text').text('');
1510 jQuery('#updraft_zip_download_item').hide();
1511 }
1512 });
1513
1514 jQuery('#updraft_zip_download_item').on('click', function(event) {
1515
1516 event.preventDefault();
1517
1518 var path = jQuery('#updraft_zip_path_text').text();
1519
1520 updraft_send_command('get_zipfile_download', {path:path, timestamp:timestamp, type:type, findex:findex}, function(response) {
1521 if (response.hasOwnProperty('error')) {
1522 alert(response.error);
1523 } else if (response.hasOwnProperty('path')) {
1524 location.href =ajaxurl+'?_wpnonce='+updraft_download_nonce+'&timestamp='+timestamp+'&type='+type+'&stage=2&findex='+findex+'&filepath='+response.path+'&action=updraft_download_backup';
1525 } else {
1526 alert(updraftlion.download_timeout);
1527 }
1528 }, { error_callback: function(response, status, error_code, resp) {
1529 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
1530 console.error(resp.fatal_error_message);
1531 alert(resp.fatal_error_message);
1532 } else {
1533 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
1534 console.log(error_message);
1535 alert(error_message);
1536 console.log(response);
1537 }
1538 }
1539 });
1540 });
1541 }
1542
1543 /**
1544 * This function will clean up the updraft downloader UI
1545 *
1546 * @param {object} item - the object pressed in the UI
1547 * @param {string} what - the file entity
1548 */
1549 function remove_updraft_downloader(item, what) {
1550 jQuery(item).closest('.updraftplus_downloader').fadeOut().remove();
1551 if (0 == jQuery('.updraftplus_downloader_container_'+what+' .updraftplus_downloader').length) jQuery('.updraftplus_downloader_container_'+what).remove();
1552 }
1553
1554 /**
1555 * This function will prepare the downloader UI and kick of the request to download the file entities.
1556 *
1557 * @param {string} base - the base string for the id
1558 * @param {integer} backup_timestamp - the backup timestamp
1559 * @param {string} what - the file entity
1560 * @param {string} whicharea - the area we want to append the downloader
1561 * @param {string} set_contents - the contents we want to download
1562 * @param {string} prettydate - the pretty backup date
1563 * @param {boolean} async - boolean to indicate if this is a async request or not
1564 */
1565 function updraft_downloader(base, backup_timestamp, what, whicharea, set_contents, prettydate, async) {
1566
1567 if (typeof set_contents !== "string") set_contents = set_contents.toString();
1568
1569 jQuery('.ud_downloadstatus').show();
1570
1571 var set_contents = set_contents.split(',');
1572 var prdate = (prettydate) ? prettydate : backup_timestamp;
1573
1574 // Old-style, from when it was a form
1575 // var data = jQuery('#updraft-navtab-backups-content .uddownloadform_'+what+'_'+backup_timestamp+'_'+set_contents[i]).serialize();
1576 var nonce = jQuery('#updraft-navtab-backups-content .uddownloadform_'+what+'_'+backup_timestamp+'_'+set_contents[0]).data('wp_nonce').toString();
1577
1578 if (!jQuery('.updraftplus_downloader_container_'+what).length) {
1579 jQuery(whicharea).append('<div class="updraftplus_downloader_container_' + what + ' postbox"></div>');
1580 jQuery('.updraftplus_downloader_container_' + what).append('<strong style="clear:left; padding: 8px; margin-top: 4px;">' + updraftlion.download + ' ' + what + ' (' + prdate + '):</strong>');
1581 }
1582
1583 for (var i = 0; i < set_contents.length; i++) {
1584 // Create somewhere for the status to be found
1585 var stid = base+backup_timestamp+'_'+what+'_'+set_contents[i];
1586 var stid_selector = '.'+stid;
1587 var show_index = parseInt(set_contents[i]); show_index++;
1588 var itext = (0 == set_contents[i]) ? '' : ' ('+show_index+')';
1589 if (!jQuery(stid_selector).length) {
1590 jQuery('.updraftplus_downloader_container_'+what).append('<div style="clear:left; padding: 8px; margin-top: 4px;" class="'+stid+' updraftplus_downloader"><button onclick="remove_updraft_downloader(this, \''+what+'\');" type="button" style="float:right; margin-bottom: 8px;" class="ud_downloadstatus__close" aria-label="Close"><span class="dashicons dashicons-no-alt"></span></button><strong>'+what+itext+'</strong>:<div class="raw">'+updraftlion.begunlooking+'</div><div class="file '+stid+'_st"><div class="dlfileprogress" style="width: 0;"></div></div></div>');
1591 jQuery(stid_selector).data('downloaderfor', { base: base, nonce: backup_timestamp, what: what, index: set_contents[i] });
1592 setTimeout(function() {
1593 updraft_activejobs_update(true);
1594 },
1595 1500);
1596 }
1597 jQuery(stid_selector).data('lasttimebegan', (new Date).getTime());
1598 }
1599
1600 // Now send the actual request to kick it all off
1601 async = async ? true : false;
1602
1603 var data = {
1604 type: what,
1605 timestamp: backup_timestamp,
1606 findex: set_contents
1607 };
1608
1609 var options = {
1610 action: 'updraft_download_backup',
1611 nonce_key: '_wpnonce',
1612 nonce: nonce,
1613 timeout: 10000,
1614 async: async
1615 }
1616
1617 updraft_send_command('updraft_download_backup', data, null, options);
1618
1619 // We don't want the form to submit as that replaces the document
1620 return false;
1621 }
1622
1623 /**
1624 * Parse JSON string, including automatically detecting unwanted extra input and skipping it
1625 *
1626 * @param {string} json_mix_str - JSON string which need to parse and convert to object
1627 * @param {boolean} analyse - if true, then the return format will contain information on the parsing, and parsing will skip attempting to JSON.parse() the entire string (will begin with trying to locate the actual JSON)
1628 *
1629 * @throws SyntaxError|String (including passing on what JSON.parse may throw) if a parsing error occurs.
1630 *
1631 * @returns Mixed parsed JSON object. Will only return if parsing is successful (otherwise, will throw). If analyse is true, then will rather return an object with properties (mixed)parsed, (integer)json_start_pos and (integer)json_end_pos
1632 */
1633 function ud_parse_json(json_mix_str, analyse) {
1634
1635 analyse = ('undefined' === typeof analyse) ? false : true;
1636
1637 // Just try it - i.e. the 'default' case where things work (which can include extra whitespace/line-feeds, and simple strings, etc.).
1638 if (!analyse) {
1639 try {
1640 var result = JSON.parse(json_mix_str);
1641 return result;
1642 } catch (e) {
1643 console.log('UpdraftPlus: Exception when trying to parse JSON (1) - will attempt to fix/re-parse based upon first/last curly brackets');
1644 console.log(json_mix_str);
1645 }
1646 }
1647
1648 var json_start_pos = json_mix_str.indexOf('{');
1649 var json_last_pos = json_mix_str.lastIndexOf('}');
1650
1651 // Case where some php notice may be added after or before json string
1652 if (json_start_pos > -1 && json_last_pos > -1) {
1653 var json_str = json_mix_str.slice(json_start_pos, json_last_pos + 1);
1654 try {
1655 var parsed = JSON.parse(json_str);
1656 if (!analyse) { console.log('UpdraftPlus: JSON re-parse successful'); }
1657 return analyse ? { parsed: parsed, json_start_pos: json_start_pos, json_last_pos: json_last_pos + 1 } : parsed;
1658 } catch (e) {
1659 console.log('UpdraftPlus: Exception when trying to parse JSON (2) - will attempt to fix/re-parse based upon bracket counting');
1660
1661 var cursor = json_start_pos;
1662 var open_count = 0;
1663 var last_character = '';
1664 var inside_string = false;
1665
1666 // Don't mistake this for a real JSON parser. Its aim is to improve the odds in real-world cases seen, not to arrive at universal perfection.
1667 while ((open_count > 0 || cursor == json_start_pos) && cursor <= json_last_pos) {
1668
1669 var current_character = json_mix_str.charAt(cursor);
1670
1671 if (!inside_string && '{' == current_character) {
1672 open_count++;
1673 } else if (!inside_string && '}' == current_character) {
1674 open_count--;
1675 } else if ('"' == current_character && '\\' != last_character) {
1676 inside_string = inside_string ? false : true;
1677 }
1678
1679 last_character = current_character;
1680 cursor++;
1681 }
1682 console.log("Started at cursor="+json_start_pos+", ended at cursor="+cursor+" with result following:");
1683 console.log(json_mix_str.substring(json_start_pos, cursor));
1684
1685 try {
1686 var parsed = JSON.parse(json_mix_str.substring(json_start_pos, cursor));
1687 console.log('UpdraftPlus: JSON re-parse successful');
1688 return analyse ? { parsed: parsed, json_start_pos: json_start_pos, json_last_pos: cursor } : parsed;
1689 } catch (e) {
1690 // Throw it again, so that our function works just like JSON.parse() in its behaviour.
1691 throw e;
1692 }
1693 }
1694 }
1695
1696 throw "UpdraftPlus: could not parse the JSON";
1697
1698 }
1699
1700 // Catch HTTP errors if the download status check returns them
1701 jQuery(document).ajaxError(function(event, jqxhr, settings, exception) {
1702 if (exception == null || exception == '') return;
1703 if (jqxhr.responseText == null || jqxhr.responseText == '') return;
1704 console.log("Error caught by UpdraftPlus ajaxError handler (follows) for "+settings.url);
1705 console.log(exception);
1706 if (settings.url.search(ajaxurl) == 0) {
1707 // TODO subaction=downloadstatus is no longer used. This should be adjusted to the current set-up.
1708 if (settings.url.search('subaction=downloadstatus') >= 0) {
1709 var timestamp = settings.url.match(/timestamp=\d+/);
1710 var type = settings.url.match(/type=[a-z]+/);
1711 var findex = settings.url.match(/findex=\d+/);
1712 var base = settings.url.match(/base=[a-z_]+/);
1713 findex = (findex instanceof Array) ? parseInt(findex[0].substr(7)) : 0;
1714 type = (type instanceof Array) ? type[0].substr(5) : '';
1715 base = (base instanceof Array) ? base[0].substr(5) : '';
1716 timestamp = (timestamp instanceof Array) ? parseInt(timestamp[0].substr(10)) : 0;
1717 if ('' != base && '' != type && timestamp >0) {
1718 var stid = base+timestamp+'_'+type+'_'+findex;
1719 jQuery('.'+stid+' .raw').html('<strong>'+updraftlion.error+'</strong> '+updraftlion.servererrorcode);
1720 }
1721 } else if (settings.url.search('subaction=restore_alldownloaded') >= 0) {
1722 // var timestamp = settings.url.match(/timestamp=\d+/);
1723 jQuery('#updraft-restore-modal-stage2a').append('<br><strong>'+updraftlion.error+'</strong> '+updraftlion.servererrorcode+': '+exception);
1724 }
1725 }
1726 });
1727
1728 function updraft_restorer_checkstage2(doalert) {
1729 // How many left?
1730 var stilldownloading = jQuery('#ud_downloadstatus2 .file').length;
1731 if (stilldownloading > 0) {
1732 if (doalert) { alert(updraftlion.stilldownloading); }
1733 return;
1734 }
1735 // Allow pressing 'Restore' to proceed
1736 jQuery('.updraft-restore--next-step').prop('disabled', true);
1737 jQuery('#updraft-restore-modal-stage2a').html('<span class="dashicons dashicons-update rotate"></span> '+updraftlion.preparing_backup_files);
1738 updraft_send_command('restore_alldownloaded', {
1739 timestamp: jQuery('#updraft_restore_timestamp').val(),
1740 restoreopts: jQuery('#updraft_restore_form').serialize()
1741 }, function(resp, status, data) {
1742 var info = null;
1743 jQuery('#updraft_restorer_restore_options').val('');
1744 jQuery('.updraft-restore--next-step').prop('disabled', false);
1745 try {
1746 // var resp = ud_parse_json(data);
1747 if (null == resp) {
1748 jQuery('#updraft-restore-modal-stage2a').html(updraftlion.emptyresponse);
1749 return;
1750 }
1751 var report = resp.m;
1752 if (resp.w != '') {
1753 report = report + '<div class="udp-notice notice-warning"><p><span class="dashicons dashicons-warning"></span> <strong>' + updraftlion.warnings +'</strong></p>' + resp.w + '</div>';
1754 }
1755 if (resp.e != '') {
1756 report = report + '<div class="udp-notice notice-error"><p><span class="dashicons dashicons-dismiss"></span> <strong>' + updraftlion.errors+'</strong></p>' + resp.e + '</div>';
1757 } else {
1758 updraft_restore_stage = 3;
1759 }
1760 if (resp.hasOwnProperty('i')) {
1761 // Store the information passed back from the backup scan
1762 try {
1763 info = ud_parse_json(resp.i);
1764 // if (info.hasOwnProperty('multisite') && info.multisite && info.hasOwnProperty('same_url') && info.same_url) {
1765 if (info.hasOwnProperty('addui')) {
1766 console.log("Further UI options are being displayed");
1767 var addui = info.addui;
1768 report += '<div id="updraft_restoreoptions_ui">'+addui+'</div>';
1769 if (typeof JSON == 'object' && typeof JSON.stringify == 'function') {
1770 // If possible, remove from the stored info, to prevent passing back potentially large amounts of unwanted data
1771 delete info.addui;
1772 resp.i = JSON.stringify(info);
1773 }
1774 }
1775 if (info.hasOwnProperty('php_max_input_vars')) {
1776 php_max_input_vars = parseInt(info.php_max_input_vars);
1777 }
1778 if (info.hasOwnProperty('skipped_db_scan')) {
1779 skipped_db_scan = parseInt(info.skipped_db_scan);
1780 }
1781 } catch (err) {
1782 console.log(err);
1783 console.log(resp);
1784 }
1785 jQuery('#updraft_restorer_backup_info').val(resp.i);
1786 } else {
1787 jQuery('#updraft_restorer_backup_info').val();
1788 }
1789 jQuery('#updraft-restore-modal-stage2a').html(report);
1790 jQuery('.updraft-restore--next-step').text(updraftlion.restore);
1791 if (jQuery('#updraft-restore-modal-stage2a .updraft_select2').length > 0) {
1792 jQuery('#updraft-restore-modal-stage2a .updraft_select2').select2();
1793 }
1794 } catch (err) {
1795 console.log(data);
1796 console.log(err);
1797 jQuery('#updraft-restore-modal-stage2a').text(updraftlion.jsonnotunderstood+' '+updraftlion.errordata+": "+data).html();
1798 }
1799 }, { error_callback: function(response, status, error_code, resp) {
1800 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
1801 console.error(resp.fatal_error_message);
1802 jQuery('#updraft-restore-modal-stage2a').html('<p style="color: red;">'+resp.fatal_error_message+'</p>');
1803 alert(resp.fatal_error_message);
1804 } else {
1805 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
1806 jQuery('#updraft-restore-modal-stage2a').html('<p style="color: red;">'+error_message+'</p>');
1807 console.log(error_message);
1808 alert(error_message);
1809 console.log(response);
1810 }
1811 }
1812 });
1813 }
1814
1815
1816 function updraft_downloader_status(base, nonce, what, findex) {
1817 // Short-circuit. See previous versions for the old code.
1818 return;
1819 }
1820
1821 function updraft_downloader_status_update(download_status, response_raw) {
1822
1823 var cancel_repeat = 0;
1824
1825 jQuery(download_status).each(function (x, dstatus) {
1826 if (dstatus.base == '') return;
1827
1828 var stid = dstatus.base + dstatus.timestamp + '_' + dstatus.what + '_' + dstatus.findex;
1829 var stid_selector = '.' + stid;
1830
1831 if (dstatus.e != null) {
1832 jQuery(stid_selector + ' .raw').html('<strong>' + updraftlion.error + '</strong> ' + dstatus.e);
1833 console.log(dstatus);
1834 } else if (dstatus.p != null) {
1835 jQuery(stid_selector + '_st .dlfileprogress').width(dstatus.p + '%');
1836 // jQuery(stid_selector+'_st .dlsofar').html(Math.round(dstatus.s/1024));
1837 // jQuery(stid_selector+'_st .dlsize').html(Math.round(dstatus.t/1024));
1838
1839 // Is a restart appropriate?
1840 // dstatus.a, if set, indicates that a) the download is incomplete and b) the value is the number of seconds since the file was last modified...
1841 if (dstatus.a != null && dstatus.a > 0) {
1842 var timenow = (new Date).getTime();
1843 var lasttimebegan = jQuery(stid_selector).data('lasttimebegan');
1844 // Remember that this is in milliseconds
1845 var sincelastrestart = timenow - lasttimebegan;
1846 if (dstatus.a > 90 && sincelastrestart > 60000) {
1847 console.log(dstatus.timestamp + " " + dstatus.what + " " + dstatus.findex + ": restarting download: file_age=" + dstatus.a + ", sincelastrestart_ms=" + sincelastrestart);
1848 jQuery(stid_selector).data('lasttimebegan', (new Date).getTime());
1849
1850 var $original_button = jQuery('#updraft-navtab-backups-content .uddownloadform_' + dstatus.what + '_' + dstatus.timestamp + '_' + dstatus.findex);
1851
1852 var data = {
1853 type: dstatus.what,
1854 timestamp: dstatus.timestamp,
1855 findex: dstatus.findex
1856 };
1857
1858 var options = {
1859 action: 'updraft_download_backup',
1860 nonce_key: '_wpnonce',
1861 nonce: $original_button.data('wp_nonce').toString(),
1862 timeout: 10000
1863 };
1864
1865 updraft_send_command('updraft_download_backup', data, null, options);
1866
1867 jQuery(stid_selector).data('lasttimebegan', (new Date).getTime());
1868 }
1869 }
1870
1871 if (dstatus.m != null) {
1872 if (dstatus.p >= 100 && 'udrestoredlstatus_' == dstatus.base) {
1873 jQuery(stid_selector + ' .raw').html(dstatus.m);
1874 jQuery(stid_selector).fadeOut('slow', function () {
1875 remove_updraft_downloader(this, dstatus.what);
1876 updraft_restorer_checkstage2(0);
1877 });
1878 } else if (dstatus.p >= 100 && dstatus.base == 'udclonedlstatus_') {
1879 jQuery(stid_selector + ' .raw').html(dstatus.m);
1880 jQuery(stid_selector).fadeOut('slow', function () {
1881 remove_updraft_downloader(this, dstatus.what);
1882 });
1883 } else if (dstatus.p < 100 || dstatus.base != 'uddlstatus_') {
1884 jQuery(stid_selector + ' .raw').html(dstatus.m);
1885 } else {
1886 var file_ready_actions = updraftlion.fileready + ' ' + '(size: ' + convert_numeric_size_to_text(dstatus.s) + '). ' + updraftlion.actions + ':\
1887 <button class="button" type="button" onclick="updraftplus_downloadstage2(\''+ dstatus.timestamp + '\', \'' + dstatus.what + '\', \'' + dstatus.findex + '\')\">' + updraftlion.downloadtocomputer + '</button> \
1888 <button class="button" id="uddownloaddelete_'+ dstatus.timestamp + '_' + dstatus.what + '" type="button" onclick="updraftplus_deletefromserver(\'' + dstatus.timestamp + '\', \'' + dstatus.what + '\', \'' + dstatus.findex + '\')\">' + updraftlion.deletefromserver + '</button>';
1889
1890 if (dstatus.hasOwnProperty('can_show_contents') && dstatus.can_show_contents) {
1891 file_ready_actions += ' <button class="button" type="button" onclick="updraftplus_show_contents(\'' + dstatus.timestamp + '\', \'' + dstatus.what + '\', \'' + dstatus.findex + '\')\">' + updraftlion.browse_contents + '</button>';
1892 }
1893 jQuery(stid_selector + ' .raw').html(file_ready_actions);
1894 jQuery(stid_selector + '_st').remove();
1895 }
1896 }
1897 // dlstatus_lastlog = response_raw;
1898 } else if (dstatus.m != null) {
1899 jQuery(stid_selector + ' .raw').html(dstatus.m);
1900 } else {
1901 jQuery(stid_selector + ' .raw').html(updraftlion.jsonnotunderstood + ' (' + response_raw + ')');
1902 cancel_repeat = 1;
1903 }
1904 });
1905
1906 return cancel_repeat;
1907 }
1908
1909 /**
1910 * Converts a number of bytes into a suitable textual unit value
1911 *
1912 * @param {long} bytes
1913 * @returns string
1914 */
1915 function convert_numeric_size_to_text(bytes) {
1916 if (1024 > bytes) {
1917 return bytes + " b";
1918 } else if (1024 * 1024 >bytes) {
1919 return (bytes / 1024).toFixed(2) + " KB";
1920 } else if (1024 * 1024 * 1024 > bytes ) {
1921 return (bytes / (1024 * 1024)).toFixed(2) + " MB";
1922 } else {
1923 return (bytes / (1024 * 1024 * 1024)).toFixed(2) + " GB";
1924 }
1925 }
1926
1927 /**
1928 * Function that sets up a ajax call to start a backup
1929 *
1930 * @param {Integer} backupnow_nodb Indicate whether the database should be backed up: valid values are 0, 1
1931 * @param {Integer} backupnow_nofiles Indicate whether any files should be backed up: valid values are 0, 1
1932 * @param {Integer} backupnow_nocloud Indicate whether the backup should be uploaded to cloud storage: valid values are 0, 1
1933 * @param {String} onlythesefileentities A csv list of file entities to be backed up
1934 * @param {String} onlythesetableentities A csv list of table entities to be backed up
1935 * @param {Array} extradata any extra data to be added
1936 * @param {String} label A optional label to be added to a backup
1937 * @param {String} only_these_cloud_services An array of remote sorage locations to be backed up to
1938 */
1939 function updraft_backupnow_go(backupnow_nodb, backupnow_nofiles, backupnow_nocloud, onlythesefileentities, extradata, label, onlythesetableentities, only_these_cloud_services) {
1940
1941 var params = {
1942 backupnow_nodb: backupnow_nodb,
1943 backupnow_nofiles: backupnow_nofiles,
1944 backupnow_nocloud: backupnow_nocloud,
1945 backupnow_label: label,
1946 extradata: extradata
1947 };
1948
1949 if ('' != onlythesefileentities) {
1950 params.onlythisfileentity = onlythesefileentities;
1951 }
1952
1953 if ('' != onlythesetableentities) {
1954 params.onlythesetableentities = onlythesetableentities;
1955 }
1956
1957 if ('' != only_these_cloud_services) {
1958 params.only_these_cloud_services = only_these_cloud_services;
1959 }
1960
1961 params.always_keep = (typeof extradata.always_keep !== 'undefined') ? extradata.always_keep : 0;
1962 delete extradata.always_keep;
1963
1964 params.incremental = (typeof extradata.incremental !== 'undefined') ? extradata.incremental : 0;
1965 delete extradata.incremental;
1966
1967 params.db_anon_all = (typeof extradata.db_anon !== 'undefined' && typeof extradata.db_anon.all !== 'undefined') ? extradata.db_anon.all : 0;
1968 params.db_anon_non_staff = (typeof extradata.db_anon !== 'undefined' && typeof extradata.db_anon.non_staff !== 'undefined') ? extradata.db_anon.non_staff : 0;
1969 params.db_anon_wc_orders = (typeof extradata.db_anon !== 'undefined' && typeof extradata.db_anon.wc_orders !== 'undefined') ? extradata.db_anon.wc_orders : 0;
1970 if ('undefined' !== typeof extradata.db_anon) {
1971 delete extradata.db_anon.all;
1972 delete extradata.db_anon.non_staff;
1973 delete extradata.db_anon.wc_orders;
1974 }
1975
1976
1977 // Display Request start message
1978 if (!jQuery('.updraft_requeststart').length) {
1979 var requeststart_el = jQuery('<div class="updraft_requeststart" />').html('<span class="spinner"></span>'+updraftlion.requeststart);
1980 requeststart_el.data('remove', false);
1981 setTimeout(
1982 function() {
1983 requeststart_el.data('remove', true);
1984 },
1985 3000
1986 );
1987 setTimeout(
1988 function() {
1989 requeststart_el.remove();
1990 },
1991 75000
1992 );
1993 jQuery('#updraft_activejobsrow').before(requeststart_el);
1994 }
1995
1996 updraft_activejobslist_backupnownonce_only = 1;
1997 updraft_send_command('backupnow', params, function(resp) {
1998 if (resp.hasOwnProperty('error')) {
1999 jQuery('.updraft_requeststart').remove();
2000 alert(resp.error);
2001 return;
2002 }
2003 jQuery('#updraft_backup_started').html(resp.m);
2004 if (resp.hasOwnProperty('nonce')) {
2005 // Can't return it from this context
2006 updraft_backupnow_nonce = resp.nonce;
2007 console.log("UpdraftPlus: ID of started job: "+updraft_backupnow_nonce);
2008 }
2009 setTimeout(function() {
2010 updraft_activejobs_update(true);}, 500);
2011 });
2012 }
2013
2014 jQuery(function($) {
2015
2016 // actioned When the checkout embed is complete
2017 $(document).on('udp/checkout/done', function(e, data) {
2018 if (data.hasOwnProperty('product') && 'updraftpremium' === data.product && 'complete' === data.status) {
2019 $('.premium-upgrade-purchase-success').show();
2020 $('.updraft_feat_table').closest('section').hide();
2021 $('.updraft_premium_cta__action').hide();
2022 }
2023 });
2024
2025 // Advanced settings new menu button listeners
2026 $('.expertmode .advanced_settings_container .advanced_tools_button').on('click', function() {
2027 advanced_tool_hide($(this).attr("id"));
2028 });
2029
2030 function advanced_tool_hide(show_tool) {
2031
2032 $('.expertmode .advanced_settings_container .advanced_tools:not(".'+show_tool+'")').hide();
2033 $('.expertmode .advanced_settings_container .advanced_tools.'+show_tool).fadeIn('slow');
2034
2035 $('.expertmode .advanced_settings_container .advanced_tools_button:not(#'+show_tool+')').removeClass('active');
2036 $('.expertmode .advanced_settings_container .advanced_tools_button#'+show_tool).addClass('active');
2037
2038 }
2039 // https://github.com/select2/select2/issues/1246#issuecomment-71710835
2040 if (jQuery.ui && jQuery.ui.dialog && jQuery.ui.dialog.prototype._allowInteraction) {
2041 var ui_dialog_interaction = jQuery.ui.dialog.prototype._allowInteraction;
2042 jQuery.ui.dialog.prototype._allowInteraction = function(e) {
2043 if (jQuery(e.target).closest('.select2-dropdown').length) return true;
2044 return ui_dialog_interaction.apply(this, arguments);
2045 };
2046 }
2047
2048 // Check SFTP and FTP host as user edits
2049 $('#updraft-navtab-settings-content #remote-storage-holder').on('input', '.updraft_sftp_host_settings, .updraft_ftp_host_settings', function() {
2050 var notice_selector = $(this).closest('tr').find('[class^="updraft_"][class$="_host_error"]');
2051
2052 notice_selector.hide();
2053 if (/\/|^https?:/.test($(this).val())) {
2054 $(this).val($(this).val().replace(/^https?:|\/+/g, ''));
2055 notice_selector.show();
2056 }
2057 });
2058
2059 // Update WebDAV URL as user edits
2060 $('#updraft-navtab-settings-content #remote-storage-holder').on('change keyup paste', '.updraft_webdav_settings', function() {
2061 var attr_id = $(this).attr('id');
2062 if ('string' !== typeof attr_id) return;
2063 var parsed_attr_id = attr_id.match(/updraft_webdav_(.+)_(s-[^_]+)$/i);
2064 if (!parsed_attr_id || !parsed_attr_id[1] || !parsed_attr_id[2]) return;
2065 var instance_id = parsed_attr_id[2],
2066 webdav_input = parsed_attr_id[1].toLowerCase(),
2067 masked_password = '';
2068
2069 if ('host' === webdav_input) {
2070 $('.webdav-'+instance_id+' .updraft_webdav_host_error').hide();
2071 if ($(this).val().indexOf("@") >= 0) {
2072 $(this).val($(this).val().replaceAll('@', encodeURIComponent('@')));
2073 } else if ($(this).val().indexOf("/") >= 0) {
2074 $(this).val($(this).val().replaceAll('/', ''));
2075 $('.webdav-'+instance_id+' .updraft_webdav_host_error').show();
2076 }
2077 } else if ('path' === webdav_input && 0 == $(this).val().indexOf('/')) {
2078 $(this).val($(this).val().replace(/^[\/]+/, ''));
2079 }
2080
2081 var webdav = $('#updraft_webdav_webdav_' + instance_id).val(),
2082 host = $('#updraft_webdav_host_' + instance_id).val() || '',
2083 user = $('#updraft_webdav_user_' + instance_id).val() || '',
2084 password = $('#updraft_webdav_pass_' + instance_id).val() || '',
2085 port = $('#updraft_webdav_port_' + instance_id).val() || '',
2086 path = $('#updraft_webdav_path_' + instance_id).val() || '';
2087
2088 if (password) {
2089 masked_password = password.replace(/./gi,'*');
2090 }
2091 if (user && password) {
2092 user += ':';
2093 }
2094 if ((user || password) && host) {
2095 masked_password += '@';
2096 password += '@';
2097 }
2098 if (host && port) {
2099 host += ':';
2100 }
2101 if (path) {
2102 path = '/' + path;
2103 }
2104
2105 $('#updraft_webdav_url_' + instance_id).val(webdav + user + password + host + port + path);
2106 $('#updraft_webdav_masked_url_' + instance_id).val(webdav + user + masked_password + host + port + path);
2107 });
2108
2109 $('div.ud-phpseclib-notice').on('click', 'button.notice-dismiss', function (event) {
2110 event.stopImmediatePropagation();
2111 updraft_send_command('dismiss_phpseclib_notice', null, function(resp, status, response) {
2112 if (!resp.hasOwnProperty('success') || 1 !== resp.success) {
2113 console.log(resp);
2114 alert(updraftlion.unexpectedresponse+' '+response);
2115 }
2116 });
2117 });
2118
2119 // Delete button
2120 $('#updraft-navtab-backups-content').on('click', '.js--delete-selected-backups', function(e) {
2121 e.preventDefault();
2122 updraft_deleteallselected();
2123 });
2124
2125 $('#updraft-navtab-backups-content').on('click', '.updraft_existing_backups .backup-select input', function(e) {
2126 // e.preventDefault();
2127 updraft_backups_selection.toggle($(this).closest('.updraft_existing_backups_row'));
2128 });
2129
2130 $('#updraft-navtab-backups-content').on('click', '#cb-select-all', function(e) {
2131 if ($(this).is(':checked')) {
2132 updraft_backups_selection.selectAll();
2133 } else {
2134 updraft_backups_selection.deselectAll();
2135 }
2136 });
2137
2138 $('#updraft-wrap').on('click', '[id^=updraftplus_manual_authorisation_submit_]', function(e) {
2139 e.preventDefault();
2140 var method = $(this).data('method');
2141 var auth_data = $('#updraftplus_manual_authentication_data_'+method).val();
2142 $('#updraftplus_manual_authentication_error_'+method).text();
2143 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method+' .updraftplus_spinner.spinner').addClass('visible');
2144 $('#updraftplus_manual_authorisation_submit_'+method).prop('disabled', true);
2145 manual_remote_storage_auth(method, auth_data);
2146 });
2147
2148 /**
2149 * This method will send the ajax request to manually authenticate the remote storage method and then update the page with the response
2150 *
2151 * @param {string} method - the remote storage method
2152 * @param {string} auth_data - the auth data as a base64 json encoded string
2153 */
2154 function manual_remote_storage_auth(method, auth_data) {
2155 updraft_send_command('manual_remote_storage_authentication', {method: method, auth_data: auth_data}, function(response) {
2156 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method+' .updraftplus_spinner.spinner').removeClass('visible');
2157 if (response.hasOwnProperty('result') && 'success' === response.result) {
2158 $('#updraft-wrap .updraftplus-top-menu').before(response.data);
2159 $('#updraft-wrap #updraftplus_manual_authorisation_template_'+method).parent().remove();
2160 $('#updraft-wrap .updraft_authenticate_'+method).remove();
2161 } else if (response.hasOwnProperty('result') && 'error' === response.result) {
2162 $('#updraftplus_manual_authentication_error_'+method).text(response.data);
2163 $('#updraftplus_manual_authorisation_submit_'+method).prop('disabled', false);
2164 }
2165 });
2166 }
2167
2168
2169 $('#updraft-navtab-backups-content').on('click', '.js--select-all-backups', function(e) {
2170 updraft_backups_selection.selectAll();
2171 });
2172
2173 $('#updraft-navtab-backups-content').on('click', '.js--deselect-all-backups', function(e) {
2174 updraft_backups_selection.deselectAll();
2175 });
2176
2177 $('#updraft-navtab-backups-content').on('click', '.updraft_existing_backups .updraft_existing_backups_row', function(e) {
2178 if (!e.ctrlKey && !e.metaKey) return;
2179 if (e.shiftKey) {
2180 // it's multiple range selection, it requires the user to hold shift+ctrl buttons during the range selection, the initial and the new starting index is saved in firstMultipleSelectionIndex variable
2181 if ("undefined" == typeof updraft_backups_selection.firstMultipleSelectionIndex) {
2182 // if all the above conditions are fulfilled then we need to set up the keyup event handler only for range selection operation. By doing it, we also ignore the Apple Command (metaKey) keycode checking which varies among the browser https://unixpapa.com/js/key.html
2183 $(document).on('keyup.MultipleSelection', function(e) {
2184 // multiple range selection operation requires the user to hold ctrl/cmd + shift buttons all the time during the selections, the range selection operation will be canceled if the user releases one of the held buttons (shitf or ctrl/cmd) and if that happens the highlight mode will stop working
2185 updraft_backups_selection.unregister_highlight_mode();
2186 // once this event handler has been triggered and the highlight mode has been turned off, this event handler needs to be removed by using its namespace .MultipleSelection
2187 $(document).off('.MultipleSelection');
2188 });
2189 updraft_backups_selection.select(this);
2190 $(this).addClass('range-selection-start');
2191 updraft_backups_selection.register_highlight_mode();
2192 } else {
2193 updraft_backups_selection.selectAllInBetween(this);
2194 jQuery('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').removeClass('range-selection');
2195 }
2196 // set the new starting index to the ending range index
2197 updraft_backups_selection.firstMultipleSelectionIndex = this.rowIndex - 1;
2198 } else {
2199 updraft_backups_selection.toggle(this);
2200 }
2201 });
2202
2203 updraft_backups_selection.checkSelectionStatus();
2204
2205 $('#updraft-navtab-addons-content .wrap').on('click', '.updraftplus_com_login .ud_connectsubmit', function (e) {
2206 e.preventDefault();
2207 var email = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_email').val();
2208 var password = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_password').val();
2209 var auto_update = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_auto_updates').is(':checked') ? 1: 0;
2210 var auto_udc_connect = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_auto_udc_connect').is(':checked') ? 1: 0;
2211 var options = {
2212 email: email,
2213 password: password,
2214 auto_update: auto_update,
2215 auto_udc_connect: auto_udc_connect
2216 };
2217 updraftplus_com_login.submit(options);
2218 });
2219
2220 $('#updraft-navtab-addons-content .wrap').on('keydown', '.updraftplus_com_login input', function (e) {
2221 if (13 == e.which) {
2222 e.preventDefault();
2223 var email = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_email').val();
2224 var password = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_password').val();
2225 var auto_update = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_auto_updates').is(':checked') ? 1: 0;
2226 var auto_udc_connect = $('#updraft-navtab-addons-content .wrap .updraftplus_com_login #updraftplus-addons_options_auto_udc_connect').is(':checked') ? 1: 0;
2227 var options = {
2228 email: email,
2229 password: password,
2230 auto_update: auto_update,
2231 auto_udc_connect: auto_udc_connect
2232 };
2233 updraftplus_com_login.submit(options);
2234 }
2235 });
2236
2237 $('#updraft-navtab-migrate-content').on('click', '.updraftclone_show_step_1', function (e) {
2238 $('.updraftplus-clone').addClass('opened');
2239 $('.updraftclone_show_step_1').hide();
2240 $('.updraft_migrate_widget_temporary_clone_stage1').show();
2241 $('.updraft_migrate_widget_temporary_clone_stage0').hide();
2242 });
2243
2244 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_widget_temporary_clone_show_stage0', function(e) {
2245 e.preventDefault();
2246 $('.updraft_migrate_widget_temporary_clone_stage0').toggle();
2247 });
2248
2249 // First tab setup
2250 setup_migrate_tabs();
2251
2252 // hide section when clicking the close button
2253 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_widget_module_content .close', function (e) {
2254 $('.updraft_migrate_intro').show();
2255 $(this).closest('.updraft_migrate_widget_module_content').hide();
2256 });
2257
2258 $('#updraft-navtab-migrate-content').on('click', '#updraft_migrate_tab_alt .close', function (e) {
2259 e.preventDefault();
2260 $('.updraft_migrate_intro').show();
2261 $('#updraft_migrate_tab_alt').html('').hide();
2262 });
2263
2264 // Migrate show Add site button
2265 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_add_site--trigger', function (e) {
2266 e.preventDefault();
2267 $('.updraft_migrate_add_site').toggle();
2268 });
2269
2270 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_widget_module_content .updraftplus_com_login .ud_connectsubmit', function (e) {
2271 e.preventDefault();
2272 var email = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_email').val();
2273 var password = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_password').val();
2274 var tfa = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_two_factor_code').val();
2275 var consent = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login .temporary_clone_terms_and_conditions').is(':checked') ? 1 : 0;
2276 var options = {
2277 form_data: {
2278 email: email,
2279 password: password,
2280 two_factor_code: tfa,
2281 consent: consent
2282 }
2283 };
2284 if (!email || !password) {
2285 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login_status').html('<b>' + updraftlion.error + '</b> ' + updraftlion.username_password_required).show();
2286 } else {
2287 temporary_clone_submit(options);
2288 }
2289 });
2290
2291 $('#updraft-navtab-migrate-content').on('keydown', '.updraft_migrate_widget_module_content .updraftplus_com_login input', function (e) {
2292 if (13 == e.which) {
2293 e.preventDefault();
2294 var email = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_email').val();
2295 var password = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_password').val();
2296 var tfa = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_two_factor_code').val();
2297 var consent = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login .temporary_clone_terms_and_conditions').is(':checked') ? 1 : 0;
2298 var options = {
2299 form_data: {
2300 email: email,
2301 password: password,
2302 two_factor_code: tfa,
2303 consent: consent
2304 }
2305 };
2306 if (!email || !password) {
2307 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login_status').html('<b>' + updraftlion.error + '</b> ' + updraftlion.username_password_required).show();
2308 } else {
2309 temporary_clone_submit(options);
2310 }
2311 }
2312 });
2313
2314 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_widget_module_content .updraftplus_com_key .ud_key_connectsubmit', function (e) {
2315 e.preventDefault();
2316 var clone_key = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key #temporary_clone_options_key').val();
2317 var consent = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key .temporary_clone_terms_and_conditions').is(':checked') ? 1 : 0;
2318 var options = {
2319 form_data: {
2320 clone_key: clone_key,
2321 consent: consent
2322 }
2323 };
2324 if (!clone_key) {
2325 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key_status').html('<b>' + updraftlion.error + '</b> ' + updraftlion.clone_key_required).show();
2326 } else {
2327 temporary_clone_key_submit(options);
2328 }
2329 });
2330
2331 $('#updraft-navtab-migrate-content').on('keydown', '.updraft_migrate_widget_module_content .updraftplus_com_key input', function (e) {
2332 if (13 == e.which) {
2333 e.preventDefault();
2334 var clone_key = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key #temporary_clone_options_key').val();
2335 var consent = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key .temporary_clone_terms_and_conditions').is(':checked') ? 1 : 0;
2336 var options = {
2337 form_data: {
2338 clone_key: clone_key,
2339 consent: consent
2340 }
2341 };
2342 if (!clone_key) {
2343 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key_status').html('<b>' + updraftlion.error + '</b> ' + updraftlion.clone_key_required).show();
2344 } else {
2345 temporary_clone_key_submit(options);
2346 }
2347 }
2348 });
2349
2350 $('#updraft-navtab-migrate-content').on('change', '.updraft_migrate_widget_module_content #updraftplus_clone_php_options', function () {
2351 var php_version = $(this).data('php_version');
2352 var selected_version = $(this).val();
2353
2354 if (selected_version < php_version) {
2355 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html(updraftlion.clone_version_warning);
2356 } else {
2357 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html('');
2358 }
2359 });
2360
2361 $('#updraft-navtab-migrate-content').on('change', '.updraft_migrate_widget_module_content #updraftplus_clone_wp_options', function () {
2362 var wp_version = $(this).data('wp_version');
2363 var selected_version = $(this).val();
2364
2365 if (selected_version < wp_version) {
2366 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html(updraftlion.clone_version_warning);
2367 } else {
2368 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html('');
2369 }
2370 });
2371
2372 $('#updraft-navtab-migrate-content').on('change', '.updraft_migrate_widget_module_content #updraftplus_clone_backup_options', function() {
2373
2374 // reset the package list
2375 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options > option').each(function() {
2376 var value = $(this).val();
2377 if ('starter' == value) $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options option[value="'+value+'"]').prop('selected', true);
2378 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options option[value="'+value+'"]').prop("disabled", false);
2379 });
2380
2381 var clone_backup_select = $(this).find('option:selected');
2382
2383 if ('current' == $(clone_backup_select).data('nonce') || 'wp_only' == $(clone_backup_select).data('nonce')) return;
2384
2385 var total_size = $(clone_backup_select).data('size');
2386
2387 // Disable packages that are to small for this backup set, then set the first available package as the selected option
2388 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options > option').each(function() {
2389 var size = $(this).data('size');
2390 var value = $(this).val();
2391 if (total_size >= size) {
2392 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options option[value="'+value+'"]').prop("disabled", true);
2393 } else {
2394 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options option[value="'+value+'"]').prop('selected', true);
2395 return false;
2396 }
2397 });
2398 });
2399
2400 $('#updraft-navtab-migrate-content').on('click', '.updraft_migrate_widget_module_content #updraft_migrate_createclone', function (e) {
2401 e.preventDefault();
2402
2403 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraft_migrate_createclone').prop('disabled', true);
2404 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html('');
2405 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_spinner.spinner').addClass('visible');
2406
2407 var clone_id = $(this).data('clone_id');
2408 var secret_token = $(this).data('secret_token');
2409 var php_version = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_php_options').val();
2410 var wp_version = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_wp_options').val();
2411 var region = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_region_options').val();
2412 var package = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_package_options').val();
2413 var updraftclone_branch = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_updraftclone_branch').val();
2414 var updraftplus_branch = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_updraftplus_branch').val();
2415 var admin_only = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_admin_login_options').is(':checked');
2416 var use_queue = $('#updraftplus_clone_use_queue').is(':checked') ? 1 : 0;
2417 var db_anon_all = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_backupnow_db_anon_all').is(':checked') ? 1 : 0;
2418 var db_anon_non_staff = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_backupnow_db_anon_non_staff').is(':checked') ? 1 : 0;
2419 var db_anon_wc_orders = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_backupnow_db_anon_wc_order_data').is(':checked') ? 1 : 0;
2420
2421 var backup_nonce = 'current';
2422 var backup_timestamp = 'current';
2423 var clone_backup_select_length = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_backup_options').length;
2424 var clone_backup_select = $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraftplus_clone_backup_options').find('option:selected');
2425 if (0 !== clone_backup_select_length && 'undefined' !== typeof clone_backup_select) {
2426 backup_nonce = clone_backup_select.data('nonce');
2427 backup_timestamp = clone_backup_select.data('timestamp');
2428 }
2429
2430 var options = {
2431 form_data: {
2432 clone_id: clone_id,
2433 secret_token: secret_token,
2434 install_info: {
2435 php_version: php_version,
2436 wp_version: wp_version,
2437 region: region,
2438 package: package,
2439 admin_only: admin_only,
2440 updraftclone_branch: ('undefined' === typeof updraftclone_branch) ? '' : updraftclone_branch,
2441 updraftplus_branch: ('undefined' === typeof updraftplus_branch) ? '' : updraftplus_branch,
2442 use_queue: ('undefined' === typeof use_queue) ? 1 : use_queue
2443 }
2444 }
2445 };
2446
2447 var backup_options = {
2448 db_anon_all: db_anon_all,
2449 db_anon_non_staff: db_anon_non_staff,
2450 db_anon_wc_orders: db_anon_wc_orders,
2451 clone_region: region
2452 }
2453
2454 if ('wp_only' === backup_nonce) {
2455 options['form_data']['install_info']['wp_only'] = 1;
2456 }
2457
2458 temporary_clone_process_create(options, backup_timestamp, backup_nonce, backup_options);
2459 });
2460
2461 // Create a updraftplus_com_login object, to store functions and variables
2462 var updraftplus_com_login = {};
2463
2464 updraftplus_com_login.set_status = function(status) {
2465 $('#updraft-navtab-addons-content .wrap').find('.updraftplus_spinner.spinner').text(status);
2466 }
2467
2468 updraftplus_com_login.show_loader = function() {
2469 $('#updraft-navtab-addons-content .wrap').find('.updraftplus_spinner.spinner').addClass('visible');
2470 $('#updraft-navtab-addons-content .wrap').find('.ud_connectsubmit').prop('disabled', 'disabled');
2471 }
2472
2473 updraftplus_com_login.hide_loader = function() {
2474 $('#updraft-navtab-addons-content .wrap').find('.updraftplus_spinner.spinner').removeClass('visible').text(updraftlion.processing);
2475 $('#updraft-navtab-addons-content .wrap').find('.ud_connectsubmit').prop('disabled', false);
2476 }
2477
2478 /*
2479 This function will send an AJAX request to the backend to check the users credentials, then it will either inform the user of any errors or if there are none it will submit the form.
2480 @param {array} options - an array that includes the users email and password
2481 */
2482
2483 updraftplus_com_login.submit = function(options) {
2484
2485 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html('').hide();
2486
2487 if (this.stage) {
2488 switch (this.stage) {
2489 case 'connect_udc':
2490 case 'connect_udc_TFA':
2491 // update data in object
2492 var email = $('#updraftplus-addons_options_email').val();
2493 var password = $('#updraftplus-addons_options_password').val();
2494 this.login_data.email = email;
2495 this.login_data.password = password;
2496 // connect_udc again
2497 this.connect_udc();
2498 break;
2499 case 'create_key':
2500 this.create_key();
2501 break;
2502 default:
2503 this.stage = null;
2504 updraftplus_com_login.submit();
2505 break;
2506 }
2507
2508 return;
2509 }
2510
2511 this.set_status(updraftlion.connecting);
2512 this.show_loader();
2513
2514 updraft_send_command('updraftplus_com_login_submit', {
2515 data: options,
2516 }, function (response) {
2517 if (response.hasOwnProperty('success')) {
2518
2519 // logged in was successful, so create a key if the checkbox was checked.
2520 if ($('#updraftplus-addons_options_auto_udc_connect').is(':checked')) {
2521
2522 this.login_data = {
2523 email: options.email,
2524 password: options.password,
2525 i_consent: 1,
2526 two_factor_code: ''
2527 };
2528
2529 // CREATE KEY
2530 updraftplus_com_login.create_key();
2531
2532 } else {
2533 updraftplus_com_login.hide_loader();
2534 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login').trigger('submit');
2535 }
2536 } else if (response.hasOwnProperty('error')) {
2537 updraftplus_com_login.hide_loader();
2538 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(response.message).show();
2539 }
2540 }.bind(this));
2541 }
2542
2543 updraftplus_com_login.create_key = function() {
2544
2545 this.stage = 'create_key';
2546
2547 this.set_status(updraftlion.udc_cloud_connected);
2548 this.show_loader();
2549
2550 var command_data = {
2551 where_send: '__updraftpluscom',
2552 key_description: '',
2553 key_size: null,
2554 mothership_firewalled: 0
2555 };
2556
2557 // updraftcentral_cloud_show_spinner(modal);
2558 updraft_send_command('updraftcentral_create_key', command_data, function(response) {
2559 // updraftcentral_cloud_hide_spinner(modal);
2560 try {
2561 var data = ud_parse_json(response);
2562 if (data.hasOwnProperty('error')) {
2563 console.log(data);
2564 return;
2565 }
2566
2567 if (data.hasOwnProperty('bundle')) {
2568
2569 console.log('bundle', data.bundle);
2570
2571 this.login_data.key = data.bundle,
2572 this.stage = 'connect_udc';
2573
2574 updraftplus_com_login.connect_udc();
2575
2576 } else {
2577 if (data.hasOwnProperty('r')) {
2578 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(updraftlion.trouble_connecting).show();
2579 alert(data.r);
2580 } else {
2581 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(updraftlion.trouble_connecting).show();
2582 console.log(data);
2583 }
2584 updraftplus_com_login.hide_loader();
2585 }
2586 } catch (err) {
2587 console.log(err);
2588 updraftplus_com_login.hide_loader();
2589 }
2590 }.bind(this), { json_parse: false });
2591
2592 }
2593
2594 updraftplus_com_login.connect_udc = function() {
2595
2596 var container = $('#updraft-navtab-addons-content .wrap');
2597
2598 updraftplus_com_login.set_status(updraftlion.udc_cloud_key_created);
2599 updraftplus_com_login.show_loader();
2600
2601 if ('connect_udc_TFA' == this.stage) {
2602 this.login_data.two_factor_code = container.find('input#updraftplus-addons_options_two_factor_code').val();
2603 updraftplus_com_login.set_status(updraftlion.checking_tfa_code);
2604 }
2605
2606 var login_data = { form_data: this.login_data };
2607 login_data.form_data.addons_options_connect = 1;
2608
2609 // Final step, connect UDC with the Key and all.
2610 updraft_send_command('process_updraftcentral_login', login_data, function(login_response) {
2611 try {
2612
2613 var data = ud_parse_json(login_response);
2614
2615 if (data.hasOwnProperty('error')) {
2616 if ('incorrect_password' === data.code) {
2617 container.find('.tfa_fields').hide();
2618 container.find('.non_tfa_fields').show();
2619 container.find('input#updraftplus-addons_options_two_factor_code').val('');
2620 container.find('input#updraftplus-addons_options_password').val('').trigger('focus');
2621 }
2622 if ('no_key_found' === data.code) {
2623 this.stage = 'create_key';
2624 }
2625
2626 // Continue with UpdraftPlus account even if the user has used all UpdraftCentral licences
2627 if ('no_licences_available' === data.code) {
2628 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(updraftlion.login_udc_no_licences_short).show();
2629 data.status = 'authenticated';
2630 container.find('input[name="_wp_http_referer"]').val(function(index, val) {
2631 return val + '&udc_connect=0';
2632 });
2633 } else {
2634 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(data.message).show();
2635 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').find('a').attr('target', '_blank');
2636 console.log(data);
2637 updraftplus_com_login.hide_loader();
2638 return;
2639 }
2640 }
2641
2642 if (data.hasOwnProperty('tfa_enabled') && true == data.tfa_enabled) {
2643 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html('').hide();
2644 container.find('.non_tfa_fields').hide();
2645 container.find('.tfa_fields').show();
2646 container.find('input#updraftplus-addons_options_two_factor_code').trigger('focus');
2647 this.stage = 'connect_udc_TFA';
2648 }
2649
2650 if ('authenticated' === data.status) {
2651 container.find('.non_tfa_fields').hide();
2652 container.find('.tfa_fields').hide();
2653 container.find('.updraft-after-form-table').hide();
2654
2655 this.stage = null;
2656
2657 $('#updraft-navtab-addons-content .wrap .updraftplus_com_login_status').html(updraftlion.login_successful_short).show().addClass('success');
2658
2659 // submit the form (to reload the page).
2660 setTimeout(function() {
2661 $('#updraft-navtab-addons-content .wrap form.updraftplus_com_login').trigger('submit');
2662 }, 1000);
2663 }
2664
2665 } catch (err) {
2666 console.log(err);
2667 }
2668 updraftplus_com_login.hide_loader();
2669 }.bind(this), { json_parse: false });
2670
2671
2672 }
2673
2674 /**
2675 * This function will send an AJAX request to the backend to check the users credentials, then it will either inform the user of any errors or display UI elements that include their token count and a way to create new clones.
2676 *
2677 * @param {array} options - an array that includes the users email and password
2678 */
2679 function temporary_clone_submit(options) {
2680 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login_status').html('').hide();
2681 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login .updraftplus_spinner.spinner').addClass('visible');
2682 updraft_send_command('process_updraftplus_clone_login', options, function (response) {
2683 try {
2684 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login .updraftplus_spinner.spinner').removeClass('visible');
2685
2686 if (response.hasOwnProperty('status') && 'error' == response.status) {
2687 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login_status').html(response.message).show();
2688 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .tfa_fields').hide();
2689 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .non_tfa_fields').show();
2690 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_login #temporary_clone_options_two_factor_code').val('');
2691 return;
2692 }
2693
2694 if (response.hasOwnProperty('tfa_enabled') && true == response.tfa_enabled) {
2695 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .non_tfa_fields').hide();
2696 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .tfa_fields').show();
2697 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 input#temporary_clone_options_two_factor_code').trigger('focus');
2698 }
2699
2700 if ('authenticated' === response.status) {
2701 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1').hide();
2702 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .non_tfa_fields').show();
2703 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 .tfa_fields').hide();
2704 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1 input#temporary_clone_options_two_factor_code').val('');
2705 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').show();
2706 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').html(response.html);
2707 if (response.hasOwnProperty('clone_info') && response.clone_info.hasOwnProperty('expires_after')) temporary_clone_timer(response.clone_info.expires_after);
2708 }
2709 } catch (err) {
2710 console.log(err);
2711 }
2712 });
2713 }
2714
2715 /**
2716 * This function will send an AJAX request to the backend to check the clone key, then it will either inform the user of any errors or display UI elements that include their token count and a way to create new clones.
2717 *
2718 * @param {array} options - an array that includes the clone key
2719 */
2720 function temporary_clone_key_submit(options) {
2721 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key_status').html('').hide();
2722 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key .updraftplus_spinner.spinner').addClass('visible');
2723 updraft_send_command('process_updraftplus_clone_login', options, function (response) {
2724 try {
2725 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key .updraftplus_spinner.spinner').removeClass('visible');
2726
2727 if (response.hasOwnProperty('status') && 'error' == response.status) {
2728 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_com_key_status').html(response.message).show();
2729 return;
2730 }
2731
2732 if ('authenticated' === response.status) {
2733 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1').hide();
2734 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').show();
2735 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').html(response.html);
2736 if (response.hasOwnProperty('clone_info') && response.clone_info.hasOwnProperty('expires_after')) temporary_clone_timer(response.clone_info.expires_after);
2737 }
2738 } catch (err) {
2739 console.log(err);
2740 }
2741 });
2742 }
2743
2744 /**
2745 * This function will add a timer to reset the UI if the user does not create the clone before it expires
2746 *
2747 * @param {integer} expires_after - the clone expires time in seconds
2748 */
2749 function temporary_clone_timer(expires_after) {
2750
2751 // the expires_after time is in seconds we need it in milliseconds for the setTimeout function
2752 var timeout = expires_after * 1000;
2753
2754 temporary_clone_timeout = setTimeout(function () {
2755 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').hide();
2756 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').html('');
2757 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage1').show();
2758 }, timeout);
2759 }
2760
2761 /**
2762 * This function will check if we are using an existing backup and if anything needs downloading before proceeding to process the clone create command
2763 *
2764 * @param {array} options - an array of options to create the clone
2765 * @param {string} backup_timestamp - the timestamp of the backup we want to use or 'current' to create a new backup
2766 * @param {string} backup_nonce - the backup nonce of the backup we want to use or 'current' to create a new backup
2767 * @param {array} backup_options - an array of options for the backup
2768 */
2769 function temporary_clone_process_create(options, backup_timestamp, backup_nonce, backup_options) {
2770
2771 var which_to_download = '';
2772 if ('current' != backup_timestamp) {
2773 updraft_send_command('whichdownloadsneeded', {
2774 updraftplus_clone: true,
2775 timestamp: backup_timestamp
2776 }, function (response) {
2777 if (response.hasOwnProperty('downloads')) {
2778 console.log('UpdraftPlus: items which still require downloading follow');
2779 which_to_download = response.downloads;
2780 console.log(which_to_download);
2781 }
2782
2783 // Kick off any downloads, if needed
2784 if (0 == which_to_download.length) return;
2785
2786 for (var i = 0; i < which_to_download.length; i++) {
2787 // updraft_downloader(base, backup_timestamp, what, whicharea, set_contents, prettydate, async)
2788 updraft_downloader('udclonedlstatus_', backup_timestamp, which_to_download[i][0], '#ud_downloadstatus3', which_to_download[i][1], '', false);
2789 }
2790
2791 }, {
2792 alert_on_error: false, error_callback: function (response, status, error_code, resp) {
2793 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
2794 console.error(resp.fatal_error_message);
2795 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html('<p style="color:red;">' + resp.fatal_error_message + '</p>');
2796 } else {
2797 var error_message = "updraft_send_command: error: " + status + " (" + error_code + ")";
2798 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html('<p style="color:red; margin: 5px;">' + error_message + '</p>');
2799 console.log(error_message);
2800 console.log(response);
2801 }
2802 }
2803 });
2804 }
2805
2806 setTimeout(function () {
2807 if (0 != which_to_download.length) {
2808 temporary_clone_process_create(options, backup_timestamp, backup_nonce, backup_options);
2809 return;
2810 }
2811 var clone_id = options['form_data']['clone_id'];
2812 var secret_token = options['form_data']['secret_token'];
2813 updraft_send_command('process_updraftplus_clone_create', options, function (response) {
2814 try {
2815 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraft_migrate_createclone').prop('disabled', false);
2816 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_spinner.spinner').removeClass('visible');
2817
2818 if (response.hasOwnProperty('status') && 'error' == response.status) {
2819 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html(updraftlion.error + ' ' + response.message).show();
2820 return;
2821 }
2822
2823 if ('success' === response.status) {
2824 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage2').hide();
2825 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage3').show();
2826 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraft_migrate_widget_temporary_clone_stage3').html(response.html);
2827
2828 // remove the clone timeout as the clone has now been created
2829 if (temporary_clone_timeout) clearTimeout(temporary_clone_timeout);
2830
2831 // check if the response includes a secret token, if it does we have claimed a clone from the queue and need to update our current secret token to the one that belongs to the claimed clone
2832 if (response.hasOwnProperty('secret_token')) {
2833 secret_token = response.secret_token;
2834 }
2835
2836 if ('wp_only' === backup_nonce) {
2837 jQuery('#updraft_clone_progress .updraftplus_spinner.spinner').addClass('visible');
2838 temporary_clone_poll(clone_id, secret_token);
2839 } else {
2840 jQuery('#updraft_clone_progress .updraftplus_spinner.spinner').addClass('visible');
2841 temporary_clone_boot_backup(clone_id, secret_token, response.url, response.key, backup_nonce, backup_timestamp, backup_options);
2842 }
2843 }
2844 } catch (err) {
2845 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraft_migrate_createclone').prop('disabled', false);
2846 console.log("Error when processing the response of process_updraftplus_clone_create (as follows)");
2847 console.log(err);
2848 }
2849 });
2850 }, 5000);
2851 }
2852
2853 /**
2854 * This function will send an AJAX request to the backend to start a clone backup job
2855 *
2856 * @param {string} clone_id - the clone id
2857 * @param {string} secret_token - the clone secret
2858 * @param {string} clone_url - the clone url
2859 * @param {string} key - the migration key
2860 * @param {string} backup_nonce - the nonce for the backup we want to use or 'current' for a fresh backup
2861 * @param {string} backup_timestamp - the timestamp for the backup we want to use or 'current' for a fresh backup
2862 * @param {array} backup_options - an array of options for the backup
2863 */
2864 function temporary_clone_boot_backup(clone_id, secret_token, clone_url, key, backup_nonce, backup_timestamp, backup_options) {
2865
2866 var params = {
2867 updraftplus_clone_backup: 1,
2868 backupnow_nodb: 0,
2869 backupnow_nofiles: 0,
2870 backupnow_nocloud: 0,
2871 backupnow_label: 'UpdraftClone',
2872 extradata: '',
2873 onlythisfileentity: 'plugins,themes,uploads,others',
2874 clone_id: clone_id,
2875 secret_token: secret_token,
2876 clone_url: clone_url,
2877 key: key,
2878 backup_nonce: backup_nonce,
2879 backup_timestamp: backup_timestamp,
2880 db_anon_all: backup_options['db_anon_all'],
2881 db_anon_non_staff: backup_options['db_anon_non_staff'],
2882 db_anon_wc_orders: backup_options['db_anon_wc_orders'],
2883 clone_region: backup_options['clone_region']
2884 };
2885
2886 updraft_activejobslist_backupnownonce_only = 1;
2887
2888 updraft_send_command('backupnow', params, function (response) {
2889 jQuery('#updraft_clone_progress .updraftplus_spinner.spinner').removeClass('visible');
2890 jQuery('#updraft_backup_started').html(response.m);
2891 if (response.hasOwnProperty('nonce')) {
2892 // Can't return it from this context
2893 updraft_backupnow_nonce = response.nonce;
2894 updraft_clone_jobs.push(updraft_backupnow_nonce);
2895 updraft_inpage_success_callback = function () {
2896 jQuery('#updraft_clone_activejobsrow').hide();
2897 // If user aborts the job
2898 if (updraft_aborted_jobs[updraft_backupnow_nonce]) {
2899 jQuery('#updraft_clone_progress').html(updraftlion.clone_backup_aborted);
2900 } else {
2901 jQuery('#updraft_clone_progress').html(updraftlion.clone_backup_complete);
2902 }
2903 };
2904 console.log("UpdraftPlus: ID of started job: " + updraft_backupnow_nonce);
2905 }
2906
2907 updraft_activejobs_update(true);
2908 });
2909 }
2910
2911 /**
2912 * This function will send an AJAX request to the backend to poll for the clones install information
2913 *
2914 * @param {string} clone_id - the clone id
2915 * @param {string} secret_token - the clone secret
2916 */
2917 function temporary_clone_poll(clone_id, secret_token) {
2918 var options = {
2919 clone_id: clone_id,
2920 secret_token: secret_token,
2921 };
2922
2923 setTimeout(function () {
2924 updraft_send_command('process_updraftplus_clone_poll', options, function (response) {
2925 if (response.hasOwnProperty('status')) {
2926
2927 if ('error' == response.status) {
2928 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_clone_status').html(updraftlion.error + ' ' + response.message).show();
2929 return;
2930 }
2931
2932 if ('success' === response.status) {
2933 if (response.hasOwnProperty('data') && response.data.hasOwnProperty('wordpress_credentials')) {
2934 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content .updraftplus_spinner.spinner').removeClass('visible');
2935 $('#updraft-navtab-migrate-content .updraft_migrate_widget_module_content #updraft_clone_progress').append('<br>WordPress ' + updraftlion.credentials + ':<br>' + updraftlion.username + ': ' + response.data.wordpress_credentials.username + '<br>' + updraftlion.password + ': ' + response.data.wordpress_credentials.password);
2936 return;
2937 }
2938 }
2939 } else {
2940 console.log(response);
2941 }
2942 temporary_clone_poll(clone_id, secret_token);
2943 });
2944 }, 60000);
2945 }
2946
2947 $('#updraft-navtab-settings-content #remote-storage-holder').on('click', '.updraftplusmethod a.updraft_add_instance', function(e) {
2948 e.preventDefault();
2949
2950 updraft_settings_form_changed = true;
2951 load_save_button();
2952
2953 var method = $(this).data('method');
2954 add_new_instance(method);
2955 });
2956
2957 $('#updraft-navtab-settings-content #remote-storage-holder').on('click', '.updraftplusmethod a.updraft_delete_instance', function(e) {
2958 e.preventDefault();
2959
2960 updraft_settings_form_changed = true;
2961 load_save_button();
2962
2963 var method = $(this).data('method');
2964 var instance_id = $(this).data('instance_id');
2965
2966 if (1 === $('.' + method + '_updraft_remote_storage_border').length) {
2967 add_new_instance(method);
2968 }
2969
2970 $('.' + method + '-' + instance_id).hide('slow', function() {
2971 $(this).remove();
2972 });
2973 });
2974
2975 $('#updraft-navtab-settings-content #remote-storage-holder').on('click', '.updraftplusmethod .updraft_edit_label_instance', function(e) {
2976 $(this).find('span').hide();
2977 $(this).attr('contentEditable', true).trigger('focus');
2978 });
2979
2980 $('#updraft-navtab-settings-content #remote-storage-holder').on('keyup', '.updraftplusmethod .updraft_edit_label_instance', function(e) {
2981 var method = jQuery(this).data('method');
2982 var instance_id = jQuery(this).data('instance_id');
2983 var content = jQuery(this).text();
2984
2985 $('#updraft_' + method + '_instance_label_' + instance_id).val(content);
2986 });
2987
2988 $('#updraft-navtab-settings-content #remote-storage-holder').on('blur', '.updraftplusmethod .updraft_edit_label_instance', function(e) {
2989 $(this).attr('contentEditable', false);
2990 $(this).find('span').show();
2991 });
2992
2993 $('#updraft-navtab-settings-content #remote-storage-holder').on('keypress', '.updraftplusmethod .updraft_edit_label_instance', function(e) {
2994 if (13 === e.which) {
2995 $(this).attr('contentEditable', false);
2996 $(this).find('span').show();
2997 $(this).trigger('blur');
2998 }
2999 });
3000
3001 /**
3002 * This method will get the default options and compile a template with them
3003 *
3004 * @param {string} method - the remote storage name
3005 * @param {boolean} first_instance - indicates if this is the first instance of this type
3006 */
3007 function add_new_instance(method) {
3008 var template = Handlebars.compile(updraftlion.remote_storage_templates[method]);
3009 var context = {}; // Initiate a reference by assigning an empty object to a variable (in this case the context variable) so that it can be used as a target of merging one or more other objects. Unlike basic values (boolean, string, integer, etc.), in Javascript objects and arrays are passed by reference
3010 // copy what are in the template properties to the context overwriting the same object properties, and then copy what are in the default instance settings to the context overwriting all the same properties from the previous merging operation (if any). The context properties are overwritten by other objects that have the same properties later in the parameters order
3011 Object.assign(context, updraftlion.remote_storage_options[method]['template_properties'], updraftlion.remote_storage_options[method]['default']);
3012 var method_name = updraftlion.remote_storage_methods[method];
3013 context['instance_id'] = 's-' + generate_instance_id(32);
3014 context['instance_enabled'] = 1;
3015 context['instance_label'] = method_name + ' (' + (jQuery('.' + method + '_updraft_remote_storage_border').length + 1) + ')';
3016 context['instance_conditional_logic'] = {
3017 type: '', // always by default
3018 rules: [],
3019 day_of_the_week_options: updraftlion.conditional_logic.day_of_the_week_options,
3020 logic_options: updraftlion.conditional_logic.logic_options,
3021 operand_options: updraftlion.conditional_logic.operand_options,
3022 operator_options: updraftlion.conditional_logic.operator_options,
3023 };
3024 var html = template(context);
3025 jQuery(html).hide().insertAfter(jQuery('.' + method + '_add_instance_container').first()).show('slow', function() {
3026 initialize_remote_storage_select2_elements(this);
3027 });
3028 }
3029
3030 /**
3031 * This method will return a random instance id string
3032 *
3033 * @param {integer} length - the length of the string to be generated
3034 *
3035 * @return string - the instance id
3036 */
3037 function generate_instance_id(length) {
3038 var uuid = '';
3039 var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
3040
3041 for (var i = 0; i < length; i++) {
3042 uuid += characters.charAt(Math.floor(Math.random() * characters.length));
3043 }
3044
3045 return uuid;
3046 }
3047
3048 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on("change", "input[class='updraft_instance_toggle']", function () {
3049 updraft_settings_form_changed = true;
3050 load_save_button();
3051 if (jQuery(this).is(':checked')) {
3052 jQuery(this).siblings('label').html(updraftlion.instance_enabled);
3053 } else {
3054 jQuery(this).siblings('label').html(updraftlion.instance_disabled);
3055 }
3056 });
3057
3058 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on("change", "select[class='logic_type']", function () {
3059 updraft_settings_form_changed = true;
3060 load_save_button();
3061 if ('' !== this.value) {
3062 jQuery('div.logic', jQuery(this).parents('tr.updraftplusmethod')).show();
3063 jQuery(this).parents('tr.updraftplusmethod').find('div.logic ul.rules > li').each(function() {
3064 jQuery(this).find('select').each(function() {
3065 jQuery(this).prop('disabled', false);
3066 })
3067 });
3068 } else {
3069 jQuery(this).parents('tr.updraftplusmethod').find('div.logic ul.rules > li').each(function() {
3070 jQuery(this).find('select').each(function() {
3071 jQuery(this).prop('disabled', true);
3072 })
3073 });
3074 jQuery(this).parents('tr.updraftplusmethod').find('div.logic').hide();
3075 }
3076 });
3077
3078 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on("change", "select[class='conditional_logic_operand']", function () {
3079 updraft_settings_form_changed = true;
3080 load_save_button();
3081 jQuery(this).parent().find('select:nth(2)').empty();
3082 if ('day_of_the_week' === jQuery(this).val()) {
3083 for (var i=0; i<updraftlion.conditional_logic.day_of_the_week_options.length; i++) {
3084 jQuery(this).parent().find('select:nth(2)').append(jQuery('<option value="'+updraftlion.conditional_logic.day_of_the_week_options[i].index+'"></option>').text(updraftlion.conditional_logic.day_of_the_week_options[i].value));
3085 }
3086 } else if ('day_of_the_month' === jQuery(this).val()) {
3087 for (var i=1; i<=31; i++) {
3088 jQuery(this).parent().find('select:nth(2)').append(jQuery('<option value="'+i+'"></option>').text(i));
3089 }
3090 }
3091 });
3092
3093 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on("click", "div.conditional_remote_backup ul.rules li span", function () {
3094 updraft_settings_form_changed = true;
3095 load_save_button();
3096 var $ul = jQuery(this).parents('ul.rules');
3097 if (jQuery(this).hasClass('remove-rule')) {
3098 jQuery(this).parent().slideUp(function() {
3099 jQuery(this).remove();
3100 if (jQuery($ul).find('> li').length < 2) {
3101 jQuery('li:nth(0) span.remove-rule', $ul).remove();
3102 }
3103 });
3104 }
3105 });
3106
3107 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on("click", "div.conditional_remote_backup input.add-new-rule", function () {
3108 var $ul = jQuery(this).parent().find('ul.rules');
3109 if (jQuery($ul).find('> li').length < 2) {
3110 jQuery($ul).find('li:nth(0)').append('<span class="remove-rule"><svg viewbox="0 0 25 25"><line x1="6.5" y1="18.5" x2="18.5" y2="6.5" fill="none" stroke="#FF6347" stroke-width="3" vector-effect="non-scaling-stroke" ></line><line y1="6.5" x1="6.5" y2="18.5" x2="18.5" fill="none" stroke="#FF6347" stroke-width="3" vector-effect="non-scaling-stroke" ></line></svg></span>');
3111 }
3112 $cloned_item = jQuery($ul).find('> li').last().clone();
3113 jQuery($cloned_item).find('> select').each(function() {
3114 jQuery(this).prop('name', jQuery(this).prop('name').replace(/\[instance_conditional_logic\]\[rules\]\[[0-9]+\]/gi, '[instance_conditional_logic][rules]['+jQuery($ul).data('rules')+']'));
3115 });
3116 jQuery($ul).append($cloned_item);
3117 jQuery($ul).data('rules', parseInt(jQuery($ul).data('rules')) + 1);
3118 jQuery($cloned_item).find('select[name*="[operand]"]').trigger('change');
3119 });
3120
3121 jQuery('#updraft-navtab-settings-content #remote-storage-holder').on('click', '.updraftplusmethod button.updraft-test-button', function() {
3122
3123 var method = jQuery(this).data('method');
3124 var instance_id = jQuery(this).data('instance_id');
3125 updraft_remote_storage_test(method, function(response, status, data) {
3126 if ('sftp' != method) { return false; }
3127
3128 if (data.hasOwnProperty('scp') && data.scp) {
3129 alert(updraftlion.settings_test_result.replace('%s', 'SCP')+' '+response.output);
3130 } else {
3131 alert(updraftlion.settings_test_result.replace('%s', 'SFTP')+' '+response.output);
3132 }
3133
3134 if (response.hasOwnProperty('data') && response.data) {
3135 if (response.data.hasOwnProperty('valid_md5_fingerprint') && response.data.valid_md5_fingerprint) {
3136 $('#updraft_sftp_fingerprint_'+instance_id).val(response.data.valid_md5_fingerprint);
3137 }
3138 }
3139
3140 return true;
3141
3142 }, instance_id);
3143 });
3144
3145 $('#updraft-navtab-settings-content select.updraft_interval, #updraft-navtab-settings-content select.updraft_interval_database').on('change', function() {
3146 updraft_check_same_times();
3147 });
3148
3149 $('#backupnow_includefiles_showmoreoptions').on('click', function(e) {
3150 e.preventDefault();
3151 $('#backupnow_includefiles_moreoptions').toggle();
3152 });
3153
3154 $('#backupnow_database_showmoreoptions').on('click', function(e) {
3155 e.preventDefault();
3156 $('#backupnow_database_moreoptions').toggle();
3157 });
3158
3159 $('#updraft-navtab-migrate-content').on('click', '#backupnow_database_showmoreoptions', function (e) {
3160 e.preventDefault();
3161 $('#updraft-navtab-migrate-content #backupnow_database_moreoptions').toggle();
3162 });
3163
3164 $('#backupnow_db_anon_all').on('click', function(e) {
3165 if ($('#backupnow_db_anon_non_staff').prop('checked')) $('#backupnow_db_anon_non_staff').prop("checked", false);
3166 });
3167
3168 $('#backupnow_db_anon_non_staff').on('click', function(e) {
3169 if ($('#backupnow_db_anon_all').prop('checked')) $('#backupnow_db_anon_all').prop("checked", false);
3170 });
3171
3172 $('#updraft-navtab-migrate-content').on('click', '#updraftplus_migration_backupnow_db_anon_all', function() {
3173 if ($('#updraftplus_migration_backupnow_db_anon_non_staff').prop('checked')) $('#updraftplus_migration_backupnow_db_anon_non_staff').prop("checked", false);
3174 });
3175
3176 $('#updraft-navtab-migrate-content').on('click', '#updraftplus_migration_backupnow_db_anon_non_staff', function() {
3177 if ($('#updraftplus_migration_backupnow_db_anon_all').prop('checked')) $('#updraftplus_migration_backupnow_db_anon_all').prop("checked", false);
3178 });
3179
3180 $('#updraft-navtab-migrate-content').on('click', '#updraftplus_clone_backupnow_db_anon_all', function() {
3181 if ($('#updraftplus_clone_backupnow_db_anon_non_staff').prop('checked')) $('#updraftplus_clone_backupnow_db_anon_non_staff').prop("checked", false);
3182 });
3183
3184 $('#updraft-navtab-migrate-content').on('click', '#updraftplus_clone_backupnow_db_anon_non_staff', function() {
3185 if ($('#updraftplus_clone_backupnow_db_anon_all').prop('checked')) $('#updraftplus_clone_backupnow_db_anon_all').prop("checked", false);
3186 });
3187
3188 $('#updraft-backupnow-modal').on('click', '#backupnow_includecloud_showmoreoptions', function(e) {
3189 e.preventDefault();
3190 $('#backupnow_includecloud_moreoptions').toggle();
3191 });
3192
3193 $('#updraft-navtab-backups-content').on('click', 'a.updraft_diskspaceused_update',function(e) {
3194 e.preventDefault();
3195 updraftplus_diskspace();
3196 });
3197
3198 // For Advanced Tools > Site information > Web-server disk space in use by UpdraftPlus
3199 $('.advanced_settings_content a.updraft_diskspaceused_update').on('click', function(e) {
3200 e.preventDefault();
3201 jQuery('.advanced_settings_content .updraft_diskspaceused').html('<em>'+updraftlion.calculating+'</em>');
3202 updraft_send_command('get_fragment', { fragment: 'disk_usage', data: 'updraft' }, function(response) {
3203 jQuery('.advanced_settings_content .updraft_diskspaceused').html(response.output);
3204 }, { type: 'GET' });
3205 });
3206
3207 $('#updraft-navtab-backups-content a.updraft_uploader_toggle').on('click', function(e) {
3208 e.preventDefault();
3209 $('#updraft-plupload-modal').slideToggle();
3210 });
3211
3212 $('#updraft-navtab-backups-content a.updraft_rescan_local').on('click', function(e) {
3213 e.preventDefault();
3214 updraft_updatehistory(1, 0);
3215 });
3216
3217 $('#updraft-navtab-backups-content a.updraft_rescan_remote').on('click', function(e) {
3218 e.preventDefault();
3219 if (!confirm(updraftlion.remote_scan_warning)) return;
3220 updraft_updatehistory(1, 1);
3221 });
3222
3223 $('#updraftplus-remote-rescan-debug').on('click', function(e) {
3224 e.preventDefault();
3225 updraft_updatehistory(1, 1, 1);
3226 });
3227
3228 jQuery('#updraft_reset_sid').on('click', function(e) {
3229 e.preventDefault();
3230 updraft_send_command('reset_site_id', null, function(response) {
3231 jQuery('#updraft_show_sid').html(response);
3232 }, { json_parse: false });
3233 });
3234
3235 jQuery("#updraft-navtab-settings-content").on('input', "form input:not('.udignorechange'), form textarea:not('.udignorechange')", function(e) {
3236 updraft_settings_form_changed = true;
3237 load_save_button();
3238 });
3239
3240 jQuery("#updraft-navtab-settings-content").on('change', "form select", function(e) {
3241 updraft_settings_form_changed = true;
3242 load_save_button();
3243 });
3244
3245 jQuery("#updraft-navtab-settings-content").on('click', "form input[type='submit']", function (e) {
3246 updraft_settings_form_changed = false;
3247 });
3248
3249 var bigbutton_width = 180;
3250 jQuery('.updraft-bigbutton').each(function(x,y) {
3251 var bwid = jQuery(y).width();
3252 if (bwid > bigbutton_width) bigbutton_width = bwid;
3253 });
3254 if (bigbutton_width > 180) jQuery('.updraft-bigbutton').width(bigbutton_width);
3255
3256 if (jQuery('#updraft-navtab-backups-content').length) {
3257 // setTimeout(function(){updraft_showlastlog(true);}, 1200);
3258 setInterval(function() {
3259 updraft_activejobs_update(false);}, 1250);
3260 }
3261
3262 // Prevent profusion of notices
3263 setTimeout(function() {
3264 jQuery('#setting-error-settings_updated').slideUp();}, 5000);
3265
3266 jQuery('#updraft_restore_db').on('change', function() {
3267 if (jQuery('#updraft_restore_db').is(':checked') && 1 == jQuery(this).data('encrypted')) {
3268 jQuery('#updraft_restorer_dboptions').slideDown();
3269 } else {
3270 jQuery('#updraft_restorer_dboptions').slideUp();
3271 }
3272 });
3273
3274 updraft_check_same_times();
3275
3276 var updraft_message_modal_buttons = {};
3277 updraft_message_modal_buttons[updraftlion.close] = function() {
3278 jQuery(this).dialog("close");
3279 };
3280 jQuery("#updraft-message-modal").dialog({
3281 autoOpen: false, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3282 open: function(event, ui) {
3283 $(this).dialog('option', 'width', 520);
3284 $(this).dialog('option', 'minHeight', 260);
3285 if ($(window).height() > 360 ) {
3286 $(this).dialog('option', 'height', 360);
3287 } else {
3288 $(this).dialog('option', 'height', $(window).height()-30);
3289 }
3290 },
3291 modal: true,
3292 buttons: updraft_message_modal_buttons
3293 });
3294
3295 var updraft_delete_modal_buttons = {};
3296 updraft_delete_modal_buttons[updraftlion.deletebutton] = function() {
3297 updraft_remove_backup_sets(0, 0, 0, 0, [], false);
3298 };
3299
3300
3301 /**
3302 * Perform a manual backup sets deletion
3303 *
3304 * @param {integer} deleted_counter - The total number of local and remote files that have successfully been removed already. This and the next three parameters are used recursively so that the final total can be displayed to the user in a display message.
3305 * @param {integer} backup_local - The total number of local files that have been removed
3306 * @param {integer} backup_remote - The total number of remote files that have successfully been removed
3307 * @param {integer} backup_sets - The total number of backup sets that have been deleted
3308 * @param {array} processed_instance_ids - An array that contains a group of storage instance IDs that have been processed
3309 * @param {boolean} is_continuation - Whether or not the backup sets deletion is a continuation of an ongoing deletion
3310 */
3311 function updraft_remove_backup_sets(deleted_counter, backup_local, backup_remote, backup_sets, processed_instance_ids, is_continuation) {
3312 jQuery("#updraft-delete-modal").dialog('close');
3313 var deleted_files_counter = deleted_counter;
3314 var local_deleted = backup_local;
3315 var remote_deleted = backup_remote;
3316 var sets_deleted = backup_sets;
3317 var error_log_prompt = '';
3318
3319 var form_data = jQuery('#updraft_delete_form').serializeArray();
3320 var data = {};
3321
3322 $.each(form_data, function() {
3323 if (undefined !== data[this.name]) {
3324 if (!data[this.name].push) {
3325 data[this.name] = [data[this.name]];
3326 }
3327 data[this.name].push(this.value || '');
3328 } else {
3329 data[this.name] = this.value || '';
3330 }
3331 });
3332
3333 if (data.delete_remote) {
3334 jQuery('#updraft-delete-waitwarning').find('.updraft-deleting-remote').show();
3335 } else {
3336 jQuery('#updraft-delete-waitwarning').find('.updraft-deleting-remote').hide();
3337 }
3338
3339 jQuery('#updraft-delete-waitwarning').slideDown().addClass('active');
3340
3341 data.remote_delete_limit = updraftlion.remote_delete_limit;
3342 data.processed_instance_ids = processed_instance_ids;
3343 data.is_continuation = is_continuation;
3344
3345 delete data.action;
3346 delete data.subaction;
3347 delete data.nonce;
3348
3349 updraft_send_command('deleteset', data, function(resp) {
3350 if (!resp.hasOwnProperty('result') || resp.result == null) {
3351 jQuery('#updraft-delete-waitwarning').slideUp();
3352 return;
3353 }
3354 if (resp.result == 'error') {
3355 jQuery('#updraft-delete-waitwarning').slideUp();
3356 alert(updraftlion.error+' '+resp.message);
3357 } else if (resp.result == 'continue') {
3358 deleted_files_counter = deleted_files_counter + resp.backup_local + resp.backup_remote;
3359 local_deleted = local_deleted + resp.backup_local;
3360 remote_deleted = remote_deleted + resp.backup_remote;
3361 sets_deleted = sets_deleted + resp.backup_sets;
3362 var deleted_timestamps = resp.deleted_timestamps.split(',');
3363 for (var i = 0; i < deleted_timestamps.length; i++) {
3364 var timestamp = deleted_timestamps[i];
3365 jQuery('#updraft-navtab-backups-content .updraft_existing_backups_row_' + timestamp).slideUp().remove();
3366 }
3367 jQuery('#updraft_delete_timestamp').val(resp.timestamps);
3368 jQuery('#updraft-deleted-files-total').text(deleted_files_counter + ' ' + updraftlion.remote_files_deleted);
3369 updraft_remove_backup_sets(deleted_files_counter, local_deleted, remote_deleted, sets_deleted, resp.processed_instance_ids, true);
3370 } else if (resp.result == 'success') {
3371
3372 setTimeout(function() {
3373 jQuery('#updraft-deleted-files-total').text('');
3374 jQuery('#updraft-delete-waitwarning').slideUp();
3375 }, 500);
3376
3377 update_backupnow_modal(resp);
3378
3379 if (resp.hasOwnProperty('backupnow_file_entities')) {
3380 impossible_increment_entities = resp.backupnow_file_entities;
3381 }
3382
3383 if (resp.hasOwnProperty('count_backups')) {
3384 jQuery('#updraft-existing-backups-heading').html(updraftlion.existing_backups+' <span class="updraft_existing_backups_count">'+resp.count_backups+'</span>');
3385 }
3386 var deleted_timestamps = resp.deleted_timestamps.split(',');
3387 for (var i = 0; i < deleted_timestamps.length; i++) {
3388 var timestamp = deleted_timestamps[i];
3389 jQuery('#updraft-navtab-backups-content .updraft_existing_backups_row_' + timestamp).slideUp().remove();
3390 }
3391
3392 updraft_backups_selection.checkSelectionStatus();
3393
3394 updraft_history_lastchecksum = false;
3395
3396 local_deleted = local_deleted + resp.backup_local;
3397 remote_deleted = remote_deleted + resp.backup_remote;
3398 sets_deleted = sets_deleted + resp.backup_sets;
3399 if ('' != resp.error_messages) {
3400 error_log_prompt = updraftlion.delete_error_log_prompt;
3401 }
3402
3403 setTimeout(function() {
3404 alert(resp.set_message + " " + sets_deleted + "\n" + resp.local_message + " " + local_deleted + "\n" + resp.remote_message + " " + remote_deleted + "\n\n" + resp.error_messages + "\n" + error_log_prompt);
3405 }, 900);
3406 }
3407 });
3408 };
3409
3410 updraft_delete_modal_buttons[updraftlion.cancel] = function() {
3411 jQuery(this).dialog("close"); };
3412 jQuery("#updraft-delete-modal").dialog({
3413 autoOpen: false, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3414 open: function(event, ui) {
3415 $(this).css('minHeight', 83);
3416 },
3417 modal: true,
3418 buttons: updraft_delete_modal_buttons
3419 });
3420
3421 var updraft_restore_modal = {
3422 initialized: false,
3423 init: function() {
3424 if (this.initialized) return;
3425
3426 this.initialized = true;
3427
3428 // Setup cancel button events
3429 $('.updraft-restore--cancel').on('click', function(e) {
3430 e.preventDefault();
3431 jQuery('#ud_downloadstatus2').html('');
3432 this.close();
3433 }.bind(this));
3434
3435 this.default_next_text = $('.updraft-restore--next-step').eq(0).text();
3436
3437 // Setup next button event
3438 $('.updraft-restore--next-step').on('click', function(e) {
3439 e.preventDefault();
3440 this.process_next_action();
3441 }.bind(this));
3442 },
3443 close: function() {
3444 $('.updraft_restore_container').hide();
3445 $('body').removeClass('updraft-modal-is-opened');
3446 },
3447 open: function() {
3448 this.init();
3449 // reset elements
3450 $('#updraft-restore-modal-stage1').show();
3451 $('#updraft-restore-modal-stage2').hide();
3452 $('#updraft-restore-modal-stage2a').html('');
3453 $('.updraft-restore--next-step').text(this.default_next_text);
3454 $('.updraft-restore--stages li').removeClass('active').first().addClass('active');
3455 // Show restoration window
3456 $('.updraft_restore_container').show();
3457 $('body').addClass('updraft-modal-is-opened');
3458 },
3459 process_next_action: function() {
3460 var anyselected = 0;
3461 var moreselected = 0;
3462 var dbselected = 0;
3463 var pluginselected = 0;
3464 var themeselected = 0;
3465 var whichselected = [];
3466 // Make a list of what files we want
3467 var already_added_wpcore = 0;
3468 var meta_foreign = $('#updraft_restore_meta_foreign').val();
3469 $('input[name="updraft_restore[]"]').each(function(x, y) {
3470 if ($(y).is(':checked') && !$(y).is(':disabled')) {
3471 anyselected = 1;
3472 var howmany = $(y).data('howmany');
3473 var type = $(y).val();
3474 if ('more' == type) moreselected = 1;
3475 if ('db' == type) dbselected = 1;
3476 if ('plugins' == type) pluginselected = 1;
3477 if ('themes' == type) themeselected = 1;
3478 if (1 == meta_foreign || (2 == meta_foreign && 'db' != type)) {
3479 if ('wpcore' != type) {
3480 howmany = $('#updraft_restore_form #updraft_restore_wpcore').data('howmany');
3481 }
3482 type = 'wpcore';
3483 }
3484 if ('wpcore' != type || already_added_wpcore == 0) {
3485 var restobj = [ type, howmany ];
3486 whichselected.push(restobj);
3487 // alert($(y).val());
3488 if ('wpcore' == type) { already_added_wpcore = 1; }
3489 }
3490 }
3491 });
3492 if (1 == anyselected) {
3493 // Work out what to download
3494 if (1 == updraft_restore_stage) {
3495 // meta_foreign == 1 : All-in-one format: the only thing to download, always, is wpcore
3496 // if ('1' == meta_foreign) {
3497 // whichselected = [];
3498 // whichselected.push([ 'wpcore', 0 ]);
3499 // } else if ('2' == meta_foreign) {
3500 // $(whichselected).each(function(x,y) {
3501 // restobj = whichselected[x];
3502 // });
3503 // whichselected = [];
3504 // whichselected.push([ 'wpcore', 0 ]);
3505 // }
3506 $('.updraft-restore--stages li').removeClass('active').eq(1).addClass('active');
3507 $('#updraft-restore-modal-stage1').slideUp('slow', function() {
3508 $('#updraft-restore-modal-stage2').show(100, function() {
3509 updraft_restore_stage = 2;
3510 var pretty_date = $('.updraft_restore_date').first().text();
3511 // Create the downloader active widgets
3512
3513 // See if we some are already known to be downloaded - in which case, skip creating the download widget. (That saves on HTTP round-trips, as each widget creates a new POST request. Of course, this is at the expense of one extra one here).
3514 var which_to_download = whichselected;
3515 var backup_timestamp = $('#updraft_restore_timestamp').val();
3516
3517 try {
3518 $('.updraft-restore--next-step').prop('disabled', true);
3519 $('#updraft-restore-modal-stage2a').html('<span class="dashicons dashicons-update rotate"></span> '+updraftlion.maybe_downloading_entities);
3520 updraft_send_command('whichdownloadsneeded', {
3521 downloads: whichselected,
3522 timestamp: backup_timestamp
3523 }, function(response) {
3524 $('.updraft-restore--next-step').prop('disabled', false);
3525 if (response.hasOwnProperty('downloads')) {
3526 console.log('UpdraftPlus: items which still require downloading follow');
3527 which_to_download = response.downloads;
3528 console.log(which_to_download);
3529 }
3530
3531 // Kick off any downloads, if needed
3532 if (0 == which_to_download.length) {
3533 updraft_restorer_checkstage2(0);
3534 } else {
3535 for (var i=0; i<which_to_download.length; i++) {
3536 // updraft_downloader(base, backup_timestamp, what, whicharea, set_contents, prettydate, async)
3537 updraft_downloader('udrestoredlstatus_', backup_timestamp, which_to_download[i][0], '#ud_downloadstatus2', which_to_download[i][1], pretty_date, true);
3538 }
3539 }
3540
3541 }, { alert_on_error: false, error_callback: function(response, status, error_code, resp) {
3542 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
3543 console.error(resp.fatal_error_message);
3544 $('#updraft-restore-modal-stage2a').html('<p style="color:red;">'+resp.fatal_error_message+'</p>');
3545 } else {
3546 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
3547 $('#updraft-restore-modal-stage2a').html('<p style="color:red; margin: 5px;">'+error_message+'</p>');
3548 console.log(error_message);
3549 console.log(response);
3550 }
3551 }
3552 });
3553 } catch (err) {
3554 console.log("UpdraftPlus: error (follows) when looking for items needing downloading");
3555 console.log(err);
3556 alert(updraftlion.jsonnotunderstood);
3557 }
3558 });
3559 });
3560
3561 // Make sure all are downloaded
3562 } else if (2 == updraft_restore_stage) {
3563 updraft_restorer_checkstage2(1);
3564 } else if (3 == updraft_restore_stage) {
3565 var continue_restore = 1;
3566 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', true);
3567 $('#updraft_restoreoptions_ui input.required').each(function(index) {
3568 if (continue_restore == 0) return;
3569 var sitename = $(this).val();
3570 if (sitename == '') {
3571 alert(updraftlion.pleasefillinrequired);
3572 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3573 continue_restore = 0;
3574 } else if ($(this).attr('pattern') != '') {
3575 var pattern = $(this).attr('pattern');
3576 var re = new RegExp(pattern, "g");
3577 if (!re.test(sitename)) {
3578 alert($(this).data('invalidpattern'));
3579 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3580 continue_restore = 0;
3581 }
3582 }
3583 });
3584
3585 if (1 == dbselected) {
3586
3587 anyselected = 0;
3588
3589 jQuery('input[name="updraft_restore_tables_options[]"').each(function (x, y) {
3590 if (jQuery(y).is(':checked') && !jQuery(y).is(':disabled')) anyselected = 1;
3591 });
3592
3593 if (0 == anyselected && !skipped_db_scan) {
3594 alert(updraftlion.youdidnotselectany);
3595 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3596 return;
3597 }
3598 }
3599
3600 if (1 == pluginselected) {
3601
3602 anyselected = 0;
3603
3604 if (!jQuery(".updraftplus_restore_plugins_options_container").length) anyselected = 1;
3605
3606 jQuery('input[name="updraft_restore_plugins_options[]"').each(function (x, y) {
3607 if (jQuery(y).is(':checked') && !jQuery(y).is(':disabled')) anyselected = 1;
3608 });
3609
3610 if (0 == anyselected) {
3611 alert(updraftlion.youdidnotselectany);
3612 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3613 return;
3614 }
3615 }
3616
3617 if (1 == themeselected) {
3618
3619 anyselected = 0;
3620
3621 if (!jQuery(".updraftplus_restore_themes_options_container").length) anyselected = 1;
3622
3623 jQuery('input[name="updraft_restore_themes_options[]"').each(function (x, y) {
3624 if (jQuery(y).is(':checked') && !jQuery(y).is(':disabled')) anyselected = 1;
3625 });
3626
3627 if (0 == anyselected) {
3628 alert(updraftlion.youdidnotselectany);
3629 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3630 return;
3631 }
3632 }
3633
3634 if (1 == moreselected) {
3635
3636 anyselected = 0;
3637
3638 jQuery('input[name="updraft_include_more_index[]"').each(function (x, y) {
3639 if (jQuery(y).is(':checked') && !jQuery(y).is(':disabled')) {
3640 anyselected = 1;
3641 if ('' == jQuery('#updraft_include_more_path_restore' + x).val()) {
3642 alert(updraftlion.emptyrestorepath);
3643 }
3644 }
3645 });
3646
3647 if (0 == anyselected) {
3648 alert(updraftlion.youdidnotselectany);
3649 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3650 return;
3651 }
3652 }
3653
3654 if (!continue_restore) return;
3655 var restore_options = $('#updraft_restoreoptions_ui select, #updraft_restoreoptions_ui input').serialize();
3656
3657 // jQuery serialize does not pick up unchecked checkboxes, but we want to include these so that we have a list of table/plugins/themes the user does not want to restore we prepend these with udp-skip-{entity}- and check this on the backend
3658 var entities = ['tables', 'plugins', 'themes'];
3659
3660 jQuery.each(entities, function(i, entity) {
3661 jQuery.each(jQuery('input[name="updraft_restore_' + entity + '_options[]').filter(function(idx) {
3662 return jQuery(this).prop('checked') === false
3663 }), function(idx, el) {
3664 restore_options += '&' + jQuery(el).attr('name') + '=' + 'udp-skip-' + entity + '-' + jQuery(el).val();
3665 });
3666 })
3667
3668 console.log("Restore options: "+restore_options);
3669
3670 if (typeof php_max_input_vars !== 'undefined') {
3671 var restore_options_length = restore_options.split("&").length;
3672 var warning_template_start = '<div class="udp-notice notice-warning"><p><span class="dashicons dashicons-warning"></span> <strong>' + updraftlion.warnings +'</strong></p><ul id="updraft_restore_warnings">';
3673 var warning_template_end = '</ul></div>';
3674
3675 // If we can't detect the php_max_input_vars assume the PHP default of 1000
3676 if (!php_max_input_vars && 1000 <= restore_options_length) {
3677 console.log('Restore options: ' + restore_options_length + ' PHP max input vars not detected; using default: 1000');
3678 } else if (php_max_input_vars && restore_options_length >= php_max_input_vars) {
3679 var warning = '<li>' + updraftlion.php_max_input_vars_detected_warning + '</li>';
3680 if (1 != jQuery('#updraft-restore-modal-stage2a .notice-warning').length) {
3681 var final_warning = warning_template_start + warning + warning_template_end;
3682 jQuery('#updraft_restoreoptions_ui').prepend(final_warning);
3683 } else {
3684 jQuery('#updraft-restore-modal-stage2a #updraft_restore_warnings').append(warning);
3685 }
3686 console.log('Restore options: ' + restore_options_length + ' PHP max input vars: ' + php_max_input_vars);
3687 jQuery('.updraft-restore--next-step, .updraft-restore--cancel').prop('disabled', false);
3688 php_max_input_vars = undefined;
3689 return;
3690 }
3691 }
3692
3693 $('#updraft_restorer_restore_options').val(restore_options);
3694 // This must be done last, as it wipes out the section with #updraft_restoreoptions_ui
3695 $('#updraft-restore-modal-stage2a').html(updraftlion.restore_proceeding);
3696 $('#updraft_restore_form').trigger('submit');
3697 // In progress; prevent the button being pressed again
3698 updraft_restore_stage = 4;
3699 }
3700 } else {
3701 alert(updraftlion.youdidnotselectany);
3702 }
3703 }
3704 }
3705
3706 var original_restore_main_activity_width = $('.updraft_restore_main--activity').width();
3707 jQuery('#activity-full-log').on('click', function() {
3708 var activity_log_max_width = $('.updraft_restore_main').css('max-width') == '1460px' ? '860px' : '1460px';
3709 var restore_main_activity_width = $('.updraft_restore_main--activity').width() == original_restore_main_activity_width ? '100%' : original_restore_main_activity_width + 'px';
3710 var activity_log_max_height = $('.updraft_restore_main--activity').css('min-height') == '600px' ? '0px' : '600px';
3711 var activity_log_icon_title = $('#activity-full-log').attr('title') == updraftlion.restoreactivitylogscreenexit ? updraftlion.restoreactivitylogfullscreen : updraftlion.restoreactivitylogscreenexit;
3712 $('#activity-full-log').toggleClass('dashicons-fullscreen-exit-alt');
3713 $('#activity-full-log').attr('title', activity_log_icon_title);
3714 $('.updraft_restore_main--components').toggle('fast');
3715 $('.updraft_restore_main--header').toggle('fast');
3716 $('.updraft_restore_main--activity').animate({minHeight: activity_log_max_height, width: restore_main_activity_width});
3717 $('.updraft_restore_main').animate({maxWidth: activity_log_max_width});
3718 });
3719
3720 jQuery("#updraft-iframe-modal").dialog({
3721 autoOpen: false, height: 500, width: 780, modal: true
3722 });
3723
3724 jQuery("#updraft-backupnow-inpage-modal").dialog({
3725 autoOpen: false, modal: true, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3726 open: function(event, ui) {
3727 $(this).dialog('option', 'width', 580);
3728 $(this).dialog('option', 'minHeight', 261);
3729 $(this).dialog('option', 'height', 380);
3730 },
3731 });
3732
3733 var backupnow_modal_buttons = {};
3734 backupnow_modal_buttons[updraftlion.backupnow] = function() {
3735
3736 var backupnow_nodb = jQuery('#backupnow_includedb').is(':checked') ? 0 : 1;
3737 var backupnow_nofiles = jQuery('#backupnow_includefiles').is(':checked') ? 0 : 1;
3738 var backupnow_nocloud = jQuery('#backupnow_includecloud').is(':checked') ? 0 : 1;
3739 var db_anon_all = jQuery('#backupnow_db_anon_all').is(':checked') ? 1 : 0;
3740 var db_anon_non_staff = jQuery('#backupnow_db_anon_non_staff').is(':checked') ? 1 : 0;
3741 var db_anon_wc_orders = jQuery('#backupnow_db_anon_wc_order_data').is(':checked') ? 1 : 0;
3742 var onlythesetableentities = backupnow_whichtables_checked('');
3743 var always_keep = jQuery('#always_keep').is(':checked') ? 1 : 0;
3744 var incremental = ('incremental' == jQuery('#updraft-backupnow-modal').data('backup-type')) ? 1 : 0;
3745
3746 if (updraftlion.hosting_restriction.includes('only_one_backup_per_month') && !incremental) {
3747 alert(updraftlion.hosting_restriction_one_backup_permonth);
3748 return;
3749 }
3750
3751 if (updraftlion.hosting_restriction.includes('only_one_incremental_per_day') && incremental) {
3752 alert(updraftlion.hosting_restriction_one_incremental_perday);
3753 return;
3754 }
3755
3756 if ('' == onlythesetableentities && 0 == backupnow_nodb) {
3757 alert(updraftlion.notableschosen);
3758 jQuery('#backupnow_database_moreoptions').show();
3759 return;
3760 }
3761
3762 if (typeof onlythesetableentities === 'boolean') {
3763 onlythesetableentities = null;
3764 }
3765
3766 var onlythesefileentities = backupnow_whichfiles_checked('');
3767
3768 if ('' == onlythesefileentities && 0 == backupnow_nofiles) {
3769 alert(updraftlion.nofileschosen);
3770 jQuery('#backupnow_includefiles_moreoptions').show();
3771 return;
3772 }
3773
3774 var only_these_cloud_services = jQuery("input[name^='updraft_include_remote_service_']").serializeArray();
3775
3776 if ('' == only_these_cloud_services && 0 == backupnow_nocloud) {
3777 alert(updraftlion.nocloudserviceschosen);
3778 jQuery('#backupnow_includecloud_moreoptions').show();
3779 return;
3780 }
3781
3782 if (typeof only_these_cloud_services === 'boolean') {
3783 only_these_cloud_services = null;
3784 }
3785
3786 if (backupnow_nodb && backupnow_nofiles) {
3787 alert(updraftlion.excludedeverything);
3788 return;
3789 }
3790
3791 jQuery(this).dialog("close");
3792
3793 setTimeout(function() {
3794 jQuery('#updraft_lastlogmessagerow').fadeOut('slow', function() {
3795 jQuery(this).fadeIn('slow');
3796 });
3797 }, 1700);
3798
3799 updraft_backupnow_go(backupnow_nodb, backupnow_nofiles, backupnow_nocloud, onlythesefileentities, {always_keep: always_keep, incremental: incremental, db_anon: { all: db_anon_all, non_staff: db_anon_non_staff, wc_orders: db_anon_wc_orders }}, jQuery('#backupnow_label').val(), onlythesetableentities, only_these_cloud_services);
3800 };
3801 backupnow_modal_buttons[updraftlion.cancel] = function() {
3802 jQuery(this).dialog("close"); };
3803
3804 jQuery("#updraft-backupnow-modal").dialog({
3805 autoOpen: false, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3806 open: function(event, ui) {
3807 $(this).dialog('option', 'width', 610);
3808 $(this).dialog('option', 'minHeight', 300);
3809 $(this).dialog('option', 'height', 472);
3810 },
3811 modal: true,
3812 buttons: backupnow_modal_buttons,
3813 create: function () {
3814 $(this).closest(".ui-dialog")
3815 .find(".ui-dialog-buttonpane .ui-button").first() // the first button
3816 .addClass("js-tour-backup-now-button");
3817 }
3818 });
3819
3820 jQuery("#updraft-poplog").dialog({
3821 autoOpen: false, modal: true, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3822 open: function(event, ui) {
3823 $(this).dialog('option', 'width', 860);
3824 $(this).dialog('option', 'minHeight', 260);
3825 if ($(window).height() > 600) {
3826 $(this).dialog('option', 'height', 600);
3827 } else {
3828 $(this).dialog('option', 'height', $(window).height()-50);
3829 }
3830 },
3831 });
3832
3833 jQuery('#updraft-navtab-settings-content .enableexpertmode').on('click', function() {
3834 jQuery('#updraft-navtab-settings-content .expertmode').fadeIn();
3835 jQuery('#updraft-navtab-settings-content .enableexpertmode').off('click');
3836 return false;
3837 });
3838
3839 jQuery('#updraft-navtab-settings-content .backupdirrow').on('click', 'a.updraft_backup_dir_reset', function() {
3840 jQuery('#updraft_dir').val('updraft'); return false;
3841 });
3842
3843 function setup_file_entity_exclude_field(field, instant) {
3844 if (jQuery('#updraft-navtab-settings-content #updraft_include_'+field).is(':checked')) {
3845 if (instant) {
3846 jQuery('#updraft-navtab-settings-content #updraft_include_'+field+'_exclude_container').show();
3847 } else {
3848 jQuery('#updraft-navtab-settings-content #updraft_include_'+field+'_exclude_container').slideDown();
3849 }
3850 } else {
3851 if (instant) {
3852 jQuery('#updraft-navtab-settings-content #updraft_include_'+field+'_exclude').hide();
3853 } else {
3854 jQuery('#updraft-navtab-settings-content #updraft_include_'+field+'_exclude_container').slideUp();
3855 }
3856 }
3857 }
3858
3859 jQuery('#updraft-navtab-settings-content .updraft_include_entity').on('click', function() {
3860 var has_exclude_field = jQuery(this).data('toggle_exclude_field');
3861 if (has_exclude_field) {
3862 setup_file_entity_exclude_field(has_exclude_field, false);
3863 }
3864 });
3865
3866 jQuery('.updraft_exclude_entity_container').on('click', '.updraft_exclude_entity_delete', function(event) {
3867 event.preventDefault();
3868 if (!confirm(updraftlion.exclude_rule_remove_conformation_msg)) return;
3869
3870 var include_entity_name = jQuery(this).data('include-backup-file');
3871 jQuery.when(
3872 jQuery(this).closest('.updraft_exclude_entity_wrapper').remove()
3873 ).then(
3874 updraft_exclude_entity_update(include_entity_name)
3875 );
3876 });
3877
3878 jQuery('.updraft_exclude_entity_container').on('click', '.updraft_exclude_entity_edit', function(event) {
3879 event.preventDefault();
3880 var wrapper = jQuery(this).hide().closest('.updraft_exclude_entity_wrapper');
3881 var input = wrapper.find('input');
3882 input.prop('readonly', false).trigger('focus');
3883
3884 // place caret at the end of the text
3885 var input_val = input.val();
3886 input.val('');
3887 input.val(input_val);
3888
3889 wrapper.find('.updraft_exclude_entity_update').addClass('is-active').show();
3890 });
3891
3892 jQuery('.updraft_exclude_entity_container').on('click', '.updraft_exclude_entity_update', function(event) {
3893 event.preventDefault();
3894 var wrapper = jQuery(this).closest('.updraft_exclude_entity_wrapper');
3895 var include_backup_file = jQuery(this).data('include-backup-file')
3896 var exclude_item_val = wrapper.find('input').val().trim();
3897
3898 var should_be_updated = false;
3899 if (exclude_item_val == wrapper.find('input').data('val')) {
3900 should_be_updated = true;
3901 } else if (updraft_is_unique_exclude_rule(exclude_item_val, include_backup_file)) {
3902 should_be_updated = true;
3903 }
3904
3905 if (should_be_updated) {
3906 jQuery(this).hide().removeClass('is-active');
3907 jQuery.when(
3908 wrapper.find('input').prop('readonly', 'readonly').data('val', exclude_item_val)
3909 ).then(function() {
3910 wrapper.find('.updraft_exclude_entity_edit').show();
3911 updraft_exclude_entity_update(include_backup_file);
3912 });
3913 }
3914 });
3915
3916 jQuery('#updraft_exclude_modal').dialog({
3917 autoOpen: false, modal: true, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
3918 open: function(event,ui) {
3919 $(this).parent().trigger('focus');
3920 $(this).dialog('option', 'width', 520);
3921 $(this).dialog('option', 'minHeight', 260);
3922 if ($(window).height() > 579) {
3923 $(this).css('height', 'auto');
3924 } else if ($(window).height() < 580 && $(window).height() > 410) {
3925 $(this).dialog('option', 'height', 410);
3926 $(this).css('height', 'auto');
3927 } else {
3928 $(this).dialog('option', 'height', $(window).height()-20);
3929 }
3930 }
3931 });
3932
3933 jQuery('#updraft_include_others_exclude_container, #updraft_include_uploads_exclude_container, .updraft_exclude_container').on('click', 'a.updraft_add_exclude_item', function(event) {
3934 event.preventDefault();
3935 var backup_entity = jQuery(this).data('include-backup-file');
3936 jQuery('#updraft_exclude_modal_for').val(backup_entity);
3937 jQuery('#updraft_exclude_modal_path').val(jQuery(this).data('path'));
3938 if ('uploads' == backup_entity) {
3939 jQuery('#updraft-exclude-file-dir-prefix').html(jQuery('#updraft-exclude-upload-base-dir').val());
3940 }
3941 jQuery('.updraft-exclude-modal-reset').trigger('click');
3942 jQuery('#updraft_exclude_modal').dialog('open');
3943 });
3944
3945 jQuery('.updraft-exclude-link').on('click', function(event) {
3946 event.preventDefault();
3947 var panel = jQuery(this).data('panel');
3948 if ('file-dir' == panel) {
3949 jQuery('#updraft_exclude_files_folders_jstree').jstree({
3950 "core": {
3951 "multiple": false,
3952 "data": function (nodeid, callback) {
3953 updraft_send_command('get_jstree_directory_nodes', {entity: 'filebrowser', node:nodeid, path: jQuery('#updraft_exclude_modal_path').val(), findex: 0, skip_root_node: true}, function(response) {
3954 if (response.hasOwnProperty('error')) {
3955 alert(response.error);
3956 } else {
3957 callback.call(this, response.nodes);
3958 }
3959 }, { error_callback: function(response, status, error_code, resp) {
3960 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
3961 console.error(resp.fatal_error_message);
3962 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+resp.fatal_error_message+'</p>');
3963 alert(resp.fatal_error_message);
3964 } else {
3965 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
3966 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+error_message+'</p>');
3967 console.log(error_message);
3968 alert(error_message);
3969 console.log(response);
3970 }
3971 }
3972 });
3973 },
3974 "error": function(error) {
3975 alert(error);
3976 console.log(error);
3977 },
3978 },
3979 "search": {
3980 "show_only_matches": true
3981 },
3982 "plugins": ["sort"],
3983 });
3984 } else if ('contain-clause' == panel) {
3985 jQuery('#updraft_exclude_files_folders_wildcards_jstree').jstree({
3986 "core": {
3987 "multiple": false,
3988 "data": function (nodeid, callback) {
3989 updraft_send_command('get_jstree_directory_nodes', {entity: 'filebrowser', directories_only: 1, node:nodeid, path: jQuery('#updraft_exclude_modal_path').val(), findex: 0, skip_root_node: 0}, function(response) {
3990 if (response.hasOwnProperty('error')) {
3991 alert(response.error);
3992 } else {
3993 callback.call(this, response.nodes);
3994 }
3995 }, { error_callback: function(response, status, error_code, resp) {
3996 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
3997 console.error(resp.fatal_error_message);
3998 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+resp.fatal_error_message+'</p>');
3999 alert(resp.fatal_error_message);
4000 } else {
4001 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
4002 jQuery('#updraft_zip_files_jstree').html('<p style="color:red; margin: 5px;">'+error_message+'</p>');
4003 console.log(error_message);
4004 alert(error_message);
4005 console.log(response);
4006 }
4007 }
4008 });
4009 },
4010 "error": function(error) {
4011 alert(error);
4012 console.log(error);
4013 },
4014 },
4015 "search": {
4016 "show_only_matches": true
4017 },
4018 "plugins": ["sort"],
4019 });
4020 }
4021 jQuery('#updraft_exclude_modal_main').slideUp();
4022 jQuery('.updraft-exclude-panel').hide();
4023 jQuery('.updraft-exclude-panel[data-panel='+panel+']').slideDown();
4024 });
4025
4026 jQuery('.updraft-exclude-modal-reset').on('click', function(event) {
4027 event.preventDefault();
4028 jQuery('#updraft_exclude_files_folders_jstree').jstree("destroy");
4029 jQuery('#updraft_exclude_files_folders_wildcards_jstree').jstree("destroy");
4030 jQuery('#updraft_exclude_extension_field').val('');
4031 jQuery('#updraft_exclude_prefix_field').val('');
4032 jQuery('.updraft-exclude-panel').slideUp();
4033 jQuery('#updraft_exclude_modal_main').slideDown();
4034 });
4035
4036 jQuery('.updraft-exclude-submit').on('click', function() {
4037 var panel = jQuery(this).data('panel');
4038 var exclude_item_val = '';
4039 switch (panel) {
4040 case 'file-dir':
4041 var exclude_jstree_selected = jQuery("#updraft_exclude_files_folders_jstree").jstree("get_selected");
4042 if (0 == exclude_jstree_selected.length) {
4043 alert(updraftlion.exclude_select_file_or_folder_msg);
4044 return;
4045 }
4046 var selected_file_or_folder = exclude_jstree_selected[0];
4047 var prefix_path = jQuery('#updraft_exclude_modal_path').val();
4048 if (selected_file_or_folder.substr(0, prefix_path.length) == prefix_path) {
4049 selected_file_or_folder = selected_file_or_folder.substr(prefix_path.length, selected_file_or_folder.length);
4050 }
4051 if ('/' == selected_file_or_folder.charAt(0)) selected_file_or_folder = selected_file_or_folder.substr(1);
4052 if ('/' == selected_file_or_folder.charAt(selected_file_or_folder.length - 1)) selected_file_or_folder = selected_file_or_folder.substr(0, selected_file_or_folder.length - 1);
4053 exclude_item_val = selected_file_or_folder;
4054 break;
4055
4056 case 'extension':
4057 var exclude_extension = jQuery('#updraft_exclude_extension_field').val();
4058 if ('' == exclude_extension) {
4059 alert(updraftlion.exclude_type_ext_msg);
4060 return;
4061 }
4062 if (!exclude_extension.match(/^[0-9a-zA-Z]+$/)) {
4063 alert(updraftlion.exclude_ext_error_msg);
4064 return;
4065 }
4066 exclude_item_val = 'ext:'+exclude_extension;
4067 break;
4068
4069 case 'begin-with':
4070 var prefix = jQuery('#updraft_exclude_prefix_field').val();
4071 if ('' == prefix) {
4072 alert(updraftlion.exclude_type_prefix_msg);
4073 return;
4074 }
4075 if (!prefix.match(/^\s*[a-z-_\d,\s]+\s*$/i)) {
4076 alert(updraftlion.exclude_prefix_error_msg);
4077 return;
4078 }
4079 exclude_item_val = 'prefix:'+prefix;
4080 break;
4081
4082 case 'contain-clause':
4083 var exclude_jstree_selected = jQuery("#updraft_exclude_files_folders_wildcards_jstree").jstree("get_selected");
4084 if (0 == exclude_jstree_selected.length) {
4085 alert(updraftlion.exclude_select_folder_wildcards_msg);
4086 return;
4087 }
4088 var clause_val = jQuery(this).parents('div.updraft-exclude-panel').find('div.clause-input-container input').val();
4089 jQuery(this).parents('div.updraft-exclude-panel').find('div.clause-input-container input').val('');
4090 var clause_type = jQuery(this).parents('div.updraft-exclude-panel').find('div.clause-input-container select').val();
4091 if ('' == clause_val) {
4092 alert(updraftlion.exclude_contain_error_msg);
4093 return;
4094 }
4095 jQuery(this).parents('div.updraft-exclude-panel').find('div.clause-input-container select option').eq(0).prop('selected', true);
4096 var selected_file_or_folder = exclude_jstree_selected[0];
4097 var prefix_path = jQuery('#updraft_exclude_modal_path').val();
4098 if (selected_file_or_folder.substr(0, prefix_path.length) == prefix_path) {
4099 selected_file_or_folder = selected_file_or_folder.substr(prefix_path.length, selected_file_or_folder.length);
4100 }
4101 if ('/' == selected_file_or_folder.charAt(0)) selected_file_or_folder = selected_file_or_folder.substr(1);
4102 if ('/' == selected_file_or_folder.charAt(selected_file_or_folder.length - 1)) selected_file_or_folder = selected_file_or_folder.substr(0, selected_file_or_folder.length - 1);
4103 exclude_item_val = selected_file_or_folder;
4104 if ('' !== exclude_item_val) exclude_item_val += '/';
4105 clause_val = clause_val.replace(/\*/g, '\\*');
4106 if ('beginning' === clause_type) {
4107 exclude_item_val += clause_val + '*';
4108 } else if ('middle' === clause_type) {
4109 exclude_item_val += '*' + clause_val + '*';
4110 } else if ('end' === clause_type) {
4111 exclude_item_val += '*' + clause_val;
4112 }
4113 break;
4114
4115 default:
4116 return;
4117 }
4118
4119 var include_backup_file = jQuery('#updraft_exclude_modal_for').val();
4120 if (!updraft_is_unique_exclude_rule(exclude_item_val, include_backup_file)) return;
4121
4122 var exclude_entity_html = '<div class="updraft_exclude_entity_wrapper"><input type="text" class="updraft_exclude_entity_field updraft_include_' + include_backup_file + '_exclude_entity" name="updraft_include_' + include_backup_file + '_exclude_entity[]" value="' + exclude_item_val + '" data-val="' + exclude_item_val + '" data-include-backup-file="' + include_backup_file + '" readonly="readonly"><a href="#" class="updraft_exclude_entity_edit dashicons dashicons-edit" data-include-backup-file="' + include_backup_file + '"></a><a href="#" class="updraft_exclude_entity_update dashicons dashicons-yes" data-include-backup-file="' + include_backup_file + '" style="display: none;"></a><a href="#" class="updraft_exclude_entity_delete dashicons dashicons-no" data-include-backup-file="' + include_backup_file + '"></a></div>';
4123 jQuery('.updraft_exclude_entity_container[data-include-backup-file="' + include_backup_file + '"]').append(exclude_entity_html);
4124 updraft_exclude_entity_update(include_backup_file);
4125 jQuery('#updraft_exclude_modal').dialog('close');
4126 });
4127
4128 // TODO: This is suspected to be obsolete. Confirm + remove.
4129 jQuery('#updraft-navtab-settings-content .updraft-service').on('change', function() {
4130 var active_class = jQuery(this).val();
4131 jQuery('#updraft-navtab-settings-content .updraftplusmethod').hide();
4132 jQuery('#updraft-navtab-settings-content .'+active_class).show();
4133 });
4134
4135 jQuery('#updraft-navtab-settings-content a.updraft_show_decryption_widget').on('click', function(e) {
4136 e.preventDefault();
4137 jQuery('#updraftplus_db_decrypt').val(jQuery('#updraft_encryptionphrase').val());
4138 jQuery('#updraft-manualdecrypt-modal').slideToggle();
4139 });
4140
4141 jQuery('#updraftplus-phpinfo').on('click', function(e) {
4142 e.preventDefault();
4143 updraft_iframe_modal('phpinfo', updraftlion.phpinfo);
4144 });
4145
4146 jQuery('#updraftplus-rawbackuphistory').on('click', function(e) {
4147 e.preventDefault();
4148 updraft_iframe_modal('rawbackuphistory', updraftlion.raw);
4149 });
4150
4151 // + Added addons navtab
4152 jQuery('#updraft-navtab-status').on('click', function(e) {
4153 e.preventDefault();
4154 updraft_open_main_tab('status');
4155 updraft_page_is_visible = 1;
4156 updraft_console_focussed_tab = 'status';
4157 // Refresh the console, as its next update might be far away
4158 updraft_activejobs_update(true);
4159 });
4160 jQuery('#updraft-navtab-expert').on('click', function(e) {
4161 e.preventDefault();
4162 updraft_open_main_tab('expert');
4163 updraft_page_is_visible = 1;
4164 });
4165 jQuery('#updraft-navtab-settings, #updraft-navtab-settings2, #updraft_backupnow_gotosettings').on('click', function(e) {
4166 e.preventDefault();
4167 // These next two should only do anything if the relevant selector was clicked
4168 jQuery(this).parents('.updraftmessage').remove();
4169 jQuery('#updraft-backupnow-modal').dialog('close');
4170 updraft_open_main_tab('settings');
4171 updraft_page_is_visible = 1;
4172 });
4173 jQuery('#updraft-navtab-addons').on('click', function(e) {
4174 e.preventDefault();
4175 jQuery(this).addClass('b#nav-tab-active');
4176 updraft_open_main_tab('addons');
4177 updraft_page_is_visible = 1;
4178 });
4179
4180 jQuery('#updraft-navtab-backups').on('click', function(e) {
4181 e.preventDefault();
4182 updraft_console_focussed_tab = 'backups';
4183 updraft_historytimertoggle(1);
4184 updraft_open_main_tab('backups');
4185 });
4186
4187 jQuery('#updraft-navtab-migrate').on('click', function(e) {
4188 e.preventDefault();
4189 jQuery('#updraft_migrate_tab_alt').html('').hide();
4190 updraft_open_main_tab('migrate');
4191 updraft_page_is_visible = 1;
4192 if (!jQuery('#updraft_migrate .updraft_migrate_widget_module_content').is(':visible')) {
4193 jQuery('.updraft_migrate_intro').show();
4194 }
4195 });
4196
4197 if ('migrate' == updraftlion.tab) jQuery('#updraft-navtab-migrate').trigger('click');
4198
4199 updraft_send_command('ping', null, function(data, response) {
4200 if ('success' == response && data != 'pong' && data.indexOf('pong')>=0) {
4201 jQuery('#updraft-navtab-backups-content .ud-whitespace-warning').show();
4202 console.log("UpdraftPlus: Extra output warning: response (which should be just (string)'pong') follows.");
4203 console.log(data);
4204 }
4205 }, { json_parse: false, type: 'GET' });
4206
4207 // Section: Plupload
4208 try {
4209 if (typeof updraft_plupload_config !== 'undefined') {
4210 plupload_init();
4211 }
4212 } catch (err) {
4213 console.log(err);
4214 }
4215
4216 function plupload_init() {
4217
4218 // create the uploader and pass the config from above
4219 var uploader = new plupload.Uploader(updraft_plupload_config);
4220
4221 // checks if browser supports drag and drop upload, makes some css adjustments if necessary
4222 uploader.bind('Init', function(up) {
4223 var uploaddiv = jQuery('#plupload-upload-ui');
4224
4225 if (up.features.dragdrop) {
4226 uploaddiv.addClass('drag-drop');
4227 jQuery('#drag-drop-area')
4228 .on('dragover.wp-uploader', function() {
4229 uploaddiv.addClass('drag-over'); })
4230 .on('dragleave.wp-uploader, drop.wp-uploader', function() {
4231 uploaddiv.removeClass('drag-over'); });
4232
4233 } else {
4234 uploaddiv.removeClass('drag-drop');
4235 jQuery('#drag-drop-area').off('.wp-uploader');
4236 }
4237 });
4238
4239 uploader.init();
4240
4241 // a file was added in the queue
4242 uploader.bind('FilesAdded', function(up, files) {
4243 if ($('#updraft-plupload-modal').is(':hidden')) {
4244 $('#updraft-plupload-modal').slideToggle();
4245 }
4246 // var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
4247
4248 plupload.each(files, function(file) {
4249 // @codingStandardsIgnoreLine
4250 if (! /^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-[\-a-z]+([0-9]+?)?(\.(zip|gz|gz\.crypt))?$/i.test(file.name) && ! /^log\.([0-9a-f]{12})\.txt$/.test(file.name)) {
4251 var accepted_file = false;
4252 for (var i = 0; i<updraft_accept_archivename.length; i++) {
4253 if (updraft_accept_archivename[i].test(file.name)) {
4254 var accepted_file = true;
4255 }
4256 }
4257 if (!accepted_file) {
4258 if (/\.(zip|tar|tar\.gz|tar\.bz2)$/i.test(file.name) || /\.sql(\.gz)?$/i.test(file.name)) {
4259 jQuery('#updraft-message-modal-innards').html('<p><strong>'+file.name+"</strong></p> "+updraftlion.notarchive2);
4260 jQuery('#updraft-message-modal').dialog('open');
4261 } else {
4262 alert(file.name+": "+updraftlion.notarchive);
4263 }
4264 uploader.removeFile(file);
4265 return;
4266 }
4267 }
4268
4269 // a file was added, you may want to update your DOM here...
4270 jQuery('#filelist').append(
4271 '<div class="file" id="' + file.id + '"><b>' +
4272 file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
4273 '<div class="fileprogress"></div></div>');
4274 });
4275
4276 up.refresh();
4277 up.start();
4278 });
4279
4280 uploader.bind('UploadProgress', function(up, file) {
4281 jQuery('#' + file.id + " .fileprogress").width(file.percent + "%");
4282 jQuery('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
4283
4284 if (file.size == file.loaded) {
4285 jQuery('#' + file.id).html('<div class="file" id="' + file.id + '"><b>' +
4286 file.name + '</b> (<span>' + plupload.formatSize(parseInt(file.size * file.percent / 100)) + '</span>/' + plupload.formatSize(file.size) + ') - ' + updraftlion.complete +
4287 '</div>'); // Removed <div class="fileprogress"></div> (just before closing </div>) to make clearer it's complete.
4288 jQuery('#' + file.id + " .fileprogress").width(file.percent + "%");
4289 }
4290 });
4291
4292 uploader.bind('Error', function(up, error) {
4293
4294 console.log(error);
4295
4296 var err_makesure;
4297 if (error.code == "-200") {
4298 err_makesure = '\n'+updraftlion.makesure2;
4299 } else {
4300 err_makesure = updraftlion.makesure;
4301 }
4302
4303 var msg = updraftlion.uploaderr+' (code '+error.code+') : '+error.message;
4304
4305 if (error.hasOwnProperty('status') && error.status) {
4306 msg += ' ('+updraftlion.http_code+' '+error.status+')';
4307 }
4308
4309 if (error.hasOwnProperty('response')) {
4310 console.log('UpdraftPlus: plupload error: '+error.response);
4311 if (error.response.length < 100) msg += ' '+updraftlion.error+' '+error.response+'\n';
4312 }
4313
4314 msg += ' '+err_makesure;
4315
4316 alert(msg);
4317 });
4318
4319 // a file was uploaded
4320 uploader.bind('FileUploaded', function(up, file, response) {
4321
4322 if (response.status == '200') {
4323 // this is your ajax response, update the DOM with it or something...
4324 try {
4325 resp = ud_parse_json(response.response);
4326 if (resp.e) {
4327 alert(updraftlion.uploaderror+" "+resp.e);
4328 } else if (resp.dm) {
4329 alert(resp.dm);
4330 updraft_updatehistory(1, 0);
4331 } else if (resp.m) {
4332 updraft_updatehistory(1, 0);
4333 } else {
4334 alert('Unknown server response: '+response.response);
4335 }
4336
4337 } catch (err) {
4338 console.log(response);
4339 alert(updraftlion.jsonnotunderstood);
4340 }
4341
4342 } else {
4343 alert('Unknown server response status: '+response.code);
4344 console.log(response);
4345 }
4346
4347 });
4348 }
4349
4350 // Functions in the debugging console
4351 jQuery('#updraftplus_httpget_go').on('click', function(e) {
4352 e.preventDefault();
4353 updraftplus_httpget_go(0);
4354 });
4355
4356 jQuery('#updraftplus_httpget_gocurl').on('click', function(e) {
4357 e.preventDefault();
4358 updraftplus_httpget_go(1);
4359 });
4360
4361 jQuery('#updraftplus_callwpaction_go').on('click', function(e) {
4362 e.preventDefault();
4363 params = { wpaction: jQuery('#updraftplus_callwpaction').val() };
4364 updraft_send_command('call_wordpress_action', params, function(response) {
4365 if (response.e) {
4366 alert(response.e);
4367 } else if (response.s) {
4368 // Silence
4369 } else if (response.r) {
4370 jQuery('#updraftplus_callwpaction_results').html(response.r);
4371 } else {
4372 console.log(response);
4373 alert(updraftlion.jsonnotunderstood);
4374 }
4375 });
4376 });
4377
4378 function updraftplus_httpget_go(curl) {
4379 params = { uri: jQuery('#updraftplus_httpget_uri').val() };
4380 params.curl = curl;
4381 updraft_send_command('httpget', params, function(resp) {
4382 if (resp.e) { alert(resp.e); }
4383 if (resp.r) {
4384 jQuery('#updraftplus_httpget_results').html('<pre>'+resp.r+'</pre>');
4385 } else {
4386 console.log(resp);
4387 }
4388 }, { type: 'GET' });
4389 }
4390
4391 jQuery('#updraft_activejobs_table, #updraft-navtab-migrate-content').on('click', '.updraft_jobinfo_delete', function(e) {
4392 e.preventDefault();
4393 var job_id = jQuery(this).data('jobid');
4394 if (job_id) {
4395 $(this).addClass('disabled');
4396 updraft_activejobs_delete(job_id);
4397 } else {
4398 console.log("UpdraftPlus: A stop job link was clicked, but the Job ID could not be found");
4399 }
4400 });
4401
4402 jQuery('#updraft_activejobs_table, #updraft-navtab-backups-content .updraft_existing_backups, #updraft-backupnow-inpage-modal, #updraft-navtab-migrate-content').on('click', '.updraft-log-link', function(e) {
4403 e.preventDefault();
4404 var file_id = jQuery(this).data('fileid');
4405 var job_id = jQuery(this).data('jobid');
4406 if (file_id) {
4407 updraft_popuplog(file_id);
4408 } else if (job_id) {
4409 updraft_popuplog(job_id);
4410 } else {
4411 console.log("UpdraftPlus: A log link was clicked, but the Job ID could not be found");
4412 }
4413 });
4414
4415 function updraft_restore_setup(entities, key, show_data) {
4416 updraft_restore_setoptions(entities);
4417 if (key.toString().match(/^[0-9]+$/i)) jQuery('#updraft_restore_timestamp').val(key);
4418 jQuery('.updraft_restore_date').text(show_data);
4419
4420 updraft_restore_stage = 1;
4421
4422 // jQuery('#updraft-restore-modal').dialog('open');
4423 updraft_restore_modal.open();
4424 updraft_activejobs_update(true);
4425 }
4426
4427 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', 'button.choose-components-button', function(e) {
4428 var entities = jQuery(this).data('entities');
4429 var backup_timestamp = jQuery(this).data('backup_timestamp');
4430 var show_data = jQuery(this).data('showdata');
4431 updraft_restore_setup(entities, backup_timestamp, show_data);
4432 });
4433
4434 /**
4435 * Get the value of a named URL parameter - https://stackoverflow.com/questions/4548487/jquery-read-query-string
4436 *
4437 * @param {string} name - URL parameter to return the value of
4438 *
4439 * @returns {string}
4440 */
4441 function get_parameter_by_name(name) {
4442 name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
4443 var regex_s = "[\\?&]"+name+"=([^&#]*)";
4444 var regex = new RegExp(regex_s);
4445 var results = regex.exec(window.location.href);
4446 if (results == null) {
4447 return '';
4448 } else {
4449 return decodeURIComponent(results[1].replace(/\+/g, ' '));
4450 }
4451 }
4452
4453 if (get_parameter_by_name('udaction') == 'initiate_restore') {
4454 var entities = get_parameter_by_name('entities');
4455 var backup_timestamp = get_parameter_by_name('backup_timestamp');
4456 var show_data = get_parameter_by_name('showdata');
4457 updraft_restore_setup(entities, backup_timestamp, show_data);
4458 }
4459
4460 var updraft_upload_modal_buttons = {};
4461
4462 updraft_upload_modal_buttons[updraftlion.uploadbutton] = function () {
4463 var key = jQuery('#updraft_upload_timestamp').val();
4464 var nonce = jQuery('#updraft_upload_nonce').val();
4465 var services = '';
4466 var send_list = false;
4467
4468 jQuery('.updraft_remote_storage_destination').each(function (index) {
4469 if (jQuery(this).is(':checked')) { send_list = true; }
4470 });
4471
4472 if (!send_list) {
4473 jQuery('#updraft-upload-modal-error').html(updraftlion.local_upload_error);
4474 return;
4475 } else {
4476 services = jQuery("input[name^='updraft_remote_storage_destination_']").serializeArray();
4477 }
4478
4479 jQuery(this).dialog("close");
4480 alert(updraftlion.local_upload_started);
4481 updraft_send_command('upload_local_backup', {
4482 use_nonce: nonce,
4483 use_timestamp: key,
4484 services: services
4485 });
4486
4487 };
4488
4489 updraft_upload_modal_buttons[updraftlion.cancel] = function () {
4490 jQuery(this).dialog("close");
4491 };
4492
4493 jQuery("#updraft-upload-modal").dialog({
4494 autoOpen: false, modal: true, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
4495 open: function(event, ui) {
4496 $(this).parent().trigger('focus');
4497 $(this).dialog('option', 'width', 308);
4498 if (jQuery(window).height() > 460) {
4499 $(this).dialog('option', 'height', 318);
4500 } else if (jQuery(window).height() > 250 && jQuery(window).height() < 461) {
4501 $(this).dialog('option', 'height', 460);
4502 } else {
4503 $(this).dialog('option', 'height', jQuery(window).height() - 20);
4504 }
4505 },
4506 buttons: updraft_upload_modal_buttons
4507 });
4508
4509 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', 'button.updraft-upload-link', function (e) {
4510 e.preventDefault();
4511 var nonce = jQuery(this).data('nonce').toString();
4512 var key = jQuery(this).data('key').toString();
4513 var services = jQuery(this).data('services').toString();
4514 if (nonce) {
4515 updraft_upload(key, nonce, services);
4516 } else {
4517 console.log("UpdraftPlus: A upload link was clicked, but the Job ID could not be found");
4518 }
4519 });
4520
4521 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', '.updraft-load-more-backups', function (e) {
4522 e.preventDefault();
4523 var backup_count = parseInt(jQuery('#updraft-navtab-backups-content .updraft_existing_backups .updraft_existing_backups_row').length) + parseInt(updraftlion.existing_backups_limit);
4524 updraft_updatehistory(0, 0, 0, backup_count);
4525 });
4526
4527 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', '.updraft-load-all-backups', function (e) {
4528 e.preventDefault();
4529 updraft_updatehistory(0, 0, 0, 9999999);
4530 });
4531
4532 /**
4533 * Opens the dialog box for confirmation of where to upload the backup
4534 *
4535 * @param {string} key - The UNIX timestamp of the backup
4536 * @param {string} nonce - The backup job ID
4537 * @param {string} services - A list of services that have not been uploaded to yet
4538 */
4539 function updraft_upload(key, nonce, services) {
4540 jQuery('#updraft_upload_timestamp').val(key);
4541 jQuery('#updraft_upload_nonce').val(nonce);
4542 var services_array = services.split(",");
4543 jQuery('.updraft_remote_storage_destination').each(function (index) {
4544 var name = jQuery(this).val();
4545 if (jQuery.inArray(name, services_array) == -1) {
4546 jQuery(this).prop('checked', false);
4547 jQuery(this).prop('disabled', true);
4548 var label = $(this).prop("labels");
4549 jQuery(label).find('span').show();
4550 }
4551 });
4552 jQuery('#updraft-upload-modal').dialog('open');
4553 }
4554
4555 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', '.updraft-delete-link', function(e) {
4556 e.preventDefault();
4557 var hasremote = jQuery(this).data('hasremote');
4558 var nonce = jQuery(this).data('nonce').toString();
4559 var key = jQuery(this).data('key').toString();
4560 if (nonce) {
4561 updraft_delete(key, nonce, hasremote);
4562 } else {
4563 console.log("UpdraftPlus: A delete link was clicked, but the Job ID could not be found");
4564 }
4565 });
4566
4567 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('click', 'button.updraft_download_button', function(e) {
4568 e.preventDefault();
4569 var base = 'uddlstatus_';
4570 var backup_timestamp = jQuery(this).data('backup_timestamp');
4571 var what = jQuery(this).data('what');
4572 var whicharea = '.ud_downloadstatus';
4573 var set_contents = jQuery(this).data('set_contents');
4574 var prettydate = jQuery(this).data('prettydate');
4575 var async = true;
4576 updraft_downloader(base, backup_timestamp, what, whicharea, set_contents, prettydate, async);
4577 });
4578
4579 jQuery('#updraft-navtab-backups-content .updraft_existing_backups').on('dblclick', '.updraft_existingbackup_date', function (e) {
4580 e.preventDefault();
4581 var nonce = jQuery(this).data('nonce').toString();
4582 var timestamp = jQuery(this).data('timestamp').toString();
4583 updraft_send_command('rawbackup_history', { timestamp: timestamp, nonce: nonce }, function (response) {
4584 if (response.hasOwnProperty('rawbackup')) {
4585 var textArea = document.createElement('textarea');
4586 textArea.innerHTML = response.rawbackup;
4587 updraft_html_modal(textArea.value, updraftlion.raw, 780, 500);
4588 } else {
4589 updraft_html_modal(updraftlion.jsonnotunderstood, updraftlion.raw, 780, 500);
4590 }
4591 }, { type: 'POST' });
4592
4593 updraft_html_modal('<div style="margin:auto;text-align:center;margin-top:150px;"><img src="' + updraftlion.ud_url + '/images/udlogo-rotating.gif" /> <br>'+ updraftlion.loading +'</div>', updraftlion.raw, 780, 500);
4594 });
4595
4596 jQuery('#backupnow_database_moreoptions').on('click', 'div.backupnow-db-tables > a', function(e) {
4597 e.preventDefault();
4598 jQuery('> input', jQuery(this).parents('div.backupnow-db-tables')).prop('checked', false);
4599 if (jQuery(this).hasClass('backupnow-select-all-table')) {
4600 jQuery('> input', jQuery(this).parents('div.backupnow-db-tables')).prop('checked', true);
4601 } else if (jQuery(this).hasClass('backupnow-select-all-this-site')) {
4602 jQuery('> input', jQuery(this).parents('div.backupnow-db-tables')).not('[data-non_wp_table]').prop('checked', true);
4603
4604 }
4605 });
4606 jQuery('#updraft-restore-modal').on('click', '.updraft_restore_select_all_themes', function(e) {
4607 e.preventDefault();
4608 jQuery('.updraft_restore_themes_options').prop('checked', true);
4609 });
4610 jQuery('#updraft-restore-modal').on('click', '.updraft_restore_deselect_all_themes', function(e) {
4611 e.preventDefault();
4612 jQuery('.updraft_restore_themes_options').prop('checked', false);
4613 });
4614 jQuery('#updraft-restore-modal').on('click', '.updraft_restore_select_all_plugins', function(e) {
4615 e.preventDefault();
4616 jQuery('.updraft_restore_plugins_options').prop('checked', true);
4617 });
4618 jQuery('#updraft-restore-modal').on('click', '.updraft_restore_deselect_all_plugins', function(e) {
4619 e.preventDefault();
4620 jQuery('.updraft_restore_plugins_options').prop('checked', false);
4621 });
4622 jQuery('.updraftmessage.admin-warning-litespeed').on('click', '.notice-dismiss', function(e) {
4623 e.preventDefault();
4624 updraft_send_command('dismiss_admin_warning_litespeed');
4625 });
4626 jQuery('.updraftmessage.admin-warning-pclzip').on('click', '.notice-dismiss', function(e) {
4627 e.preventDefault();
4628 updraft_send_command('dismiss_admin_warning_pclzip');
4629 });
4630
4631 function apply_search_on_db_size() {
4632 var value = jQuery('.db-search').val().toLowerCase();
4633 jQuery(".db-size-content tr").filter(function() {
4634 jQuery(this).toggle(jQuery(this).text().toLowerCase().indexOf(value) > -1)
4635 });
4636 }
4637
4638 jQuery('#db_size.advanced_tools_button, .db-size-refresh').on('click', function(e) {
4639 e.preventDefault();
4640
4641 var $total_size = jQuery('.advanced_settings_content .advanced_tools.db_size .total-size');
4642 var $table_body = jQuery('.advanced_settings_content .advanced_tools.db_size tbody.db-size-content');
4643
4644 // trigger the ajax from the 'Database size' menu only for the first time
4645 if (jQuery(this).hasClass('advanced_tools_button') && '' != $table_body.html()) { return; }
4646
4647 $table_body.html('');
4648
4649 updraft_send_command('db_size', 1, function (response) {
4650 $total_size.html(response.size);
4651 var html = '';
4652 $.each(response.tables, function(i, table) {
4653 html += '<tr>' +
4654 '<td>' + table.name + '</td>' +
4655 '<td>' + table.records + '</td>' +
4656 '<td>' + convert_numeric_size_to_text(table.data_length) + '</td>' +
4657 '<td>' + convert_numeric_size_to_text(table.index_length) + '</td>' +
4658 '<td>' + table.type + '</td>' +
4659 '</tr>';
4660 });
4661 $table_body.html(html);
4662 apply_search_on_db_size();
4663 });
4664 });
4665
4666 jQuery('.db-search').on('input', function() {
4667 apply_search_on_db_size();
4668 });
4669
4670 jQuery('.db-search-clear').on('click', function(e) {
4671 e.preventDefault();
4672 jQuery('.db-search').val('');
4673 apply_search_on_db_size();
4674 });
4675
4676 jQuery('.updraft_restore_main').on('click', 'button#updraft_restore_abort', function(e) {
4677 e.preventDefault();
4678 jQuery('#updraft_restore_continue_action').val('updraft_restore_abort');
4679 jQuery(this).parent('form').trigger('submit');
4680 });
4681
4682 jQuery('#cron_events.advanced_tools_button').on('click', function(e) {
4683 e.preventDefault();
4684
4685 var $table_body = jQuery('.advanced_settings_content .advanced_tools.cron_events tbody');
4686 $table_body.html('');
4687
4688 updraft_send_command('get_cron_events', 1, function (response) {
4689 $.each(response, function(index, item) {
4690 var first_column = '<td>';
4691 if (item.overdue) first_column = '<td style="border-left:4px solid #DB6A03;">';
4692
4693 $table_body.append($('<tr>').append(
4694 $(first_column).text(item.hook),
4695 $('<td>').text(item.name)
4696 ));
4697 if (item.overdue) {
4698 $table_body.find('tr:last').append('<td><span></span><br><span class="dashicons dashicons-warning" aria-hidden="true" style="color:#DB6A03"></span> <span></span></td>');
4699 } else {
4700 $table_body.find('tr:last').append('<td><span></span><br><span></span></td>');
4701 }
4702 $table_body.find('tr:last td:last span').not('.dashicons').first().text(item.time);
4703 $table_body.find('tr:last td:last span').last().text(item.interval);
4704 });
4705 });
4706 });
4707 });
4708
4709 // UpdraftVault
4710 jQuery(function($) {
4711
4712 var settings_css_prefix = '#updraft-navtab-settings-content ';
4713
4714 $(settings_css_prefix+'#remote-storage-holder').on('click', '.updraftvault_backtostart', function(e) {
4715 e.preventDefault();
4716 $(settings_css_prefix+'#updraftvault_settings_showoptions').slideUp();
4717 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
4718 $(settings_css_prefix+'#updraftvault_settings_connected').slideUp();
4719 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
4720 });
4721
4722 // Prevent default event when pressing return in the form
4723 $(settings_css_prefix).on('keypress','#updraftvault_settings_connect input', function(e) {
4724 if (13 == e.which) {
4725 $(settings_css_prefix+'#updraftvault_connect_go').trigger('click');
4726 return false;
4727 }
4728 });
4729
4730 $(settings_css_prefix+'#remote-storage-holder').on('click', '#updraftvault_recountquota', function(e) {
4731 e.preventDefault();
4732 $(settings_css_prefix+'#updraftvault_recountquota').html(updraftlion.counting);
4733 try {
4734 updraft_send_command('vault_recountquota', { instance_id: $('#updraftvault_settings_connect').data('instance_id') }, function(response) {
4735 $(settings_css_prefix+'#updraftvault_recountquota').html(updraftlion.updatequotacount);
4736 if (response.hasOwnProperty('html')) {
4737 $(settings_css_prefix+'#updraftvault_settings_connected').html(response.html);
4738 if (response.hasOwnProperty('connected')) {
4739 if (response.connected) {
4740 $(settings_css_prefix+'#updraftvault_settings_default').hide();
4741 $(settings_css_prefix+'#updraftvault_settings_connected').show();
4742 } else {
4743 $(settings_css_prefix+'#updraftvault_settings_connected').hide();
4744 $(settings_css_prefix+'#updraftvault_settings_default').show();
4745 }
4746 }
4747 }
4748 }, { error_callback: function(response, status, error_code, resp) {
4749 $(settings_css_prefix+'#updraftvault_recountquota').html(updraftlion.updatequotacount);
4750 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
4751 console.error(resp.fatal_error_message);
4752 alert(resp.fatal_error_message);
4753 } else {
4754 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
4755 console.log(error_message);
4756 alert(error_message);
4757 console.log(response);
4758 }
4759 }
4760 });
4761 } catch (err) {
4762 $(settings_css_prefix+'#updraftvault_recountquota').html(updraftlion.updatequotacount);
4763 console.log(err);
4764 }
4765 });
4766
4767 $(settings_css_prefix+'#remote-storage-holder').on('click', '#updraftvault_disconnect', function(e) {
4768 e.preventDefault();
4769 $(settings_css_prefix+'#updraftvault_disconnect').html(updraftlion.disconnecting);
4770 try {
4771 updraft_send_command('vault_disconnect', { immediate_echo: true, instance_id: $('#updraftvault_settings_connect').data('instance_id') }, function(response) {
4772 $(settings_css_prefix+'#updraftvault_disconnect').html(updraftlion.disconnect);
4773 if (response.hasOwnProperty('html')) {
4774 $(settings_css_prefix+'#updraftvault_settings_connected').html(response.html).slideUp();
4775 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
4776 }
4777 }, { error_callback: function(response, status, error_code, resp) {
4778 $(settings_css_prefix+'#updraftvault_disconnect').html(updraftlion.disconnect);
4779 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
4780 console.error(resp.fatal_error_message);
4781 alert(resp.fatal_error_message);
4782 } else {
4783 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
4784 console.log(error_message);
4785 alert(error_message);
4786 console.log(response);
4787 }
4788 }
4789 });
4790 } catch (err) {
4791 $(settings_css_prefix+'#updraftvault_disconnect').html(updraftlion.disconnect);
4792 console.log(err);
4793 }
4794 });
4795
4796 $(settings_css_prefix+'#remote-storage-holder').on('click', '#updraftvault_connect', function(e) {
4797 e.preventDefault();
4798 $(settings_css_prefix+'#updraftvault_settings_default').slideUp();
4799 $(settings_css_prefix+'#updraftvault_settings_connect').slideDown();
4800 });
4801
4802 $(settings_css_prefix+'#remote-storage-holder').on('click', '#updraftvault_showoptions', function(e) {
4803 e.preventDefault();
4804 $(settings_css_prefix+'#updraftvault_settings_default').slideUp();
4805 $(settings_css_prefix+'#updraftvault_settings_showoptions').slideDown();
4806 });
4807
4808 $('#remote-storage-holder').on('keyup', '.updraftplus_onedrive_folder_input', function(e) {
4809 var folder = $(this).val();
4810 var td_container = $(this).closest('td')
4811 if (0 == folder.indexOf('https:') || 0 == folder.indexOf('http:')) {
4812 if (!td_container.find('.onedrive_folder_error').length) {
4813 td_container.append('<div class="onedrive_folder_error">'+updraftlion.onedrive_folder_url_warning+'</div>');
4814 }
4815 } else {
4816 td_container.find('.onedrive_folder_error').slideUp('slow', function() {
4817 td_container.find('.onedrive_folder_error').remove();
4818 });
4819 }
4820 });
4821
4822 $(settings_css_prefix+'#remote-storage-holder').on('click', '#updraftvault_connect_go', function(e) {
4823 $(settings_css_prefix+'#updraftvault_connect_go').html(updraftlion.connecting);
4824 updraft_send_command('vault_connect', {
4825 email: $('#updraftvault_email').val(),
4826 pass: $('#updraftvault_pass').val(),
4827 instance_id: $('#updraftvault_settings_connect').data('instance_id'),
4828 }, function(resp, status, response) {
4829 $(settings_css_prefix+'#updraftvault_connect_go').html(updraftlion.connect);
4830 if (resp.hasOwnProperty('e')) {
4831 updraft_html_modal('<h4 style="margin-top:0px; padding-top:0px;">'+updraftlion.errornocolon+'</h4><p>'+resp.e+'</p>', updraftlion.disconnect, 400, 250);
4832 if (resp.hasOwnProperty('code') && resp.code == 'no_quota') {
4833 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
4834 $(settings_css_prefix+'#updraftvault_settings_default').slideDown();
4835 }
4836 } else if (resp.hasOwnProperty('connected') && resp.connected && resp.hasOwnProperty('html')) {
4837 $(settings_css_prefix+'#updraftvault_settings_connect').slideUp();
4838 $(settings_css_prefix+'#updraftvault_settings_connected').html(resp.html).slideDown();
4839 } else {
4840 console.log(resp);
4841 alert(updraftlion.unexpectedresponse+' '+response);
4842 }
4843 }, { error_callback: function(response, status, error_code, resp) {
4844 $(settings_css_prefix+'#updraftvault_connect_go').html(updraftlion.connect);
4845 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
4846 console.error(resp.fatal_error_message);
4847 alert(resp.fatal_error_message);
4848 } else {
4849 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
4850 console.log(error_message);
4851 alert(error_message);
4852 console.log(response);
4853 }
4854 }
4855 });
4856 return false;
4857 });
4858
4859 // Mark a backup as always keep (do not delete)
4860 $('#updraft-iframe-modal').on('change', '#always_keep_this_backup', function() {
4861 var backup_key = $(this).data('backup_key');
4862 var params = {
4863 backup_key: backup_key,
4864 always_keep: $(this).is(':checked') ? 1 : 0,
4865 };
4866 updraft_send_command('always_keep_this_backup', params, function(resp) {
4867 if (resp.hasOwnProperty('rawbackup')) {
4868 jQuery('#updraft-iframe-modal').dialog('close');
4869 jQuery('.updraft_existing_backups_row_'+backup_key+' .updraft_existingbackup_date').data('rawbackup', resp.rawbackup);
4870 updraft_html_modal(jQuery('.updraft_existing_backups_row_'+backup_key+' .updraft_existingbackup_date').data('rawbackup'), updraftlion.raw, 780, 500);
4871 }
4872 });
4873 });
4874
4875
4876 }); // End ready Vault
4877
4878 // Next: the encrypted database pluploader
4879 jQuery(function($) {
4880
4881 try {
4882 if (typeof updraft_plupload_config2 !== 'undefined') {
4883 plupload_init();
4884 }
4885 } catch (err) {
4886 console.log(err);
4887 }
4888
4889 function plupload_init() {
4890 // create the uploader and pass the config from above
4891 var uploader = new plupload.Uploader(updraft_plupload_config2);
4892
4893 // checks if browser supports drag and drop upload, makes some css adjustments if necessary
4894 uploader.bind('Init', function(up) {
4895 var uploaddiv = jQuery('#plupload-upload-ui2');
4896
4897 if (up.features.dragdrop) {
4898 uploaddiv.addClass('drag-drop');
4899 jQuery('#drag-drop-area2')
4900 .on('dragover.wp-uploader', function() {
4901 uploaddiv.addClass('drag-over'); })
4902 .on('dragleave.wp-uploader, drop.wp-uploader', function() {
4903 uploaddiv.removeClass('drag-over'); });
4904 } else {
4905 uploaddiv.removeClass('drag-drop');
4906 jQuery('#drag-drop-area2').off('.wp-uploader');
4907 }
4908 });
4909
4910 uploader.init();
4911
4912 // a file was added in the queue
4913 uploader.bind('FilesAdded', function(up, files) {
4914 // var hundredmb = 100 * 1024 * 1024, max = parseInt(up.settings.max_file_size, 10);
4915
4916 plupload.each(files, function(file) {
4917 // @codingStandardsIgnoreLine
4918 if (!/^backup_([\-0-9]{15})_.*_([0-9a-f]{12})-db([0-9]+)?\.(gz\.crypt)$/i.test(file.name)) {
4919 alert(file.name+': '+updraftlion.notdba);
4920 uploader.removeFile(file);
4921 return;
4922 }
4923
4924 // a file was added, you may want to update your DOM here...
4925 jQuery('#filelist2').append(
4926 '<div class="file" id="' + file.id + '"><b>' +
4927 file.name + '</b> (<span>' + plupload.formatSize(0) + '</span>/' + plupload.formatSize(file.size) + ') ' +
4928 '<div class="fileprogress"></div></div>');
4929 });
4930
4931 up.refresh();
4932 up.start();
4933 });
4934
4935 uploader.bind('UploadProgress', function(up, file) {
4936 jQuery('#' + file.id + " .fileprogress").width(file.percent + "%");
4937 jQuery('#' + file.id + " span").html(plupload.formatSize(parseInt(file.size * file.percent / 100)));
4938 });
4939
4940 uploader.bind('Error', function(up, error) {
4941 if ('-200' == error.code) {
4942 err_makesure = '\n'+updraftlion.makesure2;
4943 } else {
4944 err_makesure = updraftlion.makesure;
4945 }
4946 alert(updraftlion.uploaderr+' (code '+error.code+") : "+error.message+" "+err_makesure);
4947 });
4948
4949 // a file was uploaded
4950 uploader.bind('FileUploaded', function(up, file, response) {
4951
4952 if (response.status == '200') {
4953 // this is your ajax response, update the DOM with it or something...
4954 if (response.response.substring(0,6) == 'ERROR:') {
4955 alert(updraftlion.uploaderror+" "+response.response.substring(6));
4956 } else if (response.response.substring(0,3) == 'OK:') {
4957 bkey = response.response.substring(3);
4958 jQuery('#' + file.id + " .fileprogress").hide();
4959 jQuery('#' + file.id).append(updraftlion.uploaded+' <a href="?page=updraftplus&action=downloadfile&updraftplus_file='+bkey+'&decrypt_key='+encodeURIComponent(jQuery('#updraftplus_db_decrypt').val())+'">'+updraftlion.followlink+'</a> '+updraftlion.thiskey+' '+jQuery('#updraftplus_db_decrypt').val().replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"));
4960 } else {
4961 alert(updraftlion.unknownresp+' '+response.response);
4962 }
4963 } else {
4964 alert(updraftlion.ukrespstatus+' '+response.code);
4965 }
4966
4967 });
4968 }
4969
4970 jQuery('#updraft-hidethis').remove();
4971
4972 /*
4973 * A Handlebarsjs helper function that is used to compare
4974 * two values if they are equal. Please refer to the example below.
4975 * Assuming "comment_status" contains the value of "spam".
4976 *
4977 * @param {mixed} a The first value to compare
4978 * @param {mixed} b The second value to compare
4979 *
4980 * @example
4981 * // returns "<span>I am spam!</span>", otherwise "<span>I am not a spam!</span>"
4982 * {{#ifeq "spam" comment_status}}
4983 * <span>I am spam!</span>
4984 * {{else}}
4985 * <span>I am not a spam!</span>
4986 * {{/ifeq}}
4987 *
4988 * @return {string}
4989 */
4990
4991 Handlebars.registerHelper('ifeq', function (a, b, opts) {
4992 if ('string' !== typeof a && 'undefined' !== typeof a && null !== a) a = a.toString();
4993 if ('string' !== typeof b && 'undefined' !== typeof b && null !== b) b = b.toString();
4994 if (a === b) {
4995 return opts.fn(this);
4996 } else {
4997 return opts.inverse(this);
4998 }
4999 });
5000
5001 /*
5002 * Handlebars helper function to replace all password chars into asterisk char
5003 *
5004 * @param {string} password Required. The plain-text password
5005 *
5006 * @return {string}
5007 */
5008 Handlebars.registerHelper('maskPassword', function(password) {
5009 return password.replace(/./gi,'*');
5010 });
5011
5012 /*
5013 * Handlebars helper function that wraps javascript encodeURIComponent so that it could encode the following characters: , / ? : @ & = + $ #
5014 *
5015 * @param {string} uri Required. The URI to be encoded
5016 */
5017 Handlebars.registerHelper('encodeURIComponent', function(uri) {
5018 return encodeURIComponent(uri);
5019 });
5020
5021 /**
5022 * Handlebars helper function to compare two values using a specified operator
5023 *
5024 * @see https://stackoverflow.com/questions/8853396/logical-operator-in-a-handlebars-js-if-conditional#answer-16315366
5025 *
5026 * @param {mixed} v1 the first value to compare
5027 * @param {mixed} v2 the second value to compare
5028 *
5029 * @return {boolean} true if the first value matched against the second value, false otherwise
5030 */
5031 Handlebars.registerHelper('ifCond', function(v1, operator, v2, options) {
5032 switch (operator) {
5033 case '==':
5034 return (v1 == v2) ? options.fn(this) : options.inverse(this);
5035 case '===':
5036 return (v1 === v2) ? options.fn(this) : options.inverse(this);
5037 case '!=':
5038 return (v1 != v2) ? options.fn(this) : options.inverse(this);
5039 case '!==':
5040 return (v1 !== v2) ? options.fn(this) : options.inverse(this);
5041 case '<':
5042 return (v1 < v2) ? options.fn(this) : options.inverse(this);
5043 case '<=':
5044 return (v1 <= v2) ? options.fn(this) : options.inverse(this);
5045 case '>':
5046 return (v1 > v2) ? options.fn(this) : options.inverse(this);
5047 case '>=':
5048 return (v1 >= v2) ? options.fn(this) : options.inverse(this);
5049 case '&&':
5050 return (v1 && v2) ? options.fn(this) : options.inverse(this);
5051 case '||':
5052 return (v1 || v2) ? options.fn(this) : options.inverse(this);
5053 case 'typeof':
5054 return (v1 === typeof v2) ? options.fn(this) : options.inverse(this);
5055 case 'not_typeof':
5056 return (v1 !== typeof v2) ? options.fn(this) : options.inverse(this);
5057 default:
5058 return options.inverse(this);
5059 }
5060 });
5061
5062 /**
5063 * Handlebars helper function for looping through a block of code a specified number of times
5064 *
5065 * @param {mixed} from the start value
5066 * @param {mixed} to the end value where the loop will stop
5067 * @param {mixed} incr the increment number
5068 *
5069 * @return {mixed} the current processing number
5070 */
5071 Handlebars.registerHelper('for', function(from, to, incr, block) {
5072 var accum = '';
5073 for (var i = from; i < to; i += incr)
5074 accum += block.fn(i);
5075 return accum;
5076 });
5077
5078 /**
5079 * Assign value into a variable
5080 *
5081 * @param {string} name the variable name
5082 * @param {mixed} val the value
5083 */
5084 Handlebars.registerHelper('set_var', function(name, val, options) {
5085 if (!options.data.root) {
5086 options.data.root = {};
5087 }
5088 options.data.root[name] = val;
5089 });
5090
5091 /**
5092 * Get length of an array/object
5093 *
5094 * @param {mixed} object the object
5095 */
5096 Handlebars.registerHelper('get_length', function(object) {
5097 if ("undefined" !== typeof object && false === object instanceof Array) {
5098 return Object.keys(object).length;
5099 } else if (true === object instanceof Array) {
5100 return object.length;
5101 } else {
5102 return 0;
5103 }
5104 });
5105
5106 /**
5107 * Return a space-separated list of CSS classes suitable for rows in the configuration section
5108 *
5109 * @see UpdraftPlus_BackupModule::get_css_classes()
5110 *
5111 * @param {boolean} include_instance a boolean value to indicate if we want to include the instance_id in the css class, we may not want to include the instance if it's for a UI element that we don't want to be removed along with other UI elements that do include a instance id
5112 * @return {string} the list of CSS classes
5113 */
5114 Handlebars.registerHelper('get_template_css_classes', function(include_instance, options) {
5115 var css_classes = options.data.root.css_class + ' ' + options.data.root.method_id;
5116 if (!include_instance || !options.data.root['is_multi_options_feature_supported']) return css_classes;
5117 if (options.data.root['is_config_templates_feature_supported']) {
5118 css_classes += ' ' + options.data.root.method_id + '-' + options.data.root.instance_id;
5119 } else {
5120 css_classes += ' ' + options.data.root.method_id + '-' + options.data.root._instance_id;
5121 }
5122 return css_classes;
5123 });
5124
5125 /**
5126 * Output the value of an id or name attribute, as if currently within an input tag
5127 * This assumes standardised options handling (i.e. that the options array is updraft_(method-id))
5128 *
5129 * @see UpdraftPlus_BackupModule::output_settings_field_name_and_id()
5130 *
5131 * @param {string} input_attribute The attribute of an input tag
5132 * @param {mixed} fields the field identifiers
5133 * @return {string} a specific value to the given input attribute
5134 */
5135 Handlebars.registerHelper('get_template_input_attribute_value', function(input_attribute, fields, options) {
5136 var instance_id = options.data.root['is_config_templates_feature_supported'] ? options.data.root.instance_id : options.data.root._instance_id;
5137 var id = ename = '';
5138 var method_id = options.data.root.method_id;
5139 try {
5140 fields = JSON.parse(fields);
5141 } catch (e) {}
5142 if ("undefined" !== typeof fields && Array === fields.constructor) {
5143 for (var i=0; i<fields.length; i++) {
5144 id += '_' + fields[i];
5145 ename += '[' + fields[i] + ']';
5146 }
5147 } else {
5148 id = '_' + fields;
5149 ename = '[' + fields + ']';
5150 }
5151 if ('id' === input_attribute) {
5152 return 'updraft_'+method_id+id+'_'+instance_id;
5153 } else if ('name' === input_attribute) {
5154 return 'updraft_'+method_id+'[settings]['+instance_id+']'+ename;
5155 } else {
5156 return '';
5157 }
5158 });
5159
5160 /**
5161 * Return HTML a row of HTML elements for a test button
5162 *
5163 * @see UpdraftPlus_BackupModule::get_test_button_html()
5164 *
5165 * @param {string} title The text to be used in the button
5166 * @return {string} The HTML to be inserted into the settings page
5167 */
5168 Handlebars.registerHelper('get_template_test_button_html', function(title, options) {
5169 var instance_id = options.data.root['is_config_templates_feature_supported'] ? Handlebars.escapeExpression(options.data.root.instance_id) : Handlebars.escapeExpression(options.data.root._instance_id);
5170 var css_classes = Handlebars.escapeExpression(Handlebars.helpers.get_template_css_classes.apply(this, [true, options]));
5171 var input_label = Handlebars.escapeExpression(options.data.root.input_test_label);
5172 var method_id = Handlebars.escapeExpression(options.data.root.method_id);
5173 return '\
5174 <tr class="'+css_classes+'"> \
5175 <th></th> \
5176 <td> \
5177 <p> \
5178 <button id="updraft-'+method_id+'-test-'+instance_id+'" type="button" class="button-primary updraft-test-button updraft-'+method_id+'-test-'+instance_id+'" data-instance_id="'+instance_id+'" data-method="'+method_id+'" data-method_label="'+title+'">'+input_label+'</button> \
5179 </p> \
5180 </td> \
5181 </tr>';
5182 });
5183
5184 // Add remote methods html using handlebarjs
5185 if ($('#remote-storage-holder').length) {
5186 var html = '';
5187 var not_instance_ids = ['default', 'template_properties'];
5188 for (var method in updraftlion.remote_storage_templates) {
5189 if ('undefined' != typeof updraftlion.remote_storage_options[method] && not_instance_ids.length < Object.keys(updraftlion.remote_storage_options[method]).length) {
5190 var template = Handlebars.compile(updraftlion.remote_storage_templates[method]);
5191 for (var partial_template_name in updraftlion.remote_storage_partial_templates[method]) {
5192 Handlebars.registerPartial(partial_template_name, Handlebars.compile(updraftlion.remote_storage_partial_templates[method][partial_template_name]));
5193 }
5194 var first_instance = true;
5195 var instance_count = 1;
5196 for (var instance_id in updraftlion.remote_storage_options[method]) {
5197 if (not_instance_ids.indexOf(instance_id) > -1) continue;
5198
5199 var context = {}; // Initiate a reference by assigning an empty object to a variable (in this case the context variable) so that it can be used as a target of merging one or more other objects. Unlike basic values (boolean, string, integer, etc.), in Javascript objects and arrays are passed by reference
5200 // copy what are in the template properties to the context overwriting the same object properties, and then copy what are in the instance settings to the context overwriting all the same properties from the previous merging operation (if any). The context properties are overwritten by other objects that have the same properties later in the parameters order
5201 Object.assign(context, updraftlion.remote_storage_options[method]['template_properties'], updraftlion.remote_storage_options[method][instance_id]);
5202
5203 if ('undefined' == typeof context['instance_conditional_logic']) {
5204 context['instance_conditional_logic'] = {
5205 type: '', // always by default
5206 rules: [],
5207 };
5208 }
5209 context['instance_conditional_logic'].day_of_the_week_options = updraftlion.conditional_logic.day_of_the_week_options;
5210 context['instance_conditional_logic'].logic_options = updraftlion.conditional_logic.logic_options;
5211 context['instance_conditional_logic'].operand_options = updraftlion.conditional_logic.operand_options;
5212 context['instance_conditional_logic'].operator_options = updraftlion.conditional_logic.operator_options;
5213
5214 context['first_instance'] = first_instance;
5215 if ('undefined' == typeof context['instance_enabled']) {
5216 context['instance_enabled'] = 1;
5217 }
5218 if ('undefined' == typeof context['instance_label'] || '' == context['instance_label']) {
5219 var method_name = updraftlion.remote_storage_methods[method];
5220 var instance_label = ' (' + instance_count + ')';
5221 if (1 == instance_count) {
5222 instance_label = '';
5223 }
5224 context['instance_label'] = method_name + instance_label;
5225 }
5226 html += template(context);
5227 first_instance = false;
5228 instance_count++;
5229 }
5230 } else {
5231 html += updraftlion.remote_storage_templates[method];
5232 }
5233 }
5234 $('#remote-storage-holder').append(html).ready(function () {
5235 $('.updraftplusmethod').not('.none').hide();
5236 updraft_remote_storage_tabs_setup();
5237 updraft_setup_remote_storage_config_link();
5238 updraft_scroll_to_remote_storage_config();
5239 // Displays warning to the user of their mistake if they try to enter a URL in the OneDrive settings and saved
5240 $('#remote-storage-holder .updraftplus_onedrive_folder_input').trigger('keyup');
5241 initialize_remote_storage_select2_elements(jQuery('#remote-storage-holder'));
5242 });
5243 }
5244
5245 });
5246
5247 // Save/Export/Import settings via AJAX
5248 jQuery(function($) {
5249 // Pre-load the image so that it doesn't jerk when first used
5250 var my_image = new Image();
5251 my_image.src = updraftlion.ud_url+'/images/notices/updraft_logo.png';
5252
5253 // When inclusion options for file entities in the settings tab, reflect that in the "Backup Now" dialog, to prevent unexpected surprises
5254 $('#updraft-navtab-settings-content input.updraft_include_entity').on('change', function(e) {
5255 var event_target = $(this).attr('id');
5256 var checked = $(this).is(':checked');
5257 var backup_target = '#backupnow_files_'+event_target;
5258 $(backup_target).prop('checked', checked);
5259 });
5260
5261 $('#updraftplus-settings-save').on('click', function(e) {
5262 e.preventDefault();
5263 $.blockUI({
5264 css: {
5265 width: '300px',
5266 border: 'none',
5267 'border-radius': '10px',
5268 left: 'calc(50% - 150px)',
5269 padding: '20px',
5270 },
5271 message: '<div style="margin: 8px; font-size:150%;" class="updraft_saving_popup"><img src="'+updraftlion.ud_url+'/images/notices/updraft_logo.png" height="80" width="80" style="padding-bottom:10px;"><br>'+updraftlion.saving+'</div>'
5272 });
5273
5274 var form_data = gather_updraft_settings('string');
5275 // POST the settings back to the AJAX handler
5276 updraft_send_command('savesettings', {
5277 settings: form_data,
5278 updraftplus_version: updraftlion.updraftplus_version
5279 }, function(resp, status, response) {
5280 // Add page updates etc based on response
5281 updraft_handle_page_updates(resp, response);
5282
5283 $('#updraft-wrap .fade').delay(6000).fadeOut(2000);
5284 if (window.updraft_main_tour && !window.updraft_main_tour.canceled) {
5285 window.updraft_main_tour.show('settings_saved');
5286 check_cloud_authentication();
5287 } else {
5288 $('html, body').animate({
5289 scrollTop: $("#updraft-wrap").offset().top
5290 }, 1000, function() {
5291 check_cloud_authentication()
5292 });
5293 }
5294
5295 $.unblockUI();
5296 }, { action: 'updraft_savesettings', error_callback: function(response, status, error_code, resp) {
5297 $.unblockUI();
5298 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
5299 console.error(resp.fatal_error_message);
5300 alert(resp.fatal_error_message);
5301 } else {
5302 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
5303 console.log(error_message);
5304 alert(error_message);
5305 console.log(response);
5306 }
5307 }, nonce: updraftplus_settings_nonce});
5308 });
5309
5310 $('#updraftplus-settings-export').on('click', function() {
5311 if (updraft_settings_form_changed) {
5312 alert(updraftlion.unsaved_settings_export);
5313 }
5314 export_settings();
5315 });
5316
5317 $('#updraftplus-settings-import').on('click', function() {
5318 $.blockUI({
5319 css: {
5320 width: '300px',
5321 border: 'none',
5322 'border-radius': '10px',
5323 left: 'calc(50% - 150px)',
5324 padding: '20px',
5325 },
5326 message: '<div style="margin: 8px; font-size:150%;" class="updraft_saving_popup"><img src="'+updraftlion.ud_url+'/images/notices/updraft_logo.png" height="80" width="80" style="padding-bottom:10px;"><br>'+updraftlion.importing+'</div>'
5327 });
5328 var updraft_import_file_input = document.getElementById('import_settings');
5329 if (updraft_import_file_input.files.length == 0) {
5330 alert(updraftlion.import_select_file);
5331 $.unblockUI();
5332 return;
5333 }
5334 var updraft_import_file_file = updraft_import_file_input.files[0];
5335 var updraft_import_file_reader = new FileReader();
5336 updraft_import_file_reader.onload = function() {
5337 import_settings(this.result);
5338 };
5339 updraft_import_file_reader.readAsText(updraft_import_file_file);
5340 });
5341
5342 function export_settings() {
5343 var form_data = gather_updraft_settings('object');
5344
5345 var date_now = new Date();
5346
5347 // The 'version' attribute indicates the last time the format changed - i.e. do not update this unless there is a format change
5348 form_data = JSON.stringify({
5349 version: '1.12.40',
5350 epoch_date: date_now.getTime(),
5351 local_date: date_now.toLocaleString(),
5352 network_site_url: updraftlion.network_site_url,
5353 data: form_data
5354 });
5355
5356 // Attach this data to an anchor on page
5357 var link = document.body.appendChild(document.createElement('a'));
5358 link.setAttribute('download', updraftlion.export_settings_file_name);
5359 link.setAttribute('style', "display:none;");
5360 link.setAttribute('href', 'data:text/json' + ';charset=UTF-8,' + encodeURIComponent(form_data));
5361 link.click();
5362 }
5363
5364 function import_settings(updraft_file_result) {
5365 var parsed;
5366 try {
5367 parsed = ud_parse_json(updraft_file_result);
5368 } catch (e) {
5369 $.unblockUI();
5370 jQuery('#import_settings').val('');
5371 console.log(updraft_file_result);
5372 console.log(e);
5373 alert(updraftlion.import_invalid_json_file);
5374 return;
5375 }
5376 if (window.confirm(updraftlion.importing_data_from + ' ' + parsed['network_site_url'] + "\n" + updraftlion.exported_on + ' ' + parsed['local_date'] + "\n" + updraftlion.continue_import)) {
5377 // GET the settings back to the AJAX handler
5378 var stringified = JSON.stringify(parsed['data']);
5379 updraft_send_command('importsettings', {
5380 settings: stringified,
5381 updraftplus_version: updraftlion.updraftplus_version,
5382 }, function(decoded_response, status, response) {
5383 var resp = updraft_handle_page_updates(decoded_response);
5384 if (!resp.hasOwnProperty('saved') || resp.saved) {
5385 // Prevent the user being told they have unsaved settings
5386 updraft_settings_form_changed = false;
5387 // Add page updates etc based on response
5388 location.replace(updraftlion.updraft_settings_url);
5389 } else {
5390 $.unblockUI();
5391 if (resp.hasOwnProperty('error_message') && resp.error_message) {
5392 alert(resp.error_message);
5393 }
5394 }
5395 }, { action: 'updraft_importsettings', nonce: updraftplus_settings_nonce, error_callback: function(response, status, error_code, resp) {
5396 $.unblockUI();
5397 if (typeof resp !== 'undefined' && resp.hasOwnProperty('fatal_error')) {
5398 console.error(resp.fatal_error_message);
5399 alert(resp.fatal_error_message);
5400 } else {
5401 var error_message = "updraft_send_command: error: "+status+" ("+error_code+")";
5402 console.log(error_message);
5403 console.log(response);
5404 alert(error_message);
5405
5406 }
5407 }
5408 });
5409 } else {
5410 $.unblockUI();
5411 }
5412 }
5413
5414 /**
5415 * Retrieve the current settings from the DOM
5416 *
5417 * @param {string} output_format - the output format; valid values are 'string' or 'object'
5418 *
5419 * @returns String|Object
5420 */
5421 function gather_updraft_settings(output_format) {
5422
5423 var form_data = '';
5424 var output_format = ('undefined' === typeof output_format) ? 'string' : output_format;
5425
5426 if ('object' == output_format) {
5427 // Excluding the unnecessary 'action' input avoids triggering a very mis-conceived mod_security rule seen on one user's site
5428 form_data = $("#updraft-navtab-settings-content form input[name!='action'][name!='option_page'][name!='_wpnonce'][name!='_wp_http_referer'], #updraft-navtab-settings-content form textarea, #updraft-navtab-settings-content form select, #updraft-navtab-settings-content form input[type=checkbox]").serializeJSON({checkboxUncheckedValue: '0', useIntKeysAsArrayIndex: true});
5429 } else {
5430 // Excluding the unnecessary 'action' input avoids triggering a very mis-conceived mod_security rule seen on one user's site
5431 form_data = $("#updraft-navtab-settings-content form input[name!='action'], #updraft-navtab-settings-content form textarea, #updraft-navtab-settings-content form select").serialize();
5432
5433 // include unchecked checkboxes. user filter to only include unchecked boxes.
5434 $.each($('#updraft-navtab-settings-content form input[type=checkbox]')
5435 .filter(function(idx) {
5436 return $(this).prop('checked') == false
5437 }),
5438 function(idx, el) {
5439 // attach matched element names to the form_data with chosen value.
5440 var empty_val = '0';
5441 form_data += '&' + $(el).attr('name') + '=' + empty_val;
5442 }
5443 );
5444 }
5445
5446 return form_data;
5447 }
5448
5449 /**
5450 * Method to parse the response from the backend and update the page with the returned content or display error messages if failed
5451 *
5452 * @param {array} resp - the JSON-decoded response containing information to update the settings page with
5453 * @param {string} response - the JSON-encoded response containing information to update the settings page with
5454 *
5455 * @return {object} - the decoded response (empty if decoding was not successful)
5456 */
5457 function updraft_handle_page_updates(resp, response) {
5458
5459 try {
5460 var messages = resp.messages;
5461 // var debug = resp.changed.updraft_debug_mode;
5462
5463 // If backup dir is not writable, change the text, and grey out the 'Backup Now' button
5464 var backup_dir_writable = resp.backup_dir.writable;
5465 var backup_dir_message = resp.backup_dir.message;
5466 var backup_button_title = resp.backup_dir.button_title;
5467 } catch (e) {
5468 console.log(e);
5469 console.log(response);
5470 alert(updraftlion.jsonnotunderstood);
5471 $.unblockUI();
5472 return {};
5473 }
5474
5475 if (resp.hasOwnProperty('changed')) {
5476 console.log("UpdraftPlus: savesettings: some values were changed after being filtered");
5477 console.log(resp.changed);
5478 for (prop in resp.changed) {
5479 if ('object' === typeof resp.changed[prop]) {
5480 for (innerprop in resp.changed[prop]) {
5481 if (!$("[name='"+innerprop+"']").is(':checkbox')) {
5482 $("[name='"+prop+"["+innerprop+"]']").val(resp.changed[prop][innerprop]);
5483 }
5484 }
5485 } else {
5486 if (!$("[name='"+prop+"']").is(':checkbox')) {
5487 $("[name='"+prop+"']").val(resp.changed[prop]);
5488 }
5489 }
5490 }
5491 }
5492
5493 $('#updraft_writable_mess').html(backup_dir_message);
5494
5495 if (false == backup_dir_writable) {
5496 $('#updraft-backupnow-button').attr('disabled', 'disabled');
5497 $('#updraft-backupnow-button').attr('title', backup_button_title);
5498 $('.backupdirrow').css('display', 'table-row');
5499 } else {
5500 $('#updraft-backupnow-button').prop('disabled', false);
5501 $('#updraft-backupnow-button').removeAttr('title');
5502 // $('.backupdirrow').hide();
5503 }
5504
5505 if (resp.hasOwnProperty('updraft_include_more_path')) {
5506 $('#backupnow_includefiles_moreoptions').html(resp.updraft_include_more_path);
5507 }
5508
5509 if (resp.hasOwnProperty('backup_now_message')) { $('#backupnow_remote_container').html(resp.backup_now_message); }
5510
5511 // Move from 2 to 1
5512 $('.updraftmessage').remove();
5513
5514 $('#updraft_backup_started').before(resp.messages);
5515
5516 updraft_setup_remote_storage_config_link();
5517
5518 console.log(resp);
5519 // $('#updraft-next-backup-inner').html(resp.scheduled);
5520 $('#updraft-next-files-backup-inner').html(resp.files_scheduled);
5521 $('#updraft-next-database-backup-inner').html(resp.database_scheduled);
5522
5523 return resp;
5524
5525 }
5526
5527 /**
5528 * This function has the workings for checking if any cloud storage needs authentication
5529 * If so, these are amended to the HTML and the popup is shown to the users.
5530 */
5531 function check_cloud_authentication(){
5532 var show_auth_modal = false;
5533 jQuery('#updraft-authenticate-modal-innards').html('');
5534
5535 jQuery("div[class*=updraft_authenticate_] a.updraft_authlink").each(function () {
5536 var pretext = jQuery(this).data('pretext');
5537 if ('undefined' === typeof pretext) pretext = '';
5538 jQuery("#updraft-authenticate-modal-innards").append(pretext+'<p><a class="'+jQuery(this).attr('class')+'" href="'+jQuery(this).attr('href')+'">'+jQuery(this).html()+'</a></p>');
5539 show_auth_modal = true;
5540 });
5541
5542
5543 if (show_auth_modal) {
5544 var updraft_authenticate_modal_buttons = {};
5545 updraft_authenticate_modal_buttons[updraftlion.cancel] = function() {
5546 jQuery(this).dialog("close"); };
5547
5548 jQuery('#updraft-authenticate-modal').dialog({autoOpen: true,
5549 modal: true, resizable: false, draggable: false, resizeOnWindowResize: true, scrollWithViewport: true, resizeAccordingToViewport: true, useContentSize: false,
5550 open: function(event, ui) {
5551 $(this).dialog('option', 'width', 860);
5552 $(this).dialog('option', 'height', 260);
5553 },
5554 buttons: updraft_authenticate_modal_buttons}).dialog('open');
5555 }
5556 }
5557
5558 $('.udp-replace-with-iframe--js').on('click', function(e) {
5559 e.preventDefault();
5560 var url = $(this).prop('href');
5561 var iframe = $('<iframe width="356" height="200" allowfullscreen webkitallowfullscreen mozallowfullscreen>').attr('src', url);
5562 iframe.insertAfter($(this));
5563 $(this).remove();
5564 });
5565
5566 });
5567
5568 // For When character set and collate both are unsupported at restoration time and if user change anyone substitution dropdown from both, Other substitution select box value should be change respectively.
5569 jQuery(function($) {
5570 jQuery('#updraft-restore-modal').on('change', '#updraft_restorer_charset', function(e) {
5571 if ($('#updraft_restorer_charset').length && $('#updraft_restorer_collate').length && $('#collate_change_on_charset_selection_data').length) {
5572 var updraft_restorer_charset = $('#updraft_restorer_charset').val();
5573 // For only show collate which are related to charset
5574 $('#updraft_restorer_collate option').show();
5575 $('#updraft_restorer_collate option[data-charset!='+updraft_restorer_charset+']').hide();
5576 updraft_send_command('collate_change_on_charset_selection', {
5577 collate_change_on_charset_selection_data: $('#collate_change_on_charset_selection_data').val(),
5578 updraft_restorer_charset: updraft_restorer_charset,
5579 updraft_restorer_collate: $('#updraft_restorer_collate').val(),
5580 }, function(response) {
5581 if (response.hasOwnProperty('is_action_required') && 1 == response.is_action_required && response.hasOwnProperty('similar_type_collate')) {
5582 $('#updraft_restorer_collate').val(response.similar_type_collate);
5583 }
5584 });
5585 }
5586 });
5587
5588 jQuery('#updraft-restore-modal').on('click', '#updraftplus_restore_tables_showmoreoptions', function(e) {
5589 e.preventDefault();
5590 jQuery('.updraftplus_restore_tables_options_container').toggle();
5591 });
5592
5593 jQuery('#updraft-restore-modal').on('click', '#updraftplus_restore_plugins_showmoreoptions', function(e) {
5594 e.preventDefault();
5595 jQuery('.updraftplus_restore_plugins_options_container').toggle();
5596 });
5597
5598 jQuery('#updraft-restore-modal').on('click', '#updraftplus_restore_themes_showmoreoptions', function(e) {
5599 e.preventDefault();
5600 jQuery('.updraftplus_restore_themes_options_container').toggle();
5601 });
5602
5603 jQuery('#updraft-restore-modal').on('click', '.updraft-select-all-tables', function(e) {
5604 e.preventDefault();
5605 jQuery('.updraft_restore_tables_options:not(:disabled)').prop('checked', true);
5606 });
5607
5608 jQuery('#updraft-restore-modal').on('click', '.updraft-deselect-all-tables', function(e) {
5609 e.preventDefault();
5610 jQuery('.updraft_restore_tables_options:not(:disabled)').prop('checked', false);
5611 });
5612
5613 var last_checked = null;
5614
5615 jQuery('#updraft-restore-modal').on('click', '.updraft_restore_tables_options', function(e) {
5616 if (!last_checked) {
5617 last_checked = this;
5618 return;
5619 }
5620
5621 if (e.shiftKey) {
5622 var start = jQuery('.updraft_restore_tables_options').index(this);
5623 var end = jQuery('.updraft_restore_tables_options').index(last_checked);
5624
5625 jQuery('.updraft_restore_tables_options').slice(Math.min(start, end), Math.max(start, end)+1).prop('checked', last_checked.checked);
5626
5627 }
5628
5629 last_checked = this;
5630 });
5631
5632 /**
5633 * Sends request to generate a key to be used between UpdraftPlus
5634 * and UpdraftCentral communication
5635 *
5636 * @param {string} keysize - The size of the encryption key to use
5637 * @param {string} firewalled - Indicates whether the target website is protected by some security protocol
5638 * @param {function} callback - The function to execute on successful key creation
5639 * @param {object} modal - jQuery object representing the current modal element
5640 *
5641 * @returns {void}
5642 */
5643 function updraftcentral_cloud_create_updraft_key(keysize, firewalled, callback, modal) {
5644 if ('function' !== typeof callback) return;
5645
5646 // Check for an already created key to avoid generating
5647 // the key more than once for the current session
5648 var form = $(modal).find('#updraftcentral_cloud_form');
5649 var key = form.find('.form_hidden_fields input[name="key"]');
5650 if (key.length) {
5651 if ('' !== key.val()) {
5652 callback.apply(this, [key.val()]);
5653 return;
5654 }
5655 }
5656
5657 var data = {
5658 where_send: '__updraftpluscom',
5659 key_description: '',
5660 key_size: keysize,
5661 mothership_firewalled: firewalled
5662 };
5663
5664 updraftcentral_cloud_show_spinner(modal);
5665 updraft_send_command('updraftcentral_create_key', data, function(response) {
5666 updraftcentral_cloud_hide_spinner(modal);
5667
5668 try {
5669 data = ud_parse_json(response);
5670 if (data.hasOwnProperty('error')) {
5671 console.log(data);
5672 return;
5673 }
5674
5675 if (data.hasOwnProperty('bundle')) {
5676 callback.apply(this, [data.bundle]);
5677 } else {
5678 if (data.hasOwnProperty('r')) {
5679 $(modal).find('.updraftcentral_cloud_notices').html(updraftlion.trouble_connecting).addClass('updraftcentral_cloud_info');
5680 alert(data.r);
5681 } else {
5682 console.log(data);
5683 }
5684 }
5685 } catch (err) {
5686 console.log(err);
5687 }
5688 }, { json_parse: false });
5689 }
5690
5691 /**
5692 * Shows the spinner to indicate that a process is currently on-going
5693 *
5694 * @param {object} modal - jQuery object representing the current modal element
5695 *
5696 * @returns {void}
5697 */
5698 function updraftcentral_cloud_show_spinner(modal) {
5699 $(modal).find('.updraftplus_spinner.spinner').addClass('visible');
5700 }
5701
5702 /**
5703 * Hides the spinner to indicate that a process has completed its job
5704 *
5705 * @param {object} modal - jQuery object representing the current modal element
5706 *
5707 * @returns {void}
5708 */
5709 function updraftcentral_cloud_hide_spinner(modal) {
5710 $(modal).find('.updraftplus_spinner.spinner').removeClass('visible');
5711 }
5712
5713 /**
5714 * Sends request to the server to register a new user
5715 *
5716 * @param {array} data - The form data that will be submitted to the server
5717 * @param {object} modal - jQuery object representing the current modal element
5718 *
5719 * @returns {void}
5720 */
5721 function updraftcentral_cloud_process_registration(data, modal) {
5722 updraftcentral_cloud_show_spinner(modal);
5723 updraft_send_command('process_updraftcentral_registration', data, function(response) {
5724 updraftcentral_cloud_hide_spinner(modal);
5725
5726 try {
5727 data = ud_parse_json(response);
5728 if (data.hasOwnProperty('error')) {
5729 var message = data.message;
5730 var existing_email_errors = ['existing_user_email', 'email_exists'];
5731
5732 if (-1 !== $.inArray(data.code, existing_email_errors)) message = data.message+' '+updraftlion.perhaps_login;
5733
5734 $(modal).find('.updraftcentral_cloud_notices').html(message).addClass('updraftcentral_cloud_error');
5735 $(modal).find('.updraftcentral_cloud_notices a').attr('target', '_blank');
5736 console.log(data);
5737 return;
5738 }
5739
5740 if ('registered' === data.status) {
5741 $(modal).find('.updraftcentral_cloud_form_container').hide();
5742 $(modal).find('.updraftcentral-subheading').hide();
5743 $(modal).find('.updraftcentral_cloud_notices').removeClass('updraftcentral_cloud_error');
5744
5745 updraftcentral_cloud_process_response(modal, data, updraftlion.registration_successful);
5746 }
5747 } catch (err) {
5748 console.log(err);
5749 }
5750 }, { json_parse: false });
5751 }
5752
5753 /**
5754 * Sends request to the server to login an existing user
5755 *
5756 * @param {array} form_data - The form data that will be submitted to the server
5757 * @param {object} modal - jQuery object representing the current modal element
5758 *
5759 * @returns {void}
5760 */
5761 function updraftcentral_cloud_process_login(form_data, modal) {
5762 updraftcentral_cloud_show_spinner(modal);
5763 updraft_send_command('process_updraftcentral_login', form_data, function(response) {
5764 updraftcentral_cloud_hide_spinner(modal);
5765
5766 try {
5767 data = ud_parse_json(response);
5768 if (data.hasOwnProperty('error')) {
5769 if ('incorrect_password' === data.code) {
5770 $(modal).find('.updraftcentral_cloud_form_container .tfa_fields').hide();
5771 $(modal).find('.updraftcentral_cloud_form_container .non_tfa_fields').show();
5772 $(modal).find('input#two_factor_code').val('');
5773 $(modal).find('input#password').val('').trigger('focus');
5774 }
5775
5776 if ('email_not_registered' === data.code) {
5777 // Account does not exists then we will execute a registration process instead
5778 updraftcentral_cloud_process_registration(form_data, modal);
5779 } else {
5780 $(modal).find('.updraftcentral_cloud_notices').html(data.message).addClass('updraftcentral_cloud_error');
5781 $(modal).find('.updraftcentral_cloud_notices a').attr('target', '_blank');
5782 console.log(data);
5783 return;
5784 }
5785 }
5786
5787 if (data.hasOwnProperty('tfa_enabled') && true == data.tfa_enabled) {
5788 $(modal).find('.updraftcentral_cloud_notices').html('').removeClass('updraftcentral_cloud_error');
5789 $(modal).find('.updraftcentral_cloud_form_container .non_tfa_fields').hide();
5790 $(modal).find('.updraftcentral_cloud_form_container .tfa_fields').show();
5791
5792 $(modal).find('input#two_factor_code').trigger('focus');
5793 }
5794
5795 if ('authenticated' === data.status) {
5796 $(modal).find('.updraftcentral_cloud_form_container').hide();
5797 $(modal).find('.updraftcentral_cloud_notices').removeClass('updraftcentral_cloud_error');
5798
5799 updraftcentral_cloud_process_response(modal, data, updraftlion.login_successful);
5800 }
5801 } catch (err) {
5802 console.log(err);
5803 }
5804 }, { json_parse: false });
5805 }
5806
5807 /**
5808 * Updates the redirect form with the needed details to redirect
5809 * to UpdraftCentral Cloud
5810 *
5811 * @param {object} modal - jQuery object representing the current modal element
5812 * @param {array} data - The response data that was received from the UpdraftCentral Cloud
5813 * @param {string} message - A success string/message to show to the user before redirecting
5814 *
5815 * @returns {void}
5816 */
5817 function updraftcentral_cloud_process_response(modal, data, message) {
5818 var form = $(modal).find('form#updraftcentral_cloud_redirect_form');
5819 form.attr('action', data.redirect_url);
5820 form.attr('target', '_blank');
5821
5822 if ('undefined' !== typeof data.redirect_token) {
5823 form.append('<input type="hidden" name="redirect_token" value="'+data.redirect_token+'">');
5824 }
5825
5826 // Success, so we're updating the keys in advanced tools->updraftcentral area
5827 if (data.hasOwnProperty('keys_table') && data.keys_table) {
5828 $('#updraftcentral_keys_content').html(data.keys_table);
5829 }
5830
5831 // Remove the option in the Extensions tab
5832 $('.updraftplus-addons-connect-to-udc').remove();
5833
5834 $redirect_lnk = '<a href="'+updraftlion.current_clean_url+'" class="updraftcentral_cloud_redirect_link">'+updraftlion.updraftcentral_cloud+'</a>';
5835 $close_lnk = '<a href="'+updraftlion.current_clean_url+'" class="updraftcentral_cloud_close_link">'+updraftlion.close_wizard+'</a>';
5836 $(modal).find('.updraftcentral_cloud_notices').html(message.replace('%s', $redirect_lnk)+' '+$close_lnk+'<br/><br/>'+updraftlion.control_udc_connections);
5837
5838 $(modal).find('.updraftcentral_cloud_notices .updraftcentral_cloud_redirect_link').off('click').on('click', function(e) {
5839 e.preventDefault();
5840
5841 form.trigger('submit');
5842 $(modal).find('.updraftcentral_cloud_notices .updraftcentral_cloud_close_link').trigger('click');
5843 });
5844
5845 $(modal).find('.updraftcentral_cloud_notices .updraftcentral_cloud_close_link').off('click').on('click', function(e) {
5846 e.preventDefault();
5847
5848 $(modal).dialog('close');
5849 $('#updraftcentral_cloud_connect_container').hide();
5850 });
5851 }
5852
5853 /**
5854 * Checks and validates submitted data before sending to the server
5855 *
5856 * @param {object} modal - jQuery object representing the current modal element
5857 *
5858 * @returns {boolean}
5859 */
5860 function updraftcentral_cloud_pre_validate_input(modal) {
5861 var form = $(modal).find('#updraftcentral_cloud_form');
5862 var email = form.find('input#email').val();
5863 var password = form.find('input#password').val();
5864 var email_format = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,})+$/;
5865
5866 $(modal).find('.updraftcentral_cloud_notices').html('').removeClass('updraftcentral_cloud_error updraftcentral_cloud_info');
5867
5868 // Check whether the data consent was checked, if not, then we display
5869 // some error requiring the user to tick it before proceeding.
5870 var is_checked = form.find('.updraftcentral-data-consent > input[name="i_consent"]').is(':checked');
5871 if (!is_checked) {
5872 $(modal).find('.updraftcentral_cloud_notices').html(updraftlion.data_consent_required).addClass('updraftcentral_cloud_error');
5873 return false;
5874 }
5875
5876 if (0 === email.length || 0 === password.length) {
5877 $(modal).find('.updraftcentral_cloud_notices').html(updraftlion.username_password_required).addClass('updraftcentral_cloud_error');
5878 return false;
5879 }
5880
5881 if (null === email.match(email_format)) {
5882 $(modal).find('.updraftcentral_cloud_notices').html(updraftlion.valid_email_required).addClass('updraftcentral_cloud_error');
5883 return false;
5884 }
5885
5886 return true;
5887 }
5888
5889 /**
5890 * Prepares the data and executes the appropriate request based
5891 * on the currently requested process (login or register)
5892 *
5893 * @param {object} modal - jQuery object representing the current modal element
5894 * @param {boolean} is_register - Indicates whether the current request is for registration
5895 *
5896 * @returns {void}
5897 */
5898 function updraftcentral_cloud_prepare_data_and_send(modal, is_register) {
5899 var keysize = $(modal).find('#updraft_central_keysize').val();
5900 var firewalled = $(modal).find('#updraft_central_firewalled').is(':checked') ? 1 : 0;
5901
5902 updraftcentral_cloud_create_updraft_key(keysize, firewalled, function(key) {
5903 var form = $(modal).find('#updraftcentral_cloud_form');
5904 var field = form.find('.form_hidden_fields input[name="key"]');
5905 if (0 === field.length) {
5906 form.find('.form_hidden_fields').append('<input type="hidden" name="key" value="'+key+'">');
5907 }
5908
5909 var form_data = form.find('input').serialize();
5910 var data = {
5911 form_data: form_data
5912 }
5913
5914 // Checks whether a login process or registration is to be execute
5915 // for the current call
5916 if ('undefined' !== typeof is_register && is_register) {
5917 updraftcentral_cloud_process_registration(data, modal);
5918 } else {
5919 updraftcentral_cloud_process_login(data, modal);
5920 }
5921 }, modal);
5922 }
5923
5924 /**
5925 * Opens the UpdraftCentral Cloud login modal
5926 *
5927 * @returns {void}
5928 */
5929 function updraftcentral_cloud_login_modal() {
5930 var form_template = $('#updraftcentral_cloud_login_form');
5931 if (form_template.length) {
5932
5933 updraft_html_modal(form_template.html(), updraftlion.updraftcentral_cloud, 520, 400);
5934
5935 var modal = jQuery('#updraft-iframe-modal');
5936 var consent_container = modal.find('.updraftcentral-data-consent');
5937 var name = consent_container.find('input').attr('name');
5938
5939 if ('undefined' !== typeof name && name) {
5940 consent_container.find('input').attr('id', name);
5941 consent_container.find('label').attr('for', name);
5942 }
5943 }
5944 }
5945
5946 // Handles the click event of the "Connect this site to an UpdraftCentral Cloud" button
5947 $('#updraft-wrap #btn_cloud_connect').on('click', function() {
5948 updraftcentral_cloud_login_modal();
5949 });
5950
5951 // Handles the click event to connect to the Self-Hosted UpdraftCentral
5952 $('#updraft-wrap a#self_hosted_connect').on('click', function(e) {
5953 e.preventDefault();
5954
5955 $('h2.nav-tab-wrapper > a#updraft-navtab-expert').trigger('click');
5956 $('div.advanced_settings_menu > #updraft_central').trigger('click');
5957 });
5958
5959 // Handles the login button - triggered by a click event
5960 $('#updraft-iframe-modal').on('click', '#updraftcentral_cloud_login', function(e) {
5961 e.preventDefault();
5962 var modal = $(this).closest('#updraft-iframe-modal');
5963
5964 if (updraftcentral_cloud_pre_validate_input(modal)) {
5965 updraftcentral_cloud_prepare_data_and_send(modal);
5966 }
5967 });
5968
5969 var heartbeat_last_parameters = {};
5970
5971 $(document).on('heartbeat-send', function(event, heartbeat_data) {
5972 heartbeat_last_parameters = updraft_poll_get_parameters();
5973 heartbeat_data.updraftplus = heartbeat_last_parameters;
5974 });
5975
5976 $(document).on('heartbeat-tick', function(event, heartbeat_data) {
5977 if (null === heartbeat_data || !heartbeat_data.hasOwnProperty('updraftplus') || null == heartbeat_data.updraftplus) return;
5978 var resp = heartbeat_data.updraftplus;
5979 var response_raw = JSON.stringify(resp);
5980 // We do somewhat assume that there can't be overlapping heartbeat calls - they should be far enough apart to make that very unlikely (and even if it happened, it is unlikely to cause any trouble)
5981 updraft_process_status_check(resp, response_raw, heartbeat_last_parameters);
5982 if (!heartbeat_data.updraftplus.hasOwnProperty('time_now')) return;
5983 // Set the 'Time Now' status in the UI to the current time
5984 jQuery('body.settings_page_updraftplus #updraft-navtab-backups-content .updraft_time_now_wrapper .updraft_time_now').empty().html(heartbeat_data.updraftplus.time_now);
5985 });
5986 });
5987
5988 /**
5989 * Process a status check result
5990 *
5991 * @param {Object} resp - the response after being parsed
5992 * @param {String} response_raw - the raw response
5993 * @param {Object} original_parameters - the original parameters used to make the check
5994 *
5995 * @returns {void}
5996 */
5997 function updraft_process_status_check(resp, response_raw, original_parameters) {
5998
5999 if (resp.hasOwnProperty('fatal_error')) {
6000 console.error(resp.fatal_error_message);
6001 if (true === updraftplus_activejobs_list_fatal_error_alert) {
6002 updraftplus_activejobs_list_fatal_error_alert = false;
6003 alert(this.alert_done + ' ' +resp.fatal_error_message);
6004 }
6005 return;
6006 }
6007
6008 try {
6009 if (resp.hasOwnProperty('l')) {
6010 if (resp.l) {
6011 jQuery('#updraft_lastlogmessagerow').show();
6012 jQuery('#updraft_lastlogcontainer').html(resp.l);
6013 } else {
6014 jQuery('#updraft_lastlogmessagerow').hide();
6015 jQuery('#updraft_lastlogcontainer').html('('+updraftlion.nothing_yet_logged+')');
6016 }
6017 }
6018
6019 // hosting restrictions
6020 if (updraftlion.hasOwnProperty('hosting_restriction') && updraftlion.hosting_restriction instanceof Array) {
6021 updraftlion.hosting_restriction.length = 0;
6022 if (resp.hasOwnProperty('hosting_restriction')) {
6023 if (resp.hosting_restriction && resp.hosting_restriction.includes('only_one_backup_per_month')) {
6024 updraftlion.hosting_restriction.push('only_one_backup_per_month');
6025 }
6026 if (resp.hosting_restriction && resp.hosting_restriction.includes('only_one_incremental_per_day')) {
6027 updraftlion.hosting_restriction.push('only_one_incremental_per_day');
6028 }
6029 }
6030 }
6031
6032 if (!jQuery('#updraft-wrap #updraft-navtab-settings-content').is(':hidden')) {
6033 // auto-updates synchronised setting
6034 if (resp.hasOwnProperty('automatic_updates')) {
6035 jQuery('input[name="updraft_auto_updates"]').prop('checked', resp.automatic_updates);
6036 }
6037 }
6038
6039 var lastactivity = -1;
6040
6041 // Requested start of backup text
6042 var requeststart_el = jQuery('.updraft_requeststart');
6043 if (resp.j && requeststart_el.length && requeststart_el.data('remove')) {
6044 requeststart_el.remove();
6045 }
6046
6047 // Parse response to add classes before inserting it, to avoid unwanted artifacts
6048 var $list_prepare = jQuery(resp.j);
6049 $list_prepare.find('.updraft_jobtimings').each(function(ind, element) {
6050 var $el = jQuery(element);
6051 if ($el.data('jobid')) {
6052 var jobid = $el.data('jobid');
6053 var job_row = $el.closest('.updraft_row');
6054 if (updraft_aborted_jobs[jobid]) {
6055 job_row.hide();
6056 }
6057 }
6058 });
6059
6060 jQuery('#updraft_activejobsrow').html($list_prepare);
6061
6062 var $clone_jobs = $list_prepare.find('.job-id[data-isclone="1"]');
6063
6064 if ($clone_jobs.length > 0) {
6065 if (jQuery('.updraftclone_action_box .updraftclone_network_info').length == 0 && jQuery('#updraft_activejobsrow .job-id .updraft_clone_url').length > 0) {
6066 var clone_url = jQuery('#updraft_activejobsrow .job-id .updraft_clone_url').data('clone_url');
6067
6068 updraft_send_command('get_clone_network_info', { clone_url: clone_url }, function(response) {
6069 if (response.hasOwnProperty('html')) {
6070 jQuery('.updraftclone_action_box').html(response.html);
6071 }
6072 });
6073 }
6074
6075 jQuery('#updraft_clone_activejobsrow').empty();
6076 $clone_jobs.each(function(ind, element) {
6077 var $el = jQuery(element);
6078 $el.closest('.updraft_row')
6079 // .clone() // Clone allows to have the job on both tabs
6080 .appendTo(jQuery('#updraft_clone_activejobsrow'));
6081 });
6082 }
6083
6084 jQuery('#updraft_activejobs .updraft_jobtimings').each(function(ind, element) {
6085 var $el = jQuery(element);
6086 // lastactivity, nextresumption, nextresumptionafter
6087 if ($el.data('lastactivity') && $el.data('jobid')) {
6088 var jobid = $el.data('jobid');
6089 var new_lastactivity = $el.data('lastactivity');
6090 if (lastactivity == -1 || new_lastactivity < lastactivity) { lastactivity = new_lastactivity; }
6091 var nextresumptionafter = $el.data('nextresumptionafter');
6092 var nextresumption = $el.data('nextresumption');
6093
6094 // Milliseconds
6095 timenow = (new Date).getTime();
6096 if (new_lastactivity > 50 && nextresumption >0 && nextresumptionafter < -30 && timenow > updraft_last_forced_when+100000 && (updraft_last_forced_jobid != jobid || nextresumption != updraft_last_forced_resumption)) {
6097 updraft_last_forced_resumption = nextresumption;
6098 updraft_last_forced_jobid = jobid;
6099 updraft_last_forced_when = timenow;
6100 console.log('UpdraftPlus: force resumption: job_id='+jobid+', resumption='+nextresumption);
6101 updraft_send_command('forcescheduledresumption', {
6102 resumption: nextresumption,
6103 job_id: jobid
6104 }, function(response) {
6105 console.log(response);
6106 }, { json_parse: false, alert_on_error: false });
6107 }
6108 }
6109 });
6110
6111 timenow = (new Date).getTime();
6112 updraft_activejobs_nextupdate = timenow + 180000;
6113 // More rapid updates needed if a) we are on the main console, or b) a downloader is open (which can only happen on the restore console)
6114 if ((updraft_page_is_visible == 1 && 'backups' == updraft_console_focussed_tab)) {
6115 if (lastactivity > -1) {
6116 if (lastactivity < 5) {
6117 updraft_activejobs_nextupdate = timenow + 1750;
6118 } else {
6119 updraft_activejobs_nextupdate = timenow + 5000;
6120 }
6121 } else if (lastlog_lastdata == response_raw) {
6122 updraft_activejobs_nextupdate = timenow + 7500;
6123 } else {
6124 updraft_activejobs_nextupdate = timenow + 1750;
6125 }
6126 }
6127
6128 if ($clone_jobs.length > 0) updraft_activejobs_nextupdate = timenow + 6000;
6129
6130 lastlog_lastdata = response_raw;
6131
6132 if (resp.j != null && resp.j != '') {
6133 jQuery('#updraft_activejobsrow').show();
6134 if ($clone_jobs.length > 0) jQuery('#updraft_clone_activejobsrow').show();
6135
6136 if (original_parameters.hasOwnProperty('thisjobonly') && !updraft_inpage_hasbegun && jQuery('#updraft-jobid-'+original_parameters.thisjobonly).length) {
6137 updraft_inpage_hasbegun = 1;
6138 console.log('UpdraftPlus: the start of the requested backup job has been detected');
6139 } else if (!updraft_inpage_hasbegun && updraft_activejobslist_backupnownonce_only && jQuery('.updraft_jobtimings.isautobackup').length) {
6140 autobackup_nonce = jQuery('.updraft_jobtimings.isautobackup').first().data('jobid');
6141 if (autobackup_nonce) {
6142 updraft_inpage_hasbegun = 1;
6143 updraft_backupnow_nonce = autobackup_nonce;
6144 original_parameters.thisjobonly = autobackup_nonce;
6145 console.log('UpdraftPlus: the start of the requested backup job has been detected; id: '+autobackup_nonce);
6146 }
6147 }
6148
6149 if (updraft_inpage_hasbegun == 1 && jQuery('#updraft-jobid-'+original_parameters.thisjobonly+'.updraft_finished').length) {
6150 // Don't reset to 0 - this will cause the 'began' event to be detected again
6151 updraft_inpage_hasbegun = 2;
6152
6153 console.log('UpdraftPlus: the end of the requested backup job has been detected');
6154 if (updraft_activejobs_update_timer) clearInterval(updraft_activejobs_update_timer);
6155 if (typeof updraft_inpage_success_callback !== 'undefined' && updraft_inpage_success_callback != '') {
6156 // Move on to next page
6157 updraft_inpage_success_callback.call(false);
6158 } else {
6159 jQuery('#updraft-backupnow-inpage-modal').dialog('close');
6160 }
6161 }
6162 if ('' == lastlog_jobs) {
6163 setTimeout(function() {
6164 jQuery('#updraft_backup_started').slideUp();}, 3500);
6165 }
6166
6167 // detect manual backup
6168 if (original_parameters.hasOwnProperty('thisjobonly') && updraft_backupnow_nonce && original_parameters.thisjobonly === updraft_backupnow_nonce) {
6169 jQuery('.updraft_requeststart').remove();
6170
6171 var thisjob = jQuery('#updraft-jobid-'+updraft_backupnow_nonce);
6172 // detect manual backup end
6173 if (thisjob.is('.updraft_finished')) {
6174 // reset current job vars
6175 updraft_activejobslist_backupnownonce_only = 0;
6176 // Aborted jobs
6177 if (updraft_aborted_jobs[updraft_backupnow_nonce]) {
6178 // remove deleted job from deleted jobs list
6179 updraft_aborted_jobs = updraft_aborted_jobs.filter(function(val, index) {
6180 return val != updraft_backupnow_nonce;
6181 });
6182 } else {
6183
6184 if (updraft_active_job_is_clone(updraft_backupnow_nonce)) {
6185 // A clone job is complete
6186 updraft_show_success_modal(updraftlion.clone_backup_complete);
6187 updraft_clone_jobs = updraft_clone_jobs.filter(function(val) {
6188 return val != updraft_backupnow_nonce;
6189 });
6190 } else {
6191 // A normal manual backup is complete
6192 updraft_show_success_modal(updraftlion.backup_complete);
6193 }
6194 }
6195 updraft_backupnow_nonce = '';
6196 // Force fetch active jobs
6197 updraft_activejobs_update(true);
6198
6199 }
6200 }
6201 } else {
6202 if (!jQuery('#updraft_activejobsrow').is(':hidden')) {
6203 // Backup has now apparently finished - hide the row. If using this for detecting a finished job, be aware that it may never have shown in the first place - so you'll need more than this.
6204 if (typeof lastbackup_laststatus != 'undefined') { updraft_showlastbackup(); }
6205 updraft_updatehistory(0, 0);
6206 jQuery('#updraft_activejobsrow').hide();
6207 }
6208 }
6209 lastlog_jobs = resp.j;
6210
6211 // Download status
6212 if (resp.ds != null && resp.ds != '') {
6213 updraft_downloader_status_update(resp.ds, response_raw);
6214 }
6215
6216 if (resp.u != null && resp.u != '' && jQuery("#updraft-poplog").dialog("isOpen")) {
6217 var log_append_array = resp.u;
6218 if (log_append_array.nonce == updraft_poplog_log_nonce) {
6219 updraft_poplog_log_pointer = log_append_array.pointer;
6220 if (log_append_array.log != null && log_append_array.log != '') {
6221 var oldscroll = jQuery('#updraft-poplog').scrollTop();
6222 jQuery('#updraft-poplog-content').append(log_append_array.log);
6223 if (updraft_poplog_lastscroll == oldscroll || updraft_poplog_lastscroll == -1) {
6224 jQuery('#updraft-poplog').scrollTop(jQuery('#updraft-poplog-content').prop("scrollHeight"));
6225 updraft_poplog_lastscroll = jQuery('#updraft-poplog').scrollTop();
6226 }
6227 }
6228 }
6229 }
6230 } catch (err) {
6231 console.log(updraftlion.unexpectedresponse+' '+response_raw);
6232 console.log(err);
6233 }
6234 }
6235
6236 /**
6237 * Creates an instance of the updraft_js_tree class.
6238 *
6239 * @constructor
6240 * @param {string} remote_storage - The remote storage identifier.
6241 */
6242 function updraft_js_tree(remote_storage) {
6243
6244 var self = this; // Store a reference to the object
6245 self.remote_storage = remote_storage;
6246
6247 /**
6248 * Hides the jstree and related elements.
6249 *
6250 * @param {jQuery} parent - The parent element containing the jstree.
6251 */
6252 this.hide_jstree = function(parent) {
6253 parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').removeAttr('readonly');
6254
6255 parent.find('.updraft_' + self.remote_storage + '_select_folder').show();
6256 parent.find('.updraft_' + self.remote_storage + '_container').hide();
6257
6258 // hide action buttons
6259 parent.find('.updraft_jstree_cancel').hide();
6260 parent.find('.updraft_jstree_confirm').hide();
6261 };
6262
6263 /**
6264 * Gets the structured folder path based on the selected node in the jstree.
6265 *
6266 * @param {Object} selected_node - The selected node in the jstree.
6267 * @returns {string} The structured folder path.
6268 */
6269 this.get_structured_folder = function(selected_node) {
6270 var level = selected_node.node.parents.length;
6271 var selected_id = selected_node.node.id;
6272 var parent = jQuery("#" + selected_id);
6273 var parents = selected_node.node.text + '/';
6274
6275 for (var ln = 0; ln <= level -1; ln++) {
6276 var parent = parent.parent().parent();
6277 if (parent.children()[1] != undefined) {
6278 parents = parent.children()[1].text + '/' + parents;
6279 }
6280 }
6281 if (parents.length > 0) {
6282 parents = parents.substring(0, parents.length - 1);
6283 }
6284
6285 return parents;
6286 };
6287
6288 /**
6289 * Lists folders from the remote storage and initializes the jstree.
6290 *
6291 * @param {string} entity - The entity type.
6292 * @param {jQuery} parent - The parent element where the jstree will be displayed.
6293 * @param {string} instance_id - The instance identifier.
6294 */
6295 this.list_folders = function(entity, parent, instance_id) {
6296 parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').prop('readOnly', true);
6297 parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').attr('previous-value', parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').val());
6298
6299 parent.find('.updraft_' + self.remote_storage + '_select_folder').hide();
6300 parent.find('.updraft_' + self.remote_storage + '_container').show();
6301
6302 // show action buttons
6303 parent.find('.updraft_jstree_cancel').show();
6304 parent.find('.updraft_jstree_confirm').show();
6305
6306 // init jstree
6307 parent.find('.updraft_' + self.remote_storage + '_jstree_container').jstree({
6308 "core": {
6309 "multiple": false,
6310 "data": function (nodeid, callback) {
6311 updraft_send_command('get_jstree_directory_nodes', {entity:entity, node:nodeid, instance_id:instance_id}, function(response) {
6312 if (response.hasOwnProperty('error')) {
6313 jQuery('.updraft_include_' + self.remote_storage + '_paths_error').text(response.error);
6314 } else {
6315 jQuery('.updraft_include_' + self.remote_storage + '_paths_error').text('');
6316 callback.call(this, response.nodes);
6317 }
6318 });
6319 }
6320 },
6321 'plugins' : ['sort','types'],
6322 'sort' : function(a, b) {
6323 a1 = this.get_node(a);
6324 b1 = this.get_node(b);
6325 if (a1.icon == b1.icon) {
6326 return (a1.text > b1.text) ? 1 : -1;
6327 } else {
6328 return (a1.icon < b1.icon) ? 1 : -1;
6329 }
6330 },
6331 });
6332
6333 // Detect change on the tree and update the input that has been marked as editing
6334 parent.find('.updraft_' + self.remote_storage + '_jstree_container').on("changed.jstree", function (e, data) {
6335 parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').val(self.get_structured_folder(data));
6336 });
6337
6338 parent.find('.updraft_' + self.remote_storage + '_jstree_confirm, .updraft_' + self.remote_storage + '_jstree_cancel').on('click', function(e) {
6339 e.preventDefault();
6340
6341 if (jQuery(this).hasClass('updraft_' + self.remote_storage + '_jstree_cancel')) {
6342 parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').val(parent.find('[id^="updraft_' + self.remote_storage + '_folder"]').attr('previous-value'));
6343 }
6344
6345 self.hide_jstree(parent);
6346 });
6347 };
6348
6349 /**
6350 * Initializes the updraft_js_tree instance by setting up event handlers.
6351 */
6352 this.init = function() {
6353 jQuery(function() {
6354 jQuery('.updraft_' + self.remote_storage + '_select_folder').on('click', function(e) {
6355 e.preventDefault();
6356 var $parent = jQuery(this).closest('tr');
6357 var instance_id = $parent.find('[id^="updraft_' + self.remote_storage + '_folder_"]').attr('id').replace('updraft_' + self.remote_storage + '_folder_', '');
6358 self.list_folders(self.remote_storage, $parent, instance_id);
6359 });
6360 });
6361 };
6362
6363 }
6364
6365 /**
6366 * Initializes Select2 dynamic input for all <select> elements matching the given object of remote storage.
6367 *
6368 * @param {string} remote_storage_elements - An object of HTML elements of the remote storage template
6369 * @returns {void}
6370 */
6371 function initialize_remote_storage_select2_elements(remote_storage_elements) {
6372 // <select> tag added to any remote storage configuration should have `select2` defined in its class attribute
6373 var select_element = jQuery(remote_storage_elements).find('select.select2-storage-config');
6374 for (var i=0; i < select_element.length; i++) {
6375 // Initialize select2 text input.
6376 jQuery(select_element[i]).select2({
6377 tags: true
6378 });
6379 // any specific actions applied to remote storage should be implemented by first checking the remote storage ID
6380 if ('dreamobjects' === jQuery(select_element[i]).data('storage-id')) {
6381 if ('endpoint' === jQuery(select_element[i]).data('field-id')) {
6382 jQuery(select_element[i]).on('change', function(e) {
6383 validate_dreamobjects_endpoint(e.target);
6384 });
6385 validate_dreamobjects_endpoint(select_element[i]);
6386 }
6387 }
6388 }
6389 }
6390
6391 /**
6392 * Validate selected DreamObjects endpoint.
6393 *
6394 * @param {HTMLSelectElement} select_element - The <select> element for DreamObjects endpoint.
6395 *
6396 * @returns {void}
6397 */
6398 function validate_dreamobjects_endpoint(select_element) {
6399 var endpoint = select_element.value.trim();
6400 // Show or hide error message depending on endpoint validity.
6401 if (updraftlion.dreamobject_endpoints.includes(endpoint) || new RegExp(updraftlion.dreamobject_endpoint_regex, 'i').test(endpoint)) {
6402 select_element.classList.remove('updraft-input--invalid');
6403 } else {
6404 select_element.classList.add('updraft-input--invalid');
6405 }
6406 }
6407
6408 /**
6409 * Reference to the authentication popup window.
6410 *
6411 * @type {Window|null}
6412 */
6413 var updraft_popup_ref = null;
6414
6415 /**
6416 * Interval ID used to check if the popup window has been closed.
6417 *
6418 * @type {number|null}
6419 */
6420 var updraft_popup_check_interval = null;
6421
6422 /**
6423 * Opens (or focuses) an authentication popup window and monitors when it closes.
6424 *
6425 * When the popup is closed, a `CustomEvent` named `updraftAuthPopupClosed` is dispatched
6426 * on the `window` object, containing the opened URL in the event detail.
6427 *
6428 * @param {string} url - The URL to open in the popup window.
6429 * @fires window#updraftAuthPopupClosed
6430 */
6431 function updraft_open_authentication_popup(url) {
6432 const width = 1000;
6433 const height = 800;
6434 const left = (window.screen.width / 2) - (width / 2);
6435 const top = (window.screen.height / 2) - (height / 2);
6436
6437 // Open (or focus existing) popup
6438 if (!updraft_popup_ref || updraft_popup_ref.closed) {
6439 updraft_popup_ref = window.open(
6440 url,
6441 'updraft_auth_popup',
6442 'width=' + width + ',height=' + height + ',top=' + top + ',left=' + left + ',scrollbars=yes,resizable=yes'
6443 );
6444 } else {
6445 updraft_popup_ref.focus();
6446 }
6447
6448 // Clear any previous interval
6449 if (updraft_popup_check_interval) clearInterval(updraft_popup_check_interval);
6450
6451 // Check every 500ms if popup closed
6452 updraft_popup_check_interval = setInterval(function() {
6453 if (!updraft_popup_ref || updraft_popup_ref.closed) {
6454 clearInterval(updraft_popup_check_interval);
6455 updraft_popup_check_interval = null;
6456
6457 /**
6458 * Fired when the authentication popup window is closed.
6459 *
6460 * @event window#updraftAuthPopupClosed
6461 * @type {CustomEvent}
6462 * @property {Object} detail - Additional event details.
6463 * @property {string} detail.url - The URL that was opened in the popup.
6464 */
6465 window.dispatchEvent(new CustomEvent('updraftAuthPopupClosed', {
6466 detail: { url: url }
6467 }));
6468 }
6469 }, 500);
6470 }
6471
6472 window.addEventListener('message', function (event) {
6473 if (!event.data || event.data.type !== 'auth_success' || jQuery('#teamupdraft-onboarding').length === 1) {
6474 return;
6475 }
6476
6477 window.location.reload();
6478 });
6479
6480 /**
6481 * Handles click events on authentication and deauthentication links.
6482 * Prevents default navigation and opens the popup using {@link updraft_open_authentication_popup}.
6483 *
6484 * @param {MouseEvent} e - The click event.
6485 * @returns {boolean|void} Returns false if the click should not open a popup.
6486 */
6487 jQuery(document).on('click', 'a.updraft_authlink', function(e, data) {
6488 e.preventDefault();
6489
6490 // Prevent middle-click or Ctrl/Cmd + click from opening new tab
6491 if (e.button === 1 || e.ctrlKey || e.metaKey) {
6492 return false;
6493 }
6494
6495 if (!data) data = {};
6496
6497 if (data && data.is_requesting_popup_auth) {
6498 updraft_open_authentication_popup(this.href);
6499 } else {
6500 window.location.href = this.href;
6501 }
6502 });
6503