Escape special characters # & ' " in a string in Coldfusion - coldfusion

Following thie topic AngularJS - Special Characters in JSON and Coldfusion Request I have concluded that the problem didn't come from ANGULARJS or my JSON syntax. It's certainly a problem with Coldfusion.
For reminder, I'm trying to use a JSON string for doing an INSERT in a database with ColdFusion. I'm using a function defined in a component for doing that.
My function has the string as argument.
Here an example of the string used:
jsStruct={"LASTNAME":"Nämé","FIRSTN%a£öME":"TestFirstName","PHONENUMBER":48484488,"EMAIL":"tes.test#test.test","COMPANY":"Test & Comp"}
My string is correct and the structure of the JSON is ok.
In my Coldfusion component "component.cfc":
<cffunction name="myfunction" access="remote" returnformat="JSON" output="no">
<cfargument name="jsStruct" type="string" required="true">
<cfset var cfStruct=DeserializeJSON(jsStruct)>
..................
</cffunction>
I obtain this error on the server when I use the string because in my string there is special characters. For instance "COMPANY":"Test & Comp":
JSON parsing failure: Unexpected end of JSON string
The error occurred in ../contacts.cfc: line 267
265 : <cfargument name="jsStruct" type="string" required="true">
266 :
267 : <cfset var cfStruct=DeserializeJSON(jsStruct)>
Could you please help me to solve this problem and prevent (escape) special characters used by ColdFusion and Oracle as &, #, ', " and others?

You say, in error,
My function has the string as argument.
Here an example of the string used:
*jsStruct={"LASTNAME":"Nämé","FIRSTN%a£öME":"TestFirstName","PHONENUMBER":48484488,"EMAIL":"tes.test#test.test","COMPANY":"Test & Comp"}*
You yourself call that a struct, which is correct. It is not a string.
Use something like:
jsonString='{"LASTNAME":"Nämé","FIRSTN%a£öME":"TestFirstName","PHONENUMBER":48484488,"EMAIL":"tes.test#test.test","COMPANY":"Test & Comp"}';

Related

How do you protect css id

I have a value coming in that will ultimately be an html id= attribute. I don't have control over what set the value, so it is possible that it is not safe. I know to check for single quotes and double quotes, but ow do I check to make sure that it clean?
variables.result &= '<div class="alert alert-danger"';
if(attributes.id != "") variables.result &= ' id="#attributes.id#"';
If using ColdFusion to generate the variable name, you could use the "variablise" method of the Inflector CFC. It will convert any string into a safe underscore-separated list that can be used as a ColdFusion variable name. (Inflector is based on the Ruby on Rails ActiveSupport::Inflector class.)
https://github.com/timblair/coldfusion-inflector
<cffunction name="variablise" access="public" returntype="string" output="no" hint="Converts a string to a variable name, e.g. CamelCase becomes camel_case, 'big CSSDogThing' becomes big_css_dog_thing etc.">
<cfargument name="string" type="string" required="yes" hint="The string to variablise">
<cfset arguments.string = replace(trim(rereplace(arguments.string, "([^[:alnum:]_-]+)", " ", "ALL")), " ", "-", "ALL")>
<cfset arguments.string = rereplace(arguments.string, "([A-Z]+)([A-Z][a-z])", "\1_\2", "ALL")>
<cfset arguments.string = rereplace(arguments.string, "([a-z\d])([A-Z])", "\1_\2", "ALL")>
<cfreturn lcase(replace(arguments.string, "-", "_", "ALL"))>
</cffunction>
If I understand you correctly then this might be what you're looking for:
http://code.google.com/p/google-caja/wiki/JsHtmlSanitizer
EDIT: in PHP:
What's the best method for sanitizing user input with PHP?
EDIT2: didn't see you are using coldfusion, maybe this is it:
Cleansing string / input in Coldfusion 9

Skip to sending parameter in ColdFusion REST Service

