obf 0.6.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/lib/obf/utils.rb +2 -3
  3. data/lib/obf/validator.rb +257 -81
  4. metadata +2 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3e249a35931e0186e77d7891dd62ea793e590029
4
- data.tar.gz: f5ac6ea76ef9258197bdc8668bfdc9eddbf4db6e
3
+ metadata.gz: e04159aa51fa8c477f23c58a9dc7eda8f1abca98
4
+ data.tar.gz: 7281b01429f081deb13970741a95b5ef025bb8fa
5
5
  SHA512:
6
- metadata.gz: 10eaf3229ebf54f38d81524a72729885a8a95645f66179595cd47d1cf5f232f8524b0be4eaad15aaf1efe103c66daf1bfd66d9a009ce0de3490a53b251e41375
7
- data.tar.gz: c34e9d79971e8aefba7de989d0bf45a861f37b30b4f796287d99456991d99627b4af4d4a6c98ffeaff56ac84682dc283bcac2d00852524c539e44f5e41111eb0
6
+ metadata.gz: b3527a3ff96333f841b662008533ff81a4a06ea1429551c604a4d232b61de6d9aa79caca2f735efba04adf178a534574ad50fe504ca30c76583bae8ffd7ed893
7
+ data.tar.gz: 75ab9ed7797c959ddc16589c302e2b75addb2b7460e91be9299464660198b423ce254fd31cf935ae547fb5821c4616674820f73efcda1b680c3bd7eb109fbb4d
@@ -73,9 +73,8 @@ module OBF::Utils
73
73
  end
74
74
  end
75
75
  return type if type
76
- # rescue => e
77
- # puts e.class.to_s
78
- # puts e.message.to_s
76
+ rescue => e
77
+ return :unknown
79
78
  end
80
79
  end
81
80
  return :unknown
@@ -35,13 +35,46 @@ module OBF
35
35
  @warnings || 0
36
36
  end
37
37
 
38
- def self.validate_obf(path)
38
+ def self.validate_file(path)
39
+ type = Utils::identify_file(path)
40
+ fn = File.basename(path)
41
+ filesize = File.size(path)
42
+ if type == :obf
43
+ validate_obf(path)
44
+ elsif type == :obz
45
+ validate_obz(path)
46
+ else
47
+ {
48
+ :filename => fn,
49
+ :filesize => filesize,
50
+ :valid => false,
51
+ :errors => 1,
52
+ :results => [{
53
+ 'type' => 'valid_file',
54
+ 'description' => 'valid .obf or .obz file',
55
+ 'valid' => false,
56
+ 'error' => 'file must be an .obf JSON file or a .obz zip package'
57
+ }]
58
+ }
59
+ end
60
+ end
61
+
62
+ def self.validate_obf(path, opts={})
39
63
  v = self.new
40
64
  fn = File.basename(path)
