(rails) how to validate whether an uploaded .txt file is not, say, an image file? - ruby-on-rails

I have a upload text file field, and with it I plan to save the file somewhere and then store the location of the file in a database. However, I want to make sure the file they uploaded is a .txt file, and not, say, an image file. I imagine this happens in the validation step. How does one validate such a thing? Also, how do you get the filename of the uploaded file? I could always just check if it said '.txt' but for future reference knowing how to validate without just the filename would be helpful.

Trying to validate the contents of a file based on the filename extension is opening the door for major hackerdom. It's trivial to change the extension and upload the file.
If you are on a Mac/Linux/Unix-based system the OS "file" command is the standard because it looks inside the file for key bytes that flag file types. http://en.wikipedia.org/wiki/File_(Unix) I'm not sure what's available for Windows, but this might help: Determine file type in Ruby

One way of doing it, the simple way really, would be to pass the file through an image loader, preferably one that handles multiple common formats, and see if it throws an error.
The other way is to manually check the file header for common image format headers. For example, .bmp files start with BM. Other formats have their own specific markings you can use.

Related

What is the header Content type suppose to do?

So i have this ASP.Net app and i want to allow the client to have the option to download an xlsx file, im using the HttpContext.Response to set the Content Type "application/xlsx" and the Content-Disposition sets the file name with the extension .xlsx, the download works correctly.
if I change the file name to .pdf then the file is downloaded as a pdf, when I checked the developer tool network response the Content Type was "application/xlsx" and in another test I change the name fileto .png and the file was downloaded as an image (it did not work, but it was shown as an image)
So what is the content type supposed to do, does it bring some sort of security how do i make sure that the user can only downloads the file associated to the content type?
Im using response.BinaryWrite()
A content type indicates what type of content is being transmitted over http regardless of the content name. For example as you already have tested, you can transmit a pdf file naming it as a .png file.
It is the browser or the operating system that is representing a file with the name .png as an image to you. Another software would treat a pdf file with .png name as a pdf file.
The name of the file matters after the download is complete. But the software that is handling the download (in this case a web browser) actually may need to know the original media type. And you might want to write client side codes that would need to know what type of file is being transferred from the server regardless of the file name.

Making my own container file type

I would like to create a file type with a personal extension by combining two other file types, like .mp3 and .pdf.
Later I need to re-open the custom files I've made and be able to use the included files in my app.
How do I do that on iOS?
One option is to append the data of the two files together. Include a few bytes of data at the start that tell you the size of each and maybe their original filenames. Then when you want to recreate the two files from the one custom one, you read your header to get the sizes and names, then use that info to recreate the original files.
Another option would be to zip the two files together. Just give the zip file your own custom extension.
Another option would be to use an NSFileWrapper. Include the two regular files in the wrapper.

Download Directory and Contents

Is it possible to persuade the stream result to download an entire directory and it's contents? And if so, how? I've no problem getting it to download individual files, but I have a need to download a series of files that must be in a specific directory structure.
I don't think so.
Stream result allow you to download ONE content, with its MIME type, its name, etc.
This makes it impossible to work with a lot of files, with different names and content type.
What you can do is:
Render in a JSP the list of files (in anchor tags for example), everyone targeting the Action that will download that single file;
Call multiple Actions via scripting opening multiple pages (target="_blank") for every file you have (dangerous, annoying, almost useless...);
Create a zip with Java in server side, containing all your files and directories, then output the zip with Stream result.
I think you may consider the third option.

Ruby file copy produces different file

I'm not very familiar with file handling in ruby. A problem I've come accross is that reading and writing a binary file doesn't produce exactly the same file.
clone = Tempfile.new(tempfile.original_filename)
FileUtils.copy_stream(tempfile, clone)
clone.flush
From the image below it is clear that it is not an exact file copy, when I try to open the newly created file in an image viewer it reports that the file is corrupt. I have tried copying the file in different ways such as clone.write(tempfile.read), etc. without success.
*The file viewer also indicates the original is ANSI Dos/Windows and the clone is ANSI Macintosh. The file size also differs by about 200 bytes.
What I'm trying to accomplish is actually simply using a Tempfile twice. A file is uploaded via rails and given to me as a Tempfile. I want to submit it to two different restful services and RestClient.post closes the file automatically. Another option would be to submit some sort of in memory stream clone to RestClient so that it can not close my file. If I submit File.open(tempfile.path) to RestClient it produces the same broken file, this indicates that the reading is the problem and not the writing. If I submit the original Tempfile object to RestClient it works perfectly but then it is closed and deleted and I cannot send it again.
Please help!
Regards,
Pierre
It would be much more helpful to see a hex view of these files instead of a text editor's intepretation. My guess is that at least one of the files is not opened in binary mode. In Ruby 1.9, try
open(filename, 'rb')
open(filename, 'wb')
Tempfile.new(filename, :binmode => true)
for opening a file for reading / writing and to create a binary temporary file, respectively.

Upload file type verification with Rails and Javascript

I'm currently working on a project where users can upload datasets in CSV format.
Is there a good way with Ruby other than checking file extension to determine if they're really uploading a CSV and not some executable or some other file type?
You can't do this in javascript that's for sure. If you're in a UNIX environment, you can check the documentation about this.
I don't think there is any SURE way of checking this. Usually checking the file extension is fine. Plus you said you're getting CSVs, couldn't you try to parse them? If it fails, then either the document is not at the right format or it's not a csv.
Anyways, make sure that you're storing your files in a directory that has no execute access right.

Resources