votifier 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
19
+
20
+ *~
21
+ #*#
22
+ .#*
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 pr4xt3roy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9
+ the Software, and to permit persons to whom the Software is furnished to do so,
10
+ subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,38 @@
1
+ # Votifier Gem
2
+
3
+ Ruby Gem for a Votifier Server and Client for Minecraft
4
+
5
+ ## Installation
6
+
7
+ For a manual installation, type this on your console:
8
+
9
+ $ gem install votifier
10
+
11
+ ## Usage
12
+
13
+ require 'votifier'
14
+ Votifier::Client.new(public_key_file, "MyMinecraftServerList.info", :username => "Notch").send
15
+
16
+ If you have the player's IP addess and the timestamp, you can pass them
17
+
18
+ require 'votifier'
19
+ Votifier::Client.new(public_key_file, "MyMinecraftServerList.info", :username => "Notch", :ip_address => @ip_address, :timestamp => @timestamp).send
20
+
21
+ For the server:
22
+
23
+ require 'votifier'
24
+ Votifier::Server.new(:private_key => private_key_file).listen
25
+
26
+ ## TODO
27
+
28
+ * Unit Tests
29
+ * Support .pem, .key keys or string keys.
30
+ * The username, ip and timestamp should be passed to Votifier::Client#send instead of the contructor
31
+
32
+ ## Contributing
33
+
34
+ 1. Fork it
35
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
36
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
37
+ 4. Push to the branch (`git push origin my-new-feature`)
38
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/votifier', __FILE__)
4
+
5
+ public_key_file = File.expand_path('../../config/sample-public.key', __FILE__)
6
+ Votifier::Client.new(public_key_file, "Testing", :username => "linkoer").send
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/votifier', __FILE__)
4
+
5
+ private_key_file = File.expand_path('../../config/sample-private.key', __FILE__)
6
+ Votifier::Server.new(:private_key => private_key_file).listen
@@ -0,0 +1 @@
1
+ MIIEogIBAAKCAQEAqEyG+i/SNvCRsvM4jt3tm2fresIPCBpfU/5j0Pq4i2IjPzX0YQqHmBqrKqzIpMTgj9ITrxJ4v3FO8WHjjArEAJhYPc26w9cniVaXAFavQX07q0wZ9DJRdei6lchd5ecLQ5J90TrR4BpwxFGtw55vOpPElQi2jG1crr3fIqVspMtqPUXYesmD5Ymoace0ycPs46yS6ItWwgbPBaryeimUG0ErHoYV2aWjfP/FHnawU2n3fNWy3ZD9e7AWSwdFxYnPSZ3R9+V/YSlyYX/ls0k8SC/L9xB63rh8ifg66sgN5hlxbMIIwX2trGueeDYbYkiL499Hzj4KPfWT1L+t3a8HdwIDAQABAoIBAHcXSAAr7L3xt7gAggoeoq9wduI0Bfz+5GwEPE+5yvLerABjxp0QnWiVnn+hKo3lvt4mksU09frKTElksmb7izy8kNyTAtDoI9L8UffsXzGhU6LgRBFXtesQl0+8LC2uM3tKYvu2eqLxMtDI14PwTdcOj3HCa6KtFIOWWhojIuDs5f45V64pBqrC0a4Alcppzjb1rJTsg7FXp1EIwx+WEc+sV34y9dwogokQrpU7mD2LdTOT4jcQ/NnpSMXMGpbi+CtynOhM6G4vwy2hLaV5dENwchlyWYXnDPuDEZK6/+1WWWJnHV1mhKDK1PEvia7JRxWNlZeNrDKMpDgoDg5BuSECgYEA2wU7euS4ekugZ1XHakrno55phdS39jS4YaB9RoheAt2IusbYK309q8PtcsDt8mtT9F3ji5C66YJsvuht7Dfb4HXVvpPkKU8eN3wOzI3zBEZ0HEmbKf6AKTE4msjd3/zAeMGr2KSllJbomqrQBieMDdffRZ8qyo10WENlH5miw0cCgYEAxLbyygzV6r0mRxtw4H8SjrjAPyA9eOhwDB07peGi7kv6dEUYhu4gcaUPQSMigqV0ADNTed8ueq2HzJ4V5nqkg97sK6Q00yLOxUkwq5aKD4Fq1vctotawX9SOPyjzKwtu8BXzJDESIyrxuWgDB2ZGQtfvaI+guOVHakwq1+SJ0lECgYAtmchJjQdvxwEtoqlzUwcphNj5mVF3/IALK4wJvGi+dft6z93AKEJH2fI9OzgPihMfxNCUhVy1M4eKs//296Za9I29MTOG+kcTTEwUgNWBJV4VaanZs3hhmzLq3zl64jf8rG4oHBexeT4Svc+0CFXbp/9/kmUpaQw5OEb8rlM6DwKBgHUNe9kY3C2LEfzb6kXbt1ovu02UzJ9miE3dE0I4ym/LzCNlfhvEFJArLLGQy5c8BpOb9v8c+5ZKLfVm2BdGQSCrBJNPaZN9MdaZH5nqwQpK8x0pBgHQiDDt1RrmLhQeAIxiM0UE4gsFIcM2jh7YD9T0kuQAGx4KaH1rB09iEVSRAoGALrDquzyGNU75h9X46wFibbLbRs5H/pjwFn2kXjdfCatrPRYhCDBp2cM2jRLt3xua/Icg8b3tzAEcyabIuieH0tTI+Cc+IzrJeLspHHOvgqa1voJEwnkmsCorwh4umV+5yCtFWuVQNNpbU7Kk50FhlSaS75JQsrxmkUJaQ7+9Lt0=
@@ -0,0 +1 @@
1
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqEyG+i/SNvCRsvM4jt3tm2fresIPCBpfU/5j0Pq4i2IjPzX0YQqHmBqrKqzIpMTgj9ITrxJ4v3FO8WHjjArEAJhYPc26w9cniVaXAFavQX07q0wZ9DJRdei6lchd5ecLQ5J90TrR4BpwxFGtw55vOpPElQi2jG1crr3fIqVspMtqPUXYesmD5Ymoace0ycPs46yS6ItWwgbPBaryeimUG0ErHoYV2aWjfP/FHnawU2n3fNWy3ZD9e7AWSwdFxYnPSZ3R9+V/YSlyYX/ls0k8SC/L9xB63rh8ifg66sgN5hlxbMIIwX2trGueeDYbYkiL499Hzj4KPfWT1L+t3a8HdwIDAQAB
@@ -0,0 +1,4 @@
1
+ require File.expand_path('../votifier/vote', __FILE__)
2
+ require File.expand_path('../votifier/server', __FILE__)
3
+ require File.expand_path('../votifier/client', __FILE__)
4
+ require File.expand_path('../votifier/key', __FILE__)
@@ -0,0 +1,81 @@
1
+ require 'socket' # Sockets are in standard library
2
+
3
+ module Votifier
4
+ class Client
5
+
6
+ attr_reader :public_key, :service_name
7
+ attr_accessor :username, :ip_address, :timestamp
8
+
9
+ def initialize(public_key_file, service_name, opts = {})
10
+ init_public_key(public_key_file)
11
+ @service_name = service_name
12
+ @username = opts.fetch(:username, nil)
13
+ @ip_address = opts.fetch(:ip_address, detect_ip_address)
14
+ @timestamp = opts.fetch(:timestamp, Time.now.to_i)
15
+ end
16
+
17
+ def init_public_key(public_key_file)
18
+ @public_key = Votifer::Key.from_public_key_file(public_key_file)
19
+ end
20
+
21
+ def detect_ip_address
22
+ remote_ip = ENV['HTTP_X_FORWARDED_FOR'] || ENV['REMOTE_ADDR'] || my_best_ip_address
23
+ remote_ip = remote_ip.ip_address if remote_ip.respond_to?(:ip_address)
24
+ remote_ip = remote_ip.scan(/[\d.]+/).first
25
+ end
26
+
27
+ def my_best_ip_address
28
+ my_first_public_ipv4 || my_first_private_ipv4
29
+ end
30
+
31
+ def my_first_public_ipv4
32
+ ips.detect{|intf| intf.ipv4? and !intf.ipv4_loopback? and !intf.ipv4_multicast? and !intf.ipv4_private?}
33
+ end
34
+
35
+ def my_first_private_ipv4
36
+ ips.detect{|intf| intf.ipv4_private?}
37
+ end
38
+
39
+ def ips
40
+ @ips ||= Socket.ip_address_list
41
+ end
42
+
43
+ def send
44
+ validate!
45
+ votifier_string = to_a.join("\n")
46
+ encrypted = encrypt(votifier_string)
47
+ send_to_server(encrypted)
48
+ end
49
+
50
+ def validate!
51
+ raise 'Usename must be present' unless !username.nil?
52
+ end
53
+
54
+ def encrypt(votifier_string)
55
+ encrypted = public_key.public_encrypt(votifier_string)
56
+ raise "Error encrypting, invalid size: #{encrypted.bytesize}" unless encrypted.bytesize == 256
57
+ encrypted
58
+ end
59
+
60
+ def send_to_server(encrypted)
61
+ hostname = 'localhost'
62
+ port = 8193
63
+
64
+ s = TCPSocket.open(hostname, port)
65
+
66
+ s.print encrypted
67
+ s.close
68
+ end
69
+
70
+ def to_a
71
+ [
72
+ "VOTE",
73
+ service_name,
74
+ username,
75
+ ip_address,
76
+ timestamp
77
+ ]
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,51 @@
1
+ require 'forwardable'
2
+ require 'openssl'
3
+ module Votifer
4
+ class Key
5
+
6
+ def initialize(pem_key_content)
7
+ @key = OpenSSL::PKey::RSA.new(pem_key_content)
8
+ end
9
+
10
+ def self.from_pem_key_file(key_file)
11
+ key_content = File.read(key_file)
12
+ self.from_perm_key_content(key_content)
13
+ end
14
+
15
+ def self.from_public_key_file(key_file)
16
+ self.from_key_file(key_file, :public)
17
+ end
18
+
19
+ def self.from_key_file(key_file, type = :private)
20
+ key_content = File.read(key_file)
21
+ self.from_key_content(key_content, type)
22
+ end
23
+
24
+ def self.from_key_content(key_content, type = :private)
25
+ pem_key_content = convert_to_pem_format(key_content, type)
26
+ from_pem_key_content(pem_key_content)
27
+ end
28
+
29
+ def self.from_pem_key_content(pem_key_content)
30
+ key = self.new(pem_key_content)
31
+ key
32
+ end
33
+
34
+ def self.convert_to_pem_format(key_content, type = :private)
35
+ key_headers = {
36
+ :private => "RSA PRIVATE",
37
+ :public => "PUBLIC"
38
+ }
39
+ header = key_headers[type]
40
+ wrapped_key_content = key_content.scan(/.{1,65}/).join("\n")
41
+ pem_key_content = "-----BEGIN #{header} KEY-----\n" +
42
+ wrapped_key_content + "\n" +
43
+ "-----END #{header} KEY-----"
44
+ pem_key_content
45
+ end
46
+
47
+ extend Forwardable
48
+ def_delegators :@key, :private_decrypt, :public_encrypt
49
+
50
+ end
51
+ end
@@ -0,0 +1,64 @@
1
+ require 'socket' # Get sockets from stdlib
2
+ module Votifier
3
+ class Server
4
+
5
+ attr_reader :private_key
6
+
7
+ def initialize(opts)
8
+ raise ':private_key options is required' unless opts.key?(:private_key)
9
+ init_private_key(opts[:private_key])
10
+ end
11
+
12
+ def init_private_key(private_key_file)
13
+ @private_key = Votifer::Key.from_key_file(private_key_file)
14
+ end
15
+
16
+ def listen
17
+ server = TCPServer.open(8193) # Socket to listen on port
18
+ loop { # Servers run forever
19
+ Thread.start(server.accept) do |client| # Wait for a client to connect
20
+ handle_connection(client)
21
+ end
22
+ }
23
+ end
24
+
25
+ def handle_connection(client)
26
+ lines = ""
27
+ while line = client.gets
28
+ lines += line
29
+ end
30
+ begin
31
+ vote_info = parse_content(lines)
32
+ vote = Vote.from_array(vote_info)
33
+ puts vote.to_h
34
+ client.close # Disconnect from the client
35
+ rescue => e
36
+ puts e.inspect
37
+ puts e.backtrace
38
+ end
39
+ end
40
+
41
+ def parse_content(content)
42
+ raise Error::InvalidVotePacket, "Must be 256 bytes: is #{content.bytesize}" unless content.bytesize == 256
43
+ vote_info_string = decrypt(content)
44
+ raise Error::InvalidVotePacket, 'Must contains newline characters' unless vote_info_string.match(/\n/)
45
+ vote_info = vote_info_string.split("\n")
46
+ raise Error::InvalidVotePacket, 'Must contain 5 elements or more' unless vote_info.size >= 5
47
+ raise Error::InvalidVotePacket, 'Invalid opcode: must be VOTE' unless vote_info[0] == "VOTE"
48
+ vote_info
49
+ end
50
+
51
+ def decrypt(encrypted_string)
52
+ string = private_key.private_decrypt(encrypted_string)
53
+ string
54
+ end
55
+
56
+ class Error
57
+ class InvalidVotePacket < StandardError
58
+ def initialize(str)
59
+ super("Invalid Vote Packet: #{str}")
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,3 @@
1
+ module Votifier
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,27 @@
1
+ module Votifier
2
+ class Vote
3
+ attr_reader :service_name, :username, :ip_address, :timestamp
4
+
5
+ def initialize(service_name, username, ip_address, timestamp)
6
+ @service_name = service_name
7
+ @username = username
8
+ @ip_address = ip_address
9
+ @timestamp = timestamp
10
+ end
11
+
12
+ def self.from_array(vote_info)
13
+ opcode, service_name, username, ip_address, timestamp, empty_space = vote_info
14
+ vote = Vote.new(service_name, username, ip_address, timestamp)
15
+ vote
16
+ end
17
+
18
+ def to_h
19
+ {
20
+ :service_name => service_name,
21
+ :username => username,
22
+ :ip_address => ip_address,
23
+ :timestamp => timestamp
24
+ }
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+ require 'votifier'
3
+
4
+ class VotifierTest < Test::Unit::TestCase
5
+ def test_votifier
6
+ assert true
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/votifier/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'votifier'
6
+ gem.summary = %q{Votifier Server and Client for Minecraft}
7
+ gem.description = %q{This allows you to accept Votifier connections OR send them to a Minecraft Server.}
8
+ gem.authors = ["Pr4xt3roy"]
9
+ gem.email = %W(pr4xt3roy@capricatown.net)
10
+ gem.homepage = 'https://github.com/pr4xt3roy/votifier-gem'
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.license = 'MIT'
14
+ gem.require_paths = ["lib"]
15
+
16
+ gem.version = Votifier::VERSION
17
+ gem.date = '2013-09-08'
18
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: votifier
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Pr4xt3roy
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2013-09-08 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: This allows you to accept Votifier connections OR send them to a Minecraft Server.
22
+ email:
23
+ - pr4xt3roy@capricatown.net
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - LICENSE
33
+ - README.md
34
+ - Rakefile
35
+ - bin/votifier-client
36
+ - bin/votifier-server
37
+ - config/sample-private.key
38
+ - config/sample-public.key
39
+ - lib/votifier.rb
40
+ - lib/votifier/client.rb
41
+ - lib/votifier/key.rb
42
+ - lib/votifier/server.rb
43
+ - lib/votifier/version.rb
44
+ - lib/votifier/vote.rb
45
+ - test/test_votifer.rb
46
+ - votifier.gemspec
47
+ homepage: https://github.com/pr4xt3roy/votifier-gem
48
+ licenses:
49
+ - MIT
50
+ post_install_message:
51
+ rdoc_options: []
52
+
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ hash: 3
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ hash: 3
70
+ segments:
71
+ - 0
72
+ version: "0"
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.8.15
77
+ signing_key:
78
+ specification_version: 3
79
+ summary: Votifier Server and Client for Minecraft
80
+ test_files: []
81
+