IE and Safari cannot open/read/inflate gzipped CSS or JavaScript - coldfusion

I’ve run into a seemingly particular problem that I’ve been unable to figure out thus far.
I’ve gzipped a bunch of the static CSS and JavaScript files on our website for the client’s browser to consume. I am using a ColdFusion page to check the Accept-Encoding to determine if the browser says it can inflate the .gz files. If it cannot I send the regular .css or .js file.
After implementing this process I tested it on both my local and our dev environment with no issue in all major browsers with no problems. However, in our production environment only, Safari and IE cannot seem to inflate the gzipped files despite indicating they can when I check the Accept-Encoding.
Here is a snip of what Safari reads the file as:
¬� !T
common.css�}k��F��� �?�,4��#� �(�
�8{�� ���־� n %�JܖD-IuuY��~�Έ��$Um/p���.�̌�|E�;7���z����t�>��ݮ<=�o�թ =����r�}]��a��E��O�0�Sq�\���}m�S3j��||�V���-�i�:ز�ũ]��yyj�D�_����ܵ���"=y ���d�Ku��U����;�"[7�u]>�[��b���<< ���? �-]z�JOAi�� �� �� lPxJ bAOx�Mն�Q�Oƛꋪ�-S� � �~?��Q �,�� m��aw�5S�i��8�>
�G ���ݫ.��(h�Q O>�_wes>�/�'��u�¬6Nى�K�F"y�]
T1 fE� ¬�Į>
On all three servers are Windows machines, running ColdFusion 10 on tomcat. We are using IIS 7.5 on all servers as well.
After a lot of research last week, I’m no closer to an explanation/solution.
What I’ve read on the net as indicated that the “Transfer-Encoding: chunked” could be a problem. I can see it listed in the response headers of IE (Safari lists it as Transfer-Encoding: Identity) and this header only appears there when looking at the production environment as well.
In relation to the Transfer-Encoding, when it is not present (local and dev) the Content-Length header comes through where it is not present when the “Transfer-Encoding: chunked” is there.
Also I can confirm that Static compression is enabled in IIS for the site in all three environments.
Many people have recommended disabling chunked Transfer-Encoding via the ASP portion of IIS and while we could do this, I’m not sure if it’s a good idea?
ASP is NOT installed on our production environment and our Sys Admin is understandably wary of installing it (so it appears in IIS) when we do not write anything in ASP.
I have also read about forcing http/1.0 rather than allowing http/1.1 but this seems like a cop-out and a rather inefficient one at that.
But is that our only option? And if so, is it worth it? Am I even going about this is the correct fashion? I wanted to pre-compile the .gz files to eliminate any unneeded processing on our production server.
I’m not sure what other information I could provide to be helpful but I can gladly ass more info to this post if needed.
Example of .cfm that loads the CSS:
<cfparam name="URL.name" default="" />
<cfif Len( URL['name'] ) GT 0 AND Len( url.name ) LT 64 AND ReFind( url.name, "[^a-zA-Z\-\.\_]+" ) EQ 0>
<cfif CGI['http_accept_encoding'] CONTAINS "gzip" AND FileExists( ExpandPath( './css/' & url.name & '.gz' ) )>
<cfheader name="Content-Encoding" value="gzip" />
<cfcontent reset="true" type="text/css" deletefile="no" file="#ExpandPath('./css/#url.name#.gz')#" />
<cfelseif FileExists( ExpandPath( './css/#url.name#.css' ) )>
<cfcontent reset="true" type="text/css" deletefile="no" file="#ExpandPath('./css/#url.name#.css')#" />
</cfif>
</cfif>
<cfabort>

Related

how can I use cfdirectory to make a list of documents downloadable using ColdFusion/Lucee?

In my Application.cfc, I setup a mapping
this.mappings["/downloads"]="J:\Downloads\documents";
In my template, I have
<cfdirectory action="list" directory="#expandpath("/downloads")#" filter="*.zip|*.docx" name="downloads" recurse="yes">
<!--- <cfdump var="#expandpath("/software")#"> --->
<cfdump var="#downloads#">
<ul>
<cfoutput query="#downloads#">
<li>#downloads.name#</li>
</cfoutput>
</ul>
I'm trying to make the documents downloadable but when the link is clicked, nothing is happening which makes me think my links are not correct however when I mouse over the link, I see the full path which is correct.
What am I missing to make the list of documents clickable?
Here is the URL displayed when mouseover the 3rd document for example.
Since the files are outside of your webroot you will need to have ColdFusion read the file and send it back to the browser.
You will need to create a page, like download.cfm, that can accept a URL parameter to know which file to access. Once you have selected the file you can use something like the following to stream the file.
<cfheader name="Content-disposition" value="attachment;filename=#datafile#">
<cfcontent file="#datafile#" type="application/pdf">
The above code was pulled from https://www.raymondcamden.com/2006/03/10/Ask-a-Jedi-Using-ColdFusion-to-serve-files
WARNING:
Reading URL parameters in this way and giving people access to the filesystem is extremely unsafe. Safer alternatives should be considered before moving something like this into a production environment.
All I needed to do for this exercise is to setup a mapping in my Application.cfc. As others have stated, there is zero security here but for the purpose of this exercise of understanding virtual directories (IIS) and aliases (CommandBox), this is sufficient.
this.mappings["/guides"]="J:\guides";
Then I can use cfdirectory to build my query object
<cfdirectory action="list" directory="j:\guides" recurse="false" name="nameofqry" type="file" sort="datelastmodified desc" filter="*.docx">
Next, perform a cfoutput using my alias as the a href link
<cfoutput query="nameofqry" maxrows="40">
<li>#nameofqry.name#</li>
</cfoutput>

<CFPDFForm> Populating PDFs from MySQL DB (Quit Working)

Without warning and with no code change on my end the hosting company applied Update 19 to ColdFusion 11. They claim it's unrelated yet no PDF document can be populated from the DB.
Here's the beginning of the code that worked perfect for years.
<cfpdfform source="#ExpandPath( 'FORMS/PDF_FORM_TEMPATE.pdf' )#" action="populate" destination="#expandPath('TEMP/I9_#accountinfo.company_id#_#EMPLOYEE_ID#_#hog_data.LAST_NAME#.pdf')#" overwrite=true >
<cfpdfsubform name="i9Main">
<cfpdfformparam name="LAST_NAME" value="#hog_data.LAST_NAME#">
Then I end the code by writing it to the final destinations and output it to the screen for viewing.
<cfpdf action="write" destination="#expandPath('FINAL/I9_#accountinfo.company_id#_#EMPLOYEE_ID#_#hog_data.LAST_NAME#.pdf')#" source="#expandPath('TEMP/I9_#accountinfo.company_id#_#EMPLOYEE_ID#_#hog_data.LAST_NAME#.pdf')#" flatten="yes" overwrite="yes">
<cffile action="delete" file="#expandPath('TEMP/I9_#accountinfo.company_id#_#EMPLOYEE_ID#_#hog_data.LAST_NAME#.pdf')#">
<cflocation url="final/I9_#accountinfo.company_id#_#EMPLOYEE_ID#_#hog_data.LAST_NAME#.pdf">
This code has worked great until 6 Mar when the web hosting company applied ColdFusion Update 19. Has anyone has an issue with this or have suggestions?
First off, I want to thank all of you who provided suggestion. Turns out Adrian J. Moreno was correct. This issue was caused by an incompatible version of the Java Run Time Environment. Updating this fixed the issue and populating PDFs is now working again site-wide.

How do I locate a custom tag instantiation in a coldFusion App

I am migrating a very old app (currently running in CF8) to Lucee. But I am running into a problem with what appears to be a custom tag of some sort.
I have tried to make sure that all the virtual directories are the same in IIS for both the old and the new installs. And made sure the mapping and custom tag paths in both the CFIDE and the Lucee Admin are the same.
But I am getting this error. And can't figure out how this cflink is being instantiated.
I have found the location of the erroring code on line 300 the utils.cfc file
I haven't used custom tags in a long time but thought they were generally called with an underscore and the code should like more like <cf_link pageid="#LinkPageID#" Init="start"> if this was being called as a custom tag.
If I go the the current CF server that is running this app I can find that a cfclass files HAS been created
From a file called cflink.cfm in a directory called "tags" even though there seems to be no mapping for the "tags" directory nor is is listed under "custom tags paths" in the administrator.
This App was start in 2003 and as you can imagine has grown into a mis-match of spaghetti code and no one from the beginning is around to ask how this tag is instantiated.
Does anyone with experience in legacy code has any other ideas where I should be looking to try to get this to work? The currently has only a production environment and if I can get it to work on Lucee it will not only be a dev environment that hasn't existed here in 10 years but will be a great way for me to be able to continue showcasing Lucee as a great CFML engine
Adding addition info
Leigh had asked if the init might be a jar reference but in the cflink.cfm file I see this code:
<cfif Attributes.Init IS "start">
<cfset Request.PageID = Attributes.PageID>
<cfset Request.Page_Width = Variables.qParentInfo.Page_Width>
<cfset Request.Page_Height = Variables.qParentInfo.Page_Height>
<cfset Request.Page_TypeID = Variables.qParentInfo.Page_TypeID>
<cfset Request.AddPath = "">
<cfif IsDefined("Attributes.Anchor")>
<cfset Request.Anchor = Attributes.Anchor>
<cfelse>
<cfset Request.Anchor = "">
</cfif>
<cfset Request.IsInternalLink = false>
<cfexit method="EXITTAG">
</cfif>
There are also references to cflink in the code inside tags\cflink.cfm
<cfif Len(Variables.qParentInfo.ParentID) GT 0>
<!--- Add the page title to the end of the path --->
<cfset Request.AddPath = ReplaceNoCase(Variables.qParentInfo.Nav_Title," ","_","ALL") & "/" & Request.AddPath>
<cflink init="working" pageid="#Variables.qParentInfo.ParentID#" popcode="#Attributes.popcode#">
<cfelse> ......</cfif>
Although this may be recursion given it was written in 2004 I kind of doubt it
Adding screen shots of searches
If anyone else runs into this. In CF8, and presuming earlier versions, you could put a cfm file into the ColdFusion8\wwwroot\WEB-INF\cftags Directory and that file in this case ColdFusion8\wwwroot\WEB-INF\cftags\link.cfm Then acts as any other cftag.
I was able to find the person who originally build this app in 2004 and he told me that they did it this way to avoid typing the underscore that they would have typed if they'd done it as a custom tag.
I kind of get it since this tag is used everywhere in the app, literally hundreds of times. Bit boy with a bitch to find.
Now all I have to do is figure out how to move it to the Lucee world in a similar fashion. So it instanciates the same way.
Thanks #Leigh for all your help, you are always amazing!
Adding more information
if there are files in the WEB-INF\lucee\library\tag the corresponding Lucee directory is WEB-INF\lucee\library\tag. These files are read on load and then able to be used as any other cf tag.
For example if you have file WEB-INF\lucee\library\tag\link.cfm it can be called by `cflink'.
Seems like a cool idea but a bit of a bitch for someone to find 10 years after the fact

ColdFusion - How to limit data retrieved via CFHTTP?

I am using cfhttp to get documents and parse the content like so:
<cfhttp
method="GET"
url="#url.strURL#"
resolveurl="true"
useragent="#CGI.http_user_agent#"
result="objGet"
timeout="60"
charset="utf-8"
/>
However, some of the documents are rather large. I do not need to get the entire thing - which could take a long time.
Is there any way in which I can stop running cfhttp after X number of bytes loaded? Or set a limit on how much to get for example.
Appreciate the help.
If the target server supports it, you can use the Range http header:
<cfhttp
method="GET"
url="#url.strURL#"
resolveurl="true"
useragent="#CGI.http_user_agent#"
result="objGet"
timeout="60"
charset="utf-8"/>
<cfhttpparam type="header" name="Range" value="bytes=0-499" />
</cfhttp>
Apache and IIS supports this, so for static content you'll probably be in luck. Dynamic content would be trickier...
...I've just tried this with a CFM being served through Apache, and it looks like that didn't work. I suspect that if Apache/IIS is serving a static file, then it can safely send back a range of bytes from the document you're requesting because it can read the file. If the request is for something being generated by CF/ASP/JSP/whatever, then it'd be up to the Appliation to honour the Range: header in the request. In my case, I still got the whole document because my Application doesn't look at the Range header.
I should also mention that it's possible to do what you're after in Java, as you've got finer-level control of what's going on, but you'd have to write something yourself or use one of the alternative HTTP Client Libraries out there. It depends how important the feature is to you I suppose. If the documents are seriously large then you may need to use the file attribute of cfhttp to avoid getting the whole response into memory, which could cause crashes.

Is ColdFusion Scripted Linearly? Why this error?

I have received this error
Element CUSTOMERID is undefined in CLIENT.
D:\Inetpub\wwwsitecom\wwwroot\rders.cfm:296
on a page that begins with the following code:
<cfif NOT CreateObject("component","User.User").IsLoggedIn()>
<script type="text/javascript">
window.location.href='/index.cfm';
</script>
<cfabort>
</cfif>
<cfif NOT IsDefined("client.customerid")>
<cfparam name="client.customerid" default="0">
<script type="text/javascript">
alert("We're sorry.");
window.location.href="/logout.cfm";
</script>
<cfabort>
</cfif>
and on line 296
<cfinvoke component="Account" method="getAccessInfo" returnvariable="getInfo">
<cfinvokeargument name="customerid" value="#client.CustomerID#">
</cfinvoke>
The IsLoggedIn Function has this piece of code
<cfif NOT StructKeyExists(client,"customerid")>
<cfset strIsLoggedIn = 0>
</cfif>
If ColdFusion processes scripts linearly, how would it have gotten to the undefined client.customerid on line 296 without processing the first parts of the page?
If ColdFusion does not process scripts linearly, how can I prevent this error?
First, I would check that you aren't creating a variable somewhere (perhaps in an implicit scope in a <cfoutput> or <cfloop> tag) that's named client. Since CF is a late-bound language, that can change the semantics, and references to client.CustomerID will be looking in your local client variable, not the Client scope.
Secondly, if you want to do a redirect, please, please, use <cflocation> instead of doing this crazy JavaScript redirect. Remember that JavaScript is executed on the client side, and it is perfectly possible (and not even that uncommon) for browsers to have JavaScript disabled. <cflocation> results in an HTTP 3xx response being sent, which will work correctly in any browser that implements HTTP, regardless of whether or not JavaScript is enabled. It's also much more secure, since there's no chance of parts of the page being flushed to the client before the redirect.
Make sure you have client variables set up correctly in cfide and check that they are enabled in your Application.cfc file.