Use FindNoCase to find url string - coldfusion

I've search around and find some valuable info. about FindNoCase but I have not yet found the answer to this specific question.
I'm using FindNoCase to find "/us/" in the url and then process some code. This works fine for one country site.
<cfif FindNoCase("/us/",#cgi.SCRIPT_NAME#)>
Process some code here.
</cfif>
My question is: Is there a way to find the piece of the url, "/xx/", for multiple country sites and process the same code between the cfif tags? For example "/us/", "/ca/", "/mx/", etc.
Hopes this makes sense.

If searching for multiple different codes among a string, I'd use REFindNoCase. Make a regex like so (/us/)|(/ca/) which would look for /us/ or /ca/ and per the documentation (http://help.adobe.com/en_US/ColdFusion/9.0/CFMLRef/WSc3ff6d0ea77859461172e0811cbec22c24-7e99.html) you can return the sub-expressions and reference them.
No looping required.
REFindNoCase("(/us/)|(/ca/)", URL, 1, true)
To reference the strings you would do:
<cfset URL = 'domaim.com/page/us/' />
<cfset match = REFindNoCase("(/us/)|(/ca/)", URL, 1, true) />
<cfif arrayLen(match) GT 0>
<cfset value = Mid(URL,match.pos[1],match.len[1]) />
<cfswitch expression="#value#">
<cfcase value="/us/">
<!--- Do something for US match --->
</cfcase>
<cfcase value="/ca/">
<!--- Do something for CA match --->
</cfcase>
<!--- ETC --->
</cfswitch>
<cfelse>
<!--- Do something if no match found --->
</cfif>
In this case, value would equal /us/. Or it should anyway. I'm writing all of this here and not actually testing on my server. You'd have to adjust this if you want to cover multiple matches in a string.

If I'm understanding your question correctly, you want to process the SAME code for several countries, if detected in the URL. You could just create a database of country codes you want to process a certain way (CountryTableXYZ), query it, then loop through that query so it'll search the URL for each entry you have in the table.
<cfloop query="CountryQuery">
<cfif FindNoCase("#countryCode#",#cgi.SCRIPT_NAME#)>
Process some code here.
</cfif>
</cfloop>
At least that's how I interpret it. If I'm not correct please let me know or clarify your initial post.

Related

Coldfusion Complex Construct

I am trying to construct a coldfusion conditional statement that looks for incremental form ID checkboxes to have been selected. All checkboxes are defined as Component[component number]. I have established a loop that is looking for a URL variable that is different for every form that calls on the condition as seen below. The issue I am having is that I recieve an error when executing that tells me "Complex constructs are not supported with function parameterexists."
Clearly it has to do with the dynamic nature of the parameterexists statement, but I do not fully know what this means. Can anyone explain this and also offer a solution? I am fairly new to coldfusion and coding, so take it easy on me.
<cfloop from="1" to="#URL.loopcounter#" index="loopvar">
<cfif parameterexists(Form.Component#loopvar#)>
INSERT INTO Results (MP_Barcode, Reworked, Reworked_By)
VALUES ('#Form.MontaplastBarcode#', 'YES', '#URL.BadgeNumber#')
</cfloop>
<cfoutput>
<p class="success">YOUR REWORK HAS BEEN SUBMITTED SUCCESSFULLY.</p>
</cfoutput>
<cfelse>
<p class="error">NO REWORK WAS SUBMITTED. NO COMPONENTS SELECTED.</p>
</cfif>
Depending on the form that calls on this action, the URL loopcounter variable could range from 1 to 50.
To answer the question, there are several ColdFusion functions that won't allow you to create a dynamic name before the function evaluates it. parameterExists() was one of those. Both isDefined() and structKeyExists() will allow dynamic variables. So will the member function of structKeyExists() > structName.keyExists("theKey").
Again, if you are new to ColdFusion, I'd simply pretend you never saw parameterExists(). I believe it has been listed as "deprecated" since CF 4.5 or somewhere around there. That's almost 20 years ago. That function has actually become somewhat of a joke about how Adobe never really throws away their trash.
As I pointed out above, I'd get rid of it completely and go with structKeyExists(). I also don't know what your whole page is doing, but with the code you provided, I'd change it to something like this:
<cfloop from="1" to="#url.loopcounter#" index="loopvar">
<cfoutput>
<cfif structKeyExists(form,"Component#loopvar#")>
<!--- SANITIZE INPUTS --->
<cfset inMontplastBarcode = sanitizingFunction(FORM.MontaplastBarcode)>
<cfset inBadgeNumber = sanitizingFunction(URL.BadgeNumber)>
<!--- Now use sanitized inputs in query with queryparams --->
<cfquery name="InsertStuff" datasource="myds">
INSERT INTO Results (MP_Barcode, Reworked, Reworked_By)
VALUES (
<cfqueryparam value="#inMontaplastBarcode#" cfsqltype="cf_sql_varchar" maxlength="50">
, 'YES'
, <cfqueryparam value="#inBadgeNumber#" cfsqltype="cf_sql_varchar" maxlength="20">
)
</cfquery>
</cfif>
</cfoutput>
</cfloop>
In your database, Reworked should be a boolean datatype. It appears that it may be a 'Yes' or 'No' string. A true boolean will be a) smaller and b) easier to validate. In the cfqueryparams, if you are using a cf_sql_varchar datatype, make sure you set an appropriate max length. You'll need to look at the available CF datatypes and see how they match up to your database datatypes. (Also see https://cfdocs.org/cfqueryparam)
For your sanitizingFunction() that you'll use to sanitize your input variables, you'll want to write a function that will follow through the steps to clean up your variables to strip out unsafe characters or other things you don't want. That is an entirely different, extremely large topic all on its own.
In your form, name your checkboxes simpler. Like reworked01 through reworked50.
On the action page use cfparam to default them to zero (since html forms don't post unchecked boxes):
<cfloop from="1" to="#url.loopCounter#" index="i">
<cfparam name="form.reworked#numberFormat(i, 00)#" default="0">
</cfloop>
Then instead of fumbling with whether or not a variable exists, you can instead look for the value:
<cfloop from="1" to="#url.loopCounter#" index="i">
<cfif evaluate("form.reworked"&i) eq 1>
<!--- some logic here --->
<cfelse>
<!--- some other logic here --->
</cfif>
</cfloop>

Check values in a list are all identical

Ok here's a thing, I have a form which when submitted can only update a table when a particular checkbox form variable values are identical, if one is different then it should proceed to update the table. So basically the user is selecting different rows and hitting the submit button.
So for example a good submission would be
form.claimid = 12,12,12,12,12
a bad submission would be
form.claimid = 1,5,77,33,4,
I'm not sure how to check in a list if all the values in the form.claimid list are identical or not?
I would appreciate any ideas on this.
You can also use CF's native ListRemoveDuplicates() if the version is sufficient (CF10, Railo/Lucee 4)
https://wikidocs.adobe.com/wiki/display/coldfusionen/ListRemoveDuplicates
<cfif ListLen(ListRemoveDuplicates(mylist)) eq 1>
I'll leave this as an alternate means for older CFs.
I'm not sure how to check in a list if all the values in the form.claimid list are identical or not?
There are a couple ways, most of which involve looping, but I'm going to show you a regular expression that can do this. We're going to get the first value using ListFirst, and use a ReReplace on that value to see if every other value matches.
I use a loop here but only as a demonstration.
<cfoutput>
<cfset mylist = "11,22,33,44|44,44,33,44|557,557,557">
<cfloop list="#mylist#" index="m" delimiters="|">
<cfset matchele = listfirst(m)>
<cfset eradicate = rereplace(m,"(?:(?:^|,)#matchele#(?=,|$))+","","ALL")>
"#m#", "#matchele#", "#eradicate#"<br />
</cfloop>
</cfoutput>
If you're stuck on CF 9 or lower, you could loop over the list and put the elements into a struct:
<cfset list_coll = structNew() />
<cfloop list="#mylist#" index="myitem">
<cfset list_coll[myitem] = "dummy" />
</cfloop>
<cfif structCount(list_coll) EQ 1>
<!--- This is good --->
<cfelse>
<!--- This is bad --->
</cfif>
The reason this works is that structs can't have duplicate keys.

Can i remove Pagination from external site with cfhttp

I am fetching one website results in my website and if there are any much more records, the pagination is also coming along with it, so it is displaying pagination and records
this is more than a question rather than before i make any try and i do not know where to start
is this possible, can i make infinite pagination of the results through some client side or server side, let me know please thanks
Pagination look like this in the cfhttp.filecontent as:
<TD align="right" width="100"><font class="MainBody">Pages: << 1 2 >> </FONT></TD>
This should work for you. It searches for a TD tag followed by a FONT tag, followed by Pages.. and then searches to the first closing TD.
The result is stored in newfilecontent.
<cfset newfilecontent = REReplaceNoCase(cfhttp.filecontent,"<td.*?><font.*?>Pages.*?<\/td>","","ALL")>
With a more detailed question, what you need is basically a rudimentary spider.
This is only designed to work from the first page of results onward. You can't target this at say, page 3, and get page 2 and page 1's.
<cfhttp...> <!--- initial cfhttp --->
<cfset buildContents = ArrayNew(1)>
<cfset buildContents[1] = ReReplaceNoCase(cfHttp.fileContent,".*<body.*?>(.*)</body>.*","\1","ALL")>
<!--- Quick regex to parse the contents of the body tag out of the cfhttp --->
<cfloop condition="#ReFindNoCase("(http[^""]*?pagenum=\d+)(?="">>>)",currentContent)# gt 0">
<cfset GetNextPage = ReMatchNoCase("(http[^""]*?pagenum=\d+)(?="">>>)",currentContents)>
<cfhttp url="#GetNextPage[1]#"... result="inLoop">
<cfset currentContents = ReReplaceNoCase(inLoop.filecontent,".*<body.*?>(.*)</body>.*","\1","ALL")>
<cfset ArrayAppend(buildContents,REReplaceNoCase(currentContents,"<td.*?><font.*?>Pages.*?<\/td>","","ALL"))>
<cfif ArrayLen(buildContents) gt 10>
<!--- This code is untested, so this is a safety that you can remove or modify. If BuildContents has more than ten elements, it stops the looping. You can remove this cfif or maybe raise the number as a safety net.--->
<cfbreak>
</cfif>
</cfloop>
<cfdump var="#buildContents#">

cffeed function: show just most recent post?

We have a function to pull RSS feeds and display the post on a ColdFusion page using this code:
<cfset rssUrl = "rss1">
<cffeed action="read" source="#rssUrl#" query="fitness" properties="info">
<cfset rssUrl2 = "rss2">
<cffeed action="read" source="#rssUrl2#" query="nutrition" properties="info">
<cfif #fitness.PUBLISHEDDATE# gt #nutrition.PUBLISHEDDATE#>
<cfset entries="fitness">
<cfelse>
<cfset entries="nutrition">
</cfif>
Output done via:
<cfoutput query="#entries#">
Problem is, the RSS feed has several posts and we only want to show one. Any thoughts on how to get it to pull and display only the most recent post? (We want the feed to have multiple posts, so right now our non ideal solution is to set maximum posts per feed to 1)
cfoutput/query=".." will go over an entire query. If you only want to do the first row, use:
<cfoutput>
Title from row 1: #somequery.title[1]#
</cfoutput>
Basically - array notation on the column. Make sense?
There's nothing wrong with Ray's answer, but here are some other options.
<cfoutput query="#entries#" maxrows="1">
Offers the least disruption to your existing code and, should you decide to change the number of rows displayed (like, via a user setting) it's an easy change.
OR
If you copy the query object rather than the query name (which isn't actually a copy but a copy by reference)
<cfset entries = fitness>
instead of
<cfset entries = "fitness">
you can do this
<cfoutput>
#entries.columnName1#
#entries.columnName2#
<!--- etc. --->
</cfoutput>
which will, by default, display only the first row of the query.

Coldfusion-Best way to hide urls on pages by using CFSWITCH?

I want to build a framework that hides the URL's and am just learning CFSWITCH. Navigation links are queried in datatable. I have tried to query around cfswitch and keep getting error
Example:
?category=5&page=21 ( where category=page_category and 5= page_categoryid
and page is page_id is 21 in datatable )
<cfoutput query="pagecategories" group="page_categoryid">
<cfswitch expression="#URL.category#">
<cfcase value="21">
<cfinclude template="../templates/index_welcome.cfm">
</cfcase>
<cfcase value="#page_categoryid#">
<cfinclude template="../templates/page_bycategory.cfm?page_categoryid=#page_categoryid#">
</cfcase>
<cfcase value="22">
<cfinclude template="/modules/blog/">
</cfcase>
</cfswitch>
</cfoutput>
First, welcome to ColdFusion, it's a great language, I think you'll like it. :)
What you're attempting here is a really bad idea for a number of reasons, read on for why and some alternatives.
1) it needlessly obfuscates it from you, the developer. Trust me you will learn to hate it 6 months from now when you go back in for some arbitrary changes and can't remember what "14" means.
2) it is bad for search engines - google SES urls for more info (search engine safe).
3) numeric incrementing keys are less secure than descriptive texts. I can just loop over numbers and see all your pages, skipping your navigation and seeing everything.
4) you get no perceivable advantages that can't be gained in other ways (which I'll show you one next).
Instead of going about it the way you have listed, arbitrary numbers that link to different elements- why not instead key them off of actual strings that have meanings? If what you are trying to accomplish is hiding the actual page names that are processing the request, why not instead use something like this:
http://www.domain.com/?/category/blog/page/links
instead of:
http://www.domain.com/page.cfm?category_id=21&page=5
In my example, i'm not pointing to an actual directory, I'm going to take the cgi.querystring param (which will contain the string "/category/blog/page/links") and parse it and match it to key values. (see coldfusion list functions: http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=functions-pt0_13.html, use "/" as delimiter). Then I can pull up whatever logic i need for category "blog" and page "links" - which can be stored in a database just the same as "21" and "14". :)
Now, on to your code...
As for the switch statement, it simply works sort of like a set of if statements :
<cfswitch expression="value_to_check">
<cfcase value="possible_value_1">
<!--- do something --->
</cfcase>
<cfcase value="possible_value_2,another_possible_value">
<!--- do something different --->
</cfcase>
<cfdefaultcase>
<!--- if none of the above, do this --->
</cfdefaultcase>
</cfswitch>
You also have some weirdness in your include statement. You can't specify any url parameters in a <cfinclude> statement. Think of it as literally grabbing the code from the page you specify and pasting it into the document. It does exactly that, no more, no less. Therefore, you can't specify url parameters. This is invalid :
<cfinclude template="../templates/page_bycategory.cfm?page_categoryid=#page_categoryid#">
Additionally, it's pretty abnormal for the case statement to have a dynamic value such as this:
<cfcase value="#page_categoryid#">
Let me know if you have any questions / need clarification