telnetd 0.0.1.alpha.2 → 0.0.1.alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d4e64bb72f46024a89922a2f71cf075542e6b615
4
+ data.tar.gz: be007072af40fc04d3fa06479ba86fedaea26735
5
+ SHA512:
6
+ metadata.gz: 1fb9016bca31322aab61837721fdbb971ad94c1aad14702f0adb592ae6d554d2947beda7e356cd8c0159619cddfd7b7285a9c40ab3877809a6ee2afcbd33810f
7
+ data.tar.gz: a7d46ef8aa4a4507068cb868221e58938ebf12b35984cab79c015739f464816441fc53173e794970debbd85e16e670cd03e03b5a79ccd4390652072ebb0215e8
data/README.md CHANGED
@@ -3,21 +3,34 @@ telnetd
3
3
 
4
4
  Simple ruby telnet server with build in commands.
5
5
 
6
+ Commands available
7
+ ==================
8
+ - Cat
9
+ - Cd
10
+ - Dir
11
+ - Exit
12
+ - Help
13
+ - Pwd
14
+ - Uptime
15
+ - Touch
6
16
 
7
-
8
-
9
- Commands
10
- ========
17
+ Commands planned
18
+ ==================
11
19
  - Broadcast
12
- - Cat
13
20
  - Copy
14
21
  - Del
15
- - Exit
16
- - *Help
17
- - Pwd
22
+ - Exec
23
+ - Fileinfo
18
24
  - Mkdir
19
25
  - Move
20
26
  - Stats
21
- - Touch
22
- - *Uptime
23
- - Who
27
+ - Who
28
+
29
+ Known Issues
30
+ ============
31
+ - (Solved) Cat cmd does not handle line breaks correct
32
+ - (Solved) Commands with backspaces are not correct handled. Eg. "kat\b\b\bcat"
33
+
34
+ Execute from Git
35
+ ============
36
+ ruby -Ilib bin\telnetd
data/bin/telnetd CHANGED
@@ -2,4 +2,6 @@
2
2
 
3
3
  require 'telnetd'
4
4
 
5
- Telnetd.run
5
+ module Telnetd
6
+ Telnetd.run
7
+ end
data/lib/telnetd.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'telnetd/telnet_server'
2
2
 
3
+ module Telnetd
3
4
  # telnetd console runner
4
5
  class Telnetd
5
6
 
@@ -13,5 +14,5 @@ class Telnetd
13
14
  telnetd.stop
14
15
  puts "Telnet server stopped."
15
16
  end
16
-
17
17
  end
18
+ end
@@ -1,7 +1,9 @@
1
+ require 'pathname'
2
+
3
+ module Telnetd
1
4
  # Client context instance.
2
5
  # Used to handle all informations relevant for a connected client
3
6
  # A class instance is valid as long the associated client is conntected.
4
-
5
7
  class ClientContext
6
8
 
7
9
  # Read the client connection start timestamp.
@@ -13,11 +15,42 @@ class ClientContext
13
15
  # Create a new instance of the context
14
16
  def initialize
15
17
  @start_time = Time.now
16
- @path = application_path
18
+ @path = Pathname.new(application_path)
19
+ end
20
+
21
+ # Used to list the folders of the current working directory
22
+ def list_folders
23
+ result = []
24
+ @path.each_child { |path|
25
+ result << path if File::directory?(path)
26
+ }
27
+ return result
28
+ end
29
+
30
+ # Used to list the files of the current working directory
31
+ def list_files
32
+ result = []
33
+ @path.each_child { |path|
34
+ result << path if File::file?(path)
35
+ }
36
+ return result
37
+ end
38
+
39
+ # Change the dirctory to the path of the argument
40
+ # ==== Argument
41
+ # *+arg+ The path argument. May contain '..' to navigate to the parent folder
42
+ # ==== Result
43
+ # * An error message if the requested path does not exists
44
+ def cd(arg)
45
+ newpath = @path.join(Pathname.new(arg))
46
+ return "Path does not exists." unless newpath.exist?
47
+ @path = newpath
17
48
  end
