Coldfusion cflocation strange behavior - coldfusion

I am storing a google review URL in my database as:
https://www.google.com/search?CFID=ac59cfdf-bbad-4017-9759-e88054f3f242&CFTOKEN=0&q=njcomputerrepair%2Bbrick%2Bnj&oq=njcomp&aqs=chrome.1.69i60j69i59j69i60j69i57j0l2.2762j0j9&sourceid=chrome&ie=UTF-8#lrd=0x89c18348735c2907:0x59aa614832a36b22,3,
And then in my application I set that URL to a variable and I redirect the user to that URL using cflocation.
<cfquery name="geturl" datasource="#datasource#">
select (residential_ReviewURL) as redirectURL
from subscribers
</cfquery>
<!--- Redirect to main html redirect page --->
<cfoutput>
<cflocation url="#getURL.redirectURL#">
</cfoutput>
However the URL gets changed at some point because I think that Coldfusion doesn't like the characters in the URL and it replaces them with % or removes them. Therefore when the user hits the google page, the page doesn't process as it should.
Here is how the URL looks after the redirect:
https://www.google.com/search?CFID=ac59cfdf-bbad-4017-9759-e88054f3f242&CFTOKEN=0&CFID=ac59cfdf-bbad-4017-9759-e88054f3f242&CFTOKEN=0&q=njcomputerrepair%2Bbrick%2Bnj&oq=njcomp&aqs=chrome.1.69i60j69i59j69i60j69i57j0l2.2762j0j9&sourceid=chrome&ie=UTF-8#lrd%3D0x89c18348735c2907%3A0x59aa614832a36b22%2C3%2C
How can I stop ColdFusion from changing the URL and keep id exactly as how it is stored in the database?
UPDATE
So I found that URLdecode will preserve the string. Here is what I have.
#urlDecode(getURL.redirectURL)#
The output is as follows
https://www.google.com/search?CFID=ac59cfdf-bbad-4017-9759-e88054f3f242&CFTOKEN=0&q=njcomputerrepair+brick+nj&oq=njcomp&aqs=chrome.1.69i60j69i59j69i60j69i57j0l2.2762j0j9&sourceid=chrome&ie=UTF-8#lrd=0x89c18348735c2907:0x59aa614832a36b22,3,
Why is it adding CFID and CFTOKEN to the URL though? I have it turned off in my Application.CFM:
<cfapplication name="yaya"
clientmanagement="no"
sessionmanagement="no"
setclientcookies="no"
setdomaincookies="no"
sessiontimeout="#CreateTimeSpan(0,2,0,0)#"
applicationtimeout="#CreateTimeSpan(1,0,0,0)#"
>

To help others coming here:
cflocation have a parameter addToken which needs to set to no if we do not want to add CFID and CFTOKEN to the generated URL.
Adobe CFML reference: https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-j-l/cflocation.html

Related

Why does cflocation strip characters and not visit the URL?

I have a URL stored as:
<cfset VisitURL = 'http://www.toysexample.com/search.aspx?searchBox=christmasgifts≠Sort=high&search=new' />
(The above URL string actually comes from a database field that I have no control over)
When I ask cflocation to visit the above URL like this:
<cflocation url="#EncodeForURL(VisitURL)#" addtoken="no" />
It visits the URL as a subfolder within my site. So I end up going to the URL http://www.volumeoneexample.com/http:/www.toysexample.com/search.aspx?searchBox=christmasgifts≠Sort=high&search=new
As you can see it has dropped one of the forward-slashes from the http:// part and also appended the URL as a folder within my site. I don't get why its doing this?
As mentioned in the comments, you're "over encoding". The EncodeForURL() should only be on the URL parameters.
Since you're not able to retrieve the URL and parameters separately, you might be able to get away with treating them like a list.
<cflocation url="#ListFirst(VisitURL,"?")#?#EncodeForURL(ListRest(VisitURL,"?"))#" />
If things get a little wonky you'll need to do more manipulation than that.

Error using cfhttp to retrieve page contents from bitly url

