I have the following downloadZip.html. The download works in Chrome and Edge, but not in IE. This file gets called as below from jspf page. When I click "Download listed documents" it call popupDownloadWindow(), which will open downloadZip.html in plainview. This html when loaded calls enableLink() and the flow goes. As the view is plainview, only first if block of enableLink() is executed (if(callerview == "plainview")). Not sure if this is happening because of setTimeout(). Please help me here. Let me know for any information.
function checkReturn(){
//alert('checkReturn - sessionsNotOk global var = '+sessionsNotOk);
if (sessionsNotOk != "DEF") {
var docbases = sessionsNotOk.split(",");
//alert('checkReturn - docbases arr = '+docbases+', length='+docbases.length);
if (docbases.length == 1 && docbases[0] == "OK"){
// All sessions are faja
document.getElementById('divIndicator').style.display='none';
document.getElementById('checkSession').style.display='none';
document.getElementById('noSession').style.display='none';
document.getElementById('dlink').style.display='inline';
document.getElementById('dlink').style.textAlign='center';
document.getElementById('dlink').style.display='';
} else {
// We need to show the sublogin dialog
var nextDocbase = docbases[0];
//alert("Next NOT AVAILABLE session = "+nextDocbase);
window.opener.$('#subloginmessage').css('display','none');
window.opener.$('#loginIndicator').css('display','none');
window.opener.$('#sub-uid').val(window.opener.$('#user_name').text());
window.opener.$('#sub-uid').attr('disabled','disabled');
window.opener.$('#sub_docbase').text(nextDocbase);
document.getElementById('checkSession').style.display='none';
document.getElementById('noSession').style.display='inline';
document.getElementById('noSession').style.textAlign='center';
document.getElementById('noSession').style.display='';
window.opener.sublogin_fw = "download";
window.opener.sublogin_db = nextDocbase;
window.opener.$('#sublogindialog').dialog('open');
window.opener.$('#sublogindialog').dialog('option','title','Login to docbase: ' + nextDocbase + ' and click on Download listed documents link again!');
}
return;
}
//Check again in 0.5 second
setTimeout("checkReturn()",500);
//setTimeout(function() {
// checkReturn();
//}, 500);
}
Complete code:
<script>
var downloadZipChildWindow;
function popupDownloadWindow(){
downloadZipChildWindow = window.open('../html/downloadZip.html?view=plainview','downloadwindow','width=300,height=200,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,copyhistory=no,resizable=no');
}
</script>
<a id='download_link' class='download_link' href="#" onClick="popupDownloadWindow()">Download listed documents</a>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Download documents as Zip file</title>
<script type="text/javascript" src="../js/jquery-1.6.1.min.js" ></script>
<style type="text/css">
p
{
font-family:"Verdana";
font-size:small;
}
a
{
font-family:"Helvetica";
font-size:small;
}
</style>
<script type="text/javascript">
var lastParam;
var sessionsNotOk = "DEF";
var callerView;
function getParam( paramName )
{
paramName = paramName.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+paramName+"=([^&#]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
/*
* Checks the return from ajax servlet call "../downloadzip?ask=isSRPsessionsOK&packageIDs="+pIDs".
* Called always right after checkDocbaseSessions() call.
*/
function checkReturn(){
//alert('checkReturn - sessionsNotOk global var = '+sessionsNotOk);
if (sessionsNotOk != "DEF") {
var docbases = sessionsNotOk.split(",");
//alert('checkReturn - docbases arr = '+docbases+', length='+docbases.length);
if (docbases.length == 1 && docbases[0] == "OK"){
// All sessions are faja
document.getElementById('divIndicator').style.display='none';
document.getElementById('checkSession').style.display='none';
document.getElementById('noSession').style.display='none';
document.getElementById('dlink').style.display='inline';
document.getElementById('dlink').style.textAlign='center';
document.getElementById('dlink').style.display='';
} else {
// We need to show the sublogin dialog
var nextDocbase = docbases[0];
//alert("Next NOT AVAILABLE session = "+nextDocbase);
window.opener.$('#subloginmessage').css('display','none');
window.opener.$('#loginIndicator').css('display','none');
window.opener.$('#sub-uid').val(window.opener.$('#user_name').text());
window.opener.$('#sub-uid').attr('disabled','disabled');
window.opener.$('#sub_docbase').text(nextDocbase);
document.getElementById('checkSession').style.display='none';
document.getElementById('noSession').style.display='inline';
document.getElementById('noSession').style.textAlign='center';
document.getElementById('noSession').style.display='';
window.opener.sublogin_fw = "download";
window.opener.sublogin_db = nextDocbase;
window.opener.$('#sublogindialog').dialog('open');
window.opener.$('#sublogindialog').dialog('option','title','Login to docbase: ' + nextDocbase + ' and click on Download listed documents link again!');
}
return;
}
//Check again in 0.5 second
//setTimeout("checkReturn()",500);
setTimeout(function() {
checkReturn();
}, 500);
}
function enableLink(){
callerView = getParam("view");
var pkgType = "";
var params = "";
var packageIDs = "";
if (callerView == "plainview") {
pkgType = window.opener.$('#hiddenPkgType').attr('value');
// Check available sessions
if (pkgType == 'srp'){
document.getElementById('dlink').style.display='none';
document.getElementById('checkSession').style.display='inline';
document.getElementById('checkSession').style.textAlign='center';
document.getElementById('checkSession').style.display='';
packageIDs = window.opener.$('#hiddenSRPIDs').attr('value');
checkDocbaseSessions(packageIDs);
checkReturn();
}
params = window.opener.$('#hiddenDownloadParams').attr('value');
} else if (callerView == "packagedetailview") {
pkgType = window.opener.$('#hiddenPkgType_DetailedPackageView').attr('value');
if (pkgType == "" || pkgType == null) {
alert("Still loading data, window will be closed. Please click on download button after all data have been loaded on the page!");
window.close();
}
params = window.opener.$('#hiddenDownloadParams_DetailedPackageView').attr('value');
} else if (callerView == "SRP_packagedetailview") {
// Prepare/check remote sessions
packageIDs = window.opener.$('#SRP_DPV_pkgIDs').attr('value');
checkDocbaseSessions(packageIDs);
checkReturn();
pkgType = 'srp';
if (pkgType == "" || pkgType == null) {
alert("Still loading data, window will be closed. Please click on download button after all data have been loaded on the page!");
window.close();
}
params = window.opener.$('#hiddenDownloadParams_SRP_DetailedPackageView').attr('value');
} else if (callerView == "SRP_checkstatusview") {
// Prepare/check remote sessions
packageIDs = window.opener.$('#SRP_CSV_pkgIDs').attr('value');
checkDocbaseSessions(packageIDs);
checkReturn();
pkgType = 'srp';
if (pkgType == "" || pkgType == null) {
alert("Still loading data, window will be closed. Please click on download button after all data have been loaded on the page!");
window.close();
}
params = window.opener.$('#hiddenDownloadParams_SRP_CheckStatusView').attr('value');
}
if (pkgType == 'nlp' || pkgType == 'monnlp') {
document.getElementById('download_zip_stdfilenames_nlp_country').style.display='inline';
document.getElementById('download_zip_stdfilenames_nlp_product').style.display='inline';
document.getElementById('download_zip_stdfilenames_nlp_country').style.textAlign='center';
document.getElementById('download_zip_stdfilenames_nlp_product').style.textAlign='center';
document.getElementById('download_zip_stdfilenames').style.display='none';
} else if (pkgType == 'clp') {
document.getElementById('download_zip_stdfilenames_nlp_country').style.display='none';
document.getElementById('download_zip_stdfilenames_nlp_product').style.display='none';
document.getElementById('download_zip_stdfilenames').style.display='inline';
document.getElementById('download_zip_stdfilenames').style.textAlign='center';
} else if (pkgType == 'ipl') {
document.getElementById('download_zip_stdfilenames_nlp_country').style.display='none';
document.getElementById('download_zip_stdfilenames_nlp_product').style.display='none';
document.getElementById('download_zip_stdfilenames').style.display='inline';
document.getElementById('download_zip_stdfilenames').style.textAlign='center';
}
//Defined as global
zipParamsImp = params + "&filename=import";
zipParamsStd = params + "&filename=standard";
}
function showIndicator(param){
document.getElementById('divIndicator').style.display='inline';
document.getElementById('divIndicator').style.textAlign='center';
document.getElementById('divIndicator').style.display='';
document.getElementById('dlink').style.display='none';
var parameters = "";
if (param == 'import'){
parameters = zipParamsImp;
} else if (param == 'standard') {
parameters = zipParamsStd;
} else if (param == 'standard_nlp_country') {
parameters = zipParamsStd + "_nlp_country";
} else if (param == 'standard_nlp_product') {
parameters = zipParamsStd + "_nlp_product";
}
lastParam = param;
postwith("../downloadzip",parameters);
}
function postwith (to, params) {
var myForm = window.opener.document.createElement("form");
myForm.method="post" ;
myForm.action = to ;
myForm.style.display = 'none';
jQuery.each(params.split('&'), function(){
var pair = this.split('=');
var myInput = window.opener.document.createElement("input") ;
myInput.setAttribute("name", pair[0]) ;
myInput.setAttribute("value", pair[1]);
myForm.appendChild(myInput);
});
var lastInput = window.opener.document.createElement("input") ;
lastInput.setAttribute("name", "download_token_value_id") ;
lastInput.setAttribute("value", "");
myForm.appendChild(lastInput);
window.opener.document.body.appendChild(myForm) ;
myForm.submit();
window.opener.document.body.removeChild(myForm) ;
//setTimeout("checkProgress()",1000);
setTimeout(function(){
checkProgress();
},1000);
}
/*
* Checks return from servlet call "../downloadzip?ask=isready" -> ask whether DownloadAsZipServlet
* has finished its work or not. If finished, close this popup.
*/
function checkProgress(){
window.focus();
$.ajax({
type: "GET",
url: "../downloadzip?ask=isready",
dataType: "text",
//dataType: "script",
//timeout: 2000,
success: function(results)
{
// Normal flow
//var result = eval('('+results+')');
var currParams = window.opener.$('#hiddenDownloadParams').attr('value');
//After closing DPV and clicking on Download Listed Documents button, we have to remove caller param, because there is no caller.
//Caller exists only if openPackage function called, and Download is on a DPV page.
//If we do not remove caller param, then exception occurs.
var callerPrefix = currParams.substring(0,currParams.indexOf('&'));
if (callerPrefix.indexOf('caller=') > -1) {
window.opener.$('#hiddenDownloadParams').attr('value',currParams.replace(callerPrefix+'&',""));
} else {
// No caller param found
}
if (results.indexOf('window.close()') > -1) {
window.close();
}
},
error: function(XMLHttpRequest, textStatus, errorThrown){
window.top.document.location.href = "../jsp/logout.jsp?msg=Application error (HTTPREQ quicksearch download documents). You have been logged out!";
}
});
}
/*
* In case of SRP - checks whether sessions for all required docbases are available.
* It is needed, because SRP package documents can be located in different docbases.
*/
function checkDocbaseSessions(pIDs){
sessionsNotOk = "DEF";
$.ajax({
type: "GET",
url: "../downloadzip?ask=isSRPsessionsOK&packageIDs="+pIDs,
dataType: "text",
success: function(results)
{
//alert(results);
if ($.trim(results) == 'OK'){
//alert("Sessions are OK!");
sessionsNotOk="OK";
} else {
sessionsNotOk=results;
//alert("Sessions are NOT OK! - "+sessionsNotOk);
}
},
error: function(XMLHttpRequest, textStatus, errorThrown){
window.top.document.location.href = "../jsp/logout.jsp?msg=Application error (HTTPREQ quicksearch download documents). You have been logged out!";
}
});
}
</script>
</head>
<body style="background-color: #ffffff; font-family: Verdana, Helvetica; font-size: x-small;" onload="enableLink();">
<div id="divIndicator" style="display: none"><br />
<p>Zip file creation in progress. This may take a few minutes, please wait and do not navigate away or start another query!</p>
<br />
<br />
<span id="qIndicator"> <img border="0" src="../img/indicator.gif"></span>
<br />
<br />
</div>
<p style="text-align: center">Download listed documents</p>
<div id="dlink" style="text-align: center">
With import file names
<br />
With standard file names
With standard file names starting with country
With standard file names starting with product
</div>
<div id="noSession" style="display: none">
<p>Some required sessions are unavailable. Please login to the docbase!</p>
</div>
<div id="checkSession" style="display: none">
<p>Checking required sessions in progress. Please wait...</p>
<br />
<span id="qIndicator"> <img border="0" src="../img/indicator.gif"></span>
<br />
</div>
</body>
</html>
Related
I am building an add-on for google docs (Just for practice) that will act like email. I already incorporated sending, receiving, deleting, and viewing messages. I added the code needed for a UI modal dialog, but one of the functions is only returning undfined. I tested this function in the code.gs file, and it worked perfectly. Here is a section of code.gs:
function onInstall() {
var html = HtmlService.createHtmlOutputFromFile('Startup').setWidth(350).setHeight(170);
DocumentApp.getUi().showModalDialog(html, 'New account:');
}
function testCheck() {
var ui = DocumentApp.getUi();
ui.alert(checkUsername(ui.prompt('').getResponseText(), ui.prompt('').getResponseText()));
}
function checkUsername(un, em) {
var i; var a; var is;
var props = PropertiesService.getScriptProperties();
if (props.getProperty(un) == null) {
is = true;
} else {
return 'This username is taken!';
}
if (em.length == 0) {
return true;
} else {
var len = (em.match(/#/g) || []).length;
if (len == 1) {
if (props.getProperty(em) != null) {
return 'Someone has already registered this email address as ' + props.getProperty(em);
} else {
return true;
}
} else {
if (em.indexOf(', ') != -1) {
em = em.split(', ');
} else if (em.indexOf('; ') != -1) {
em = em.split('; ');
} else if (em.indexOf(' + ') != -1) {
em = em.split(' + ');
} else if (em.indexOf(';') != -1) {
em = em.split(';');
} else if (em.indexOf(',') != -1) {
em = em.split(',');
} else if (em.indexOf('+') != -1) {
em = em.split('+');
} else if (em.indexOf(' ') != -1) {
em = em.split(' ');
} else {
return 'Please separate your email addresses with a comma, space, or semicolon.';
}
for (i = 0; i < em.length; i++) {
a = em[i];
if (props.getProperty(a) != null) {
return 'Someone has already registered ' + a + ' as ' + props.getProperty(a);
}
}
return true;
}
}
}
Here is the html file:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
</head>
<body>
Username:<br>
<input type='text' id='user' style='width:350px' maxlength='12'/><br>
Other email addresses:<br>
<textarea id='extras' style='width:350px' rows='2'></textarea><br>
<span class='error' id='err'></span><br>
<button class='action' onClick='check()'>Next</button>
<button onclick='group()'>Groups</button><br>
<script>
function check() {
var un = document.getElementById('user').value;
var em = document.getElementById('extras').value;
var fail = document.getElementById('err');
var is = google.script.run.checkUsername(un, em);
if (typeof is == 'string') {
fail.innerHTML = is;
} else {
google.script.host.close();
google.script.run.setAccount(un, em);
}
}
function group() {
var un = document.getElementById('user').value;
var em = document.getElementById('extras').value;
var is = google.script.run.checkUsername(un, em);
if (typeof is == 'boolean') {
setGroupAddress(un, em);
} else {
document.getElementById('err').innerHtml = is;
}
}
</script>
</body>
</html>
Update: I completely retyped the functions, but the program continues to return undefined. All inputs are the correct values, and the function returns information correctly in a ui.alert() box.
I figured it out after completely reading the Google Apps Script Documentation. The google.script.run.function() API does not return a value. In order to fetch data from a script, you must have the script generate raw HTML, and create a dialog with an HTML string.
Due to security considerations, scripts cannot directly return HTML to a browser. Instead, they must sanitize it so that it cannot perform malicious actions. You can return sanitized HTML using the createHtmlOutput API
function doGet() {
return HtmlService.createHtmlOutput('<b>Hello, world!</b>');
}
The code in the HtmlOutput can include embedded JavaScript and CSS. (This is standard client-side JavaScript that manipulates the DOM, not Apps Script). All of this content is sanitized using Google Caja, which applies some limitations to your client-side code. For more information, see the guide to restrictions in HTML service.
https://developers.google.com/apps-script/reference/html/html-output#
Hello I have a jquery and ajax validation form, when you fill the values (wrong values) x#x.com and 1111111 in password it will give ajax validation notice (which is fine) but after that if you put in the values (correct values) example#example.com and 12345678 it requires two clicks to submit. Meaning if you put wrong values first and then put correct values then it will require two clicks to submit. following is the code. I have set the code below so you can copy and paste the code into files (filenames given before) and you will have a working model to work with. I have hardcoded the php validate file so you guys can copy and paste the code and see how it works.
index.php
<?php
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
?>
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
</head>
<body>
<form method="post" name="loginform" action="success.php">
<input type="email" class="homepage" name="user_email2" id="user_email2" placeholder="Email" maxlength="50" required />
<div class ="errormsg" id ="errormsg6"></div>
<input type="password" class="homepage" name="user_password2" id="user_password2" placeholder="Password" maxlength="20" required />
<div class ="errormsg" id ="errormsg7"></div>
<input type="submit" name="login" id="login" value="Submit">
<div class ="errormsglast" id ="errormsg8"></div>
</form>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript" src="validatelogin.js"></script>
</body>
</html>
validatelogin.js
$(document).ready(function()
{
/* ----------------- Login Validations Global Variables ----------------- */
var user_email2 = "";
var user_emailajax2 = "";
var user_password2 = "";
var user_passwordajax2 = "";
var emailformat = new RegExp(/^[+a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/i);
/* ----------------- Define Validate Email */
var validate_email_login = function()
{
var item5 = $("#user_email2").val();
var item5 = item5.toLowerCase();
if (item5.length < 6 || item5.length > 50)
{
$("#errormsg6").html("Email : 6 - 50 Characters");
user_email2 = "";
}
else
{
$("#errormsg6").html("");
user_email2 = item5;
if (!emailformat.test(item5))
{
$("#errormsg6").html("Wrong Email Format");
user_email2 = "";
}
else
{
$("#errormsg6").html("");
user_email2 = item5;
$.ajax(
{
type: 'POST',
url: 'validatelogin.php?f=1',
data: "user_email2=" + item5,
success: function(msg)
{
if (msg == "ok")
{
user_emailajax2 = "";
$("#errormsg6").html("Email Does Not Exist");
}
else if (msg == "exists")
{
user_emailajax2 = item5;
$("#errormsg6").html("");
}
}
});
}
}
}
/* ----------------- Define Validate Password */
var validate_password_login = function()
{
var item5 = $("#user_email2").val();
var item5 = item5.toLowerCase();
var item6 = $("#user_password2").val();
if (item6.length < 8 || item6.length > 20)
{
$("#errormsg7").html("Password : 8-20 Characters");
user_password2 = "";
}
else
{
$("#errormsg7").html("");
user_password2 = item6;
if (user_email2 != "" && user_emailajax2 != "")
{
$.ajax(
{
method: "POST",
url: "validatelogin.php?f=2",
data: "user_email2=" + item5 + "&user_password2=" + item6,
success: function(msg)
{
if (msg == "WrongPw")
{
user_passwordajax2 = "";
$("#errormsg7").html("Wrong Password");
}
else if (msg == "CorrectPw")
{
user_passwordajax2 = item6;
$("#errormsg7").html("");
/* window.location.href="manage-properties"; */
}
}
});
}
}
}
/* ----------------- Run Functions */
$("#user_email2").on('focusout', validate_email_login);
$("#user_password2").on('focusout', validate_password_login);
$("#login").on('click', validate_email_login);
$("#login").on('click', validate_password_login);
/* ----------------- Stop on Submit */
$("#login").on('click', function()
{
if (user_email2 == "" || user_emailajax2 == "" || user_password2 == "" || user_passwordajax2 == "")
{
$("#errormsg8").html("Please Fill All Fields (Correctly)");
console.log("submit false");
return false;
}
else
{
$("#errormsg8").html("");
console.log("submit true");
return true;
}
});
});
validatelogin.php
<?php
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if($_GET['f']==1) {
if(isset($_POST['user_email2'])) {
$user_email2 = strtolower($_POST['user_email2']);
if($user_email2 == "example#example.com") {
echo "exists";
} else {
echo "ok";
}
}
}
if($_GET['f']==2) {
if(isset($_POST['user_email2'], $_POST['user_password2'] )) {
$user_email2 = strtolower($_POST['user_email2']);
$user_password2 = $_POST['user_password2'];
if($user_email2!="example#example.com" and $user_password2!="12345678") {
echo "WrongPw";
} elseif($user_email2=="example#example.com" and $user_password2=="12345678") {
echo "CorrectPw";
}
}
}
?>
success.php
<?php
echo "Login Successful";
?>
Tried Solutions
1. Putting a delay on the submit button
2. On Keyup instead of on Focusout (this works but not what is required)
3. Give delay to keyup (could not get it to work with ajax - but its closer to what I require, but not exactly what I require
4. Triggering the click on submit on return true of ajax (also did not work)
I need some javascript expert to look into it and give me solution.
Okay, I don't want to be rude, but all that code is a bit of a disaster. You're calling the on click function 3 different times, you're making ajax calls to the server on every form change and on submit. Then you're actually making two separate ajax calls for the actual submit function.
The code below is a lot more compact, only ever makes one ajax call and should work. I'll explain a bit before each code block
Your form add an id so that jQuery can use serialize in the ajax call
<form method="post" id="loginform" name="loginform" action="success.php">
<input type="email" class="homepage" name="user_email2" id="user_email2" placeholder="Email" maxlength="50" required />
<div class ="errormsg" id ="errormsg6"></div>
<input type="password" class="homepage" name="user_password2" id="user_password2" placeholder="Password" maxlength="20" required />
<div class ="errormsg" id ="errormsg7"></div>
<input type="submit" name="login" id="login" value="Submit">
<div class ="errormsglast" id ="errormsg8"></div>
</form>
validatelogin.php - This should only be one call to the server, do both functions in one, return the data as json rather than echoing single values, that way you get an object back that you can parse in your jQuery code.
<?php
if (session_status() == PHP_SESSION_NONE) {
session_start();
}
if(isset($_POST['user_email2'], $_POST['user_password2'] )) {
$user_password2 = $_POST['user_password2'];
$user_email2 = strtolower($_POST['user_email2']);
if($user_email2 != "example#example.com") {
$data['email_check'] = 'false';
} else {
$data['email_check'] = 'true';
}
$data = array;
if($user_email2!="example#example.com" && $user_password2!="12345678") {
$data['password_check'] = 'false';
} else {
$data['password_check'] = 'true';
}
}
print(json_encode($data));
jQuery - I am not really sure why you're calling all these functions on blur and the multiple on clicks. Just do it in the one on click, call validate email, if that passes you move on to validate password and if that passes it makes the ajax call to actually check the details against the server.
Also avoid variable names like item5, errormsg6, to another developer that means nothing, and it won't to you in 6 months either. And don't tell people which element was wrong, ie "Incorrect password" just for security, just tell them their login details are wrong.
$(document).ready(function() {
/* ----------------- Login Validations Global Variables ----------------- */
var user_email2 = "";
var user_emailajax2 = "";
var user_password2 = "";
var user_passwordajax2 = "";
var emailformat = new RegExp(/^[+a-zA-Z0-9._-]+#[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/i);
/* ----------------- Define Validate Email */
var validate_email_login = function() {
var email = $("#user_email2").val().toLowerCase();
var errors = [];
if (email.length < 6 || email.length > 50) {
errors.push("Email : 6 - 50 Characters<br>");
}
if (!emailformat.test(email)) {
errors.push("Wrong Email Format");
}
if( errors.length > 0 ) {
$("#errormsg6").html(errors);
return false;
}
$("#errormsg6").html();
validate_password_login();
}
/* ----------------- Define Validate Password */
var validate_password_login = function() {
var item6 = $("#user_password2").val();
if (item6.length < 8 || item6.length > 20) {
$("#errormsg7").html("Password : 8-20 Characters");
return false;
}
$("#errormsg7").html("");
submitForm();
}
var submitForm = function() {
$.ajax({
type: 'POST',
url: 'validatelogin.php',
dataType: "json",
data: $("#loginform").serialize(),
success: function(msg) {
if(msg.email_check == 'true' && msg.password_check == 'true') {
//do whatever it is you want to do on correct login here
} else {
$("#errormsg6").html("Your login details are incorrect, please check and try again");
}
}
});
}
/* ----------------- Stop on Submit */
$("#login").on('click', function() {
errors = [];
if(validate_email_login() == true) {
alert("hi");
}
});
});
You can see the error validation on the jQuery end here: https://jsfiddle.net/calder12/3fhvpenr/
I developed a web application and deployed into the server and my security team come up with the below security remidiation issue.
Reflected HTML Parameter Pollution (HPP) is an injection weakness vulnerability that occurs when an attacker can inject a delimiter and change the parameters of a URL generated by an application. The consequences of the attack depend upon the functionality of the application, but may include accessing and potentially exploiting uncontrollable variables, conducting other attacks such as Cross-Site Request Forgery, or altering application behavior in an unintended manner. Recommendations include using strict validation inputs to ensure that the encoded parameter delimiter “%26” is handled properly by the server, and using URL encoding whenever user-supplied content is contained within links or other forms of output generated by the application.
Can any one have the idea about how to prevent HTML parameter pollution in asp.net
here is the script code in the webpage
<script type="text/javascript" language="javascript">
document.onclick = doNavigationCheck ;
var srNumberFinal="";
function OpenDetailsWindow(srNumber)
{
window.open("xxx.aspx?SRNumber="+srNumber+ "","","minimize=no,maximize=no,scrollbars=yes,status=no,toolbar=no,menubar=no,location=no,width=800,directories=no,resizable=yes,titlebar=no");
}
function OpenPrintWindow()
{
var querystrActivityId = "<%=Request.QueryString["activityId"]%>";
if(querystrActivityId != "")
{
var url = "abc.aspx?id=" + "<%=Request.QueryString["id"]%>" + "&activityId=" + querystrActivityId + "";
}
else
{
var hdrActivityId = document.getElementById('<%=uxHdnHdrActivityId.ClientID%>').value;
var url = "PrintServiceRequestDetail.aspx?id=" + "<%=Request.QueryString["id"]%>" + "&activityId=" + hdrActivityId + "";
}
childWinReference=window.open(url, "ChildWin","minimize=yes,maximize=yes,scrollbars=yes,status=yes,toolbar=no,menubar=yes,location=no,directories=no,resizable=yes,copyhistory=no");
childWinReference.focus();
}
function NavigateSRCopy(srNumber)
{
srNumberFinal = srNumber;
if (srNumber != "undefined" && srNumber != null && srNumber != "")
{
new Ajax.Request('<%= (Request.ApplicationPath != "/") ? Request.ApplicationPath : string.Empty %>/xxx/AutoCompleteService.asmx/CheckFormID'
, { method: 'post', postBody: 'srNumber=' + srNumber, onComplete: SearchResponse });
}
}
function SearchResponse(xmlResponse)
{
var xmlDoc;
try //Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(xmlResponse.responseText);
}
catch(e)
{
try // Firefox, Mozilla, Opera, etc.
{
parser=new DOMParser();
xmlDoc=parser.parseFromString(xmlResponse.responseText,"text/xml");
}
catch(e)
{
alert(e.message);
return;
}
}
if(xmlDoc.getElementsByTagName("string")[0].childNodes[0] != null)
{
formID = xmlDoc.getElementsByTagName("string")[0].childNodes[0].nodeValue;
}
else
{
formID = null;
}
if(formID != null && formID != "")
{
window.location.href = '/CustomerSupportRequest/CreateServiceRequest.aspx?id=' + formID + '&TemplateSR=' + srNumberFinal + '&Frompage=CopySR';
return true;
}
else
{
alert("This Service Request cannot be copied because it meets at least one of these conditions: \t\t\n\n * It was created prior to 10/15/2008 \n * It was auto generated as part of the Report Requeue Process \n * It was auto generated as part of the ERA Requeue Process \n * It was not created online");
}
}
function UpdateChildCases()
{
var modalPopup = $find('modalParentChildComments');
modalPopup.show();
}
function HideParentChildPopup()
{
var modalPopup = $find('modalParentChildComments');
modalPopup.hide();
return false;
}
function HideErrorSRNumsPopup()
{
var modalPopup = $find('modalParentErrorSRNumDisplay');
modalPopup.hide();
return false;
}
function HideRetrySRNumsPopup()
{
var modalPopup = $find('modalRetrySRNumDisplay');
modalPopup.hide();
return false;
}
function RemoveParent_ChildFlag(type)
{
var childCases = document.getElementById("<%=uxHdnChildCases.ClientID %>");
var msg = "";
var btn;
if(type == "Child")
{
if(childCases.value.indexOf(',') != -1)
msg = "Are you sure you want to remove the Child flag from this Service Request?";
else
msg = "This is the only child associated to the parent case. Removing the child flag will also remove the parent flag from the associated case. Choose OK to remove the flags, or Cancel to close this dialog";
btn = document.getElementById('<%=uxRemoveChildFlag.ClientID%>');
}
else
{
msg = "Removing the parent flag from this case will also remove the child flag from all associated cases. Are you sure you want to remove the Parent flag from this Service Request?";
btn = document.getElementById('<%=uxRemoveParentFlag.ClientID%>');
}
if(btn)
{
if(!confirm(msg))
{
return false;
}
else
{
btn.click();
}
}
}
function limitTextForParentChildComments()
{
var objLblCharCount = document.getElementById('uxLblPCCharCount');
var objTxtComments = document.getElementById('<%=txtParentComment.ClientID%>');
if (objTxtComments.value.length > 1500)
{
objTxtComments.value = objTxtComments.value.substring(0, 1500);
}
else
{
objLblCharCount.innerHTML = 1500 - objTxtComments.value.length + " ";
}
setTimeout("limitTextForParentChildComments()",50);
}
function ValidateInputs()
{
var lblErrorMessage = document.getElementById('<%=lblCommentErrorTxt.ClientID%>');
var objTxtComments = document.getElementById('<%=txtParentComment.ClientID%>');
if(objTxtComments.value.trim() == "")
{
lblErrorMessage.style.display = "block";
return false;
}
}
</script>
As per OWASP Testing for HTTP Parameter pollution, ASP.NET is not vulnerable to HPP because ASP.NET will return all occurrences of a query string value concatenated with a comma (e.g. color=red&color=blue gives color=red,blue).
See here for an example explanation.
That said, your code appears to be vulnerable to XSS instead:
var querystrActivityId = "<%=Request.QueryString["activityId"]%>";
If the query string parameter activityId="; alert('xss');" (URL encoded of course), then an alert box will trigger on your application because this code will be generated in your script tag.
var querystrActivityId = ""; alert('xss');"";
I have set 2 min for session timeout and if it occurred the page
will redirect to a session timeout page.
However, I have some pages that could be browsed without login.
In these pages, if I leave it more than 2 min, pop out will appear asking user to log in again. User will go back to click it and it will redirect to session timeout page.
Could anyone teach me, how to get rid of this such that the pages be browsed without login should not occur session time?
ajax.js
window.onload = init;
var interval;
function init() {
interval = setInterval(trackLogin, 1000);
}
function trackLogin() {
var xmlReq = false;
try {
xmlReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
xmlReq = false;
}
}
if (!xmlReq && typeof XMLHttpRequest != 'undefined') {
xmlReq = new XMLHttpRequest();
}
xmlReq.open('get', 'check.php', true);
xmlReq.setRequestHeader("Connection", "close");
xmlReq.send(null);
xmlReq.onreadystatechange = function() {
if (xmlReq.readyState == 4 && xmlReq.status == 200) {
if (xmlReq.responseText == 1) {
clearInterval(interval);
alert('You have been logged out. You will now be redirected to home page.');
document.location.href = "index.php";
}
}
}
}
firstSession
<?php
// session_start ();
if (! isset ( $_SESSION ["isLoggedIn"] ) || ! ($_SESSION ['isLoggedIn'])) {
// code for authentication comes here
// ASSUME USER IS VALID
$_SESSION ['isLoggedIn'] = true;
$_SESSION ['timeOut'] = 120;
$logged = time ();
$_SESSION ['loggedAt'] = $logged;
// showLoggedIn ();
} else {
require 'timeCheck.php';
$hasSessionExpired = checkIfTimedOut ();
if ($hasSessionExpired) {
session_unset ();
header ( "Location:index.php" );
exit ();
} else {
$_SESSION ['loggedAt'] = time ();
}
}
?>
footer.php
<?php include ('includes/firstSession.php'); ?>
<footer class="main">
<div class="wrapper container">
<div class="copyright">All Rights Reserved
</div>
<div class="logo"><img src="images/logo.png"></div>
</footer>
</div>
draft ajax.js
window.onload = init;
var interval;
function init() {
interval = setInterval(trackLogin, 1000);
}
function trackLogin() {
var xmlReq = false;
try {
xmlReq = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlReq = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e2) {
xmlReq = false;
}
}
if (!xmlReq && typeof XMLHttpRequest != 'undefined') {
xmlReq = new XMLHttpRequest();
}
xmlReq.open('get', 'check.php', true);
xmlReq.setRequestHeader("Connection", "close");
xmlReq.send(null);
xmlReq.onreadystatechange = function() {
if (xmlReq.readyState == 4 && xmlReq.status == 200) {
return json_encode(array(
'role' => $_SESSION['role'], //assuming something like guest/logged-in
'user_id' => $_SESSION['user_id']
));
var obj = xmlReq.responseText;
var jsonObj = JSON.parse(obj);
//now we can make a comparison against our keys 'role' and 'user_id'
if(jsonObj['role'] == 'guest'){
//guest role, do something here
} else if (jsonObj['role'] == 'logged-in') {
alert('You have been logged out. You will now be redirected to home page.');
document.location.href = "index.php";
//do something else for logged in users
}
I think since you have a session that is persistent whether logged in or not, you need to base your action on the username (however that is set). See if this is what you are trying to do. I have notated for clarity:
myfunctions.php
<?php
// return a session set on not set OR false if set
function is_loggedin()
{
return (!empty($_SESSION["isLoggedIn"]));
}
// Check if username is set (not sure how your usernames are stored in your session
// but that is what you want to check here
function user_set()
{
return (!empty($_SESSION["username"]));
}
// Do your set time function
function set_time_out($timeout = 120)
{
$_SESSION['isLoggedIn'] = true;
$_SESSION['timeOut'] = (is_numeric($timeout))? $timeout : 120;
$_SESSION['loggedAt'] = time();
}
function process_timeout($supRed = false)
{
// If a user has NOT already been poking around your site
if(!is_loggedin()) {
// Set the timeout
set_time_out();
return 0;
}
else {
// If a navigating user is logged in
if(user_set()) {
// Check for expire time
require('timeCheck.php');
// If they have been timed out
if(checkIfTimedOut()) {
if(!$supRed) {
// destroy the session and forward to login (or wherever)
session_destroy();
header("Location:index.php" );
exit();
}
return 1;
}
}
// Set the logged time by default
$_SESSION['loggedAt'] = time();
}
return 0;
}
header.php
<?php
include_once("includes/firstSession.php");
include_once("includes/myfunctions.php");
process_timeout();
?><!DOCTYPE html>
...etc
check.php
<?php
include_once("includes/firstSession.php");
include_once("includes/myfunctions.php");
echo process_timeout(true);
EDIT:
This is the entire script, both js and php.
// return a session set on not set OR false if set
function is_loggedin()
{
return (!empty($_SESSION["isLoggedIn"]));
}
// Check if username is set (not sure how your usernames are stored in your session
// but that is what you want to check here
function user_set()
{
return (!empty($_SESSION["username"]));
}
// Do your set time function
function set_time_out($timeout = 120)
{
$_SESSION['isLoggedIn'] = true;
$_SESSION['timeOut'] = (is_numeric($timeout))? $timeout : 120;
$_SESSION['loggedAt'] = time();
}
function checkIfTimedOut()
{
if(!empty($_SESSION['loggedAt'])) {
$active = ($_SESSION['loggedAt'] + strtotime("120 seconds"));
$now = time();
return (($active - $now) > 0);
}
return true;
}
function process_timeout($supRed = false)
{
// If a user has NOT already been poking around your site
if(!is_loggedin()) {
// Set the timeout
set_time_out();
return 0;
}
else {
// If a navigating user is logged in
if(user_set()) {
// Check for expire time
// If they have been timed out
if(checkIfTimedOut()) {
// destroy the session
session_destroy();
if(!$supRed) {
// Forward to login (or wherever)
header("Location:index.php" );
exit();
}
return 1;
}
}
// Set the logged time by default
$_SESSION['loggedAt'] = time();
}
return 0;
}
check.php:
// Include the functions here
if(!empty($_POST['getPost'])) {
echo json_encode(array("redirect"=>process_timeout(true),"sess"=>$_SESSION));
exit;
}
CALLING PAGE:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>
<script>
function init()
{
interval = setInterval(trackLogin, 2000);
}
function trackLogin()
{
$.ajax({
url: '/check.php',
data: { getPost: true },
type: 'post',
success: function(response) {
var instr = JSON.parse(response);
console.log(response);
if(instr.redirect == 1) {
clearInterval(interval);
alert('You have been logged out. You will now be redirected to home page.');
document.location.href = "index.php";
}
}
});
}
$(document).ready(function() {
var interval;
init();
});
</script>
EDITED
I have this script below which is used in a survey. The problem I have is, onbeforeunload() works when I don't call a function inside it. If I make any function call(save_survey() or fetch_demographics()) inside it, the browser or the tab closes without any prompt.
<script type="text/javascript">
$(document).ready(function() {
$('#select_message').hide();
startTime = new Date().getTime();
});
loc = 0;
block_size = {{ block_size }};
sid = {{ sid }};
survey = {{ survey|tojson }};
survey_choices = '';
startTime = 0;
demographics_content = {};
function save_survey(sf)
{
var timeSpentMilliseconds = new Date().getTime() - startTime;
var t = timeSpentMilliseconds / 1000 / 60;
var surveydat = '';
if(sf==1)
{ //Success
surveydat = 'sid='+sid+'&dem='+JSON.stringify(demographics_content)+'&loc='+loc+'&t='+t+'&survey_choice='+JSON.stringify(survey_choices);
}
if(sf==0)
{ //Fail
surveydat = 'sid='+sid+'&dem='+json_encode(demographics_content)+'&loc='+loc+'&t='+t+'&survey_choice='+json_encode(survey_choices);
}
//Survey Save Call
$.ajax({
type: 'POST',
url: '/save_surveyresponse/'+sf,
data: surveydat,
beforeSend:function(){
// this is where we append a loading image
$('#survey_holder').html('<div class="loading"><img src="/static/img/loading.gif" alt="Loading..." /></div>');
},
success:function(data){
// successful request; do something with the data
$('#ajax-panel').empty();
$('#survey_holder').html('Success');
alert("Dev Alert: All surveys are over! Saving data now...");
window.location.replace('http://localhost:5000/surveys/thankyou');
},
error:function(){
// failed request; give feedback to user
$('#survey_holder').html('<p class="error"><strong>Oops!</strong> Try that again in a few moments.</p>');
}
});
}
function verify_captcha()
{
// alert($('#g-recaptcha-response').html());
}
function block_by_block()
{
var div_content ='<table border="0" cellspacing="10" class="table-condensed"><tr>';
var ii=0;
var block = survey[loc];
var temp_array = block.split("::");
if(loc>=1)
{
var radio_val = $('input[name=block_child'+(loc-1)+']:checked', '#listform').val();
//console.log(radio_val);
if(radio_val!=undefined)
survey_choices += radio_val +'\t';
else
{
alert("Please select one of the choices");
loc--;
return false;
}
}
for(ii=0;ii<block_size;ii++)
{
//Chop the strings and change the div content
div_content+="<td>" + temp_array[ii]+"</td>";
div_content+="<td>" + ' <label class="btn btn-default"><input type="radio" id = "block_child'+loc+'" name="block_child'+loc+'" value="'+temp_array[ii]+'"></label></td>';
div_content+="</tr><tr>";
}
div_content+='<tr><td><input type="button" class="btn" value="Next" onClick="survey_handle()"></td><td>';
div_content+='<input type="button" class="btn" value="Quit" onClick="quit_survey()"></td></tr>';
div_content+="</table></br>";
$("#survey_holder").html(div_content);
//return Success;
}
function updateProgress()
{
var progress = (loc/survey.length)*100;
$('.progress-bar').css('width', progress+'%').attr('aria-valuenow', progress);
$("#active-bar").html(Math.ceil(progress));
}
function survey_handle()
{
if(loc==0)
{
verify_captcha();
$("#message").hide();
//Save the participant data and start showing survey
fetch_demographics();
block_by_block();
updateProgress();
$('#select_message').show();
}
else if(loc<survey.length)
{
block_by_block();
updateProgress();
}
else if(loc == survey.length)
{
//Save your data and show final page
$('#select_message').hide();
survey_choices += $('input[name=block_child'+(loc-1)+']:checked', '#listform').val()+'\t';
//alert(survey_choices);
//Great way to call AJAX
save_survey(1);
}
loc++;
return false;
}
</script>
<script type="text/javascript">
window.onbeforeunload = function() {
var timeSpentMilliseconds = new Date().getTime() - startTime;
var t = timeSpentMilliseconds / 1000 / 60;
//fetch_demographics();
save_survey(0);
return "You have spent "+Math.ceil(t)+ " minute/s on the survey!";
//!!delete last inserted element if not quit
}
</script>
I have checked whether those functions have any problem but they work fine when I call them from different part of the code. Later, I thought it might be because of unreachable function scope but its not the case. I have tried moving the onbeforeunload() at the end of script and the problem still persists. Wondering why this is happening, can anyone enlighten me?
I identified where the problem was. I am using json_encode instead of JSON.stringify and hence it is crashing(which I found and changed already in sf=1 case). That tip with debugger is invaluable. Also, its working fine even without async: false.
Thank you again #AdrianoRepetti!