41
- results = v.validate_obf(path)
65
+ filesize = 0
66
+ content = nil
67
+ if opts['zipper']
68
+ content = opts['zipper'].read(path)
69
+ filesize = opts['zipper'].glob(path)[0].size
70
+ else
71
+ content = File.read(path)
72
+ filesize = File.size(path)
73
+ end
74
+ results = v.validate_obf(content, fn, opts)
42
75
  {
43
76
  :filename => fn,
44
- :filesize => File.size(path),
77
+ :filesize => filesize,
45
78
  :valid => v.errors == 0,
46
79
  :errors => v.errors,
47
80
  :warnings => v.warnings,
@@ -50,39 +83,176 @@ module OBF
50
83
  end
51
84
 
52
85
  def self.validate_obz(path)
86
+ v = self.new
87
+ fn = File.basename(path)
88
+ results, sub_results = v.validate_obz(path, fn)
89
+ errors = ([v.errors] + sub_results.map{|r| r[:errors] }).inject(:+)
90
+ warnings = ([v.warnings] + sub_results.map{|r| r[:warnings] }).inject(:+)
91
+ {
92
+ :filename => fn,
93
+ :filesize => File.size(path),
94
+ :valid => errors == 0,
95
+ :errors => errors,
96
+ :warnings => warnings,
97
+ :results => results,
98
+ :sub_results => sub_results
99
+ }
53
100
  end
54
-
55
- def validate_obf(path, opts={})
101
+
102
+ def setup
56
103
  @blocked = nil
57
104
  @errored = false
58
105
  @warnings = 0
59
106
  @errors = 0
60
107
  @checks = []
108
+ @sub_checks = []
109
+ end
110
+
111
+ def validate_obz(path, filename)
112
+ setup
113
+
114
+ add_check('filename', "file name") do
115
+ if !filename.match(/\.obz$/)
116
+ warn "filename should end with .obz"
117
+ end
118
+ end
119
+
120
+ valid_zip = false
121
+ add_check('zip', 'valid zip') do
122
+ begin
123
+ Utils::load_zip(path) do |zipper|
124
+ end
125
+ valid_zip = true
126
+ rescue Zip::Error => e
127
+ err "file is not a valid zip package"
128
+ end
129
+ end
130
+ if valid_zip
131
+ Utils::load_zip(path) do |zipper|
132
+ json = nil
133
+ add_check('manifest', 'manifest.json') do
134
+ if zipper.glob('manifest.json').length == 0
135
+ err "manifest.json is required in the zip package"
136
+ end
137
+ json = JSON.parse(zipper.read('manifest.json')) rescue nil
138
+ if !json
139
+ err "manifest.json must contain a valid JSON structure"
140
+ end
141
+ end
142
+ if json
143
+ add_check('manifest_format', 'manifest.json format version') do
144
+ if !json['format']
145
+ err "format attribute is required, set to #{OBF::FORMAT}"
146
+ end
147
+ version = json['format'].split(/-/, 3)[-1].to_f
148
+ if version > OBF::FORMAT_CURRENT_VERSION
149
+ err "format version (#{version}) is invalid, current version is #{OBF::FORMAT_CURRENT_VERSION}"
150
+ elsif version < OBF::FORMAT_CURRENT_VERSION
151
+ warn "format version (#{version}) is old, consider updating to #{OBF::FORMAT_CURRENT_VERSION}"
152
+ end
153
+ end
154
+
155
+ add_check('manifest_root', 'manifest.json root attribute') do
156
+ if !json['root']
157
+ err "root attribute is required"
158
+ end
159
+ if zipper.glob(json['root']).length == 0
160
+ err "root attribute must reference a file in the package"
161
+ end
162
+ end
163
+
164
+ paths = nil
165
+ add_check('manifest_paths', 'manifest.json paths attribute') do
166
+ if !json['paths'] || !json['paths'].is_a?(Hash)
167
+ err "paths attribute must be a valid hash"
168
+ end
169
+ if !json['paths']['boards'] || !json['paths']['boards'].is_a?(Hash)
170
+ err "paths.boards must be a valid hash"
171
+ end
172
+ if json['paths']['images'] && !json['paths']['images'].is_a?(Hash)
173
+ err "paths.images must be a valid hash if defined"
174
+ end
175
+ if json['paths']['sounds'] && !json['paths']['sounds'].is_a?(Hash)
176
+ err "paths.sounds must be a valid hash if defined"
177
+ end
178
+ end
179
+ add_check('manifest_extras', 'manifest.json extra attributes') do
180
+ attrs = ['format', 'root', 'paths']
181
+ json.keys.each do |key|
182
+ if !attrs.include?(key) && !key.match(/^ext_/)
183
+ warn "#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
184
+ end
185
+ end
186
+
187
+ attrs = ['boards', 'images', 'sounds']
188
+ json['paths'].keys.each do |key|
189
+ if !attrs.include?(key) && !key.match(/^ext_/)
190
+ warn "paths.#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
191
+ end
192
+ end
193
+ end
194
+ add_check('manifest_boards', 'manifest.json referenced boards') do
195
+ end
196
+
197
+ add_check('manifest_images', 'manifest.json referenced images') do
198
+ end
199
+
200
+ add_check('manifest_sounds', 'manifest.json referenced sounds') do
201
+ end
202
+
203
+ sub_results = []
204
+ if json['paths']['boards'] && json['paths']['boards'].is_a?(Hash)
205
+ json['paths']['boards'].each do |key, path|
206
+ sub = Validator.validate_obf(path, {'zipper' => zipper})
207
+ sub_results << sub
208
+ end
209
+ end
210
+ @sub_checks = sub_results
211
+ end
212
+ if zipper.glob('manifest.json').length > 0
213
+ json = JSON.parse(zipper.read('manifest.json')) rescue nil
214
+ if json['root'] && json['format'] && json['format'].match(/^open-board-/)
215
+ type = :obz
216
+ end
217
+ end
218
+ end
219
+ end
220
+ return [@checks, @sub_checks]
221
+ end
222
+
223
+ def validate_obf(content, filename, opts={})
224
+ setup
61
225
 
62
226
  # TODO enforce extra attributes being defined with ext_
63
227
 
228
+ add_check('filename', "file name") do
229
+ if !filename.match(/\.obf$/)
230
+ warn "filename should end with .obf"
231
+ end
232
+ end
233
+
64
234
  json = nil
65
- add_check('valid_json', "JSON File") do
235
+ add_check('valid_json', "JSON file") do
66
236
  begin
67
- json = JSON.parse(File.read(path))
237
+ json = JSON.parse(content)
68
238
  rescue => e
69
239
  err "Couldn't parse as JSON", true
70
240
  end
71
241
  end
72
242
 
73
243
  ext = nil
74
- add_check('to_external', "OBF Structure") do
244
+ add_check('to_external', "OBF structure") do
75
245
  begin
76
- ext = External.from_obf(path, {})
246
+ External.from_obf(json, {})
247
+ ext = JSON.parse(content)
77
248
  rescue External::StructureError => e
78
249
  err "Couldn't parse structure: #{e.message}", true
79
250
  end
80
251
  end
81
- ext = json
82
-
252
+
83
253
  add_check('format_version', "format version") do
84
254
  if !ext['format']
85
- err "format attribute is required, set to #{FORMAT}"
255
+ err "format attribute is required, set to #{OBF::FORMAT}"
86
256
  end
87
257
  version = ext['format'].split(/-/, 3)[-1].to_f
88
258
  if version > OBF::FORMAT_CURRENT_VERSION
@@ -188,89 +358,95 @@ module OBF
188
358
  warn("not all defined buttons were included in the grid order (#{(button_ids - used_button_ids).join(',')})") if (button_ids - used_button_ids).length > 0
189
359
  end
190
360
 
191
- unless opts['obz']
192
- button_image_ids = []
193
- if ext['buttons'] && ext['buttons'].is_a?(Array)
194
- ext['buttons'].each{|b| button_image_ids << b['image_id'] if b.is_a?(Hash) && b['image_id'] }
195
- end
196
- add_check('images', "images attribute") do
197
-
198
- if !ext['images']
199
- err "images attribute is required"
200
- elsif !ext['images'].is_a?(Array)
201
- err "images attribute must be an array"
202
- end
203
- end
361
+ button_image_ids = []
362
+ if ext && ext['buttons'] && ext['buttons'].is_a?(Array)
363
+ ext['buttons'].each{|b| button_image_ids << b['image_id'] if b.is_a?(Hash) && b['image_id'] }
364
+ end
365
+ add_check('images', "images attribute") do
204
366
 
205
- if ext['images'] && ext['images'].is_a?(Array)
206
- ext['images'].each_with_index do |image, idx|
207
- add_check("image[#{idx}]", "image at images[#{idx}]") do
208
- if !image.is_a?(Hash)
209
- err "image must be a hash"
210
- elsif !image['id']
211
- err "image.id is required"
212
- elsif !image['width'] || !image['width'].is_a?(Fixnum)
213
- err "image.width must be a valid positive number"
214
- elsif !image['height'] || !image['height'].is_a?(Fixnum)
215
- err "image.height must be a valid positive number"
216
- elsif !image['content_type'] || !image['content_type'].match(/^image\/.+$/)
217
- err "image.content_type must be a valid image mime type"
218
- elsif !image['url'] && !image['data'] && !image['symbol']
219
- err "image must have data, url or symbol attribute defined"
220
- elsif image['data'] && !image['data'].match(/^data:image\/.+;base64,.+$/)
221
- err "image.data must be a valid data URI if defined"
222
- elsif image['symbol'] && !image['symbol'].is_a?(Hash)
223
- err "image.symbol must be a hash if defined"
224
- end
225
-
226
- attrs = ['id', 'width', 'height', 'content_type', 'data', 'url', 'symbol', 'path', 'data_url', 'license']
227
- image.keys.each do |key|
228
- if !attrs.include?(key) && !key.match(/^ext_/)
229
- warn "image.#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
367
+ if !ext['images']
368
+ err "images attribute is required"
369
+ elsif !ext['images'].is_a?(Array)
370
+ err "images attribute must be an array"
371
+ end
372
+ end
373
+
374
+ if ext && ext['images'] && ext['images'].is_a?(Array)
375
+ ext['images'].each_with_index do |image, idx|
376
+ add_check("image[#{idx}]", "image at images[#{idx}]") do
377
+ if !image.is_a?(Hash)
378
+ err "image must be a hash"
379
+ elsif !image['id']
380
+ err "image.id is required"
381
+ elsif !image['width'] || !image['width'].is_a?(Fixnum)
382
+ err "image.width must be a valid positive number"
383
+ elsif !image['height'] || !image['height'].is_a?(Fixnum)
384
+ err "image.height must be a valid positive number"
385
+ elsif !image['content_type'] || !image['content_type'].match(/^image\/.+$/)
386
+ err "image.content_type must be a valid image mime type"
387
+ elsif !image['url'] && !image['data'] && !image['symbol']
388
+ err "image must have data, url or symbol attribute defined"
389
+ elsif image['data'] && !image['data'].match(/^data:image\/.+;base64,.+$/)
390
+ err "image.data must be a valid data URI if defined"
391
+ elsif image['symbol'] && !image['symbol'].is_a?(Hash)
392
+ err "image.symbol must be a hash if defined"
393
+ end
394
+ if image['path']
395
+ if opts['zipper']
396
+ if opts['zipper'].glob(image['path']).length == 0
397
+ err "image.path \"#{image['path']}\" not found in .obz package"
230
398
  end
399
+ else
400
+ err "image.path should not be defined outside of an .obz package"
401
+ end
402
+ end
403
+
404
+ attrs = ['id', 'width', 'height', 'content_type', 'data', 'url', 'symbol', 'path', 'data_url', 'license']
405
+ image.keys.each do |key|
406
+ if !attrs.include?(key) && !key.match(/^ext_/)
407
+ warn "image.#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
231
408
  end
232
409
  end
233
410
  end
234
411
  end
412
+ end
235
413
 
236
- add_check('sounds', "sounds attribute") do
237
-
238
- if !ext['sounds']
239
- err "sounds attribute is required"
240
- elsif !ext['sounds'].is_a?(Array)
241
- err "sounds attribute must be an array"
242
- end
414
+ add_check('sounds', "sounds attribute") do
415
+ if !ext['sounds']
416
+ err "sounds attribute is required"
417
+ elsif !ext['sounds'].is_a?(Array)
418
+ err "sounds attribute must be an array"
243
419
  end
244
-
245
- if ext['sounds'] && ext['sounds'].is_a?(Array)
246
- ext['sounds'].each_with_index do |sound, idx|
247
- add_check("sounds[#{idx}]", "sound at sounds[#{idx}]") do
248
- if !sound.is_a?(Hash)
249
- err "sound must be a hash"
250
- elsif !sound['id']
251
- err "sound.id is required"
252
- elsif !sound['duration'] || !sound['duration'].is_a?(Fixnum)
253
- err "sound.duration must be a valid positive number"
254
- elsif !sound['content_type'] || !sound['content_type'].match(/^audio\/.+$/)
255
- err "sound.content_type must be a valid audio mime type"
256
- elsif !sound['url'] && !sound['data'] && !sound['symbol']
257
- err "sound must have data, url or symbol attribute defined"
258
- elsif sound['data'] && !sound['data'].match(/^data:audio\/.+;base64,.+$/)
259
- err "sound.data must be a valid data URI if defined"
260
- end
261
-
262
- attrs = ['id', 'duration', 'content_type', 'data', 'url', 'path', 'data_url', 'license']
263
- sound.keys.each do |key|
264
- if !attrs.include?(key) && !key.match(/^ext_/)
265
- warn "sound.#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
266
- end
420
+ end
421
+
422
+ if ext && ext['sounds'] && ext['sounds'].is_a?(Array)
423
+ ext['sounds'].each_with_index do |sound, idx|
424
+ add_check("sounds[#{idx}]", "sound at sounds[#{idx}]") do
425
+ if !sound.is_a?(Hash)
426
+ err "sound must be a hash"
427
+ elsif !sound['id']
428
+ err "sound.id is required"
429
+ elsif !sound['duration'] || !sound['duration'].is_a?(Fixnum)
430
+ err "sound.duration must be a valid positive number"
431
+ elsif !sound['content_type'] || !sound['content_type'].match(/^audio\/.+$/)
432
+ err "sound.content_type must be a valid audio mime type"
433
+ elsif !sound['url'] && !sound['data'] && !sound['symbol']
434
+ err "sound must have data, url or symbol attribute defined"
435
+ elsif sound['data'] && !sound['data'].match(/^data:audio\/.+;base64,.+$/)
436
+ err "sound.data must be a valid data URI if defined"
437
+ end
438
+
439
+ attrs = ['id', 'duration', 'content_type', 'data', 'url', 'path', 'data_url', 'license']
440
+ sound.keys.each do |key|
441
+ if !attrs.include?(key) && !key.match(/^ext_/)
442
+ warn "sound.#{key} attribute is not defined in the spec, should be prefixed with ext_yourapp_"
267
443
  end
268
444
  end
269
445
  end
270
446
  end
271
447
  end
272
448
 
273
- if ext['buttons'] && ext['buttons'].is_a?(Array)
449
+ if ext && ext['buttons'] && ext['buttons'].is_a?(Array)
274
450
  ext['buttons'].each_with_index do |button, idx|
275
451
  add_check("buttons[#{idx}]", "button at buttons[#{idx}]") do
276
452
  if !button.is_a?(Hash)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: obf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Whitmer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-04 00:00:00.000000000 Z
11
+ date: 2014-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json