I am using cfhttp (Lucee Server) to scrape page contents from a url in the following manner:
<cfhttp url="#libs.originalAdPage#" method="GET" />
I then place this content in a div on my page.
This code has been working for a long time.
I have a need to report on the url's that have been scraped for their content and that information is placed into another website form that is not in my control. I decided to convert the url's to shortened bitly url's. I built the process into the page to create a bitly link and return that url to replace the existing url.
If i use the page with a shortened url from linkedin the page is scraped and displayed correctly in the div.
<cfhttp url="http://bit.ly/1NPhPgc" method="GET" />
But if I do an identical cfhttp call to a Indeed.com page shorted to a bitly URL I get a connection failure error.
<cfhttp url="http://bit.ly/1RQvlim" method="GET" />[![cfdump of connection failure][1]][1]
If I open this URL directly in the browser the page is displayed correctly.
Any ideas would be greatly appreciated.
Thanks,
Michael
I don't have access to a Lucee server to test with, however cfhttp on a ColdFusion server works fine for me for both of those bitly URLs. cfhttp follows the redirect and the FileContent contains the indeed.com page as would be expected.
Have you verified what happens with the Bitly Indeed URL if you prevent cfhttp from automatically following the redirects so that you can debug and follow the redirects manually? ie
<cftry>
<cfhttp url="http://bit.ly/1RQvlim" method="GET" redirect="no" />
<cfdump var="#cfhttp.responseHeader#" />
<cfhttp url="#cfhttp.responseHeader.Location#" method="GET" />
<cfdump var="#cfhttp#" label="cfhttp2" />
<cfcatch>
<cfdump var="#cfcatch#" label="cfcatch" />
</cfcatch>
</cftry>
Indeed.com do pay attention to crawlers and user agents - just see their robots.txt for evidence of this.
Do you have access to a different server to test with in case there is something specific to Lucee's cfhttp implementation or to your IP address (eg blacklisted due to all the scraping)?
Have you tried tweaking the cfhttp useragent and/or any other headers as per How to emulate a real http request via cfhttp?

Exempting Coldfusion page from authentication

I need to post from a non-secure CF page to a secure CF page. I don't want to have to go through and implement the user authentication on the page sending the values because its a rather cumbersome process due to the way this legacy site was setup and secondly because the page sending the values is acting as a service between two unrelated order management systems as opposed to a user.
Right now, when I try to post to, the response result is a redirect to the login of the homepage. Is there a way to make an exception for a posting or receiving page from forcing user authentication?
I'm using <cfhttp> to post the values to post page which has a series of <cfparam>'s that I'm passing the values to. Once I pass those values into the post page is when the post page triggers a redirect to the home page because the post page is an internal page in the order management system and is displayed as a client logs in and a session is created for them.
Since you did not provide any code, here is a guess what it might look like and how you could add an exception for specific requests:
<cffunction name="onRequestStart" access="public" output="false" returnType="boolean">
<cfargument name="targetPage" type="string" required="true">
<!--- treat initialized SESSION or matching request token (rtoken) as successful authentication --->
<cfset LOCAL.isAuthenticated = (
isDefined("SESSION.userID")
or
( structKeyExists(FORM, "rtoken") and (FORM["rtoken"] eq "some-secret-only-you-know") )
)>
<cfif LOCAL.isAuthenticated>
<!--- do something... --->
<!--- not authenticated --->
<cfelse>
<!--- redirect to login --->
<cflocation url="login.cfm" statusCode="303" addToken="false">
</cfif>
</cffunction>
Now you could simple add the key-value-pair rtoken=some-secret-only-you-know (i.e. <input type="hidden" name="rtoken" value="some-secret-only-you-know" />) to your POST to bypass the session based authentification.
Disclaimer: Only use this method if the POST parameters (form fields) are not public/editable by the user.
Feel free to provide actual context so I can assist in a more concrete way.
I have written a couple of apps with similar, but not identical requirements. Here is how I handled those requirements in the last one I wrote. All this code is the Application.cfc file in the methods specified.
In onApplicationStart:
application.securityNotNeededPages =
"somePage.cfm,someOtherPage.cfm,someMorePages.cfm";
In onRequestStart
var ThisPage = listlast(cgi.PATH_INFO, "/");
...
if (ListFindNoCase(application.securityNotNeededPages, ThisPage) is false) {
security related code
}
else {
code for when the page does not to be secured
}

URL Rewrite with IIS using ColdFusion