I was writing a REST component but having difficulties when I do not want to pass argument for a parameter. My code and URL (PATH style) look like this.
Component definition:
<cfcomponent rest="true" restPath="SearchRestAPI">
<cffunction name="restaurantResults" access="remote" httpMethod="get"
output="false" returntype="Query" produces="application/json"
restPath="Search/{city : ([a-zA-Z])*}/{address}/{type}">
<cfargument name="city" default="" type="string" restargsource="path">
<cfargument name="address" default="" type="string" restargsource="path">
<cfargument name="type" default="" type="string" restargsource="path">
Calling URL/Path to consume the REST service. Notice I do not want to send any value for type parameter so there is double slash at the end of the path:
http://localhost:8502/backend/section/SearchResAPI/Search/Calcutta/Lindsay Street//
But this is throwing a "Not Found" error. Any suggestion would be highly appreciated.
I am not sure about this ColdFusion functionality, but looks like "restPath" works with regular expressions (which you are already using when capturing the city parameter
([a-zA-Z])* // your city parameter matches the specified character sets zero or more times.
Similarly to the above, you could try:
restPath="Search/{city : ([a-zA-Z])*}/{address}/{type: ([a-zA-Z])*}"
Here is a ColdFusion page that has some examples as well (search the page for "restPath"):
https://wikidocs.adobe.com/wiki/display/coldfusionen/cfcomponent

ColdFusion 11 Data type preservation during serialization

I recently moved my code from CF9 to CF11 and I am having issues when I am trying to use serializeJSON. According to CF docs:
Starting from ColdFusion 11, the data type is preserved during the
code execution time for Query and CFCs.
SerializeJSON considers datatypes defined in the database for
serialization. If the database defines a column as a string, any
number inserted into the column will still be treated as a string by
SerializeJSON.
But I guess this is not the case....
When I am pulling data out of a varchar column in CF9 it comes out like this "docid":"123" which is what I want but in CF11 the same data look like this "docid":123 and is causing an issue with what I am trying to do.
To be more specific, my ids look like this 2001101009460111385185 which is longer than what javascript can accept and they get converted into scientific notation. With the old format I didn't have this issue because my ids were treated as a string which is what I want.
Note: my code is exactly the same on both versions of CF
Anyone had this issue before and HOW did you go around it?
Code Sample
I am calling this function via an AJAX call, this function returns an array with a struct in it. When I dump the return value after I serialize the result I can see a JSON object in my console but the quotes are missing from all the number values. In a test file I created a simple query and then I am serializing the results and everything looks good......
<cffunction name="locationData" returnformat="json" access="remote">
<cfargument name="locationid" required="yes" type="string">
<cfargument name="clientBrandid" required="yes" type="string">
<cfscript>
locationData = new mod_sigweb.components.xamplifierCFCs.location_info();
result = locationData.getLocation(locationid,clientBrandid);
</cfscript>
<cfdump var="#serializeJSON(result[1],'struct')#">
<cfabort>
<cfreturn #result#>
</cffunction>
The unfortunate workaround that I have had to use for this bug is to concatenate a space to the end of the value
<cfloop index="i" from="1" to="#ArrayLen(result)#">
<cfset result[i].docid = result[i].docid & " "/>
</cfloop>
and then the js has to be aware of this (I know, it's bad) and remove that trailing space.

validating JSON posted to a CFC

I have a CFC (call it proxy.cfc) that I'm using as a proxy for a simple API that I've written. Everything has been going along just fine and a few partners are starting to use the API effectively.
However, one site that is attempting to post data isn't sending valid JSON and I can't seem tho figure how to gracefully handle this error.
A valid JSON string that is posted as a URL param may look like this:
{"apicomponent":"proxyRemoteAdd","apimethod":"add","apiarguments":{"ph_num":1212,"rbpid":999,"ph_exch":555,"state":"HI","address_1":"123 Main Street","address_2":"","rmtid":"PON83","last_name":"Smith","test":1,"zip":999999,"first_name":"Joe","email":"test#test.com","city":"Honolulu","type":"SP","ph_area":995},"apiauthkey":"abc123"}
And that works just fine.
However, if that string is truncated for any reason:
{"apicomponent":"proxyRemoteAdd","apimethod":"add","apiarguments":{"ph_num":1212,"rbpid":999,"ph_exch":555,"state":"HI"
I catch an exception as follows: Exception: JSON parsing failure: Unexpected end of JSON string
This is coming from my onError in Application.cfc. I did add some code to isolate it in Application.cfc as follows:
<cfif ARGUMENTS.EXCEPTION.MESSAGE IS "JSON parsing failure: Unexpected end of JSON string">
<!--- do some stuff here --->
</cfif>
Is that the best way to handle that sort of error? Is there anyway to pass it off to the proxy.cfc file so I can return an error message back to the posting client? As it is now the Application.cfc is catching it and not even letting me get to the proxy.cfc file.
UPDATE - here's some specific code samples. This is how I've been testing and will illustrate how the data gets posted:
<cfhttp url="https://www.domain.com/api/proxy.cfc" method="post" result="httpResult" charset="UTF-8">
<cfhttpparam type="url" name="method" value="apiauth"/>
<cfhttpparam type="url" name="argumentCollection" value="#jsData#"/>
</cfhttp>
"apiauth" is the method in the CFC that acts as the authorization and proxy.
The argument collection is a JSON string as shown below. It lists a component (a different CFC), the method in that component, the authkey of the user accessing the AP, and then a JSON string called apiarguments which contains the arguments and data that get passed to the apicomponent listed.
The proxy CFC file looks like this:
<cffunction name="apiauth" access="remote" returntype="any" output="false" returnFormat="JSON">
<cfargument name="apicomponent" required="yes" type="string"/>
<cfargument name="apimethod" required="yes" type="string"/>
<cfargument name="apiauthkey" required="yes" type="string"/>
<cfargument name="apiarguments" required="yes" type="struct"/>
<cfset var LOCAL = {}/>
<cfif not isDefined("ARGUMENTS.apiauthkey")>
<cfreturn THIS.NewErrorResponse("Error 401 Malformed Request.") />
</cfif>
<cfif not isDefined("ARGUMENTS.apicomponent")>
<cfreturn THIS.NewErrorResponse("Error 402 Malformed Request.") />
</cfif>
<cfif not isDefined("ARGUMENTS.apimethod")>
<cfreturn THIS.NewErrorResponse("Error 403 Malformed Request.") />
</cfif>
<cfset LOCAL.checkpwResult = FALSE/>
<cfset LOCAL.apicomponent = ARGUMENTS.apicomponent />
<cfset LOCAL.apimethod = ARGUMENTS.apimethod />
At this point some other CFCs are access to check the API key and user ID # to make sure they can access the API. If everything checks out there the data gets passed off to the correct component/method:
<cfinvoke component="#LOCAL.apicomponent#" method="#LOCAL.apimethod#" argumentcollection="#apiarguments#" returnvariable="LOCAL.Response.Data"/>
However the JSON exception is being thrown before this CFC can even be accessed by the Application.cfc file. If I drop a quick cfmail in proxy.cfc to just dump and mail the arguments it doesn't even hit that.
Here's a chunk of the stack trace:
coldfusion.runtime.JSONUtils$JSONParseOverflowException: JSON parsing failure: Unexpected end of JSON string at
coldfusion.runtime.JSONUtils$ParserState.incrementOffset(JSONUtils.java:1999) at coldfusion.runtime.JSONUtils$ParserState.incrementOffset(JSONUtils.java:1980) at coldfusion.runtime.JSONUtils.parseString(JSONUtils.java:1385) at coldfusion.runtime.JSONUtils.parseObject(JSONUtils.java:1074) at coldfusion.runtime.JSONUtils.parseStruct(JSONUtils.java:1178) at coldfusion.runtime.JSONUtils.parseObject(JSONUtils.java:1059) at coldfusion.runtime.JSONUtils.parseStruct(JSONUtils.java:1178) at coldfusion.runtime.JSONUtils.parseObject(JSONUtils.java:1059) at coldfusion.runtime.JSONUtils.parseJSON(JSONUtils.java:1028) at coldfusion.runtime.JSONUtils.deserializeJSON(JSONUtils.java:168) at coldfusion.runtime.JSONUtils.deserializeJSON(JSONUtils.java:128) at coldfusion.filter.FilterUtils.GetArgumentCollection(FilterUtils.java:50) at coldfusion.filter.ComponentFilter.invoke(ComponentFilter.java:193) at coldfusion.filter.ApplicationFilter.invoke(ApplicationFilter.java:442) at coldfusion.filter.RequestMonitorFilter.invoke(RequestMonitorFilter.java:48) at coldfusion.filter.MonitoringFilter.invoke(MonitoringFilter.java:40)
coldfusion.filter.PathFilter.invoke(PathFilter.java:112) at coldfusion.filter.ExceptionFilter.invoke(ExceptionFilter.java:94) at coldfusion.filter.ClientScopePersistenceFilter.invoke(ClientScopePersistenceFilter.java:28) at coldfusion.filter.BrowserFilter.invoke(BrowserFilter.java:38) at coldfusion.filter.NoCacheFilter.invoke(NoCacheFilter.java:58) at coldfusion.filter.GlobalsFilter.invoke(GlobalsFilter.java:38) at coldfusion.filter.DatasourceFilter.invoke(DatasourceFilter.java:22) at coldfusion.xml.rpc.CFCServlet.invoke(CFCServlet.java:155) at coldfusion.xml.rpc.CFCServlet.doPost(CFCServlet.java:331) at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) at
If your argument is always a JSON string, you should be able to change the argument type to string, and pass it in that way (it will make it through Application.cfc) and then validate it within your apiAuth function using isJSON() - you should be validating it against malicious JSON anyways, so it won't be much code to initially check against isJSON(). This way, your API will give meaningful feedback and keep all the code where it should be.
However if you have other users passing an actual struct into your method, that won't work.
And you will definitely want to find out why the JSON string is being truncated. At a guess I would suggest there might be some un-escaped characters being passed in which is truncating the string early...

Coldfusion date conversion: "2013-11-15T06:11:57.87 is an invalid date or time string"

I am trying to convert a date from UTC to local and I am getting the following error:
"2013-11-15T06:11:57.87 is an invalid date or time string"
Here is the partial code:
#DateFormat(DateConvert("utc2Local", apiResult.Created), 'm/d/yy')#
As you have guessed apiResult.Created is 2013-11-15T06:11:57.87
Any ideas?
Thank you
Your problem seems to be that the string 2013-11-15T06:11:57.87 is not a recognised date string format. You're probably going to have to parse it yourself. I found this example for twitter dates which you could probably modify to your needs:
<cffunction name="parseTwitterDateFormat" output="false" returntype="String" hint="I return the date in a useable date format.">
<cfargument name="twitterDate" required="true" type="string" hint="The Twitter date." />
<cfset var formatter = CreateObject("java", "java.text.SimpleDateFormat").init("EEE MMM d kk:mm:ss Z yyyy") />
<cfset formatter.setLenient(true) />
<cfreturn formatter.parse(arguments.twitterDate) />
</cffunction>
More info: http://www.petefreitag.com/item/569.cfm
Java Documentation for SimpleDateFormat: http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html
Based on the Java documentation I think you need the format string: "yyyy-MM-dd'T'HH:mm:ss.SS"
Note that I did read a comment stating the SimpleDateFormat class converts the time to local time, you may want to check this.