18
49
 
19
50
  private
51
+ # Get the application startup path
20
52
  def application_path
21
53
  return File.dirname(__FILE__)
22
54
  end
55
+ end
23
56
  end
@@ -0,0 +1,39 @@
1
+
2
+ module Telnetd
3
+ # Cat command implementation
4
+ class CatCmd
5
+
6
+ # Handle the touch command.
7
+ # Create a new empty file with the given file name
8
+ # ==== Arguments
9
+ # *+client+ The client to handle the command for
10
+ # *+commandtime+ The command string content
11
+ def handle(client, command)
12
+ args = command.split(' ')
13
+ if(args.length == 2)
14
+ # FileUtils.cd(client.context.path) do
15
+ # FileUtils.touch(args[1])
16
+ # end
17
+ begin
18
+ file = File.new("#{client.context.path}/#{args[1]}", "r")
19
+ while (line = file.gets)
20
+ line = line.gsub("\n", "\r\n")
21
+ client.print("#{line}")
22
+ end
23
+ file.close
24
+
25
+ #client.println(File.read("#{client.context.path}/#{args[1]}"))
26
+ rescue => err
27
+ client.println(err)
28
+ end
29
+ else
30
+ client.println("Missing filename.")
31
+ end
32
+ end
33
+
34
+ # Describe the uptime command
35
+ def describe
36
+ "Print the content of the file to the client"
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+
2
+ module Telnetd
3
+ # Handle the cd command with the one argument passed
4
+ class CdCmd
5
+
6
+ # Handle the cd command.
7
+ # Shows the folder and files of the present working directory.
8
+ # ==== Arguments
9
+ # *+client+ The client to handle the command for
10
+ # *+command+ The command string content
11
+ def handle(client, command)
12
+ args = command.split(' ')
13
+ if(args.length == 2)
14
+ client.println(cd(client.context, args[1]))
15
+ else
16
+ client.println("Missing the folder name argument.")
17
+ end
18
+ end
19
+
20
+ # Execute the cd command against the client context.
21
+ # ==== Argument
22
+ # *+context+ The client context to execute the cd command on.
23
+ # *+arg+ The argument with the requested path to be changed.
24
+ def cd(context, arg)
25
+ context.cd(arg)
26
+ end
27
+
28
+ # Describe the dir command
29
+ def describe
30
+ "Change the working directory with the passed argument. Use '..' to navigate upwards."
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,62 @@
1
+ require 'pathname'
2
+
3
+ module Telnetd
4
+ # Dir command implementation
5
+ class DirCmd
6
+
7
+ # Handle the dir command.
8
+ # Shows the folder and files of the present working directory.
9
+ # ==== Arguments
10
+ # *+client+ The client to handle the command for
11
+ # *+command+ The command string content
12
+ def handle(client, command)
13
+ client.println(format(client.context))
14
+ end
15
+
16
+ # Describe the dir command
17
+ def describe
18
+ "Shows the folder and files of the present working directory."
19
+ end
20
+
21
+ # Format the content of the path as human readable string
22
+ # ==== Arguments
23
+ # *+context+ The client context to access the present working directory
24
+ def format(context)
25
+ return "#{header(context)}#{folders(context)}#{files(context)}"
26
+ end
27
+
28
+ private
29
+
30
+ def header(context)
31
+ "Content of directory: #{context.path}" +
32
+ "\r\n-------------------------------------------------------------------" +
33
+ "\r\n\t%-40s \t %-10s" % ["Name", "Size"] +
34
+ "\r\n-------------------------------------------------------------------"
35
+ end
36
+
37
+ def folders(context)
38
+ result = ""
39
+ context.list_folders.each { |folder|
40
+ result += "\r\n\t%-40s \t %-10s" % [Pathname.new(folder).basename, "<DIR>"]
41
+ }
42
+ return result
43
+ end
44
+
45
+ def files(context)
46
+ result = ""
47
+ context.list_files.each { |file|
48
+ result += "\r\n\t%-40s \t %-10s" % [File.basename(file), as_size(File.size(file))]
49
+ }
50
+ return result
51
+ end
52
+
53
+ def as_size(s)
54
+ units = %W(B KiB MiB GiB TiB)
55
+ size, unit = units.reduce(s.to_f) do |(fsize, _), utype|
56
+ fsize > 512 ? [fsize / 1024, utype] : (break [fsize, utype])
57
+ end
58
+ "#{size > 9 || size.modulo(1) < 0.1 ? '%d' : '%.1f'} %s" % [size, unit]
59
+ end
60
+
61
+ end
62
+ end
@@ -1,5 +1,6 @@
1
- # Exit command used to close a client connection
2
1
 
