localeapp 0.6.8 → 0.6.9
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.
- data/CHANGELOG.md +4 -0
- data/README.md +9 -0
- data/lib/localeapp/cli/install.rb +1 -1
- data/lib/localeapp/configuration.rb +5 -0
- data/lib/localeapp/version.rb +1 -1
- data/lib/localeapp.rb +7 -0
- data/localeapp.gemspec +1 -1
- data/spec/localeapp/cli/install_spec.rb +1 -1
- data/spec/localeapp/updater_spec.rb +43 -101
- data/spec/localeapp_spec.rb +17 -0
- metadata +35 -33
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -10,6 +10,15 @@ The gem hooks into the i18n exception mechanism to send missing translations to
|
|
10
10
|
the app. When translated content has been added it's automatically pulled down
|
11
11
|
so you can see it straight away.
|
12
12
|
|
13
|
+
## Security
|
14
|
+
|
15
|
+
Though the i18n gem uses YAML as it's default file format it doesn't require
|
16
|
+
serialization of ruby objects. To prevent the kind of security problems
|
17
|
+
detailed in [CVE-2013-0156][1] the localeapp gem will not load any YAML containing
|
18
|
+
the string !ruby/ as of version 0.6.9.
|
19
|
+
|
20
|
+
[1]: https://groups.google.com/forum/?fromgroups=#!topic/rubyonrails-security/61bkgvnSGTQ
|
21
|
+
|
13
22
|
## Installation
|
14
23
|
|
15
24
|
### Rails 3
|
@@ -145,7 +145,7 @@ require 'localeapp/rails'
|
|
145
145
|
|
146
146
|
Localeapp.configure do |config|
|
147
147
|
config.api_key = ENV['LOCALEAPP_API_KEY']
|
148
|
-
config.
|
148
|
+
config.environment_name = ENV['LOCALEAPP_ENV'] unless ENV['LOCALEAPP_ENV'].nil?
|
149
149
|
config.polling_environments = [:development, :staging]
|
150
150
|
config.reloading_environments = [:development, :staging]
|
151
151
|
config.sending_environments = [:development, :staging]
|
@@ -70,6 +70,10 @@ module Localeapp
|
|
70
70
|
# The complete path to the directory where translations are stored
|
71
71
|
attr_accessor :translation_data_directory
|
72
72
|
|
73
|
+
# Enable or disable the insecure yaml exception
|
74
|
+
# default: true
|
75
|
+
attr_accessor :raise_on_insecure_yaml
|
76
|
+
|
73
77
|
def initialize
|
74
78
|
defaults.each do |setting, value|
|
75
79
|
send("#{setting}=", value)
|
@@ -90,6 +94,7 @@ module Localeapp
|
|
90
94
|
:daemon_pid_file => File.join('tmp', 'pids', 'localeapp.pid'),
|
91
95
|
:daemon_log_file => File.join('log', 'localeapp_daemon.log'),
|
92
96
|
:translation_data_directory => File.join('config', 'locales'),
|
97
|
+
:raise_on_insecure_yaml => true,
|
93
98
|
}
|
94
99
|
if ENV['DEBUG']
|
95
100
|
require 'logger'
|
data/lib/localeapp/version.rb
CHANGED
data/lib/localeapp.rb
CHANGED
@@ -54,6 +54,9 @@ module Localeapp
|
|
54
54
|
API_VERSION = "1"
|
55
55
|
LOG_PREFIX = "** [Localeapp] "
|
56
56
|
|
57
|
+
class LocaleappError < StandardError; end
|
58
|
+
class PotentiallyInsecureYaml < LocaleappError; end
|
59
|
+
|
57
60
|
class << self
|
58
61
|
# An Localeapp configuration object.
|
59
62
|
attr_accessor :configuration
|
@@ -115,6 +118,10 @@ module Localeapp
|
|
115
118
|
end
|
116
119
|
|
117
120
|
def load_yaml(contents)
|
121
|
+
if Localeapp.configuration.raise_on_insecure_yaml
|
122
|
+
raise Localeapp::PotentiallyInsecureYaml if contents =~ /!ruby\//
|
123
|
+
end
|
124
|
+
|
118
125
|
if defined?(Psych) && defined?(Psych::VERSION)
|
119
126
|
Psych.load(contents)
|
120
127
|
else
|
data/localeapp.gemspec
CHANGED
@@ -30,6 +30,6 @@ Gem::Specification.new do |s|
|
|
30
30
|
s.add_development_dependency('rspec', '2.11.0')
|
31
31
|
s.add_development_dependency('yard', '0.6.7')
|
32
32
|
s.add_development_dependency('RedCloth', '4.2.9')
|
33
|
-
s.add_development_dependency('aruba', '0.
|
33
|
+
s.add_development_dependency('aruba', '0.5.1')
|
34
34
|
s.add_development_dependency('fakeweb', '1.3.0')
|
35
35
|
end
|
@@ -206,7 +206,7 @@ require 'localeapp/rails'
|
|
206
206
|
|
207
207
|
Localeapp.configure do |config|
|
208
208
|
config.api_key = ENV['LOCALEAPP_API_KEY']
|
209
|
-
config.
|
209
|
+
config.environment_name = ENV['LOCALEAPP_ENV'] unless ENV['LOCALEAPP_ENV'].nil?
|
210
210
|
config.polling_environments = [:development, :staging]
|
211
211
|
config.reloading_environments = [:development, :staging]
|
212
212
|
config.sending_environments = [:development, :staging]
|
@@ -17,6 +17,10 @@ describe Localeapp::Updater, ".update(data)" do
|
|
17
17
|
@updater.update(data)
|
18
18
|
end
|
19
19
|
|
20
|
+
def load_yaml(locale)
|
21
|
+
YAML.load(File.read(File.join(@yml_dir, "#{locale}.yml")))
|
22
|
+
end
|
23
|
+
|
20
24
|
it "adds, updates and deletes keys in the yml files" do
|
21
25
|
do_update({
|
22
26
|
'translations' => {
|
@@ -35,59 +39,19 @@ describe Localeapp::Updater, ".update(data)" do
|
|
35
39
|
'locales' => %w{en es}
|
36
40
|
})
|
37
41
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
EN
|
52
|
-
else
|
53
|
-
File.read(File.join(@yml_dir, 'en.yml')).should == <<-EN
|
54
|
-
en:
|
55
|
-
foo:
|
56
|
-
monkey: hello
|
57
|
-
night: the night
|
58
|
-
space: !!null
|
59
|
-
blank: ''
|
60
|
-
tilde: !!null
|
61
|
-
scalar1: !!null
|
62
|
-
scalar2: !!null
|
63
|
-
EN
|
64
|
-
end
|
65
|
-
else
|
66
|
-
File.read(File.join(@yml_dir, 'en.yml')).should == <<-EN
|
67
|
-
en:
|
68
|
-
foo:
|
69
|
-
monkey: hello
|
70
|
-
night: the night
|
71
|
-
space:
|
72
|
-
blank: ''
|
73
|
-
tilde:
|
74
|
-
scalar1:
|
75
|
-
scalar2:
|
76
|
-
EN
|
77
|
-
end
|
78
|
-
else
|
79
|
-
File.read(File.join(@yml_dir, 'en.yml')).should == <<-EN
|
80
|
-
en:
|
81
|
-
blank: ""
|
82
|
-
foo:
|
83
|
-
monkey: hello
|
84
|
-
night: "the night"
|
85
|
-
scalar1: ~
|
86
|
-
scalar2: ~
|
87
|
-
space: ~
|
88
|
-
tilde: ~
|
89
|
-
EN
|
90
|
-
end
|
42
|
+
load_yaml('en').should == {
|
43
|
+
'en' => {
|
44
|
+
'foo' => {
|
45
|
+
'monkey' => 'hello',
|
46
|
+
'night' => 'the night'
|
47
|
+
},
|
48
|
+
'space' => nil,
|
49
|
+
'blank' => '',
|
50
|
+
'tilde' => nil,
|
51
|
+
'scalar1' => nil,
|
52
|
+
'scalar2' => nil,
|
53
|
+
}
|
54
|
+
}
|
91
55
|
end
|
92
56
|
|
93
57
|
it "deletes keys in the yml files when updates are empty" do
|
@@ -100,19 +64,14 @@ EN
|
|
100
64
|
],
|
101
65
|
'locales' => %w{es}
|
102
66
|
})
|
103
|
-
|
104
|
-
|
105
|
-
es
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
es:
|
112
|
-
foo:
|
113
|
-
monkey: Mono
|
114
|
-
ES
|
115
|
-
end
|
67
|
+
|
68
|
+
load_yaml('es').should == {
|
69
|
+
'es' => {
|
70
|
+
'foo' => {
|
71
|
+
'monkey' => 'Mono'
|
72
|
+
}
|
73
|
+
}
|
74
|
+
}
|
116
75
|
end
|
117
76
|
|
118
77
|
it "creates a new yml file if an unknown locale is passed" do
|
@@ -122,17 +81,12 @@ ES
|
|
122
81
|
},
|
123
82
|
'locales' => ['ja']
|
124
83
|
})
|
125
|
-
|
126
|
-
|
127
|
-
ja
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
File.read(File.join(@yml_dir, 'ja.yml')).should == <<-JA
|
132
|
-
ja:
|
133
|
-
foo: bar
|
134
|
-
JA
|
135
|
-
end
|
84
|
+
|
85
|
+
load_yaml('ja').should == {
|
86
|
+
'ja' => {
|
87
|
+
'foo' => 'bar'
|
88
|
+
}
|
89
|
+
}
|
136
90
|
end
|
137
91
|
|
138
92
|
it "doesn't create a new yml file if an unknown locale is passed but it has no translations" do
|
@@ -144,7 +98,7 @@ JA
|
|
144
98
|
File.exist?(File.join(@yml_dir, 'ja.yml')).should be_false
|
145
99
|
end
|
146
100
|
|
147
|
-
if defined?(Psych) && Psych::VERSION >= "1.1.0"
|
101
|
+
if defined?(Psych) && Psych::VERSION >= "1.1.0" && !RUBY_PLATFORM == 'jruby'
|
148
102
|
it "doesn't try to wrap long lines in the output" do
|
149
103
|
do_update({
|
150
104
|
'translations' => {
|
@@ -202,33 +156,21 @@ describe Localeapp::Updater, ".dump(data)" do
|
|
202
156
|
|
203
157
|
it "replaces the content of an existing yml file" do
|
204
158
|
filepath = File.join(@yml_dir, 'en.yml')
|
205
|
-
content = lambda { File.read(filepath) }
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
else
|
212
|
-
expect { do_dump({'en' => {'updated' => 'content'}}) }.to change(content, :call).to <<-EN
|
213
|
-
en:
|
214
|
-
updated: content
|
215
|
-
EN
|
216
|
-
end
|
159
|
+
content = lambda { YAML.load(File.read(filepath)) }
|
160
|
+
expect { do_dump({'en' => {'updated' => 'content'}}) }.to change(content, :call).to({
|
161
|
+
'en' => {
|
162
|
+
'updated' => 'content'
|
163
|
+
}
|
164
|
+
})
|
217
165
|
end
|
218
166
|
|
219
167
|
it "creates a new yml file if an unknown locale is passed" do
|
220
168
|
do_dump({'ja' => { 'foo' => 'bar'} })
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
else
|
227
|
-
File.read(File.join(@yml_dir, 'ja.yml')).should == <<-JA
|
228
|
-
ja:
|
229
|
-
foo: bar
|
230
|
-
JA
|
231
|
-
end
|
169
|
+
YAML.load(File.read(File.join(@yml_dir, 'ja.yml'))).should == {
|
170
|
+
'ja' => {
|
171
|
+
'foo' => 'bar'
|
172
|
+
}
|
173
|
+
}
|
232
174
|
end
|
233
175
|
|
234
176
|
it "doesn't change a yml file's permissions" do
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Localeapp, "#load_yaml(content)" do
|
4
|
+
let(:bad_yaml) { "---\n- 1\n- 2\n- 3\n- !ruby/object:Object\n foo: 1\n" }
|
5
|
+
|
6
|
+
it "raises an exception if the content contains potentially insecure yaml" do
|
7
|
+
with_configuration(:raise_on_insecure_yaml => true) do
|
8
|
+
expect { Localeapp.load_yaml(bad_yaml) }.to raise_error(Localeapp::PotentiallyInsecureYaml)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "doesn't raise if the raise_on_insecure_yaml setting is false" do
|
13
|
+
with_configuration(:raise_on_insecure_yaml => false) do
|
14
|
+
expect { Localeapp.load_yaml(bad_yaml) }.to_not raise_error
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: localeapp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 9
|
10
|
+
version: 0.6.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Christopher Dell
|
@@ -16,12 +16,10 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date:
|
19
|
+
date: 2013-01-15 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: i18n
|
23
|
-
type: :runtime
|
24
|
-
prerelease: false
|
25
23
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|
26
24
|
none: false
|
27
25
|
requirements:
|
@@ -31,11 +29,11 @@ dependencies:
|
|
31
29
|
segments:
|
32
30
|
- 0
|
33
31
|
version: "0"
|
32
|
+
type: :runtime
|
34
33
|
requirement: *id001
|
34
|
+
prerelease: false
|
35
35
|
- !ruby/object:Gem::Dependency
|
36
36
|
name: json
|
37
|
-
type: :runtime
|
38
|
-
prerelease: false
|
39
37
|
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
38
|
none: false
|
41
39
|
requirements:
|
@@ -45,11 +43,11 @@ dependencies:
|
|
45
43
|
segments:
|
46
44
|
- 0
|
47
45
|
version: "0"
|
46
|
+
type: :runtime
|
48
47
|
requirement: *id002
|
48
|
+
prerelease: false
|
49
49
|
- !ruby/object:Gem::Dependency
|
50
50
|
name: rest-client
|
51
|
-
type: :runtime
|
52
|
-
prerelease: false
|
53
51
|
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
52
|
none: false
|
55
53
|
requirements:
|
@@ -59,11 +57,11 @@ dependencies:
|
|
59
57
|
segments:
|
60
58
|
- 0
|
61
59
|
version: "0"
|
60
|
+
type: :runtime
|
62
61
|
requirement: *id003
|
62
|
+
prerelease: false
|
63
63
|
- !ruby/object:Gem::Dependency
|
64
64
|
name: ya2yaml
|
65
|
-
type: :runtime
|
66
|
-
prerelease: false
|
67
65
|
version_requirements: &id004 !ruby/object:Gem::Requirement
|
68
66
|
none: false
|
69
67
|
requirements:
|
@@ -73,11 +71,11 @@ dependencies:
|
|
73
71
|
segments:
|
74
72
|
- 0
|
75
73
|
version: "0"
|
74
|
+
type: :runtime
|
76
75
|
requirement: *id004
|
76
|
+
prerelease: false
|
77
77
|
- !ruby/object:Gem::Dependency
|
78
78
|
name: gli
|
79
|
-
type: :runtime
|
80
|
-
prerelease: false
|
81
79
|
version_requirements: &id005 !ruby/object:Gem::Requirement
|
82
80
|
none: false
|
83
81
|
requirements:
|
@@ -87,11 +85,11 @@ dependencies:
|
|
87
85
|
segments:
|
88
86
|
- 0
|
89
87
|
version: "0"
|
88
|
+
type: :runtime
|
90
89
|
requirement: *id005
|
90
|
+
prerelease: false
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rake
|
93
|
-
type: :development
|
94
|
-
prerelease: false
|
95
93
|
version_requirements: &id006 !ruby/object:Gem::Requirement
|
96
94
|
none: false
|
97
95
|
requirements:
|
@@ -101,11 +99,11 @@ dependencies:
|
|
101
99
|
segments:
|
102
100
|
- 0
|
103
101
|
version: "0"
|
102
|
+
type: :development
|
104
103
|
requirement: *id006
|
104
|
+
prerelease: false
|
105
105
|
- !ruby/object:Gem::Dependency
|
106
106
|
name: rack
|
107
|
-
type: :development
|
108
|
-
prerelease: false
|
109
107
|
version_requirements: &id007 !ruby/object:Gem::Requirement
|
110
108
|
none: false
|
111
109
|
requirements:
|
@@ -115,11 +113,11 @@ dependencies:
|
|
115
113
|
segments:
|
116
114
|
- 0
|
117
115
|
version: "0"
|
116
|
+
type: :development
|
118
117
|
requirement: *id007
|
118
|
+
prerelease: false
|
119
119
|
- !ruby/object:Gem::Dependency
|
120
120
|
name: rspec
|
121
|
-
type: :development
|
122
|
-
prerelease: false
|
123
121
|
version_requirements: &id008 !ruby/object:Gem::Requirement
|
124
122
|
none: false
|
125
123
|
requirements:
|
@@ -131,11 +129,11 @@ dependencies:
|
|
131
129
|
- 11
|
132
130
|
- 0
|
133
131
|
version: 2.11.0
|
132
|
+
type: :development
|
134
133
|
requirement: *id008
|
134
|
+
prerelease: false
|
135
135
|
- !ruby/object:Gem::Dependency
|
136
136
|
name: yard
|
137
|
-
type: :development
|
138
|
-
prerelease: false
|
139
137
|
version_requirements: &id009 !ruby/object:Gem::Requirement
|
140
138
|
none: false
|
141
139
|
requirements:
|
@@ -147,11 +145,11 @@ dependencies:
|
|
147
145
|
- 6
|
148
146
|
- 7
|
149
147
|
version: 0.6.7
|
148
|
+
type: :development
|
150
149
|
requirement: *id009
|
150
|
+
prerelease: false
|
151
151
|
- !ruby/object:Gem::Dependency
|
152
152
|
name: RedCloth
|
153
|
-
type: :development
|
154
|
-
prerelease: false
|
155
153
|
version_requirements: &id010 !ruby/object:Gem::Requirement
|
156
154
|
none: false
|
157
155
|
requirements:
|
@@ -163,27 +161,27 @@ dependencies:
|
|
163
161
|
- 2
|
164
162
|
- 9
|
165
163
|
version: 4.2.9
|
164
|
+
type: :development
|
166
165
|
requirement: *id010
|
166
|
+
prerelease: false
|
167
167
|
- !ruby/object:Gem::Dependency
|
168
168
|
name: aruba
|
169
|
-
type: :development
|
170
|
-
prerelease: false
|
171
169
|
version_requirements: &id011 !ruby/object:Gem::Requirement
|
172
170
|
none: false
|
173
171
|
requirements:
|
174
172
|
- - "="
|
175
173
|
- !ruby/object:Gem::Version
|
176
|
-
hash:
|
174
|
+
hash: 9
|
177
175
|
segments:
|
178
176
|
- 0
|
179
|
-
-
|
180
|
-
-
|
181
|
-
version: 0.
|
177
|
+
- 5
|
178
|
+
- 1
|
179
|
+
version: 0.5.1
|
180
|
+
type: :development
|
182
181
|
requirement: *id011
|
182
|
+
prerelease: false
|
183
183
|
- !ruby/object:Gem::Dependency
|
184
184
|
name: fakeweb
|
185
|
-
type: :development
|
186
|
-
prerelease: false
|
187
185
|
version_requirements: &id012 !ruby/object:Gem::Requirement
|
188
186
|
none: false
|
189
187
|
requirements:
|
@@ -195,7 +193,9 @@ dependencies:
|
|
195
193
|
- 3
|
196
194
|
- 0
|
197
195
|
version: 1.3.0
|
196
|
+
type: :development
|
198
197
|
requirement: *id012
|
198
|
+
prerelease: false
|
199
199
|
description: Synchronizes i18n translation keys and content with localeapp.com so you don't have to manage translations by hand.
|
200
200
|
email:
|
201
201
|
- chris@tigrish.com
|
@@ -286,6 +286,7 @@ files:
|
|
286
286
|
- spec/localeapp/routes_spec.rb
|
287
287
|
- spec/localeapp/sender_spec.rb
|
288
288
|
- spec/localeapp/updater_spec.rb
|
289
|
+
- spec/localeapp_spec.rb
|
289
290
|
- spec/spec_helper.rb
|
290
291
|
- spec/support/i18n/missing_translation.rb
|
291
292
|
- spec/support/localeapp_integration_data.rb
|
@@ -319,7 +320,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
319
320
|
requirements: []
|
320
321
|
|
321
322
|
rubyforge_project: localeapp
|
322
|
-
rubygems_version: 1.8.
|
323
|
+
rubygems_version: 1.8.24
|
323
324
|
signing_key:
|
324
325
|
specification_version: 3
|
325
326
|
summary: Easy i18n translation management with localeapp.com
|
@@ -358,6 +359,7 @@ test_files:
|
|
358
359
|
- spec/localeapp/routes_spec.rb
|
359
360
|
- spec/localeapp/sender_spec.rb
|
360
361
|
- spec/localeapp/updater_spec.rb
|
362
|
+
- spec/localeapp_spec.rb
|
361
363
|
- spec/spec_helper.rb
|
362
364
|
- spec/support/i18n/missing_translation.rb
|
363
365
|
- spec/support/localeapp_integration_data.rb
|