From 109ecb11c2f061d8cff344ba0e30970924578eb0 Mon Sep 17 00:00:00 2001 From: Iain Beeston Date: Thu, 30 Jun 2016 09:46:52 +0100 Subject: [PATCH] Removed uuidtools --- .travis.yml | 2 - CHANGELOG.md | 3 + gemfiles/Gemfile.uuidtools.x | 5 - lib/json-schema/util/uri.rb | 6 + lib/json-schema/util/uuid.rb | 285 ----------------------------------- lib/json-schema/validator.rb | 18 +-- test/uri_util_test.rb | 11 ++ 7 files changed, 23 insertions(+), 307 deletions(-) delete mode 100644 gemfiles/Gemfile.uuidtools.x delete mode 100644 lib/json-schema/util/uuid.rb create mode 100644 test/uri_util_test.rb diff --git a/.travis.yml b/.travis.yml index f34b9e45..235f7814 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,5 +20,3 @@ matrix: gemfile: "gemfiles/Gemfile.multi_json.x" - rvm: "2.3.1" gemfile: "gemfiles/Gemfile.yajl-ruby.x" - - rvm: "2.3.1" - gemfile: "gemfiles/Gemfile.uuidtools.x" diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ef35b47..6ac029ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Changed +- Replaced UUIDs with SHA1 hashes as the cache key for parsed schemas + ## [2.7.0] - 2016-09-29 ### Fixed diff --git a/gemfiles/Gemfile.uuidtools.x b/gemfiles/Gemfile.uuidtools.x deleted file mode 100644 index e3f30e93..00000000 --- a/gemfiles/Gemfile.uuidtools.x +++ /dev/null @@ -1,5 +0,0 @@ -source "https://rubygems.org" - -gemspec :path => "../" - -gem "uuidtools" diff --git a/lib/json-schema/util/uri.rb b/lib/json-schema/util/uri.rb index 6061625e..e8cfbc57 100644 --- a/lib/json-schema/util/uri.rb +++ b/lib/json-schema/util/uri.rb @@ -1,4 +1,5 @@ require 'addressable/uri' +require 'digest/sha1' module JSON module Util @@ -54,6 +55,11 @@ def self.file_uri(uri) Addressable::URI.convert_path(parsed_uri.path) end + def self.fake_uri(string) + digest = Digest::SHA1.hexdigest(string) + parse(digest) + end + def self.unescape_uri(uri) Addressable::URI.unescape(uri) end diff --git a/lib/json-schema/util/uuid.rb b/lib/json-schema/util/uuid.rb deleted file mode 100644 index 30879ad2..00000000 --- a/lib/json-schema/util/uuid.rb +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/env ruby -### http://mput.dip.jp/mput/uuid.txt - -# Copyright(c) 2005 URABE, Shyouhei. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this code, to deal in the code without restriction, including without -# limitation the rights to use, copy, modify, merge, publish, distribute, -# sublicense, and/or sell copies of the code, and to permit persons to whom the -# code is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the code. -# -# THE CODE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE CODE OR THE USE OR OTHER DEALINGS IN THE -# CODE. -# -# 2009-02-20: Modified by Pablo Lorenzoni to correctly -# include the version in the raw_bytes. - - -require 'digest/md5' -require 'digest/sha1' -require 'tmpdir' - -module JSON - module Util - - # Pure ruby UUID generator, which is compatible with RFC4122 - UUID = Struct.new :raw_bytes - - class UUID - private_class_method :new - - class << self - def mask19 v, str # :nodoc - nstr = str.bytes.to_a - version = [0, 16, 32, 48, 64, 80][v] - nstr[6] &= 0b00001111 - nstr[6] |= version - # nstr[7] &= 0b00001111 - # nstr[7] |= 0b01010000 - nstr[8] &= 0b00111111 - nstr[8] |= 0b10000000 - str = '' - nstr.each { |s| str << s.chr } - str - end - - def mask18 v, str # :nodoc - version = [0, 16, 32, 48, 64, 80][v] - str[6] &= 0b00001111 - str[6] |= version - # str[7] &= 0b00001111 - # str[7] |= 0b01010000 - str[8] &= 0b00111111 - str[8] |= 0b10000000 - str - end - - def mask v, str - if RUBY_VERSION >= "1.9.0" - return mask19 v, str - else - return mask18 v, str - end - end - private :mask, :mask18, :mask19 - - # UUID generation using SHA1. Recommended over create_md5. - # Namespace object is another UUID, some of them are pre-defined below. - def create_sha1 str, namespace - sha1 = Digest::SHA1.new - sha1.update namespace.raw_bytes - sha1.update str - sum = sha1.digest - raw = mask 5, sum[0..15] - ret = new raw - ret.freeze - ret - end - alias :create_v5 :create_sha1 - - # UUID generation using MD5 (for backward compat.) - def create_md5 str, namespace - md5 = Digest::MD5.new - md5.update namespace.raw_bytes - md5.update str - sum = md5.digest - raw = mask 3, sum[0..16] - ret = new raw - ret.freeze - ret - end - alias :create_v3 :create_md5 - - # UUID generation using random-number generator. From it's random - # nature, there's no warranty that the created ID is really universaly - # unique. - def create_random - rnd = [ - rand(0x100000000), - rand(0x100000000), - rand(0x100000000), - rand(0x100000000), - ].pack "N4" - raw = mask 4, rnd - ret = new raw - ret.freeze - ret - end - alias :create_v4 :create_random - - def read_state fp # :nodoc: - fp.rewind - Marshal.load fp.read - end - - def write_state fp, c, m # :nodoc: - fp.rewind - str = Marshal.dump [c, m] - fp.write str - end - - private :read_state, :write_state - STATE_FILE = 'ruby-uuid' - - # create the "version 1" UUID with current system clock, current UTC - # timestamp, and the IEEE 802 address (so-called MAC address). - # - # Speed notice: it's slow. It writes some data into hard drive on every - # invokation. If you want to speed this up, try remounting tmpdir with a - # memory based filesystem (such as tmpfs). STILL slow? then no way but - # rewrite it with c :) - def create clock=nil, time=nil, mac_addr=nil - c = t = m = nil - Dir.chdir Dir.tmpdir do - unless FileTest.exist? STATE_FILE then - # Generate a pseudo MAC address because we have no pure-ruby way - # to know the MAC address of the NIC this system uses. Note - # that cheating with pseudo arresses here is completely legal: - # see Section 4.5 of RFC4122 for details. - sha1 = Digest::SHA1.new - 256.times do - r = [rand(0x100000000)].pack "N" - sha1.update r - end - str = sha1.digest - r = rand 14 # 20-6 - node = str[r, 6] || str - if RUBY_VERSION >= "1.9.0" - nnode = node.bytes.to_a - nnode[0] |= 0x01 - node = '' - nnode.each { |s| node << s.chr } - else - node[0] |= 0x01 # multicast bit - end - k = rand 0x40000 - open STATE_FILE, 'w' do |fp| - fp.flock IO::LOCK_EX - write_state fp, k, node - fp.chmod 0o777 # must be world writable - end - end - open STATE_FILE, 'r+' do |fp| - fp.flock IO::LOCK_EX - c, m = read_state fp - c = clock % 0x4000 if clock - m = mac_addr if mac_addr - t = time - if t.nil? then - # UUID epoch is 1582/Oct/15 - tt = Time.now - t = tt.to_i*10000000 + tt.tv_usec*10 + 0x01B21DD213814000 - end - c = c.succ # important; increment here - write_state fp, c, m - end - end - - tl = t & 0xFFFF_FFFF - tm = t >> 32 - tm = tm & 0xFFFF - th = t >> 48 - th = th & 0x0FFF - th = th | 0x1000 - cl = c & 0xFF - ch = c & 0x3F00 - ch = ch >> 8 - ch = ch | 0x80 - pack tl, tm, th, cl, ch, m - end - alias :create_v1 :create - - # A simple GUID parser: just ignores unknown characters and convert - # hexadecimal dump into 16-octet object. - def parse obj - str = obj.to_s.sub %r/\Aurn:uuid:/, '' - str.gsub! %r/[^0-9A-Fa-f]/, '' - raw = str[0..31].lines.to_a.pack 'H*' - ret = new raw - ret.freeze - ret - end - - # The 'primitive constructor' of this class - # Note UUID.pack(uuid.unpack) == uuid - def pack tl, tm, th, ch, cl, n - raw = [tl, tm, th, ch, cl, n].pack "NnnCCa6" - ret = new raw - ret.freeze - ret - end - end - - # The 'primitive deconstructor', or the dual to pack. - # Note UUID.pack(uuid.unpack) == uuid - def unpack - raw_bytes.unpack "NnnCCa6" - end - - # Generate the string representation (a.k.a GUID) of this UUID - def to_s - a = unpack - tmp = a[-1].unpack 'C*' - a[-1] = sprintf '%02x%02x%02x%02x%02x%02x', *tmp - "%08x-%04x-%04x-%02x%02x-%s" % a - end - alias guid to_s - - # Convert into a RFC4122-comforming URN representation - def to_uri - "urn:uuid:" + self.to_s - end - alias urn to_uri - - # Convert into 128-bit unsigned integer - # Typically a Bignum instance, but can be a Fixnum. - def to_int - tmp = self.raw_bytes.unpack "C*" - tmp.inject do |r, i| - r * 256 | i - end - end - alias to_i to_int - - # Gets the version of this UUID - # returns nil if bad version - def version - a = unpack - v = (a[2] & 0xF000).to_s(16)[0].chr.to_i - return v if (1..5).include? v - return nil - end - - # Two UUIDs are said to be equal if and only if their (byte-order - # canonicalized) integer representations are equivallent. Refer RFC4122 for - # details. - def == other - to_i == other.to_i - end - - include Comparable - # UUIDs are comparable (don't know what benefits are there, though). - def <=> other - to_s <=> other.to_s - end - - # Pre-defined UUID Namespaces described in RFC4122 Appendix C. - NameSpace_DNS = parse "6ba7b810-9dad-11d1-80b4-00c04fd430c8" - NameSpace_URL = parse "6ba7b811-9dad-11d1-80b4-00c04fd430c8" - NameSpace_OID = parse "6ba7b812-9dad-11d1-80b4-00c04fd430c8" - NameSpace_X500 = parse "6ba7b814-9dad-11d1-80b4-00c04fd430c8" - - # The Nil UUID in RFC4122 Section 4.1.7 - Nil = parse "00000000-0000-0000-0000-000000000000" - end - end -end \ No newline at end of file diff --git a/lib/json-schema/validator.rb b/lib/json-schema/validator.rb index 9aac21c2..c1d7990b 100644 --- a/lib/json-schema/validator.rb +++ b/lib/json-schema/validator.rb @@ -507,14 +507,6 @@ def validators_for_names(names) private - if Gem::Specification::find_all_by_name('uuidtools').any? - require 'uuidtools' - @@fake_uuid_generator = lambda{|s| UUIDTools::UUID.sha1_create(UUIDTools::UUID_URL_NAMESPACE, s).to_s } - else - require 'json-schema/util/uuid' - @@fake_uuid_generator = lambda{|s| JSON::Util::UUID.create_v5(s,JSON::Util::UUID::Nil).to_s } - end - def serialize schema if defined?(MultiJson) MultiJson.respond_to?(:dump) ? MultiJson.dump(schema) : MultiJson.encode(schema) @@ -523,15 +515,11 @@ def serialize schema end end - def fake_uuid schema - @@fake_uuid_generator.call(schema) - end - def initialize_schema(schema) if schema.is_a?(String) begin # Build a fake URI for this - schema_uri = JSON::Util::URI.parse(fake_uuid(schema)) + schema_uri = JSON::Util::URI.fake_uri(schema) schema = JSON::Schema.new(JSON::Validator.parse(schema), schema_uri, @options[:version]) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema @@ -553,14 +541,14 @@ def initialize_schema(schema) schema = self.class.schema_for_uri(schema_uri) if @options[:list] && @options[:fragment].nil? schema = schema.to_array_schema - schema.uri = JSON::Util::URI.parse(fake_uuid(serialize(schema.schema))) + schema.uri = JSON::Util::URI.fake_uri(serialize(schema.schema)) Validator.add_schema(schema) end schema end end elsif schema.is_a?(Hash) - schema_uri = JSON::Util::URI.parse(fake_uuid(serialize(schema))) + schema_uri = JSON::Util::URI.fake_uri(serialize(schema)) schema = JSON::Schema.stringify(schema) schema = JSON::Schema.new(schema, schema_uri, @options[:version]) if @options[:list] && @options[:fragment].nil? diff --git a/test/uri_util_test.rb b/test/uri_util_test.rb new file mode 100644 index 00000000..49e10623 --- /dev/null +++ b/test/uri_util_test.rb @@ -0,0 +1,11 @@ +require File.expand_path('../support/test_helper', __FILE__) + +class UriUtilTest < Minitest::Test + def test_fake_uri_is_unique + refute_equal JSON::Util::URI.fake_uri('foo'), JSON::Util::URI.fake_uri('bar') + end + + def test_fake_uri_is_reproducible + assert_equal JSON::Util::URI.fake_uri('foo'), JSON::Util::URI.fake_uri('foo') + end +end