Auto 4.0.0.alpha.1-x86-mingw32

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 (65) hide show
  1. data/.yardopts +7 -0
  2. data/Gemfile +19 -0
  3. data/LICENSE.md +31 -0
  4. data/README.md +109 -0
  5. data/Rakefile +41 -0
  6. data/bin/auto +110 -0
  7. data/bin/auto-conf +45 -0
  8. data/conf/example.json +100 -0
  9. data/conf/example.yml +125 -0
  10. data/docs/Contributing.md +77 -0
  11. data/docs/Events.md +103 -0
  12. data/docs/Todo.md +21 -0
  13. data/docs/Upgrade.md +16 -0
  14. data/ext/dsl_base.c +49 -0
  15. data/ext/libauto/auto.h +20 -0
  16. data/ext/libauto/extconf.rb +16 -0
  17. data/ext/libauto/libauto.c +29 -0
  18. data/ext/libauto/libauto.h +28 -0
  19. data/ext/libauto/logger.c +177 -0
  20. data/ext/libauto/logger.h +44 -0
  21. data/lib/auto.rb +43 -0
  22. data/lib/auto/api.rb +7 -0
  23. data/lib/auto/api/events.rb +166 -0
  24. data/lib/auto/api/object.rb +29 -0
  25. data/lib/auto/api/plugin.rb +155 -0
  26. data/lib/auto/api/timers.rb +93 -0
  27. data/lib/auto/bot.rb +338 -0
  28. data/lib/auto/config.rb +181 -0
  29. data/lib/auto/configure.rb +410 -0
  30. data/lib/auto/configure/shell.rb +154 -0
  31. data/lib/auto/dsl/base.rb +74 -0
  32. data/lib/auto/dsl/irc.rb +13 -0
  33. data/lib/auto/irc.rb +8 -0
  34. data/lib/auto/irc/common.rb +63 -0
  35. data/lib/auto/irc/library.rb +89 -0
  36. data/lib/auto/irc/object/channel.rb +21 -0
  37. data/lib/auto/irc/object/entity.rb +90 -0
  38. data/lib/auto/irc/object/message.rb +99 -0
  39. data/lib/auto/irc/object/user.rb +139 -0
  40. data/lib/auto/irc/protocol.rb +164 -0
  41. data/lib/auto/irc/protocol/numerics.rb +60 -0
  42. data/lib/auto/irc/sasl/diffie_hellman.rb +36 -0
  43. data/lib/auto/irc/sasl/mech.rb +15 -0
  44. data/lib/auto/irc/sasl/mech/dh_blowfish.rb +83 -0
  45. data/lib/auto/irc/sasl/mech/plain.rb +39 -0
  46. data/lib/auto/irc/server.rb +301 -0
  47. data/lib/auto/irc/state/channel_manager.rb +6 -0
  48. data/lib/auto/irc/state/support.rb +142 -0
  49. data/lib/auto/irc/state/user_manager.rb +6 -0
  50. data/lib/auto/irc/std/commands.rb +99 -0
  51. data/lib/auto/irc/std/numerics.rb +216 -0
  52. data/lib/auto/rubyext/integer.rb +25 -0
  53. data/lib/auto/rubyext/string.rb +10 -0
  54. data/lib/auto/version.rb +18 -0
  55. data/lib/libauto.so +0 -0
  56. data/spec/api_events_spec.rb +68 -0
  57. data/spec/config_json_spec.rb +116 -0
  58. data/spec/config_other_spec.rb +29 -0
  59. data/spec/config_yaml_spec.rb +136 -0
  60. data/spec/helper.rb +19 -0
  61. data/spec/irc_object_entity_spec.rb +51 -0
  62. data/spec/logger_spec.rb +30 -0
  63. data/spec/plugin_base_spec.rb +35 -0
  64. data/spec/timers_spec.rb +42 -0
  65. metadata +238 -0