2
+ module Telnetd
3
+ # Exit command used to close a client connection
3
4
  class ExitCmd
4
5
 
5
6
  # Handle the exit command by closing the client connection.
@@ -15,4 +16,5 @@ class ExitCmd
15
16
  def describe
16
17
  "Close the connetion to the server."
17
18
  end
19
+ end
18
20
  end
@@ -1,5 +1,6 @@
1
- # Help command is used to display all available commands with a one line description
2
1
 
2
+ module Telnetd
3
+ # Help command is used to display all available commands with a one line description
3
4
  class HelpCmd
4
5
 
5
6
  # Used to show all available commands to the client
@@ -10,12 +11,11 @@ class HelpCmd
10
11
  client.command_registry.commands.each { |name,cmd|
11
12
  client.println("#{name} \t #{cmd.describe}")
12
13
  }
13
- #client.println("#{client.command_registry}")
14
14
  end
15
15
 
16
16
  # Describe the help command
17
17
  def describe
18
18
  "Show the list of all available commands."
19
19
  end
20
-
20
+ end
21
21
  end
@@ -1,5 +1,6 @@
1
- # Shows the present working directory to the client
2
1
 
2
+ module Telnetd
3
+ # Shows the present working directory to the client
3
4
  class PwdCmd
4
5
 
5
6
  # Handle the uptime command. Shows the connection time span in seconds.
@@ -14,5 +15,5 @@ class PwdCmd
14
15
  def describe
15
16
  "Show the present working directory."
16
17
  end
17
-
18
+ end
18
19
  end
@@ -0,0 +1,29 @@
1
+ require 'fileutils'
2
+
3
+ module Telnetd
4
+ #Touch command implementation
5
+ class TouchCmd
6
+
7
+ # Handle the touch command.
8
+ # Create a new empty file with the given file name
9
+ # ==== Arguments
10
+ # *+client+ The client to handle the command for
11
+ # *+commandtime+ The command string content
12
+ def handle(client, command)
13
+ args = command.split(' ')
14
+ if(args.length == 2)
15
+ FileUtils.cd(client.context.path) do
16
+ FileUtils.touch(args[1])
17
+ end
18
+ else
19
+ client.println("Missing filename.")
20
+ end
21
+ end
22
+
23
+ # Describe the uptime command
24
+ def describe
25
+ "Create a new file with the new name provided as argument."
26
+ end
27
+
28
+ end
29
+ end
@@ -1,5 +1,6 @@
1
- # Handle an unknown command
2
1
 
2
+ module Telnetd
3
+ # Handle an unknown command
3
4
  class UnknownCmd
4
5
 
5
6
  # Handle an unknown command by echo the provided command with a string that
@@ -9,8 +10,8 @@ class UnknownCmd
9
10
  # *+client+ The client to handle the command for
10
11
  # *+command+ The command string content
11
12
  def handle(client, command)
12
- client.println("Unknown command \"#{command}\"")
13
+ client.println("Unknown command \"#{command.dump}\"")
13
14
  client.println("Type \"help\" for a full list of available commands.")
