Add XSLT validation on XSLT File Upload - ruby-on-rails

I have a Rails application with Paperclip file upload which is used to upload a XSLT file. I am looking for ways to validate the XSLT file before uploading. i can actually validate the content_type using paperclip
validates_attachment_content_type :xslt, content_type: "application/xslt+xml", message: 'Invalid Content Type. Please upload a valid XSLT file'
Is there a way I validate the XSLT file completely for syntax before saving it?

Yes, you can use Oxygen Editor to validate it or you can write the .net tool to validate it using Saxon dll.

Assuming you have the xslt files you could use the Nokogiri gem and do it as follows:
validate :xslt_validation
def xslt_validation(xml_message)
xml = Nokogiri::XML(xml_message)
template = Nokogiri::XSLT(File.open(Rails.root.join('path from root to xslt')))
validation = template.transform(xml)
result = Hash.from_xml(validation.to_s)['Name of the error report']
errors.add(:xslt_field, "XSLT errors: #{result['Errors']}") if result['Errors'].present?
end

Related

CDF V2 Document, No summary info. while using paperclip

Content type not recognizing while uploading files using paperclip + jquery file upload.
Throwing below error "content type discovered from file command: CDF V2 Document, No summary info. See documentation to allow this combination"
fail to upload the same.
We can fix this issue by adding below file in the intializers in rails -
# config/initializers/paperclip.rb
Paperclip.options[:content_type_mappings] = {
:xls => "CDF V2 Document, No summary info"
}
This solve my problem, hope this will help you as well.
Thank you.

Converting .txt file to .xml ruby on rails

I have a custom file type (.map) that I am unzipping from a Gzip file and then writing to a new file in order to pass it along to Paperclip and upload to s3. My problem is that the type should be an xml, while it is saving as a text document instead with all xml formatting correct. I need a way to convert it into the xml type and then save that as a new File object before passing it along.
Here is my code so far:
Zlib::GzipReader.open(f.tempfile) do |gz|
puts gz.orig_name
#tmp = File.new(gz.orig_name, "w+")
while chunk = gz.read(16*1024) do
#tmp.write(chunk)
end
end
reader = #tmp.read
s = location.posts.create!(
subject: #email.subject,
from: #email.from[:email],
mapfile: #tmp)
}
ideally i will be passing mapfile the xml type file, but right now it seems to be text
Update:
So now I have set my post.rb to do this, and added a name attribute to post containing the original file name:
has_attached_file :mapfile,
:preserve_files => "true",
:path =>
':rails_root/non-public/system/:id/:basename.:extension',
:url => '/:class/:id/mapfiles',
:s3_headers => lambda { |attachment| {'Content-Disposition' => "attachment; filename = #{attachment.name}"}}
And this works perfectly!
It sounds like you are talking about `Content-Type'. When you save a file to the filesystem, you can't set this: the system will decide what to use based on the file extension and possibly by analysing the contents, if it's a text file.
However, you can set the content type when you serve a file to someone's browser, and when you upload it to S3. See here for the latter Setting the Content-Type in direct to S3 upload using Rails and jQuery File Upload

Paperclip + RSpec: content_type validation

I am using Paperclip in my Rails application for attaching images.
I declared validation for content_type in my model as
validates_attachment :image,
:content_type => { :content_type => ["image/jpg", "image/gif", "image/png"] }
I have two examples, one with a valid image and other with an invalid image
For an invalid image, i just renamed a .txt file to a .png
it "Image is valid" do
image = File.new("#{Rails.root}/spec/support/right.png")
expect(FactoryGirl.build(:pin, image: image)).to be_valid
end
it "Image is invalid" do
image = File.new("#{Rails.root}/spec/support/wrong.png")
expect(FactoryGirl.build(:pin, image: image)).to have(1).errors_on(:image_content_type)
end
I expected that both my examples should run successfully. BUT, my second example fails.
I don't get any error for content_type of wrong.png.
I thought that Paperclip's content_type validation would actually check file format(binary data encoding) of an uploaded file. BUT it seems that here, its just checking for the file extension. Does this validation only check extension of an uploaded file?
I maybe missing something here(configuration?). Is there any other validation available in Paperclip to achieve this? Or should I opt for a Custom Validator in this case?
This issue is resolved in Paperclip's latest version 4.1.1 released on February 21, 2014.
Both of my following examples pass correctly now.
it "Image is valid" do
image = File.new("#{Rails.root}/spec/support/right.png")
expect(FactoryGirl.build(:pin, image: image)).to be_valid
end
it "Image is invalid" do
image = File.new("#{Rails.root}/spec/support/wrong.png")
expect(FactoryGirl.build(:pin, image: image)).to have(1).errors_on(:image_content_type)
end
After a little bit of research found out that,
When I upload an invalid image,
For example: spoof(renamed) wrong.txt file as wrong.png and upload.
In prior release of Paperclip, wrong.png passes the content_type validation with flying colors without giving any error because Paperclip only used to check the extensions of the uploaded file and not content within.
Whereas, In the current release of Paperclip 4.1.1, same spoofed wrong.png fails the validation and throws the following error in view:
Image has an extension that does not match its contents
Upon investigating server log entries, I found the following:
Command :: file -b --mime-type
'/var/folders/tg/8sxl1vss4fb0sqtcrv3lzcfm0000gn/T/a7f21d0002b0d9d91eb158d702cd930320140317-531-swkmb8'
[paperclip] Content Type Spoof: Filename wrong.png (["image/png"]),
content type discovered from file command: text/plain. See
documentation to allow this combination.
Here, you can see that Paperclip actually checked the content of the uploaded file stating text/plain and also erred out saying Content Type Spoof.
Hope my findings will help others to understand how Paperclip's content-type validation has improved over the time.

Import excel files using Paperclip, S3 and Roo

I'm trying to import an excel file using Paperclip and save it to S3 then extract and parse using the Roo gem.
When I attempt something like this:
#excel = Excel.new(#manifest.attachment.url)
I get the following error:
http://s3.amazonaws.com/mybucket/attachments/22/manifest.xls?1343835058 is not an Excel file
I'm guessing the appended timestamp on the end of the filename is causing Roo to not think this is an Excel file.
How do i fix this?
To remove the timestamp you need to pass the 'false' argument in the url method.
For you : #excel = Excel.new(#manifest.attachment.url)
you should try with #excel = Excel.new(#manifest.attachment.url(:original, false)) then you will be getting the following url:
http://s3.amazonaws.com/mybucket/attachments/22/original/manifest.xls
But if you are trying to retrieve the image url then you should have #manifest.attachment.url(:large, false). Note: it can be :large, :medium or your customized styles in the model.
I hope that this might help you to solve your issues.
thanks

Cannot send xlsx as attachment in Rails mailer

I am trying to send an email containing a file attachment created by the user.
attachments[document.display_name] = File.read(document.public_filename)
This works in most conditions (including .docx, but fails for .xlsx files with the error:
invalid byte sequence in UTF-8
I am using attachment_fu to upload the attachments, and delayed_job to defer sending the emails, however the file I am trying to attach looks ok, and I can open it successfully outside the application.
I also saw a suggestion to change the code as follows, but it does not seem to help:
include an extra.
attachments[document.display_name] = { :content => File.read(document.public_filename), :transfer_encoding => :binary }
How can I make the code work for all attachment types?
You need to specify the mode or encoding to let it read the file as binary:
attachments[document.display_name] = File.read(document.public_filename, :mode => 'rb')
or
attachments[document.display_name] = File.read(document.public_filename, :encoding => 'BINARY')

Resources