How safe is createuuid in a clustered environment? - coldfusion

The title pretty much says it all. The scenario is a user uploads a file but they could be hitting 1 of 6 servers depending on the current load at the time. We have run into a situation where the users are trying to upload files with special characters in their names. We can write a function to sanitize the file name but then we have to check that the new sanitized file name doesn't exists. My thought was to just rename the file using createuuid(). I believe the createuuid() function uses the servername as part of the algorithm if I remember correctly so if anything, the uniqueness should be 6 fold due to the 6 servers. Am I correct in this thinking?

If I remember correctly, CF uses timestamp+clock+servername.
Did you consider sanitizing the uploaded filename and just append the UUID? This appears failproof to me.

Related

Can I write a file to a linux directory specifying file permissions in cfscript?

I have a function which writes a coldfusion query result as file to the temp directory. It works fine, and saves having to run the query so often.
However, I want to write a git hook to delete these cached files as when we push new code the data may have become stale and so should be replaced. The files are created by the apache user in 644 mode. The git user is in the same group as the apache user, so for the git user to be able to delete the files, I want to either create them in, or subsequently set them to 664 mode.
Initially I added fileSetAccessMode after the objectSave I was using:
objectSave( data, filepath );
fileSetAccessMode( filepath, '664' )
However this didn't seem to have any effect, so tried
fileWrite( filepath, data, '664' );
which also seems to write the file fine, but not set the the permissions.
I note that the Adobe Docs for fileWrite don't specify a parameter for mode, so I guess that's why that doesn't work. I much prefer cfdocs.org in general but I was quite confused by their take on the cfscript versions of cffile, as it wasn't obvious which functions used which parameters.
After some more googling, I found this cflib.org cftag style function which I guess I could borrow and reference in cfscript but I don't really want to have to do that.
What I really want to know is, can I achieve this purely in cfscript or is there a genuine difference in API functionality between script and tag? (I'm pretty sure this is the case in other instances).
Very grateful for any input.
After taking a break and coming back to this, I discovered that I can use
fileSetAccessMode( file, '664' );
In cfscript, and embarrassingly I had it in the wrong place in my code. However, it is still necessary to do that separately having created the file previously because
fileWrite( file, content );
doesn't support the "mode" parameter as in
<cffile action="write" file="file" output="content" mode="664">
having consulted with some wiser members of the community, I have filed this as a bug with Adobe.

Human readable file name

Whenever I create an ImageField using a file called moon.png, Django, correctly following my configuration settings, puts the file in:
campaign/primary-banner/2015/11/25/moon.png
or
campaign/primary-banner/2015/11/25/moon_RcJ3FuD.png
And that is the value of imagefield.name, which I can show to the user, but is not really user friendly.
I would like to show the name of ImageField.name, but in a human readable format. Is it possible to extract the original file name (moon.png) from the ImageField? The workarounds that I can think of are:
add an extra field to my model to hold the human readable file name. Extra work, which I would like to avoid: DRY.
process the imagefield.name value to extract the original filename, but this seems too complex (I would need to exactly understand how django is generating the filename in the first place, to make sure I cover corner cases)
I had similar problem and solved it by creating my own subdirectry under MEDIA_ROOT, in which I made directory structure involvind the date and also some unique identifier. Then I moved my file to that final subdirectory and put the name to FileField.name. Everything works like charm - files are unique (thanks to unique directories) and the final name is exactly what i want user to see (as there is no need to rename it - no conflict is possible)
p.filename=get_filename_of_existing_file_to_be_stored()
p.originalfilename=get_how_it_should_be_named()
masterobject=MyNewMaster.objects.get(pk=some_id)
uniq_name=masterobject.make_something_unique()
new_object=MyObject()
new_object.master=masterobject
new_object.some_fields=some_values
daystr=date.today().strftime('%y-%m-%d')
directory='MyDir/%s/%s/%s/'%(daystr,masterobject.id,uniq_name)
if not os.path.exists(os.path.join(settings.MEDIA_ROOT,directory)):
os.makedirs(os.path.join(settings.MEDIA_ROOT,directory))
fname=os.path.join(directory,p.originalfilename)
os.rename(p.filename,os.path.join(settings.MEDIA_ROOT,fname))
new_object.filename = fname
new_object.save()
Now everthing works for me and no conflicts are possible and even Django seems happy with this hack and provides the correct filename and url for everything i tried to do with MyObject :)
Now I ended with path like:
MyDir/2015-11-29/12345/child_7/moon.png

