diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index fabb3f3a4..2ff5c9c15 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -52,6 +52,12 @@ class UsersController < ApplicationController else flash[:notice] = I18n.t 'users.update.settings_not_updated' end + elsif u[:strip_exif] + if @user.update_attributes(u) + flash[:notice] = I18n.t 'users.update.settings_updated' + else + flash[:notice] = I18n.t 'users.update.settings_not_updated' + end elsif u[:language] if @user.update_attributes(u) I18n.locale = @user.language @@ -182,6 +188,7 @@ class UsersController < ApplicationController :invitation_service, :invitation_identifier, :show_community_spotlight_in_stream, + :strip_exif, :auto_follow_back, :auto_follow_back_aspect_id, :remember_me, diff --git a/app/models/photo.rb b/app/models/photo.rb index 7c57d1cb2..b652093e7 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -81,10 +81,13 @@ class Photo < ActiveRecord::Base photo.random_string = SecureRandom.hex(10) + if photo.author.local? + photo.unprocessed_image.strip_exif = photo.author.owner.strip_exif + end + if params[:user_file] image_file = params.delete(:user_file) photo.unprocessed_image.store! image_file - elsif params[:image_url] photo.remote_unprocessed_image_url = params[:image_url] photo.unprocessed_image.store! diff --git a/app/models/user.rb b/app/models/user.rb index 3fdbec790..1fa150afb 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -489,6 +489,7 @@ class User < ActiveRecord::Base :show_community_spotlight_in_stream].each do |field| self[field] = false end + self[:strip_exif] = true self[:email] = "deletedaccount_#{self[:id]}@example.org" random_password = SecureRandom.hex(20) @@ -527,6 +528,6 @@ class User < ActiveRecord::Base "created_at", "updated_at", "locked_at", "serialized_private_key", "getting_started", "disable_mail", "show_community_spotlight_in_stream", - "email", "remove_after", "export", "exporting", "exported_at"] + "strip_exif", "email", "remove_after", "export", "exporting", "exported_at"] end end diff --git a/app/serializers/export/user_serializer.rb b/app/serializers/export/user_serializer.rb index 9621d2095..a7563cc27 100644 --- a/app/serializers/export/user_serializer.rb +++ b/app/serializers/export/user_serializer.rb @@ -7,7 +7,8 @@ module Export :disable_mail, :show_community_spotlight_in_stream, :auto_follow_back, - :auto_follow_back_aspect + :auto_follow_back_aspect, + :strip_exif has_one :profile, serializer: Export::ProfileSerializer has_many :aspects, each_serializer: Export::AspectSerializer has_many :contacts, each_serializer: Export::ContactSerializer @@ -19,4 +20,4 @@ module Export end end -end \ No newline at end of file +end diff --git a/app/uploaders/processed_image.rb b/app/uploaders/processed_image.rb index 89750f336..71bae76a1 100644 --- a/app/uploaders/processed_image.rb +++ b/app/uploaders/processed_image.rb @@ -19,27 +19,15 @@ class ProcessedImage < CarrierWave::Uploader::Base version :thumb_small do process :resize_to_fill => [50,50] - process :strip end version :thumb_medium do process :resize_to_limit => [100,100] - process :strip end version :thumb_large do process :resize_to_limit => [300,300] - process :strip end version :scaled_full do process :resize_to_limit => [700,nil] - process :strip - end - - def strip - manipulate! do |img| - img.strip - img = yield(img) if block_given? - img - end end end diff --git a/app/uploaders/unprocessed_image.rb b/app/uploaders/unprocessed_image.rb index 8de9ed0f3..86d425eb2 100644 --- a/app/uploaders/unprocessed_image.rb +++ b/app/uploaders/unprocessed_image.rb @@ -5,6 +5,12 @@ class UnprocessedImage < CarrierWave::Uploader::Base include CarrierWave::MiniMagick + attr_accessor :strip_exif + + def strip_exif + @strip_exif || false + end + def store_dir "uploads/images" end @@ -17,11 +23,13 @@ class UnprocessedImage < CarrierWave::Uploader::Base model.random_string + File.extname(@filename) if @filename end - process :orient_image + process :basic_process - def orient_image + def basic_process manipulate! do |img| img.auto_orient + img.strip if strip_exif + img = yield(img) if block_given? img end end diff --git a/app/views/users/privacy_settings.html.haml b/app/views/users/privacy_settings.html.haml index 830f65eb8..7fec95c91 100644 --- a/app/views/users/privacy_settings.html.haml +++ b/app/views/users/privacy_settings.html.haml @@ -15,6 +15,26 @@ = t('privacy') = render 'shared/settings_nav' + .row-fluid + .span3 + .span5 + %h3 + = t('.title') + + = form_for current_user, :url => user_path, :html => { :method => :put } do |f| + = f.error_messages + + = f.fields_for :stream_preferences do |type| + #stream_prefs + = f.label :strip_exif, :class => "checkbox" do + = f.check_box :strip_exif + = t('.strip_exif') + + .small-horizontal-spacer + = f.submit t('.change'), :class => 'btn' + + %hr + .row-fluid .span3 .span5 diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index 80f13fda3..468f929e0 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -1316,8 +1316,10 @@ en: privacy_settings: title: "Privacy Settings" ignored_users: "Ignored Users" + strip_exif: "Strip metadata such as location, author, and camera model from uploaded images (recommended)" stop_ignoring: "Stop ignoring" no_user_ignored_message: "You are currently ignoring no other user" + change: "Change" destroy: success: "Your account has been locked. It may take 20 minutes for us to finish closing your account. Thank you for trying diaspora*." diff --git a/db/migrate/20141230214830_user_pref_strip_exif.rb b/db/migrate/20141230214830_user_pref_strip_exif.rb new file mode 100644 index 000000000..79983181d --- /dev/null +++ b/db/migrate/20141230214830_user_pref_strip_exif.rb @@ -0,0 +1,9 @@ +class UserPrefStripExif < ActiveRecord::Migration + def up + add_column :users, :strip_exif, :boolean, default: true + end + + def down + remove_column :users, :strip_exif + end +end diff --git a/db/schema.rb b/db/schema.rb index d176940cd..e2251207a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141227120907) do +ActiveRecord::Schema.define(version: 20141230214830) do create_table "account_deletions", force: true do |t| t.string "diaspora_handle" @@ -558,6 +558,7 @@ ActiveRecord::Schema.define(version: 20141227120907) do t.datetime "reset_password_sent_at" t.datetime "last_seen" t.datetime "remove_after" + t.boolean "strip_exif", default: true t.string "export" t.datetime "exported_at" t.boolean "exporting", default: false diff --git a/spec/fixtures/exif.jpg b/spec/fixtures/exif.jpg new file mode 100644 index 000000000..60236d594 Binary files /dev/null and b/spec/fixtures/exif.jpg differ diff --git a/spec/lib/diaspora/exporter_spec.rb b/spec/lib/diaspora/exporter_spec.rb index 412be8a8f..7bb429cc8 100644 --- a/spec/lib/diaspora/exporter_spec.rb +++ b/spec/lib/diaspora/exporter_spec.rb @@ -37,6 +37,7 @@ describe Diaspora::Exporter do it { matches :user, :show_community_spotlight_in_stream } it { matches :user, :auto_follow_back } it { matches :user, :auto_follow_back_aspect } + it { matches :user, :strip_exif } it { matches :user, :profile, :first_name, root: @user1.person.profile } it { matches :user, :profile, :last_name, root: @user1.person.profile } diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 5b568f401..df2ca276a 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -140,6 +140,39 @@ describe Photo, :type => :model do end end + context 'with a saved photo containing EXIF data' do + before do + @exif_filename = 'exif.jpg' + @exif_name = File.join(File.dirname(__FILE__), '..', 'fixtures', @exif_filename) + end + + it 'should contain EXIF data if user prefer' do + @alice_photo = alice.build_post(:photo, :user_file => File.open(@exif_name), :to => alice.aspects.first.id) + + with_carrierwave_processing do + @alice_photo.unprocessed_image.store! File.open(@exif_name) + @alice_photo.save + end + + new_filename = File.join(File.dirname(__FILE__), '../../public/', @alice_photo.unprocessed_image.store_dir, @alice_photo.unprocessed_image.filename) + image = MiniMagick::Image.new(new_filename) + expect(image.exif.length).not_to eq(0) + end + + it 'should not contain EXIF data if user prefer' do + @bob_photo = bob.build_post(:photo, :user_file => File.open(@exif_name), :to => @aspect.id) + + with_carrierwave_processing do + @bob_photo.unprocessed_image.store! File.open(@exif_name) + @bob_photo.save + end + + new_filename = File.join(File.dirname(__FILE__), '../../public/', @bob_photo.unprocessed_image.store_dir, @bob_photo.unprocessed_image.filename) + image = MiniMagick::Image.new(new_filename) + expect(image.exif.length).to eq(0) + end + end + describe 'non-image files' do it 'should not store' do file = File.open(@fail_fixture_name) diff --git a/spec/support/fixture_builder.rb b/spec/support/fixture_builder.rb index 656406025..34f981a33 100644 --- a/spec/support/fixture_builder.rb +++ b/spec/support/fixture_builder.rb @@ -8,7 +8,7 @@ FixtureBuilder.configure do |fbuilder| # now declare objects fbuilder.factory do # Users - alice = FactoryGirl.create(:user_with_aspect, :username => "alice") + alice = FactoryGirl.create(:user_with_aspect, :username => "alice", :strip_exif => false) alices_aspect = alice.aspects.where(:name => "generic").first eve = FactoryGirl.create(:user_with_aspect, :username => "eve")