Javascript and Escape Character on Android Webview - javascript

i need to be able to capture user's password and then bypass it if user authorized with biometrics to Android WebView. I'm successfully capturing the password and passing it to the webview, I'm executing the js like this, the method returns me js with injected css selector and value to input which I run against the webview
fun getJsToEnterValueToTextField(cssSelectorById: String, value: String): String {
val js = "javascript:(function() { " +
"var element = document.getElementById(\"$cssSelectorById\");" +
"console.log(element);" +
"element.value='${value.trim()}';" +
" element.dispatchEvent(new Event('input', {\n" +
" view: window,\n" +
" bubbles: true,\n" +
" cancelable: true\n" +
" }))" +
"})()"
Timber.d("SWA_WEBVIEW - getJsToEnterValueToTextField >> $js")
return js
}
//--//
webview.loadUrl(url2load)
The problem happens if the user has any escape characters in the value,
for example if user has '%E9' as part of that password string, once I run that js > this %E9 would transform to é
Does anyone know if there is a way around it? I searched all over but nothing seems to make a difference.

Related

Implement a StorageEvent by localStorage

Because StorageEvent does not work here, I want to implement an event handler by localStorage.
Assume we have a web page as follows. Any change to the input field will trigger an event, we save the new value to localStorage. JSBin
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
</head>
<body ng-controller="Ctrl">
<input type="text" ng-model="text"></input>
<div id="console"></div>
<script>
var app = angular.module('app', []);
app.controller('Ctrl', ["$scope", function ($scope) {
$scope.$watch('text', function (newValue, oldValue) {
var x = "nV: " + newValue;
localStorage.setItem("messages", localStorage.getItem("messages") + " " + x)
debug(localStorage.getItem("messages"))
}, false)
}])
function debug(msg) {
document.getElementById("console").innerHTML += msg + "<br/>";
}
</script>
</body>
</html>
And we have another web page that listens. It scans localStorage by setInterval. It is actually a pipe: several messages can be stored in localStorage, and we should treat them all and then empty localStorage. JSBin
<html>
<body>
<div id="console"></div>
<script>
var listen = setInterval(function () {
var m = localStorage.getItem("messages");
if ((m !== "") && (m !== undefined)) {
localStorage.setItem("messages", "")
treatMessages(m);
}
}, 100)
function treatMessages(messages) {
debug(messages)
}
function debug(msg) {
document.getElementById("console").innerHTML += msg + "<br/>";
}
</script>
</body>
</html>
But what is important, is that we should make sure that no message is missed by the receiver. Unfortunately, it is not the case for the moment, For example, I typed quickly 123456789 in the input field, then 12345 was missing on the side of the receiver. It is probably because the sender generated 12345 just after the receiver read the localStorage and before the receiver emptied the localStorage.
So does anyone know how to fix this? Should we have a semaphore for localStorage or is there any other workaround?
Edit 1: I tried to add a semaphore by lock and waitfor: the sender and the receiver, but it still can miss messages. For example, 123456 is missing in the example below. It is not surprising, I think it is because when lock is free, we entered simultaneously the callback of the 2 waitfor, then it messed up.
Edit 2: I have done another shot which is supposed to work better, but I don't know why the two pages cannot align their localStorage value: the sender and the receiver
Try the newer IndexedDB. https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB. It is more sophisticated/complex. It is now broadly supported: http://caniuse.com/#search=indexeddb.
I believe it can solve your issue above (missed messages), but there is no changeEvent. I also believe it will not be able to see changes across browser (WebKit) instances on Mac (e.g. Excel for Mac) due to caching, but should work across tabs.
I suggest using localDataStorage to fire the events for you, for each key value addition, deletion or change. It even reports these events in a single page/tab! This utility can transparently set/get any of the following "types": Array, Boolean, Date, Float, Integer, Null, Object or String (no conversion needed).
[DISCLAIMER] I am the author of the utility [/DISCLAIMER]
Once you instantiate the utility, the following snippet will allow you to monitor the events:
function localStorageChangeEvents( e ) {
console.log(
"timestamp: " + e.detail.timestamp + " (" + new Date( e.detail.timestamp ) + ")" + "\n" +
"key: " + e.detail.key + "\n" +
"old value: " + e.detail.oldval + "\n" +
"new value: " + e.detail.newval + "\n"
);
};
document.addEventListener(
"localDataStorage"
, localStorageChangeEvents
, false
);

Jsf Renderer script Code is uncommended [duplicate]

