From 9705c249ac9da3aeb9f5bd86aeaf3a98a7ea4f2d Mon Sep 17 00:00:00 2001 From: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com> Date: Fri, 15 Feb 2019 14:59:15 +0000 Subject: [PATCH] Sanitize no-parsable BOM characters inserted by Excel --- .../admin/product_import_controller.rb | 3 ++- app/services/upload_sanitizer.rb | 18 +++++++++++++++++ spec/services/upload_sanitizer_spec.rb | 20 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 app/services/upload_sanitizer.rb create mode 100644 spec/services/upload_sanitizer_spec.rb diff --git a/app/controllers/admin/product_import_controller.rb b/app/controllers/admin/product_import_controller.rb index 201d57033f..72a5a63f30 100644 --- a/app/controllers/admin/product_import_controller.rb +++ b/app/controllers/admin/product_import_controller.rb @@ -84,7 +84,8 @@ module Admin directory = 'tmp/product_import' Dir.mkdir(directory) unless File.exist?(directory) File.open(Rails.root.join(directory, filename + extension), 'wb') do |f| - f.write(upload.read) + data = UploadSanitizer.new(upload.read).call + f.write(data) f.path end end diff --git a/app/services/upload_sanitizer.rb b/app/services/upload_sanitizer.rb new file mode 100644 index 0000000000..132669c884 --- /dev/null +++ b/app/services/upload_sanitizer.rb @@ -0,0 +1,18 @@ +# Formats uploaded files to UTF-8 encoding and strips unexpected BOM characters. +# Takes an open File object as input +class UploadSanitizer + def initialize(upload) + @data = upload + end + + def call + @data.force_encoding('UTF-8') + strip_bom_character + end + + private + + def strip_bom_character + @data.gsub("\xEF\xBB\xBF".force_encoding("UTF-8"), '') + end +end diff --git a/spec/services/upload_sanitizer_spec.rb b/spec/services/upload_sanitizer_spec.rb new file mode 100644 index 0000000000..6d8e6f029c --- /dev/null +++ b/spec/services/upload_sanitizer_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe UploadSanitizer do + describe "#call" do + let(:upload) do + File.open("/tmp/unsanitized.csv", 'wb:ascii-8bit') do |f| + f << "\xEF\xBB\xBF" + f << "Test" + end + end + let(:service) { UploadSanitizer.new(File.open(upload).read) } + + it "sanitizes the uploaded file" do + sanitized_upload = service.call + + expect(sanitized_upload.encoding.name).to eq "UTF-8" + expect(sanitized_upload.to_s).to eq "Test" + end + end +end