blur 1.8.6 → 2.1

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.
@@ -1,17 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- # The +Encryption+ module extends the communication-functionality of
5
- # the client. It is intended to enable helpers but also core functionality
6
- # that encrypts the incoming and outgoing data of Blur.
7
- #
8
- # Encryption modules are not loaded into the VM until it's required.
9
- module Encryption
10
- # Indicates that user-input (a channel user message, e.g.) is in invalid
11
- # format to a certain encryption algorithm.
12
- class BadInputError < StandardError; end
13
-
14
- autoload :FiSH, "blur/encryption/fish"
15
- autoload :Base64, "blur/encryption/base64"
16
- end
17
- end
@@ -1,71 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- module Encryption
5
- # The +Encryption::Base64+ module differs from the original Base64
6
- # implementation. I'm not sure how exactly, perhaps the charset?
7
- #
8
- # I originally found the Ruby implementation of FiSH on a website where
9
- # it was graciously submitted by an anonymous user, since then I've
10
- # implemented it in a weechat script, and now I've refactored it for use in
11
- # Blur.
12
- #
13
- # @see http://maero.dk/pub/sources/weechat/ruby/autoload/fish.rb
14
- module Base64
15
- # The difference I suspect between the original Base64 implementation
16
- # and the one used in FiSH.
17
- Charset = "./0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
18
-
19
- # Decode a base64-encoded string.
20
- #
21
- # @return [String] Base64-decoded string.
22
- def self.decode string
23
- unless string.length % 12 == 0
24
- raise BadInputError, "input has to be a multiple of 12 characters."
25
- end
26
-
27
- String.new.tap do |buffer|
28
- j = -1
29
-
30
- while j < string.length - 1
31
- right, left = 0, 0
32
-
33
- 6.times{|i| right |= Charset.index(string[j += 1]) << (i * 6) }
34
- 6.times{|i| left |= Charset.index(string[j += 1]) << (i * 6) }
35
-
36
- 4.times do |i|
37
- buffer << ((left & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
38
- end
39
-
40
- 4.times do |i|
41
- buffer << ((right & (0xFF << ((3 - i) * 8))) >> ((3 - i) * 8)).chr
42
- end
43
- end
44
- end
45
- end
46
-
47
- # Encode a string-cipher.
48
- #
49
- # @return [String] Base64-encoded string.
50
- def self.encode string
51
- unless string.length % 8 == 0
52
- raise BadInputError, "input has to be a multiple of 8 characters."
53
- end
54
-
55
- left = 0
56
- right = 0
57
- decimals = [24, 16, 8, 0]
58
-
59
- String.new.tap do |buffer|
60
- string.each_block do |block|
61
- 4.times{|i| left += (block[i].ord << decimals[i]) }
62
- 4.times{|i| right += (block[i+4].ord << decimals[i]) }
63
-
64
- 6.times{|i| buffer << Charset[right & 0x3F].chr; right = right >> 6 }
65
- 6.times{|i| buffer << Charset[left & 0x3F].chr; left = left >> 6 }
66
- end
67
- end
68
- end
69
- end
70
- end
71
- end
@@ -1,80 +0,0 @@
1
- # encoding: utf-8
2
-
3
- require 'crypt/blowfish'
4
-
5
- module Blur
6
- module Encryption
7
- # The +FiSH+ algorithm is a combination of Base64 encoding
8
- # and the blowfish encryption.
9
- #
10
- # Shared text messages are prepended by "++OK+", an older implementation
11
- # prepends it with "+mcps+" - Blur drops support for that implementation.
12
- #
13
- # There's multiple client-implementations available on the official FiSH
14
- # homepage.
15
- #
16
- # == DH1080 Key exchange
17
- # The newer FiSH implementation introduces a 1080bit Diffie-Hellman
18
- # key-exchange mechanism.
19
- #
20
- # Blur does currently not support key exchanges.
21
- class FiSH
22
- # The standard FiSH block-size.
23
- BlockSize = 8
24
-
25
- # @return [String] the blowfish salt-key.
26
- attr_accessor :keyphrase
27
-
28
- # Change the keyphrase and instantiate a new blowfish object.
29
- def keyphrase= keyphrase
30
- @keyphrase = keyphrase
31
- @blowfish = Crypt::Blowfish.new @keyphrase
32
- end
33
-
34
- # Instantiate a new fish-encryption object.
35
- def initialize keyphrase
36
- @keyphrase = keyphrase
37
- @blowfish = Crypt::Blowfish.new keyphrase
38
- end
39
-
40
- # Encrypt an input string using the keyphrase stored in the +@blowfish+
41
- # object.
42
- #
43
- # @return [String] the encrypted string.
44
- def encrypt string
45
- String.new.tap do |buffer|
46
- nullpad(string).each_block do |block|
47
- chunk = @blowfish.encrypt_block block
48
- buffer.concat Base64.encode chunk
49
- end
50
- end
51
- end
52
-
53
- # Decrypt an input string using the keyphrase stored in the +@blowfish+
54
- # object.
55
- #
56
- # @return [String] the decrypted string.
57
- def decrypt string
58
- unless string.length % 12 == 0
59
- raise BadInputError, "input has to be a multiple of 12 characters."
60
- end
61
-
62
- String.new.tap do |buffer|
63
- string.each_block 12 do |block|
64
- chunk = @blowfish.decrypt_block Base64.decode block
65
- buffer.concat chunk
66
- end
67
- end.rstrip
68
- end
69
-
70
- private
71
- # Fill up the last block with null-bytes until it's a multiple of 8.
72
- #
73
- # @return [String] the nullpadded string.
74
- def nullpad string
75
- length = string.length + BlockSize - string.length % BlockSize
76
- string.ljust length, ?\0
77
- end
78
- end
79
- end
80
- end
@@ -1,13 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- module Evaluable
5
- # Evaluate the contents of the input file in the context of +self+.
6
- def evaluate_source_file path
7
- instance_eval File.read(path), File.basename(path), 0
8
- @__evaluated = true
9
- rescue Exception => exception
10
- puts "#{exception.message ^ :bold} on line #{exception.line.to_s ^ :bold}"
11
- end
12
- end
13
- end
@@ -1,42 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- # +Extension+ provides a sort of modules for scripts, for common functionality.
5
- #
6
- # Think of it as a kind of scripts for scripts.
7
- class Extension
8
- include Evaluable
9
- include Script::DSL
10
- include Logging
11
-
12
- # @return the path in which the script remains.
13
- attr_accessor :__path
14
- # Can be used inside the script to act with the client itself.
15
- # @return [Network::Client] the client delegate.
16
- attr_accessor :__client
17
-
18
- # Instantiates a new extension context and evaluates the +path+ extension
19
- # file.
20
- def initialize path
21
- @__path = path
22
-
23
- if evaluate_source_file path
24
- log.info "Loaded extension #{@__path}"
25
- end
26
- end
27
-
28
- # Purely for DSL purposes.
29
- #
30
- # @example
31
- # Extension :http do
32
- # …
33
- # end
34
- def Extension name, &block
35
- @__name = name
36
-
37
- instance_eval &block
38
-
39
- true
40
- end
41
- end
42
- end
@@ -1,91 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- class Network
5
- # The +Channel+ class is used for encapsulating a channel and its properties.
6
- #
7
- # Users inside the channel is stored in the {#channels} attribute.
8
- #
9
- # Modes can be set for a channel, but Blur is not
10
- # {http://www.irc.org/tech_docs/005.html ISupport}-compliant yet.
11
- #
12
- # @todo make so that channels *and* users belongs to the network, and not
13
- # like now where the user belongs to the channel, resulting in multiple
14
- # user instances.
15
- class Channel
16
- # @return [String] the channels name.
17
- attr_accessor :name
18
- # @return [Array] a list of users in the channel.
19
- attr_accessor :users
20
- # @return [String] the channels topic.
21
- attr_accessor :topic
22
- # @return [String] all the modes set on the channel.
23
- attr_accessor :modes
24
- # @return [Network] a reference to the network.
25
- attr_accessor :network
26
- # @return [Encryption::Fish] the channel encryption, if any.
27
- attr_accessor :encryption
28
-
29
- # Check whether or not this is an encrypted channel.
30
- def encrypted?; not @encryption.nil? end
31
-
32
- # Instantiate a user with a nickname, a network and a user list.
33
- def initialize name, network = nil, users = []
34
- @name = name
35
- @users = users
36
- @modes = ""
37
- @network = network
38
-
39
- users.each { |user| user.channel = self }
40
- end
41
-
42
- # Merge the channels mode corresponding to the leading character (+ or -).
43
- #
44
- # @param [String] modes the modes to merge with.
45
- def merge_modes modes
46
- addition = true
47
-
48
- modes.each_char do |char|
49
- case char
50
- when ?+
51
- addition = true
52
- when ?-
53
- addition = false
54
- else
55
- addition ? @modes.concat(char) : @modes.delete!(char)
56
- end
57
- end
58
- end
59
-
60
- # Send a message to the channel.
61
- #
62
- # @param [String] message the message to send.
63
- def say message
64
- @network.say self, message
65
- end
66
-
67
- # Find a user with +nick+ as its nickname.
68
- #
69
- # @param [String] nick the nickname to find the user of.
70
- def user_by_nick nick
71
- @users.find { |user| user.nick == nick }
72
- end
73
-
74
- # Convert it to a debug-friendly format.
75
- def inspect
76
- %{#<#{self.class.name} @name=#{@name.inspect} @users=#{@users.inspect}}
77
- end
78
-
79
- # Called when YAML attempts to save the object, which happens when a
80
- # scripts cache contains this user and the script is unloaded.
81
- def to_yaml options = {}
82
- @name.to_yaml options
83
- end
84
-
85
- # Get the channels name.
86
- def to_s
87
- @name
88
- end
89
- end
90
- end
91
- end
@@ -1,83 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- class Network
5
- # The +Command+ class is used for encapsulating the command-lines.
6
- #
7
- # Blur is using regular-expression for parsing, this is to be replaced
8
- # with a more native way of parsing, making it much, much easier on the
9
- # processor.
10
- class Command
11
- # @return [Symbol, Fixnum] the command name.
12
- # @example
13
- # 332 or :quit
14
- attr_accessor :name
15
- # @return [Array] a list of parameters.
16
- attr_accessor :params
17
- # @return [String] a hostname or a hostmask.
18
- attr_accessor :prefix
19
-
20
- # The arbitrary regex pattern.
21
- Pattern = /^(?:[:@]([^\s]+) )?([^\s]+)(?: ((?:[^:\s][^\s]* ?)*))?(?: ?:(.*))?$/
22
-
23
- # Parse a line and encapsulate it as a Command.
24
- #
25
- # @return [Command] the parsed command.
26
- # @example
27
- # Command.parse "ChanServ!ChanServ@services.uplink.io MODE #uplink +v mk"
28
- # # => #<Blur::Network::Command … >
29
- def self.parse data
30
- match = data.strip.match Pattern
31
- prefix, name, args, extra = match.captures
32
- params = extra ? args.split << extra : args.split
33
-
34
- new(name, params).tap do |this|
35
- this.prefix = prefix
36
- end
37
- end
38
-
39
- # Get a parameter by its +index+.
40
- def [] index; @params[index] end
41
-
42
- # Instantiate a command.
43
- #
44
- # @see Command.parse
45
- def initialize name, params = []
46
- @name, @params = name, params
47
- end
48
-
49
- # Get the sender of the command.
50
- #
51
- # @note the return value is a string if it's a hostname, and an openstruct
52
- # with the attributes #nickname, #username and #hostname if it's a
53
- # hostmask.
54
- #
55
- # @return [String, OpenStruct] the sender.
56
- def sender
57
- return @sender if @sender
58
-
59
- if prefix =~ /^(\S+)!(\S+)@(\S+)$/
60
- @sender = OpenStruct.new nickname: $1, username: $2, hostname: $3
61
- else
62
- @sender = prefix
63
- end
64
- end
65
-
66
- # Convert it to an IRC-compliant line.
67
- #
68
- # @return [String] the command line.
69
- def to_s
70
- String.new.tap do |line|
71
- line << "#{prefix} " if prefix
72
- line << name.to_s
73
-
74
- params.each_with_index do |param, index|
75
- line << ' '
76
- line << ?: if index == params.length - 1 and param =~ /[ :]/
77
- line << param.to_s
78
- end
79
- end
80
- end
81
- end
82
- end
83
- end
@@ -1,106 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module Blur
4
- class Network
5
- # The +User+ class is used for encapsulating a user and its properties.
6
- #
7
- # The user owns a reference to its parent channel.
8
- #
9
- # Modes can be set for a user, but Blur is not
10
- # {http://www.irc.org/tech_docs/005.html ISupport}-compliant yet.
11
- #
12
- # @todo make so that channels *and* users belongs to the network, and not
13
- # like now where the user belongs to the channel, resulting in multiple
14
- # user instances.
15
- class User
16
- # @return [String] the users nickname.
17
- attr_accessor :nick
18
- # @return [String] the users username.
19
- attr_accessor :name
20
- # @return [String] the users hostname.
21
- attr_accessor :host
22
- # @return [String] all the modes set on the user.
23
- attr_accessor :modes
24
- # @return [Channel] a reference to the users channel.
25
- attr_accessor :channel
26
- # @return [Network] a reference to the network.
27
- attr_accessor :network
28
-
29
- # Check to see if the user is an admin (+a)
30
- def admin?; @modes.include? "a" end
31
- # Check to see if the user has voice (+v)
32
- def voice?; @modes.include? "v" end
33
- # Check to see if the user is the owner (+q)
34
- def owner?; @modes.include? "q" end
35
- # Check to see if the user is an operator (+o)
36
- def operator?; @modes.include? "o" end
37
- # Check to see if the user is an half-operator (+h)
38
- def half_operator?; @modes.include? "h" end
39
-
40
- # Instantiate a user with a nickname.
41
- def initialize nick
42
- @nick = nick
43
- @modes = ""
44
-
45
- if modes = prefix_to_mode(nick[0])
46
- @nick = nick[1..-1]
47
- @modes = modes
48
- end
49
- end
50
-
51
- # Merge the users mode corresponding to the leading character (+ or -).
52
- #
53
- # @param [String] modes the modes to merge with.
54
- def merge_modes modes
55
- addition = true
56
-
57
- modes.each_char do |char|
58
- case char
59
- when ?+
60
- addition = true
61
- when ?-
62
- addition = false
63
- else
64
- addition ? @modes.concat(char) : @modes.delete!(char)
65
- end
66
- end
67
- end
68
-
69
- # Send a private message to the user.
70
- #
71
- # @param [String] message the message to send.
72
- def say message
73
- @network.say self, message
74
- end
75
-
76
- # Convert it to a debug-friendly format.
77
- def inspect
78
- %{#<#{self.class.name} @nick=#{@nick.inspect} @channel=#{@channel.name.inspect}>}
79
- end
80
-
81
- # Called when YAML attempts to save the object, which happens when a
82
- # scripts cache contains this user and the script is unloaded.
83
- def to_yaml options = {}
84
- @nick.to_yaml options
85
- end
86
-
87
- # Get the users nickname.
88
- def to_s
89
- @nick
90
- end
91
-
92
- private
93
-
94
- # Translate a nickname-prefix to a mode character.
95
- def prefix_to_mode prefix
96
- case prefix
97
- when '@' then 'o'
98
- when '+' then 'v'
99
- when '%' then 'h'
100
- when '&' then 'a'
101
- when '~' then 'q'
102
- end
103
- end
104
- end
105
- end
106
- end