How do I retrieve the current value of enablecfoutputonly? - coldfusion

We are using Coldfusion 9.
Is there a simple way to know if enablecfoutputonly has been set to true during a particular request?

I cannot test with CF9 right now, but in CF10 it is accessible from getPageContext() by checking the output object:
<cfscript>
out = getPageContext().getOut();
// Is the cfsetting enablecfoutputonly value currently true?
isSettingEnabled = out.getDisableCount() > 0;
WriteOutput("isSettingEnabled="& isSettingEnabled &"<br>");
// Is output currently allowed?
isOuputtingEnabled = out.getDisableCount() == 0 || out.getOutputCount() > 0;
WriteOutput("isOuputtingEnabled="& isOuputtingEnabled &"<br>");
</cfscript>
.. or using reflection:
<cfscript>
out = getPageContext().getOut();
internalMethod = out.getClass().getDeclaredMethod("isOutputEnabled", []);
internalMethod.setAccessible( true );
isOuputtingEnabled = internalMethod.invoke( out, [] );
// is output currently allowed?
WriteOutput("isOuputtingEnabled="& isOuputtingEnabled);
</cfscript>

Related

Jsoup to post data and parse alternative URLs on CFscript

I need to get and parse a page from primary_URL using Jsoup in CFscript.
If page status is not OK or data is corrupt or empty, I should try an alternative page from secondary_URL.
primary_URL accepts POST requests only and I don't know how do it in cfscript
secondary_URL accepts GET by default
This is an idea:
<cfscript>
jsoup = createObject("java", "org.jsoup.Jsoup");
response = jsoup.connect(primary_URL).userAgent("#CGI.Http_User_Agent#").timeout(10000).method(Connection.Method.POST).execute(); // How to use Method.POST in this case???
if(response.statusCode() == 200)
{
doc = response.parse();
theData = doc.select("div##data");
...
`some other parsing and SQL UPDATE routine`
}
else
{
response = jsoup.connect(secondary_URL).userAgent("#CGI.Http_User_Agent#").timeout(10000).execute(); // default is GET
if(response.statusCode() == 200)
{
doc = response.parse();
theData = doc.select("div##same_data");
...
`some other parsing and SQL UPDATE routine`
}
}
</cfscript>
How to jump to the secondary_URL in case the response is OK but the data appears to be currupt or empty? A kind of goto operator?
Running ColdFusion 11.
How to jump to the secondary_URL in case the response is OK but the data appears to be currupt or empty? A kind of goto operator?
Instead of checking the statusCode only, call a function. Inside this function perform all necessary checks (corrupted data, empty data ...).
<cfscript>
function IsValid(response) {
// Perform all the tests here...
// Return TRUE on success or FALSE otherwise
return true;
}
jsoup = createObject("java", "org.jsoup.Jsoup");
response = jsoup //
.connect(primary_URL) //
.userAgent("#CGI.Http_User_Agent#") //
.timeout(10000) //
.post(); // Simply call the post() method for posting...
if( IsValid(response) ) {
} else {
response = jsoup //
.connect(secondary_URL) //
.userAgent("#CGI.Http_User_Agent#") //
.timeout(10000) //
.get(); // Make your intent clear
if ( IsValid(response) ) {
// ...
}
}
</cfscript>

Coldfusion Struct getting only numeric key list

