is cffile action="rename" === fileMove in CFScript? - coldfusion

Does fileMove() do exactly the same thing as <cffile action="rename">?

No they are different. There is no CFML Script function available to do a file Rename. So, the above use case is just a trick to achieve file rename.
You have to specify the same source and destination folder but change the file name in <destination>.
filemove("c:\userdata\files\myFile.docx", "c:\userdata\files\yourFile.docx");

Related

How to specify a relative in CFFile?

This is the path of my json file: https://devbox.mysite.com/search/KOGroups.json
But instead of using cfhttp, I like to use cfifle with read action. I don't know how to turn this path into a relative path for cffile. I've read about this ColdFusion Read File article and it looks like they use absolute path in their example. I've tried Ben Nadel's "Relative File Paths Work In A ColdFusion File System" article but the code that he provides for getting the parent directory is not working for me. All I need is to turn this path, https://devbox.mysite.com/search/, into cffile tag so I can read the .json file.
Use the function expandPath() for this.
expandPath('../path/to/file') returns the full server path to that file.
Looks like BKBK over in Adob coldfusion forum answered my question with the following:
<cfset koGroupsJSON = fileRead("https://devbox.mysite.com/search/KOGroups.json")>

CFZip of certain file type

Is it possible to use cfzip to create a zip folder containing of a certain type. I need to do this to take out .bak files from a folder with different filetypes and insert them into a zip folder.
Thanks
Colin
Steve already pointed you to the CF documentation which has example of delete. To create a zip, the simplest way is as follows:
<cfset fileName = createUUID() />
<cfzip file="D:\#fileName#.zip" action="zip"
source="D:\myfolder"
filter="*.bak"
recurse="No" >
If you want to add the files of a sub-directory, then make recurse="yes". To filter multiple file types you can simply use comma separated file type in filter like this filter="*.jpg, *.gif, *.png"
Note: I have used dynamic file name in case you want to run this script multiple times and have different file name, or multiple users are accessing this script at the same time.

ColdFusion CFFILE to limit text file upload

