kataba 1.0.0 → 1.0.3

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.
Files changed (3) hide show
  1. checksums.yaml +5 -5
  2. data/lib/kataba.rb +75 -20
  3. metadata +57 -16
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: fd9fd6f5ee1170b5552d4345a4c23fab923efcaa
4
- data.tar.gz: e78ca648b702ecd40a576263eb6aaab7d4fd4d13
2
+ SHA256:
3
+ metadata.gz: 97107593bef37bc5a20d934c683ca45c5c1142d301bc705067a20b3e94a07d58
4
+ data.tar.gz: fee7e5c92557a7f85170a395a97de0055b447d978d822575aadf8a6fe301b391
5
5
  SHA512:
6
- metadata.gz: 13ed9bbd4e28ee1e7e8e955f6ea9084b52e94da83458d395fb776a75b40094079e640bdb82c7424eca93dc27b1063968b3fb96791723d1a9d432a29837a18362
7
- data.tar.gz: 46f8e1813d56ecdd4cd689bd5ee2354d250861f1b627cd0812fed4ed36b4ccab8aa8313a779416e0ee69e12fb08c048c7f4bd109d2f626af1e20ac49c426ac5c
6
+ metadata.gz: 28c18ab1818719194b5f9ae1a512bfad8716caf430fac3ce4509dad455e4796cf9634bf33fec4b0e51501cea3dc70b1908945dfd4c80d71316d61bac2fa68293
7
+ data.tar.gz: d7d05f52acc72e4f6ed031d255304b7d37984f07e89d24bf76c74e9e6be40bf06e1dab08a07f9eb8e7b2d8633c39b6d93ea10df503752189672ea0689e397dc0
data/lib/kataba.rb CHANGED
@@ -2,12 +2,17 @@ require 'nokogiri'
2
2
  require 'tmpdir'
3
3
  require 'digest/md5'
4
4
  require 'open-uri'
5
+ require 'fileutils'
6
+ require 'yaml'
5
7
 
6
8
  module Kataba
7
9
 
8
- class << self
9
- attr_accessor :configuration
10
- end
10
+ # Allows for configuration by block
11
+ #
12
+ # Example:
13
+ # MegaLotto.configure do |config|
14
+ # config.drawing_count = 10
15
+ # end
11
16
 
12
17
  def self.configure
13
18
  yield(configuration) if block_given?
@@ -17,35 +22,71 @@ module Kataba
17
22
  @configuration ||= Configuration.new
18
23
  end
19
24
 
25
+ # Undoes any configuration - this method was built for testing purposes
26
+ #
27
+ # Example:
28
+ # Kataba.reset
29
+
20
30
  def self.reset
21
31
  @configuration = Configuration.new
22
32
  end
23
33
 
24
34
  class Configuration
35
+ # Offline storage is "#{Dir.tmpdir}/kataba" by default.
36
+ # This attribute allows the user to change that default value.
37
+ #
38
+ # Example:
39
+ # Kataba.configuration.offline_storage = "/tmp/kataba"
25
40
  attr_accessor :offline_storage
41
+ # The user can optionally provide a mirror list to reduce stress on primary XSD providers.
42
+ # This attribute allows the user to configure Kataba to use a YAML file with key/value pairs of
43
+ # original/mirror values. Sample YAML file can be found at https://github.com/dgcliff/kataba/blob/master/test/fixtures/mirror.yml
44
+ #
45
+ # Example:
46
+ # Kataba.configuration.mirror_list = File.join(Rails.root, 'config', 'mirror.yml')
26
47
  attr_accessor :mirror_list
27
48
 
49
+ # Default configuration values
28
50
  def initialize
29
51
  @offline_storage = "#{Dir.tmpdir}/kataba"
30
52
  end
31
53
  end
32
54
 
55
+ # If already downloaded, uses offline version. If not, downloads from the URI provided.
56
+ # If mirror list is configured, searches for mirrored URI instead.
57
+ #
58
+ # Example:
59
+ # Kataba.fetch_schema("http://www.loc.gov/standards/mods/v3/mods-3-5.xsd")
60
+ #
61
+ # Arguments:
62
+ # xsd_uri: (String)
63
+
33
64
  def self.fetch_schema(xsd_uri)
34
65
  uri_md5 = Digest::MD5.hexdigest(xsd_uri)
35
66
  dir_path = "#{self.configuration.offline_storage}"
36
67
  xsd_path = "#{dir_path}/#{uri_md5}.xsd"
37
68
 