I have a coldfusion Struct containing mix keys numeric and alpha, alphanumerics
I need to access only the numeric keys.
My code looks like
<cfset ids = structkeyList(st ) />
<cfset numericIDs = "" />
<cfloop list="#ids#" index="i">
<cfif IsNumeric(i)>
<cfset numericIDs = ListAppend( numericIDs , i ) />
</cfif>
</cfloop>
Is there a better method to solve such problems?
Is there a better method to solve such problems?
I would use something like this:
<cfset numericIDs = arrayToList(reMatch('\b\d+(?=,|$)\b', structKeyList(st)))>
Is there a better method to solve such problems?
I'd generally recommend working with arrays instead of lists.
In CF9 a loop similar to yours is as good as it gets. You can make a utility function out of it if you need it more than once. This one avoids StructKeyList() to be able to deal with all kinds of keys, independent of a separator character:
<cfscript>
function GetNumericKeys(struct) {
var keys = struct.keys();
var result = ArrayNew(1);
var key = "";
while (keys.hasNext()) {
key = keys.next();
if (IsNumeric(key)) ArrayAppend(result, key);
}
return result;
}
</cfscript>
and
<cfset nkeys = GetNumericKeys(st)>
In CF11 you can get a little more sophisticated (tested on CF11, can't say how CF10 handles this code).
<cfscript>
numericIDs = arrayFilter(structKeyArray(st), function (key) {
return IsNumeric(key);
});
</cfscript>
To ensure integer keys, use:
<cfscript>
numericIDs = arrayFilter(structKeyArray(st), function (key) {
return Int(key) eq key;
});
</cfscript>
I really don't see what's wrong with this. It should work quite well already, and it is very readable.
Sometimes working with a List is faster than an Array.
I had this:
<cfscript> function ListNumeric(principal) {
a=principal;
cleanlist = ''; for (i=1; i <= ListLen(a);i=i+1) { if(IsNumeric(ListGetAt(a,i))){ cleanlist = ListAppend(cleanlist,ListGetAt(a,i)); } } Return cleanlist; } </cfscript>
Also possible to work with regular expression:
inList2 = REReplace(inList,"[^0-9.]", "","ALL");

How to create application variables in application.cfc

I'm new to using the application.cfc file in our application and some of these don't seem to be working and I can't figure out why. I have tried to cfdump "application". I get Application.DSN, Application.USERNAME, Application.Password, but not Application.SYSTEMPATH or Application.ACCOUNT
<cffunction name="onApplicationStart">
<cfscript>
Application.availableResources=0;
Application.DSN = "XXX";
Application.USERNAME = "XXX" ;
Application.PASSWORD = "XXX";
Application.SYSTEMPATH = "http://example.com/"; // This doesn't work
Application.ACCOUNT = XXX; // This doesn't work.
Application.counter1=1;
Application.sessions=0;
</cfscript>
</cffunction>
I think you want this:
Application.SYSTEMPATH = GetDirectoryFromPath(GetCurrentTemplatePath());
This will work too:
Application.SYSTEMPATH = expandPath( './' );
Now this...
Application.ACCOUNT = XXX; // This doesn't work. (because it is assuming XXX is a variable).
You need this:
XXX = 'something'; or XXX = 1; or Remove it altogether because it serves no purpose.
Then when you call:
Application.ACCOUNT = XXX; it won't give you errors.
Or you can just skip it and do this:
Application.ACCOUNT = 'something'; (a string)
Application.ACCOUNT = 1; (a number)
Then it won't fall apart (Because XXX is a variable not a value and you can't call a variable that doesn't exist).
So, if you have a 'variable' it has to have a 'value' (variable/value pair) or at least set a placeholder like XXX=0; or XXX=''; if you must have it.
Have I killed this variable/value dead horse to death??? Lol... :D
Jokes aside let us know if you have another question about your Application variables because some seem unnecessary (can't judge for sure though).

ColdFusion Code as failing on if condition

Working with cfscript code in ColdFusion, The following seems correct to me, if client_discount is either 0 or NULL, just do not generate the UniqueKey, use existing else use new one. But it does work somehow, I am not sure what I am missing here, trying different cflib UDF's also:
Here is my code:
f = structnew();
f.discountoffered = '#arguments.structform.client_discount#';
writedump(arguments);
result = structFindKeyWithValue(f,f.discountoffered,"0","ALL");
writedump(result);
if((arguments.structform.client_discount EQ 0)
OR (arguments.structform.client_discount NEQ "")) {
f.orderunique = generateRandomKey();
}
else {
f.orderunique = '#arguments.structform.orderunique#';
}
NULL is kind of wonky in ColdFusion.
I would handle this by paraming the value so it gets a value I decide if it does not exist.
Add this code under f = structNew() - or at the beginning of the function, does not really matter.
param name="arguments.structForm" default="#structNew()#;
param name="arguments.structForm.client_discount" default="0";
This way if client_discount is not present, it is set to 0 - the first line is to make sure that structform exists in arguments and if not, sets it to an empty struct.
Then your if statement need only check if it is 0.
if( arguments.structForm.client_discount == 0 ){
f.orderunique = generateRandomKey();
}
else{
f.orderunique = arguments.structform.orderunique;
}
Of course...you would need to verify that arguments.structForm.orderunique exists before using it.
I think that's what you are trying to do
<cfscript>
f = structnew();
if(not isnull(arguments.structform.client_discount)){
f.discountoffered = '#arguments.structform.client_discount#';
result = structFindKeyWithValue(f,f.discountoffered,"0","ALL");
if((arguments.structform.client_discount EQ 0))
f.orderunique = generateRandomKey();
else
f.orderunique = '#arguments.structform.orderunique#';
}
else {
f.orderunique = '#arguments.structform.orderunique#';
}
</cfscript>

QueryAddRow throwing error in Coldfusion Webservice

I am facing a weird issue.
When I am consuming the below snippet of code as a webservice residing in a CF9 server I am getting the error "The value coldfusion.runtime.Struct cannot be converted to a number."
The call returns an array of structures. I would like to create a query from this array of structure. When I place this code as a standalone code in my local server(CF10) it works fine. But as soon i place it in the remote server to be invoked i get the error.
I almost pulled out my hair when I got the same error message even when I replaced the variable 'tempstruct' with a hard coded structure. As soon I remove the QueryAddRow I am able to return anything.
Any help is appreciated.
<cfset myquery=querynew("category,category_id,event_description","varchar,integer,varchar")>
<cfinvoke
webservice="http://199.99.99.999/vod_queries.cfc?wsdl"
method="getAllCategoryByResort"
returnvariable="arrAllSpaEvents"
refreshwsdl="true" >
<cfinvokeargument name="Resort" value="SRB" >
</cfinvoke>
<cfif arraylen(arrAllSpaEvents) GT 0>
<cfloop array="#arrAllSpaEvents#" index="cur_row">
<cfset tempstruct=StructNew()>
<cfset tempstruct.CATEGORY=cur_row.CATEGORY>
<cfset tempstruct.CATEGORY_ID=cur_row.CATEGORY_ID>
<cfset tempstruct.EVENT_DESCRIPTION=cur_row.EVENT_DESCRIPTION>
<cfset QueryAddRow(myquery,#tempstruct#)>
</cfloop>
</cfif>
<cfreturn myquery>
You almost got.
However, indeed you are using new CF10 overloading in CF9. What's more, if you were using CF10, it looks like you could stuff the whole top array in with looping like that.
But you can almost do the same thing. CF9 will take an array overload for the value.
Not quite as clean as CF10 but you do what you can.
Also, the extra # signs are superfluous.
Here is an example with something that your data might look like:
<cfscript> // I did this all in a cfscript block for simplicity
Your retrieved data might look something like this guessin from example
arrAllSpaEvents = [
{category='fun', category_id=1, event_description='massage'},
{category='work', category_id=2, event_description='spinning'},
{category='beauty', category_id=3, event_description='mani'},
{category='beauty', category_id=3, event_description='pedi'}
];
Create a more useful struct to build the query dynamically
s = {
category = {colType = 'varchar', colVals = []},
category_id = {colType = 'integer', colVals = []},
event_description = {colType = 'varchar', colVals = []}
};
This is looping the data to fill the colVals arrays
for(c = 1; c <= arrAllSpaEvents.size(); c++ ) {
for(k in arrAllSpaEvents[c]) {
s[k].colVals[c] = arrAllSpaEvents[c][k];
}
}
This is the short form of the same double loop above in a single line
for(c = 1; c <= arrAllSpaEvents.size(); c++ ) for(k in arrAllSpaEvents[c]) s[k].colVals[c] = arrAllSpaEvents[c][k];
Now build your query. Start with an empty query (pass in a blank);
q = queryNew('');
Then loop your struct and using the keys for the column names (for simplicity they are the same key)
for(k in s ) queryAddColumn(q,k,s[k].colType,s[k].colVals);
Verify your struct and query:
writedump(s);
writedump(q);
</cfscript>
I ran this in CF9 so should work fine for you.
This should get you going.