Does anyone know if the new websockets feature in CF10 can be used cross domain and cross server? And does anyone know or have some sample code to do this?
I have a simple live help chat working on my app but I want to apply it to other sites and have one central admin chat area where the support agents will interact with users cross domain.
As far as I know they do not. You can, however, use a <cfhttp> to call a file on the other site that will publish the message. Here is I accomplished this.
Create a file called socketPublisher.cfm and save it in a directory that does not require a login access a file.
socketPublisher.cfm
<cfparam name="Request.Attributes.msgType" default="newJob">
<cfparam name="Request.Attributes.channel" default="notify">
<cfparam name="Request.Attributes.Type" default="">
<cfoutput>
<cfswitch expression="#Request.Attributes.Type#">
<cfcase value="yourType">
<cfscript>
WSPublish('chat',{message: '', msgType: '#Request.Attributes.msgType#'});
</cfscript>
</cfcase>
<cfdefaultcase>
<cfscript>
WSPublish('#Request.Attributes.channel#',{message: '', msgType: '#Request.Attributes.msgType#'});
</cfscript>
</cfdefaultcase>
</cfswitch>
</cfoutput>
Then in you action page on the other site, you will need to make your http request to that file.
actionPage.cfm
<cfhttp method="Post" url="#socketURL#/_scripts/socketPublisher.cfm">
<cfhttpparam type="URL" name="msgType" value="pendingFiles">
</cfhttp>
That should do it.
There is also a know issue with CF10 WSPublish that it will change the CGI scope cause error when trying to do a redirect from an action page. I am using this as a workaround for that issue until I can find a better solution.
Related
Can't get to work a Coldfusion webservice that uploads a file in an external server.
My application runs in "Server A" and the file repository (external server) is in "Server B"
The template (inicio.cfm) which contains the form with the <cfinput type="file"> to select the client's file to be uploaded, is stored in "Server A". This template performs more tasks than just show the upload form. It performs calculations, queries, etc. outside the form's code block. Also, the action page of this form is the template itself (because of my application's needed tasks).
The first code line of my form definition is (inside inicio.cfm):
<cfform method="post" name="AltaConvocatoria" enctype="multipart/form-data">
Which demonstrate that I'm using the right enctype definition.
In the other hand, stored in "Server B" is my Coldfusion component or webservice (alta_ga.cfc) which only task is to upload the file selected by user in "inicio.cfm" form and rename it.
Here's alta_ga.cfc code:
<cfcomponent>
<cffunction access="remote" returntype="void" name="cargaAnuncio">
<cfargument name="destinoAnuncio" required="yes" type="string">
<cfargument name="PrefijoNvoNombre" required="yes" type="string">
<cffile action="upload"
fileField="str_ArchivoAnuncio"
destination="#destinoAnuncio#"
nameconflict="Overwrite">
<cfset NvoNomAnuncio = #PrefijoNvoNombre# & #Right(cffile.ClientFile, 5)#>
<cfset viejoNombre1 = #destinoAnuncio# & #cffile.ClientFile#>
<cffile
action = "rename"
destination = "#NvoNomAnuncio#"
source = "#viejoNombre1#">
</cffunction>
</cfcomponent>
For that pupose, I invoke the webservice from the form's action code block in inicio.cfm with this:
<cfinvoke webservice="http://192.168.208.128/podi/mgmt/alta_ga.cfc?wsdl" method="cargaAnuncio" >
<cfinvokeargument name="destinoAnuncio" value="#form.destinoAnuncio#" />
<cfinvokeargument name="PrefijoNvoNombre" value="#form.PrefijoNvoNombre#" />
</cfinvoke>
When I try to load a file using my form's template inicio.cfm I get this message:
Cannot perform web service invocation cargaAnuncio.
The fault returned when invoking the web service operation is:
'' podi.mgmt.PodiMgmtAlta_gaCfcCFCInvocationExceptionException: coldfusion.tagext.io.FileUtils$CFFileNonMultipartException : Invalid content type: application/soap+xml; charset=UTF-8; action="urn:cargaAnuncio".The files upload action requires forms to use enctype="multipart/form-data".]
All the arguments and variables that I'm using are correct, because I tested the webservice as a local component (stored in Server A and uploading the file in the same server) and worked fine. Here's the code of the succesful test (invoked as a component instead of a webservice):
<cfinvoke component="alta_ga" method="cargaAnuncio" destinoAnuncio="#form.destinoAnuncio#" PrefijoNvoNombre="#form.PrefijoNvoNombre#">
¿What could be wrong?
There's a lack of documentation about this functionality. Adobe's user guide doesn't explain this functionality in depht. Ben Forta's books... same. Or I couldn't find the information.
Thanks in advance.
When a form is posted to a CFML server, the posted file is saved in a temporary directory before any of your code runs. All <cffile action="upload"> does is to copy a file from that temporary directory to the location you want it to be. Your remote server ServerB has no idea about any file posted on ServerA, so <cffile action="upload"> will not help you.
The action is misleading. It's not upload-ing anything. It's just copying from a predetermined temp directory. The web server handles the uploading before the CF server is even involved.
You will likely need to <cffile action="upload"> on ServerA to a specific place, and then it needs to post that file to your web service on ServerB. Then ServerB should be able to use <cffile action="upload"> to transfer it from the upload temp directory to wherever you need it to be. That said I have never tried this when posting to a web service.
Alternatively you could just post the file directly to ServerB in the first place, to save needing ServerA to be an intermediary. This might not be possible, of course.
OK, so I've spent the last couple of days researching this issue on various websites including this one and I'm still no closer to having an answer. I have seen claims that this was a bug and was fixed on Adobe's end in one of the CF11 patches and I have even seen one answer that claimed that Adobe was emailing the fix directly to individuals - though no information on how to go about getting Adobe to do that was provided on that webpage.
We just updated our intranet to Coldfusion 11 and pages that have a cfgrid using the HTML format and bind data from a cfc no longer show the cfgrid on the page. Other pages that use the Flash format with cfgrid (which apparently can't use the bind attribute with Flash) do work. These HTML cfgrid pages were working properly in Coldfusion 9 before we migrated to 11.
I have simplified the code as much as I can to eliminate other error possibilities - i.e. I've stripped out formatting and am pulling only a couple columns from the database. Here is the code I am currently working on in my dev sandbox:
<cfgrid format="html"
name="userGrid"
bind="cfc:editorFunc.getGridData({cfgridpage},{cfgridpagesize},{cfgridsortcolumn},{cfgridsortdirection})"
pagesize="20">
<cfgridcolumn name="REGION" header="Region">
<cfgridcolumn name="managmentArea" header="Management Area">
</cfgrid>
Here is the code in the cfc (the query does produce results when dumped to the page):
<cffunction name="getGridData" access="remote">
<cfargument name="page">
<cfargument name="pageSize">
<cfargument name="gridsortcolumn">
<cfargument name="gridsortdir">
<cfquery name="records" datasource="webData">
SELECT REGION, managmentArea
FROM areaDesc
ORDER BY Region ASC
</cfquery>
<cfset result = queryConvertForGrid(duplicate(records), arguments.page, arguments.pagesize)>
<cfreturn result>
</cffunction>
Has anyone had any luck getting a cfgrid like this to work in CF11? I could try a JQuery solution like JGrid, however I would prefer to figure out the existing issue with this code if possible.
Any help is much appreciated.
Add this..
<cfif not len(trim(arguments.gridsortcolumn))>
<cfset arguments.gridsortcolumn = "REGION">
<cfset arguments.gridsortdir = "desc">
</cfif>
query....
ORDER BY #arguments.gridsortcolumn# #arguments.gridsortdir#
I need to post from a non-secure CF page to a secure CF page. I don't want to have to go through and implement the user authentication on the page sending the values because its a rather cumbersome process due to the way this legacy site was setup and secondly because the page sending the values is acting as a service between two unrelated order management systems as opposed to a user.
Right now, when I try to post to, the response result is a redirect to the login of the homepage. Is there a way to make an exception for a posting or receiving page from forcing user authentication?
I'm using <cfhttp> to post the values to post page which has a series of <cfparam>'s that I'm passing the values to. Once I pass those values into the post page is when the post page triggers a redirect to the home page because the post page is an internal page in the order management system and is displayed as a client logs in and a session is created for them.
Since you did not provide any code, here is a guess what it might look like and how you could add an exception for specific requests:
<cffunction name="onRequestStart" access="public" output="false" returnType="boolean">
<cfargument name="targetPage" type="string" required="true">
<!--- treat initialized SESSION or matching request token (rtoken) as successful authentication --->
<cfset LOCAL.isAuthenticated = (
isDefined("SESSION.userID")
or
( structKeyExists(FORM, "rtoken") and (FORM["rtoken"] eq "some-secret-only-you-know") )
)>
<cfif LOCAL.isAuthenticated>
<!--- do something... --->
<!--- not authenticated --->
<cfelse>
<!--- redirect to login --->
<cflocation url="login.cfm" statusCode="303" addToken="false">
</cfif>
</cffunction>
Now you could simple add the key-value-pair rtoken=some-secret-only-you-know (i.e. <input type="hidden" name="rtoken" value="some-secret-only-you-know" />) to your POST to bypass the session based authentification.
Disclaimer: Only use this method if the POST parameters (form fields) are not public/editable by the user.
Feel free to provide actual context so I can assist in a more concrete way.
I have written a couple of apps with similar, but not identical requirements. Here is how I handled those requirements in the last one I wrote. All this code is the Application.cfc file in the methods specified.
In onApplicationStart:
application.securityNotNeededPages =
"somePage.cfm,someOtherPage.cfm,someMorePages.cfm";
In onRequestStart
var ThisPage = listlast(cgi.PATH_INFO, "/");
...
if (ListFindNoCase(application.securityNotNeededPages, ThisPage) is false) {
security related code
}
else {
code for when the page does not to be secured
}
Well, I have been experiencing same error as discussed here:
Coldfusion 10 File Not Found Error
I am using Coldfusion 11 , developer edition on my Laptop , Windows 8.1 Pro (OS).
People have suggested two approaches over there to overcome this problem:
1) Setting Missing Template in CFAdmin
2) Setup onMissingTemplate function in Application.cfc
I am basically not sure with any of the approaches , however, I would like to go with the first approach. Could anyone tell me how should I set up missing template in CFadmin?
Why do you prefer letting the server handle the missing template? Myself, I like to handle it on a per-application basis. Some applications should never have links leading to non-existing files, others may operate on that as part of its core.
Straight from adobe's docs, you can use (I accidentally pulled this info from cf8 docs, but the link is to current docs and the result is largely the same.
<cffunction name="onMissingTemplate" returnType="boolean">
<cfargument type="string" name="targetPage" required=true/>
...
<cfreturn BooleanValue />
</cffunction>
For a few of my projects, I've written a CMS (Content-Management-System) that stores all the content in the database in fashion.
CMSPages
------------
PID PTitle PFile PContent
1 Home /index.cfm <b>Hey!</b> Welcome to our gollygizmo website.
And then I (my real code actually uses cfincludes rather than directly in the document. You can do it either way, but it was easiest for me to demonstrate with inline code).
<cffunction name="onMissingTemplate" returnType="boolean">
<cfargument type="string" name="targetPage" required=true/>
<cftry>
<cfquery name="FindPage">
select * from CMSPages
where pFile = <cfqueryparam cfsqltype="nvarchar" value="#Arguments.targetPage#">
</cfquery>
<cfif FindPage.recordcount eq 1>
<cfoutput query="FindPage">show page stuffs</cfoutput>
<cfreturn true>
<cfelse>
<!--- Page not found, log some stuff or email stuff
include cgi data so you know where the link came from --->
Hey, this page doesn't exist, sorry about that.
<cfreturn true>
</cfif>
<cfcatch>
<!--- Something went wrong, log/email error info and --->
<cfreturn false>
<!--- We return false here to pass it back to the default error handler, which can be a handler set in cfadmin. --->
</cfcatch>
</cftry>
</cffunction>
In such a scenario, it's probably beneficial to cache queries based on query name, you can do something like
<cfquery name="local.FindPage#hash(arguments.targetpage)#" cachedWithin="...">
...
</cfquery>
<cfset request.FindPage=local["Findpage#hash(arguments.targetpage)#"]>
So that the queries are cached by unique names, even though it's easily accesible in your document by a common name.
However, if you still prefer server-centric missing template handling, a simple search for cold fusion admin missing template will bring you here.
In the ColdFusion Administrator, click on "Settings" to view the "Server Settings" page
Specify the absolute path that ColdFusion will use to find your error handling template
When a user logs in and is redirected to a secured page, the url is getting appended twice like a list. This in turn causes a 404.
(example: http://uwf.edu/something.cfm,http://uwf.edu/something.cfm)
Currently, the site has a custom login tag which I am unable to edit as I do not have control over it. (It's just a custom cf tag that allows people to login at the university.)
I have to do additional processing after this tag to verify that they are eligible to login on this particular site. Once they have been verified, they are re-directed to another page with cflocation.
<custom login tag>
<cfinvoke component="#application.path#cfc/security" method = "constructSession" returnvariable = "status">
.. params excluded..
</cfinvoke>
<cfif status eq 1>
<cflocation url="#someurl_invalid#" addtoken="no" />
<cfelse>
<cflocation url="#someurl#" addtoken="no" />
</cfif>
The custom login tag refreshed the current page already, but I obviously do not want that and thus had used the above method to re-direct. This worked in ColdFusion 8.
I read this article: http://www.bennadel.com/blog/2050-Changes-In-CFLocation-OnRequestEnd-Behavior-In-ColdFusion-9-s-Application-cfc.htm
The article gave me some insight as to what is going on...but I am unsure how to fix the issue.
Does anyone have any solutions?
Since you don't have control over the custom tag, you'll have to work around the issue instead of fixing it.
I would recommend changing the code:
<cfif status eq 1>
<cflocation url="#ListFirst(someurl_invalid)#" addtoken="no" />
<cfelse>
<cflocation url="#ListFirst(someurl)#" addtoken="no" />
</cfif>
It's not pretty but will work whether the URLs are lists or not.