From 0c35e2ab5be46e98fbec162f98740ae248c0f260 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:19:44 +0100 Subject: [PATCH 01/13] Remove methods not defined on routes --- app/controllers/servers_controller.rb | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index 72825c2..2df8ae4 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -1,11 +1,6 @@ class ServersController < ApplicationController before_filter :get_server, except: [:index, :refresh, :new, :create] - def refresh - Server.refresh - render :text => t(:servers_updated) - end - def index @servers = Server.hlds.active.ordered.all :include => :user @ns2 = Server.ns2.active.ordered.all :include => :user @@ -25,15 +20,6 @@ class ServersController < ApplicationController raise AccessError unless @server.can_update? cuser end - def admin - @result = @server.execute params[:query] if params[:query] - raise AccessError unless @server.can_update? cuser - - if request.xhr? - render partial: 'response', layout: false - end - end - def create @server = Server.new params[:server] @server.user = cuser From 41386846625281027e3d7afd022229142425f1b8 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:19:58 +0100 Subject: [PATCH 02/13] No more graphing --- Gemfile | 1 - 1 file changed, 1 deletion(-) diff --git a/Gemfile b/Gemfile index ae4dda3..9bb95ef 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,6 @@ gem 'puma', '~> 2.11.1' gem 'exceptional', '~> 2.0.33' gem 'oj', '~> 2.5.5' gem 'faraday', '~> 0.9.0' -gem 'gruff', '~> 0.3.6' gem 'nokogiri', '~> 1.6.1' gem 'bbcoder', '~> 1.0.1' gem 'sanitize', '~> 2.1.0' From 267214a563e9a4186b51ea92b17dd6b719c80214 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:20:23 +0100 Subject: [PATCH 03/13] Remove methods which are never invoked --- app/models/server.rb | 394 ++++++++++++------------------------------- 1 file changed, 106 insertions(+), 288 deletions(-) diff --git a/app/models/server.rb b/app/models/server.rb index 5154198..6962480 100644 --- a/app/models/server.rb +++ b/app/models/server.rb @@ -31,7 +31,6 @@ # category_id :integer # -require "rcon" require "yaml" class Server < ActiveRecord::Base @@ -40,12 +39,8 @@ class Server < ActiveRecord::Base DOMAIN_HLDS = 0 DOMAIN_HLTV = 1 DOMAIN_NS2 = 2 - HLTV_IDLE = 1200 - DEMOS = "/var/www/virtual/ensl.org/hlds_l/ns/demos" - QSTAT = "/usr/bin/quakestat" - TMPFILE = "tmp/server.txt" - attr_accessor :rcon_handle, :pwd + attr_accessor :pwd attr_protected :id, :user_id, :updated_at, :created_at, :map, :players, :maxplayers, :ping, :version validates_length_of [:name, :dns,], :in => 1..30 @@ -71,301 +66,124 @@ class Server < ActiveRecord::Base AND match_time > '#{(time.ago(Match::MATCH_LENGTH).utc).strftime("%Y-%m-%d %H:%M:%S")}' AND match_time < '#{(time.ago(-Match::MATCH_LENGTH).utc).strftime("%Y-%m-%d %H:%M:%S")}'", :conditions => "matches.hltv_id IS NULL"} } - scope :of_addr, - lambda { |addr| { - :conditions => { - :ip => addr.match(/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})/)[0], - :port => addr.match(/:([0-9]{1,5})/)[1] } } } - scope :of_category, - lambda { |category| { - :conditions => {:category_id => category.id} }} - has_many :logs - has_many :matches - has_many :challenges - belongs_to :user - belongs_to :recordable, :polymorphic => true + has_many :logs + has_many :matches + has_many :challenges + belongs_to :user + belongs_to :recordable, :polymorphic => true - before_create :set_category + before_create :set_category - acts_as_versioned - non_versioned_columns << 'name' - non_versioned_columns << 'description' - non_versioned_columns << 'dns' - non_versioned_columns << 'ip' - non_versioned_columns << 'port' - non_versioned_columns << 'rcon' - non_versioned_columns << 'password' - non_versioned_columns << 'irc' - non_versioned_columns << 'user_id' - non_versioned_columns << 'official' - non_versioned_columns << 'domain' - non_versioned_columns << 'reservation' - non_versioned_columns << 'recording' - non_versioned_columns << 'idle' - non_versioned_columns << 'default_id' - non_versioned_columns << 'active' - non_versioned_columns << 'recordable_type' - non_versioned_columns << 'recordable_id' + acts_as_versioned + non_versioned_columns << 'name' + non_versioned_columns << 'description' + non_versioned_columns << 'dns' + non_versioned_columns << 'ip' + non_versioned_columns << 'port' + non_versioned_columns << 'rcon' + non_versioned_columns << 'password' + non_versioned_columns << 'irc' + non_versioned_columns << 'user_id' + non_versioned_columns << 'official' + non_versioned_columns << 'domain' + non_versioned_columns << 'reservation' + non_versioned_columns << 'recording' + non_versioned_columns << 'idle' + non_versioned_columns << 'default_id' + non_versioned_columns << 'active' + non_versioned_columns << 'recordable_type' + non_versioned_columns << 'recordable_id' - def domains - {DOMAIN_HLTV => "HLTV", DOMAIN_HLDS => "NS Server", DOMAIN_NS2 => "NS2 Server"} - end - - def to_s - name - end - - def addr - ip + ":" + port.to_s - end - - def players_s - if players.nil? or max_players.nil? - "N/A" - else - players.to_s + " / " + max_players.to_s - end - end - - def recording_s - return nil if self.domain != DOMAIN_HLTV - # recording.to_i > 0 ? Match.find(recording).to_s : recording - recording - end - - def reservation_s - return nil if domain != DOMAIN_HLTV - reservation - end - - def graphfile - File.join("public", "images", "servers", id.to_s + ".png") - end - - def set_category - self.category_id = (domain == DOMAIN_NS2 ? 45 : 44 ) - end - - def after_validation_on_update - if reservation_changed? - rcon_connect - if reservation == nil - rcon_exec "stop" - self.recording = nil - self.recordable = nil - self.idle = nil - save_demos if self.recording - hltv_stop - else - if changes['reservation'][0].nil? - hltv_start - rcon_exec "stop" - self.recording = recordable.demo_name if recordable and recordable_type == "Match" or recordable_type == "Gather" - rcon_exec "record demos/" + self.recording if self.recording - end - rcon_exec "serverpassword " + pwd - rcon_exec "connect " + reservation - self.idle = DateTime.now - end - rcon_disconnect - end - end - - def execute command - rcon_connect - response = rcon_exec command - rcon_disconnect - response - end - - def rcon_connect - self.rcon_handle = RCon::Query::Original.new(ip, port, rcon) - end - - def rcon_exec command - response = rcon_handle.command(command) - - Log.transaction do - Log.add(self, Log::DOMAIN_RCON_COMMAND, command) - if response.to_s.length > 0 - Log.add(self, Log::DOMAIN_RCON_RESPONSE, response) - end - end - - response - end - - def rcon_disconnect - rcon_handle.disconnect - end - - def hltv_start - if nr = hltv_nr - `screen -d -m -S "Hltv-#{nr[1]}" -c $HOME/.screenrc-hltv $HOME/hlds_l/hltv -ip 78.46.36.107 -port 28#{nr[1]}00 +exec ns/hltv#{nr[1]}.cfg` - sleep 1 - end - end - - def hltv_nr - self.name.match(/Tv \#([0-9])/) - end - - def hltv_stop - if nr = hltv_nr - sleep 5 - rcon_exec "exit" - #`screen -S "Hltv-#{nr[1]}" -X 'quit'` - end - end - - def save_demos - dir = case recordable_type - when "Match" then - recordable.contest.demos - when "Gather" then - Directory.find(Directory::DEMOS_GATHERS) - end - - dir ||= Directory.find(Directory::DEMOS_DEFAULT) - zip_path = File.join(dir.path, recording + ".zip") - - Zip::ZipOutputStream::open(zip_path) do |zos| - if recordable_type == "Match" - zos.put_next_entry "readme.txt" - zos.write "Team1: " + recordable.contester1.to_s + "\r\n" - zos.write "Team2: " + recordable.contester2.to_s + "\r\n" - zos.write "Date: " + recordable.match_time.to_s + "\r\n" - zos.write "Contest: " + recordable.contest.to_s + "\r\n" - zos.write "Server: " + recordable.server.addr + "\r\n" if recordable.server - zos.write "HLTV: " + addr + "\r\n" - zos.write YAML::dump(recordable.attributes).to_s - end - Dir.glob("#{DEMOS}/*").each do |file| - if File.file?(file) and file.match(/#{recording}.*\.dem/) - zos.put_next_entry File.basename(file) - zos.write(IO.read(file)) - end - end - end - - DataFile.transaction do - unless dbfile = DataFile.find_by_path(zip_path) - dbfile = DataFile.new - dbfile.path = zip_path - dbfile.directory = dir - dbfile.save! - DataFile.update_all({:name => File.basename(zip_path)}, {:id => dbfile.id}) - end - if recordable_type == "Match" - recordable.demo = dbfile - recordable.save - end - end - end - - def make_stats - graph = Gruff::Line.new - graph.title = name - pings = [] - players = [] - labels = {} - n = 0 - - for version in versions.all(:order => "updated_at DESC", :limit => 30).reverse - pings << version.ping.to_i - players << version.players.to_i - labels[n] = version.updated_at.strftime("%H:%M") if n % 3 == 0 - n = n + 1 - end - - graph.theme_37signals - graph.data("Ping", pings, '#057fc0') - graph.data("Players", players, '#ff0000') - graph.labels = labels - graph.write(graphfile) - end - - def default_record - # if self.default - # rcon_exec "record demos/auto-" + Verification.uncrap(default.name) - # rcon_exec "serverpassword " + default.password - # rcon_exec "connect " + default.addr - # end -end - -def is_free time - challenges.around(time).pending.count == 0 and matches.around(time).count == 0 -end - -def can_create? cuser - cuser -end - -def can_update? cuser - cuser and cuser.admin? or user == cuser -end - -def can_destroy? cuser - cuser and cuser.admin? -end - -def self.refresh - servers = "" - Server.hlds.active.all.each do |server| - servers << " -a2s " + server.ip + ":" + server.port.to_s + def domains + {DOMAIN_HLTV => "HLTV", DOMAIN_HLDS => "NS Server", DOMAIN_NS2 => "NS2 Server"} end - file = File.join(Rails.root, TMPFILE) - system "#{QSTAT} -xml #{servers} | grep -v '' > #{file}" + def to_s + name + end - doc = REXML::Document.new(File.new(file).read) - doc.elements.each('qstat/server') do |server| - hostname = server.elements['hostname'].text.split(':', 2) - if s = Server.active.first(:conditions => {:ip => hostname[0], :port => hostname[1]}) - if server.elements.include? 'map' - s.map = server.elements['map'].text - s.players = server.elements['numplayers'].text.to_i - s.max_players = server.elements['maxplayers'].text.to_i - s.ping = server.elements['ping'].text - s.map = server.elements['map'].text - s.save - s.make_stats + def addr + ip + ":" + port.to_s + end + + def set_category + self.category_id = (domain == DOMAIN_NS2 ? 45 : 44 ) + end + + def save_demos + dir = case recordable_type + when "Match" then + recordable.contest.demos + when "Gather" then + Directory.find(Directory::DEMOS_GATHERS) + end + + dir ||= Directory.find(Directory::DEMOS_DEFAULT) + zip_path = File.join(dir.path, recording + ".zip") + + Zip::ZipOutputStream::open(zip_path) do |zos| + if recordable_type == "Match" + zos.put_next_entry "readme.txt" + zos.write "Team1: " + recordable.contester1.to_s + "\r\n" + zos.write "Team2: " + recordable.contester2.to_s + "\r\n" + zos.write "Date: " + recordable.match_time.to_s + "\r\n" + zos.write "Contest: " + recordable.contest.to_s + "\r\n" + zos.write "Server: " + recordable.server.addr + "\r\n" if recordable.server + zos.write "HLTV: " + addr + "\r\n" + zos.write YAML::dump(recordable.attributes).to_s + end + Dir.glob("#{DEMOS}/*").each do |file| + if File.file?(file) and file.match(/#{recording}.*\.dem/) + zos.put_next_entry File.basename(file) + zos.write(IO.read(file)) + end + end + end + + DataFile.transaction do + unless dbfile = DataFile.find_by_path(zip_path) + dbfile = DataFile.new + dbfile.path = zip_path + dbfile.directory = dir + dbfile.save! + DataFile.update_all({:name => File.basename(zip_path)}, {:id => dbfile.id}) + end + if recordable_type == "Match" + recordable.demo = dbfile + recordable.save end end end - servers = "" - Server.hltvs.reserved.each do |server| - servers << " -a2s #{server.reservation}" + def is_free time + challenges.around(time).pending.count == 0 and matches.around(time).count == 0 end - doc = REXML::Document.new(`#{QSTAT} -xml #{servers} | grep -v ''`) - doc.elements.each('qstat/server') do |server| - hostname = server.elements['hostname'].text.split(':', 2) - if s = Server.hltvs.reserved.first(:conditions => {:ip => hostname[0], :port => hostname[1]}) - if server.elements['numplayers'].text.to_i > 0 - s.update_attribute :idle, DateTime.now - elsif (s.idle + HLTV_IDLE).past? - s.reservation = nil - s.save - end + def can_create? cuser + cuser + end + + def can_update? cuser + cuser and cuser.admin? or user == cuser + end + + def can_destroy? cuser + cuser and cuser.admin? + end + + def self.move addr, newaddr, newpwd + self.hltvs.all(:conditions => {:reservation => addr}).each do |hltv| + hltv.reservation = newaddr + hltv.pwd = newpwd + hltv.save! + end + end + + def self.stop addr + self.hltvs.all(:conditions => {:reservation => addr}).each do |hltv| + hltv.reservation = nil + hltv.save! end end end - -def self.move addr, newaddr, newpwd - self.hltvs.all(:conditions => {:reservation => addr}).each do |hltv| - hltv.reservation = newaddr - hltv.pwd = newpwd - hltv.save! - end -end - -def self.stop addr - self.hltvs.all(:conditions => {:reservation => addr}).each do |hltv| - hltv.reservation = nil - hltv.save! - end -end -end From 64e0ed662c5423b4099e1313bc2c5e7c522987fb Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:20:37 +0100 Subject: [PATCH 04/13] Admin route never used --- app/views/servers/admin.html.erb | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 app/views/servers/admin.html.erb diff --git a/app/views/servers/admin.html.erb b/app/views/servers/admin.html.erb deleted file mode 100644 index cbd8fb2..0000000 --- a/app/views/servers/admin.html.erb +++ /dev/null @@ -1,19 +0,0 @@ -