@@ -0,0 +1,36 @@
1
+ # This code exists in the public domain.
2
+
3
+ class DiffieHellman
4
+
5
+ attr_reader :p, :g, :q, :x, :e
6
+
7
+ # p is the prime, g the generator and q order of the subgroup
8
+ def initialize p, g, q
9
+ @p = p
10
+ @g = g
11
+ @q = q
12
+ end
13
+
14
+ # generate the [secret] random value and the public key
15
+ def generate tries=16
16
+ tries.times do
17
+ @x = rand(@q)
18
+ @e = self.g.mod_exp(@x, self.p)
19
+ return @e if self.valid?
20
+ end
21
+ raise ArgumentError, "can't generate valid e"
22
+ end
23
+
24
+ # validate a public key
25
+ def valid?(_e = self.e)
26
+ _e and _e.between?(2, self.p-2) and _e.bits_set > 1
27
+ end
28
+
29
+ # compute the shared secret, given the public key
30
+ def secret f
31
+ f.mod_exp(self.x, self.p)
32
+ end
33
+
34
+ end
35
+
36
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,15 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (LICENSE.md).
3
+
4
+ module Auto
5
+ module IRC
6
+ module SASL
7
+ module Mech
8
+ autoload :DHBlowfish, 'auto/irc/sasl/mech/dh_blowfish'
9
+ autoload :Plain, 'auto/irc/sasl/mech/plain'
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,83 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (LICENSE.md).
3
+
4
+ require 'base64'
5
+ require 'openssl'
6
+ require 'auto/rubyext/integer'
7
+ require 'auto/irc/sasl/diffie_hellman'
8
+
9
+ module Auto
10
+
11
+ module IRC
12
+
13
+ module SASL
14
+
15
+ module Mech
16
+
17
+ # Module which implements the SASL DH-BLOWFISH mechanism.
18
+ # @author noxgirl
19
+ module DHBlowfish
20
+
21
+ # Create an SASL-encrypted hash.
22
+ #
23
+ # @param [String] username The username.
24
+ # @param [String] password The password associated with the username.
25
+ # @param [String] provision The key provided by the server.
26
+ def self.encrypt username, password, provision
27
+ # This is a fairly complex process. Duplicate +username+ and
28
+ # +password+ for safety.
29
+ user = username.dup
30
+ pass = password.dup
31
+
32
+ # Decode the key from base64.
33
+ key = Base64.decode64(provision).force_encoding('ASCII-8BIT')
34
+
35
+ # Unpack it.
36
+ p, g, y = unpack_key key
37
+
38
+ dh = DiffieHellman.new(p, g, 23)
39
+ pkey = dh.generate
40
+ secret = OpenSSL::BN.new(dh.secret(y).to_s).to_s(2)
41
+ pub = OpenSSL::BN.new(pkey.to_s).to_s(2)
42
+
43
+ pass.concat "\0"
44
+ pass.concat('.' * (8 - (password.size % 8)))
45
+
46
+ cipher = OpenSSL::Cipher::Cipher.new 'BF-ECB'
47
+ cipher.key_len = 32
48
+ cipher.encrypt
49
+ cipher.key = secret
50
+
51
+ enc = cipher.update(pass).to_s
52
+ answer = [pub.bytesize, pub, user, enc].pack('na*Z*a*')
53
+
54
+ Base64.strict_encode64(answer) # finally, return the hash
55
+ end
56
+
57
+ # @return [Array(Numeric, Numeric, Numeric)] +p+, +g+, and +y+ for
58
+ # Diffie-Hellman key exchange
59
+ def self.unpack_key key
60
+ key = key.dup
61
+ pgy = []
62
+
63
+ 3.times do
64
+ size = key.unpack('n').first
65
+ key.slice! 0, 2
66
+ pgy << key.unpack("a#{size}").first
67
+ key.slice!(0, size)
68
+ end
69
+
70
+ pgy.map { |int| OpenSSL::BN.new(int, 2).to_i }
71
+ end
72
+
73
+ end # module DHBlowfish
74
+
75
+ end # module Mech
76
+
77
+ end # module SASL
78
+
79
+ end # module IRC
80
+
81
+ end # module Auto
82
+
83
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,39 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (LICENSE.md).
3
+
4
+ require 'base64'
5
+
6
+ module Auto
7
+
8
+ module IRC
9
+
10
+ module SASL
11
+
12
+ module Mech
13
+
14
+ # Module which implements the SASL PLAIN mechanism.
15
+ module Plain
16
+
17
+ # Create an SASL-encrypted hash.
18
+ #
19
+ # @author noxgirl
20
+ #
21
+ # @param [String] username The username.
22
+ # @param [String] password The password associated with the username.
23
+ # @param [String] provision The key provided by the server.
24
+ def self.encrypt username, password, provision
25
+ # Easy as this:
26
+ Base64.encode64([username, username, password].join("\0")).gsub(/\n/, '')
27
+ end
28
+
29
+ end # module Plain
30
+
31
+ end # module Mech
32
+
33
+ end # module SASL
34
+
35
+ end # module IRC
36
+
37
+ end # module Auto
38
+
39
+ # vim: set ts=4 sts=2 sw=2 et:
@@ -0,0 +1,301 @@
1
+ # Copyright (c) 2013, Autumn Perrault, et al. All rights reserved.
2
+ # This free software is distributed under the FreeBSD license (LICENSE.md).
3
+
4
+ require 'ostruct'
5
+ require 'socket'
6
+ require 'openssl'
7
+ require 'thread'
8
+ require 'auto/dsl/base'
9
+ require 'auto/irc/state/support'
10
+ require 'auto/irc/std/commands'
11
+
12
+ # namespace Auto
13
+ module Auto
14
+
15
+ # Entering namespace: IRC
16
+ module IRC
17
+
18
+ # A class which maintains a connection to an IRC server and provides a highly
19
+ # usable interface for the IRC server.
20
+ #
21
+ # @api IRC
22
+ # @since 4.0.0
23
+ # @author noxgirl
24
+ #
25
+ # @!attribute [r] socket
26
+ # @return [TCPSocket] The TCP socket being used for the connection.
27
+ #
28
+ # @!attribute [r] in
29
+ # @return [Integer] The number of bytes received from the socket.
30
+ #
31
+ # @!attribute [r] out
32
+ # @return [Integer] The number of bytes sent to the socket.
33
+ #
34
+ # @!attribute [r] type
35
+ # @return [Symbol] +:irc+
36
+ #
37
+ # @!attribute [r] supp
38
+ # @return [Auto::IRC::State::Support] The IRCd capabilities.
39
+ #
40
+ # @!attribute name
41
+ # @return [String] The name of the server as specified by configuration.
42
+ #
43
+ # @!attribute address
44
+ # @return [String] The address used to connect to the server.
45
+ #
46
+ # @!attribute port
47
+ # @return [Integer] The port used to connect to the server
48
+ #
49
+ # @!attribute nick
50
+ # @return [String] The nickname of the bot on the server.
51
+ #
52
+ # @!attribute user
53
+ # @return [String] The username of the bot on the server.
54
+ #
55
+ # @!attribute real
56
+ # @return [String] The real name or GECOS of the bot on the server.
57
+ #
58
+ # @!attribute password
59
+ # @return [String] If needed, the password used to connect to the server
60
+ # @return [nil] If not needed.
61
+ #
62
+ # @!attribute bind
63
+ # @return [String] If desired, the address to which to bind for this socket
64
+ # @return [nil] If not desired.
65
+ # @note This appears to be unused at the moment.
66
+ #
67
+ # @!attribute ssl
68
+ # @return [true, false] If SSL should [not] be used for the connection.
69
+ #
70
+ # @!attribute sasl_id
71
+ # @return [String] If SASL is desired, the username with which to authenticate.
72
+ # @return [nil] If not used.
73
+ # @note This is seemingly deprecated?
74
+ #
75
+ # @!attribute connected
76
+ # @return [true, false] Whether or not we are connected to the server.
77
+ #
78
+ # @!attribute mask
79
+ # @return [String] The bot's own hostname or mask on the IRC server.
80
+ #
81
+ # @!attribute recvq
82
+ # @return [Array<String>] The socket's receive queue, which is comprised of an array
83
+ # of strings which are pending processing.
84
+ #
85
+ #
86
+ # @!attribute prefixes
87
+ # @return [Hash{String => String}] The IRC server's supported prefixes, with the key being
88
+ # the channel mode which represents the prefix, and the value being the prefix.
89
+ #
90
+ # @!attribute channel_modes
91
+ # @return [Hash{Symbol => Array<String>}] The IRC server's supported channel modes, divided as thus:
92
+ #
93
+ # - +:list+ = A list of modes which add/remove a nickname or mask from a channel list, such as ops and bans.
94
+ # - +:always+ = A llst of modes which change a channel setting, and always have a parameter.
95
+ # - +:set+ = A list of modes which change a channel setting, and which have a parameter only when set.
96
+ # - +:never+ = A list of modes which change a channel setting, and which never have a parameter.
97
+ #
98
+ # @!attribute max_modes
99
+ # @return [Integer] The maximum number of mode changes which may be specified in a /MODE query.
100
+ #
101
+ # @!attribute await_self_who
102
+ # @return [true, false] Whether or not we are awaiting for a response to a /WHO on ourselves.
103
+ #
104
+ # @!attribute channels
105
+ # @return [Hash{String => IRC::Object::Channel}] A list of channels in which we reside,
106
+ # with each key being the channel's name in all-lowercase, and the respective values
107
+ # being of {IRC::Object::Channel IRC::Object::Channel}.
108
+ #
109
+ # @!attribute users
110
+ # @return [Hash{String => IRC::Object::User}] A list of users who are known to us,
111
+ # with each key being the user's nickname in all-lowercase, and the respective values
112
+ # being of {IRC::Object::User IRC::Object::User}.
113
+ class Server
114
+ include Auto::DSL::Base
115
+
116
+ attr_reader :socket, :in, :out, :type, :supp
117
+ attr_accessor :name, :address, :port, :nick, :user, :real, :password,
118
+ :bind, :ssl, :connected, :chans, :users
119
+
120
+ # Produce a new instance of {Auto::IRC::Server}.
121
+ #
122
+ # @param [String] name The name of the server to which we should connect.
123
+ #
124
+ # @yieldparam [Auto::IRC::Server] c This instance, intended for configuration of the
125
+ # attributes.
126
+ #
127
+ # Configuration attributes are +address+, +port+, +nick+, +user+, +real+,
128
+ # +password+, +bind+, and +ssl+.
129
+ #
130
+ #
131
+ # @example
132
+ # irc = Auto::IRC::Server.new('Freenode') do |c|
133
+ # c.address = 'irc.freenode.net'
134
+ # c.port = 7000
135
+ # c.nick = 'cowmoon'
136
+ # c.user = 'foo1'
137
+ # c.real = "The night is lovely."
138
+ # c.bind = 'localhost'
139
+ # c.ssl = true
140
+ # end
141
+ def initialize(name)
142
+
143
+ # Prepare attributes.
144
+ @name = name
145
+ @address = nil
146
+ @port = nil
147
+ @nick = nil
148
+ @user = nil
149
+ @real = nil
150
+ @password = nil
151
+ @bind = nil
152
+ @ssl = false
153
+
154
+ # Yield for configuration.
155
+ yield(self) if block_given? or raise ArgumentError, "Server #{name} unable to initialize because it was not configured."
156
+
157
+ # Additional instance attributes.
158
+ @in = 0
159
+ @out = 0
160
+ @socket = nil
161
+ @connected = false
162
+ @type = :irc
163
+
164
+ # Pull in commands.
165
+ extend Auto::IRC::Std::Commands
166
+ # State managers.
167
+ @supp = Auto::IRC::State::Support.new
168
+ @chans = nil
169
+ @users = nil
170
+
171
+ # Our receive queue remainder.
172
+ @recv_rem = nil
173
+
174
+ # Mutual exclusion for thread safety.
175
+ @lock = Mutex.new
176
+
177
+ end
178
+
179
+ # Establish (or attempt to) a connection with the server.
180
+ def connect
181
+
182
+ # Check for missing attributes.
183
+ begin
184
+ attribute_check
185
+ rescue => e
186
+ $m.error("Cannot connect to server #@name: #{e}", false, e.backtrace)
187
+ end
188
+
189
+ $m.info("Connecting to #@name @ #@address:#@port...")
190
+
191
+ # Create a new socket.
192
+ begin
193
+ socket = TCPSocket.new(@address, @port, @bind)
194
+ rescue => e
195
+ $m.error("Failed to connect to server #@name: #{e}", false, e.backtrace)
196
+ raise
197
+ end
198
+
199
+ # Wrap it in SSL if told to.
200
+ if ssl
201
+ begin
202
+ socket = OpenSSL::SSL::SSLSocket.new(socket)
203
+ socket.connect
204
+ rescue => e
205
+ $m.error("Failed to connect to server #@name: #{e}", false, e.backtrace)
206
+ raise
207
+ end
208
+ end
209
+
210
+ @socket = socket
211
+
212
+ # Register.
213
+ emit :irc, :preconnect, self
214
+ pass @password if @password
215
+ snd 'CAP LS'
216
+ self.nickname = @nick
217
+ user @user, Socket.gethostname, @address, @real
218
+
219
+ end
220
+
221
+ # Send data to the socket.
222
+ #
223
+ # @param [String] data The string of data, which should not exceed 512 in length.
224
+ def snd data
225
+ $m.foreground("{irc-send} #@name << #{data}")
226
+ @socket.write("#{data}\r\n")
227
+ @out += "#{data}\r\n".length
228
+ end
229
+
230
+ # Receive data from the socket, and push it into the recvQ.
231
+ def recv
232
+
233
+ # Thread safety.
234
+ @lock.synchronize do
235
+
236
+ if @socket.nil? or @socket.eof?
237
+ return
238
+ end
239
+
240
+ # Read the data.
241
+ data = @socket.sysread(1024)
242
+ # Increase in.
243
+ @in += data.length
244
+
245
+ # Split the data.
246
+ recv = []
247
+ until data !~ /\r\n/
248
+ line, data = data.split(/(?<=\r\n)/, 2)
249
+ recv.push line.chomp "\r\n"
250
+ end
251
+
252
+ # Check if there's a remainder in the recvQ.
253
+ if @recv_rem != ''
254
+ recv[0] = "#@recv_rem#{recv[0]}"
255
+ @recv_rem = ''
256
+ end
257
+ @recv_rem = data if data != ''
258
+
259
+ # Lastly, sent the data out
260
+ recv.each do |dline|
261
+ $m.foreground("{irc-recv} #@name >> #{dline}")
262
+ emit :irc, :receive, self, dline # send it out to :receive
263
+ end
264
+
265
+ end
266
+
267
+ end
268
+
269
+ def to_s; @name; end
270
+ def inspect; "#<Auto::IRC::Server: name='#@name'>"; end
271
+ alias_method :s, :to_s
272
+
273
+ #######
274
+ private
275
+ #######
276
+
277
+ # Check the presence of all attributes.
278
+ def attribute_check
279
+ raise(ConfigError, "Missing server address") unless @address
280
+ raise(ConfigError, "Missing server port") unless @port
281
+ raise(ConfigError, "Missing nickname to use") unless @nick
282
+ raise(ConfigError, "Missing username to use") unless @user
283
+ raise(ConfigError, "Missing realname to use") unless @real
284
+ end
285
+
286
+ # Check if we are connected.
287
+ #
288
+ # @return [true, false]
289
+ def connected?
290
+ return false unless @socket
291
+ return false unless @connected
292
+ true
293
+ end
294
+
295
+ end # class Server
296
+
297
+ end # module IRC
298
+
299
+ end # module Auto
300
+
301
+ # vim: set ts=4 sts=2 sw=2 et: