From 69611520c35aa5a555318baed2a7d0d5cf3ba6f2 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 10 Oct 2019 01:56:38 +0900 Subject: [PATCH 1/5] Support submitting arbitrary forms by AJAX or IFRAME --- classes/context/Context.class.php | 1 + classes/module/ModuleHandler.class.php | 18 ++++++++ common/js/xml_handler.js | 58 ++++++++++++++++++++------ 3 files changed, 65 insertions(+), 12 deletions(-) diff --git a/classes/context/Context.class.php b/classes/context/Context.class.php index 7377cecf1..dc7c8f5a9 100644 --- a/classes/context/Context.class.php +++ b/classes/context/Context.class.php @@ -166,6 +166,7 @@ class Context private static $_reserved_keys = array( '_rx_ajax_compat' => true, '_rx_csrf_token' => true, + '_rx_target_iframe' => true, ); /** diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index c32074e32..a41c94e36 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -940,6 +940,24 @@ class ModuleHandler extends Handler $methodList = array('XMLRPC' => 1, 'JSON' => 1, 'JS_CALLBACK' => 1); if(!isset($methodList[Context::getRequestMethod()])) { + // Handle iframe form submissions. + if(isset($_POST['_rx_target_iframe']) && starts_with('_rx_temp_', $_POST['_rx_target_iframe'])) + { + if($this->error) + { + ob_end_clean(); + echo sprintf('', json_encode($this->error), json_encode($_POST['_rx_target_iframe'])); + return; + } + elseif($_SESSION['XE_VALIDATOR_RETURN_URL']) + { + ob_end_clean(); + echo sprintf('', json_encode($_SESSION['XE_VALIDATOR_RETURN_URL'])); + return; + } + } + + // Handle redirects. if($_SESSION['XE_VALIDATOR_RETURN_URL']) { if ($_SESSION['is_new_session']) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index b5780e8b3..481dba265 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -190,16 +190,18 @@ window.exec_json = $.exec_json = function(action, params, callback_success, callback_error) { // Convert params to object and fill in the module and act. - params = params ? ($.isArray(params) ? arr2obj(params) : params) : {}; - action = action.split("."); - //if (action.length != 2) return; - params.module = action[0]; - params.act = action[1]; - params._rx_ajax_compat = 'JSON'; - params._rx_csrf_token = getCSRFToken(); - - // Fill in the XE vid. - if (typeof(xeVid) != "undefined") params.vid = xeVid; + if (action === 'raw') { + var request_info = 'RAW FORM SUBMISSION'; + } else { + params = params ? ($.isArray(params) ? arr2obj(params) : params) : {}; + action = action.split("."); + //if (action.length != 2) return; + params.module = action[0]; + params.act = action[1]; + params._rx_ajax_compat = 'JSON'; + params._rx_csrf_token = getCSRFToken(); + var request_info = params.module + "." + params.act; + } // Delay the waiting message for 1 second to prevent rapid blinking. waiting_obj.css("opacity", 0.0); @@ -218,7 +220,7 @@ // Add debug information. if (data._rx_debug) { - data._rx_debug.page_title = "AJAX : " + params.module + "." + params.act; + data._rx_debug.page_title = "AJAX : " + request_info; if (window.rhymix_debug_add_data) { window.rhymix_debug_add_data(data._rx_debug); } else { @@ -238,7 +240,7 @@ if (data.message) { alert(data.message.replace(/\\n/g, "\n")); } else { - alert("AJAX communication error while requesting " + data.module + "." + data.act); + alert("AJAX communication error while requesting " + request_info); } if ($.isFunction(callback_error)) { callback_error(data); @@ -283,6 +285,7 @@ dataType: "json", url: request_uri, data: params, + processData: (action !== 'raw'), success : successHandler, error : errorHandler }); @@ -356,6 +359,37 @@ } }; + /** + * Function for AJAX submission of arbitrary forms. + */ + $(document).on('submit', 'form.rx_ajax', function(event) { + // Abort if the form already has a 'target' attribute. + var form = $(this); + if (form.attr('target')) { + return; + } + event.preventDefault(); + // If the form has file uploads, use a hidden iframe to submit. Otherwise use exec_json. + var has_files = form.find('input[type=file][name!=Filedata]').size(); + if (has_files) { + var iframe_id = '_rx_temp_' + (new Date()).getTime(); + $('').appendTo($(document.body)); + form.attr('target', iframe_id).find('input[name=_rx_target_iframe]').remove(); + form.append(''); + window.remove_iframe = function(iframe_id) { + if (iframe_id.match(/^_rx_temp_[0-9]+$/)) { + $('iframe#' + iframe_id).remove(); + } + }; + setTimeout(function() { + form.removeAttr('target').find('input[name=_rx_target_iframe]').remove(); + }, 1000); + form.submit(); + } else { + window.exec_json('raw', form.serialize()); + } + }); + /** * Empty placeholder for beforeUnload handler. */ From 4e6607c1c3ee173fd675e6cbca2ae0c3eecf6515 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 10 Oct 2019 02:27:11 +0900 Subject: [PATCH 2/5] Automatically add method=POST and enctype=multipart/form-data to iframe submissions --- common/js/xml_handler.js | 1 + 1 file changed, 1 insertion(+) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 481dba265..fd05d9f64 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -374,6 +374,7 @@ if (has_files) { var iframe_id = '_rx_temp_' + (new Date()).getTime(); $('').appendTo($(document.body)); + form.attr('method', 'POST').attr('enctype', 'multipart/form-data'); form.attr('target', iframe_id).find('input[name=_rx_target_iframe]').remove(); form.append(''); window.remove_iframe = function(iframe_id) { From 2385a62b95d561101e875cee92437d04f54ba693 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 10 Oct 2019 02:28:18 +0900 Subject: [PATCH 3/5] Fix duplicate definition of request_info --- common/js/xml_handler.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index fd05d9f64..4a2eb802c 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -190,8 +190,9 @@ window.exec_json = $.exec_json = function(action, params, callback_success, callback_error) { // Convert params to object and fill in the module and act. + var request_info; if (action === 'raw') { - var request_info = 'RAW FORM SUBMISSION'; + request_info = 'RAW FORM SUBMISSION'; } else { params = params ? ($.isArray(params) ? arr2obj(params) : params) : {}; action = action.split("."); @@ -200,7 +201,7 @@ params.act = action[1]; params._rx_ajax_compat = 'JSON'; params._rx_csrf_token = getCSRFToken(); - var request_info = params.module + "." + params.act; + request_info = params.module + "." + params.act; } // Delay the waiting message for 1 second to prevent rapid blinking. From 0f6c1edc68f860e74bcfdd911a4553f93c5e72f0 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 10 Oct 2019 02:36:03 +0900 Subject: [PATCH 4/5] Support success and error callbacks in rx_ajax forms --- common/js/xml_handler.js | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/common/js/xml_handler.js b/common/js/xml_handler.js index 4a2eb802c..eb6d531bd 100644 --- a/common/js/xml_handler.js +++ b/common/js/xml_handler.js @@ -369,7 +369,21 @@ if (form.attr('target')) { return; } + // Prevent page refresh. event.preventDefault(); + // Get success and error callback functions. + var callback_success = form.data('callback-success'); + if (callback_success && window[callback_success] && $.isFunction(window[callback_success])) { + callback_success = window[callback_success]; + } else { + callback_success = null; + } + var callback_error = form.data('callback-error'); + if (callback_error && window[callback_error] && $.isFunction(window[callback_error])) { + callback_error = window[callback_error]; + } else { + callback_error = null; + } // If the form has file uploads, use a hidden iframe to submit. Otherwise use exec_json. var has_files = form.find('input[type=file][name!=Filedata]').size(); if (has_files) { @@ -388,7 +402,7 @@ }, 1000); form.submit(); } else { - window.exec_json('raw', form.serialize()); + window.exec_json('raw', form.serialize(), callback_success, callback_error); } }); From 9c10fa56bb462ec702d603afaf4245375be75e39 Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Thu, 10 Oct 2019 15:08:40 +0900 Subject: [PATCH 5/5] Change order of redirect and error message --- classes/module/ModuleHandler.class.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/classes/module/ModuleHandler.class.php b/classes/module/ModuleHandler.class.php index a41c94e36..ab7f0c1c4 100644 --- a/classes/module/ModuleHandler.class.php +++ b/classes/module/ModuleHandler.class.php @@ -943,18 +943,18 @@ class ModuleHandler extends Handler // Handle iframe form submissions. if(isset($_POST['_rx_target_iframe']) && starts_with('_rx_temp_', $_POST['_rx_target_iframe'])) { + if($_SESSION['XE_VALIDATOR_RETURN_URL']) + { + ob_end_clean(); + echo sprintf('', json_encode($_SESSION['XE_VALIDATOR_RETURN_URL'])); + return; + } if($this->error) { ob_end_clean(); echo sprintf('', json_encode($this->error), json_encode($_POST['_rx_target_iframe'])); return; } - elseif($_SESSION['XE_VALIDATOR_RETURN_URL']) - { - ob_end_clean(); - echo sprintf('', json_encode($_SESSION['XE_VALIDATOR_RETURN_URL'])); - return; - } } // Handle redirects.