- RCON: <%= h @server %> -

- -<%= image_tag "icons/spinner.gif", - :align => "absmiddle", - :id => "spinner", - :style =>"display: none;" %> - -
- <%= render :partial => "response" %> -
- -<% form_tag remote: true, update: 'serverLog', - :before => "Element.show('spinner')", - :success => "Element.hide('spinner'); $('serverLog').scrollTop = $('serverLog').scrollHeight;" do %> - <%= label_tag :query, "Rcon Command:" %> - <%= text_field_tag "query", params['query'], :size => 30 %> -<% end %> From a520f2e671d612551a67da366e9215841693fa8b Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:20:41 +0100 Subject: [PATCH 05/13] Remove rcon --- vendor/plugins/rcon/bin/rcontool | 296 ------- vendor/plugins/rcon/lib/rcon.rb | 499 ----------- vendor/plugins/rcon/rcon.gemspec | 13 - vendor/plugins/rcon/setup.rb | 1360 ------------------------------ 4 files changed, 2168 deletions(-) delete mode 100644 vendor/plugins/rcon/bin/rcontool delete mode 100644 vendor/plugins/rcon/lib/rcon.rb delete mode 100644 vendor/plugins/rcon/rcon.gemspec delete mode 100644 vendor/plugins/rcon/setup.rb diff --git a/vendor/plugins/rcon/bin/rcontool b/vendor/plugins/rcon/bin/rcontool deleted file mode 100644 index 8734dba..0000000 --- a/vendor/plugins/rcon/bin/rcontool +++ /dev/null @@ -1,296 +0,0 @@ -#!/usr/bin/env ruby -################################################################ -# -# rcontool - shell interface to rcon commands -# -# (C) 2006 Erik Hollensbe, License details below -# -# Use 'rcontool -h' for usage instructions. -# -# The compilation of software known as rcontool is distributed under the -# following terms: -# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved. -# -# Redistribution and use in source form, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -# -# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -# -################################################################ - -# -# rubygems hack -# - -begin - require 'rubygems' -rescue LoadError => e -end -begin - require 'rcon' - require 'ip' -rescue LoadError => e - $stderr.puts "rcontool requires the rcon and ip libraries be installed." - $stderr.puts "You can find them both via rubygems or at http://rubyforge.org." - exit -1 -end - -RCONTOOL_VERSION = '0.1.0' - -require 'optparse' -require 'ostruct' - -# -# Manages our options -# - -def get_options - options = OpenStruct.new - # ip address (IP::Address object) - options.ip_address = nil - # port (integer) - options.port = nil - # password - options.password = nil - # protocol type (one of :hlds, :source, :oldquake, :newquake) - options.protocol_type = nil - # verbose, spit out extra information - options.verbose = false - # command to execute on the server - options.command = nil - - optparse = OptionParser.new do |opts| - opts.banner = "Usage: #{File.basename $0} [options]" - opts.separator "" - opts.separator "Options:" - - opts.on("--ip-address [ADDRESS]", - "Provide an IP address to connect to. Does not take a port.") do |ip_address| - if ! options.ip_address.nil? - $stderr.puts "Error: you have already provided an IP Address." - $stderr.puts opts - exit -1 - end - - options.ip_address = IP::Address.new(ip_address) - end - - opts.on("-r", "--port [PORT]", - "Port to connect to.") do |port| - if ! options.port.nil? - $stderr.puts "Error: you have already provided a port." - $stderr.puts opts - exit -1 - end - - options.port = port.to_i - end - - opts.on("-c", "--command [COMMAND]", - "Command to run on the server.") do |command| - if ! options.command.nil? - $stderr.puts "Error: you have already provided a command." - $stderr.puts opts - exit -1 - end - - options.command = command - end - - opts.on("-p", "--password [PASSWORD]", - "Provide a password on the command line.") do |password| - options.password = password - end - - opts.on("-f", "--password-from [FILENAME]", - "Get the password from a file (use '/dev/fd/0' or '/dev/stdin' to read from Standard Input).") do |filename| - if !filename.nil? - f = File.open(filename) - options.password = f.gets.chomp - f.close - else - $stderr.puts "Error: filename (from -f) is not valid." - $stderr.puts opts - exit -1 - end - end - - opts.on("-t", "--protocol-type [TYPE]", [:hlds, :source, :oldquake, :newquake], - "Type of rcon connection to make: (hlds, source, oldquake, newquake).", - " Note: oldquake is quake1/quakeworld, newquake is quake2/3.") do |protocol_type| - options.protocol_type = protocol_type - end - - opts.on("-v", "--[no-]verbose", - "Run verbosely, print information about each packet recieved and turnaround times.") do |verbose| - options.verbose = verbose - end - - opts.on("-h", "--help", - "This help message.") do - $stderr.puts opts - exit -1 - end - - opts.on("--version", "Print the version information.") do - $stderr.puts "This is rcontool version #{RCONTOOL_VERSION}," - $stderr.puts "it is located at #{File.expand_path $0}." - exit -1 - end - - opts.separator "" - opts.separator "Note: IP, port, protocol type, password and command are required to function." - opts.separator "" - opts.separator "Examples (all are equivalent):" - opts.separator "\t#{File.basename($0)} 10.0.0.11 status -t hlds -r 27015 -p foobar" - opts.separator "\techo 'foobar' | #{File.basename($0)} 10.0.0.11:27015 status -t hlds -f /dev/stdin" - opts.separator "\t#{File.basename($0)} --ip-address 10.0.0.11 --port 27015 -c status -t hlds -f file_with_password" - opts.separator "" - - end - - ################################################################ - # - # This hackery is to help facilitate the bareword options if - # they exist, while still allowing for the option parser - # to work properly. - # - ################################################################ - - s1 = ARGV.shift - s2 = ARGV.shift - - begin - options.ip_address = IP::Address::IPv4.new(s1) - options.command = s2 - rescue IP::AddressException => e - # attempt to split it first... not sure how to best handle this situation - begin - ip,port = s1.split(/:/, 2) - options.ip_address = IP::Address::IPv4.new(ip) - options.port = port.to_i - options.command = s2 - rescue Exception => e - end - - if [options.ip_address, options.port].include? nil - ARGV.unshift(s2) - ARGV.unshift(s1) - end - end - - optparse.parse! - - if [options.ip_address, options.protocol_type, options.port, options.password, options.command].include? nil - $stderr.puts optparse - exit -1 - end - - return options -end - -def verbose(string) - $stderr.puts string if $options.verbose -end - -def dump_source_packet(packet) - if $options.verbose - verbose "Request ID: #{packet.request_id}" - verbose "Packet Size: #{packet.packet_size}" - verbose "Response Type: #{packet.command_type}" - end -end - -################################################################ -# -# start main block -# -################################################################ - -$options = get_options - -################################################################ -# -# Source query -# -################################################################ - -if $options.protocol_type == :source - verbose "Protocol type 'SOURCE' selected." - - rcon = RCon::Query::Source.new($options.ip_address.ip_address, $options.port) - - # if we have a verbose request, give all the information we can about - # the query, including the packet information. - rcon.return_packets = $options.verbose - - verbose "Attempting authentication to #{$options.ip_address.ip_address}:#{$options.port} with password '#{$options.password}'" - - value = rcon.auth $options.password - - dump_source_packet value - - if ($options.verbose && value.command_type == RCon::Packet::Source::RESPONSE_AUTH) || value - verbose "Authentication succeeded. Sending command: '#{$options.command}'" - - value = rcon.command $options.command - - dump_source_packet value - verbose "" - - if $options.verbose - puts value.string1 - else - puts value - end - - exit 0 - else - $stderr.puts "Authentication failed." - exit 1 - end - -################################################################ -# -# Original Query -# -################################################################ - -else - rcon = nil - case $options.protocol_type - when :hlds - verbose "Protocol type 'HLDS' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::HLDS) - when :oldquake - verbose "Protocol type 'OLDQUAKE' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::QUAKEWORLD) - when :newquake - verbose "Protocol type 'NEWQUAKE' selected" - rcon = RCon::Query::Original.new($options.ip_address.ip_address, $options.port, $options.password, - RCon::Query::Original::NEWQUAKE) - end - verbose "Attempting transmission to #{$options.ip_address.ip_address}:#{$options.port}" - verbose "Using password: '#{$options.password}' and sending command: '#{$options.command}'" - verbose "" - string = rcon.command($options.command) - - puts string - exit 0 -end - diff --git a/vendor/plugins/rcon/lib/rcon.rb b/vendor/plugins/rcon/lib/rcon.rb deleted file mode 100644 index 9977135..0000000 --- a/vendor/plugins/rcon/lib/rcon.rb +++ /dev/null @@ -1,499 +0,0 @@ -# encoding: US-ASCII - -require 'socket' - -# -# RCon is a module to work with Quake 1/2/3, Half-Life, and Half-Life -# 2 (Source Engine) RCon (Remote Console) protocols. -# -# Version:: 0.2.0 -# Author:: Erik Hollensbe -# License:: BSD -# Contact:: erik@hollensbe.org -# Copyright:: Copyright (c) 2005-2006 Erik Hollensbe -# -# The relevant modules to query RCon are in the RCon::Query namespace, -# under RCon::Query::Original (for Quake 1/2/3 and Half-Life), and -# RCon::Query::Source (for HL2 and CS: Source, and other Source Engine -# games). The RCon::Packet namespace is used to manage complex packet -# structures if required. The Original protocol does not require -# this, but Source does. -# -# Usage is fairly simple: -# -# # Note: Other classes have different constructors -# -# rcon = RCon::Query::Source.new("10.0.0.1", 27015) -# -# rcon.auth("foobar") # source only -# -# rcon.command("mp_friendlyfire") => "mp_friendlyfire = 1" -# -# rcon.cvar("mp_friendlyfire") => 1 -# -#-- -# -# The compilation of software known as rcon.rb is distributed under the -# following terms: -# Copyright (C) 2005-2006 Erik Hollensbe. All rights reserved. -# -# Redistribution and use in source form, with or without -# modification, are permitted provided that the following conditions -# are met: -# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. -# -# THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND -# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -# ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -# SUCH DAMAGE. -# -#++ - - -class RCon - class Packet - # placeholder so ruby doesn't bitch - end - class Query - - # - # Convenience method to scrape input from cvar output and return that data. - # Returns integers as a numeric type if possible. - # - # ex: rcon.cvar("mp_friendlyfire") => 1 - # - - def cvar(cvar_name) - response = command(cvar_name) - match = /^.+?\s(?:is|=)\s"([^"]+)".*$/.match response - match = match[1] - if /\D/.match match - return match - else - return match.to_i - end - end - end -end - -# -# RCon::Packet::Source generates a packet structure useful for -# RCon::Query::Source protocol queries. -# -# This class is primarily used internally, but is available if you -# want to do something more advanced with the Source RCon -# protocol. -# -# Use at your own risk. -# - -class RCon::Packet::Source - # execution command - COMMAND_EXEC = 2 - # auth command - COMMAND_AUTH = 3 - # auth response - RESPONSE_AUTH = 2 - # normal response - RESPONSE_NORM = 0 - # packet trailer - TRAILER = "\x00\x00" - - # size of the packet (10 bytes for header + string1 length) - attr_accessor :packet_size - # Request Identifier, used in managing multiple requests at once - attr_accessor :request_id - # Type of command, normally COMMAND_AUTH or COMMAND_EXEC. In response packets, RESPONSE_AUTH or RESPONSE_NORM - attr_accessor :command_type - # First string, the only used one in the protocol, contains - # commands and responses. Null terminated. - attr_accessor :string1 - # Second string, unused by the protocol. Null terminated. - attr_accessor :string2 - - # - # Generate a command packet to be sent to an already - # authenticated RCon connection. Takes the command as an - # argument. - # - def command(string) - @request_id = rand(1000) - @string1 = string - @string2 = TRAILER - @command_type = COMMAND_EXEC - - @packet_size = build_packet.length - - return self - end - - # - # Generate an authentication packet to be sent to a newly - # started RCon connection. Takes the RCon password as an - # argument. - # - def auth(string) - @request_id = rand(1000) - @string1 = string - @string2 = TRAILER - @command_type = COMMAND_AUTH - - @packet_size = build_packet.length - - return self - end - - # - # Builds a packet ready to deliver, without the size prepended. - # Used to calculate the packet size, use #to_s to get the packet - # that srcds actually needs. - # - def build_packet - return [@request_id, @command_type, @string1, @string2].pack("VVa#{@string1.length}a2") - end - - # Returns a string representation of the packet, useful for - # sending and debugging. This include the packet size. - def to_s - packet = build_packet - @packet_size = packet.length - return [@packet_size].pack("V") + packet - end - -end - -# -# RCon::Query::Original queries Quake 1/2/3 and Half-Life servers -# with the rcon protocol. This protocol travels over UDP to the -# game server port, and requires an initial authentication step, -# the information of which is provided at construction time. -# -# Some of the work here (namely the RCon packet structure) was taken -# from the KKRcon code, which is written in perl. -# -# One query per authentication is allowed. -# - -class RCon::Query::Original < RCon::Query - # HLDS-Based Servers - HLDS = "l" - # QuakeWorld/Quake 1 Servers - QUAKEWORLD = "n" - # Quake 2/3 Servers - NEWQUAKE = "" - - # Request to be sent to server - attr_reader :request - # Response from server - attr_reader :response - # Challenge ID (served by server-side of connection) - attr_reader :challenge_id - # UDPSocket object - attr_reader :socket - # Host of connection - attr_reader :host - # Port of connection - attr_reader :port - # RCon password - attr_reader :password - # type of server - attr_reader :server_type - - # - # Creates a RCon::Query::Original object for use. - # - # The type (the default of which is HLDS), has multiple possible - # values: - # - # HLDS - Half Life 1 (will not work with older versions of HLDS) - # - # QUAKEWORLD - QuakeWorld/Quake 1 - # - # NEWQUAKE - Quake 2/3 (and many derivatives) - # - - def initialize(host, port, password, type=HLDS) - @host = host - @port = port - @password = password - @server_type = type - end - - # - # Sends a request given as the argument, and returns the - # response as a string. - # - def command(request) - @request = request - @challenge_id = nil - - establish_connection - - @socket.print "\xFF" * 4 + "challenge rcon\n\x00" - - tmp = retrieve_socket_data - challenge_id = /challenge rcon (\d+)/.match tmp - if challenge_id - @challenge_id = challenge_id[1] - end - - if @challenge_id.nil? - raise RCon::NetworkException.new("RCon challenge ID never returned: wrong rcon password?") - end - - @socket.print "\xFF" * 4 + "rcon #{@challenge_id} \"#{@password}\" #{@request}\n\x00" - @response = retrieve_socket_data - - @response.sub!(/^\xFF\xFF\xFF\xFF#{@server_type}/, "") - @response.sub!(/\x00+$/, "") - - return @response - end - - # - # Disconnects the RCon connection. - # - def disconnect - if @socket - @socket.close - @socket = nil - end - end - - protected - - # - # Establishes the connection. - # - def establish_connection - if @socket.nil? - @socket = UDPSocket.new - @socket.connect(@host, @port) - end - end - - # - # Generic method to pull data from the socket. - # - - def retrieve_socket_data - return "" if @socket.nil? - - retval = "" - loop do - break unless IO.select([@socket], nil, nil, 10) - packet = @socket.recv(8192) - retval << packet - break if packet.length < 8192 - end - - return retval - end - -end - -# -# RCon::Query::Source sends queries to a "Source" Engine server, -# such as Half-Life 2: Deathmatch, Counter-Strike: Source, or Day -# of Defeat: Source. -# -# Note that one authentication packet needs to be sent to send -# multiple commands. Sending multiple authentication packets may -# damage the current connection and require it to be reset. -# -# Note: If the attribute 'return_packets' is set to true, the full -# RCon::Packet::Source object is returned, instead of just a string -# with the headers stripped. Useful for debugging. -# - -class RCon::Query::Source < RCon::Query - # RCon::Packet::Source object that was sent as a result of the last query - attr_reader :packet - # TCPSocket object - attr_reader :socket - # Host of connection - attr_reader :host - # Port of connection - attr_reader :port - # Authentication Status - attr_reader :authed - # return full packet, or just data? - attr_accessor :return_packets - - # - # Given a host and a port (dotted-quad or hostname OK), creates - # a RCon::Query::Source object. Note that this will still - # require an authentication packet (see the auth() method) - # before commands can be sent. - # - - def initialize(host, port) - @host = host - @port = port - @socket = nil - @packet = nil - @authed = false - @return_packets = false - end - - # - # See RCon::Query#cvar. - # - - def cvar(cvar_name) - return_packets = @return_packets - @return_packets = false - response = super - @return_packets = return_packets - return response - end - - # - # Sends a RCon command to the server. May be used multiple times - # after an authentication is successful. - # - # See the class-level documentation on the 'return_packet' attribute - # for return values. The default is to return a string containing - # the response. - # - - def command(command) - - if ! @authed - raise RCon::NetworkException.new("You must authenticate the connection successfully before sending commands.") - end - - @packet = RCon::Packet::Source.new - @packet.command(command) - - @socket.print @packet.to_s - rpacket = build_response_packet - - if rpacket.command_type != RCon::Packet::Source::RESPONSE_NORM - raise RCon::NetworkException.new("error sending command: #{rpacket.command_type}") - end - - if @return_packets - return rpacket - else - return rpacket.string1 - end - end - - # - # Requests authentication from the RCon server, given a - # password. Is only expected to be used once. - # - # See the class-level documentation on the 'return_packet' attribute - # for return values. The default is to return a true value if auth - # succeeded. - # - - def auth(password) - establish_connection - - @packet = RCon::Packet::Source.new - @packet.auth(password) - - @socket.print @packet.to_s - # on auth, one junk packet is sent - rpacket = nil - 2.times { rpacket = build_response_packet } - - if rpacket.command_type != RCon::Packet::Source::RESPONSE_AUTH - raise RCon::NetworkException.new("error authenticating: #{rpacket.command_type}") - end - - @authed = true - if @return_packets - return rpacket - else - return true - end - end - - alias_method :authenticate, :auth - - # - # Disconnects from the Source server. - # - - def disconnect - if @socket - @socket.close - @socket = nil - @authed = false - end - end - - protected - - # - # Builds a RCon::Packet::Source packet based on the response - # given by the server. - # - def build_response_packet - rpacket = RCon::Packet::Source.new - total_size = 0 - request_id = 0 - type = 0 - response = "" - message = "" - - - loop do - break unless IO.select([@socket], nil, nil, 10) - - # - # TODO: clean this up - read everything and then unpack. - # - - tmp = @socket.recv(14) - if tmp.nil? - return nil - end - size, request_id, type, message = tmp.unpack("VVVa*") - total_size += size - - # special case for authentication - break if message.sub!(/\x00\x00$/, "") - - response << message - - # the 'size - 10' here accounts for the fact that we've snarfed 14 bytes, - # the size (which is 4 bytes) is not counted, yet represents the rest - # of the packet (which we have already taken 10 bytes from) - - tmp = @socket.recv(size - 10) - response << tmp - response.sub!(/\x00\x00$/, "") - end - - rpacket.packet_size = total_size - rpacket.request_id = request_id - rpacket.command_type = type - - # strip nulls (this is actually the end of string1 and string2) - rpacket.string1 = response.sub(/\x00\x00$/, "") - return rpacket - end - - # establishes a connection to the server. - def establish_connection - if @socket.nil? - @socket = TCPSocket.new(@host, @port) - end - end - -end - -# Exception class for network errors -class RCon::NetworkException < Exception -end diff --git a/vendor/plugins/rcon/rcon.gemspec b/vendor/plugins/rcon/rcon.gemspec deleted file mode 100644 index 03527ca..0000000 --- a/vendor/plugins/rcon/rcon.gemspec +++ /dev/null @@ -1,13 +0,0 @@ -spec = Gem::Specification.new -spec.name = "rcon" -spec.version = "0.2.1" -spec.author = "Erik Hollensbe" -spec.email = "erik@hollensbe.org" -spec.summary = "Ruby class to work with Quake 1/2/3, Half-Life and Source Engine rcon (remote console)" -spec.has_rdoc = true -spec.autorequire = "rcon" -spec.bindir = 'bin' -spec.executables << 'rcontool' -spec.add_dependency('ip', '>= 0.2.1') -spec.files = Dir['lib/rcon.rb'] + Dir['bin/rcontool'] -spec.rubyforge_project = 'rcon' diff --git a/vendor/plugins/rcon/setup.rb b/vendor/plugins/rcon/setup.rb deleted file mode 100644 index 0807023..0000000 --- a/vendor/plugins/rcon/setup.rb +++ /dev/null @@ -1,1360 +0,0 @@ -# -# setup.rb -# -# Copyright (c) 2000-2004 Minero Aoki -# -# This program is free software. -# You can distribute/modify this program under the terms of -# the GNU LGPL, Lesser General Public License version 2.1. -# - -unless Enumerable.method_defined?(:map) # Ruby 1.4.6 - module Enumerable - alias map collect - end -end - -unless File.respond_to?(:read) # Ruby 1.6 - def File.read(fname) - open(fname) {|f| - return f.read - } - end -end - -def File.binread(fname) - open(fname, 'rb') {|f| - return f.read - } -end - -# for corrupted windows stat(2) -def File.dir?(path) - File.directory?((path[-1,1] == '/') ? path : path + '/') -end - - -class SetupError < StandardError; end - -def setup_rb_error(msg) - raise SetupError, msg -end - -# -# Config -# - -if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } - ARGV.delete(arg) - require arg.split(/=/, 2)[1] - $".push 'rbconfig.rb' -else - require 'rbconfig' -end - -def multipackage_install? - FileTest.directory?(File.dirname($0) + '/packages') -end - - -class ConfigItem - def initialize(name, template, default, desc) - @name = name.freeze - @template = template - @value = default - @default = default.dup.freeze - @description = desc - end - - attr_reader :name - attr_reader :description - - attr_accessor :default - alias help_default default - - def help_opt - "--#{@name}=#{@template}" - end - - def value - @value - end - - def eval(table) - @value.gsub(%r<\$([^/]+)>) { table[$1] } - end - - def set(val) - @value = check(val) - end - - private - - def check(val) - setup_rb_error "config: --#{name} requires argument" unless val - val - end -end - -class BoolItem < ConfigItem - def config_type - 'bool' - end - - def help_opt - "--#{@name}" - end - - private - - def check(val) - return 'yes' unless val - unless /\A(y(es)?|n(o)?|t(rue)?|f(alse))\z/i =~ val - setup_rb_error "config: --#{@name} accepts only yes/no for argument" - end - (/\Ay(es)?|\At(rue)/i =~ value) ? 'yes' : 'no' - end -end - -class PathItem < ConfigItem - def config_type - 'path' - end - - private - - def check(path) - setup_rb_error "config: --#{@name} requires argument" unless path - path[0,1] == '$' ? path : File.expand_path(path) - end -end - -class ProgramItem < ConfigItem - def config_type - 'program' - end -end - -class SelectItem < ConfigItem - def initialize(name, template, default, desc) - super - @ok = template.split('/') - end - - def config_type - 'select' - end - - private - - def check(val) - unless @ok.include?(val.strip) - setup_rb_error "config: use --#{@name}=#{@template} (#{val})" - end - val.strip - end -end - -class PackageSelectionItem < ConfigItem - def initialize(name, template, default, help_default, desc) - super name, template, default, desc - @help_default = help_default - end - - attr_reader :help_default - - def config_type - 'package' - end - - private - - def check(val) - unless File.dir?("packages/#{val}") - setup_rb_error "config: no such package: #{val}" - end - val - end -end - -class ConfigTable_class - - def initialize(items) - @items = items - @table = {} - items.each do |i| - @table[i.name] = i - end - ALIASES.each do |ali, name| - @table[ali] = @table[name] - end - end - - include Enumerable - - def each(&block) - @items.each(&block) - end - - def key?(name) - @table.key?(name) - end - - def lookup(name) - @table[name] or raise ArgumentError, "no such config item: #{name}" - end - - def add(item) - @items.push item - @table[item.name] = item - end - - def remove(name) - item = lookup(name) - @items.delete_if {|i| i.name == name } - @table.delete_if {|name, i| i.name == name } - item - end - - def new - dup() - end - - def savefile - '.config' - end - - def load - begin - t = dup() - File.foreach(savefile()) do |line| - k, v = *line.split(/=/, 2) - t[k] = v.strip - end - t - rescue Errno::ENOENT - setup_rb_error $!.message + "#{File.basename($0)} config first" - end - end - - def save - @items.each {|i| i.value } - File.open(savefile(), 'w') {|f| - @items.each do |i| - f.printf "%s=%s\n", i.name, i.value if i.value - end - } - end - - def [](key) - lookup(key).eval(self) - end - - def []=(key, val) - lookup(key).set val - end - -end - -c = ::Config::CONFIG - -rubypath = c['bindir'] + '/' + c['ruby_install_name'] - -major = c['MAJOR'].to_i -minor = c['MINOR'].to_i -teeny = c['TEENY'].to_i -version = "#{major}.#{minor}" - -# ruby ver. >= 1.4.4? -newpath_p = ((major >= 2) or - ((major == 1) and - ((minor >= 5) or - ((minor == 4) and (teeny >= 4))))) - -if c['rubylibdir'] - # V < 1.6.3 - _stdruby = c['rubylibdir'] - _siteruby = c['sitedir'] - _siterubyver = c['sitelibdir'] - _siterubyverarch = c['sitearchdir'] -elsif newpath_p - # 1.4.4 <= V <= 1.6.3 - _stdruby = "$prefix/lib/ruby/#{version}" - _siteruby = c['sitedir'] - _siterubyver = "$siteruby/#{version}" - _siterubyverarch = "$siterubyver/#{c['arch']}" -else - # V < 1.4.4 - _stdruby = "$prefix/lib/ruby/#{version}" - _siteruby = "$prefix/lib/ruby/#{version}/site_ruby" - _siterubyver = _siteruby - _siterubyverarch = "$siterubyver/#{c['arch']}" -end -libdir = '-* dummy libdir *-' -stdruby = '-* dummy rubylibdir *-' -siteruby = '-* dummy site_ruby *-' -siterubyver = '-* dummy site_ruby version *-' -parameterize = lambda {|path| - path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix')\ - .sub(/\A#{Regexp.quote(libdir)}/, '$libdir')\ - .sub(/\A#{Regexp.quote(stdruby)}/, '$stdruby')\ - .sub(/\A#{Regexp.quote(siteruby)}/, '$siteruby')\ - .sub(/\A#{Regexp.quote(siterubyver)}/, '$siterubyver') -} -libdir = parameterize.call(c['libdir']) -stdruby = parameterize.call(_stdruby) -siteruby = parameterize.call(_siteruby) -siterubyver = parameterize.call(_siterubyver) -siterubyverarch = parameterize.call(_siterubyverarch) - -if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } - makeprog = arg.sub(/'/, '').split(/=/, 2)[1] -else - makeprog = 'make' -end - -common_conf = [ - PathItem.new('prefix', 'path', c['prefix'], - 'path prefix of target environment'), - PathItem.new('bindir', 'path', parameterize.call(c['bindir']), - 'the directory for commands'), - PathItem.new('libdir', 'path', libdir, - 'the directory for libraries'), - PathItem.new('datadir', 'path', parameterize.call(c['datadir']), - 'the directory for shared data'), - PathItem.new('mandir', 'path', parameterize.call(c['mandir']), - 'the directory for man pages'), - PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), - 'the directory for man pages'), - PathItem.new('stdruby', 'path', stdruby, - 'the directory for standard ruby libraries'), - PathItem.new('siteruby', 'path', siteruby, - 'the directory for version-independent aux ruby libraries'), - PathItem.new('siterubyver', 'path', siterubyver, - 'the directory for aux ruby libraries'), - PathItem.new('siterubyverarch', 'path', siterubyverarch, - 'the directory for aux ruby binaries'), - PathItem.new('rbdir', 'path', '$siterubyver', - 'the directory for ruby scripts'), - PathItem.new('sodir', 'path', '$siterubyverarch', - 'the directory for ruby extentions'), - PathItem.new('rubypath', 'path', rubypath, - 'the path to set to #! line'), - ProgramItem.new('rubyprog', 'name', rubypath, - 'the ruby program using for installation'), - ProgramItem.new('makeprog', 'name', makeprog, - 'the make program to compile ruby extentions'), - SelectItem.new('shebang', 'all/ruby/never', 'ruby', - 'shebang line (#!) editing mode'), - BoolItem.new('without-ext', 'yes/no', 'no', - 'does not compile/install ruby extentions') -] -class ConfigTable_class # open again - ALIASES = { - 'std-ruby' => 'stdruby', - 'site-ruby-common' => 'siteruby', # For backward compatibility - 'site-ruby' => 'siterubyver', # For backward compatibility - 'bin-dir' => 'bindir', - 'bin-dir' => 'bindir', - 'rb-dir' => 'rbdir', - 'so-dir' => 'sodir', - 'data-dir' => 'datadir', - 'ruby-path' => 'rubypath', - 'ruby-prog' => 'rubyprog', - 'ruby' => 'rubyprog', - 'make-prog' => 'makeprog', - 'make' => 'makeprog' - } -end -multipackage_conf = [ - PackageSelectionItem.new('with', 'name,name...', '', 'ALL', - 'package names that you want to install'), - PackageSelectionItem.new('without', 'name,name...', '', 'NONE', - 'package names that you do not want to install') -] -if multipackage_install? - ConfigTable = ConfigTable_class.new(common_conf + multipackage_conf) -else - ConfigTable = ConfigTable_class.new(common_conf) -end - - -module MetaConfigAPI - - def eval_file_ifexist(fname) - instance_eval File.read(fname), fname, 1 if File.file?(fname) - end - - def config_names - ConfigTable.map {|i| i.name } - end - - def config?(name) - ConfigTable.key?(name) - end - - def bool_config?(name) - ConfigTable.lookup(name).config_type == 'bool' - end - - def path_config?(name) - ConfigTable.lookup(name).config_type == 'path' - end - - def value_config?(name) - case ConfigTable.lookup(name).config_type - when 'bool', 'path' - true - else - false - end - end - - def add_config(item) - ConfigTable.add item - end - - def add_bool_config(name, default, desc) - ConfigTable.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) - end - - def add_path_config(name, default, desc) - ConfigTable.add PathItem.new(name, 'path', default, desc) - end - - def set_config_default(name, default) - ConfigTable.lookup(name).default = default - end - - def remove_config(name) - ConfigTable.remove(name) - end - -end - - -# -# File Operations -# - -module FileOperations - - def mkdir_p(dirname, prefix = nil) - dirname = prefix + File.expand_path(dirname) if prefix - $stderr.puts "mkdir -p #{dirname}" if verbose? - return if no_harm? - - # does not check '/'... it's too abnormal case - dirs = File.expand_path(dirname).split(%r<(?=/)>) - if /\A[a-z]:\z/i =~ dirs[0] - disk = dirs.shift - dirs[0] = disk + dirs[0] - end - dirs.each_index do |idx| - path = dirs[0..idx].join('') - Dir.mkdir path unless File.dir?(path) - end - end - - def rm_f(fname) - $stderr.puts "rm -f #{fname}" if verbose? - return if no_harm? - - if File.exist?(fname) or File.symlink?(fname) - File.chmod 0777, fname - File.unlink fname - end - end - - def rm_rf(dn) - $stderr.puts "rm -rf #{dn}" if verbose? - return if no_harm? - - Dir.chdir dn - Dir.foreach('.') do |fn| - next if fn == '.' - next if fn == '..' - if File.dir?(fn) - verbose_off { - rm_rf fn - } - else - verbose_off { - rm_f fn - } - end - end - Dir.chdir '..' - Dir.rmdir dn - end - - def move_file(src, dest) - File.unlink dest if File.exist?(dest) - begin - File.rename src, dest - rescue - File.open(dest, 'wb') {|f| f.write File.binread(src) } - File.chmod File.stat(src).mode, dest - File.unlink src - end - end - - def install(from, dest, mode, prefix = nil) - $stderr.puts "install #{from} #{dest}" if verbose? - return if no_harm? - - realdest = prefix ? prefix + File.expand_path(dest) : dest - realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) - str = File.binread(from) - if diff?(str, realdest) - verbose_off { - rm_f realdest if File.exist?(realdest) - } - File.open(realdest, 'wb') {|f| - f.write str - } - File.chmod mode, realdest - - File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| - if prefix - f.puts realdest.sub(prefix, '') - else - f.puts realdest - end - } - end - end - - def diff?(new_content, path) - return true unless File.exist?(path) - new_content != File.binread(path) - end - - def command(str) - $stderr.puts str if verbose? - system str or raise RuntimeError, "'system #{str}' failed" - end - - def ruby(str) - command config('rubyprog') + ' ' + str - end - - def make(task = '') - command config('makeprog') + ' ' + task - end - - def extdir?(dir) - File.exist?(dir + '/MANIFEST') - end - - def all_files_in(dirname) - Dir.open(dirname) {|d| - return d.select {|ent| File.file?("#{dirname}/#{ent}") } - } - end - - REJECT_DIRS = %w( - CVS SCCS RCS CVS.adm .svn - ) - - def all_dirs_in(dirname) - Dir.open(dirname) {|d| - return d.select {|n| File.dir?("#{dirname}/#{n}") } - %w(. ..) - REJECT_DIRS - } - end - -end - - -# -# Main Installer -# - -module HookUtils - - def run_hook(name) - try_run_hook "#{curr_srcdir()}/#{name}" or - try_run_hook "#{curr_srcdir()}/#{name}.rb" - end - - def try_run_hook(fname) - return false unless File.file?(fname) - begin - instance_eval File.read(fname), fname, 1 - rescue - setup_rb_error "hook #{fname} failed:\n" + $!.message - end - true - end - -end - - -module HookScriptAPI - - def get_config(key) - @config[key] - end - - alias config get_config - - def set_config(key, val) - @config[key] = val - end - - # - # srcdir/objdir (works only in the package directory) - # - - #abstract srcdir_root - #abstract objdir_root - #abstract relpath - - def curr_srcdir - "#{srcdir_root()}/#{relpath()}" - end - - def curr_objdir - "#{objdir_root()}/#{relpath()}" - end - - def srcfile(path) - "#{curr_srcdir()}/#{path}" - end - - def srcexist?(path) - File.exist?(srcfile(path)) - end - - def srcdirectory?(path) - File.dir?(srcfile(path)) - end - - def srcfile?(path) - File.file? srcfile(path) - end - - def srcentries(path = '.') - Dir.open("#{curr_srcdir()}/#{path}") {|d| - return d.to_a - %w(. ..) - } - end - - def srcfiles(path = '.') - srcentries(path).select {|fname| - File.file?(File.join(curr_srcdir(), path, fname)) - } - end - - def srcdirectories(path = '.') - srcentries(path).select {|fname| - File.dir?(File.join(curr_srcdir(), path, fname)) - } - end - -end - - -class ToplevelInstaller - - Version = '3.3.1' - Copyright = 'Copyright (c) 2000-2004 Minero Aoki' - - TASKS = [ - [ 'all', 'do config, setup, then install' ], - [ 'config', 'saves your configurations' ], - [ 'show', 'shows current configuration' ], - [ 'setup', 'compiles ruby extentions and others' ], - [ 'install', 'installs files' ], - [ 'clean', "does `make clean' for each extention" ], - [ 'distclean',"does `make distclean' for each extention" ] - ] - - def ToplevelInstaller.invoke - instance().invoke - end - - @singleton = nil - - def ToplevelInstaller.instance - @singleton ||= new(File.dirname($0)) - @singleton - end - - include MetaConfigAPI - - def initialize(ardir_root) - @config = nil - @options = { 'verbose' => true } - @ardir = File.expand_path(ardir_root) - end - - def inspect - "#<#{self.class} #{__id__()}>" - end - - def invoke - run_metaconfigs - case task = parsearg_global() - when nil, 'all' - @config = load_config('config') - parsearg_config - init_installers - exec_config - exec_setup - exec_install - else - @config = load_config(task) - __send__ "parsearg_#{task}" - init_installers - __send__ "exec_#{task}" - end - end - - def run_metaconfigs - eval_file_ifexist "#{@ardir}/metaconfig" - end - - def load_config(task) - case task - when 'config' - ConfigTable.new - when 'clean', 'distclean' - if File.exist?(ConfigTable.savefile) - then ConfigTable.load - else ConfigTable.new - end - else - ConfigTable.load - end - end - - def init_installers - @installer = Installer.new(@config, @options, @ardir, File.expand_path('.')) - end - - # - # Hook Script API bases - # - - def srcdir_root - @ardir - end - - def objdir_root - '.' - end - - def relpath - '.' - end - - # - # Option Parsing - # - - def parsearg_global - valid_task = /\A(?:#{TASKS.map {|task,desc| task }.join '|'})\z/ - - while arg = ARGV.shift - case arg - when /\A\w+\z/ - setup_rb_error "invalid task: #{arg}" unless valid_task =~ arg - return arg - - when '-q', '--quiet' - @options['verbose'] = false - - when '--verbose' - @options['verbose'] = true - - when '-h', '--help' - print_usage $stdout - exit 0 - - when '-v', '--version' - puts "#{File.basename($0)} version #{Version}" - exit 0 - - when '--copyright' - puts Copyright - exit 0 - - else - setup_rb_error "unknown global option '#{arg}'" - end - end - - nil - end - - - def parsearg_no_options - unless ARGV.empty? - setup_rb_error "#{task}: unknown options: #{ARGV.join ' '}" - end - end - - alias parsearg_show parsearg_no_options - alias parsearg_setup parsearg_no_options - alias parsearg_clean parsearg_no_options - alias parsearg_distclean parsearg_no_options - - def parsearg_config - re = /\A--(#{ConfigTable.map {|i| i.name }.join('|')})(?:=(.*))?\z/ - @options['config-opt'] = [] - - while i = ARGV.shift - if /\A--?\z/ =~ i - @options['config-opt'] = ARGV.dup - break - end - m = re.match(i) or setup_rb_error "config: unknown option #{i}" - name, value = *m.to_a[1,2] - @config[name] = value - end - end - - def parsearg_install - @options['no-harm'] = false - @options['install-prefix'] = '' - while a = ARGV.shift - case a - when /\A--no-harm\z/ - @options['no-harm'] = true - when /\A--prefix=(.*)\z/ - path = $1 - path = File.expand_path(path) unless path[0,1] == '/' - @options['install-prefix'] = path - else - setup_rb_error "install: unknown option #{a}" - end - end - end - - def print_usage(out) - out.puts 'Typical Installation Procedure:' - out.puts " $ ruby #{File.basename $0} config" - out.puts " $ ruby #{File.basename $0} setup" - out.puts " # ruby #{File.basename $0} install (may require root privilege)" - out.puts - out.puts 'Detailed Usage:' - out.puts " ruby #{File.basename $0} " - out.puts " ruby #{File.basename $0} [] []" - - fmt = " %-24s %s\n" - out.puts - out.puts 'Global options:' - out.printf fmt, '-q,--quiet', 'suppress message outputs' - out.printf fmt, ' --verbose', 'output messages verbosely' - out.printf fmt, '-h,--help', 'print this message' - out.printf fmt, '-v,--version', 'print version and quit' - out.printf fmt, ' --copyright', 'print copyright and quit' - out.puts - out.puts 'Tasks:' - TASKS.each do |name, desc| - out.printf fmt, name, desc - end - - fmt = " %-24s %s [%s]\n" - out.puts - out.puts 'Options for CONFIG or ALL:' - ConfigTable.each do |item| - out.printf fmt, item.help_opt, item.description, item.help_default - end - out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" - out.puts - out.puts 'Options for INSTALL:' - out.printf fmt, '--no-harm', 'only display what to do if given', 'off' - out.printf fmt, '--prefix=path', 'install path prefix', '$prefix' - out.puts - end - - # - # Task Handlers - # - - def exec_config - @installer.exec_config - @config.save # must be final - end - - def exec_setup - @installer.exec_setup - end - - def exec_install - @installer.exec_install - end - - def exec_show - ConfigTable.each do |i| - printf "%-20s %s\n", i.name, i.value - end - end - - def exec_clean - @installer.exec_clean - end - - def exec_distclean - @installer.exec_distclean - end - -end - - -class ToplevelInstallerMulti < ToplevelInstaller - - include HookUtils - include HookScriptAPI - include FileOperations - - def initialize(ardir) - super - @packages = all_dirs_in("#{@ardir}/packages") - raise 'no package exists' if @packages.empty? - end - - def run_metaconfigs - eval_file_ifexist "#{@ardir}/metaconfig" - @packages.each do |name| - eval_file_ifexist "#{@ardir}/packages/#{name}/metaconfig" - end - end - - def init_installers - @installers = {} - @packages.each do |pack| - @installers[pack] = Installer.new(@config, @options, - "#{@ardir}/packages/#{pack}", - "packages/#{pack}") - end - - with = extract_selection(config('with')) - without = extract_selection(config('without')) - @selected = @installers.keys.select {|name| - (with.empty? or with.include?(name)) \ - and not without.include?(name) - } - end - - def extract_selection(list) - a = list.split(/,/) - a.each do |name| - setup_rb_error "no such package: #{name}" unless @installers.key?(name) - end - a - end - - def print_usage(f) - super - f.puts 'Inluded packages:' - f.puts ' ' + @packages.sort.join(' ') - f.puts - end - - # - # multi-package metaconfig API - # - - attr_reader :packages - - def declare_packages(list) - raise 'package list is empty' if list.empty? - list.each do |name| - raise "directory packages/#{name} does not exist"\ - unless File.dir?("#{@ardir}/packages/#{name}") - end - @packages = list - end - - # - # Task Handlers - # - - def exec_config - run_hook 'pre-config' - each_selected_installers {|inst| inst.exec_config } - run_hook 'post-config' - @config.save # must be final - end - - def exec_setup - run_hook 'pre-setup' - each_selected_installers {|inst| inst.exec_setup } - run_hook 'post-setup' - end - - def exec_install - run_hook 'pre-install' - each_selected_installers {|inst| inst.exec_install } - run_hook 'post-install' - end - - def exec_clean - rm_f ConfigTable.savefile - run_hook 'pre-clean' - each_selected_installers {|inst| inst.exec_clean } - run_hook 'post-clean' - end - - def exec_distclean - rm_f ConfigTable.savefile - run_hook 'pre-distclean' - each_selected_installers {|inst| inst.exec_distclean } - run_hook 'post-distclean' - end - - # - # lib - # - - def each_selected_installers - Dir.mkdir 'packages' unless File.dir?('packages') - @selected.each do |pack| - $stderr.puts "Processing the package `#{pack}' ..." if @options['verbose'] - Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") - Dir.chdir "packages/#{pack}" - yield @installers[pack] - Dir.chdir '../..' - end - end - - def verbose? - @options['verbose'] - end - - def no_harm? - @options['no-harm'] - end - -end - - -class Installer - - FILETYPES = %w( bin lib ext data ) - - include HookScriptAPI - include HookUtils - include FileOperations - - def initialize(config, opt, srcroot, objroot) - @config = config - @options = opt - @srcdir = File.expand_path(srcroot) - @objdir = File.expand_path(objroot) - @currdir = '.' - end - - def inspect - "#<#{self.class} #{File.basename(@srcdir)}>" - end - - # - # Hook Script API base methods - # - - def srcdir_root - @srcdir - end - - def objdir_root - @objdir - end - - def relpath - @currdir - end - - # - # configs/options - # - - def no_harm? - @options['no-harm'] - end - - def verbose? - @options['verbose'] - end - - def verbose_off - begin - save, @options['verbose'] = @options['verbose'], false - yield - ensure - @options['verbose'] = save - end - end - - # - # TASK config - # - - def exec_config - exec_task_traverse 'config' - end - - def config_dir_bin(rel) - end - - def config_dir_lib(rel) - end - - def config_dir_ext(rel) - extconf if extdir?(curr_srcdir()) - end - - def extconf - opt = @options['config-opt'].join(' ') - command "#{config('rubyprog')} #{curr_srcdir()}/extconf.rb #{opt}" - end - - def config_dir_data(rel) - end - - # - # TASK setup - # - - def exec_setup - exec_task_traverse 'setup' - end - - def setup_dir_bin(rel) - all_files_in(curr_srcdir()).each do |fname| - adjust_shebang "#{curr_srcdir()}/#{fname}" - end - end - - def adjust_shebang(path) - return if no_harm? - tmpfile = File.basename(path) + '.tmp' - begin - File.open(path, 'rb') {|r| - first = r.gets - return unless File.basename(config('rubypath')) == 'ruby' - return unless File.basename(first.sub(/\A\#!/, '').split[0]) == 'ruby' - $stderr.puts "adjusting shebang: #{File.basename(path)}" if verbose? - File.open(tmpfile, 'wb') {|w| - w.print first.sub(/\A\#!\s*\S+/, '#! ' + config('rubypath')) - w.write r.read - } - move_file tmpfile, File.basename(path) - } - ensure - File.unlink tmpfile if File.exist?(tmpfile) - end - end - - def setup_dir_lib(rel) - end - - def setup_dir_ext(rel) - make if extdir?(curr_srcdir()) - end - - def setup_dir_data(rel) - end - - # - # TASK install - # - - def exec_install - rm_f 'InstalledFiles' - exec_task_traverse 'install' - end - - def install_dir_bin(rel) - install_files collect_filenames_auto(), "#{config('bindir')}/#{rel}", 0755 - end - - def install_dir_lib(rel) - install_files ruby_scripts(), "#{config('rbdir')}/#{rel}", 0644 - end - - def install_dir_ext(rel) - return unless extdir?(curr_srcdir()) - install_files ruby_extentions('.'), - "#{config('sodir')}/#{File.dirname(rel)}", - 0555 - end - - def install_dir_data(rel) - install_files collect_filenames_auto(), "#{config('datadir')}/#{rel}", 0644 - end - - def install_files(list, dest, mode) - mkdir_p dest, @options['install-prefix'] - list.each do |fname| - install fname, dest, mode, @options['install-prefix'] - end - end - - def ruby_scripts - collect_filenames_auto().select {|n| /\.rb\z/ =~ n } - end - - # picked up many entries from cvs-1.11.1/src/ignore.c - reject_patterns = %w( - core RCSLOG tags TAGS .make.state - .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb - *~ *.old *.bak *.BAK *.orig *.rej _$* *$ - - *.org *.in .* - ) - mapping = { - '.' => '\.', - '$' => '\$', - '#' => '\#', - '*' => '.*' - } - REJECT_PATTERNS = Regexp.new('\A(?:' + - reject_patterns.map {|pat| - pat.gsub(/[\.\$\#\*]/) {|ch| mapping[ch] } - }.join('|') + - ')\z') - - def collect_filenames_auto - mapdir((existfiles() - hookfiles()).reject {|fname| - REJECT_PATTERNS =~ fname - }) - end - - def existfiles - all_files_in(curr_srcdir()) | all_files_in('.') - end - - def hookfiles - %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| - %w( config setup install clean ).map {|t| sprintf(fmt, t) } - }.flatten - end - - def mapdir(filelist) - filelist.map {|fname| - if File.exist?(fname) # objdir - fname - else # srcdir - File.join(curr_srcdir(), fname) - end - } - end - - def ruby_extentions(dir) - Dir.open(dir) {|d| - ents = d.select {|fname| /\.#{::Config::CONFIG['DLEXT']}\z/ =~ fname } - if ents.empty? - setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" - end - return ents - } - end - - # - # TASK clean - # - - def exec_clean - exec_task_traverse 'clean' - rm_f ConfigTable.savefile - rm_f 'InstalledFiles' - end - - def clean_dir_bin(rel) - end - - def clean_dir_lib(rel) - end - - def clean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'clean' if File.file?('Makefile') - end - - def clean_dir_data(rel) - end - - # - # TASK distclean - # - - def exec_distclean - exec_task_traverse 'distclean' - rm_f ConfigTable.savefile - rm_f 'InstalledFiles' - end - - def distclean_dir_bin(rel) - end - - def distclean_dir_lib(rel) - end - - def distclean_dir_ext(rel) - return unless extdir?(curr_srcdir()) - make 'distclean' if File.file?('Makefile') - end - - # - # lib - # - - def exec_task_traverse(task) - run_hook "pre-#{task}" - FILETYPES.each do |type| - if config('without-ext') == 'yes' and type == 'ext' - $stderr.puts 'skipping ext/* by user option' if verbose? - next - end - traverse task, type, "#{task}_dir_#{type}" - end - run_hook "post-#{task}" - end - - def traverse(task, rel, mid) - dive_into(rel) { - run_hook "pre-#{task}" - __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') - all_dirs_in(curr_srcdir()).each do |d| - traverse task, "#{rel}/#{d}", mid - end - run_hook "post-#{task}" - } - end - - def dive_into(rel) - return unless File.dir?("#{@srcdir}/#{rel}") - - dir = File.basename(rel) - Dir.mkdir dir unless File.dir?(dir) - prevdir = Dir.pwd - Dir.chdir dir - $stderr.puts '---> ' + rel if verbose? - @currdir = rel - yield - Dir.chdir prevdir - $stderr.puts '<--- ' + rel if verbose? - @currdir = File.dirname(rel) - end - -end - - -if $0 == __FILE__ - begin - if multipackage_install? - ToplevelInstallerMulti.invoke - else - ToplevelInstaller.invoke - end - rescue SetupError - raise if $DEBUG - $stderr.puts $!.message - $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." - exit 1 - end -end From b0349ab8181c853e1189088da35567497fa2668a Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:21:37 +0100 Subject: [PATCH 06/13] save never invoked --- app/models/server.rb | 45 -------------------------------------------- 1 file changed, 45 deletions(-) diff --git a/app/models/server.rb b/app/models/server.rb index 6962480..1725dbd 100644 --- a/app/models/server.rb +++ b/app/models/server.rb @@ -111,51 +111,6 @@ class Server < ActiveRecord::Base self.category_id = (domain == DOMAIN_NS2 ? 45 : 44 ) end - def save_demos - dir = case recordable_type - when "Match" then - recordable.contest.demos - when "Gather" then - Directory.find(Directory::DEMOS_GATHERS) - end - - dir ||= Directory.find(Directory::DEMOS_DEFAULT) - zip_path = File.join(dir.path, recording + ".zip") - - Zip::ZipOutputStream::open(zip_path) do |zos| - if recordable_type == "Match" - zos.put_next_entry "readme.txt" - zos.write "Team1: " + recordable.contester1.to_s + "\r\n" - zos.write "Team2: " + recordable.contester2.to_s + "\r\n" - zos.write "Date: " + recordable.match_time.to_s + "\r\n" - zos.write "Contest: " + recordable.contest.to_s + "\r\n" - zos.write "Server: " + recordable.server.addr + "\r\n" if recordable.server - zos.write "HLTV: " + addr + "\r\n" - zos.write YAML::dump(recordable.attributes).to_s - end - Dir.glob("#{DEMOS}/*").each do |file| - if File.file?(file) and file.match(/#{recording}.*\.dem/) - zos.put_next_entry File.basename(file) - zos.write(IO.read(file)) - end - end - end - - DataFile.transaction do - unless dbfile = DataFile.find_by_path(zip_path) - dbfile = DataFile.new - dbfile.path = zip_path - dbfile.directory = dir - dbfile.save! - DataFile.update_all({:name => File.basename(zip_path)}, {:id => dbfile.id}) - end - if recordable_type == "Match" - recordable.demo = dbfile - recordable.save - end - end - end - def is_free time challenges.around(time).pending.count == 0 and matches.around(time).count == 0 end From da6052f017e53ad8fef07ba1da3e7620f9d26e20 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:23:52 +0100 Subject: [PATCH 07/13] Update deps --- Gemfile.lock | 2 -- 1 file changed, 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0701597..b02d36d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -119,7 +119,6 @@ GEM ffi (1.9.3) font-awesome-sass (4.1.0) sass (~> 3.2) - gruff (0.3.7) haml (4.0.5) tilt hike (1.2.3) @@ -284,7 +283,6 @@ DEPENDENCIES factory_girl_rails (~> 4.4.1) faraday (~> 0.9.0) font-awesome-sass (~> 4.1.0.0) - gruff (~> 0.3.6) haml (~> 4.0.5) jquery-rails (~> 2.0.2) mysql2 (~> 0.3.15) From b663911ebed9a6196dd7cd715edf703c2112e181 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:31:29 +0100 Subject: [PATCH 08/13] hltvs not used in index template --- app/controllers/servers_controller.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/servers_controller.rb b/app/controllers/servers_controller.rb index 2df8ae4..e1137aa 100644 --- a/app/controllers/servers_controller.rb +++ b/app/controllers/servers_controller.rb @@ -4,7 +4,6 @@ class ServersController < ApplicationController def index @servers = Server.hlds.active.ordered.all :include => :user @ns2 = Server.ns2.active.ordered.all :include => :user - @hltvs = Server.hltvs.active.ordered.all :include => :user @officials = Server.ns2.active.ordered.where ["name LIKE ?", "%NSL%"] end From 841ffe673d366a448214aa1a08ff440f10dca7ba Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:34:35 +0100 Subject: [PATCH 09/13] Not able to find references to these views --- app/views/servers/_response.html.erb | 7 ------- app/views/servers/_response.xml.erb | 7 ------- 2 files changed, 14 deletions(-) delete mode 100644 app/views/servers/_response.html.erb delete mode 100644 app/views/servers/_response.xml.erb diff --git a/app/views/servers/_response.html.erb b/app/views/servers/_response.html.erb deleted file mode 100644 index 7aa21fa..0000000 --- a/app/views/servers/_response.html.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% @server.logs.recent.reverse_each do |log| %> - <% if log.domain == Log::DOMAIN_RCON_COMMAND %> -
<%= log.text %>
- <% elsif log.domain == Log::DOMAIN_RCON_RESPONSE %> -
<%= log.text %>
- <% end %> - <% end %> diff --git a/app/views/servers/_response.xml.erb b/app/views/servers/_response.xml.erb deleted file mode 100644 index 6481654..0000000 --- a/app/views/servers/_response.xml.erb +++ /dev/null @@ -1,7 +0,0 @@ -<% @server.logs.recent.reverse_each do |log| %> - <% if log.domain == Log::DOMAIN_RCON_COMMAND %> -
<%= log.text %>
- <% elsif log.domain == Log::DOMAIN_RCON_RESPONSE %> -
<%= log.text %>
- <% end %> -<% end %> \ No newline at end of file From cf0825ddf66a8c33a358127c965e97179c4a22e4 Mon Sep 17 00:00:00 2001 From: cblanc Date: Wed, 13 May 2015 12:34:55 +0100 Subject: [PATCH 10/13] No corresponding log method on servers controller --- app/views/servers/log.html.erb | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 app/views/servers/log.html.erb diff --git a/app/views/servers/log.html.erb b/app/views/servers/log.html.erb deleted file mode 100644 index d3a0e9d..0000000 --- a/app/views/servers/log.html.erb +++ /dev/null @@ -1,21 +0,0 @@ -

