Cfhttp result struct behaves as if null in CF8? - coldfusion

I'm trying to do some sanitation on the results of a call to Facebook but Coldfusion is telling me that the variable is null:
FILECONTENT null <br>The error occurred on line 66.
Here's the line that causes the error:
<cfif isDefined("storeFeedJSON.fileContent")>
<cfset storeFeedJSON.fileContent = process.CleanBadUnicode("#storeFeedJSON.fileContent#")>
</cfif>
The struct is clearly not null however as I have it wrapped in an "isDefined" and when I dump storeFeedJSON I can see fileContent looks like
{"data":[]}
Empty JSON but still not null...
EDIT: Here's the call I forgot to put in there:
<cfset fbURL = "https://graph.facebook.com/#qStoreFBPages.pageID#/#fbEdge#?fields=#fbFields#&since=#fbSinceTime#&#qToken.objectValue#">
<cfhttp result="storeFeedJSON" url="#fbURL#" method="get"></cfhttp>
which would probably end up looking something like this:
<cfhttp result="storeFeedJSON" url="https://graph.facebook.com/1749383765/posts?fields=created_time&since=1389296713&access_token=CAAH6oehQqUUU2IALvt0ZB3mdE6E2LCaldFc1TjIqxALUZBMqZC01O2hQXkOX8ROI9QBHn7WjWrHHneazAP4gWbj0MBsRUlel9TAG52kjBm0bBOUHVEFmEusEUHfhznlqzH1GMgCpCU4z4SmgXU8oFZBPDyAv1ByJu167jgkVd6UROWtDZBNBCP&expires=5184000" method="get"></cfhttp>
Note that will not result in a valid response from Facebook as I've changed my token and some other params.

I don't think you can re-assign the properties of the storeFeedJSON struct.
storeFeedJSON is the result of your cfhttp, right? as in
<cfhttp url="xyz" result="storeFeedJSON">
... which I think is a protected or immutable data structure. You can obviously pass it as an argument for your function, but put the output in some other variable, or perhaps straight to the json deserialize.
<cfset local.cleanFileContent = process.CleanBadUnicode(storeFeedJSON.fileContent)>
<cfdump var="#deserializeJSON(local.cleanFileContent)#">
... and while I'm at it, you might want to use getasbinary="never" because Facebook may someday give you binary data, or change its headers or something, and then your code will break. If you have to receive binary, you'll need cfhttp.fileContent.toString() or something like that.

Related

Using XML response as variable in Postman

Blockquote
Hi All,
I have a question. I just started using Postman, so please sorry if I'm not using all the correct technical terms.
I want to have a Envirionment variable in postman that contains several XML tags.
F.e.
<Storess>
<Store>
<Id>322</Id>
</Store>
<Store>
<Id>323</Id>
</Store>
<Store>
<Id>324</Id>
</Store>
</Storess>
I want everything between the tags <Storess> and </Storess> to be copied to the environment variable so that I can use {{Storess}} in the next request that i'm sending.
How should I do this?
This may be useful: https://www.marklogic.com/blog/postman-test-scripting/
In the test script of the first request, you can set the result in an environment variable like this:
var result = pm.response.text();
console.log(result);
result = result.replace("<Storess>", "").replace("</Storess>", "").trim();
postman.setEnvironmentVariable("Storess", result);
console.log(postman.getEnvironmentVariable("Storess"));
You will be able to get the information in the next request like this:
{{Storess}}
If you want the XML inside the variable Storess to be well-formatted, you'll need to work it out a little bit.

Jsoup in CFscript execute connection as POST

The page I want to parse could be get only by POST method.
This is easy for Java as I can see:
import org.jsoup.Jsoup;
Response res = Jsoup.connect("URL").method(Method.POST).execute();
Document doc = res.parse();
I could not produce the same thing using CFscript.
jsoup = createObject("java", "org.jsoup.Jsoup");
response = jsoup.connect("URL").method(Method.POST).execute();
if (response.statusCode() == 200)
{
doc = response.parse();
}
-ERR Element POST is undefined in METHOD
I tried almost everything.
I was unable to use .method() and .execute() at the same time.
If I call .get() or .post() directly I can not check statusCode() back then.
If you look at the API, Method is another JSoup class. You need to create an instance of that class before you can access the POST constant. Also, Method is a little different than your typical java class. It is an enum (or constant). Those are essentially handled as inner classes, which require a special syntax with createObject:
methodClass = createObject("java", "org.jsoup.Connection$Method");
response = jsoup.connect("http://example.com").method(methodClass.POST).execute();
Alternatively, you can invoke the post() method directly:
response = jsoup.connect("URL").post();

Issues with Application Scope for fetching the CFC's

