This file is indexed.

/usr/share/doc/ruby-net-irc/examples/ircd.rb is in ruby-net-irc 0.0.9-2.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
#!/usr/bin/env ruby
# vim:encoding=UTF-8:

require 'rubygems'
require 'net/irc'

class NetIrcServer < Net::IRC::Server::Session
	def server_name
		"net-irc"
	end

	def server_version
		"0.0.0"
	end

	def available_user_modes
		"iosw"
	end

	def default_user_modes
		""
	end

	def available_channel_modes
		"om"
	end

	def default_channel_modes
		""
	end

	def initialize(*args)
		super
		@@channels ||= {}
		@@users    ||= {}
		@ping        = false
	end

	def on_pass(m)
	end

	def on_user(m)
		@user, @real = m.params[0], m.params[3]
		@host        = @socket.peeraddr[2]
		@prefix      = Prefix.new("#{@nick}!#{@user}@#{@host}")
		@joined_on   = @updated_on = Time.now.to_i

		post @socket, @prefix, NICK, nick
		@nick = nick
		@prefix = "#{@nick}!#{@user}@#{@host}"

		time = Time.now.to_i
		@@users[@nick.downcase] = {
			:nick       => @nick,
			:user       => @user,
			:host       => @host,
			:real       => @real,
			:prefix     => @prefix,
			:socket     => @socket,
			:joined_on  => time,
			:updated_on => time
		}

		initial_message

		start_ping
	end

	def on_join(m)
		channels = m.params[0].split(/\s*,\s*/)
		password = m.params[1]

		channels.each do |channel|
			unless channel.downcase =~ /^#/
				post @socket, server_name, ERR_NOSUCHCHANNEL, @nick, channel, "No such channel"
				next
			end

			unless @@channels.key?(channel.downcase)
				channel_create(channel)
			else
				return if @@channels[channel.downcase][:users].key?(@nick.downcase)

				@@channels[channel.downcase][:users][@nick.downcase] = []
			end

			mode = @@channels[channel.downcase][:mode].empty? ? "" : "+" + @@channels[channel.downcase][:mode]
			post @socket, server_name, RPL_CHANNELMODEIS, @nick, @@channels[channel.downcase][:alias], mode

			channel_users = ""
			@@channels[channel.downcase][:users].each do |nick, m|
				post @@users[nick][:socket], @prefix, JOIN, @@channels[channel.downcase][:alias]

				case
				when m.index("@")
					f = "@"
				when m.index("+")
					f = "+"
				else
					f = ""
				end
				channel_users += "#{f}#{@@users[nick.downcase][:nick]} "
			end
			post @socket, server_name, RPL_NAMREPLY, @@users[nick][:nick], "=", @@channels[channel.downcase][:alias], "#{channel_users.strip}"
			post @socket, server_name, RPL_ENDOFNAMES, @@users[nick][:nick], @@channels[channel.downcase][:alias], "End of /NAMES list"
		end
	end

	def on_part(m)
		channel, message = *m.params

		@@channels[channel.downcase][:users].each do |nick, f|
			post @@users[nick][:socket], @prefix, PART, @@channels[channel.downcase][:alias], message
		end
		channel_part(channel)
	end

	def on_quit(m)
		message = m.params[0]
		@@channels.each do |channel, f|
			if f[:users].key?(@nick.downcase)
				channel_part(channel)
				f[:users].each do |nick, m|
					post @@users[nick][:socket], @prefix, QUIT, message
				end
			end
		end
		finish
	end

	def on_disconnected
		super
		@@channels.each do |channel, f|
			if f[:users].key?(@nick.downcase)
				channel_part(channel)
				f[:users].each do |nick, m|
					post @@users[nick][:socket], @prefix, QUIT, "disconnect"
				end
			end
		end
		channel_part_all
		@@users.delete(@nick.downcase)
	end

	def on_who(m)
		channel = m.params[0]
		return unless channel

		c = channel.downcase
		case
		when @@channels.key?(c)
			@@channels[c][:users].each do |nickname, m|
				nick = @@users[nickname][:nick]
				user = @@users[nickname][:user]
				host = @@users[nickname][:host]
				real = @@users[nickname][:real]
				case
				when m.index("@")
					f = "@"
				when m.index("+")
					f = "+"
				else
					f = ""
				end
				post @socket, server_name, RPL_WHOREPLY, @nick, @@channels[c][:alias], user, host, server_name, nick, "H#{f}", "0 #{real}"
			end
			post @socket, server_name, RPL_ENDOFWHO, @nick, @@channels[c][:alias], "End of /WHO list"
		end
	end

	def on_mode(m)
	end

	def on_privmsg(m)
		while (Time.now.to_i - @updated_on < 2)
			sleep 2
		end
		idle_update

		return on_ctcp(m[0], ctcp_decoding(m[1])) if m.ctcp?

		target, message = *m.params
		t = target.downcase

		case
		when @@channels.key?(t)
			if @@channels[t][:users].key?(@nick.downcase)
				@@channels[t][:users].each do |nick, m|
					post @@users[nick][:socket], @prefix, PRIVMSG, @@channels[t][:alias], message unless nick == @nick.downcase
				end
			else
				post @socket, nil, ERR_CANNOTSENDTOCHAN, @nick, target, "Cannot send to channel"
			end
		when @@users.key?(t)
			post @@users[nick][:socket], @prefix, PRIVMSG, @@users[t][:nick], message
		else
			post @socket, nil, ERR_NOSUCHNICK, @nick, target, "No such nick/channel"
		end
	end

	def on_ping(m)
		post @socket, server_name, PONG, m.params[0]
	end

	def on_pong(m)
		@ping = true
	end

	def idle_update
		@updated_on = Time.now.to_i
		if logged_in?
			@@users[@nick.downcase][:updated_on] = @updated_on
		end
	end

	def channel_create(channel)
		@@channels[channel.downcase] = {
			:alias      => channel,
			:topic      => "",
			:mode       => default_channel_modes,
			:users      => {@nick.downcase => ["@"]},
		}
	end

	def channel_part(channel)
		@@channels[channel.downcase][:users].delete(@nick.downcase)
		channel_delete(channel.downcase) if @@channels[channel.downcase][:users].size == 0
	end

	def channel_part_all
		@@channels.each do |c|
			channel_part(c)
		end
	end

	def channel_delete(channel)
		@@channels.delete(channel.downcase)
	end

	def post(socket, prefix, command, *params)
		m = Message.new(prefix, command, params.map{|s|
			s.gsub(/[\r\n]/, "")
		})
		socket << m
	rescue
		finish
	end

	def start_ping
		Thread.start do
			loop do
				@ping = false
				time = Time.now.to_i
				if @ping == false && (time - @updated_on > 60)
					post @socket, server_name, PING, @prefix
					loop do
						sleep 1
						if @ping
							break
						end
						if 60 < Time.now.to_i - time
							Thread.stop
							finish
						end
					end
				end
				sleep 60
			end
		end
	end

	# Call when client connected.
	# Send RPL_WELCOME sequence. If you want to customize, override this method at subclass.
	def initial_message
		post @socket, server_name, RPL_WELCOME,  @nick, "Welcome to the Internet Relay Network #{@prefix}"
		post @socket, server_name, RPL_YOURHOST, @nick, "Your host is #{server_name}, running version #{server_version}"
		post @socket, server_name, RPL_CREATED,  @nick, "This server was created #{Time.now}"
		post @socket, server_name, RPL_MYINFO,   @nick, "#{server_name} #{server_version} #{available_user_modes} #{available_channel_modes}"
	end