How does one determine the filetype on an AWS S3 hosted file without the extension?

As an example, I'm currently uploading items directly to an S3 bucket using a form. While I was testing, I didn't specify any expected filenames or extensions.
I uploaded a .png which produced this direct link:
https://s3-us-west-2.amazonaws.com/easyhighlighting2/2015-07-271438019663927upload94788
When I place this inside an img tag, it displays on a web page properly.
My question is, without an extension, how would my browser know what type of file it's loading? Inside the bucket, the file's metadata isn't even filled out.
Is there any way to get that file extension, programmatically?
I'm ready to try any clientside methods available; my server-side language is ColdFusion which is somewhat limiting, but I'm open to suggestions for that as well.
Okay, so after some more extensive digging, I found a method of retrieving the file's type that was only added since CF10 was released; that would explain the lack of documentation.
The answer lies in the FileGetMimeType function.
<cfset someVar = "https://s3-us-west-2.amazonaws.com/easyhighlighting2/2015-07-271438019663927upload94788">
<cfset FileType = FileGetMimeType(someVar)>
<cfoutput>#FileType#</cfoutput>
This code would output image/png - which is correct and has worked for every filetype I have tested thus far.
I'm surprised this kind of question hasn't popped up before, but this appears to be the best answer, at least for users of CFML.
Edit:
ColdFusion accomplishes this by either reading the contents of a file, or by trusting its extension. An implicit attribute, 'strict', is used in this function. If true, it reads the file's contents. If false, it uses the provided extension.
True is the default.
Link:
https://wikidocs.adobe.com/wiki/display/coldfusionen/FileGetMimeType
Check the Content-Type HTTP response header returned by Amazon S3.
For example, curl -I https://s3.amazonaws.com/path/to/file fetches only the headers.

In Sitecore 7.2 file upload ,the path is coming as media\test\abc.pdf instead of media/test/abc.pdf

I am trying to add one file from file directory in directory.
While I am clicking on +(insert file) the and selecting a file from directory the path is formed as media\test\abc.pdf instead of media/test/abc.pdf.
Even though chrome is able to resolve the url Firefox is not.
I believe it's because you're using a physical file path that you're getting the backslash. One of the simplest things you can do is a string.Replace() expression to make every backslash a forward slash.
Not sure what your specific use case is, or how much work it would be, but if you're going to use the path on the web and your PDF is located in the MediaLibrary, it might be worth looking into using the URL property of the Sitecore.Data.Items.MediaItem object.

Moving files in a verity collection

I have a collection of files which have been added to a verity collection. The filename, with complete path, has been used as the key.
I would like to move the location of the files on disk, but I am concerned that I will end up with duplicate entries (when I update the same file, the path to the file will be different, so I'll have an entry for the old file and an entry for the new one).
I wasn't involved with the original application setup, and I don't know much about verity or coldfusion (the rest of the app is in PHP). Can anyone suggest how I can go about running some sort of regex replace on each key in a verity collection, or possibly suggest another approach?
I would recommend to create new collection, adjust to your new specs (at least new path in your case) and swich to it in the application code (replace the collection name in cfindex/cfsearch).
After making sure it works properly you are free to delete the old one.
If you can not create collection for some reason, you can simply purge the collection, switch the path and re-index it.
Please note that you can do all of this directly from the application (maybe temporarily script) using cfcollection tag, and using CF Admin (see Verity Collections in menu) too.