I am trying to get the CFC linked but i am getting an error:
Here is my Configration in my Application.cfc
<cfset Application.relativePath = "/">
<cfset Application.componentsPath = Replace(Application.relativePath,"/","",'All')>
<cfset Application.cfcpath = Application.componentsPath & "com">
<cfset Application.tools = '#Application.cfcpath#.tools'>
Now when i acces the cfc from my page like this:
<cfset result = Application.cfcpath.tools.saveDrivers(form)>
I am getting an Error:
Element CFCPATH.TOOLS is undefined in a Java object of type class [Ljava.lang.String; referenced as ''
if i try
<cfset result = Application.tools.saveDrivers(form)>
I get an Error:
The saveDrivers method was not found.
Either there are no methods with the specified method name and argument types or the saveDrivers method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 0 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity.
I dumped out the Application Scope and all seems ok, but i am not sure what is troubling here
Both Application.cfcpath and Application.tools are just strings, so can only be used as strings; whereas Application.cfcpath.tools within the statement:
<cfset result = Application.cfcpath.tools.saveDrivers(form)>
is a variable reference. You can't have a string holding a variable reference and hope that somehow ColdFusion will magically equate the two.
It's unclear from your question whether you are trying to create an object with your statement, or are simply referencing an existing one. I suspect it's the former. In which case, you want this sort of thing, I think:
tools = createObject(Application.tools);

update() and save() methods result in "no matching method/function" in railo

I'm trying to run a very quick update query to record that a user's email address is confirmed (setting the confirmed [bit] column in my users table to 1 after they click a link sent via email). Here's the action that should do it:
<cffunction name="confirmEmail">
<cfscript>
user = model("user").findOne(where="id=#params.userid# AND uuid='#params.uuid#'", returnAs="query");
if(user.recordCount) {
pageTitle = "E-mail Confirmation Success";
user.update(confirmed=1);
} else {
redirectTo(route="authenticationDenied", alert="Something was wrong with your confirmation string. Please contact site administrators.");
}
</cfscript>
</cffunction>
But when I submit the appropriate URL (I've dumped and can see the model call finds one valid record), I get the following error in Railo 3.3.x:
No matching Method/Function [update] for call with named arguments found
...highlighting the user.update(confirmed=1); line in my code. So what am I doing wrong? Previously I have always used save/update(params.user) or thereabouts for these queries, but that seems like overkill here; I just want to pass a 1-bit update.
Okay, my CTO who is new to CFML and Wheels figured this out in like 5 seconds. Hence the "C" I guess.
By returning the user model as a query instead of an object, I didn't have access to the update/save() methods. (Duh, MVC n00b.) The reason I was returning it as a query was simply that I've been doing that a fair bit in order to have easy manipulation of output, and in this case so that I can test for the existence of a record the way I always have (if recordCount). But this works...
<cffunction name="confirmEmail">
<cfscript>
user = model("user").findOne(where="id=#params.userid# AND uuid='#params.uuid#'");
if(isObject(user)) {
user.update(confirmed="1");
} else {
flashInsert(error="Something was wrong with your confirmation string. Please contact site administrators.");
redirectTo(route="authenticationDenied");
}
</cfscript>
</cffunction>

cfquery name attribute, optional?

Is name attribute of cfquery optional? The doc said it is required, but my code seems to run fine even without it. Is there a default value if not defined? and if so, shall I local var it or safely ignore it?
Thx
I think you can safely omit the name. It does not appear to add a default name to the variables or local scopes.
However, I did notice something strange under CF9. If you do not local scope the result, the key cfquery.executiontime is added to the variables scope. This is with all debugging disabled (unless I missed something).
Results:
Before Variables = 1 Local = 1
After Variables = 2 Local = 1 (result NOT local scoped)
<cffunction name="myFunction" output="true">
<b>Before</b>
Variables = #structCount(variables)#
Local = #structCount(local)#<br />
<cfquery datasource="MyDatasource">
SELECT getDate() AS TestDate
</cfquery>
<b>After</b>
Variables = #structCount(variables)#
Local = #structCount(local)#<br />
</cffunction>
The name attribute is required, but I just tested it & it does not throw an error if the name attribute is missing... how very interesting. Though, without the name attribute - how are you going to get at the result set?
What an interesting question.
UPDATE
Just ran a quick test and did some googling:
<cfquery datasource="#dsn#" result="qresult">
select some_stuff from that_table limit a_bunch
</cfquery>
<cfdump var="#qresult#" />
Dumping the result attribute shows clearly that the query has run and did get a result set - though there appears to be no way to access it.
Googling & docs were no help with the defaults or scope.. maybe ping these guys: http://www.bennadel.com/ - I run across a lot of 'experimenting' on their site.
Now the docs do say that the name attribute is required, but I guess I can see situations where it may not be necessary - obviously memory isn't used by the name variable not being there, but what about the result set? so I'm guessing if you run any query where you don't actually need info back from it [anything but a select?] you can get all the info you need by using the result attribute and MAYBE save some memory and execution time?
isn't that a fun thought?
-sean