I've done a bit of searching but just can't put it all together. Here's what I need:
I'd like someone to surf to:
www.mysite.com/thisPlace
and have it redirect them to
www.mysite.com/template.cfm?pm=ms&loc_id=4
To do so, I somehow need to capture that they didn't request an existing file in their http request and run a .cfm page that queried the database for a record where locationName = 'thisPlace' and then redirect them to a page like
template.cfm?pm=ms&loc_id=4, where 4 is the record id of the row that matched 'thisPlace'
If your default document in IIS is set to index.cfm you could create a folder (directory) called "thisPlace" and place an index.cfm file that contains nothing but a <cflocation> tag and the accompanying query/logic to figure the URL.
Website.com/thisPlace would then function as you describe.
Edit:
You could add a custom 404 page...
Make it a .cfm file instead of html. Scan the template path to see what the user is looking for. If you find it in your database, redirect them there, else redirect them to a general 404 page.
<!---Up to a certain point (the directory in which you store your code) this will always be the same so you can hard-code your number --->
<cfset QueryConstant = #LEFT(CGI.CF_Template_Path, 22)#>
<!---Find the overall length of the template path. --->
<cfset QueryVariable = #Len(CGI.CF_Template_Path)#>
<!---Take whatever is past your QueryConstant (AKA the string that produces a 404 error.) --->
<cfset theRightNumber = QueryVariable - 22>
<cfset QuerySearchString = #RIGHT(CGI.CF_Template_Path, theRightNumber)#>
<cfquery name="ListOfLocations" datasource="CRM">
SELECT TOP 1 LocationID
FROM LocationTable
WHERE LocationName LIKE '%#QuerySearchString#%'
</cfquery>
<cfif ListOfLocations.recordcount>
<cflocation url="/SomePage.cfm?LocationID=#ListOfLocations.LocationID#">
<cfelse>
<cflocation url="/Regular404page.html">
</cfif>
Thanks guys! Huge help! Using your inputs, here's what I did:
(had to use QUERY_STRING instead of CF_Template_Path, as CF_Template_Path did not pass along anything after the url of the custom error page.
I set up a custom 404 error Execute URL in IIS to a file named check404error.cfm.
When someone looks for www.example.com/thisPlace, IIS sends them to http://www.example.com/check404error.cfm. I use the CGI.QUERY_STRING (404;http://www.example.com:443/thisPlace) to ultimately get the "thisPlace" string to search with.
<!---Up to a certain point (the directory in which you store your code) this will always be the same so you can hard-code your number --->
<cfset QueryConstant = #LEFT(CGI.QUERY_STRING, 31)#>
<!---Find the overall length of the template path. --->
<!---31 is the length of '404;http://www.example.com:443/' --->
<cfset QueryVariable = #Len(CGI.QUERY_STRING)#>
<!---Take whatever is past your QueryConstant (AKA the string that produces a 404 error.) --->
<cfset theRightNumber = QueryVariable - 31>
<cfset QuerySearchString = #RIGHT(CGI.QUERY_STRING, theRightNumber)#>
<cfquery name="ListOfLocations" datasource="#request.dsn#">
SELECT location.id
FROM location WHERE url_name = <cfqueryparam value="#QuerySearchString#" cfsqltype="CF_SQL_VARCHAR" maxlength="255"> LIMIT 1
</cfquery>
<cfif ListOfLocations.recordcount>
<cflocation url="https://example.com/template.cfm?pm=ms&loc_id=#ListOfLocations.id#" addtoken="no" statusCode="301">
<cfelse>
<cflocation url="/404error.cfm" addtoken="no">
</cfif>
This is how most popular MVC Framework work today, by parsing out the URL segments.
Do you have access to any kind of URL rewrite software?
Since you are using IIS it has a built in rewrite engine where you could simply rewrite these kind of requests to a known file saving you the overhead of sending a 404 reply and parsing that out and having more request created as a result of that.
See http://wiki.coldbox.org/wiki/URLMappings.cfm for details. We use the Isapi rewrite version version to do just what you are asking for
Receive request for www.mysite.com/thisPlace
thisPlace isn't a directory
thisPlace isn't a file
Resend to index.cfm or a location of your chosing for additional parsing
Helicon Rewrite sends an HTTP header named HTTP_X_REWRITE_URL with the original requested URL so parsing it out is then very easy.
This all happens inline withing the one request so the client is never redirected.

ColdFusion CFC returning record count

Question: I have a CFM calling my CFC on the cfform action line:
In my CFC, I have output="false". I am needing the record count sent back to my CFM. When I run my CFM and enter the form info my queries are running successfully, but it is not coming back to my CFM so I can display the proper messages. I just get the CFC page with my record count. Any suggestions? Thanks!
Since there's no code, making a few assumptions here about how you're doing things ....
Don't point to the CFC, point to a CFM page in your <cfform>. (If you omit the action, it'll point back to itself.. I like self-referencing form pages)
In your CFC, return the result struct from your query:
<cfquery datasource="#ds#" name="myQuery" result="myResult">
INSERT INTO myTable .....
</cfquery>
Then either return that entire struct, or just myResult.recordCount:
<cfreturn myResult.recordCount>
Then in your CFM page, you'll access it like so (assuming you're using <cfscript>; similar if you're doing tag-based):
recordsAdded = createObject('component','myFolder.myCFC').insertMethod(form);
I changed the cfform line to this:
....rest of my form
then added these lines to see if the form was submitted and what action is:
<!--- create object for cfc --->
But now, my query is not running....