From 5e284aba7559a21c6a20dc360f8ffbfc40620cf5 Mon Sep 17 00:00:00 2001 From: ksg97031 Date: Fri, 29 Dec 2023 14:26:58 +0900 Subject: [PATCH] refactor: Refactor analyzers and add path details to endpoints (#192) - Refactored multiple analyzer files to include the `Details` object for storing path and line number information Signed-off-by: ksg97031 --- src/analyzer/analyzers/analyzer_armeria.cr | 6 ++-- .../analyzers/analyzer_crystal_kemal.cr | 4 ++- .../analyzers/analyzer_crystal_lucky.cr | 4 ++- .../analyzers/analyzer_cs_aspnet_mvc.cr | 5 +-- src/analyzer/analyzers/analyzer_django.cr | 9 +++-- .../analyzers/analyzer_elixir_phoenix.cr | 33 ++++++++++--------- src/analyzer/analyzers/analyzer_express.cr | 4 ++- src/analyzer/analyzers/analyzer_fastapi.cr | 3 +- src/analyzer/analyzers/analyzer_flask.cr | 7 ++-- src/analyzer/analyzers/analyzer_go_echo.cr | 8 +++-- src/analyzer/analyzers/analyzer_go_fiber.cr | 8 +++-- src/analyzer/analyzers/analyzer_go_gin.cr | 8 +++-- src/analyzer/analyzers/analyzer_jsp.cr | 3 +- src/analyzer/analyzers/analyzer_oas2.cr | 10 +++--- src/analyzer/analyzers/analyzer_oas3.cr | 14 ++++---- src/analyzer/analyzers/analyzer_php_pure.cr | 6 ++-- src/analyzer/analyzers/analyzer_raml.cr | 4 ++- .../analyzers/analyzer_ruby_hanami.cr | 26 ++++++++------- src/analyzer/analyzers/analyzer_ruby_rails.cr | 25 +++++++------- .../analyzers/analyzer_ruby_sinatra.cr | 4 ++- src/analyzer/analyzers/analyzer_rust_axum.cr | 5 +-- src/analyzer/analyzers/analyzer_spring.cr | 18 +++++----- .../analyzers/file_analyzers/base64.cr | 5 +-- .../analyzers/file_analyzers/string.cr | 5 +-- 24 files changed, 135 insertions(+), 89 deletions(-) diff --git a/src/analyzer/analyzers/analyzer_armeria.cr b/src/analyzer/analyzers/analyzer_armeria.cr index ff50e1a6..2a5e8850 100644 --- a/src/analyzer/analyzers/analyzer_armeria.cr +++ b/src/analyzer/analyzers/analyzer_armeria.cr @@ -12,6 +12,8 @@ class AnalyzerArmeria < Analyzer next if File.directory?(path) if File.exists?(path) && (path.ends_with?(".java") || path.ends_with?(".kt")) + details = Details.new(PathInfo.new(path)) + content = File.read(path, encoding: "utf-8", invalid: :skip) content.scan(REGEX_SERVER_CODE_BLOCK) do |server_codeblcok_match| server_codeblock = server_codeblcok_match[0] @@ -30,7 +32,7 @@ class AnalyzerArmeria < Analyzer endpoint = split_params[endpoint_param_index].strip endpoint = endpoint[1..-2] - @result << Endpoint.new("#{endpoint}", "GET") + @result << Endpoint.new("#{endpoint}", "GET", details) end server_codeblock.scan(REGEX_ROUTE_CODE) do |route_code_match| @@ -47,7 +49,7 @@ class AnalyzerArmeria < Analyzer next if endpoint[0] != '"' endpoint = endpoint[1..-2] - @result << Endpoint.new("#{endpoint}", method) + @result << Endpoint.new("#{endpoint}", method, details) end end end diff --git a/src/analyzer/analyzers/analyzer_crystal_kemal.cr b/src/analyzer/analyzers/analyzer_crystal_kemal.cr index 9ddfb8fb..7914606f 100644 --- a/src/analyzer/analyzers/analyzer_crystal_kemal.cr +++ b/src/analyzer/analyzers/analyzer_crystal_kemal.cr @@ -9,9 +9,11 @@ class AnalyzerCrystalKemal < Analyzer if File.exists?(path) && File.extname(path) == ".cr" && !path.includes?("lib") File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| endpoint = line_to_endpoint(line) if endpoint.method != "" + details = Details.new(PathInfo.new(path, index + 1)) + endpoint.set_details(details) result << endpoint last_endpoint = endpoint end diff --git a/src/analyzer/analyzers/analyzer_crystal_lucky.cr b/src/analyzer/analyzers/analyzer_crystal_lucky.cr index 5dfa792a..2e428647 100644 --- a/src/analyzer/analyzers/analyzer_crystal_lucky.cr +++ b/src/analyzer/analyzers/analyzer_crystal_lucky.cr @@ -21,9 +21,11 @@ class AnalyzerCrystalLucky < Analyzer if File.exists?(path) && File.extname(path) == ".cr" && !path.includes?("lib") File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| endpoint = line_to_endpoint(line) if endpoint.method != "" + details = Details.new(PathInfo.new(path, index + 1)) + endpoint.set_details(details) result << endpoint last_endpoint = endpoint end diff --git a/src/analyzer/analyzers/analyzer_cs_aspnet_mvc.cr b/src/analyzer/analyzers/analyzer_cs_aspnet_mvc.cr index 06753f94..f90b93bf 100644 --- a/src/analyzer/analyzers/analyzer_cs_aspnet_mvc.cr +++ b/src/analyzer/analyzers/analyzer_cs_aspnet_mvc.cr @@ -11,7 +11,7 @@ class AnalyzerCsAspNetMvc < Analyzer maproute_check = false maproute_buffer = "" - file.each_line do |line| + file.each_line.with_index do |line, index| if line.includes? ".MapRoute(" maproute_check = true maproute_buffer = line @@ -25,7 +25,8 @@ class AnalyzerCsAspNetMvc < Analyzer buffer.split(",").each do |item| if item.includes? "url:" url = item.gsub(/url:/, "").gsub(/"/, "") - @result << Endpoint.new("/#{url}", "GET") + details = Details.new(PathInfo.new(route_config_file, index + 1)) + @result << Endpoint.new("/#{url}", "GET", details) end end diff --git a/src/analyzer/analyzers/analyzer_django.cr b/src/analyzer/analyzers/analyzer_django.cr index c38fd8c4..4826f6b4 100644 --- a/src/analyzer/analyzers/analyzer_django.cr +++ b/src/analyzer/analyzers/analyzer_django.cr @@ -112,7 +112,6 @@ class AnalyzerDjango < AnalyzerPython route = route.gsub(/^\^/, "").gsub(/\$$/, "") view = route_match[2].split(",")[0] url = "/#{django_urls.prefix}/#{route}".gsub(/\/+/, "/") - new_django_urls = nil view.scan(REGEX_INCLUDE_URLS) do |include_pattern_match| # Detect new url configs @@ -121,15 +120,18 @@ class AnalyzerDjango < AnalyzerPython if File.exists?(new_route_path) new_django_urls = DjangoUrls.new("#{django_urls.prefix}#{route}", new_route_path, django_urls.basepath) + details = Details.new(PathInfo.new(new_route_path)) get_endpoints(new_django_urls).each do |endpoint| + endpoint.set_details(details) endpoints << endpoint end end end next if new_django_urls != nil + details = Details.new(PathInfo.new(django_urls.filepath)) if view == "" - endpoints << Endpoint.new(url, "GET") + endpoints << Endpoint.new(url, "GET", details) else dotted_as_names_split = view.split(".") @@ -149,12 +151,13 @@ class AnalyzerDjango < AnalyzerPython if filepath != "" get_endpoint_from_files(url, filepath, function_or_class_name).each do |endpoint| + endpoint.set_details(details) endpoints << endpoint end else # By default, Django allows requests with methods other than GET as well # Prevent this flow, we need to improve trace code of 'get_endpoint_from_files() - endpoints << Endpoint.new(url, "GET") + endpoints << Endpoint.new(url, "GET", details) end end end diff --git a/src/analyzer/analyzers/analyzer_elixir_phoenix.cr b/src/analyzer/analyzers/analyzer_elixir_phoenix.cr index 0f26f798..52bc3c1a 100644 --- a/src/analyzer/analyzers/analyzer_elixir_phoenix.cr +++ b/src/analyzer/analyzers/analyzer_elixir_phoenix.cr @@ -8,13 +8,14 @@ class AnalyzerElixirPhoenix < Analyzer next if File.directory?(path) if File.exists?(path) && File.extname(path) == ".ex" File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| - last_endpoint = Endpoint.new("", "") - file.each_line do |line| - endpoint = line_to_endpoint(line) - if endpoint.method != "" - @result << endpoint - last_endpoint = endpoint - _ = last_endpoint + file.each_line.with_index do |line, index| + endpoints = line_to_endpoint(line) + endpoints.each do |endpoint| + if endpoint.method != "" + details = Details.new(PathInfo.new(path, index + 1)) + endpoint.set_details(details) + @result << endpoint + end end end end @@ -27,34 +28,36 @@ class AnalyzerElixirPhoenix < Analyzer @result end - def line_to_endpoint(line : String) : Endpoint + def line_to_endpoint(line : String) : Array(Endpoint) + endpoints = Array(Endpoint).new + line.scan(/get\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| - @result << Endpoint.new("#{match[1]}", "GET") + endpoints << Endpoint.new("#{match[1]}", "GET") end line.scan(/post\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| - @result << Endpoint.new("#{match[1]}", "POST") + endpoints << Endpoint.new("#{match[1]}", "POST") end line.scan(/patch\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| - @result << Endpoint.new("#{match[1]}", "PATCH") + endpoints << Endpoint.new("#{match[1]}", "PATCH") end line.scan(/put\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| - @result << Endpoint.new("#{match[1]}", "PUT") + endpoints << Endpoint.new("#{match[1]}", "PUT") end line.scan(/delete\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| - @result << Endpoint.new("#{match[1]}", "DELETE") + endpoints << Endpoint.new("#{match[1]}", "DELETE") end line.scan(/socket\s+['"](.+?)['"]\s*,\s*(.+?)\s*/) do |match| tmp = Endpoint.new("#{match[1]}", "GET") tmp.set_protocol("ws") - @result << tmp + endpoints << tmp end - Endpoint.new("", "") + endpoints end end diff --git a/src/analyzer/analyzers/analyzer_express.cr b/src/analyzer/analyzers/analyzer_express.cr index 78973237..650bea7d 100644 --- a/src/analyzer/analyzers/analyzer_express.cr +++ b/src/analyzer/analyzers/analyzer_express.cr @@ -9,9 +9,11 @@ class AnalyzerExpress < Analyzer if File.exists?(path) File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| endpoint = line_to_endpoint(line) if endpoint.method != "" + details = Details.new(PathInfo.new(path, index + 1)) + endpoint.set_details(details) result << endpoint last_endpoint = endpoint end diff --git a/src/analyzer/analyzers/analyzer_fastapi.cr b/src/analyzer/analyzers/analyzer_fastapi.cr index f978a884..c3b68c09 100644 --- a/src/analyzer/analyzers/analyzer_fastapi.cr +++ b/src/analyzer/analyzers/analyzer_fastapi.cr @@ -167,7 +167,8 @@ class AnalyzerFastAPI < AnalyzerPython end end - result << Endpoint.new(router_class.join(http_route_path), http_method_name, params) + details = Details.new(PathInfo.new(path, index + 1)) + result << Endpoint.new(router_class.join(http_route_path), http_method_name, params, details) end end end diff --git a/src/analyzer/analyzers/analyzer_flask.cr b/src/analyzer/analyzers/analyzer_flask.cr index b9d19170..ac425b2a 100644 --- a/src/analyzer/analyzers/analyzer_flask.cr +++ b/src/analyzer/analyzers/analyzer_flask.cr @@ -30,7 +30,7 @@ class AnalyzerFlask < AnalyzerPython Dir.glob("#{base_path}/**/*.py") do |path| next if File.directory?(path) File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| - file.each_line do |line| + file.each_line.with_index do |line, index| # [TODO] We should be cautious about instance replace with other variable match = line.match /(#{REGEX_PYTHON_VARIABLE_NAME})\s*=\s*Flask\s*\(/ if !match.nil? @@ -77,7 +77,8 @@ class AnalyzerFlask < AnalyzerPython if !route_url.starts_with? "/" route_url = "/#{route_url}" end - result << Endpoint.new(route_url, "GET") + details = Details.new(PathInfo.new(path, index + 1)) + result << Endpoint.new(route_url, "GET", details) end end end @@ -123,6 +124,8 @@ class AnalyzerFlask < AnalyzerPython codeblock_lines = codeblock_lines[1..] get_endpoints(route_path, extra_params, codeblock_lines, prefix).each do |endpoint| + details = Details.new(PathInfo.new(path, line_index + 1)) + endpoint.set_details(details) result << endpoint end end diff --git a/src/analyzer/analyzers/analyzer_go_echo.cr b/src/analyzer/analyzers/analyzer_go_echo.cr index 7dec7e07..fe293dcb 100644 --- a/src/analyzer/analyzers/analyzer_go_echo.cr +++ b/src/analyzer/analyzers/analyzer_go_echo.cr @@ -10,11 +10,12 @@ class AnalyzerGoEcho < Analyzer if File.exists?(path) && File.extname(path) == ".go" File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| + details = Details.new(PathInfo.new(path, index + 1)) if line.includes?(".GET(") || line.includes?(".POST(") || line.includes?(".PUT(") || line.includes?(".DELETE(") get_route_path(line).tap do |route_path| if route_path.size > 0 - new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0]) + new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0], details) result << new_endpoint last_endpoint = new_endpoint end @@ -69,7 +70,8 @@ class AnalyzerGoEcho < Analyzer p_dir["static_path"] = p_dir["static_path"][0..-2] end - result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET") + details = Details.new(PathInfo.new(path)) + result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET", details) end end end diff --git a/src/analyzer/analyzers/analyzer_go_fiber.cr b/src/analyzer/analyzers/analyzer_go_fiber.cr index e30f423c..f133ef2f 100644 --- a/src/analyzer/analyzers/analyzer_go_fiber.cr +++ b/src/analyzer/analyzers/analyzer_go_fiber.cr @@ -10,11 +10,12 @@ class AnalyzerGoFiber < Analyzer if File.exists?(path) && File.extname(path) == ".go" File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| + details = Details.new(PathInfo.new(path, index + 1)) if line.includes?(".Get(") || line.includes?(".Post(") || line.includes?(".Put(") || line.includes?(".Delete(") get_route_path(line).tap do |route_path| if route_path.size > 0 - new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0].upcase) + new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0].upcase, details) if line.includes?("websocket.New(") new_endpoint.set_protocol("ws") end @@ -80,7 +81,8 @@ class AnalyzerGoFiber < Analyzer p_dir["static_path"] = p_dir["static_path"][0..-2] end - result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET") + details = Details.new(PathInfo.new(path)) + result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET", details) end end end diff --git a/src/analyzer/analyzers/analyzer_go_gin.cr b/src/analyzer/analyzers/analyzer_go_gin.cr index 10a5c91b..c462a95a 100644 --- a/src/analyzer/analyzers/analyzer_go_gin.cr +++ b/src/analyzer/analyzers/analyzer_go_gin.cr @@ -10,11 +10,12 @@ class AnalyzerGoGin < Analyzer if File.exists?(path) && File.extname(path) == ".go" File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| + details = Details.new(PathInfo.new(path, index + 1)) if line.includes?(".GET(") || line.includes?(".POST(") || line.includes?(".PUT(") || line.includes?(".DELETE(") get_route_path(line).tap do |route_path| if route_path.size > 0 - new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0]) + new_endpoint = Endpoint.new("#{route_path}", line.split(".")[1].split("(")[0], details) result << new_endpoint last_endpoint = new_endpoint end @@ -63,7 +64,8 @@ class AnalyzerGoGin < Analyzer p_dir["static_path"] = p_dir["static_path"][0..-2] end - result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET") + details = Details.new(PathInfo.new(path)) + result << Endpoint.new("#{p_dir["static_path"]}#{path.gsub(full_path, "")}", "GET", details) end end end diff --git a/src/analyzer/analyzers/analyzer_jsp.cr b/src/analyzer/analyzers/analyzer_jsp.cr index f0e69c55..676bc1a2 100644 --- a/src/analyzer/analyzers/analyzer_jsp.cr +++ b/src/analyzer/analyzers/analyzer_jsp.cr @@ -33,7 +33,8 @@ class AnalyzerJsp < Analyzer rescue next end - result << Endpoint.new("/#{relative_path}", "GET", params_query) + details = Details.new(PathInfo.new(path)) + result << Endpoint.new("/#{relative_path}", "GET", params_query, details) end end end diff --git a/src/analyzer/analyzers/analyzer_oas2.cr b/src/analyzer/analyzers/analyzer_oas2.cr index 0a944b79..16a1071b 100644 --- a/src/analyzer/analyzers/analyzer_oas2.cr +++ b/src/analyzer/analyzers/analyzer_oas2.cr @@ -9,6 +9,7 @@ class AnalyzerOAS2 < Analyzer if swagger_jsons.is_a?(Array(String)) swagger_jsons.each do |swagger_json| if File.exists?(swagger_json) + details = Details.new(PathInfo.new(swagger_json)) content = File.read(swagger_json, encoding: "utf-8", invalid: :skip) json_obj = JSON.parse(content) base_path = "" @@ -44,9 +45,9 @@ class AnalyzerOAS2 < Analyzer params << param end end - @result << Endpoint.new(base_path + path, method.upcase, params) + @result << Endpoint.new(base_path + path, method.upcase, params, details) else - @result << Endpoint.new(base_path + path, method.upcase) + @result << Endpoint.new(base_path + path, method.upcase, details) end rescue e @logger.debug "Exception of #{swagger_json}/paths/path/method" @@ -67,6 +68,7 @@ class AnalyzerOAS2 < Analyzer if swagger_yamls.is_a?(Array(String)) swagger_yamls.each do |swagger_yaml| if File.exists?(swagger_yaml) + details = Details.new(PathInfo.new(swagger_yaml)) content = File.read(swagger_yaml, encoding: "utf-8", invalid: :skip) yaml_obj = YAML.parse(content) base_path = "" @@ -102,9 +104,9 @@ class AnalyzerOAS2 < Analyzer params << param end end - @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params) + @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params, details) else - @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase) + @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, details) end rescue e @logger.debug "Exception of #{swagger_yaml}/paths/path/method" diff --git a/src/analyzer/analyzers/analyzer_oas3.cr b/src/analyzer/analyzers/analyzer_oas3.cr index 7725d3dd..d7d153ed 100644 --- a/src/analyzer/analyzers/analyzer_oas3.cr +++ b/src/analyzer/analyzers/analyzer_oas3.cr @@ -26,6 +26,7 @@ class AnalyzerOAS3 < Analyzer if oas3_jsons.is_a?(Array(String)) oas3_jsons.each do |oas3_json| if File.exists?(oas3_json) + details = Details.new(PathInfo.new(oas3_json)) content = File.read(oas3_json, encoding: "utf-8", invalid: :skip) json_obj = JSON.parse(content) @@ -76,11 +77,11 @@ class AnalyzerOAS3 < Analyzer end if params.size > 0 - @result << Endpoint.new(base_path + path, method.upcase, params) + @result << Endpoint.new(base_path + path, method.upcase, params, details) elsif params.size > 0 - @result << Endpoint.new(base_path + path, method.upcase, params) + @result << Endpoint.new(base_path + path, method.upcase, params, details) else - @result << Endpoint.new(base_path + path, method.upcase) + @result << Endpoint.new(base_path + path, method.upcase, details) end rescue e @logger.debug "Exception of #{oas3_json}/paths/endpoint" @@ -98,6 +99,7 @@ class AnalyzerOAS3 < Analyzer if oas3_yamls.is_a?(Array(String)) oas3_yamls.each do |oas3_yaml| if File.exists?(oas3_yaml) + details = Details.new(PathInfo.new(oas3_yaml)) content = File.read(oas3_yaml, encoding: "utf-8", invalid: :skip) yaml_obj = YAML.parse(content) @@ -148,11 +150,11 @@ class AnalyzerOAS3 < Analyzer end if params.size > 0 - @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params) + @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params, details) elsif params.size > 0 - @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params) + @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, params, details) else - @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase) + @result << Endpoint.new(base_path + path.to_s, method.to_s.upcase, details) end end rescue e diff --git a/src/analyzer/analyzers/analyzer_php_pure.cr b/src/analyzer/analyzers/analyzer_php_pure.cr index 8ebddb63..c6298a03 100644 --- a/src/analyzer/analyzers/analyzer_php_pure.cr +++ b/src/analyzer/analyzers/analyzer_php_pure.cr @@ -45,10 +45,12 @@ class AnalyzerPhpPure < Analyzer rescue next end + + details = Details.new(PathInfo.new(path)) methods.each do |method| - result << Endpoint.new("/#{relative_path}", method, params_body) + result << Endpoint.new("/#{relative_path}", method, params_body, details) end - result << Endpoint.new("/#{relative_path}", "GET", params_query) + result << Endpoint.new("/#{relative_path}", "GET", params_query, details) end end end diff --git a/src/analyzer/analyzers/analyzer_raml.cr b/src/analyzer/analyzers/analyzer_raml.cr index e84864cc..f9ac8f3b 100644 --- a/src/analyzer/analyzers/analyzer_raml.cr +++ b/src/analyzer/analyzers/analyzer_raml.cr @@ -8,6 +8,8 @@ class AnalyzerRAML < Analyzer if raml_specs.is_a?(Array(String)) raml_specs.each do |raml_spec| if File.exists?(raml_spec) + details = Details.new(PathInfo.new(raml_spec)) + content = File.read(raml_spec, encoding: "utf-8", invalid: :skip) yaml_obj = YAML.parse(content) yaml_obj.as_h.each do |path, path_obj| @@ -45,7 +47,7 @@ class AnalyzerRAML < Analyzer end end - @result << Endpoint.new(path.to_s, method.to_s.upcase, params) + @result << Endpoint.new(path.to_s, method.to_s.upcase, params, details) rescue e @logger.debug "Exception of #{raml_spec}/paths/#{path}/#{method}" @logger.debug_sub e diff --git a/src/analyzer/analyzers/analyzer_ruby_hanami.cr b/src/analyzer/analyzers/analyzer_ruby_hanami.cr index 9e243d6c..25a07c5a 100644 --- a/src/analyzer/analyzers/analyzer_ruby_hanami.cr +++ b/src/analyzer/analyzers/analyzer_ruby_hanami.cr @@ -3,11 +3,13 @@ require "../../models/analyzer" class AnalyzerRubyHanami < Analyzer def analyze # Config Analysis - if File.exists?("#{@base_path}/config/routes.rb") - File.open("#{@base_path}/config/routes.rb", "r", encoding: "utf-8", invalid: :skip) do |file| + path = "#{@base_path}/config/routes.rb" + if File.exists?(path) + File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| - endpoint = line_to_endpoint(line) + file.each_line.with_index do |line, index| + details = Details.new(PathInfo.new(path, index + 1)) + endpoint = line_to_endpoint(line, details) if endpoint.method != "" @result << endpoint last_endpoint = endpoint @@ -20,46 +22,46 @@ class AnalyzerRubyHanami < Analyzer @result end - def line_to_endpoint(content : String) : Endpoint + def line_to_endpoint(content : String, details : Details) : Endpoint content.scan(/get\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "GET") + return Endpoint.new("#{match[1]}", "GET", details) end end content.scan(/post\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "POST") + return Endpoint.new("#{match[1]}", "POST", details) end end content.scan(/put\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "PUT") + return Endpoint.new("#{match[1]}", "PUT", details) end end content.scan(/delete\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "DELETE") + return Endpoint.new("#{match[1]}", "DELETE", details) end end content.scan(/patch\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "PATCH") + return Endpoint.new("#{match[1]}", "PATCH", details) end end content.scan(/head\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "HEAD") + return Endpoint.new("#{match[1]}", "HEAD", details) end end content.scan(/options\s+['"](.+?)['"]/) do |match| if match.size > 1 - return Endpoint.new("#{match[1]}", "OPTIONS") + return Endpoint.new("#{match[1]}", "OPTIONS", details) end end diff --git a/src/analyzer/analyzers/analyzer_ruby_rails.cr b/src/analyzer/analyzers/analyzer_ruby_rails.cr index 67d4bf7b..ea614c76 100644 --- a/src/analyzer/analyzers/analyzer_ruby_rails.cr +++ b/src/analyzer/analyzers/analyzer_ruby_rails.cr @@ -8,7 +8,8 @@ class AnalyzerRubyRails < Analyzer next if File.directory?(file) real_path = "#{@base_path}/public/".gsub(/\/+/, '/') relative_path = file.sub(real_path, "") - @result << Endpoint.new("/#{relative_path}", "GET") + details = Details.new(PathInfo.new(file)) + @result << Endpoint.new("/#{relative_path}", "GET", details) end rescue e logger.debug e @@ -31,20 +32,21 @@ class AnalyzerRubyRails < Analyzer end end + details = Details.new(PathInfo.new("#{@base_path}/config/routes.rb")) line.scan(/get\s+['"](.+?)['"]/) do |match| - @result << Endpoint.new("#{match[1]}", "GET") + @result << Endpoint.new("#{match[1]}", "GET", details) end line.scan(/post\s+['"](.+?)['"]/) do |match| - @result << Endpoint.new("#{match[1]}", "POST") + @result << Endpoint.new("#{match[1]}", "POST", details) end line.scan(/put\s+['"](.+?)['"]/) do |match| - @result << Endpoint.new("#{match[1]}", "PUT") + @result << Endpoint.new("#{match[1]}", "PUT", details) end line.scan(/delete\s+['"](.+?)['"]/) do |match| - @result << Endpoint.new("#{match[1]}", "DELETE") + @result << Endpoint.new("#{match[1]}", "DELETE", details) end line.scan(/patch\s+['"](.+?)['"]/) do |match| - @result << Endpoint.new("#{match[1]}", "PATCH") + @result << Endpoint.new("#{match[1]}", "PATCH", details) end end end @@ -188,6 +190,7 @@ class AnalyzerRubyRails < Analyzer end end + details = Details.new(PathInfo.new(path)) methods.each do |method| if method == "GET/INDEX" if params_method.has_key? "index" @@ -200,7 +203,7 @@ class AnalyzerRubyRails < Analyzer index_params ||= [] of Param deduplication_params_query ||= [] of Param last_params = index_params + deduplication_params_query - @result << Endpoint.new("/#{resource}", "GET", last_params) + @result << Endpoint.new("/#{resource}", "GET", last_params, details) elsif method == "GET/SHOW" if params_method.has_key? "show" show_params = [] of Param @@ -211,7 +214,7 @@ class AnalyzerRubyRails < Analyzer show_params ||= [] of Param deduplication_params_query ||= [] of Param last_params = show_params + deduplication_params_query - @result << Endpoint.new("/#{resource}/1", "GET", last_params) + @result << Endpoint.new("/#{resource}/1", "GET", last_params, details) else if method == "POST" if params_method.has_key? "create" @@ -223,7 +226,7 @@ class AnalyzerRubyRails < Analyzer create_params ||= [] of Param params_body ||= [] of Param last_params = create_params + params_body - @result << Endpoint.new("/#{resource}", method, last_params) + @result << Endpoint.new("/#{resource}", method, last_params, details) elsif method == "DELETE" params_delete = [] of Param if params_method.has_key? "delete" @@ -231,7 +234,7 @@ class AnalyzerRubyRails < Analyzer params_delete << param end end - @result << Endpoint.new("/#{resource}/1", method, params_delete) + @result << Endpoint.new("/#{resource}/1", method, params_delete, details) else if params_method.has_key? "update" update_params = [] of Param @@ -242,7 +245,7 @@ class AnalyzerRubyRails < Analyzer update_params ||= [] of Param params_body ||= [] of Param last_params = update_params + params_body - @result << Endpoint.new("/#{resource}/1", method, last_params) + @result << Endpoint.new("/#{resource}/1", method, last_params, details) end end end diff --git a/src/analyzer/analyzers/analyzer_ruby_sinatra.cr b/src/analyzer/analyzers/analyzer_ruby_sinatra.cr index 798e743e..a7572a73 100644 --- a/src/analyzer/analyzers/analyzer_ruby_sinatra.cr +++ b/src/analyzer/analyzers/analyzer_ruby_sinatra.cr @@ -9,9 +9,11 @@ class AnalyzerRubySinatra < Analyzer if File.exists?(path) File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| last_endpoint = Endpoint.new("", "") - file.each_line do |line| + file.each_line.with_index do |line, index| endpoint = line_to_endpoint(line) if endpoint.method != "" + details = Details.new(PathInfo.new(path, index + 1)) + endpoint.set_details(details) @result << endpoint last_endpoint = endpoint end diff --git a/src/analyzer/analyzers/analyzer_rust_axum.cr b/src/analyzer/analyzers/analyzer_rust_axum.cr index ad02e36b..0b682beb 100644 --- a/src/analyzer/analyzers/analyzer_rust_axum.cr +++ b/src/analyzer/analyzers/analyzer_rust_axum.cr @@ -11,14 +11,15 @@ class AnalyzerRustAxum < Analyzer if File.exists?(path) && File.extname(path) == ".rs" File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| - file.each_line do |line| + file.each_line.with_index do |line, index| if line.includes? ".route(" match = line.match(pattern) if match begin route_argument = match[1] callback_argument = match[2] - result << Endpoint.new("#{route_argument}", callback_to_method(callback_argument)) + details = Details.new(PathInfo.new(path, index + 1)) + result << Endpoint.new("#{route_argument}", callback_to_method(callback_argument), details) rescue end end diff --git a/src/analyzer/analyzers/analyzer_spring.cr b/src/analyzer/analyzers/analyzer_spring.cr index a8d3bee0..4e53ad09 100644 --- a/src/analyzer/analyzers/analyzer_spring.cr +++ b/src/analyzer/analyzers/analyzer_spring.cr @@ -17,7 +17,8 @@ class AnalyzerSpring < Analyzer # Spring MVC has_class_been_imported = false - content.each_line do |line| + content.each_line.with_index do |line, index| + details = Details.new(PathInfo.new(path, index + 1)) if has_class_been_imported == false && REGEX_CLASS_DEFINITION.match(line) has_class_been_imported = true end @@ -40,7 +41,7 @@ class AnalyzerSpring < Analyzer if line.includes? "RequestMethod" define_requestmapping_handlers(["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS", "TRACE"]) else - @result << Endpoint.new("#{url}#{mapping_path}", "GET") + @result << Endpoint.new("#{url}#{mapping_path}", "GET", details) end end end @@ -49,31 +50,31 @@ class AnalyzerSpring < Analyzer if line.includes? "PostMapping" mapping_paths = mapping_to_path(line) mapping_paths.each do |mapping_path| - @result << Endpoint.new("#{url}#{mapping_path}", "POST") + @result << Endpoint.new("#{url}#{mapping_path}", "POST", details) end end if line.includes? "PutMapping" mapping_paths = mapping_to_path(line) mapping_paths.each do |mapping_path| - @result << Endpoint.new("#{url}#{mapping_path}", "PUT") + @result << Endpoint.new("#{url}#{mapping_path}", "PUT", details) end end if line.includes? "DeleteMapping" mapping_paths = mapping_to_path(line) mapping_paths.each do |mapping_path| - @result << Endpoint.new("#{url}#{mapping_path}", "DELETE") + @result << Endpoint.new("#{url}#{mapping_path}", "DELETE", details) end end if line.includes? "PatchMapping" mapping_paths = mapping_to_path(line) mapping_paths.each do |mapping_path| - @result << Endpoint.new("#{url}#{mapping_path}", "PATCH") + @result << Endpoint.new("#{url}#{mapping_path}", "PATCH", details) end end if line.includes? "GetMapping" mapping_paths = mapping_to_path(line) mapping_paths.each do |mapping_path| - @result << Endpoint.new("#{url}#{mapping_path}", "GET") + @result << Endpoint.new("#{url}#{mapping_path}", "GET", details) end end end @@ -85,7 +86,8 @@ class AnalyzerSpring < Analyzer next if match.size != 4 method = match[2] endpoint = match[3].gsub(/\n/, "") - @result << Endpoint.new("#{url}#{endpoint}", method) + details = Details.new(PathInfo.new(path)) + @result << Endpoint.new("#{url}#{endpoint}", method, details) end end end diff --git a/src/analyzer/analyzers/file_analyzers/base64.cr b/src/analyzer/analyzers/file_analyzers/base64.cr index 4b7af710..7028d832 100644 --- a/src/analyzer/analyzers/file_analyzers/base64.cr +++ b/src/analyzer/analyzers/file_analyzers/base64.cr @@ -7,7 +7,7 @@ FileAnalyzer.add_hook(->(path : String, url : String) : Array(Endpoint) { begin File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| - file.each_line do |line| + file.each_line.with_index do |line, index| # Check base64 encoded strings base64_match = line.match(/([A-Za-z0-9+\/]{20,}={0,2})/) if base64_match @@ -16,7 +16,8 @@ FileAnalyzer.add_hook(->(path : String, url : String) : Array(Endpoint) { if url_match parsed_url = URI.parse(url_match[1]) if parsed_url.to_s.includes? url - results << Endpoint.new(parsed_url.path, "GET") + details = Details.new(PathInfo.new(path, index + 1)) + results << Endpoint.new(parsed_url.path, "GET", details) end end end diff --git a/src/analyzer/analyzers/file_analyzers/string.cr b/src/analyzer/analyzers/file_analyzers/string.cr index d5c96a0b..a4cbbbee 100644 --- a/src/analyzer/analyzers/file_analyzers/string.cr +++ b/src/analyzer/analyzers/file_analyzers/string.cr @@ -6,12 +6,13 @@ FileAnalyzer.add_hook(->(path : String, url : String) : Array(Endpoint) { begin File.open(path, "r", encoding: "utf-8", invalid: :skip) do |file| - file.each_line do |line| + file.each_line.with_index do |line, index| url_match = line.match(/(https?:\/\/[^\s"]+)/) if url_match parsed_url = URI.parse(url_match[1]) if parsed_url.to_s.includes? url - results << Endpoint.new(parsed_url.path, "GET") + details = Details.new(PathInfo.new(path, index + 1)) + results << Endpoint.new(parsed_url.path, "GET", details) end end end