ip_in_range 0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/ip_in_range +118 -0
- data/ip_in_range.gemspec +19 -0
- data/lib/email.rb +64 -0
- data/lib/file_checking.rb +119 -0
- data/lib/ip_range.rb +84 -0
- data/lib/log.conf +56 -0
- data/lib/logging.rb +198 -0
- data/lib/version.rb +4 -0
- metadata +51 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d47e8fd962fb2d1255beaf5033a5c2a46bfb11a261b11e4424034b8827d8af9b
|
4
|
+
data.tar.gz: 5214a27f60c1a1dd87eb2be2d6e45374205272b10fa6ad4885eea2ccadb1bb8a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 42804793ba4ade8ad7e6bd8144b08535b6e626ac0a0962e78829c72c8c12444cec92d95f30b0ecfe66c83f1109660476253898a0acfd7707a3834fce6556b04e
|
7
|
+
data.tar.gz: 90639f79f3dc5d8dc678c04a39b634e63aad140364e573780dace104b17782a160526efeb9eead32620b32d1d4129522eb21abdf115a8ee2bfe7428cb68f842b
|
data/bin/ip_in_range
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2021-2021, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
require_relative '../lib/ip_range'
|
24
|
+
require_relative '../lib/email'
|
25
|
+
require_relative '../lib/logging'
|
26
|
+
require_relative '../lib/file_checking'
|
27
|
+
|
28
|
+
self.extend(Logging)
|
29
|
+
log = init_logger(STDOUT)
|
30
|
+
|
31
|
+
def usage
|
32
|
+
usage = "\tUsage: " << $0 << ' first_in_range last_in_range ip_to_check'
|
33
|
+
usage << "\n\tExample: " << $0 << ' 192.168.1.100 192.168.1.255 192.168.10.100'
|
34
|
+
usage << "\n\t\t to verify Received-headers: cat mail | " << $0 << " first_in_range last_in_range"
|
35
|
+
usage << "\n\t\t or: cat mail | " << $0 << " <file>"
|
36
|
+
usage << "\n\t\t where \"file\" contains a list of ip-ranges."
|
37
|
+
end
|
38
|
+
|
39
|
+
# primitive as there is nothing to gain from more complexity
|
40
|
+
IPR = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/
|
41
|
+
|
42
|
+
# 1) first last ip_to_check
|
43
|
+
if ARGV.length >= 3
|
44
|
+
ip_range = IPRange.new(ARGV)
|
45
|
+
exit ip_range.in_range?(ARGV[2]).to_s
|
46
|
+
# 2) first last (mail is piped-in)
|
47
|
+
elsif ARGV.length == 2
|
48
|
+
ip_range = IPRange.new(ARGV)
|
49
|
+
ARGV.clear
|
50
|
+
if(!STDIN.tty?)
|
51
|
+
mail = FMail.new(ARGF.read)
|
52
|
+
else
|
53
|
+
log.error('No data to compare from STDIN – aborting!')
|
54
|
+
exit false
|
55
|
+
end
|
56
|
+
ips = mail.received.collect{|r| r.scan(IPR)}
|
57
|
+
ips.flatten!
|
58
|
+
log.debug( 'ips: ' << ips.join(', '))
|
59
|
+
ips.each do |ip|
|
60
|
+
exit true if ip_range.in_range?(ip)
|
61
|
+
end
|
62
|
+
log.info('not in range')
|
63
|
+
exit false
|
64
|
+
# 3) a text-file with ip-ranges, mail is piped in
|
65
|
+
elsif ARGV.length == 1
|
66
|
+
list_file = ARGV[0]
|
67
|
+
ARGV.clear
|
68
|
+
if(!STDIN.tty?)
|
69
|
+
mail = FMail.new(ARGF.read)
|
70
|
+
else
|
71
|
+
log.error('No data waiting on STDIN – aborting!')
|
72
|
+
exit false
|
73
|
+
end
|
74
|
+
msg = File_Checking::file_check(list_file, [:file, :exist, :readable])
|
75
|
+
if msg
|
76
|
+
log.error( "File #{list_file} is unuseable: #{msg}. Aborting!" )
|
77
|
+
exit false
|
78
|
+
end
|
79
|
+
ranges = File.readlines(list_file)
|
80
|
+
ranges.each do |l|
|
81
|
+
log.debug( "line is " << l)
|
82
|
+
if(!l.strip.empty?)
|
83
|
+
begin
|
84
|
+
log.debug 'trying to extract an IP-range'
|
85
|
+
range = l.scan(IPR).flatten
|
86
|
+
log.debug('testing range ' << range.to_s)
|
87
|
+
rescue ArgumentError => msg
|
88
|
+
er = 'Cannot interpret IP-range ' << l
|
89
|
+
er << ': ' << msg
|
90
|
+
log.error(er)
|
91
|
+
rescue Exception => msg
|
92
|
+
log.error(msg)
|
93
|
+
else
|
94
|
+
log.debug( "range is " << range.to_s )
|
95
|
+
ip_range = IPRange.new(range)
|
96
|
+
log.debug( "testing ip_range " << ip_range.vrange.to_s )
|
97
|
+
ips = mail.received.collect{|r| r.scan(IPR)}
|
98
|
+
ips.flatten!
|
99
|
+
log.debug( 'ips: ' << ips.join(', ') )
|
100
|
+
ips.each do |ip|
|
101
|
+
isso = ip_range.in_range?(ip)
|
102
|
+
msg = 'ip ' << ip << (isso ? ' is ' : ' is not ' ) << 'in range: ' << l
|
103
|
+
if isso
|
104
|
+
log.info(msg)
|
105
|
+
else
|
106
|
+
log.debug(msg)
|
107
|
+
end
|
108
|
+
exit isso if isso
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
exit false
|
114
|
+
else
|
115
|
+
log.warn( "ERROR! Arguments missing" )
|
116
|
+
log.info( usage)
|
117
|
+
exit false
|
118
|
+
end
|
data/ip_in_range.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "lib/version"
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.version = VERSION
|
6
|
+
s.name = File.basename(__FILE__, '.gemspec')
|
7
|
+
s.date = Date.today.strftime('%F')
|
8
|
+
s.summary = SUMMARY
|
9
|
+
s.description = "Verify that an IP is in a range"
|
10
|
+
s.authors = AUTHORS
|
11
|
+
s.email = EMAIL
|
12
|
+
s.files = %w~ip_in_range~.collect{|f| 'bin/' << f} + %w~log.conf ip_range.rb version.rb file_checking.rb logging.rb email.rb~.collect{|f| 'lib/' << f} + %w~ip_in_range.gemspec~.collect{|f|f} + %w~~.collect{|f| 'doc/' << f}
|
13
|
+
s.homepage = ''
|
14
|
+
#s.requirements = ''
|
15
|
+
#s.add_runtime_dependency ''
|
16
|
+
s.executables = 'ip_in_range'
|
17
|
+
s.license = 'GPL-3.0'
|
18
|
+
s.required_ruby_version = '>= 2.7'
|
19
|
+
end
|
data/lib/email.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2021-2021, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
require_relative 'logging'
|
25
|
+
require 'mail'
|
26
|
+
|
27
|
+
class FMail
|
28
|
+
extend Logging
|
29
|
+
@@log = init_logger(STDOUT)
|
30
|
+
|
31
|
+
def initialize(mail_text)
|
32
|
+
@log = @@log
|
33
|
+
if !mail_text || mail_text.empty?
|
34
|
+
@log.error('No mail-text provided. Aborting!')
|
35
|
+
exit false
|
36
|
+
end
|
37
|
+
@mail_text = mail_text
|
38
|
+
# @log.debug('mail text is ' << @mail_text)
|
39
|
+
extr_received
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_reader :received
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def extr_received
|
47
|
+
begin
|
48
|
+
@mail = Mail::read_from_string(@mail_text)
|
49
|
+
rescue Exception => ex
|
50
|
+
@log.error("cannot analyze this mail: " << ex.message)
|
51
|
+
@log.error("Aborting!")
|
52
|
+
exit false;
|
53
|
+
end
|
54
|
+
headers = @mail.header_fields
|
55
|
+
@received = headers.filter{|h| h.name == 'Received'}.collect{|h| h.unparsed_value}
|
56
|
+
@log.debug("found received-headers: " << @received.to_s)
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
############ TEST ##############
|
62
|
+
if __FILE__ == $0
|
63
|
+
ml = FMail.new(ARGF.read)
|
64
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2021 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
|
23
|
+
require 'filemagic'
|
24
|
+
|
25
|
+
=begin
|
26
|
+
A module to facilitate frequently occuring checks on
|
27
|
+
file-system objects
|
28
|
+
=end
|
29
|
+
module File_Checking
|
30
|
+
|
31
|
+
@@text_messages = {
|
32
|
+
:exist? => "does not exist!",
|
33
|
+
:exist => "does not exist!",
|
34
|
+
:readable? => "is not readable!",
|
35
|
+
:readable => "is not readable!",
|
36
|
+
:executable? => "is not executable!",
|
37
|
+
:executable => "is not executable!",
|
38
|
+
:writable? => "is not writable!",
|
39
|
+
:writable => "is not writable!",
|
40
|
+
:directory? => "is not a directory!",
|
41
|
+
:directory => "is not a directory!",
|
42
|
+
:file? => "is not a file!",
|
43
|
+
:file => "is not a file!",
|
44
|
+
# different thing
|
45
|
+
:type => "is not of the sought file-type (not '%s', but '%s')!",
|
46
|
+
:mime => "does not have the sought mime-type (not '%s', but '%s')!",
|
47
|
+
}
|
48
|
+
|
49
|
+
# Checks if the file with the name from the first
|
50
|
+
# parameter has the properties, listed in the second.
|
51
|
+
# The messages parameter is an array of one or several
|
52
|
+
# of :exist?, :readable?, :writable?, :directory? or
|
53
|
+
# their string-representations, respectively.
|
54
|
+
# Returns nil in case of success, otherwise an
|
55
|
+
# informative message, describing the first negative
|
56
|
+
# test-result.
|
57
|
+
def file_check(file, *messages)
|
58
|
+
File_Checking.file_check(file, *messages)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Checks if the file with the name from the first
|
62
|
+
# parameter has the properties, listed in the second.
|
63
|
+
# The messages parameter is an array of one or all
|
64
|
+
# of :exist?, :readable?, :writable?, :directory? or
|
65
|
+
# their string-representations, respectively.
|
66
|
+
# Returns nil in case of success, otherwise an
|
67
|
+
# informative message, describing the first negative
|
68
|
+
# test-result.
|
69
|
+
def self.file_check(file, *messages)
|
70
|
+
msg = nil
|
71
|
+
if(file && messages.respond_to?(:to_ary) && !messages.empty?)
|
72
|
+
messages.each do |k|
|
73
|
+
if( k != :mime && k != :type)
|
74
|
+
if(! k.to_s.end_with?('?'))
|
75
|
+
k = (k.to_s << '?').to_sym
|
76
|
+
end
|
77
|
+
@log.debug ('checking ' << k.to_s) if @log
|
78
|
+
if(msg == nil && File.respond_to?(k) && ! File.send(k, file.to_s))
|
79
|
+
msg = "#{file} #{@@text_messages[k.to_sym]}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
msg
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.mime_check(file, mime_type)
|
88
|
+
fm = FileMagic.mime
|
89
|
+
fd = fm.fd(File.new(file) ).split(';')[0]
|
90
|
+
if fd != mime_type.strip
|
91
|
+
return file.dup << ' ' << (@@text_messages[:mime] %[mime_type, fd])
|
92
|
+
end
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.magic_check(file, magic)
|
97
|
+
fm = FileMagic.fm
|
98
|
+
fd = fm.fd(File.new(file) ).split(';')[0]
|
99
|
+
if fd != magic.strip
|
100
|
+
return file.dup << ' ' << (@@text_messages[:type] %[magic, fd])
|
101
|
+
end
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
|
105
|
+
end # module
|
106
|
+
|
107
|
+
=begin
|
108
|
+
# example
|
109
|
+
|
110
|
+
include File_Checking
|
111
|
+
msg = file_check('some_file.txt', [:exist?, :readable?, 'writable'])
|
112
|
+
# same as
|
113
|
+
# msg = file_check('some_file.txt', [:exist, :readable, 'writable?'])
|
114
|
+
|
115
|
+
msg ||= magic_check('some_file.txt', [:type?], 'OpenDocument Text'
|
116
|
+
msg ||= mime_check('some_file.txt', [:mime?], 'application/vnd.oasis.opendocument.text'
|
117
|
+
puts msg if msg
|
118
|
+
=end
|
119
|
+
# E O F
|
data/lib/ip_range.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#encoding: UTF-8
|
3
|
+
=begin
|
4
|
+
/***************************************************************************
|
5
|
+
* ©2021-2021, Michael Uplawski <michael.uplawski@uplawski.eu> *
|
6
|
+
* *
|
7
|
+
* This program is free software; you can redistribute it and/or modify *
|
8
|
+
* it under the terms of the GNU General Public License as published by *
|
9
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
10
|
+
* (at your option) any later version. *
|
11
|
+
* *
|
12
|
+
* This program is distributed in the hope that it will be useful, *
|
13
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
14
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
15
|
+
* GNU General Public License for more details. *
|
16
|
+
* *
|
17
|
+
* You should have received a copy of the GNU General Public License *
|
18
|
+
* along with this program; if not, write to the *
|
19
|
+
* Free Software Foundation, Inc., *
|
20
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
21
|
+
***************************************************************************/
|
22
|
+
=end
|
23
|
+
|
24
|
+
require_relative 'logging'
|
25
|
+
class IPRange
|
26
|
+
extend Logging
|
27
|
+
@@log = init_logger(STDOUT)
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# return ip as Integer
|
32
|
+
def ip_to_number(ip)
|
33
|
+
nibbles = ip.split('.')
|
34
|
+
nibbles = nibbles.collect {|n| n.to_i}
|
35
|
+
if nibbles.size == 4
|
36
|
+
( (nibbles[0] * 256 + nibbles[1] ) * 256 + nibbles[2] ) * 256 + nibbles[3]
|
37
|
+
else
|
38
|
+
@log.error(ip.dup << " is not an IP-address!")
|
39
|
+
return nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
public
|
44
|
+
|
45
|
+
# check IP in range ?
|
46
|
+
def in_range?(cip)
|
47
|
+
(@first..@last) === ip_to_number(cip)
|
48
|
+
end
|
49
|
+
|
50
|
+
def irange()
|
51
|
+
[@first, @last]
|
52
|
+
end
|
53
|
+
|
54
|
+
# create an IP-range
|
55
|
+
def initialize(args)
|
56
|
+
@log = @@log
|
57
|
+
if args && args.length >= 2
|
58
|
+
|
59
|
+
#first IP
|
60
|
+
@first = ip_to_number args[0]
|
61
|
+
#last IP
|
62
|
+
@last = ip_to_number args[1]
|
63
|
+
if @last && @first && ( @last < @first )
|
64
|
+
@log.error('ERROR! Last IP is smaller than first. Aborting!')
|
65
|
+
exit false
|
66
|
+
end
|
67
|
+
@vrange = args[0,2]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
attr_reader :vrange, :first, :last
|
72
|
+
end
|
73
|
+
######### TEST #############
|
74
|
+
if __FILE__ == $0
|
75
|
+
rg = IPRange.new(['192.168.2.33', '192.168.255.150'])
|
76
|
+
puts rg.first
|
77
|
+
puts rg.last
|
78
|
+
puts rg.in_range? '192.168.1.35'
|
79
|
+
puts rg.in_range? '192.168.2.35'
|
80
|
+
|
81
|
+
puts rg.vrange.join(' - ')
|
82
|
+
puts rg.irange.join(' - ')
|
83
|
+
end
|
84
|
+
|
data/lib/log.conf
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2013 - 2019 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
|
22
|
+
A simplified logger configuration. Set the level for each individual logger
|
23
|
+
below. Choose a different log-device or log-file if you like. Keep the
|
24
|
+
formatting intact. Do not change other sections of this file.
|
25
|
+
=end
|
26
|
+
|
27
|
+
# Do not touch from here ----->
|
28
|
+
require 'logger'
|
29
|
+
|
30
|
+
debug = Logger::DEBUG
|
31
|
+
info = Logger::INFO
|
32
|
+
error = Logger::ERROR
|
33
|
+
fatal = Logger::FATAL
|
34
|
+
warn = Logger::WARN
|
35
|
+
unknown = Logger::UNKNOWN
|
36
|
+
{
|
37
|
+
# <---------------- to here !
|
38
|
+
|
39
|
+
# Enter your settings here, but take into consideration that not all
|
40
|
+
# the named classes will really produce readable output. Well, you can
|
41
|
+
# always try... Either name just the log-level or make the log-level
|
42
|
+
# precede the output-device or output-file like in the examples.
|
43
|
+
|
44
|
+
# Example: naming a log-file
|
45
|
+
#
|
46
|
+
# :HtmlBuilder => [info, 'C:\temp\htmlbuilder.log'],
|
47
|
+
#
|
48
|
+
# :HtmlBuilder => [debug, '/tmp/htmlbuilder.log'],
|
49
|
+
|
50
|
+
:FMail => info,
|
51
|
+
:IPRange => info,
|
52
|
+
:TopLevel => debug,
|
53
|
+
|
54
|
+
# And ignore the remainder, too.
|
55
|
+
}
|
56
|
+
#eof
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#encoding: UTF-8
|
2
|
+
=begin
|
3
|
+
/***************************************************************************
|
4
|
+
* ©2011-2019 Michael Uplawski <michael.uplawski@uplawski.eu> *
|
5
|
+
* *
|
6
|
+
* This program is free software; you can redistribute it and/or modify *
|
7
|
+
* it under the terms of the GNU General Public License as published by *
|
8
|
+
* the Free Software Foundation; either version 3 of the License, or *
|
9
|
+
* (at your option) any later version. *
|
10
|
+
* *
|
11
|
+
* This program is distributed in the hope that it will be useful, *
|
12
|
+
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
13
|
+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
14
|
+
* GNU General Public License for more details. *
|
15
|
+
* *
|
16
|
+
* You should have received a copy of the GNU General Public License *
|
17
|
+
* along with this program; if not, write to the *
|
18
|
+
* Free Software Foundation, Inc., *
|
19
|
+
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
|
20
|
+
***************************************************************************/
|
21
|
+
=end
|
22
|
+
require 'logger'
|
23
|
+
|
24
|
+
=begin Creates a member @log and precede its output with the name of the class
|
25
|
+
of the object.
|
26
|
+
Example for a class-level logger:
|
27
|
+
# --------------------
|
28
|
+
class TClass
|
29
|
+
self.extend(Logging)
|
30
|
+
@@log = init_logger(STDOUT)
|
31
|
+
def test_log
|
32
|
+
@@log.info('class-level logger called from instance: ' << @@log.to_s)
|
33
|
+
@log = @@log
|
34
|
+
@log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
|
35
|
+
end
|
36
|
+
def self::test_log
|
37
|
+
@log.info('class-level logger called from class: ' << @log.to_s)
|
38
|
+
@@log.info('AGAIN: class-level logger called from class: ' << @@log.to_s)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
#---------------------
|
42
|
+
Example for a object-level logger:
|
43
|
+
ATTN! This means 1 logger per object.
|
44
|
+
# --------------------
|
45
|
+
class TClass
|
46
|
+
include Logging
|
47
|
+
def initialize
|
48
|
+
init_logger(STDOUT, Logger::DEBUG)
|
49
|
+
end
|
50
|
+
def test_log
|
51
|
+
@log.debug('called test_log() ')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
=end
|
55
|
+
module Logging
|
56
|
+
|
57
|
+
@@have_log = false
|
58
|
+
@@LOG_CONF = File.dirname(File.absolute_path(__FILE__)) << File::Separator << 'log.conf'
|
59
|
+
|
60
|
+
# Call this method in an instance-method (e.g. initialize() ) to define the
|
61
|
+
# object-level logger; i.e. an object-specific member @log.
|
62
|
+
# Call this method within the class-definition for a class-level logger; i.e.
|
63
|
+
# a member @log for class-level acces.
|
64
|
+
# The method returns the logger, so you can actually do what you want with it.
|
65
|
+
def init_logger(target = STDOUT, level = Logger::INFO)
|
66
|
+
# Prepare for a class-level logger. This is actually quite cool.
|
67
|
+
|
68
|
+
# ---> Ingeniuous code starts here
|
69
|
+
cn = (self.class == Class ? name : self.class.name)
|
70
|
+
# <--- Ingeniuous code ends here
|
71
|
+
|
72
|
+
# 11/2019
|
73
|
+
if (cn == 'Object')
|
74
|
+
cn = 'Top Level'
|
75
|
+
end
|
76
|
+
|
77
|
+
# allow to override the set log-levels with an
|
78
|
+
# external configuration (log.conf).
|
79
|
+
log_conf(cn)
|
80
|
+
# Or use the defaults as set here or elsewhere...
|
81
|
+
|
82
|
+
@level ||= level
|
83
|
+
@target ||= target
|
84
|
+
|
85
|
+
@log = Logger.new(@target)
|
86
|
+
@log.level = @level
|
87
|
+
|
88
|
+
@log.formatter = proc do |severity, datetime, progname, msg|
|
89
|
+
t = Time.now
|
90
|
+
"#{cn}: #{severity} #{t.hour}-#{t.min}-#{t.sec}: #{msg}\n"
|
91
|
+
end
|
92
|
+
if ! @@have_log
|
93
|
+
@log.debug cn.dup << ' reading logging-configuration from ' << @@LOG_CONF
|
94
|
+
@@have_log = true
|
95
|
+
@log.debug('level is ' << level.to_s)
|
96
|
+
end
|
97
|
+
return @log
|
98
|
+
end
|
99
|
+
|
100
|
+
# Set the log-target to an IO object.
|
101
|
+
def log_target=(target)
|
102
|
+
@target = target
|
103
|
+
@log = Logger.new(@@target)
|
104
|
+
@log.level = @level
|
105
|
+
end
|
106
|
+
|
107
|
+
# set the log-level
|
108
|
+
def log_level=(level)
|
109
|
+
@level = level
|
110
|
+
@log.level = @level
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
# Override or set the log-level and target-device, as set in a file 'log.conf'.
|
116
|
+
# I do not like the look of this, but it works just the way I want it to.
|
117
|
+
# "HEAVANS! Isn't there a standard way to do this in Ruby, for Christ's sake?", you say.
|
118
|
+
# Heck, I don't care. <= Read that again, I say.
|
119
|
+
def log_conf(cn = nil)
|
120
|
+
config = level = target = nil
|
121
|
+
# puts 'log-config is in ' << @@LOG_CONF
|
122
|
+
if(File::exist?(@@LOG_CONF) )
|
123
|
+
begin
|
124
|
+
conf = File.read(@@LOG_CONF)
|
125
|
+
config = instance_eval(conf)
|
126
|
+
rescue Exception => ex
|
127
|
+
STDERR.puts "WARNING! Cannot evaluate the logger-configuration!" << ' ' << ex.message
|
128
|
+
STDERR.puts "Default log-levels apply."
|
129
|
+
end
|
130
|
+
else
|
131
|
+
puts "Default log-levels apply."
|
132
|
+
end
|
133
|
+
|
134
|
+
if(config && config.respond_to?(:to_hash) )
|
135
|
+
config.default = nil
|
136
|
+
if cn
|
137
|
+
config = config[cn.to_sym]
|
138
|
+
else
|
139
|
+
config = config[self.class.name.to_sym]
|
140
|
+
end
|
141
|
+
|
142
|
+
if(config )
|
143
|
+
if(config.respond_to?(:to_ary) && config.size == 2)
|
144
|
+
@level, @target = config
|
145
|
+
@target.downcase!
|
146
|
+
logdir = File.dirname(@target)
|
147
|
+
[:exist?, :directory?, :writable?].each do |m|
|
148
|
+
msg = File.send(m, logdir)
|
149
|
+
if(msg)
|
150
|
+
STDERR.puts "WARNING! A logfile for '%s' cannot be written to %s (%s)!" %[self.class.name, logdir, msg]
|
151
|
+
@target = nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
else
|
155
|
+
@level = config
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
######### test
|
163
|
+
if __FILE__ == $0
|
164
|
+
class TClass
|
165
|
+
# class level ---->
|
166
|
+
self.extend(Logging)
|
167
|
+
@@log = init_logger(STDOUT, Logger::INFO)
|
168
|
+
# <------
|
169
|
+
# object-level ---->
|
170
|
+
include Logging
|
171
|
+
# <---------
|
172
|
+
|
173
|
+
def test_log
|
174
|
+
@@log.info('class-level logger called from instance: ' << @@log.to_s)
|
175
|
+
#@log = @@log # works too
|
176
|
+
@log = TClass.class_eval{@log}
|
177
|
+
@log.info('AGAIN: class-level logger called from instance: ' << @log.to_s)
|
178
|
+
@log.debug("you won't see this on log-level INFO")
|
179
|
+
|
180
|
+
# object-level ---->
|
181
|
+
init_logger
|
182
|
+
# <-----------
|
183
|
+
@log.info("That's a different thing: " << @log.to_s << " - object-level logger!")
|
184
|
+
|
185
|
+
end
|
186
|
+
def self::test_log
|
187
|
+
@log.info('class-level logger called from class: ' << @log.to_s)
|
188
|
+
@@log.info('AGAIN: class-level logger called from class: ' << @log.to_s)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
TClass.new.test_log # class-logger + 1st object-logger
|
193
|
+
TClass.new.test_log # same class-logger + 2nd object-logger
|
194
|
+
|
195
|
+
TClass::test_log # same class-logger
|
196
|
+
puts 'And just say it once clearly: THIS IS COOOL!!'
|
197
|
+
end
|
198
|
+
#EOF
|
data/lib/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ip_in_range
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.6'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Michael Uplawski@uplawski.eu
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-03-12 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Verify that an IP is in a range
|
14
|
+
email: michael.uplawski@uplawski.eu
|
15
|
+
executables:
|
16
|
+
- ip_in_range
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- bin/ip_in_range
|
21
|
+
- ip_in_range.gemspec
|
22
|
+
- lib/email.rb
|
23
|
+
- lib/file_checking.rb
|
24
|
+
- lib/ip_range.rb
|
25
|
+
- lib/log.conf
|
26
|
+
- lib/logging.rb
|
27
|
+
- lib/version.rb
|
28
|
+
homepage: ''
|
29
|
+
licenses:
|
30
|
+
- GPL-3.0
|
31
|
+
metadata: {}
|
32
|
+
post_install_message:
|
33
|
+
rdoc_options: []
|
34
|
+
require_paths:
|
35
|
+
- lib
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.7'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
requirements: []
|
47
|
+
rubygems_version: 3.3.5
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Handle exception raised by the mail-gem
|
51
|
+
test_files: []
|