38
- # Does the offline version exist already?
39
- if !(File.exists?(xsd_path))
40
- # If not, go download
41
- xsd_array = []
42
- xsd_array << xsd_uri
43
- download_xsd(xsd_array)
44
- end
69
+ attempts = 0
70
+ begin
71
+ # Does the offline version exist already?
72
+ if !(File.exist?(xsd_path))
73
+ # If not, go download
74
+ xsd_array = []
75
+ xsd_array << xsd_uri
76
+ download_xsd(xsd_array)
77
+ end
45
78
 
46
- # Validate and return Nokogiri schema
47
- Dir.chdir(dir_path) do
48
- return Nokogiri::XML::Schema(IO.read(xsd_path))
79
+ # Validate and return Nokogiri schema
80
+ Dir.chdir(dir_path) do
81
+ return Nokogiri::XML::Schema(IO.read(xsd_path))
82
+ end
83
+ rescue Nokogiri::XML::SyntaxError
84
+ # Poisoned cache (e.g. a pre-fix install that stored a bad fetch).
85
+ # Evict the offending file and refetch once.
86
+ File.delete(xsd_path) if File.exist?(xsd_path)
87
+ attempts += 1
88
+ retry if attempts < 2
89
+ raise
49
90
  end
50
91
  end
51
92
 
@@ -67,23 +108,37 @@ module Kataba
67
108
  end
68
109
 
69
110
  file_path = "#{dir_name}/#{uri_md5}.xsd"
70
-
71
- file_paths << file_path
72
-
73
- open(file_path, "wb+") do |file|
111
+ tmp_path = "#{file_path}.part"
112
+
113
+ # Write to a .part file first; only rename to the final cache path
114
+ # after we've confirmed the bytes parse as XML. Without this, a
115
+ # malformed response (HTML error page, truncated TCP stream, captive
116
+ # portal stub) would land at the canonical cache path and poison
117
+ # every subsequent fetch.
118
+ File.open(tmp_path, "wb+") do |file|
74
119
  if !self.configuration.mirror_list.to_s.empty?
75
120
  mirror_list = YAML.load_file(self.configuration.mirror_list)
76
121
  mirror = mirror_list[xsd_uri]
77
122
  if mirror.to_s.empty?
78
123
  # No mirror for that uri
79
- file.write(open(xsd_uri).read)
124
+ file.write(URI.open(xsd_uri).read)
80
125
  else
81
- file.write(open(mirror).read)
126
+ file.write(URI.open(mirror).read)
82
127
  end
83
128
  else
84
- file.write(open(xsd_uri).read)
129
+ file.write(URI.open(xsd_uri).read)
85
130
  end
86
131
  end
132
+
133
+ begin
134
+ Nokogiri::XML(File.read(tmp_path)) { |c| c.strict }
135
+ rescue Nokogiri::XML::SyntaxError
136
+ File.delete(tmp_path)
137
+ raise
138
+ end
139
+
140
+ File.rename(tmp_path, file_path)
141
+ file_paths << file_path
87
142
  end
88
143
 
89
144
  # Search inside for other schemaLocations
metadata CHANGED
@@ -1,31 +1,73 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kataba
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cliff
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-02 00:00:00.000000000 Z
11
+ date: 2026-05-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '1.19'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
27
- description: A simple gem that allows for the functionality that an XML catalog would
28
- provide
26
+ version: '1.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: minitest
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: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: Kataba allows for mirroring and offline storage of XSD files, to enhance
70
+ Nokogiri
29
71
  email: d.cliff@northeastern.edu
30
72
  executables: []
31
73
  extensions: []
@@ -36,24 +78,23 @@ homepage: http://rubygems.org/gems/kataba
36
78
  licenses:
37
79
  - MIT
38
80
  metadata: {}
39
- post_install_message:
81
+ post_install_message:
40
82
  rdoc_options: []
41
83
  require_paths:
42
84
  - lib
43
85
  required_ruby_version: !ruby/object:Gem::Requirement
44
86
  requirements:
45
- - - ~>
87
+ - - ">="
46
88
  - !ruby/object:Gem::Version
47
- version: '2.0'
89
+ version: '3.2'
48
90
  required_rubygems_version: !ruby/object:Gem::Requirement
49
91
  requirements:
50
- - - '>='
92
+ - - ">="
51
93
  - !ruby/object:Gem::Version
52
94
  version: '0'
53
95
  requirements: []
54
- rubyforge_project:
55
- rubygems_version: 2.2.2
56
- signing_key:
96
+ rubygems_version: 3.4.10
97
+ signing_key:
57
98
  specification_version: 4
58
99
  summary: XML Schema Definition (XSD) mirroring and offline validation for Nokogiri
59
100
  test_files: []