sanitize_user_agent_header 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 108290424f2d89412961132a44c5285e03547c42
4
+ data.tar.gz: e2f08105b183eb152ea976a0f81ff8de6ce9d697
5
+ SHA512:
6
+ metadata.gz: fabbc5e3c05aaccd421f1703973a328b74efd13ab06181047415d572b0a41da3c598d9d7357b6a38d3be9a48f42012f53a2837c530c02e2c852d3e7370cda7a7
7
+ data.tar.gz: fe8acd9a4bf5e55ad64403e9f1eaad04c7b279804cec8de2c40ec42518445231d5f38b24db0d126b955a9dfc3004512f615abdc6cc72381dad93613f86e95557
@@ -0,0 +1,54 @@
1
+ # rbenv/rvm
2
+ .ruby-version
3
+
4
+ # rcov generated
5
+ coverage
6
+ coverage.data
7
+
8
+ # rdoc generated
9
+ rdoc
10
+
11
+ # yard generated
12
+ doc
13
+ .yardoc
14
+
15
+ # bundler
16
+ .bundle
17
+ Gemfile.lock
18
+ gemfiles/*.lock
19
+
20
+ # jeweler generated
21
+ pkg
22
+
23
+ # Have editor/IDE/OS specific files you need to ignore? Consider using a global gitignore:
24
+ #
25
+ # * Create a file at ~/.gitignore
26
+ # * Include files you want ignored
27
+ # * Run: git config --global core.excludesfile ~/.gitignore
28
+ #
29
+ # After doing this, these files will be ignored in all your git projects,
30
+ # saving you from having to 'pollute' every project you touch with them
31
+ #
32
+ # Not sure what to needs to be ignored for particular editors/OSes? Here's some ideas to get you started. (Remember, remove the leading # of the line)
33
+ #
34
+ # For MacOS:
35
+ #
36
+ #.DS_Store
37
+
38
+ # For TextMate
39
+ #*.tmproj
40
+ #tmtags
41
+
42
+ # For emacs:
43
+ #*~
44
+ #\#*
45
+ #.\#*
46
+
47
+ # For vim:
48
+ #*.swp
49
+
50
+ # For redcar:
51
+ #.redcar
52
+
53
+ # For rubinius:
54
+ #*.rbc
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.6
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sanitize_user_agent_header.gemspec
4
+ gemspec
@@ -0,0 +1,38 @@
1
+ Decodes the `User-Agent` header in your Rack request hash to be UTF-8. Mostly useful for headers like
2
+
3
+ User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; Telecomunicaciones espa��olas`
4
+
5
+ which get inserted by (rather clueless) telcos, especially in packaged Android distributions (one of the many reasons why letting telcos
6
+ customize the handset is a bad idea). This library will do it's best to reencode the header in good UTF-8, and barring that will do a lossy
7
+ replacement with question-mark substitions.
8
+
9
+ ## Installation
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'sanitize_user_agent_header'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install sanitize_user_agent_header
24
+
25
+ In Rails the gem will be inserted into your application stack automatically. In raw Rack, install the middleware in `config.ru` like so:
26
+
27
+ use SanitizeUserAgentHeader
28
+
29
+ ## Development
30
+
31
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
34
+
35
+ ## Contributing
36
+
37
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/sanitize_user_agent_header.
38
+
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,42 @@
1
+ require "sanitize_user_agent_header/version"
2
+
3
+ # This middleware will ensure that the User-Agent request header is actually
4
+ # UTF-8, which will prevent bad things down the road. Strictly speaking,
5
+ # the _string_ must be kept in an ISO encoding (single byte header limitations).
6
+ # But pragmatically we use this header in many places, and applying an explicit
7
+ # decode to it is a chore. Also, we are not violating the spec, merely "matching"
8
+ # the encoding of an input variable to the internal encoding of the system.
9
+ class SanitizeUserAgentHeader
10
+ HTTP_USER_AGENT = 'HTTP_USER_AGENT'.freeze
11
+ private_constant :HTTP_USER_AGENT
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ if env[HTTP_USER_AGENT]
19
+ env[HTTP_USER_AGENT] = opportunistically_convert_to_utf8(env[HTTP_USER_AGENT])
20
+ end
21
+ @app.call(env)
22
+ end
23
+
24
+ # http://stackoverflow.com/questions/10384741/is-a-unicode-user-agent-legal-inside-an-http-header
25
+ def opportunistically_convert_to_utf8(str)
26
+ try_encodings = %w( ISO-8859-1 CP1252 )
27
+ try_encodings.each do |enc|
28
+ begin
29
+ encoded_as_utf8 = str.force_encoding(enc).encode(Encoding::UTF_8)
30
+ return encoded_as_utf8
31
+ rescue Encoding::UndefinedConversionError
32
+ end
33
+ end
34
+ # Last resort, just strip it of everything
35
+ str.force_encoding(Encoding::ISO8859_1)
36
+ str.encode(Encoding::ASCII, invalid: :replace, undef: :replace, replace: '?').encode(Encoding::UTF_8)
37
+ end
38
+
39
+ if defined?(Rails)
40
+ require_relative 'sanitize_user_agent_header/railtie'
41
+ end
42
+ end
@@ -0,0 +1,5 @@
1
+ class SanitizeUserAgentHeader::Railtie < Rails::Railtie
2
+ initializer "sanitize_user_agent_header.configure_rails_initialization" do |app|
3
+ app.middleware.use SanitizeUserAgentHeader
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ class SanitizeUserAgentHeader
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sanitize_user_agent_header/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sanitize_user_agent_header"
8
+ spec.version = SanitizeUserAgentHeader::VERSION
9
+ spec.authors = ["Julik Tarkhanov"]
10
+ spec.email = ["me@julik.nl"]
11
+
12
+ spec.summary = %q{ Decodes the User-Agent header into UTF-8 in any Rack app }
13
+ spec.description = %q{ Decodes the User-Agent header into UTF-8 in any Rack app }
14
+ spec.homepage = "https://github.com/WeTransfer/sanitize_user_agent_header"
15
+
16
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
17
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
18
+ if spec.respond_to?(:metadata)
19
+ spec.metadata['allowed_push_host'] = "https://rubygems.org"
20
+ else
21
+ raise "RubyGems 2.0 or newer is required to protect against " \
22
+ "public gem pushes."
23
+ end
24
+
25
+ spec.files = `git ls-files -z`.split("\x0")
26
+ spec.bindir = "exe"
27
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
+ spec.require_paths = ["lib"]
29
+
30
+ spec.add_development_dependency "rack"
31
+ spec.add_development_dependency "rack-test"
32
+ spec.add_development_dependency "bundler"
33
+ spec.add_development_dependency "rake", "~> 10.0"
34
+ spec.add_development_dependency "rspec", "~> 3.2"
35
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ require 'rack'
3
+ require 'rack/test'
4
+
5
+ describe SanitizeUserAgentHeader do
6
+ include Rack::Test::Methods
7
+
8
+ let(:app) {
9
+ app_proc = ->(env) {
10
+ [200, {}, [env.fetch('HTTP_USER_AGENT', '<NONE>').encode(Encoding::UTF_8)]]
11
+ }
12
+ SanitizeUserAgentHeader.new(app_proc)
13
+ }
14
+
15
+ it 'calls the app when no user agent header is set' do
16
+ get '/'
17
+ expect(last_response.body).to eq("<NONE>")
18
+ end
19
+
20
+ it 'calls the app when the user agent is just ASCII' do
21
+ get '/', {}, {'HTTP_USER_AGENT' => 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)'}
22
+ expect(last_response.body).to eq("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)")
23
+ end
24
+
25
+ describe 'with non-ASCII characters in the User-Agent header combined with UTF-8 params' do
26
+ ['ISO-8859-1', 'CP1252'].each do | windows_encoding |
27
+ it "decodes the UA header and prevents encoding errors for UA header in #{windows_encoding}" do
28
+ # From our actual bug records
29
+ utf8_ua = 'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; Pernod Ricard España)'
30
+ windows_ua = utf8_ua.encode(windows_encoding)
31
+ post '/', {'message' => 'Voiçi un header'}, {'HTTP_USER_AGENT' => windows_ua}
32
+ expect(last_response).to be_ok
33
+ expect(last_response.body).to eq('Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; Pernod Ricard España)')
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,6 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
5
+ require "sanitize_user_agent_header"
6
+
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sanitize_user_agent_header
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Julik Tarkhanov
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2017-06-11 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rack-test
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.2'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ description: " Decodes the User-Agent header into UTF-8 in any Rack app "
84
+ email:
85
+ - me@julik.nl
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".travis.yml"
92
+ - Gemfile
93
+ - README.md
94
+ - Rakefile
95
+ - lib/sanitize_user_agent_header.rb
96
+ - lib/sanitize_user_agent_header/railtie.rb
97
+ - lib/sanitize_user_agent_header/version.rb
98
+ - sanitize_user_agent_header.gemspec
99
+ - spec/sanitize_user_agent_header_spec.rb
100
+ - spec/spec_helper.rb
101
+ homepage: https://github.com/WeTransfer/sanitize_user_agent_header
102
+ licenses: []
103
+ metadata:
104
+ allowed_push_host: https://rubygems.org
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ required_rubygems_version: !ruby/object:Gem::Requirement
115
+ requirements:
116
+ - - ">="
117
+ - !ruby/object:Gem::Version
118
+ version: '0'
119
+ requirements: []
120
+ rubyforge_project:
121
+ rubygems_version: 2.4.5.1
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Decodes the User-Agent header into UTF-8 in any Rack app
125
+ test_files: []