- Server Log: <%= h @server %> -

- -
- - - - - - - - <% @server.logs.each do |log| %> - - - - - - <% end %> -
DateTypeMessage
<%= shorttime log.created_at %><%= log.domains[log.domain] %><%= h log.text %>
-
From 41421eb80063d4e4e745b95d2db4220abe1f12d9 Mon Sep 17 00:00:00 2001 From: cblanc Date: Thu, 14 May 2015 17:27:12 +0100 Subject: [PATCH 11/13] Added ns server specs --- spec/factories/group.rb | 12 +++ spec/factories/grouper.rb | 5 + spec/factories/server.rb | 8 ++ spec/factories/user.rb | 7 ++ .../features/servers/server_administration.rb | 30 ++++++ spec/features/servers/user_servers.rb | 14 +++ spec/models/server_spec.rb | 98 +++++++++++++++++++ spec/spec_helper.rb | 1 + spec/support/features/server_helpers.rb | 49 ++++++++++ 9 files changed, 224 insertions(+) create mode 100644 spec/factories/group.rb create mode 100644 spec/factories/grouper.rb create mode 100644 spec/factories/server.rb create mode 100644 spec/features/servers/server_administration.rb create mode 100644 spec/features/servers/user_servers.rb create mode 100644 spec/models/server_spec.rb create mode 100644 spec/support/features/server_helpers.rb diff --git a/spec/factories/group.rb b/spec/factories/group.rb new file mode 100644 index 0000000..0a101b3 --- /dev/null +++ b/spec/factories/group.rb @@ -0,0 +1,12 @@ +FactoryGirl.define do + factory :group do + sequence(:id) { |n| n + 100 } # Preserve first 100 + sequence(:name) { |n| "Group#{n}" } + association :founder, factory: :user + end + + trait :admin do + name "Admins" + id Group::ADMINS + end +end diff --git a/spec/factories/grouper.rb b/spec/factories/grouper.rb new file mode 100644 index 0000000..54c492b --- /dev/null +++ b/spec/factories/grouper.rb @@ -0,0 +1,5 @@ +FactoryGirl.define do + factory :grouper do + sequence(:task) { |n| "Task#{n}" } + end +end \ No newline at end of file diff --git a/spec/factories/server.rb b/spec/factories/server.rb new file mode 100644 index 0000000..837c9ad --- /dev/null +++ b/spec/factories/server.rb @@ -0,0 +1,8 @@ +FactoryGirl.define do + factory :server do + sequence(:name) { |n| "ServerName#{n}" } + sequence(:dns) { |n| "DNS#{n}" } + sequence(:ip) { |n| "192.168.#{n % 255}.#{n}" } + sequence(:port) { |n| "#{1000 + n}" } + end +end \ No newline at end of file diff --git a/spec/factories/user.rb b/spec/factories/user.rb index fc5f7aa..9b15973 100644 --- a/spec/factories/user.rb +++ b/spec/factories/user.rb @@ -13,6 +13,13 @@ FactoryGirl.define do create(:profile, user: user) end + trait :admin do + after(:create) do |user| + group = create(:group, :admin) + create :grouper, user: user, group: group + end + end + factory :user_with_team do after(:create) do |user| create(:team, founder: user) diff --git a/spec/features/servers/server_administration.rb b/spec/features/servers/server_administration.rb new file mode 100644 index 0000000..fa6e125 --- /dev/null +++ b/spec/features/servers/server_administration.rb @@ -0,0 +1,30 @@ +require 'spec_helper' + +feature 'Server Administration' do + let!(:admin) { create :user, :admin } + + background do + sign_in_as admin + end + + scenario 'creating a server' do + visit servers_path + expect(page).to have_content('Listing Servers') + click_link 'New server' + test_server_creation_and_editing + visit servers_path + expect(page).to have_content Server.last.name + end + + feature 'Server deletion' do + let!(:server) { create :server } + scenario 'deleting a server' do + visit servers_path + expect(page).to have_content(server.name) + visit server_path(server) + click_link 'Delete Server' + visit servers_path + expect(page).to_not have_content(server.name) + end + end +end diff --git a/spec/features/servers/user_servers.rb b/spec/features/servers/user_servers.rb new file mode 100644 index 0000000..d8b20d1 --- /dev/null +++ b/spec/features/servers/user_servers.rb @@ -0,0 +1,14 @@ +require 'spec_helper' + +feature 'User created servers' do + let!(:user) { create :user } + + background do + sign_in_as user + end + + scenario 'Creating and updating a server' do + visit new_server_path + test_server_creation_and_editing + end +end \ No newline at end of file diff --git a/spec/models/server_spec.rb b/spec/models/server_spec.rb new file mode 100644 index 0000000..19374e8 --- /dev/null +++ b/spec/models/server_spec.rb @@ -0,0 +1,98 @@ +# == Schema Information +# +# Table name: servers +# +# id :integer not null, primary key +# name :string(255) +# description :string(255) +# dns :string(255) +# ip :string(255) +# port :string(255) +# rcon :string(255) +# password :string(255) +# irc :string(255) +# user_id :integer +# official :boolean +# created_at :datetime +# updated_at :datetime +# map :string(255) +# players :integer +# max_players :integer +# ping :string(255) +# version :integer +# domain :integer default(0), not null +# reservation :string(255) +# recording :string(255) +# idle :datetime +# default_id :integer +# active :boolean default(TRUE), not null +# recordable_type :string(255) +# recordable_id :integer +# category_id :integer +# + +require 'spec_helper' + +describe Server do + describe 'create' do + it 'sets category to 45 if domain is NS2' do + server = create :server, domain: Server::DOMAIN_NS2 + expect(server.category_id).to eq(45) + end + it 'sets category to 44 if domain is not NS2' do + server = create :server, domain: Server::DOMAIN_HLDS + expect(server.category_id).to eq(44) + end + end + + describe 'addr' do + it 'returns properly formatted IP and port number' do + ip = '1.1.1.1' + port = '8000' + server = create :server, ip: ip, port: port + expect(server.addr).to eq('1.1.1.1:8000') + end + end + + describe 'to_s' do + it 'returns server name' do + server_name = "Foo" + server = create :server, name: server_name + expect(server.to_s).to eq(server_name) + end + end + + describe 'Permissions' do + let!(:user) { create :user } + let!(:admin) { create :user, :admin } + let!(:server_user) {create :user } + let!(:server) { create :server, user: server_user } + + describe 'can_create?' do + it 'returns true for non-admins' do + expect(server.can_create? user).to be_true + end + end + + describe 'can_destroy?' do + it 'returns true for admin' do + expect(server.can_destroy? admin).to be_true + end + it 'returns false for non-admins' do + expect(server.can_destroy? user).to be_false + end + end + + describe 'can_update?' do + it 'returns true for admin' do + expect(server.can_update? admin).to be_true + end + it 'returns true if server belongs to user' do + expect(server.can_update? server_user).to be_true + end + it 'returns false for non-admins' do + expect(server.can_update? user).to be_false + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f2956e2..8e8b650 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -26,6 +26,7 @@ RSpec.configure do |config| config.include FactoryGirl::Syntax::Methods config.include Controllers::JsonHelpers, type: :controller config.include Features::FormHelpers, type: :feature + config.include Features::ServerHelpers, type: :feature config.include Features::SessionHelpers, type: :feature config.fixture_path = "#{::Rails.root}/spec/fixtures" diff --git a/spec/support/features/server_helpers.rb b/spec/support/features/server_helpers.rb new file mode 100644 index 0000000..b28df90 --- /dev/null +++ b/spec/support/features/server_helpers.rb @@ -0,0 +1,49 @@ +module Features + module ServerHelpers + def test_server_creation_and_editing + dns = 'ServerDns.com' + ip = '192.168.1.1' + port = '8000' + rcon = 'whatsrcon' + password = 'secret' + name = 'MyNsServer' + description = 'My NS Server' + irc = '#some_channel' + + visit new_server_path + fill_in 'Dns', with: dns + fill_in 'server_ip', with: ip + fill_in 'server_port', with: port + fill_in 'Password', with: password + fill_in 'Name', with: name + fill_in 'Description', with: description + fill_in 'Irc', with: irc + check 'Available for officials?' + click_button 'Save' + + expect(page).to have_content(dns) + expect(page).to have_content("#{ip}:#{port}") + expect(page).to have_content(password) + expect(page).to have_content(irc) + expect(page).to have_content(description) + + click_link 'Edit Server' + + fill_in 'Dns', with: "#{dns}2" + fill_in 'server_ip', with: "192.168.1.2" + fill_in 'server_port', with: "8001" + fill_in 'Password', with: "#{password}2" + fill_in 'Name', with: "#{name}2" + fill_in 'Description', with: "#{description}2" + fill_in 'Irc', with: "#{irc}2" + check 'Available for officials?' + click_button 'Save' + + expect(page).to have_content("192.168.1.2:8001") + expect(page).to have_content("#{dns}2") + expect(page).to have_content("#{password}2") + expect(page).to have_content("#{irc}2") + expect(page).to have_content("#{description}2") + end + end +end \ No newline at end of file From 4f1e1ce9116678f8d5b00924bd144f44b54acae2 Mon Sep 17 00:00:00 2001 From: cblanc Date: Thu, 14 May 2015 17:29:05 +0100 Subject: [PATCH 12/13] Indentation --- app/models/server.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/server.rb b/app/models/server.rb index 1725dbd..aa0339f 100644 --- a/app/models/server.rb +++ b/app/models/server.rb @@ -47,8 +47,8 @@ class Server < ActiveRecord::Base validates_length_of [:rcon, :password, :irc], :maximum => 30, :allow_blank => true validates_length_of :description, :maximum => 255, :allow_blank => true validates_format_of :ip, :with => /\A[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\z/ - validates_format_of :port, :with => /\A[0-9]{1,5}\z/ - validates_format_of :reservation, :with => /\A[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}\z/, :allow_nil => true + validates_format_of :port, :with => /\A[0-9]{1,5}\z/ + validates_format_of :reservation, :with => /\A[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{1,5}\z/, :allow_nil => true validates_format_of :pwd, :with => /\A[A-Za-z0-9_\-]*\z/, :allow_nil => true scope :ordered, :order => "name" From 9d6f4c7342f9ffdf9b9569d8efc3f62ef6ba5009 Mon Sep 17 00:00:00 2001 From: cblanc Date: Thu, 14 May 2015 17:29:16 +0100 Subject: [PATCH 13/13] Create new annotations for models --- app/models/article.rb | 4 ++-- app/models/gatherer.rb | 1 + app/models/match.rb | 1 + app/models/profile.rb | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/models/article.rb b/app/models/article.rb index 28b2f05..979b8ea 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -6,12 +6,12 @@ # title :string(255) # status :integer not null # category_id :integer -# text :text +# text :text(16777215) # user_id :integer # created_at :datetime # updated_at :datetime # version :integer -# text_parsed :text +# text_parsed :text(16777215) # text_coding :integer default(0), not null # diff --git a/app/models/gatherer.rb b/app/models/gatherer.rb index 0b49f1b..d6697bf 100644 --- a/app/models/gatherer.rb +++ b/app/models/gatherer.rb @@ -9,6 +9,7 @@ # created_at :datetime # updated_at :datetime # votes :integer default(0), not null +# status :integer default(0), not null # class Gatherer < ActiveRecord::Base diff --git a/app/models/match.rb b/app/models/match.rb index 30d7d3b..1059d07 100644 --- a/app/models/match.rb +++ b/app/models/match.rb @@ -25,6 +25,7 @@ # points1 :integer # points2 :integer # hltv_id :integer +# caster_id :string(255) # class Match < ActiveRecord::Base diff --git a/app/models/profile.rb b/app/models/profile.rb index 194e0f8..e24e4d0 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -52,6 +52,8 @@ # steam_profile :string(255) # achievements_parsed :string(255) # signature_parsed :string(255) +# stream :string(255) +# layout :string(255) # class Profile < ActiveRecord::Base