14
15
  end
15
-
16
+ end
16
17
  end
@@ -1,3 +1,5 @@
1
+
2
+ module Telnetd
1
3
  # Uptime command to show the client connection time
2
4
  class UptimeCmd
3
5
 
@@ -6,12 +8,16 @@ class UptimeCmd
6
8
  # *+client+ The client to handle the command for
7
9
  # *+commandtime+ The command string content
8
10
  def handle(client, command)
9
- seconds = Time.now - client.context.start_time;
10
- client.println("#{ seconds.to_i } seconds connected")
11
+ time = (Time.now - client.context.start_time).to_i;
12
+ hours = time/3600.to_i
13
+ minutes = (time/60 - hours * 60).to_i
14
+ seconds = (time - (minutes * 60 + hours * 3600))
15
+ client.println("Client connected since %02d:%02d:%02d [hh:mm:ss]" % [hours, minutes, seconds])
11
16
  end
12
17
 
13
18
  # Describe the uptime command
14
19
  def describe
15
20
  "Show the client connection uptime."
16
21
  end
22
+ end
17
23
  end
@@ -3,7 +3,12 @@ require 'telnetd/cmd/exit_cmd'
3
3
  require 'telnetd/cmd/help_cmd'
4
4
  require 'telnetd/cmd/uptime_cmd'
5
5
  require 'telnetd/cmd/pwd_cmd'
6
+ require 'telnetd/cmd/dir_cmd'
7
+ require 'telnetd/cmd/cd_cmd'
8
+ require 'telnetd/cmd/touch_cmd'
9
+ require 'telnetd/cmd/cat_cmd'
6
10
 
11
+ module Telnetd
7
12
  # Command Registry used to collect and manage the build in commands
8
13
  # for the telnetd
9
14
  class CommandRegistry
@@ -14,10 +19,14 @@ class CommandRegistry
14
19
  # Create a new instance of the command registry.
15
20
  def initialize
16
21
  @commands = {
22
+ "cat" => CatCmd.new,
17
23
  "exit" => ExitCmd.new,
18
24
  "help" => HelpCmd.new,
19
25
  "uptime" => UptimeCmd.new,
20
- "pwd" => PwdCmd.new
26
+ "pwd" => PwdCmd.new,
27
+ "dir" => DirCmd.new,
28
+ "cd" => CdCmd.new,
29
+ "touch" => TouchCmd.new
21
30
  }
22
31
  end
23
32
 
@@ -27,17 +36,30 @@ class CommandRegistry
27
36
  # *+client+ The client to execute the command for
28
37
  # *+command+ The command to be executed
29
38
  def handle(client, command)
30
- command.strip!
31
- if @commands.has_key? command
32
- @commands[command].handle(client, command)
39
+ command = strip_cmd(command)
40
+ cmd = command.split(' ')[0]
41
+ if @commands.has_key? cmd
42
+ @commands[cmd].handle(client, command)
33
43
  else
34
- handle_unknown_command(client, command)
44
+ handle_unknown_command(client, cmd)
35
45
  end
36
46
  end
37
47
 
38
48
  private
49
+ def strip_cmd(command)
50
+ result = ""
51
+ command.each_char { |c|
52
+ if c.eql?("\b")
53
+ result.chop!
54
+ else
55
+ result += c
56
+ end
57
+ }
58
+ return result
59
+ end
60
+
39
61
  def handle_unknown_command(client, command)
40
62
  UnknownCmd.new.handle(client, command)
41
63
  end
42
-
43
- end
64
+ end
65
+ end
@@ -1,6 +1,7 @@
1
1
  require 'telnetd/command_registry'
2
2
  require 'telnetd/client_context'
3
3
 
4
+ module Telnetd
4
5
  # Represent a telnet client.
5
6
  # This class is used to be executed in a single thread
6
7
  class TelnetClient
