web_sandbox_console 0.1.0 → 0.2.0
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 +4 -4
- data/README.md +11 -0
- data/app/assets/stylesheets/web_sandbox_console/home.css +19 -0
- data/app/controllers/web_sandbox_console/home_controller.rb +9 -0
- data/app/views/web_sandbox_console/home/do_view_file.js.erb +5 -0
- data/app/views/web_sandbox_console/home/index.html.erb +2 -1
- data/app/views/web_sandbox_console/home/view_file.html.erb +25 -0
- data/config/routes.rb +2 -0
- data/lib/generators/web_sandbox_console/templates/web_sandbox_console.rb +4 -0
- data/lib/web_sandbox_console.rb +4 -0
- data/lib/web_sandbox_console/configuration.rb +3 -0
- data/lib/web_sandbox_console/safe_ruby.rb +2 -2
- data/lib/web_sandbox_console/sandbox.rb +61 -10
- data/lib/web_sandbox_console/sandbox_error.rb +4 -0
- data/lib/web_sandbox_console/version.rb +1 -1
- data/lib/web_sandbox_console/view_file.rb +117 -0
- data/lib/web_sandbox_console/view_file_error.rb +4 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 59bdbe60c0c4fa3569ef776901c06e5519cdd804fd905fe1c81e15cfd269157c
|
4
|
+
data.tar.gz: d71b8d16c04d900fb270f196d1e2bf89b71e77ca2620e48bfdc178158637e5a6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a8f4487e10e9796fbaefa3ee6d4f8b3112e493adf165d6cacaefa71a6975d436e849ce65ad97af3ba76ad5b3261787bcc15db205576a284120a0fae50f9ce74e
|
7
|
+
data.tar.gz: d5395e322921350c55bd3e936782cac340e6f772e075166c81860378c695e79a4711b91016d06590d58384dc812084feef4496a739f64c24acf560b017655343
|
data/README.md
CHANGED
@@ -50,11 +50,22 @@ WebSandboxConsole.setup do |config|
|
|
50
50
|
# # 配置 黑名单 实例方法
|
51
51
|
# config.instance_method_blacklist = {Kernel: %i(system exec `),File: %i(chmod chown)}
|
52
52
|
|
53
|
+
# 文件黑名单列表 (如果是目录 则目录下所有文件都不用)目录以 / 结尾
|
54
|
+
# 默认都是项目路径下的
|
55
|
+
# config.view_file_blacklist = %w(config/secrets.yml vendor/)
|
56
|
+
|
53
57
|
# # 配置 日志路径 默认路径位于项目下
|
54
58
|
# config.console_log_path = "log/web_sandbox_console.log"
|
55
59
|
end
|
56
60
|
```
|
57
61
|
|
62
|
+
## other
|
63
|
+
查看目录或文件路径: `/web_sandbox_console/view_file`
|
64
|
+
除了可以查询一些数据外,还可以查看项目路径下任何文件或目录,如果你输入的是一个目录,那么会查出此目录下的文件/目录;如果你输入的是文件,那么将查出文件的内容,默认查看文件的第一行 到 100行,当然你也可以指定你需要查找的行;
|
65
|
+
|
66
|
+
如果一个文件特别大,超过10M,此时将查找文件的最后200行,指定行数将无效;当然也可在配置文件中,配置哪些文件不可查看,哪些目录不可以查看,如果指定的是目录,那么目录下的所有子文件或目录都无权查看.
|
67
|
+
|
68
|
+

|
58
69
|
## Contributing
|
59
70
|
Contribution directions go here.
|
60
71
|
|
@@ -2,3 +2,22 @@
|
|
2
2
|
Place all the styles related to the matching controller here.
|
3
3
|
They will automatically be included in application.css.
|
4
4
|
*/
|
5
|
+
|
6
|
+
|
7
|
+
.file_or_dir{
|
8
|
+
width: 500px;
|
9
|
+
height: 30px;
|
10
|
+
}
|
11
|
+
|
12
|
+
.h30{
|
13
|
+
height: 30px;
|
14
|
+
}
|
15
|
+
|
16
|
+
.view-file-button{
|
17
|
+
background: #272822;
|
18
|
+
height: 36px;
|
19
|
+
width: 132px;
|
20
|
+
font-size: 15px;
|
21
|
+
color: white;
|
22
|
+
cursor: pointer;
|
23
|
+
}
|
@@ -8,8 +8,17 @@ module WebSandboxConsole
|
|
8
8
|
def index
|
9
9
|
end
|
10
10
|
|
11
|
+
# 执行代码
|
11
12
|
def eval_code
|
12
13
|
@results = Sandbox.new(params[:code]).evalotor
|
13
14
|
end
|
15
|
+
|
16
|
+
def view_file
|
17
|
+
end
|
18
|
+
|
19
|
+
# 查看文件
|
20
|
+
def do_view_file
|
21
|
+
@results = ViewFile.new(params).view
|
22
|
+
end
|
14
23
|
end
|
15
24
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
控制台 index
|
2
|
+
<%= link_to '查看文件', web_sandbox_console.view_file_path %>
|
2
3
|
|
3
4
|
<div class="console">
|
4
5
|
<%= form_tag(web_sandbox_console.eval_code_path, remote: true, class: 'form') do %>
|
@@ -6,7 +7,7 @@
|
|
6
7
|
<input type="reset" value="重置" class='reset-button'>
|
7
8
|
<%= submit_tag '提交', data: { disable_with: "已发送,处理中..." }, class: 'send-button' %>
|
8
9
|
<% end %>
|
9
|
-
|
10
|
+
|
10
11
|
</div>
|
11
12
|
|
12
13
|
<%= button_tag '清除输出', type: 'button', onclick: "$('.output-content').empty();", class: 'clear-button' %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# view_file
|
2
|
+
<%= link_to '控制台', web_sandbox_console.root_path %>
|
3
|
+
<div class="view_file">
|
4
|
+
<%= form_tag do_view_file_path, method: :post, remote: true do %>
|
5
|
+
<table>
|
6
|
+
<tr>
|
7
|
+
<td>文件/目录路径</td>
|
8
|
+
<td>
|
9
|
+
<%= text_field_tag :file_or_dir, nil, class: 'file_or_dir', placeholder: '请输入文件路径...'%>
|
10
|
+
</td>
|
11
|
+
<td>起始行数</td>
|
12
|
+
<td><%= text_field_tag :start_line_num, nil, class: 'h30', placeholder: '默认从第1行开始...' %></td>
|
13
|
+
<td>结束行数</td>
|
14
|
+
<td><%= text_field_tag :end_line_num, nil, class: 'h30', placeholder: '默认从第100行结束...' %></td>
|
15
|
+
<td><%= submit_tag '提交', data: { disable_with: "已发送,处理中..." }, class: 'view-file-button' %></td>
|
16
|
+
</table>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<div class="output-content">
|
21
|
+
</div>
|
22
|
+
|
23
|
+
<style type="text/css">
|
24
|
+
|
25
|
+
</style>
|
data/config/routes.rb
CHANGED
@@ -16,6 +16,10 @@ WebSandboxConsole.setup do |config|
|
|
16
16
|
# # 配置 黑名单 实例方法
|
17
17
|
# config.instance_method_blacklist = {Kernel: %i(system exec `),File: %i(chmod chown)}
|
18
18
|
|
19
|
+
# 文件黑名单列表 (如果是目录 则目录下所有文件都不用)目录以 / 结尾
|
20
|
+
# 默认都是项目路径下的
|
21
|
+
# config.view_file_blacklist = %w(config/secrets.yml vendor/)
|
22
|
+
|
19
23
|
# # 配置 日志路径 默认路径位于项目下
|
20
24
|
# config.console_log_path = "log/web_sandbox_console.log"
|
21
25
|
end
|
data/lib/web_sandbox_console.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
require 'fileutils'
|
1
2
|
require "web_sandbox_console/engine"
|
3
|
+
require "web_sandbox_console/sandbox_error"
|
2
4
|
require "web_sandbox_console/configuration"
|
3
5
|
require "web_sandbox_console/common.rb"
|
4
6
|
require "web_sandbox_console/safe_ruby"
|
5
7
|
require "web_sandbox_console/sandbox"
|
8
|
+
require "web_sandbox_console/view_file_error"
|
9
|
+
require "web_sandbox_console/view_file"
|
6
10
|
|
7
11
|
|
8
12
|
module WebSandboxConsole
|
@@ -9,6 +9,8 @@ module WebSandboxConsole
|
|
9
9
|
mattr_accessor :class_method_blacklist
|
10
10
|
# 实例方法 黑名单 hash
|
11
11
|
mattr_accessor :instance_method_blacklist
|
12
|
+
# 文件列表 黑名单
|
13
|
+
mattr_accessor :view_file_blacklist
|
12
14
|
# 日志路径
|
13
15
|
mattr_accessor :console_log_path
|
14
16
|
# 挂载 引擎路由位置
|
@@ -16,6 +18,7 @@ module WebSandboxConsole
|
|
16
18
|
|
17
19
|
# 默认 引擎路由位置
|
18
20
|
@@mount_engine_route_path = '/web_sandbox_console'
|
21
|
+
|
19
22
|
|
20
23
|
# 内置 实例方法 黑名单
|
21
24
|
INSTANT_METOD_BUILT_IN_BLACKLIST = {
|
@@ -52,13 +52,13 @@ module WebSandboxConsole
|
|
52
52
|
# 将两个hash 内部数组也同时合并,并去重
|
53
53
|
def merge_method_hash(hash1, hash2)
|
54
54
|
# 格式统一
|
55
|
-
hash2.transform_keys!(&:to_sym).transform_values!{|
|
55
|
+
hash2.transform_keys!(&:to_sym).transform_keys!(&:to_sym).transform_values!{|i| i.map(&:to_sym)}
|
56
56
|
# 共有的key
|
57
57
|
common_keys = hash2.keys & hash1.keys
|
58
58
|
# hash2 特有keys
|
59
59
|
hash2_special_keys = hash2.keys - hash1.keys
|
60
60
|
# 特有keys 直接合到 hash1
|
61
|
-
hash1.merge!(hash2.slice(hash2_special_keys))
|
61
|
+
hash1.merge!(hash2.slice(*hash2_special_keys))
|
62
62
|
# 共用keys 数组去重
|
63
63
|
common_keys.each do |key|
|
64
64
|
hash1[key] = (hash1[key] | hash2[key]).uniq
|
@@ -1,16 +1,24 @@
|
|
1
1
|
module WebSandboxConsole
|
2
2
|
class Sandbox
|
3
|
-
attr_accessor :code
|
4
|
-
attr_accessor :uuid
|
3
|
+
attr_accessor :code # 代码
|
4
|
+
attr_accessor :uuid # 唯一标识
|
5
|
+
attr_accessor :exe_tmp_file # 执行临时文件(由code 组成的运行代码)
|
5
6
|
|
6
7
|
def initialize(code = nil)
|
7
|
-
@code
|
8
|
-
@uuid
|
8
|
+
@code = code
|
9
|
+
@uuid = SecureRandom.uuid
|
10
|
+
@exe_tmp_file = "#{Rails.root}/tmp/sandbox/#{uuid}.rb"
|
9
11
|
end
|
10
12
|
|
11
13
|
def evalotor
|
12
|
-
|
13
|
-
|
14
|
+
begin
|
15
|
+
check_syntax
|
16
|
+
write_exe_tmp_file
|
17
|
+
exec_rails_runner
|
18
|
+
get_result
|
19
|
+
rescue SandboxError => e
|
20
|
+
[e.message]
|
21
|
+
end
|
14
22
|
end
|
15
23
|
|
16
24
|
def runner_code
|
@@ -30,7 +38,54 @@ module WebSandboxConsole
|
|
30
38
|
WebSandboxConsole.log_p(result, "#{self.uuid}")
|
31
39
|
CODE
|
32
40
|
end
|
41
|
+
|
42
|
+
# 临时文件目录
|
43
|
+
def tmp_file_dir
|
44
|
+
File.dirname(self.exe_tmp_file)
|
45
|
+
end
|
46
|
+
|
47
|
+
# 添加临时文件目录
|
48
|
+
def add_tmp_file_dir
|
49
|
+
FileUtils.mkdir_p(tmp_file_dir) unless File.directory?(tmp_file_dir)
|
50
|
+
end
|
51
|
+
|
52
|
+
# 临时文件 需要清理?
|
53
|
+
def tmp_file_need_clean?
|
54
|
+
Dir["#{tmp_file_dir}/*"].count > 6
|
55
|
+
end
|
56
|
+
|
57
|
+
# 自动删除临时文件
|
58
|
+
def auto_clean_tmp_file
|
59
|
+
FileUtils.rm_rf(Dir["#{tmp_file_dir}/*"]) if tmp_file_need_clean?
|
60
|
+
end
|
61
|
+
|
62
|
+
# 写入 执行临时文件
|
63
|
+
def write_exe_tmp_file
|
64
|
+
add_tmp_file_dir
|
65
|
+
auto_clean_tmp_file
|
66
|
+
File.open(self.exe_tmp_file, 'w'){|f| f << runner_code}
|
67
|
+
end
|
68
|
+
|
69
|
+
# 准备检查语法
|
70
|
+
def prepare_check_syntax
|
71
|
+
add_tmp_file_dir
|
72
|
+
File.open(self.exe_tmp_file, 'w'){|f| f << self.code}
|
73
|
+
end
|
74
|
+
|
75
|
+
# 检查 语法
|
76
|
+
def check_syntax
|
77
|
+
prepare_check_syntax
|
78
|
+
unless `ruby -c #{self.exe_tmp_file}`.include?('Syntax OK')
|
79
|
+
raise SandboxError, "存在语法错误"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# 运行rails runner
|
84
|
+
def exec_rails_runner
|
85
|
+
`bundle exec rails runner #{self.exe_tmp_file}`
|
86
|
+
end
|
33
87
|
|
88
|
+
# 获取 执行结果
|
34
89
|
def get_result
|
35
90
|
last_10_lines = `tail -n 10 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
|
36
91
|
|
@@ -39,9 +94,5 @@ module WebSandboxConsole
|
|
39
94
|
end.flatten
|
40
95
|
end
|
41
96
|
|
42
|
-
# 转义单引号
|
43
|
-
def escape_single_quote_mark(code)
|
44
|
-
code.gsub(/'/,'"')
|
45
|
-
end
|
46
97
|
end
|
47
98
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module WebSandboxConsole
|
2
|
+
class ViewFile
|
3
|
+
attr_accessor :file_or_dir # 文件或目录
|
4
|
+
attr_accessor :start_line_num # 起始行数
|
5
|
+
attr_accessor :end_line_num # 结束行数
|
6
|
+
|
7
|
+
def initialize(opts = {})
|
8
|
+
@file_or_dir = opts[:file_or_dir]
|
9
|
+
@start_line_num = opts[:start_line_num].present? ? opts[:start_line_num].to_i : 1
|
10
|
+
@end_line_num = opts[:end_line_num].present? ? opts[:end_line_num].to_i : 100
|
11
|
+
end
|
12
|
+
|
13
|
+
def view
|
14
|
+
begin
|
15
|
+
check_param
|
16
|
+
file_or_dir_exists
|
17
|
+
check_blacklist
|
18
|
+
view_file
|
19
|
+
rescue ViewFileError => e
|
20
|
+
[e.message]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# 检查参数
|
25
|
+
def check_param
|
26
|
+
raise ViewFileError, '文件或目录参数不能为空' if file_or_dir.blank?
|
27
|
+
end
|
28
|
+
|
29
|
+
# 转换成项目路径
|
30
|
+
def project_path(path)
|
31
|
+
"#{Rails.root}/#{path}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# 绝对路径
|
35
|
+
def file_or_dir_path
|
36
|
+
"#{Rails.root}/#{file_or_dir}"
|
37
|
+
end
|
38
|
+
|
39
|
+
# 是否存在
|
40
|
+
def file_or_dir_exists
|
41
|
+
raise ViewFileError, '文件或目录不存在' unless File.exists?(file_or_dir_path)
|
42
|
+
end
|
43
|
+
|
44
|
+
# 是目录?
|
45
|
+
def is_directory?(path)
|
46
|
+
File.directory?(path)
|
47
|
+
end
|
48
|
+
|
49
|
+
# 目录下所有子文件 目录
|
50
|
+
def dir_all_sub_file_or_dir(current_dir)
|
51
|
+
Dir["#{current_dir}**/*"]
|
52
|
+
end
|
53
|
+
|
54
|
+
# 黑名单 包含自身 及其 子目录/文件
|
55
|
+
def blacklist_all_file_dir_arr
|
56
|
+
black_lists = WebSandboxConsole.view_file_blacklist
|
57
|
+
return [] if black_lists.blank?
|
58
|
+
|
59
|
+
result_arr = black_lists.inject([]) do |result_arr, black_item_path|
|
60
|
+
current_path = project_path(black_item_path)
|
61
|
+
|
62
|
+
if is_directory?(current_path)
|
63
|
+
result_arr.concat(dir_all_sub_file_or_dir(current_path))
|
64
|
+
else
|
65
|
+
result_arr
|
66
|
+
end
|
67
|
+
end
|
68
|
+
black_lists.map{|i| project_path(i)}.concat(result_arr)
|
69
|
+
end
|
70
|
+
|
71
|
+
# 检查是否为黑名单 文件 / 目录
|
72
|
+
def check_blacklist
|
73
|
+
black_lists = blacklist_all_file_dir_arr
|
74
|
+
raise ViewFileError, '文件或目录无权限查看' if black_lists.include?(file_or_dir_path) || black_lists.include?(file_or_dir_path + '/')
|
75
|
+
end
|
76
|
+
|
77
|
+
# 目录下文件
|
78
|
+
def files_in_dir
|
79
|
+
Dir["#{file_or_dir_path}/*"].map do |path|
|
80
|
+
path += is_directory?(path) ? '(目录)' : '(文件)'
|
81
|
+
path[file_or_dir_path.length..-1]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# 是否为大文件
|
86
|
+
def is_big_file?
|
87
|
+
File.new(file_or_dir_path).size > 10.megabytes
|
88
|
+
end
|
89
|
+
|
90
|
+
# 查看文件/目录
|
91
|
+
def view_file
|
92
|
+
if is_directory?(file_or_dir_path)
|
93
|
+
files_in_dir
|
94
|
+
else
|
95
|
+
lines = is_big_file? ? tail_200_line : special_line_content
|
96
|
+
add_line_num(lines)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# 最后 200 行内容
|
101
|
+
def tail_200_line
|
102
|
+
(`tail -n 200 #{file_or_dir_path}`).split(/[\r,\r\n]/)
|
103
|
+
end
|
104
|
+
|
105
|
+
# 按指定行返回
|
106
|
+
def special_line_content
|
107
|
+
File.readlines(file_or_dir_path)[(start_line_num - 1)..(end_line_num - 1)]
|
108
|
+
end
|
109
|
+
|
110
|
+
# 添加行号
|
111
|
+
def add_line_num(lines)
|
112
|
+
start_num = is_big_file? ? 1 : start_line_num
|
113
|
+
lines.each_with_index.map{|line, index| "#{index + start_num}: #{line}"}
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web_sandbox_console
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dongmingyan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -62,8 +62,10 @@ files:
|
|
62
62
|
- app/mailers/web_sandbox_console/application_mailer.rb
|
63
63
|
- app/models/web_sandbox_console/application_record.rb
|
64
64
|
- app/views/layouts/web_sandbox_console/application.html.erb
|
65
|
+
- app/views/web_sandbox_console/home/do_view_file.js.erb
|
65
66
|
- app/views/web_sandbox_console/home/eval_code.js.erb
|
66
67
|
- app/views/web_sandbox_console/home/index.html.erb
|
68
|
+
- app/views/web_sandbox_console/home/view_file.html.erb
|
67
69
|
- config/routes.rb
|
68
70
|
- lib/generators/web_sandbox_console/USAGE
|
69
71
|
- lib/generators/web_sandbox_console/templates/web_sandbox_console.rb
|
@@ -75,7 +77,10 @@ files:
|
|
75
77
|
- lib/web_sandbox_console/engine.rb
|
76
78
|
- lib/web_sandbox_console/safe_ruby.rb
|
77
79
|
- lib/web_sandbox_console/sandbox.rb
|
80
|
+
- lib/web_sandbox_console/sandbox_error.rb
|
78
81
|
- lib/web_sandbox_console/version.rb
|
82
|
+
- lib/web_sandbox_console/view_file.rb
|
83
|
+
- lib/web_sandbox_console/view_file_error.rb
|
79
84
|
homepage: https://github.com/dongmy54/web_sandbox_console
|
80
85
|
licenses:
|
81
86
|
- MIT
|