I have a tricky one.
By means of a <cfoutput query="…"> I list some records in the page from a SQL Server database.
By the end of each line viewing I try to add this in to a record in a MySQL database.
As you see is simple, because I can use the exact variables from the output query in to my new INSERT INTO statement.
BUT: the rsPick.name comes from a database with a different character set and the only way to get it right into my new database is to read it from the web page and not from the value came in the output query.
So I read this value with that little JavaScript I made and put it in the myValue variable and then I want ColdFusion to read that variable in order to place it in my SQL statement.
<cfoutput query="rsPick">
<tr>
<td>#rsPick.ABBREVIATION#</td>
<td id="square"> #rsPick.name# </td>
<td>#rsPick.Composition#</td>
<td> Transaction done...
<script type="text/javascript">
var myvalue = document.getElementById("square").innerHTML
</script>
</td>
<cfquery datasource="#Request.Order#">
INSERT INTO products (iniid, abbreviation, clsid, cllid, dfsid, dflid, szsid, szlid, gross, retail, netvaluebc, composition, name)
VALUES ( #rsPick.ID#, '#rsPick.ABBREVIATION#', #rsPick.CLSID#, #rsPick.CLLID#, #rsPick.DFSID#, #rsPick.DFLID#, #rsPick.SZSID#, #rsPick.SZLID#, #rsPick.GROSSPRICE#, #rsPick.RETAILPRICE#, #rsPick.NETVALUEBC#, '#rsPick.COMPOSITION#','#MYVALUE#' )
</cfquery>
</tr>
</cfoutput>
ColdFusion is processed on the server before the page is served. JavaScript is processed in the browser after the page is served. Therefore, the only way for JavaScript to serve a value to ColdFusion is either:
a) Set the variable to a form field and then post the page back to the server.
b) Send the variable back to Coldfusion via Ajax.
I think there is a safer and more reliable way to do what you need without the JavaScript.
If you are creating the page you would know what is in the DOM element "square" because you put it there. If you are doing this based on the dynamic input of the user then you would need to use a CFAJAXPROXY or simply a form post to a different page for doing the insert.
Also it's frightening to take unsanitized input from a DOM and insert into a database. Use cfqueryparam to protect against injection attacks.
Your misconception starts with this thought:
"The only way to get it right is to read the value from a web page via JavaScript."
Sorry if this sounds harsh now, but this is complete nonsense. Forget that idea. It is neither possible to read a JavaScript variable from ColdFusion the way you try it, nor is it even necessary.
For starters, I'm not sure why it must be via ColdFusion that you move values from one database to another. Database servers are perfectly able to talk directly to each other, for example via the "Linked Server" feature in MS SQL Server (see this howto).
If it must be ColdFusion, try this:
<cfoutput query="rsPick">
<cfquery datasource="#Request.Order#">
INSERT INTO products (
iniid,
/* … etc … */
name
)
VALUES (
<cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#rsPick.ID#">,
/* … etc … */
<cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#rsPick.name#">
)
</cfquery>
</cfoutput>
As long as the table data types and database connections to both databases are set up correctly, ColdFusion will handle the character encoding transparently. Note that the target DB fields should not be "less capable" than the source fields, e.g. the source should not be Unicode when the target is US ASCII.
Well, your question is really this: How do I take a string from one character encoding to another in ColdFusion?
Can you use the NVARCHAR type in SQL Server (not sure what the same thing in MySQL is) - and just store the character data as UTF8?
Also, Java is perfectly capable of dealing with the different encodings, and even provides help in the String class and the CharsetDecoder class to deal with different encodings:
String s = new String("Hello, World!");
byte[] bytes = s.getBytes("UTF-8");
String utf = new String(bytes, "UTF-8");
ColdFusion has very limited support for dealing with multiple character sets in a single request. You are almost certainly going to have to rely on the underlying Java classes to solve this problem inside of ColdFusion.
So, if you wanna to convert JS value to CFM, I feel a few steps need to do:
first of all, assign your JS value into input via javascript. after that, retrieve value from this input by submitting form.
Use JSString to convert Javascript variable to CFML variable.
<cfoutput>
var #toScript(myCFMLVaraible, "jsVar")#;
</cfoutput>
Related
this is my HTML
<div id="remove">Username</div>
and this is my JS code
function slice() {
var t = document.getElementById("remove");
t.textContent = t.textContent.slice(0, -3);
}
slice();
Username load from foreach
{foreach from=$last_user item=s}
{$s.date}
{$s.username}
{/foreach}
This code working and remove 3 letter but when right click on browser and look at page sources i can see "Username" !
I need remove three letter because of privacy and security .
something like
*** name or usern ***
Thank for help me !
The only secure way to make sure the client can't see a particular piece of information is to never send it to the client in the first place. Otherwise, there will always be a way for the client to examine the raw payloads of the network requests and figure out the information they aren't supposed to know.
You'll need to fix this on your backend - either hard-code in
<div id="remove">Usern</div>
or, for a more dynamic approach, use a template engine (or whatever's generating the HTML) and look up how to change strings with it. For example, in EJS, if user is an object with a username property, you could do
<div id="remove"><%= user.username.slice(0, -3) %></div>
Changing the content only with client-side JavaScript will not be sufficient, if you wish to keep some things truly private.
With Smarty, you can define a modifier that takes a string and returns all but the last three characters of it.
function smarty_modifier_truncate_three($string)
{
return substr($string, 0, -3);
}
and then in your template, replace
{$s.username}
with
{$s.username|truncate_three}
If you want only the first three characters, it's easier because you can use the built-in truncate.
{$s.username|truncate:3}
JS doesn't change the source, it can only change the DOM, so what you can do is to keep the element empty and add a value to it using js, but don't forget that js runs on the client's side so its better here to send the string from the server without the last 3 characters.
I have a form in JSP. I have to populate it based on the request object (from the servlet). How do I use Java Script for accessing request object attributes or if you can suggest me any other better way to populate form dynamically?
You need to realize that Java/JSP is merely a HTML/CSS/JS code producer. So all you need to do is to just let JSP print the Java variable as if it is a JavaScript variable and that the generated HTML/JS code output is syntactically valid.
Provided that the Java variable is available in the EL scope by ${foo}, here are several examples how to print it:
<script>var foo = '${foo}';</script>
<script>someFunction('${foo}');</script>
<div onclick="someFunction('${foo}')">...</div>
Imagine that the Java variable has the value "bar", then JSP will ultimately generate this HTML which you can verify by rightclick, View Source in the webbrowser:
<script>var foo = 'bar';</script>
<script>someFunction('bar');</script>
<div onclick="someFunction('bar')">...</div>
Do note that those singlequotes are thus mandatory in order to represent a string typed variable in JS. If you have used var foo = ${foo}; instead, then it would print var foo = bar;, which may end up in "bar is undefined" errors in when you attempt to access it further down in JS code (you can see JS errors in JS console of browser's web developer toolset which you can open by pressing F12 in Chrome/FireFox23+/IE9+). Also note that if the variable represents a number or a boolean, which doesn't need to be quoted, then it will just work fine.
If the variable happens to originate from user-controlled input, then keep in mind to take into account XSS attack holes and JS escaping. Near the bottom of our EL wiki page you can find an example how to create a custom EL function which escapes a Java variable for safe usage in JS.
If the variable is a bit more complex, e.g. a Java bean, or a list thereof, or a map, then you can use one of the many available JSON libraries to convert the Java object to a JSON string. Here's an example assuming Gson.
String someObjectAsJson = new Gson().toJson(someObject);
Note that this way you don't need to print it as a quoted string anymore.
<script>var foo = ${someObjectAsJson};</script>
See also:
Our JSP wiki page - see the chapter "JavaScript".
How to escape JavaScript in JSP?
Call Servlet and invoke Java code from JavaScript along with parameters
How to use Servlets and Ajax?
If you're pre-populating the form fields based on parameters in the HTTP request, then why not simply do this on the server side in your JSP... rather than on the client side with JavaScript? In the JSP it would look vaguely like this:
<input type="text" name="myFormField1" value="<%= request.getParameter("value1"); %>"/>
On the client side, JavaScript doesn't really have the concept of a "request object". You pretty much have to parse the query string yourself manually to get at the CGI parameters. I suspect that isn't what you're actually wanting to do.
Passing JSON from JSP to Javascript.
I came here looking for this, #BalusC's answer helped to an extent but didn't solve the problem to the core. After digging deep into <script> tag, I came across this solution.
<script id="jsonData" type="application/json">${jsonFromJava}</script>
and in the JS:
var fetchedJson = JSON.parse(document.getElementById('jsonData').textContent);
In JSP file:
<head>
...
<%# page import="com.common.Constants" %>
...
</head>
<script type="text/javascript">
var constant = "<%=Constants.CONSTANT%>"
</script>
This constant variable will be then available to .js files that are declared after the above code.
Constants.java is a java file containing a static constant named CONSTANT.
The scenario that I had was, I needed one constant from a property file, so instead of constructing a property file for javascript, I did this.
In JSP page :
<c:set var="list_size" value="${list1.size() }"></c:set>
Access this value in Javascipt page using :
var list_size = parseInt($('#list_size').val());
I added javascript page in my project externally.
I have a ColdFusion form and set a field value by copying it from another form with the Javascript below. (This is actually from a popup input window where you can paste large texts).
form1.remark.value = form2.remark.value;
After this happens, form1 is submitted for further processing by another process.cfm page.
The problem is the remark.value contains complex text, including XML, but it is encoded when it arrives at the process.cfm page. I'm looking for a way to correctly encode it in the Javascript portion and then decode it at process.cfm using ColdFusion code so that I get back the original text, including XML tags.
How is this best accomplished?
If you're trying to use the value of the submitted form field as the value of a JavaScript variable on the next page, then you need to use the built-in (as of ColdFusion 10) function encodeForJavaScript.
<cfoutput>var myJSvar = '#encodeForJavaScript(form.myField)#';</cfoutput>
This will properly escape the string value of form.myField, so that it can be used with JavaScript.
If you're on CF 8 or 9, the OWASP JAR file is loaded into CF (if you're patched up correctly), and you can access the same functions directly by instantiating the correct Java class.
<cfset application.xssEncoder = createObject("java", "org.owasp.esapi.esapi").encoder() />
<cfoutput>
var myJSvar = '#application.xssEncoder.encodeForJavaScript(form.myField)#';
</cfoutput>
I think you can use StringEscapeUtils class of java like this:
<cfset objEscapeUtil = createObject("java", "org.apache.commons.lang.StringEscapeUtils")>
<cfset unescapedString = objEscapeUtil.unescapeJavaScript(escapedString)>
So I'm currently using CF11 and CFWheels 1.1, the "Global Script Protection"(GSP) server feature does an awful job of covering the XSS bases. I would like to extend it to block any and all tags/vectors for JS from being inserted into the database.
CF11 offers antiSamy protection via the getSafeHTML() function which applies a xml policy file specified in application.cfc but I would still need to modify every single varchar cfqueryparam in the application to use it right?
Is there a way to get CF11 to enable the antisamy features server or application wide in a similar way that the GSP feature works? What I mean by this is GSP automatically strips tags out of input submitted to the app without having to modify all the queries/form actions. I'd like a way to apply the antisamy policy file or getSafeHTML() in the same way.
Thanks!
Why would you have to apply it to every one? You would only need to do it for string (varchar) inputs and only when inserting. And even then, you wouldn't use it everywhere. For example, if you ask for my name and bio, there is no reason why you would want html, even "good" html, in my name. So I'm sure you already use something there to escape all html or simply remove it all. Only for a field like bio would you use getSafeHTML.
Validation is work. You (typically) don't want a "all at once" solution imo. Just bite the bullet and do it.
If you did want to do it, you can use onRequestStart to automatically process all keys in the form and url scope. This is written by memory so it may have typos, but here is an example:
function onRequestStart(string req) {
for(var key in form) { form[key] = getSafeHTML(form[key]); }
for(var key in url) { url[key] = getSafeHTML(url[key]); }
}
I agree with Ray, validation is work, and it is very important work. If you could have a server wide setting it would be way to generalized to fit all situations. When you do your own validation for specific fields you can really narrow down the attack surface. For example, assume you have a form with three fields; name, credit card number, social security number. With one server wide setting it would need to be general enough to allow all three types of input. With your own validation you can be very specific for each field and only allow a certain set of characters; name - only allows alpha characters and space, credit card number - only allows digits, space, dash and must conform to the mod rule, social security number - only allows digits and dash in 3-2-4 format. Nothing else is allowed.
That being said, I just wanted to point out that the "Global Script Protection" rules can be customized. That setting works by applying a regular expression that is defined in the cf_root/lib/neo-security.xml file in the server configuration, or the cf_root/WEB-INF/cfusion/lib/neo-security.xml file in the JEE configuration to the variable value. You can customize the patterns that ColdFusion replaces by modifying the regular expression in the CrossSiteScriptPatterns variable.
The default regular expression is defined as:
<var name='CrossSiteScriptPatterns'>
<struct type='coldfusion.server.ConfigMap'>
<var name='<\s*(object|embed|script|applet|meta)'>
<string><InvalidTag</string>
</var>
</struct>
</var>
Which means, by default, the Global Script Protection mechanism is only looking for strings containing <object or <embed or <script or <applet or <meta and replacing them with <InvalidTag. You can enhance that regular expression to look for more cases if you want.
See Protecting variables from cross-site scripting attacks section on this page
The solution as implemented for a cfwheels 1.1 app:
I used the slashdot file from https://code.google.com/p/owaspantisamy/downloads/list
This goes in application.cfc:
<cfcomponent output="false">
<cfset this.security.antisamypolicy="antisamy-slashdot-1.4.4.xml">
<cfinclude template="wheels/functions.cfm">
</cfcomponent>
This goes in the /ProjectRoot/events/onrequeststart.cfm file
function xssProtection(){
var CFversion = ListToArray(SERVER.ColdFusion.productversion);
if(CFversion[1]GTE 11){
for(var key in form) {
if(not IsJSON(form[key])){
form[key] = getSafeHTML(form[key]);
}
}
for(var key in url) {
if(not IsJSON(url[key])){
url[key] = getSafeHTML(url[key]);
}
}
}
}
xssProtection();
I run into this problem constantly while developing AJAX applications. Let's say I want users to be able to click on a "flag" icon associated with each comment on my site, which results in an AJAX request being sent to the server, requesting that the comment be flagged. I need to associate a comment id with the comment on the client side so that the AJAX request may communicate to the server which comment to flag.
This page explains a number of ways to annotate HTML in this manner, but none of them are very satisfactory. While I could just use an id or class attribute to associate the comment id with the flag button (e.g. id="comment_1998221"), this fails with more complex data that doesn't fit well into those attributes (e.g. arbitrary strings). Is there a best practice for this sort of thing? Every time I need to do this, I end up with some kludge like using the id attribute, a hidden form field, or worse yet a span set to display:none.
The HTML5 data-* attributes seem like a perfect solution, but I've seen a lot of animosity toward them, which makes me think that people must already have a solution they're happy with. I'd love to know what it is.
This page explains a number of ways to annotate HTML in this manner, but none of them are very satisfactory.
Still, they are pretty much all you've got. Although that page isn't a terribly good summary, there are errors and it misunderstands what ‘unobtrusive’ JavaScript means.
For example it is in fact perfectly valid to put a script element inside body — just not directly inside a table element. You could put all the script fragments at the bottom of the table, or put each row in its own table, or even, with some limitations if you are intending to mutate the DOM, inside the row in question.
Setting “id="comment-123"” then scanning for all rows with an id starting with ‘comment-’ is indeed good for your particular case. For setting non-identifying extra info attributes, you could use either HTML5 data-attributes or hack it into the classname using eg. “class="comment type-foo data-bar"”. Of course both IDs and classnames have their limits about what characters you can use, but it's possible to encode any string down to valid strings. For example, you could use a custom URL-style encoding to hide non-alphanumeric characters:
<tr class="greeting-Hello_21_20_E2_98_BA">
...
</tr>
function getClassAttr(el, name) {
var prefix= name+'-';
var classes= el.className.split(' ');
for (var i= classes.length; i-->0;) {
if (classes[i].substring(0, prefix.length)==prefix) {
var value= classes[i].substring(prefix.length);
return decodeURIComponent(value.split('_').join('%'));
}
}
return null;
}
var greeting= getClassAttr(tr, 'greeting'); // "Hello! ☺"
You can even store complex non-string values in this way, by encoding them JavaScript or JSON strings then retrieving them using exec (or JSON.parse where available).
However, if you are putting anything non-trivial in there it soon gets messy. That's where you may prefer comments. You can fit anything in here except the sequence '--', which is easily escaped if it happens to come up in a string.
<table>
<tr class="comment">
<td>...</td>
<!-- {"id": 123, "user": 456} -->
</tr>
</table>
function getLastComment(node) {
var results= [];
for (var i= node.childNodes.length; i-->0;)
if (node.childNodes[i]==8)
return node.childNodes[i];
return null;
}
var user= getLastComment(tr).user;
The summary warns that this may not be guaranteed to work because XML parsers may discard comments, but then DOM Level 3 LS parsers must keep them by default, and every browser and major XML library so far does.
jQuery data API is nice for this.
Suppose you have the following DOM...
<div class="comment">
Flag
Some text
</div>
Then, assuming you are also loading these elements by ajax, you can do
$(".comment").data('someKey', (any javascript value/object));
Then later, upon click handler to the flag, you can do...
$(".flagSelector").click(function(ev) {
var extraData = $(this).closest(".comment").data("someKey");
// use extraData along with your request
});
If you are generating the comments on the server side and shipping them with the initial page, you need to figure out how to initialize the data. One way would be to have unique ID-s for the comment and upon pageload, still load the custom data from the server by Ajax.
Here is how I would do this:
When rendering the page server-side, generate the flag link as a normal link, so that it would work fine if you didn't have javascript enabled.
<a class="flag_link" href="/comment/123/flag/"><img src="flag.gif" /></a>
Then, in the javascript, add a click event to do this by ajax instead. I'll use jQuery for my example, but the same thing is not hard to do without it.
<script>
$('a.flag_link').click(function() {
$.get($(this).attr('href'), function() {
alert('you flagged this comment');
});
});
</script>
Of course, you'll do something more user-friendly than an alert to signal success.