I am making a cfhttp get call to another page. I am passing the url variable using cfhttpparam as shown below. But when I run the page, the url is rendered as shown in the image. I need to replace %25 to be able to get the correct url string. Can someone tell me what is wrong with the code?
<cfset vpName = "Abc def F hig K xyz" /> I want %20 in the spaces in the name here. But it is rending as show in the image![enter image description here][1]
<cfset urlvar = URLEncodedFormat("#vpName#")>
<!--- <cfoutput>#urlvar#</cfoutput>
--->
<cfhttp url="https://abc.com/xyz/EM2/LTMR.cfm" method="get" username="abcd" password="password" >
<cfhttpparam type="url" name="LTMX" value="#urlvar#">
</cfhttp>
<cfset myDocument = cfhttp.fileContent>
<cfoutput>#myDocument#</cfoutput>
URL is rendered as
abc.com/LTMR.cfm?LTMX=Andre%2520Fuetsch%2520%2520F%2520Shelly%2520K%2520Lazzaro
The %25 is what the "URLEncodedformat()" is supposed to do - replace spaces (etc) with the appropriate encoded sequence - and as Peter said the <cfhttpparam> does this automatically - so you should change this;
<cfset urlvar = URLEncodedFormat("#vpName#")>
to be this...
<cfset urlvar = vpName/>
Although you could of course simply pass in the vpName instead of creating a completely separate variable for it.
Related
I'm using <cfhttp> to pull in content from another site (coldfusion) and resolveurl="true" so all the links work. The problem I'm having is resolveurl is making the anchor links (href="#search") absolute links as well breaking them. My question is is there a way to make resolveurl="true" bypass anchor links somehow?
For starters, let's use the tutorial code from Adobe.com posted in the comments. You'll want to do something similar.
<cfhttp url="https://www.adobe.com"
method="get" result="httpResp" timeout="120">
<cfhttpparam type="header" name="Content-Type" value="application/json" />
</cfhttp>
<cfscript>
// Find all the URLs in a web page retrieved via cfhttp
// The search is case sensitive
result = REMatch("https?://([-\w\.]+)+(:\d+)?(/([\w/_\.]*(\?\S+)?)?)?", httpResp.Filecontent);
</cfscript>
<!-- Now, Loop through those URLs--->
<cfoutput>
<cfloop array="#result#" item="item" index="index">
<cfif LEFT(item, 1) is "##">
<!---Your logic if it's just an anchor--->
<cfelse>
<!---Your logic if it's a full link--->
</cfif>
<br/>
</cfloop>
</cfoutput>
If it tries to return a full URL before the anchor as you say, (I've been getting inconsistent results with resolveurl="true") hit it with this to only grab the bit you want.
<cfoutput>
<cfloop array="#result#" item="item" index="index">
#ListLast(item, "##")#
</cfloop>
</cfoutput>
What this code does is grab all the URLs, and parse them for anchors.
You'll have to decide what to do next inside your loop. Maybe preserve the values and add them to a new array, so you can save it somewhere with the links fixed?
It's impossible to assume in a situation like this.
There does not appear to be a way to prevent CF from resolving the hashes. In our usage of it the current result is actually beneficial since when we present content from another site we usually want the user to be sent there.
Here is a way to replace link href values with just anchor if one is present using regular expressions. I'm sure there are combinations of issues that could occur here if really malformed html.
<cfsavecontent variable="testcontent">
<strong>test</strong>
go to google
go to section
</cfsavecontent>
<cfset domain = replace("current.domain", ".", "\.", "all") />
<cfset match = "(href\s*=\s*(""|'))\s*(http://#domain#[^##'""]+)(##[^##'""]+)\s*(""|')" />
<cfset result = reReplaceNoCase(testcontent, match, "\1\4\6", "all") />
<cfoutput><pre>#encodeForHTML(result)#</pre></cfoutput>
Output
<strong>test</strong>
go to google
<a href="#section>go to section</a>
Another option if you are displaying the content in a normal page with js/jquery available is to run through each link on display and update it to just be the anchor. This will be less likely error with malformed html. Let me know if you have any interest in that approach.
I am trying to implement the OAuth with Dropbox from a ColdFusion application, and I managed how to call the Dropbox method to generate the access token, but... I don't know how to get the generated TOKEN from the response URI. I am getting something like this from Dropbox:
http://localhost/dropbox/generate_token.cfm#access_token=AAAAAAAAYVM_XdCYlbTz0gQOwQkWlg6TDXf84_5h4giikg6J-7Man&token_type=bearer&uid=267693&account_id=dbid%3AAABeDMm-BN0n1DofLZz9kPZAipnQ
How to I retrieve the URL variables in this case? I mean if I do a
<cfdump var="#URL#">
I am getting an empty struct. If I do a
<cfdump var="#CGI#">
I still don't see any of the URL retrieved parameters in the structure. How do I get the variables and their values from the Dropbox response?
UPDATED
At some point I thought I found a way to read the URL but now - for no reason - this doesn't work anymore! I didn't change anything but the solution below doesn't work anymore.
I can read the full URL with JavaScript using document.location but this means to do an extra submit to a ColdFusion page and I don't want to do this. I want to get the Dropbox token from the URL and save it to the database directly in this page...
Any new ideas please?
SOLUTION THAT SEEMED TO WORK AT SOME POINT ...
I found a way to get the URI string using this:
<cfset objRequest = GetPageContext().GetRequest().getParameterMap() />
<cfdump var="#objRequest#">
<cfoutput>
<cfloop collection="#objRequest#" item="i">
<p>
#i# - #objRequest[i][1]#
</p>
</cfloop>
</cfoutput>
From now on, I know how to get the values returned by Dropbox.
I found a way to get the returned parameters by reading the browser URL with JavaScript, so in two steps: first, parse and extract the full URL including the part after the # sign (I found this has a name and it is called the "URL fragment") and second, create a JavaScript form with parsed parameters and resubmitted to the server. Here is the code:
<cfparam name="FORM.action" default="">
<cfif FORM.action IS "save_token">
<cfdump var="#FORM#">
<cfelse>
<form name="main" id="main" method="post">
<input type="hidden" name="action" id="action" value="save_token">
</form>
<script type="text/javascript" language="javascript">
<!--
var parameters = window.location.hash.substr(1).split("&");
function addHidden(theForm, key, value) {
// Create a hidden input element, and append it to the form:
var input = document.createElement("input");
input.type = "hidden";
input.name = key;
input.value = value;
theForm.appendChild(input);
}
// Form reference:
var theForm = document.forms["main"];
for (var i=0; i<parameters.length; i++) {
// Add data:
addHidden(theForm, parameters[i].split("=")[0], parameters[i].split("=")[1]);
}
theForm.submit();
//-->
</script>
</cfif>
If I run the following code to get an image from Medium's site:
<cfhttp url="https://cdn-images-1.medium.com/max/600/1*3j1McX-y1rvKewzI2gWc_w.png"
method="get" useragent="#CGI.http_user_agent#" getasbinary="yes">
I then want to save the image with the same name that they used i.e. 1*3j1McX-y1rvKewzI2gWc_w.png.
How can I get the name of the file from the cfhttp request? I looked in the cfhttp.header for any sign of the content-disposition attribute but can't find it.
Assuming you are getting these URLs dynamically, why not just parse it for the filename first, then apply that to the filename attribute?
<cfset filename1 = ListLast("https://cdn-images-1.medium.com/max/600/1*3j1McX-y1rvKewzI2gWc_w.png","/") />
<cfhttp url="https://cdn-images-1.medium.com/max/600/1*3j1McX-y1rvKewzI2gWc_w.png"
method="get" useragent="#CGI.http_user_agent#" getasbinary="yes" path="whateverpath" filename="#filename1#>
I'm running Coldfusion8 and am uploading files to Amazon S3.
When displaying images, I want to check whether an image is available from S3 and if not show a fallback image. My problem is, don't know how to check for existing images.
If I list the link to an image, it's something like this:
http://s3.amazonaws.com/bucket/l_138a.jpg?AWSAccessKeyId=_key_&Expires=_exp_&Signature=_signature_
I'm trying to check for existing files like this:
<cfif fileExists("http://s3.amazonaws.com/bucket/s_" & items.filename)>
<cfdump output="e:\website\test\dump.txt" label="catch" var="found!!!">
</cfif>
Question:
Do I always have to provide accesskey, expires and signature when checking for an image? If I enter the image path without credentials in the browser, the image is loaded, so I don't understand why my fileExist is not working. Any idea?
You could use cfhttp if you have a site-wide page not found message set up.
<cfhttp url="http://a.espncdn.com/photo/2012/0813/nfl_u_flynn1x_203.jpg" method="head">
<cfdump var="#cfhttp.filecontent#">
returns object of java.io.ByteArrayOutputStream
<cfhttp url="http://a.espncdn.com/photo/20notanimage3.jpg" method="head">
<cfdump var="#cfhttp.filecontent#">
returns <html> <body> <h1>Error Processing Request</h1> </body> </html>
Can also check the statuscode returned by the server
<cfhttp url="http://a.file.exists.gif" method="head">
<cfdump var="#val(cfhttp.statuscode)#">
200 is ok, 404 is not found, etc
I've used the getObjectInfo method in the S3.cfc to see if an object exists:
<cffunction name="getObjectInfo" access="public" output="false" returntype="string"
description="Creates a bucket.">
<cfargument name="bucketName" type="string" required="yes">
<cfargument name="filekey" type="string" required="true" hint="" />
<cfset var data = "">
<cfset var content = "">
<cfset var contents = "">
<cfset var thisContent = "">
<cfset var allContents = "">
<cfset var dateTimeString = GetHTTPTimeString(Now())>
<!--- Create a canonical string to send --->
<cfset var cs = "HEAD\n\n\n#dateTimeString#\n/#arguments.bucketName#/#Arguments.filekey#">
<!--- Create a proper signature --->
<cfset var signature = createSignature(cs)>
<!--- get the bucket via REST --->
<cfhttp method="HEAD" url="http://s3.amazonaws.com/#arguments.bucketName#/#Arguments.filekey#">
<cfhttpparam type="header" name="Date" value="#dateTimeString#">
<cfhttpparam type="header" name="Authorization" value="AWS #variables.accessKeyId#:#signature#">
</cfhttp>
<cfreturn cfhttp.StatusCode />
</cffunction>
If I get a 200 status back, then I know the object exists.
I haven't used Coldfusion for a long time, but I did a quick lookup and the fileExists method seems to be for filesystem lookups, not remote URLs.
There are other Coldfusion methods for requesting URLs. One forum discussion on the subject I just quickly found is here: http://forums.adobe.com/thread/765614
But, assuming you're generating HTML to be consumed by a web browser I would suggest doing an image check / fallback in HTML/CSS/JS rather than server side. You could do this with CSS background-image tricks, or directly load and check images with JS. One question dealing with this that I found is here (there are probably a bunch of similar questions on this stuff): Inputting a default image in case the src attribute of an html <img> is not valid?
CF9 +
<cfscript>
FileExists('s3://#accessKey#:#secretKey##[your bucket]/[your file]');
</cfscript>
I'm doing some web scraping with ColdFusion and mostly everything is working fine. The only other issues I'm getting is that some URL's come through with text behind them that is now causing errors.
Not sure what's causing it, but it's probably my regex. Anyhow, there's a distinct pattern where text appears before the "http://". I'd like to simply remove everything before it.
Any chance you could help?
Take this string for example:
"I'M OBSESSED WITH MY BEAUTIFUL FRIEND" src="http://scs.viceland.com/feed/images/uk_970014338_300.jpg
I'd much appreciate your help as regex isn't something I've managed to make time for - hopefully I will some day!
Thanks.
EDIT:
Hi,
I thought it might be helpful to post my entire function, since it could be my initial REGEX that is causing the issue. Basically, the funcion takes one argument. In this case, it's the contents of a HTML file (via CFHTTP).
In some cases, every URL looks and works fine. If I try digg.com for example it works...but it dies on something like youtube.com. I guess this would be down to their specific HTML formatting. Either way, all I ever need is the value of the SRC attribute on image tags.
Here's what I have so far:
<cffunction name="extractImages" returntype="array" output="false" access="public" displayname="extractImages">
<cfargument name="fileContent" type="string" />
<cfset var local = {} />
<cfset local.images = [] />
<cfset local.imagePaths = [] />
<cfset local.temp = [] />
<cfset local.images = reMatchNoCase("<img([^>]*[^/]?)>", arguments.fileContent) />
<cfloop array="#local.images#" index="local.i">
<cfset local.temp = reMatchNoCase("(""|')(.*)(gif|jpg|jpeg|png)", local.i) />
<cfset local.path = local.temp />
<cfif not arrayIsEmpty(local.path)>
<cfset local.path = trim(replace(local.temp[1],"""","","all")) />
<cfset arrayAppend(local.imagePaths, local.path) />
</cfif>
<cfif isValid("url", local.path)>
<cftry>
<cfif fileExists(local.path)>
<cfset arrayAppend(local.imagePaths, local.path) />
</cfif>
<cfcatch type="any">
<cfset application.messagesObject.addMessage("error","We were not able to obtain all available images on this page.") />
</cfcatch>
</cftry>
</cfif>
</cfloop>
<cfset local.imagePaths = application.udfObject.removeArrayDuplicates(local.imagePaths) />
<cfreturn local.imagePaths />
</cffunction>
This function WORKS. However, on some sites, not so. It looks a bit over the top but much of it is just certain safeguards to make sure I get valid image paths.
Hope you can help.
Many thanks again.
Michael
Take a look at ReFind() or REFindNoCase() - http://cfquickdocs.com/cf9/#refindnocase
Here is a regex that will work.
<cfset string = 'IM OBSESSED WITH MY BEAUTIFUL FRIEND" src="http://scs.viceland.com/feed/images/uk_970014338_300.jpg' />
<cfdump var="#refindNoCase('https?://[-\w.]+(:\d+)?(/([\w/_.]*)?)?',string, 1, true)#">
You will see a structure returned with a POS and LEN keys. Use the first element in the POS array to see where the match starts, and the first element in the LEN array to see how long it is. You can then use these values in the Mid() function to grab just that matching URL.
I'm not familiar with ColdFusion, but it seems to me that you just need a regex that looks for http://, then any number of characters, then the end of the string.