@@ -30,11 +31,9 @@ class TelnetClient
30
31
  promt()
31
32
  while line = @client.gets
32
33
  process_cmd(line)
33
-
34
34
  if @client.closed?
35
35
  return
36
36
  end
37
-
38
37
  promt()
39
38
  end
40
39
  end
@@ -60,8 +59,8 @@ class TelnetClient
60
59
  end
61
60
 
62
61
  private
63
-
64
62
  def process_cmd(cmd)
63
+ cmd.strip!
65
64
  @command_registry.handle(self, cmd)
66
65
  end
67
66
 
@@ -74,5 +73,5 @@ private
74
73
  println("===================")
75
74
  println("Type 'help' to get a list of all commands or 'exit' to end the session.")
76
75
  end
77
-
76
+ end
78
77
  end
@@ -1,6 +1,7 @@
1
1
  require 'socket'
2
2
  require 'telnetd/telnet_client'
3
3
 
4
+ module Telnetd
4
5
  # The Telnet daemon main class. Create a new thread for each client
5
6
  class TelnetServer
6
7
 
@@ -26,7 +27,9 @@ class TelnetServer
26
27
  handleNewClient(client)
27
28
  end
28
29
  rescue Exception => e
29
- puts "Client Error: #{e.message}"
30
+ puts "Client Error: #{e.message}"
31
+ puts e.inspect
32
+ puts e.backtrace
30
33
  end
31
34
  }
32
35
  rescue Interrupt => e
@@ -63,8 +66,10 @@ private
63
66
  begin
64
67
  client.handle()
65
68
  rescue Exception => e
66
- puts "Client Error: #{e.message}"
69
+ puts "Client Error: #{e.message}"
70
+ puts e.inspect
71
+ puts e.backtrace
67
72
  end
68
73
  end
69
-
70
- end
74
+ end
75
+ end
Binary file
data/telnetd.gemspec CHANGED
@@ -2,7 +2,7 @@ require 'rake'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'telnetd'
5
- spec.version = '0.0.1.alpha.2'
5
+ spec.version = '0.0.1.alpha.3'
6
6
  spec.date = '2013-04-04'
7
7
  spec.summary = "Simple telnet daemon"
8
8
  spec.description = "Simple telnet daemon to be used from the command line or as embedded service."
@@ -0,0 +1,28 @@
1
+
2
+ require 'test/unit'
3
+ require 'telnetd/client_context'
4
+
5
+ module Telnetd
6
+ # Tests for the client context
7
+ class TestClientContext < Test::Unit::TestCase
8
+
9
+ # Test if the start time is set in the past.
10
+ def test_start_time
11
+ context = ClientContext.new
12
+ sleep(1)
13
+ assert(context.start_time < Time.now, "Expect start time before now.")
14
+ end
15
+
16
+ # Test list the available folders.
17
+ def test_list_folders
18
+ context = ClientContext.new
19
+ assert(context.list_folders.empty? == false)
20
+ end
21
+
22
+ # Test list the available files.
23
+ def test_list_files
24
+ context = ClientContext.new
25
+ assert(context.list_files.empty? == false)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,19 @@
1
+ require 'test/unit'
2
+ require 'telnetd/command_registry'
3
+
4
+ module Telnetd
5
+ # Tests for the Command Registry
6
+ class TestCommandRegistry < Test::Unit::TestCase
7
+
8
+ #Test the strip of the command
9
+ def test_strip_cmd
10
+ cr = CommandRegistry.new
11
+ assert_equal("abc", cr.send("strip_cmd", "abc "))
12
+ end
13
+
14
+ def test_strip_backspace
15
+ cr = CommandRegistry.new
16
+ assert_equal("cat", cr.send("strip_cmd", "kat\b\b\bcat"))
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+
2
+ require 'test/unit'
3
+ require 'telnetd/client_context'
4
+ require 'telnetd/cmd/dir_cmd'
5
+
6
+ module Telnetd
7
+ # Tests for the dir command
8
+ class TestDirCmd < Test::Unit::TestCase
9
+
10
+ # Test if the dir listing contains expected folder and files.
11
+ def test_dir_listing
12
+ dir = DirCmd.new
13
+ assert(dir.format(ClientContext.new).include?("cmd"))
14
+ assert(dir.format(ClientContext.new).include?("telnet_client.rb"))
15
+ assert(dir.format(ClientContext.new).include?("telnet_server.rb"))
16
+ end
17
+
18
+ end
19
+ end
@@ -2,6 +2,7 @@ require 'test/unit'
2
2
  require 'socket'