I'm want to use CFFILE upload to detect only .txt file. I've tried to use file.clientfileext to detect the extension. When TXT is detected, I'm showing a pop up error message to users and delete the file. But I was told I should not even allow user's file to reach our server.
Then I use CFFILE accept attribute to only accept text/plain. This should do it but unfortunately on my test when I tried uploading non text file I got ColdFusion error:
The MIME type of the uploaded file application/pdf was not accepted by
the server. Only files of type text/plain can be uploaded. Verify
that you are uploading a file of the appropriate type.
I tried to use cftry and cfcatch but I still get the same error, this mainly due to the MIME Type that I don't know when the file is being uploaded by the browser.
I also found the same question in this forum and tried the suggested answer, it did not work, still got the same error message (see below)
I also found another posting in this forum that do not suggest the use of CF "accept" attribute. This link is provided for a further detail explanation: http://www.petefreitag.com/item/701.cfm
So my question is, since I'm still using CF8, I actually don't have many options to prevent my users from uploading other than .txt file securely?
If I can't use the accept attribute of the CFFILE, can I at least secure my file upload functionality by doing the following? but is doing it this way safe enough?
Upload the file to a temp folder that is not under the root dir
verify the file extension
change the file name even if the extension is detected to be a .txt
move the file to the destination file under the root dir
Even if I do these steps, I have to allowed the file to reach our server, the order is to NOT allow the file to reach our server.
Below is the answer/suggestion from previous question. But it doesn't work when I tested it:
<CFTRY>
<cflock name="write_lock" type="Exclusive" timeout="120">
<cffile action="upload" filefield="filepath" destination="#DestDir#"
nameconflict="Overwrite" attributes="Archive">
</cflock>
<CFCATCH>
<cfif FindNoCase("not accepted", cfcatch.Message)>
<script>
$(function(){
alert("Only the following file types are allowed: .jpg, .gif, .bmp,
.png.");
});
</script>
<cfabort />
<cfelse>
<!--- looks like non-MIME error, handle separately --->
<cfdump var="#cfcatch#" abort />
</cfif>
</CFCATCH>
</CFTRY>
I think your steps are reasonable if you don't like using the Accept attribute for validation. FYI you can set accept to .txt instead of the MIME types. The MIME type was determined by the client so it's safer to check the extension anyway.
The exception thrown by cffile failing attribute validation may not have a type, so the code you posted tried to detect it with FindNoCase() by looking at the exception's message. You can dump the exception out and find out why the FindNoCase() failed to catch the exception.
Make sure you treat whatever uploaded as something potentially malicious and do not process them (e.g. cfinclude them). Forcing the file extension to be .txt should be safe enough, but I'll let other security experts charm in.
You can use the below code:
<cffile action="upload" filefield="BidDoc"
destination="C:\upload\"
nameconflict="makeunique"
accept="text/plain">
The other mime types which you may use are:
application/pdf
application/msword
application/vnd.ms-excel
application/vnd.openxmlformats-officedocument.wordprocessingml.document
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
As discussed in this answer, there really is no 100% fool-proof way.
If you don't want to trust the "accept" attribute, I would suggest allowing the user to upload the file and then checking the mime type of the uploaded file using the cffile.contentType property. Check against whatever mime types you wish to allow/restrict and reject with the appropriate message. You may also choose to employ a check of the file extension as an added layer of error checking.
It must be noted that like file extensions, mime types can not be 100% trusted to be accurate as they can be edited by the user. But using a combination of checks you can be reasonably that most files uploaded are of the correct type.
Coldfusion will not prevent a file from being uploaded to a server. You can set a maximum file size but this is processed during the upload. The cffile tag kicks in after the file is uploaded. Furthermore it is rather difficult to really determine if a file is a text file or a jpg, exe, rar etc file. The following q & a may help:
Determining binary/text file type in Java?
In my opinion it is best to follow the tips given by pete freitag and use a java class to determine the file type. Then you can delete all non text files.

Can <cfdirectory> location work with site-relative locations?

I've noticed that when using the tag to create a directory and then subsequently upload/delete files using , it wants a full-path from the root of the drive that website is hosted on. I would rather use site-relative locations if possible.
Here is an example of what I would like to do:
<cfdirectory action="create" directory="users/files/myfiles">
But this ends up creating a new folder structure of C:\users\files\myfiles in the hard drive. In order to get it to make the directory within my site itself I have to write this:
<cfdirectory action="create" directory="/inetpub/wwwroot/mysite/users/files/myfiles">
I don't like the idea of having to put the fully qualified path. Its not very flexible for my needs.
Its the same issue with deleting a file. I have to put in the file path starting from its location on the hard drive, rather than relative within the website's folder. Is this normal behaviour?
Just use expandpath(); this will lookup the site root for you. That way you don't need to hard code it.
i.e,
<cfset rootdir=expandPath('/users/files/myfiles')>
<cfdirectory action="create" directory="#rootdir#">

How can I confirm a cffile write is successful?

I am using cffile to create a new file or update an existing file, depending on what the user requested. The request comes through a form from the previous procedure, so the code involving cffile looks like this:
<cfset thefile = "#form.dyn#">
<cfoutput>
<cfsavecontent variable = "testvar">
#form.editor1#
</cfsavecontent>
<cffile action = "write"
file = "/var/www/reports/#thefile#.cfm"
output = "#testvar#">
</cfoutput>
When I am done writing to the file, I want to confirm to the user that this happened. For a new file I could use IsDefined to check that it is there. But I can't think of a way to check for an existing file that was updated. I considered a try/catch on the cffile, but the catch operates only if nothing seems to go wrong. If I don't get an error on the catch, can I assume everything is all right? I would prefer a direct check if possible. Does anyone have an idea?
If <cffile> doesn't work, it'll tell you by throwing an exception. If it doesn't do that, you can safely assume it has worked. Don't over-engineer your app.
You could use cfdirectory with the action="list" and filter="your-filename" to get the following information about the uploaded file:
If action = "list", cfdirectory returns the following result columns, which you can reference in a cfoutput tag:
name: Directory entry name. The entries "." and ".." are not returned.
directory: Directory that contains the entry.
size: Directory entry size.
type: File type: file, for a file; dir, for a directory.
dateLastModified: The date that an entry was last modified.
attributes: File attributes, if applicable.
mode: Empty column; retained for backward compatibility with ColdFusion 5 applications on UNIX.
Of interest to you is the dateLastModified column.
So you should be able to do something like:
<cfdirectory action="list" name="dirQuery" directory="C:/var/www/reports/" filter="#thefile#.cfm">
Then you can dump that result to see what information is available to you:
<cfdump var="#dirQuery#">
The dateLastModified column can be accessed like:
<cfoutput>#dirQuery.dateLastModified#</cfoutput>
Use CFDirectory to get the file's dateLastModified before you update the file and then again afterwards. If they are not the same, then it was updated.