syslog_protocol_ms 0.10.0

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bc4ccbeae3cd27b9c5fc849591ee09539eddb5343d0167a1f8fcaa9c0cd00590
4
+ data.tar.gz: 6b4f69ae47118e633c65a0aee4a512b941d960668ba092fb1a9203ba093d67ae
5
+ SHA512:
6
+ metadata.gz: 0bccdc5bd76ef0149c4769368370411dbf640b4b178faedaec0b93f0b8ca986710ff1cfae7a24ba25d5119f30d0ee6a3365c772d555c12dd09c79892c7ff3609
7
+ data.tar.gz: 12e4965df86733106d02d0e7ae4c656c2cb5d920c2c0d5ce8beaec555a8c0b305f39e0a0e1e9c22190bdc5936a78f4563241637a7a18fad982b2425015f06824
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # Syslog protocol
2
+
3
+ roughly conforms to the murky shade of grey known as http://www.faqs.org/rfcs/rfc3164.html
4
+
5
+ ## Examples
6
+
7
+ ### Manipulate packets manually
8
+
9
+ require 'syslog_protocol_ms'
10
+
11
+ p = SyslogProtocol::Packet.new
12
+ p.hostname = "space_station"
13
+ p.facility = "kern"
14
+ p.severity = "warn"
15
+ p.tag = "test"
16
+ p.content = "flight control broken"
17
+ p.to_s
18
+ # => "<4>Aug 1 14:01:17 space_station flight control broken"
19
+ p.pri
20
+ # => 4
21
+ p.facility
22
+ # => 0
23
+ p.facility_name
24
+ # => "kern"
25
+ p.severity_name
26
+ # => "warn"
27
+ p.warn?
28
+ # => true
29
+ p.info?
30
+ # => false
31
+
32
+
33
+ ### Use a Logger to generate packets
34
+
35
+ require 'syslog_protocol_ms'
36
+
37
+ logger = SyslogProtocol::Logger.new("space_station", "uucp")
38
+ logger.debug("looking for uucp on board the space station")
39
+ # => "<67>Aug 1 14:02:29 space_station looking for uucp on board the space station"
40
+ logger.emerg("omg we cant find uucp on the space station")
41
+ # => "<64>Aug 1 14:03:56 space_station omg we cant find uucp on the space station"
42
+
43
+
44
+ ### Parse packets
45
+
46
+ require 'syslog_protocol_ms'
47
+
48
+ p = SyslogProtocol.parse("<34>Oct 11 22:14:15 space_station space is really getting to me")
49
+ p.facility
50
+ # => 4
51
+ p.severity_name
52
+ # => "crit"
53
+ p.time
54
+ # => Sun Oct 11 22:14:15 -0700 2009
55
+ p.content
56
+ # => "space is really getting to me"
57
+
58
+
59
+ ### It yells at you for trying to abuse the protocol
60
+
61
+ p = SyslogProtocol::Packet.new
62
+ p.facility = 34534534
63
+ # => ArgumentError: Facility must be within 0-23
64
+ p.hostname = "my host"
65
+ # => ArgumentError: Hostname may not contain spaces
66
+ p.hostname = "h\000stname"
67
+ # => ArgumentError: Hostname may only contain ASCII characters 33-126
68
+ # ...etc.
69
+ # It will also unintelligently truncate messages > 1024 bytes so beware.
70
+
71
+
72
+ ## Caveats
73
+
74
+ Syslog is a terrible and loosely defined protocol. Many devices and programs do not
75
+ conform to it and so their packets may not be parsed correctly by this interpretation,
76
+ nor may the packets generated by this necessarily be recognized by other devices or programs ;)
77
+
78
+ This is probably wrong and buggy, and i know the code is ugly, thanks.
79
+
80
+ Good luck.
81
+
82
+ ## TODO
83
+
84
+ * Update to more closely map to the ruby `syslog` API where possible
85
+
86
+ The MIT License (MIT)
87
+
88
+ Copyright (c) 2013 Jake Douglas and Eric Lindvall
89
+
90
+ Permission is hereby granted, free of charge, to any person obtaining a copy
91
+ of this software and associated documentation files (the "Software"), to deal
92
+ in the Software without restriction, including without limitation the rights
93
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
94
+ copies of the Software, and to permit persons to whom the Software is
95
+ furnished to do so, subject to the following conditions:
96
+
97
+ The above copyright notice and this permission notice shall be included in
98
+ all copies or substantial portions of the Software.
99
+
100
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
101
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
102
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
103
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
104
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
105
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
106
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,150 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'date'
4
+
5
+ #############################################################################
6
+ #
7
+ # Helper functions
8
+ #
9
+ #############################################################################
10
+
11
+ def name
12
+ @name ||= Dir['*.gemspec'].first.split('.').first
13
+ end
14
+
15
+ def version
16
+ line = File.read("lib/#{name}.rb")[/^\s*VERSION\s*=\s*.*/]
17
+ line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
18
+ end
19
+
20
+ def date
21
+ Date.today.to_s
22
+ end
23
+
24
+ def rubyforge_project
25
+ name
26
+ end
27
+
28
+ def gemspec_file
29
+ "#{name}.gemspec"
30
+ end
31
+
32
+ def gem_file
33
+ "#{name}-#{version}.gem"
34
+ end
35
+
36
+ def replace_header(head, header_name)
37
+ head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
38
+ end
39
+
40
+ #############################################################################
41
+ #
42
+ # Standard tasks
43
+ #
44
+ #############################################################################
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/testtask'
49
+ Rake::TestTask.new(:test) do |test|
50
+ test.libs << 'lib' << 'test'
51
+ test.pattern = 'test/**/test_*.rb'
52
+ test.verbose = true
53
+ end
54
+
55
+ desc "Generate RCov test coverage and open in your browser"
56
+ task :coverage do
57
+ require 'rcov'
58
+ sh "rm -fr coverage"
59
+ sh "rcov test/test_*.rb"
60
+ sh "open coverage/index.html"
61
+ end
62
+
63
+ require 'rdoc/task'
64
+ Rake::RDocTask.new do |rdoc|
65
+ rdoc.rdoc_dir = 'rdoc'
66
+ rdoc.title = "#{name} #{version}"
67
+ rdoc.rdoc_files.include('README*')
68
+ rdoc.rdoc_files.include('lib/**/*.rb')
69
+ end
70
+
71
+ desc "Open an irb session preloaded with this library"
72
+ task :console do
73
+ sh "irb -rubygems -r ./lib/#{name}.rb"
74
+ end
75
+
76
+ #############################################################################
77
+ #
78
+ # Custom tasks (add your own tasks here)
79
+ #
80
+ #############################################################################
81
+
82
+
83
+
84
+ #############################################################################
85
+ #
86
+ # Packaging tasks
87
+ #
88
+ #############################################################################
89
+
90
+ desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
91
+ task :release => :build do
92
+ unless `git branch` =~ /^\* master$/
93
+ puts "You must be on the master branch to release!"
94
+ exit!
95
+ end
96
+ sh "git commit --allow-empty -a -m 'Release #{version}'"
97
+ sh "git tag v#{version}"
98
+ sh "git push origin master"
99
+ sh "git push origin v#{version}"
100
+ sh "gem push pkg/#{name}-#{version}.gem"
101
+ end
102
+
103
+ desc "Build #{gem_file} into the pkg directory"
104
+ task :build => :gemspec do
105
+ sh "mkdir -p pkg"
106
+ sh "gem build #{gemspec_file}"
107
+ sh "mv #{gem_file} pkg"
108
+ end
109
+
110
+ desc "Generate #{gemspec_file}"
111
+ task :gemspec => :validate do
112
+ # read spec file and split out manifest section
113
+ spec = File.read(gemspec_file)
114
+ head, manifest, tail = spec.split(" # = MANIFEST =\n")
115
+
116
+ # replace name version and date
117
+ replace_header(head, :name)
118
+ replace_header(head, :version)
119
+ replace_header(head, :date)
120
+ #comment this out if your rubyforge_project has a different name
121
+ replace_header(head, :rubyforge_project)
122
+
123
+ # determine file list from git ls-files
124
+ files = `git ls-files`.
125
+ split("\n").
126
+ sort.
127
+ reject { |file| file =~ /^\./ }.
128
+ reject { |file| file =~ /^(rdoc|pkg)/ }.
129
+ map { |file| " #{file}" }.
130
+ join("\n")
131
+
132
+ # piece file back together and write
133
+ manifest = " s.files = %w[\n#{files}\n ]\n"
134
+ spec = [head, manifest, tail].join(" # = MANIFEST =\n")
135
+ File.open(gemspec_file, 'w') { |io| io.write(spec) }
136
+ puts "Updated #{gemspec_file}"
137
+ end
138
+
139
+ desc "Validate #{gemspec_file}"
140
+ task :validate do
141
+ libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
142
+ unless libfiles.empty?
143
+ puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
144
+ exit!
145
+ end
146
+ unless Dir['VERSION*'].empty?
147
+ puts "A `VERSION` file at root level violates Gem best practices."
148
+ exit!
149
+ end
150
+ end
@@ -0,0 +1,8 @@
1
+ require 'syslog_protocol_ms/common'
2
+ require 'syslog_protocol_ms/packet'
3
+ require 'syslog_protocol_ms/logger'
4
+ require 'syslog_protocol_ms/parser'
5
+
6
+ module SyslogProtocolMs
7
+ VERSION = '0.10.0'
8
+ end
@@ -0,0 +1,79 @@
1
+ module SyslogProtocolMs
2
+ # These hashes stolen from Syslog.pm
3
+
4
+ FACILITIES = {
5
+ 'kern' => 0,
6
+ 'user' => 1,
7
+ 'mail' => 2,
8
+ 'daemon' => 3,
9
+ 'auth' => 4,
10
+ 'syslog' => 5,
11
+ 'lpr' => 6,
12
+ 'news' => 7,
13
+ 'uucp' => 8,
14
+ 'cron' => 9,
15
+ 'authpriv' => 10,
16
+ 'ftp' => 11,
17
+ 'ntp' => 12,
18
+ 'audit' => 13,
19
+ 'alert' => 14,
20
+ 'at' => 15,
21
+ 'local0' => 16,
22
+ 'local1' => 17,
23
+ 'local2' => 18,
24
+ 'local3' => 19,
25
+ 'local4' => 20,
26
+ 'local5' => 21,
27
+ 'local6' => 22,
28
+ 'local7' => 23
29
+ }
30
+
31
+ FACILITY_INDEX = {
32
+ 0 => 'kern',
33
+ 1 => 'user',
34
+ 2 => 'mail',
35
+ 3 => 'daemon',
36
+ 4 => 'auth',
37
+ 5 => 'syslog',
38
+ 6 => 'lpr',
39
+ 7 => 'news',
40
+ 8 => 'uucp',
41
+ 9 => 'cron',
42
+ 10 => 'authpriv',
43
+ 11 => 'ftp',
44
+ 12 => 'ntp',
45
+ 13 => 'audit',
46
+ 14 => 'alert',
47
+ 15 => 'at',
48
+ 16 => 'local0',
49
+ 17 => 'local1',
50
+ 18 => 'local2',
51
+ 19 => 'local3',
52
+ 20 => 'local4',
53
+ 21 => 'local5',
54
+ 22 => 'local6',
55
+ 23 => 'local7'
56
+ }
57
+
58
+ SEVERITIES = {
59
+ 'emerg' => 0,
60
+ 'alert' => 1,
61
+ 'crit' => 2,
62
+ 'err' => 3,
63
+ 'warn' => 4,
64
+ 'notice' => 5,
65
+ 'info' => 6,
66
+ 'debug' => 7
67
+ }
68
+
69
+ SEVERITY_INDEX = {
70
+ 0 => 'emerg',
71
+ 1 => 'alert',
72
+ 2 => 'crit',
73
+ 3 => 'err',
74
+ 4 => 'warn',
75
+ 5 => 'notice',
76
+ 6 => 'info',
77
+ 7 => 'debug'
78
+ }
79
+ end
@@ -0,0 +1,21 @@
1
+ module SyslogProtocolMs
2
+ class Logger
3
+ def initialize(hostname, tag, facility)
4
+ @packet = Packet.new
5
+ @packet.hostname = hostname
6
+ @packet.tag = tag
7
+ @packet.facility = facility
8
+ end
9
+
10
+ SEVERITIES.each do |k,v|
11
+ define_method(k) do |content|
12
+ raise ArgumentError.new("Message may not be omitted") unless content and content.length > 0
13
+
14
+ p = @packet.dup
15
+ p.severity = k
16
+ p.content = content
17
+ p.assemble
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,135 @@
1
+ module SyslogProtocolMs
2
+ class Packet
3
+ attr_reader :facility, :severity, :hostname, :tag
4
+ attr_accessor :time, :content
5
+
6
+ def to_s
7
+ assemble
8
+ end
9
+
10
+ def assemble(max_size = 1024)
11
+ unless @hostname and @facility and @severity and @tag
12
+ raise "Could not assemble packet without hostname, tag, facility, and severity"
13
+ end
14
+ data = "<#{pri}>#{generate_timestamp} #{@hostname} #{@tag}: #{@content}"
15
+
16
+ if string_bytesize(data) > max_size
17
+ data = data.slice(0, max_size)
18
+ while string_bytesize(data) > max_size
19
+ data = data.slice(0, data.length - 1)
20
+ end
21
+ end
22
+
23
+ data
24
+ end
25
+
26
+ def facility=(f)
27
+ if f.is_a? Integer
28
+ if (0..23).include?(f)
29
+ @facility = f
30
+ else
31
+ raise ArgumentError.new "Facility must be within 0-23"
32
+ end
33
+ elsif f.is_a? String
34
+ if facility = FACILITIES[f]
35
+ @facility = facility
36
+ else
37
+ raise ArgumentError.new "'#{f}' is not a designated facility"
38
+ end
39
+ else
40
+ raise ArgumentError.new "Facility must be a designated number or string"
41
+ end
42
+ end
43
+
44
+ def tag=(t)
45
+ unless t && t.is_a?(String) && t.length > 0
46
+ raise ArgumentError, "Tag must not be omitted"
47
+ end
48
+ if t.length > 32
49
+ raise ArgumentError, "Tag must not be longer than 32 characters"
50
+ end
51
+ if t =~ /\s/
52
+ raise ArgumentError, "Tag may not contain spaces"
53
+ end
54
+ if t =~ /[^\x21-\x7E]/
55
+ raise ArgumentError, "Tag may only contain ASCII characters 33-126"
56
+ end
57
+
58
+ @tag = t
59
+ end
60
+
61
+ def severity=(s)
62
+ if s.is_a? Integer
63
+ if (0..7).include?(s)
64
+ @severity = s
65
+ else
66
+ raise ArgumentError.new "Severity must be within 0-7"
67
+ end
68
+ elsif s.is_a? String
69
+ if severity = SEVERITIES[s]
70
+ @severity = severity
71
+ else
72
+ raise ArgumentError.new "'#{s}' is not a designated severity"
73
+ end
74
+ else
75
+ raise ArgumentError.new "Severity must be a designated number or string"
76
+ end
77
+ end
78
+
79
+ def hostname=(h)
80
+ unless h and h.is_a? String and h.length > 0
81
+ raise ArgumentError.new("Hostname may not be omitted")
82
+ end
83
+ if h =~ /\s/
84
+ raise ArgumentError.new("Hostname may not contain spaces")
85
+ end
86
+ if h =~ /[^\x21-\x7E]/
87
+ raise ArgumentError.new("Hostname may only contain ASCII characters 33-126")
88
+ end
89
+ @hostname = h
90
+ end
91
+
92
+ def facility_name
93
+ FACILITY_INDEX[@facility]
94
+ end
95
+
96
+ def severity_name
97
+ SEVERITY_INDEX[@severity]
98
+ end
99
+
100
+ def pri
101
+ (@facility * 8) + @severity
102
+ end
103
+
104
+ def pri=(p)
105
+ unless p.is_a? Integer and (0..191).include?(p)
106
+ raise ArgumentError.new "PRI must be a number between 0 and 191"
107
+ end
108
+ @facility = p / 8
109
+ @severity = p - (@facility * 8)
110
+ end
111
+
112
+ def generate_timestamp
113
+ time = @time || Time.now
114
+ # The timestamp format requires that a day with fewer than 2 digits have
115
+ # what would normally be a preceding zero, be instead an extra space.
116
+ day = time.strftime("%d")
117
+ day = day.sub(/^0/, ' ') if day =~ /^0\d/
118
+ time.strftime("%b #{day} %H:%M:%S.%3N")
119
+ end
120
+
121
+ if "".respond_to?(:bytesize)
122
+ def string_bytesize(string)
123
+ string.bytesize
124
+ end
125
+ else
126
+ def string_bytesize(string)
127
+ string.length
128
+ end
129
+ end
130
+
131
+ SEVERITIES.each do |k,v|
132
+ define_method("#{k}?") { SEVERITIES[k] == @severity }
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,57 @@
1
+ require 'time'
2
+
3
+ module SyslogProtocolMs
4
+
5
+ def self.parse(msg, origin=nil)
6
+ packet = Packet.new
7
+ original_msg = msg.dup
8
+ pri = parse_pri(msg)
9
+ if pri and (pri = pri.to_i).is_a? Integer and (0..191).include?(pri)
10
+ packet.pri = pri
11
+ else
12
+ # If there isn't a valid PRI, treat the entire message as content
13
+ packet.pri = 13
14
+ packet.time = Time.now
15
+ packet.hostname = origin || 'unknown'
16
+ packet.content = original_msg
17
+ return packet
18
+ end
19
+ time = parse_time(msg)
20
+ if time
21
+ packet.time = Time.parse(time)
22
+ else
23
+ packet.time = Time.now
24
+ end
25
+ hostname = parse_hostname(msg)
26
+ packet.hostname = hostname || origin
27
+ if m = msg.match(/^(\w+)(: | )(.*)$/)
28
+ packet.tag = m[1]
29
+ packet.content = m[3]
30
+ else
31
+ packet.tag = 'unknown'
32
+ packet.content = msg
33
+ end
34
+ packet
35
+ end
36
+
37
+ private
38
+
39
+ def self.parse_pri(msg)
40
+ pri = msg.slice!(/<(\d\d?\d?)>/)
41
+ pri = pri.slice(/\d\d?\d?/) if pri
42
+ if !pri or (pri =~ /^0/ and pri !~ /^0$/)
43
+ return nil
44
+ else
45
+ return pri
46
+ end
47
+ end
48
+
49
+ def self.parse_time(msg)
50
+ msg.slice!(/(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\s|[1-9])\d\s\d\d:\d\d:\d\d\s/)
51
+ end
52
+
53
+ def self.parse_hostname(msg)
54
+ msg.slice!(/^[\x21-\x7E]+\s/).rstrip
55
+ end
56
+
57
+ end
@@ -0,0 +1,81 @@
1
+ ## This is the rakegem gemspec template. Make sure you read and understand
2
+ ## all of the comments. Some sections require modification, and others can
3
+ ## be deleted if you don't need them. Once you understand the contents of
4
+ ## this file, feel free to delete any comments that begin with two hash marks.
5
+ ## You can find comprehensive Gem::Specification documentation, at
6
+ ## http://docs.rubygems.org/read/chapter/20
7
+ Gem::Specification.new do |s|
8
+ s.specification_version = 2 if s.respond_to? :specification_version=
9
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
10
+ s.rubygems_version = '1.3.5'
11
+
12
+ ## Leave these as is they will be modified for you by the rake gemspec task.
13
+ ## If your rubyforge_project name is different, then edit it and comment out
14
+ ## the sub! line in the Rakefile
15
+ s.name = 'syslog_protocol_ms'
16
+ s.version = '0.10.0'
17
+ s.date = "2021-08-03"
18
+ # s.rubyforge_project = 'syslog_protocol_ms'
19
+
20
+ ## Make sure your summary is short. The description may be as long
21
+ ## as you like.
22
+ s.summary = "Syslog protocol parser and generator"
23
+ s.description = "Syslog protocol parser and generator"
24
+
25
+ ## List the primary authors. If there are a bunch of authors, it's probably
26
+ ## better to set the email to an email list or something. If you don't have
27
+ ## a custom homepage, consider using your GitHub URL or the like.
28
+ s.authors = ["Jake Douglas", 'Eric Lindvall', 'Torben Carstens']
29
+ s.email = [ "jakecdouglas@gmail.com", 'eric@5stops.com', 'rubygems@carstens.tech' ]
30
+ s.homepage = 'https://github.com/torbencarstens/syslog_protocol_ms'
31
+
32
+ ## This gets added to the $LOAD_PATH so that 'lib/NAME.rb' can be required as
33
+ ## require 'NAME.rb' or'/lib/NAME/file.rb' can be as require 'NAME/file.rb'
34
+ s.require_paths = %w[lib]
35
+
36
+ ## This sections is only necessary if you have C extensions.
37
+ # s.require_paths << 'ext'
38
+ # s.extensions = %w[ext/extconf.rb]
39
+
40
+ ## If your gem includes any executables, list them here.
41
+ # s.executables = ["name"]
42
+ # s.default_executable = 'name'
43
+
44
+ ## Specify any RDoc options here. You'll want to add your README and
45
+ ## LICENSE files to the extra_rdoc_files list.
46
+ s.rdoc_options = ["--charset=UTF-8"]
47
+ s.extra_rdoc_files = %w[README.md]
48
+
49
+ ## List your runtime dependencies here. Runtime dependencies are those
50
+ ## that are needed for an end user to actually USE your code.
51
+ # s.add_dependency('DEPNAME', [">= 1.1.0", "< 2.0.0"])
52
+
53
+ ## List your development dependencies here. Development dependencies are
54
+ ## those that are only needed during development
55
+ s.add_development_dependency('bacon', [ '~> 1.1.0' ])
56
+
57
+ ## Leave this section as-is. It will be automatically generated from the
58
+ ## contents of your Git repository via the gemspec task. DO NOT REMOVE
59
+ ## THE MANIFEST COMMENTS, they are used as delimiters by the task.
60
+ # = MANIFEST =
61
+ s.files = %w[
62
+ Gemfile
63
+ README.md
64
+ Rakefile
65
+ lib/syslog_protocol_ms.rb
66
+ lib/syslog_protocol_ms/common.rb
67
+ lib/syslog_protocol_ms/logger.rb
68
+ lib/syslog_protocol_ms/packet.rb
69
+ lib/syslog_protocol_ms/parser.rb
70
+ syslog_protocol_ms.gemspec
71
+ test/helper.rb
72
+ test/test_logger.rb
73
+ test/test_packet.rb
74
+ test/test_parser.rb
75
+ ]
76
+ # = MANIFEST =
77
+
78
+ ## Test files will be grabbed from the file list. Make sure the path glob
79
+ ## matches what you actually use.
80
+ s.test_files = s.files.select { |path| path =~ /^test\/test_.*\.rb/ }
81
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,13 @@
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ unless ENV['BUNDLE_GEMFILE']
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ Bundler.setup
7
+ Bundler.require
8
+ end
9
+
10
+ require 'bacon'
11
+ Bacon.summary_at_exit
12
+
13
+ require 'syslog_protocol_ms'
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ describe "syslog logger" do
4
+
5
+ it "create a new logger with hostname and facility" do
6
+ lambda {@logger = SyslogProtocolMs::Logger.new("space_station", 'test', "local0")}.should.not.raise
7
+ end
8
+
9
+ it "hostname and facility must conform to the requirements of a Packet" do
10
+ lambda {SyslogProtocolMs::Logger.new("space station", "some shit", 'test test')}.should.raise ArgumentError
11
+ end
12
+
13
+ it "generates packets" do
14
+ # We have to set a time so we have a consistant timestamp to check against..
15
+ p = @logger.instance_variable_get("@packet")
16
+ p.time = Time.now
17
+ ts = p.generate_timestamp
18
+ @logger.debug("vacuum tubez are operational").should.equal "<135>#{ts} space_station test: vacuum tubez are operational"
19
+ @logger.info("firing thrusters at 13 degrees").should.equal "<134>#{ts} space_station test: firing thrusters at 13 degrees"
20
+ @logger.notice("the hyper drive has been activated").should.equal "<133>#{ts} space_station test: the hyper drive has been activated"
21
+ @logger.warn("meteorites incoming!").should.equal "<132>#{ts} space_station test: meteorites incoming!"
22
+ @logger.err("vacuum tube 3 in hyper drive failed").should.equal "<131>#{ts} space_station test: vacuum tube 3 in hyper drive failed"
23
+ @logger.crit("wing struck by a meteorite!").should.equal "<130>#{ts} space_station test: wing struck by a meteorite!"
24
+ @logger.alert("LEAKING ATMOSPHERE").should.equal "<129>#{ts} space_station test: LEAKING ATMOSPHERE"
25
+ @logger.emerg("LEAKING ASTRONAUTS WE ARE DONE").should.equal "<128>#{ts} space_station test: LEAKING ASTRONAUTS WE ARE DONE"
26
+ end
27
+
28
+ end
@@ -0,0 +1,96 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ describe "a syslog packet" do
4
+
5
+ @p = SyslogProtocolMs::Packet.new
6
+
7
+ it "should embarrass a person who does not set the fields" do
8
+ lambda { @p.to_s }.should.raise RuntimeError
9
+ end
10
+
11
+ it "hostname may not be omitted" do
12
+ lambda {@p.hostname = ""}.should.raise ArgumentError
13
+ end
14
+
15
+ it "hostname may only contain ASCII characters 33-126 (no spaces!)" do
16
+ lambda {@p.hostname = "linux box"}.should.raise ArgumentError
17
+ lambda {@p.hostname = "\000" + "linuxbox"}.should.raise ArgumentError
18
+ lambda {@p.hostname = "space_station"}.should.not.raise
19
+ end
20
+
21
+ it 'tag may only contain ASCII characters 33-126 (no spaces!)' do
22
+ lambda {@p.tag = "linux box"}.should.raise ArgumentError
23
+ lambda {@p.tag = "\000" + "linuxbox"}.should.raise ArgumentError
24
+ lambda {@p.tag = "test"}.should.not.raise
25
+ end
26
+
27
+ it "facility may only be set within 0-23 or with a proper string name" do
28
+ lambda {@p.facility = 666}.should.raise ArgumentError
29
+ lambda {@p.facility = "mir space station"}.should.raise ArgumentError
30
+
31
+ lambda {@p.facility = 16}.should.not.raise
32
+ @p.facility.should.equal 16
33
+ lambda {@p.facility = 'local0'}.should.not.raise
34
+ @p.facility.should.equal 16
35
+ end
36
+
37
+ it "severity may only be set within 0-7 or with a proper string name" do
38
+ lambda {@p.severity = 9876}.should.raise ArgumentError
39
+ lambda {@p.severity = "omgbroken"}.should.raise ArgumentError
40
+
41
+ lambda {@p.severity = 6}.should.not.raise
42
+ @p.severity.should.equal 6
43
+ lambda {@p.severity = 'info'}.should.not.raise
44
+ @p.severity.should.equal 6
45
+ end
46
+
47
+ it "severity can be checked using 'some_severity?' methods" do
48
+ @p.info?.should.equal true
49
+ @p.alert?.should.equal false
50
+ @p.emerg?.should.equal false
51
+ end
52
+
53
+ it "PRI is calculated from the facility and severity" do
54
+ @p.pri.should.equal 134
55
+ end
56
+
57
+ it "PRI may only be within 0-191" do
58
+ lambda {@p.pri = 22331}.should.raise ArgumentError
59
+ lambda {@p.pri = "foo"}.should.raise ArgumentError
60
+ end
61
+
62
+ it "facility and severity are deduced and set from setting a valid PRI" do
63
+ @p.pri = 165
64
+ @p.severity.should.equal 5
65
+ @p.facility.should.equal 20
66
+ end
67
+
68
+ it "return the proper names for facility and severity" do
69
+ @p.severity_name.should.equal 'notice'
70
+ @p.facility_name.should.equal 'local4'
71
+ end
72
+
73
+ it "set a message, which apparently can be anything" do
74
+ @p.content = "exploring ze black hole"
75
+ @p.content.should.equal "exploring ze black hole"
76
+ end
77
+
78
+ it "timestamp must conform to the retarded format (including ms)" do
79
+ @p.generate_timestamp.should.match /(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\s|[1-9])\d\s\d\d:\d\d:\d\d.\d\d\d/
80
+ end
81
+
82
+ it "use the current time and assemble the packet" do
83
+ timestamp = @p.generate_timestamp
84
+ @p.to_s.should.equal "<165>#{timestamp} space_station test: exploring ze black hole"
85
+ end
86
+
87
+ it "packets larger than 1024 will be truncated" do
88
+ @p.content = "space warp" * 1000
89
+ if "".respond_to?(:bytesize)
90
+ @p.to_s.bytesize.should.equal 1024
91
+ else
92
+ @p.to_s.size.should.equal 1024
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,51 @@
1
+ require File.expand_path('../helper', __FILE__)
2
+
3
+ describe "syslog packet parser" do
4
+
5
+ it "parse some valid packets" do
6
+ p = SyslogProtocolMs.parse("<34>Oct 11 22:14:15 mymachine su: 'su root' failed for lonvick on /dev/pts/8")
7
+ p.facility.should.equal 4
8
+ p.severity.should.equal 2
9
+ p.pri.should.equal 34
10
+ p.hostname.should.equal "mymachine"
11
+ p.tag.should.equal 'su'
12
+ p.content.should.equal "'su root' failed for lonvick on /dev/pts/8"
13
+ p.time.should.equal Time.parse("Oct 11 22:14:15")
14
+
15
+ p = SyslogProtocolMs.parse("<13>Feb 5 17:32:18 10.0.0.99 test: Use the BFG!")
16
+ p.facility.should.equal 1
17
+ p.severity.should.equal 5
18
+ p.pri.should.equal 13
19
+ p.hostname.should.equal "10.0.0.99"
20
+ p.tag.should.equal 'test'
21
+ p.content.should.equal "Use the BFG!"
22
+ p.time.should.equal Time.parse("Feb 5 17:32:18")
23
+ end
24
+
25
+ it "treat a packet with no valid PRI as all content, setting defaults" do
26
+ p = SyslogProtocolMs.parse("nomnom")
27
+ p.facility.should.equal 1
28
+ p.severity.should.equal 5
29
+ p.pri.should.equal 13
30
+ p.hostname.should.equal 'unknown'
31
+ p.content.should.equal "nomnom"
32
+ end
33
+
34
+ it "PRI with preceding 0's shall be considered invalid" do
35
+ p = SyslogProtocolMs.parse("<045>Oct 11 22:14:15 space_station my PRI is not valid")
36
+ p.facility.should.equal 1
37
+ p.severity.should.equal 5
38
+ p.pri.should.equal 13
39
+ p.hostname.should.equal 'unknown'
40
+ p.content.should.equal "<045>Oct 11 22:14:15 space_station my PRI is not valid"
41
+ end
42
+
43
+ it "allow the user to pass an origin to be used as the hostname if packet is invalid" do
44
+ p = SyslogProtocolMs.parse("<045>Oct 11 22:14:15 space_station my PRI is not valid", '127.0.0.1')
45
+ p.facility.should.equal 1
46
+ p.severity.should.equal 5
47
+ p.pri.should.equal 13
48
+ p.hostname.should.equal '127.0.0.1'
49
+ p.content.should.equal "<045>Oct 11 22:14:15 space_station my PRI is not valid"
50
+ end
51
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: syslog_protocol_ms
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.10.0
5
+ platform: ruby
6
+ authors:
7
+ - Jake Douglas
8
+ - Eric Lindvall
9
+ - Torben Carstens
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2021-08-03 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bacon
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.0
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: 1.1.0
29
+ description: Syslog protocol parser and generator
30
+ email:
31
+ - jakecdouglas@gmail.com
32
+ - eric@5stops.com
33
+ - rubygems@carstens.tech
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files:
37
+ - README.md
38
+ files:
39
+ - Gemfile
40
+ - README.md
41
+ - Rakefile
42
+ - lib/syslog_protocol_ms.rb
43
+ - lib/syslog_protocol_ms/common.rb
44
+ - lib/syslog_protocol_ms/logger.rb
45
+ - lib/syslog_protocol_ms/packet.rb
46
+ - lib/syslog_protocol_ms/parser.rb
47
+ - syslog_protocol_ms.gemspec
48
+ - test/helper.rb
49
+ - test/test_logger.rb
50
+ - test/test_packet.rb
51
+ - test/test_parser.rb
52
+ homepage: https://github.com/torbencarstens/syslog_protocol_ms
53
+ licenses: []
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options:
57
+ - "--charset=UTF-8"
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ required_rubygems_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ requirements: []
71
+ rubygems_version: 3.2.15
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Syslog protocol parser and generator
75
+ test_files:
76
+ - test/test_logger.rb
77
+ - test/test_packet.rb
78
+ - test/test_parser.rb