3
3
  require 'telnetd/telnet_server'
4
4
 
5
+ module Telnetd
5
6
  # Tests used for the telnet server
6
7
  class TelnetServerTest < Test::Unit::TestCase
7
8
 
@@ -41,4 +42,5 @@ private
41
42
  sleep(0.1)
42
43
  end
43
44
 
44
- end
45
+ end
46
+ end
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: telnetd
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.alpha.2
5
- prerelease: 6
4
+ version: 0.0.1.alpha.3
6
5
  platform: ruby
7
6
  authors:
8
7
  - Promotos
@@ -19,45 +18,51 @@ executables:
19
18
  extensions: []
20
19
  extra_rdoc_files: []
21
20
  files:
21
+ - lib/telnetd.rb
22
22
  - lib/telnetd/client_context.rb
23
+ - lib/telnetd/cmd/cat_cmd.rb
24
+ - lib/telnetd/cmd/cd_cmd.rb
25
+ - lib/telnetd/cmd/dir_cmd.rb
23
26
  - lib/telnetd/cmd/exit_cmd.rb
24
27
  - lib/telnetd/cmd/help_cmd.rb
25
28
  - lib/telnetd/cmd/pwd_cmd.rb
29
+ - lib/telnetd/cmd/touch_cmd.rb
26
30
  - lib/telnetd/cmd/unknown_cmd.rb
27
31
  - lib/telnetd/cmd/uptime_cmd.rb
28
32
  - lib/telnetd/command_registry.rb
29
33
  - lib/telnetd/telnet_client.rb
30
34
  - lib/telnetd/telnet_server.rb
31
- - lib/telnetd.rb
32
35
  - bin/telnetd
33
- - make_rdoc.bat
34
- - Rakefile
35
36
  - README.md
36
- - telnetd-0.0.1.alpha.1.gem
37
+ - Rakefile
38
+ - make_rdoc.bat
39
+ - telnetd-0.0.1.alpha.2.gem
37
40
  - telnetd.gemspec
41
+ - test/test_client_context.rb
42
+ - test/test_command_registry.rb
43
+ - test/test_dir_cmd.rb
38
44
  - test/test_telnet_server.rb
39
45
  homepage: http://rubygems.org/gems/telnetd
40
46
  licenses: []
47
+ metadata: {}
41
48
  post_install_message:
42
49
  rdoc_options: []
43
50
  require_paths:
44
51
  - lib
45
52
  required_ruby_version: !ruby/object:Gem::Requirement
46
- none: false
47
53
  requirements:
48
- - - ! '>='
54
+ - - '>='
49
55
  - !ruby/object:Gem::Version
50
56
  version: '0'
51
57
  required_rubygems_version: !ruby/object:Gem::Requirement
52
- none: false
53
58
  requirements:
54
- - - ! '>'
59
+ - - '>'
55
60
  - !ruby/object:Gem::Version
56
61
  version: 1.3.1
57
62
  requirements: []
58
63
  rubyforge_project:
59
- rubygems_version: 1.8.24
64
+ rubygems_version: 2.0.14
60
65
  signing_key:
61
- specification_version: 3
66
+ specification_version: 4
62
67
  summary: Simple telnet daemon
63
68
  test_files: []
Binary file