end


if __FILE__ == $0
	require "optparse"

	opts = {
		:port  => 6969,
		:host  => "localhost",
		:log   => nil,
		:debug => false,
		:foreground => false,
	}

	OptionParser.new do |parser|
		parser.instance_eval do
			self.banner = <<-EOB.gsub(/^\t+/, "")
				Usage: #{$0} [opts]

			EOB

			separator ""

			separator "Options:"
			on("-p", "--port [PORT=#{opts[:port]}]", "port number to listen") do |port|
				opts[:port] = port
			end

			on("-h", "--host [HOST=#{opts[:host]}]", "host name or IP address to listen") do |host|
				opts[:host] = host
			end

			on("-l", "--log LOG", "log file") do |log|
				opts[:log] = log
			end

			on("--debug", "Enable debug mode") do |debug|
				opts[:log]   = $stdout
				opts[:debug] = true
			end

			on("-f", "--foreground", "run foreground") do |foreground|
				opts[:log]        = $stdout
				opts[:foreground] = true
			end

			on("-n", "--name [user name or email address]") do |name|
				opts[:name] = name
			end

			parse!(ARGV)
		end
	end

	opts[:logger] = Logger.new(opts[:log], "daily")
	opts[:logger].level = opts[:debug] ? Logger::DEBUG : Logger::INFO

	#def daemonize(foreground = false)
	#	[:INT, :TERM, :HUP].each do |sig|
	#		Signal.trap sig, "EXIT"
	#	end
	#	return yield if $DEBUG or foreground
	#	Process.fork do
	#		Process.setsid
	#		Dir.chdir "/"
	#		STDIN.reopen  "/dev/null"
	#		STDOUT.reopen "/dev/null", "a"
	#		STDERR.reopen STDOUT
	#		yield
	#	end
	#	exit! 0
	#end

	#daemonize(opts[:debug] || opts[:foreground]) do
	Net::IRC::Server.new(opts[:host], opts[:port], NetIrcServer, opts).start
	#end
end