This question already has answers here:
Custom JSF component: Using "startElement" with "script" results in a comment
(2 answers)
Closed 7 years ago.
i try to put internal JS code into a JS block. This should be done by a custom Renderer for the h:commandButton. The Renderer is inbound and works finde. But as soon as i start to generate the script block it is put between <!-- and -->.
So here is the method for generating the script block:
private void writeScript(FacesContext ctx, HtmlCommandButton button, String event, String script) throws IOException {
String nonce = UUID.randomUUID().toString();
ResponseWriter writer = ctx.getResponseWriter();
ctx.setResponseWriter(writer);
writer.startElement("input", button);
writer.writeAttribute("type", "submit", null);
writer.endElement("input");
writer.startElement("script", button);
writer.writeAttribute("nonce", nonce, null);
writer.write("document.getElementById('" + button.getClientId()
+ "')."
+ event
+ " ="
+ " function() {"
+ script
+ "}");
writer.endElement("script");
}
Also using the startCDATA() method doesn't seem to work.
So instead of:
<script nonce="...">
document.getElementById('j_id1955899975_7494aa2f:submitButton').alert('hallo') = function() {onclick}
</script>
the generated code looks like:
<script nonce="...">
<!--
document.getElementById('j_id1955899975_7494aa2f:submitButton').alert('hallo') = function() {onclick}
//-->
</script>
What am I doing wrong ?
Would be really nice if someone could help me :D
According to Predrag Maric's link i changed code to the following:
private void writeScript(FacesContext ctx, HtmlCommandButton button, String event, String script) throws IOException {
System.out.println("das event: "+event);
String nonce = UUID.randomUUID().toString();
ResponseWriter writer = ctx.getResponseWriter();
ctx.setResponseWriter(writer);
writer.startElement("input", button);
writer.writeAttribute("type", "submit", null);
writer.writeAttribute("id", button.getClientId(), null);
writer.endElement("input");
writer.write("<script>");
writer.write("document.getElementById('" + button.getClientId()
+ "')."
+ event
+ " ="
+ " function() {"
+ script
+ "}");
writer.write("</script>");
}
The problem was writing the script tags with the writeElement() method of the ResponseWriter It automatically adds the comments... After coding it out it works, thx a lot !.

ASP.NET C# backend, did the user press OK or Cancel from JavaScript confirm box?

In the C# backend code for a website, I have the following code that displays a message for the user, enumerating the data they are about to submit, and asking for human-confirmation that the information appears accurate.
This is executed within C#, not within JavaScript, so how can I access the result of the confirm function?
My C# logic needs to follow a different path if they click OK, versus if they click Cancel.
I'm working on a very old application (13 years), that has been untouched for quite some time.
As a result, I don't have the ability to alter the general design of the application.
ClientScript.RegisterStartupScript(this.GetType(), "InvalidEntrySubTypeAlert", "confirm('" +
"Are you sure you want to create the following deal?\n" +
"\nDeal ID :\t\t\t" + nDealID +
"\nCompany Name :\t\t" + txtCompanyName.Text +
"\nEntry Subject :\t\t" + txtEntrySubject.Text +
"\nBusiness Lead :\t\t" + ddlBusinessLead.SelectedItem.Text +
"\nLicense Status :\t\t" + ddlLicenseStatus.SelectedItem.Text +
"\nEffective Date :\t\t" + string.Format("{0:MM/dd/yyyy}", calEffectiveDate.SelectedDate) +
"\nExpiration Date :\t\t" + string.Format("{0:MM/dd/yyyy}", calExpirationDate.SelectedDate) +
"\nLicense Location :\t\t" + txtLicenseLocation.Text +
"\nEntry Sub Type :\t\t" + ddlEntrySubType.SelectedItem.Text.Split(' ')[0]
+ "');", true);
You can use a HiddenField to set the value from the client side and then access it on the Server.
Here is a mockup
<asp:HiddenField ID="hndSetFromJS" runat="server"></asp:HiddenField>
And set the value like this
document.getElementById("#<%= hndSetFromJS.ClientID %>").value = "yourValue";
or
$("#<%= hndSetFromJS.ClientID %>").val("yourValue"); // Jquery
I think I would call a page method (a method in the code behind marked with webmethod attribute) from client side or use ajax to call a web service.
Since the confirm action is executed client side there's no direct link to your server side cide
You can create 2 functions in client side
function functionOK()
{
//some code
}
function functionCancel()
{
//some code
}
and change your code like this
ClientScript.RegisterStartupScript(this.GetType(), "InvalidEntrySubTypeAlert", "if(confirm('" +
"Are you sure you want to create the following deal?\n" +
"\nDeal ID :\t\t\t" + nDealID +
"\nCompany Name :\t\t" + txtCompanyName.Text +
"\nEntry Subject :\t\t" + txtEntrySubject.Text +
"\nBusiness Lead :\t\t" + ddlBusinessLead.SelectedItem.Text +
"\nLicense Status :\t\t" + ddlLicenseStatus.SelectedItem.Text +
"\nEffective Date :\t\t" + string.Format("{0:MM/dd/yyyy}", calEffectiveDate.SelectedDate) +
"\nExpiration Date :\t\t" + string.Format("{0:MM/dd/yyyy}", calExpirationDate.SelectedDate) +
"\nLicense Location :\t\t" + txtLicenseLocation.Text +
"\nEntry Sub Type :\t\t" + ddlEntrySubType.SelectedItem.Text.Split(' ')[0]
+ "')){ functionOK();} else{functionCancel()}", true);

