diff --git a/lib/sisimai/rfc5322.rb b/lib/sisimai/rfc5322.rb index bf8234d8..0573c945 100644 --- a/lib/sisimai/rfc5322.rb +++ b/lib/sisimai/rfc5322.rb @@ -2,7 +2,7 @@ module Sisimai # Sisimai::RFC5322 provide methods for checking email address. module RFC5322 class << self - require 'sisimai/string' + require 'sisimai/rfc791' require 'sisimai/address' HeaderTable = { :messageid => %w[message-id], @@ -119,7 +119,7 @@ def received(argv1) next if token[e].nil? next if token[e].empty? next unless token[e].start_with?('[') - token[e] = Sisimai::String.ipv4(token[e]).shift || '' + token[e] = Sisimai::RFC791.find(token[e]).shift || '' end token['from'] ||= '' @@ -128,7 +128,7 @@ def received(argv1) break if token['from'] == 'localhost' break if token['from'] == 'localhost.localdomain' break unless token['from'].include?('.') # A hostname without a domain name - break unless Sisimai::String.ipv4(token['from']).empty? + break unless Sisimai::RFC791.find(token['from']).empty? # No need to rewrite token['from'] right = true diff --git a/lib/sisimai/rfc791.rb b/lib/sisimai/rfc791.rb new file mode 100644 index 00000000..d4dd9059 --- /dev/null +++ b/lib/sisimai/rfc791.rb @@ -0,0 +1,53 @@ +module Sisimai + # Sisimai::RFC791 is a class related to the Internet host + module RFC791 + class << self + # Find an IPv4 address from the given string + # @param [String] argv1 String including an IPv4 address + # @return [Array] List of IPv4 addresses + # @since v5.0.0 + def find(argv0) + return nil if argv0.to_s.empty? + return [] if argv0.size < 7 + + ipv4a = [] + %w|( ) [ ] ,|.each do |e| + # Rewrite: "mx.example.jp[192.0.2.1]" => "mx.example.jp 192.0.2.1" + p0 = argv0.index(e); next unless p0 + argv0[p0, 1] = ' ' + end + + argv0.split(' ').each do |e| + # Find string including an IPv4 address + next unless e.index('.') # IPv4 address must include "." character + + lx = e.size; next if lx < 7 || lx > 17 # 0.0.0.0 = 7, [255.255.255.255] = 17 + cu = 0 # Cursor for seeking each octet of an IPv4 address + as = '' # ASCII Code of each character + eo = '' # Buffer of each octet of IPv4 Address + + while cu < lx + # Check whether each character is a number or "." or not + as = e[cu, 1].ord + cu += 1 + + if as < 48 || as > 57 + # The character is not a number(0-9) + break if as != 46 # The character is not "." + next if eo == '' # The current buffer is empty + break if eo.to_i > 255 # The current buffer is greater than 255 + eo = '' + next + end + eo << as.chr + break if eo.to_i > 255 + end + ipv4a << e if eo.size > 0 && eo.to_i < 256 + end + return ipv4a + end + + end + end +end + diff --git a/lib/sisimai/smtp/status.rb b/lib/sisimai/smtp/status.rb index 33e8e399..b634aa81 100644 --- a/lib/sisimai/smtp/status.rb +++ b/lib/sisimai/smtp/status.rb @@ -479,7 +479,7 @@ module SMTP # reason from D.S.N. value, and getting D.S.N. from the text including D.S.N. module Status class << self - require "sisimai/string" + require "sisimai/rfc791" CodePatterns = [ %r/[ ]?[(][#]([45][.]\d[.]\d+)[)]?[ ]?/, # #5.5.1 @@ -733,7 +733,7 @@ def find(argv1 = nil, argv2 = '0') esmtperror = ' ' + argv1 + ' ' lookingfor = [] - Sisimai::String.ipv4(esmtperror).each do |e| + Sisimai::RFC791.find(esmtperror).each do |e| # Rewrite an IPv4 address in the given string(argv1) with '***.***.***.***' p0 = esmtperror.index(e) || next esmtperror[p0, e.size] = '***.***.***.***' diff --git a/lib/sisimai/string.rb b/lib/sisimai/string.rb index b74caa5d..a700dd8d 100644 --- a/lib/sisimai/string.rb +++ b/lib/sisimai/string.rb @@ -75,52 +75,6 @@ def aligned(argv1, argv2) return false end - # Find an IPv4 address from the given string - # @param [String] argv1 String including an IPv4 address - # @return [Array] List of IPv4 addresses - # @since v5.0.0 - def ipv4(argv0) - return nil if argv0.to_s.empty? - return [] if argv0.size < 7 - - ipv4a = [] - %w|( ) [ ] ,|.each do |e| - # Rewrite: "mx.example.jp[192.0.2.1]" => "mx.example.jp 192.0.2.1" - p0 = argv0.index(e); next unless p0 - argv0[p0, 1] = ' ' - end - - argv0.split(' ').each do |e| - # Find string including an IPv4 address - next unless e.index('.') # IPv4 address must include "." character - - lx = e.size; next if lx < 7 || lx > 17 # 0.0.0.0 = 7, [255.255.255.255] = 17 - cu = 0 # Cursor for seeking each octet of an IPv4 address - as = '' # ASCII Code of each character - eo = '' # Buffer of each octet of IPv4 Address - - while cu < lx - # Check whether each character is a number or "." or not - as = e[cu, 1].ord - cu += 1 - - if as < 48 || as > 57 - # The character is not a number(0-9) - break if as != 46 # The character is not "." - next if eo == '' # The current buffer is empty - break if eo.to_i > 255 # The current buffer is greater than 255 - eo = '' - next - end - eo << as.chr - break if eo.to_i > 255 - end - ipv4a << e if eo.size > 0 && eo.to_i < 256 - end - - return ipv4a - end - # Convert given HTML text to plain text # @param [String] argv1 HTML text # @param [Boolean] loose Loose check flag diff --git a/test/public/rfc791-test.rb b/test/public/rfc791-test.rb new file mode 100644 index 00000000..3b40bce0 --- /dev/null +++ b/test/public/rfc791-test.rb @@ -0,0 +1,29 @@ +require 'minitest/autorun' +require 'sisimai/rfc791' + +class RFC791Test < Minitest::Test + Methods = { class: %w[find] } + + def test_ipv4 + ip4address = [ + ['host smtp.example.jp 127.0.0.4 SMTP error from remote mail server', '127.0.0.4'], + ['mx.example.jp (192.0.2.2) reason: 550 5.2.0 Mail rejete.', '192.0.2.2'], + ['Client host [192.0.2.49] blocked using cbl.abuseat.org (state 13).', '192.0.2.49'], + ['127.0.0.1', '127.0.0.1'], + ['365.31.7.1', ''], + ['a.b.c.d', ''], + ] + ip4address.each do |e| + assert_equal e[1], Sisimai::RFC791.find(e[0]).shift.to_s + end + assert_nil Sisimai::RFC791.find('') + assert_instance_of Array, Sisimai::RFC791.find('3.14') + + ce = assert_raises ArgumentError do + Sisimai::RFC791.find() + Sisimai::RFC791.find("nekochan", nil) + end + end + +end + diff --git a/test/public/string-test.rb b/test/public/string-test.rb index 2d7f0ebb..71b13511 100644 --- a/test/public/string-test.rb +++ b/test/public/string-test.rb @@ -2,7 +2,7 @@ require 'sisimai/string' class StringTest < Minitest::Test - Methods = { class: %w[token is_8bit sweep aligned ipv4 to_plain to_utf8] } + Methods = { class: %w[token is_8bit sweep aligned to_plain to_utf8] } def test_methods Methods[:class].each { |e| assert_respond_to Sisimai::String, e } @@ -69,27 +69,6 @@ def test_aligned end end - def test_ipv4 - ip4address = [ - ['host smtp.example.jp 127.0.0.4 SMTP error from remote mail server', '127.0.0.4'], - ['mx.example.jp (192.0.2.2) reason: 550 5.2.0 Mail rejete.', '192.0.2.2'], - ['Client host [192.0.2.49] blocked using cbl.abuseat.org (state 13).', '192.0.2.49'], - ['127.0.0.1', '127.0.0.1'], - ['365.31.7.1', ''], - ['a.b.c.d', ''], - ] - ip4address.each do |e| - assert_equal e[1], Sisimai::String.ipv4(e[0]).shift.to_s - end - assert_nil Sisimai::String.ipv4('') - assert_instance_of Array, Sisimai::String.ipv4('3.14') - - ce = assert_raises ArgumentError do - Sisimai::String.ipv4() - Sisimai::String.ipv4("nekochan", nil) - end - end - Ht1 = '