Close popup on cancel of javascript button.

In one modal popup, I am updating values, and upon save button click, before updating I am asking user by javascript message box : "Are you sure....?"
This I am doing by following code:
btnSave.Attributes.Add("onclick", "javascript:return " & "confirm('Are you sure " & RbtnConfirm.SelectedValue & " ' )")
But when user clicks cancel, I want to close that whole modal popup by:
modalpopup1.hide() method
I am confused how and where should I include this line of code?
From where can I get whether btnSave.Attributes.Add("onclick", "javascript:return " & "confirm('Are you sure " & RbtnConfirm.SelectedValue & " ' )") has returned false or true?
Please help me.
why the return " & "?
Anyway for inline (which is not recommended), just do
btnSave.Attributes.Add("onclick", "if (confirm('Are you sure " & RbtnConfirm.SelectedValue & " ' )) modalpopup1.hide()")
Move the confirm call to separate function, ie.:
include this in your .ascx/.aspx:
<script>
function myconfirm(sValue) {
var bValue = confirm(sValue);
if (!bValue) {
modalpopup1.hide();
}
return bValue;
}
</script>
in codebehind:
btnSave.Attributes.Add("onclick", "javascript:return " & "myconfirm('Are you sure " & RbtnConfirm.SelectedValue & " ' )")

Passing special characters to mailto body blows up JavaScript

I have a C# ASP.NET app that creates a JavaScript array of values for some user profile information. Client-side, I use jQuery/JavaScript to read the array and generate a mailto link. Some of the fields can contain special characters, such as ' & = / \ ".
Here's the C# code:
private String generateElementsArray(){
StringBuilder sb = new StringBuilder();
sb.Append("var currentElements = { currentUserName: '");
sb.Append(currentUserName);
sb.Append("', currentUserEmail: '");
sb.Append(currentUserEmail);
sb.Append("', currentSite: '");
sb.Append(currentSite);
sb.Append("', currentTitle: '");
sb.Append(currentTitle);
sb.Append("'}");
return sb.ToString();
}
I write the value of the above method to the page, which produces this JavaScript:
<script type="text/javascript">var currentElements = { currentUserName: 'Alex', currentUserEmail: 'myemailID', currentSite: 'Helpdesk', currentTitle: 'Phone User Guides & Troubleshooting'}</script>
Then I generate the email link using this JavaScript code, attaching the anchor tag to an element on the page:
function generateEmailTo(){
var body = currentElements.currentUserName + ' has shared a page with you on the intranet.%0A%0APage Title: %22' +
currentElements.currentTitle.replace("&","and") + '%22%0A' + $(location).attr('href').replace('#','');
var subject = currentElements.currentUserName + ' has shared a page with you on the intranet';
var mailto = 'mailto: ?body=' + body + '&subject=' + subject;
var anchor = '';
$("#email-placeholder").wrap(anchor);
}
....
<img id="email-placeholder" title="Send this page to a friend." src="<%= baseUrl %>/SiteAssets/media/icons/email-icon.gif"/>
For the mailto body text, I've noticed that it only takes a small set of the encoded characters, such as %22 for double-quotes, and %0A for line breaks. How do I pass the special characters such as single quotes, ampersands, etc., to the mailto body text and keep JavaScript happy?
Mailto is a URI scheme so all of its components must be URI encoded. You can use JavaScript encodeURIComponent function to encode mailto components. Please see the following example:
function buildMailTo(address, subject, body) {
var strMail = 'mailto:' + encodeURIComponent(address)
+ '?subject=' + encodeURIComponent(subject)
+ '&body=' + encodeURIComponent(body);
return strMail;
}
var strTest = buildMailTo('abc#xyz.com', 'Foo&foo', 'Bar\nBar');
/* strTest should be "mailto:abc%40xyz.com?subject=Foo%26foo&body=Bar%0ABar" */
window.open(strTest);
Hope this help.

Categories