From 7033f0f9cf202b8d756d7c272315b08581287154 Mon Sep 17 00:00:00 2001 From: ksg Date: Fri, 3 May 2024 00:00:49 +0900 Subject: [PATCH 01/14] feat: Improved performance in analyzer_java_spring.cr by caching file read data Signed-off-by: ksg --- .../analyzers/analyzer_java_spring.cr | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/analyzer/analyzers/analyzer_java_spring.cr b/src/analyzer/analyzers/analyzer_java_spring.cr index 8c0f611b..4819c468 100644 --- a/src/analyzer/analyzers/analyzer_java_spring.cr +++ b/src/analyzer/analyzers/analyzer_java_spring.cr @@ -5,6 +5,7 @@ require "../../miniparsers/java" class AnalyzerJavaSpring < Analyzer REGEX_ROUTER_CODE_BLOCK = /route\(\)?.*?\);/m REGEX_ROUTE_CODE_LINE = /((?:andRoute|route)\s*\(|\.)\s*(GET|POST|DELETE|PUT)\(\s*"([^"]*)/ + FILE_CONTENT_CACHE = Hash(String, String).new def analyze parser_map = Hash(String, JavaParser).new @@ -31,6 +32,7 @@ class AnalyzerJavaSpring < Analyzer if File.exists?(path) && path.ends_with?(".java") webflux_base_path = find_base_path(path, webflux_base_path_map) content = File.read(path, encoding: "utf-8", invalid: :skip) + FILE_CONTENT_CACHE[path] = content # Spring MVC Router (Controller) spring_web_bind_package = "org.springframework.web.bind.annotation." @@ -75,8 +77,7 @@ class AnalyzerJavaSpring < Analyzer source_path = root_source_directory.join(import_path + ".java") next if source_path.dirname == package_directory || !File.exists?(source_path) if !parser_map.has_key?(source_path.to_s) - _content = File.read(source_path.to_s, encoding: "utf-8", invalid: :skip) - _parser = get_parser(source_path, _content) + _parser = get_parser(source_path) parser_map[source_path.to_s] = _parser _parser.classes.each do |package_class| import_map[package_class.name] = package_class @@ -243,6 +244,21 @@ class AnalyzerJavaSpring < Analyzer @result end + def get_parser(path : Path, content : String = "") + if content == "" + if FILE_CONTENT_CACHE.has_key?(path.to_s) + content = FILE_CONTENT_CACHE[path.to_s] + else + content = File.read(path, encoding: "utf-8", invalid: :skip) + end + end + + lexer = JavaLexer.new + tokens = lexer.tokenize(content) + parser = JavaParser.new(path.to_s, tokens) + parser + end + def find_base_path(current_path : String, base_paths : Hash(String, String)) base_paths.keys.sort_by!(&.size).reverse!.each do |path| if current_path.starts_with?(path) @@ -407,16 +423,6 @@ class AnalyzerJavaSpring < Analyzer end end -def get_parser(path : Path, content : String = "") - if content == "" - content = File.read(path, encoding: "utf-8", invalid: :skip) - end - lexer = JavaLexer.new - tokens = lexer.tokenize(content) - parser = JavaParser.new(path.to_s, tokens) - parser -end - def analyzer_java_spring(options : Hash(Symbol, String)) instance = AnalyzerJavaSpring.new(options) instance.analyze From 48d6ed44b6319edf58eb9aaebdba10e5ddfe5ba4 Mon Sep 17 00:00:00 2001 From: ksg Date: Sat, 4 May 2024 20:30:59 +0900 Subject: [PATCH 02/14] feat: Update Spring MVC Analyzer - Update comments for clarity and accuracy - Refactored the `match_symbol_or_operator` method to `match_other` in `src/minilexers/java.cr`. - Added support for the `==` operator in the `match_other` method in `src/minilexers/java.cr`. Signed-off-by: ksg --- .../analyzers/analyzer_java_spring.cr | 87 ++++++++++--------- src/minilexers/java.cr | 22 +++-- src/models/output_builder.cr | 2 +- 3 files changed, 63 insertions(+), 48 deletions(-) diff --git a/src/analyzer/analyzers/analyzer_java_spring.cr b/src/analyzer/analyzers/analyzer_java_spring.cr index 4819c468..a578195c 100644 --- a/src/analyzer/analyzers/analyzer_java_spring.cr +++ b/src/analyzer/analyzers/analyzer_java_spring.cr @@ -11,38 +11,44 @@ class AnalyzerJavaSpring < Analyzer parser_map = Hash(String, JavaParser).new package_map = Hash(String, Hash(String, ClassModel)).new webflux_base_path_map = Hash(String, String).new + Dir.glob("#{@base_path}/**/*") do |path| + url = "" + + # Extract the Webflux base path from 'application.yml' in specified directories if File.directory?(path) if path.ends_with?("/src") - config_path = File.join(path, "main/resources/application.yml") - if File.exists?(config_path) - config = YAML.parse(File.read(config_path)) rescue nil - if config && (spring = config["spring"]?) && (webflux = spring["webflux"]?) - webflux_base_path = webflux["base-path"]? + application_yml_path = File.join(path, "main/resources/application.yml") + if File.exists?(application_yml_path) + begin + config = YAML.parse(File.read(application_yml_path)) + spring = config["spring"] + webflux = spring["webflux"] + webflux_base_path = webflux["base-path"] + if webflux_base_path webflux_base_path_map[path] = webflux_base_path.as_s end - end + rescue e + next + end end end - - next - end - url = "" - if File.exists?(path) && path.ends_with?(".java") + elsif File.exists?(path) && path.ends_with?(".java") webflux_base_path = find_base_path(path, webflux_base_path_map) + # Load Java file content into cache for processing content = File.read(path, encoding: "utf-8", invalid: :skip) FILE_CONTENT_CACHE[path] = content - # Spring MVC Router (Controller) + # Process files that include Spring MVC bindings for routing spring_web_bind_package = "org.springframework.web.bind.annotation." - has_spring_web_bind_package_been_import = content.includes?(spring_web_bind_package) - if has_spring_web_bind_package_been_import + has_spring_bindings = content.includes?(spring_web_bind_package) + if has_spring_bindings if parser_map.has_key?(path) parser = parser_map[path] tokens = parser.tokens else - parser = get_parser(Path.new(path), content) + parser = create_parser(Path.new(path), content) tokens = parser.tokens parser_map[path] = parser end @@ -62,7 +68,7 @@ class AnalyzerJavaSpring < Analyzer Dir.glob("#{import_directory}/*.java") do |_path| next if path == _path if !parser_map.has_key?(_path) - _parser = get_parser(Path.new(_path)) + _parser = create_parser(Path.new(_path)) parser_map[_path] = _parser else _parser = parser_map[_path] @@ -77,7 +83,7 @@ class AnalyzerJavaSpring < Analyzer source_path = root_source_directory.join(import_path + ".java") next if source_path.dirname == package_directory || !File.exists?(source_path) if !parser_map.has_key?(source_path.to_s) - _parser = get_parser(source_path) + _parser = create_parser(source_path) parser_map[source_path.to_s] = _parser _parser.classes.each do |package_class| import_map[package_class.name] = package_class @@ -91,14 +97,14 @@ class AnalyzerJavaSpring < Analyzer end end - # Packages in same directory + # Import packages from the same directory package_class_map = package_map[package_directory]? if package_class_map.nil? package_class_map = Hash(String, ClassModel).new Dir.glob("#{package_directory}/*.java") do |_path| next if path == _path if !parser_map.has_key?(_path) - _parser = get_parser(Path.new(_path)) + _parser = create_parser(Path.new(_path)) else _parser = parser_map[_path] end @@ -115,6 +121,7 @@ class AnalyzerJavaSpring < Analyzer end end + # Extract URL mappings and methods from Spring MVC annotated classes class_map = package_class_map.merge(import_map) parser.classes.each do |class_model| class_annotation = class_model.annotations["RequestMapping"]? @@ -130,10 +137,10 @@ class AnalyzerJavaSpring < Analyzer end class_model.methods.values.each do |method| - method.annotations.values.each do |method_annotation| # multiline annotations + method.annotations.values.each do |method_annotation| url_paths = Array(String).new - # Spring MVC Decorator + # Spring MVC method mappings request_methods = Array(String).new if method_annotation.name.ends_with? "Mapping" parameter_format = nil @@ -144,13 +151,13 @@ class AnalyzerJavaSpring < Analyzer annotation_parameter_value = annotation_parameter_tokens[-1].value if annotation_parameter_key == "method" if annotation_parameter_value == "}" - # multiple method + # Handle methods declared with multiple HTTP verbs annotation_parameter_tokens.reverse_each do |token| break if token.value == "method" next if token.type == :LBRACE || token.type == :RBRACE next if token.type == :DOT - known_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"] - if known_methods.includes?(token.value) + http_methods = ["GET", "POST", "PUT", "DELETE", "PATCH"] + if http_methods.includes?(token.value) request_methods.push(token.value) end end @@ -158,6 +165,7 @@ class AnalyzerJavaSpring < Analyzer request_methods.push(annotation_parameter_value) end elsif annotation_parameter_key == "consumes" + # Set parameter format based on the 'consumes' attribute of the annotation. if annotation_parameter_value.ends_with? "APPLICATION_FORM_URLENCODED_VALUE" parameter_format = "form" elsif annotation_parameter_value.ends_with? "APPLICATION_JSON_VALUE" @@ -171,6 +179,7 @@ class AnalyzerJavaSpring < Analyzer webflux_base_path = webflux_base_path[..-2] end + # Parse and construct endpoints for methods annotated with 'RequestMapping' or specific HTTP methods if method_annotation.name == "RequestMapping" url_paths = [""] if method_annotation.params.size > 0 @@ -181,7 +190,7 @@ class AnalyzerJavaSpring < Analyzer details = Details.new(PathInfo.new(path, line)) if request_methods.empty? - # If the method is not annotated with @RequestMapping, then 5 methods are allowed + # Handle default HTTP methods if no specific method is annotated ["GET", "POST", "PUT", "DELETE", "PATCH"].each do |_request_method| parameters = get_endpoint_parameters(parser, _request_method, method, parameter_format, class_map) url_paths.each do |url_path| @@ -189,6 +198,7 @@ class AnalyzerJavaSpring < Analyzer end end else + # Create endpoints for annotated HTTP methods url_paths.each do |url_path| request_methods.each do |request_method| parameters = get_endpoint_parameters(parser, request_method, method, parameter_format, class_map) @@ -198,6 +208,7 @@ class AnalyzerJavaSpring < Analyzer end break else + # Handle other specific mapping annotations like 'GetMapping', 'PostMapping', etc mapping_annotations = ["GetMapping", "PostMapping", "PutMapping", "DeleteMapping", "PatchMapping"] mapping_index = mapping_annotations.index(method_annotation.name) if !mapping_index.nil? @@ -225,7 +236,7 @@ class AnalyzerJavaSpring < Analyzer end end else - # Reactive Router + # Extract and construct endpoints from reactive route configurations content.scan(REGEX_ROUTER_CODE_BLOCK) do |route_code| method_code = route_code[0] method_code.scan(REGEX_ROUTE_CODE_LINE) do |match| @@ -244,7 +255,7 @@ class AnalyzerJavaSpring < Analyzer @result end - def get_parser(path : Path, content : String = "") + def create_parser(path : Path, content : String = "") if content == "" if FILE_CONTENT_CACHE.has_key?(path.to_s) content = FILE_CONTENT_CACHE[path.to_s] @@ -270,10 +281,10 @@ class AnalyzerJavaSpring < Analyzer end def get_mapping_path(parser : JavaParser, tokens : Array(Token), method_params : Array(Array(Token))) - # 1. Search for the value of the @xxxxxMapping annotation - # 2. If the value is a string literal, return it - # 3. If the value is an array, return each element - # 4. Other case return empty array + # 1. Search for the value of the Mapping annotation. + # 2. If the value is a string literal, return the literal. + # 3. If the value is an array, return each element of the array. + # 4. In other cases, return an empty array. url_paths = Array(String).new if method_params[0].size != 0 path_argument_index = 0 @@ -284,11 +295,10 @@ class AnalyzerJavaSpring < Analyzer end path_parameter_tokens = method_params[path_argument_index] + # Extract single and multiple mapping path if path_parameter_tokens[-1].type == :STRING_LITERAL - # @GetMapping("/abc") or @GetMapping(value = "/abc") url_paths << path_parameter_tokens[-1].value[1..-2] elsif path_parameter_tokens[-1].type == :RBRACE - # @GetMapping({"/abc", "/def"}) or @GetMapping(value = {"/abc", "/def"}) i = path_parameter_tokens.size - 2 while i > 0 parameter_token = path_parameter_tokens[i] @@ -335,9 +345,9 @@ class AnalyzerJavaSpring < Analyzer end default_value = nil - # @RequestParam(@RequestParam long time) -> time + # Extract parameter name directly if not an identifier parameter_name = method_param_tokens[-1].value - if method_param_tokens[-1].type != IDENTIFIER && method_param_tokens.size > 2 + if method_param_tokens.size > 2 if method_param_tokens[2].type == :LPAREN request_parameters = parser.parse_formal_parameters(method_param_tokens, 2) request_parameters.each do |request_parameter_tokens| @@ -345,17 +355,16 @@ class AnalyzerJavaSpring < Analyzer request_param_name = request_parameter_tokens[0].value request_param_value = request_parameter_tokens[-1].value + # Extract 'name' from @RequestParam(value/defaultValue = "name") if request_param_name == "value" - # abc(@RequestParam(value = "name") int xx) -> name parameter_name = request_param_value[1..-2] elsif request_param_name == "defaultValue" - # abc(@RequestParam(defaultValue = "defaultValue") String xx) -> defaultValue default_value = request_param_value[1..-2] end end end + # Handle direct string literal as parameter name, e.g., @RequestParam("name") if method_param_tokens[3].type == :STRING_LITERAL - # abc(@RequestParam("name") int xx) -> name parameter_name_token = method_param_tokens[3] parameter_name = parameter_name_token.value[1..-2] end @@ -405,7 +414,7 @@ class AnalyzerJavaSpring < Analyzer i += 1 end else - # custom class" + # Map fields of user-defined class to parameters. if package_class_map.has_key?(parameter_type) package_class = package_class_map[parameter_type] package_class.fields.values.each do |field| diff --git a/src/minilexers/java.cr b/src/minilexers/java.cr index e9926f17..d78c773f 100644 --- a/src/minilexers/java.cr +++ b/src/minilexers/java.cr @@ -192,7 +192,7 @@ class JavaLexer < MiniLexer when '"' match_string_literal_or_text_block else - match_symbol_or_operator + match_other end end @@ -335,7 +335,7 @@ class JavaLexer < MiniLexer @position += match[0].size else # impossible to reach here - self << Tuple.new(:IDENTIFIER, @input[@position].to_s) + self << Tuple.new(:UNKNOWN, @input[@position].to_s) @position += 1 end end @@ -349,28 +349,34 @@ class JavaLexer < MiniLexer @position += match[0].size else # impossible to reach here - self << Tuple.new(:IDENTIFIER, @input[@position].to_s) + self << Tuple.new(:UNKNOWN, @input[@position].to_s) @position += 1 end end - def match_symbol_or_operator + def match_other case @input[@position] when '(' then self << Tuple.new(:LPAREN, "(") when ')' then self << Tuple.new(:RPAREN, ")") - when ' ' then self << Tuple.new(:WHITESPACE, " ") when '.' then self << Tuple.new(:DOT, ".") when ',' then self << Tuple.new(:COMMA, ",") when '@' then self << Tuple.new(:AT, "@") when '{' then self << Tuple.new(:LBRACE, "{") when '}' then self << Tuple.new(:RBRACE, "}") - when '\t' then self << Tuple.new(:TAB, "\t") when ';' then self << Tuple.new(:SEMI, ";") - when '=' then self << Tuple.new(:ASSIGN, "=") + when '=' + if @input[@position + 1] == '=' + @position += 1 + Tuple.new(:EQUAL, "==") + else + Tuple.new(:ASSIGN, "=") + end + when '\t' then self << Tuple.new(:TAB, "\t") + when ' ' then self << Tuple.new(:WHITESPACE, " ") when '\n' self << Tuple.new(:NEWLINE, "\n") else - self << Tuple.new(:IDENTIFIER, @input[@position].to_s) + self << Tuple.new(:UNKNOWN, @input[@position].to_s) end @position += 1 end diff --git a/src/models/output_builder.cr b/src/models/output_builder.cr index 2443e5a0..c796d6fe 100644 --- a/src/models/output_builder.cr +++ b/src/models/output_builder.cr @@ -44,7 +44,7 @@ class OutputBuilder first_form = true if final_url.starts_with?("//") - if final_url[2] != ':' + if final_url.size != 2 && final_url[2] != ':' final_url = final_url[1..] end end From 64c66e660afc1d0e3e226c7b2dc43e79f6f20bfe Mon Sep 17 00:00:00 2001 From: ksg Date: Sat, 4 May 2024 22:37:01 +0900 Subject: [PATCH 03/14] feat: Skip whitespace for Java lexer efficiency - Replaced `before_skip_position` variable with `after_skip` for clarity and consistency Signed-off-by: ksg --- src/analyzer/analyzers/analyzer_java_spring.cr | 5 ++--- src/minilexers/java.cr | 9 +++++---- src/miniparsers/java.cr | 14 ++++++-------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/analyzer/analyzers/analyzer_java_spring.cr b/src/analyzer/analyzers/analyzer_java_spring.cr index a578195c..f1b294dd 100644 --- a/src/analyzer/analyzers/analyzer_java_spring.cr +++ b/src/analyzer/analyzers/analyzer_java_spring.cr @@ -5,7 +5,7 @@ require "../../miniparsers/java" class AnalyzerJavaSpring < Analyzer REGEX_ROUTER_CODE_BLOCK = /route\(\)?.*?\);/m REGEX_ROUTE_CODE_LINE = /((?:andRoute|route)\s*\(|\.)\s*(GET|POST|DELETE|PUT)\(\s*"([^"]*)/ - FILE_CONTENT_CACHE = Hash(String, String).new + FILE_CONTENT_CACHE = Hash(String, String).new def analyze parser_map = Hash(String, JavaParser).new @@ -379,12 +379,11 @@ class AnalyzerJavaSpring < Analyzer elsif parameter_type == "HttpServletRequest" i = 0 while i < method.body.size - 6 - if [:TAB, :WHITESPACE, :NEWLINE].index(method.body[i].type) + if [:TAB, :NEWLINE].index(method.body[i].type) i += 1 next end - next if method.body[i].type == :WHITESPACE next if method.body[i].type == :NEWLINE if method.body[i].type == :IDENTIFIER && method.body[i].value == argument_name diff --git a/src/minilexers/java.cr b/src/minilexers/java.cr index d78c773f..45d258de 100644 --- a/src/minilexers/java.cr +++ b/src/minilexers/java.cr @@ -174,11 +174,11 @@ class JavaLexer < MiniLexer end def tokenize_logic(@input : String) : Array(Token) + after_skip = -1 while @position < @input.size - before_skip_position = -1 - while before_skip_position < @position + while @position != after_skip skip_whitespace_and_comments - before_skip_position = @position + after_skip = @position end break if @position == @input.size @@ -372,9 +372,10 @@ class JavaLexer < MiniLexer Tuple.new(:ASSIGN, "=") end when '\t' then self << Tuple.new(:TAB, "\t") - when ' ' then self << Tuple.new(:WHITESPACE, " ") when '\n' self << Tuple.new(:NEWLINE, "\n") + when ' ' + # Skipping whitespace for efficiency else self << Tuple.new(:UNKNOWN, @input[@position].to_s) end diff --git a/src/miniparsers/java.cr b/src/miniparsers/java.cr index 6f1fbe27..5489438c 100644 --- a/src/miniparsers/java.cr +++ b/src/miniparsers/java.cr @@ -98,9 +98,7 @@ class JavaParser return parameters if tokens.size <= param_start_index while param_start_index < tokens.size - if tokens[param_start_index].type == :WHITESPACE - param_start_index += 1 - elsif tokens[param_start_index].type == :TAB + if tokens[param_start_index].type == :TAB param_start_index += 1 elsif tokens[param_start_index].type == :NEWLINE param_start_index += 1 @@ -138,7 +136,7 @@ class JavaParser parameter_token << token end else - unless token.type == :WHITESPACE || token.type == :TAB || token.type == :NEWLINE + unless token.type == :TAB || token.type == :NEWLINE parameter_token << token end end @@ -171,7 +169,7 @@ class JavaParser starts_with_at = while annotation_token_index < last_newline_index if tokens[annotation_token_index].type == :AT break true - elsif tokens[annotation_token_index].type == :WHITESPACE || tokens[annotation_token_index].type == :TAB || tokens[annotation_token_index].type == :WHITESPACE + elsif tokens[annotation_token_index].type == :TAB annotation_token_index += 1 next else @@ -202,7 +200,7 @@ class JavaParser lbrace = rbrace = 0 tokens.each do |token| - if !start_token_parse && token.type == :CLASS && tokens[token.index + 1].type == :WHITESPACE + if !start_token_parse && token.type == :CLASS start_token_parse = true class_body = Array(Token).new lbrace = rbrace = 0 @@ -292,7 +290,7 @@ class JavaParser line_tokens = Array(Token).new class_tokens[field_index + 1..semi_index - 1].each do |line_token| - next if line_token.type == :WHITESPACE || line_token.type == :TAB + next if line_token.type == :TAB line_tokens << line_token end @@ -427,7 +425,7 @@ class JavaParser end break - elsif previous_token.type == :WHITESPACE || previous_token.type == :TAB || previous_token.type == :NEWLINE + elsif previous_token.type == :TAB || previous_token.type == :NEWLINE previous_token_index -= 1 next elsif has_exception From 53b3241b22f98706371ee0f32b899adf0c165bd8 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 5 May 2024 00:28:17 +0900 Subject: [PATCH 04/14] Update CONTRIBUTING.md --- CONTRIBUTING.md | 42 +++++++++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c31d0c9d..5314911f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,23 @@ -## ❤️ Contribute -1. Write code in forked repo -2. Make Pull Request to `dev` branch -3. Finish :D +# ❤️ Contribution Guidelines + +Thank you for considering contributing to our project! Here are some guidelines to help you get started and ensure a smooth contribution process. + +1. Fork and Code +- Begin by forking the repository. +- Write your code within your forked repository. + +3. Pull Request +- Once your contribution is ready, create a Pull Request (PR) to the dev branch of the main repository. +- Provide a clear and concise description of your changes in the PR. + +4. Completion +- That's it! You're done. Await feedback and further instructions from the maintainers. ![](https://github.com/hahwul/noir/assets/13212227/23989dab-6b4d-4f18-904f-7f5cfd172b04) -## 🛠️ How to Build and Test? +## 🛠️ Building and Testing ### Clone and Install Dependencies + ```bash # If you've forked this repository, clone to https://github.com//noir git clone https://github.com/hahwul/noir @@ -38,13 +49,14 @@ ameba --fix ``` ## 🧭 Code structure -- spec (for `crystal spec`) - - unit_test: unit-test codes - - functional_test: functional test codes -- src - - analyzer: Code analyzers for Endpoint URL and Parameter analysis - - detector: Codes for language, framework identification - - models: Everything for the model, such as class, structure, etc - - utils: Utility codes - - etc... -- noir.cr: main and command-line parser + +- spec: + - unit_test: Unit test codes. (for `crystal spec` command) + - functional_test: Functional test codes. +- src: Contains the source code. + - analyzer: Code analyzers for Endpoint URL and Parameter analysis. + - detector: Codes for language and framework identification. + - models: Contains everything related to models, such as classes and structures. +- noir.cr: Main file and command-line parser. + +Feel free to reach out to us if you have any questions or need further assistance! \ No newline at end of file From e6d11b68ebd839c6a8540cc02bf78a0c3eb13b80 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 5 May 2024 01:45:33 +0900 Subject: [PATCH 05/14] Add unit tests for detecting various frameworks --- .../detector/detect_crystal_lucky_spec.cr | 10 ++++++++++ .../detector/detect_cs_aspnet_mvc_spec.cr | 10 ++++++++++ .../detector/detect_elixir_phoenix_spec.cr | 10 ++++++++++ spec/unit_test/detector/detect_go_beego_spec.cr | 10 ++++++++++ spec/unit_test/detector/detect_go_fiber_spec.cr | 10 ++++++++++ spec/unit_test/detector/detect_go_gin_spec.cr | 10 ++++++++++ .../detector/detect_python_fastapi_spec.cr | 10 ++++++++++ spec/unit_test/detector/detect_raml_spec.cr | 17 +++++++++++++++++ .../detector/detect_ruby_hanami_spec.cr | 13 +++++++++++++ .../unit_test/detector/detect_rust_axum_spec.cr | 10 ++++++++++ .../detector/detect_rust_rocket_spec.cr | 10 ++++++++++ 11 files changed, 120 insertions(+) create mode 100644 spec/unit_test/detector/detect_crystal_lucky_spec.cr create mode 100644 spec/unit_test/detector/detect_cs_aspnet_mvc_spec.cr create mode 100644 spec/unit_test/detector/detect_elixir_phoenix_spec.cr create mode 100644 spec/unit_test/detector/detect_go_beego_spec.cr create mode 100644 spec/unit_test/detector/detect_go_fiber_spec.cr create mode 100644 spec/unit_test/detector/detect_go_gin_spec.cr create mode 100644 spec/unit_test/detector/detect_python_fastapi_spec.cr create mode 100644 spec/unit_test/detector/detect_raml_spec.cr create mode 100644 spec/unit_test/detector/detect_ruby_hanami_spec.cr create mode 100644 spec/unit_test/detector/detect_rust_axum_spec.cr create mode 100644 spec/unit_test/detector/detect_rust_rocket_spec.cr diff --git a/spec/unit_test/detector/detect_crystal_lucky_spec.cr b/spec/unit_test/detector/detect_crystal_lucky_spec.cr new file mode 100644 index 00000000..86e8ccd7 --- /dev/null +++ b/spec/unit_test/detector/detect_crystal_lucky_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Crystal Lucky" do + options = default_options() + instance = DetectorCrystalLucky.new options + + it "shard.yml" do + instance.detect("shard.yml", "luckyframework/lucky").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_cs_aspnet_mvc_spec.cr b/spec/unit_test/detector/detect_cs_aspnet_mvc_spec.cr new file mode 100644 index 00000000..f7917c42 --- /dev/null +++ b/spec/unit_test/detector/detect_cs_aspnet_mvc_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect C# ASP.Net MVC" do + options = default_options() + instance = DetectorCSharpAspNetMvc.new options + + it "packages" do + instance.detect("packages.config", "Microsoft.AspNet.Mvc").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_elixir_phoenix_spec.cr b/spec/unit_test/detector/detect_elixir_phoenix_spec.cr new file mode 100644 index 00000000..1316fa5f --- /dev/null +++ b/spec/unit_test/detector/detect_elixir_phoenix_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Elixir Phoenix" do + options = default_options() + instance = DetectorElixirPhoenix.new options + + it "mix" do + instance.detect("mix.exs", "ElixirPhoenix").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_go_beego_spec.cr b/spec/unit_test/detector/detect_go_beego_spec.cr new file mode 100644 index 00000000..8e559a4a --- /dev/null +++ b/spec/unit_test/detector/detect_go_beego_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Go BeegoEcho" do + options = default_options() + instance = DetectorGoBeego.new options + + it "go.mod" do + instance.detect("go.mod", "github.com/beego/beego").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_go_fiber_spec.cr b/spec/unit_test/detector/detect_go_fiber_spec.cr new file mode 100644 index 00000000..c219b80d --- /dev/null +++ b/spec/unit_test/detector/detect_go_fiber_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Go Fiber" do + options = default_options() + instance = DetectorGoFiber.new options + + it "go.mod" do + instance.detect("go.mod", "github.com/gofiber/fiber").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_go_gin_spec.cr b/spec/unit_test/detector/detect_go_gin_spec.cr new file mode 100644 index 00000000..1c0b73c5 --- /dev/null +++ b/spec/unit_test/detector/detect_go_gin_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Go Gin" do + options = default_options() + instance = DetectorGoGin.new options + + it "go.mod" do + instance.detect("go.mod", "github.com/gin-gonic/gin").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_python_fastapi_spec.cr b/spec/unit_test/detector/detect_python_fastapi_spec.cr new file mode 100644 index 00000000..ecf9dc8e --- /dev/null +++ b/spec/unit_test/detector/detect_python_fastapi_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Python FastAPI" do + options = default_options() + instance = DetectorPythonFastAPI.new options + + it "settings.py" do + instance.detect("settings.py", "from fastapi").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_raml_spec.cr b/spec/unit_test/detector/detect_raml_spec.cr new file mode 100644 index 00000000..861b845d --- /dev/null +++ b/spec/unit_test/detector/detect_raml_spec.cr @@ -0,0 +1,17 @@ +require "../../../src/detector/detectors/*" + +describe "Detect RAML" do + options = default_options() + instance = DetectorRAML.new options + + it "raml" do + instance.detect("app.yaml", "#%RAML\nApp: 1").should eq(true) + end + + it "code_locator" do + locator = CodeLocator.instance + locator.clear "raml-spec" + instance.detect("app.yaml", "#%RAML\nApp: 1") + locator.all("raml-spec").should eq(["app.yaml"]) + end +end diff --git a/spec/unit_test/detector/detect_ruby_hanami_spec.cr b/spec/unit_test/detector/detect_ruby_hanami_spec.cr new file mode 100644 index 00000000..692b5fd4 --- /dev/null +++ b/spec/unit_test/detector/detect_ruby_hanami_spec.cr @@ -0,0 +1,13 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Ruby Hanami" do + options = default_options() + instance = DetectorRubyHanami.new options + + it "gemfile/single_quot" do + instance.detect("Gemfile", "gem 'hanami'").should eq(true) + end + it "gemfile/double_quot" do + instance.detect("Gemfile", "gem \"hanami\"").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_rust_axum_spec.cr b/spec/unit_test/detector/detect_rust_axum_spec.cr new file mode 100644 index 00000000..55557836 --- /dev/null +++ b/spec/unit_test/detector/detect_rust_axum_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Rust Axum" do + options = default_options() + instance = DetectorRustAxum.new options + + it "Gargo.toml" do + instance.detect("Cargo.toml", "[dependencies]\naxum = {}").should eq(true) + end +end diff --git a/spec/unit_test/detector/detect_rust_rocket_spec.cr b/spec/unit_test/detector/detect_rust_rocket_spec.cr new file mode 100644 index 00000000..16a0e931 --- /dev/null +++ b/spec/unit_test/detector/detect_rust_rocket_spec.cr @@ -0,0 +1,10 @@ +require "../../../src/detector/detectors/*" + +describe "Detect Rust Rocket" do + options = default_options() + instance = DetectorRustRocket.new options + + it "Gargo.toml" do + instance.detect("Cargo.toml", "[dependencies]\nrocket = {}").should eq(true) + end +end From bee287e84641328bf0a1c458bd759e3179f41f3d Mon Sep 17 00:00:00 2001 From: ksg Date: Sun, 5 May 2024 03:24:53 +0900 Subject: [PATCH 06/14] refactor: Improve token handling for import statement parsing - Added conditions to check for `:STATIC` and `:IDENTIFIER` types of `next_token` in `src/miniparsers/java.cr` - Modified the `trace` method in `src/models/minilexer/minilexer.cr` to correctly display source lines and tokens Signed-off-by: ksg --- src/miniparsers/java.cr | 31 +++++++++++++++++++------------ src/models/minilexer/minilexer.cr | 17 ++++++++++++----- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/src/miniparsers/java.cr b/src/miniparsers/java.cr index 5489438c..2a4973d9 100644 --- a/src/miniparsers/java.cr +++ b/src/miniparsers/java.cr @@ -67,23 +67,30 @@ class JavaParser def parse_import_statements(tokens : Array(Token)) import_tokens = tokens.select { |token| token.type == :IMPORT } import_tokens.each do |import_token| - next_token_index = import_token.index + 2 + next_token_index = import_token.index + 1 next_token = tokens[next_token_index] - if next_token && next_token.type == :IDENTIFIER - import_statement = next_token.value - next_token_index += 1 - - while next_token_index < tokens.size && tokens[next_token_index].type == :DOT - next_token_index += 1 - identifier_token = tokens[next_token_index] - break if !identifier_token || identifier_token.type != :IDENTIFIER - - import_statement += ".#{identifier_token.value}" + if next_token + if next_token.type == :STATIC next_token_index += 1 + next_token = tokens[next_token_index] end + if next_token.type == :IDENTIFIER + import_statement = next_token.value + next_token_index += 1 - @import_statements << import_statement + while next_token_index < tokens.size && tokens[next_token_index].type == :DOT + next_token_index += 1 + identifier_token = tokens[next_token_index] + break if !identifier_token + break if identifier_token.type != :IDENTIFIER && identifier_token.value != "*" + + import_statement += ".#{identifier_token.value}" + next_token_index += 1 + end + + @import_statements << import_statement + end end end end diff --git a/src/models/minilexer/minilexer.cr b/src/models/minilexer/minilexer.cr index 237c7222..85d5ae18 100644 --- a/src/models/minilexer/minilexer.cr +++ b/src/models/minilexer/minilexer.cr @@ -37,6 +37,14 @@ class MiniLexer @tokens << Token.new(t[0], t[1], @tokens.size, @position, line()) end + def <<(t : Tuple(Symbol, Char)) + @tokens << Token.new(t[0], t[1].to_s, @tokens.size, @position, line()) + end + + def <<(t : Tuple(Symbol, Char | String)) + @tokens << Token.new(t[0], t[1].to_s, @tokens.size, @position, line()) + end + def tokenize(@input : String) : Array(Token) results = tokenize_logic(input) @@ -57,14 +65,13 @@ class MiniLexer end def trace - line_number = 1 - # source_line = "" + line_number = -1 lines = @input.split "\n" puts "line size: #{lines.size}, token number: #{tokens.size}" @tokens.each do |token| - if token.line == line_number - puts "\nLine #{line_number}: " + lines[line_number - 1] - line_number += 1 + if line_number <= token.line + puts "\nLine #{token.line}: " + lines[token.line - 1] + line_number = token.line + 1 end puts token.to_s end From e467a823513f283ef1b1c0b53d7c9f4249d932d0 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 5 May 2024 17:29:20 +0900 Subject: [PATCH 07/14] Fixed #293 --- src/output_builder/only-header.cr | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/output_builder/only-header.cr b/src/output_builder/only-header.cr index d8eb97c8..76dd2ec5 100644 --- a/src/output_builder/only-header.cr +++ b/src/output_builder/only-header.cr @@ -4,14 +4,21 @@ require "../models/endpoint" class OutputBuilderOnlyHeader < OutputBuilder def print(endpoints : Array(Endpoint)) headers = [] of String + cookie = false endpoints.each do |endpoint| endpoint.params.each do |param| if param.param_type == "header" headers << param.name + elsif param.param_type == "cookie" + cookie = true end end end + if cookie + headers << "Cookie" + end + headers.uniq.each do |header| puts header.colorize(:light_green).toggle(@is_color) end From 1a45dc6ed1be83c6a8f6aea54eada8a1cc14b435 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 5 May 2024 17:30:00 +0900 Subject: [PATCH 08/14] Refactor AnalyzerJavaSpring and JavaLexer classes --- src/analyzer/analyzers/analyzer_java_spring.cr | 4 ++-- src/minilexers/java.cr | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/analyzer/analyzers/analyzer_java_spring.cr b/src/analyzer/analyzers/analyzer_java_spring.cr index f1b294dd..c4a52c44 100644 --- a/src/analyzer/analyzers/analyzer_java_spring.cr +++ b/src/analyzer/analyzers/analyzer_java_spring.cr @@ -5,7 +5,7 @@ require "../../miniparsers/java" class AnalyzerJavaSpring < Analyzer REGEX_ROUTER_CODE_BLOCK = /route\(\)?.*?\);/m REGEX_ROUTE_CODE_LINE = /((?:andRoute|route)\s*\(|\.)\s*(GET|POST|DELETE|PUT)\(\s*"([^"]*)/ - FILE_CONTENT_CACHE = Hash(String, String).new + FILE_CONTENT_CACHE = Hash(String, String).new def analyze parser_map = Hash(String, JavaParser).new @@ -31,7 +31,7 @@ class AnalyzerJavaSpring < Analyzer end rescue e next - end + end end end elsif File.exists?(path) && path.ends_with?(".java") diff --git a/src/minilexers/java.cr b/src/minilexers/java.cr index 45d258de..de46085f 100644 --- a/src/minilexers/java.cr +++ b/src/minilexers/java.cr @@ -356,14 +356,14 @@ class JavaLexer < MiniLexer def match_other case @input[@position] - when '(' then self << Tuple.new(:LPAREN, "(") - when ')' then self << Tuple.new(:RPAREN, ")") - when '.' then self << Tuple.new(:DOT, ".") - when ',' then self << Tuple.new(:COMMA, ",") - when '@' then self << Tuple.new(:AT, "@") - when '{' then self << Tuple.new(:LBRACE, "{") - when '}' then self << Tuple.new(:RBRACE, "}") - when ';' then self << Tuple.new(:SEMI, ";") + when '(' then self << Tuple.new(:LPAREN, "(") + when ')' then self << Tuple.new(:RPAREN, ")") + when '.' then self << Tuple.new(:DOT, ".") + when ',' then self << Tuple.new(:COMMA, ",") + when '@' then self << Tuple.new(:AT, "@") + when '{' then self << Tuple.new(:LBRACE, "{") + when '}' then self << Tuple.new(:RBRACE, "}") + when ';' then self << Tuple.new(:SEMI, ";") when '=' if @input[@position + 1] == '=' @position += 1 From 3fc459d0aa97a62d3512fe62edbb72d07a72834c Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 5 May 2024 23:47:52 +0900 Subject: [PATCH 09/14] Update installation instructions and add usage example --- README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e173f632..7ba1ba68 100644 --- a/README.md +++ b/README.md @@ -88,7 +88,7 @@ ## Installation -### Homebrew (macOS) +### Homebrew ```bash brew install noir @@ -96,7 +96,7 @@ brew install noir # https://formulae.brew.sh/formula/noir ``` -### Snapcraft (linux) +### Snapcraft ```bash sudo snap install noir @@ -125,10 +125,14 @@ cp ./bin/noir /usr/bin/ ### Docker (GHCR) ```bash -docker pull ghcr.io/noir-cr/noir:latest +docker pull ghcr.io/noir-cr/noir:main ``` ## Usage +```bash +noir -h +``` + ``` Usage: noir Basic: From 2adf937278159ef4dce556ea5ac8149e5ea4a6ca Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Fri, 10 May 2024 23:06:43 +0900 Subject: [PATCH 10/14] Add anything issue template --- .github/ISSUE_TEMPLATE/anything.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/anything.md diff --git a/.github/ISSUE_TEMPLATE/anything.md b/.github/ISSUE_TEMPLATE/anything.md new file mode 100644 index 00000000..6087e5ce --- /dev/null +++ b/.github/ISSUE_TEMPLATE/anything.md @@ -0,0 +1,9 @@ +--- +name: Anything +about: Anything! +title: +labels: +assignees: + +--- + From dab7354401cb1a6dca71c63fbe39a8f3cf713107 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sat, 11 May 2024 00:24:43 +0900 Subject: [PATCH 11/14] Update usage --- src/noir.cr | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/noir.cr b/src/noir.cr index fcc5321d..b9b346cd 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -13,12 +13,13 @@ noir_options = default_options() banner() OptionParser.parse do |parser| - parser.banner = "Usage: noir " - parser.separator " Basic:".colorize(:blue) + parser.banner = "USAGE: noir \n" + parser.separator "FLAGS:" + parser.separator " BASE:".colorize(:blue) parser.on "-b PATH", "--base-path ./app", "(Required) Set base path" { |var| noir_options[:base] = var } parser.on "-u URL", "--url http://..", "Set base url for endpoints" { |var| noir_options[:url] = var } - parser.separator "\n Output:".colorize(:blue) + parser.separator "\n OUTPUT:".colorize(:blue) parser.on "-f FORMAT", "--format json", "Set output format\n * plain yaml json jsonl markdown-table\n * curl httpie oas2 oas3\n * only-url only-param only-header only-cookie" { |var| noir_options[:format] = var } parser.on "-o PATH", "--output out.txt", "Write result to file" { |var| noir_options[:output] = var } @@ -33,7 +34,7 @@ OptionParser.parse do |parser| noir_options[:nolog] = "yes" end - parser.separator "\n Tagger:".colorize(:blue) + parser.separator "\n TAGGER:".colorize(:blue) parser.on "-T", "--use-all-taggers", "Activates all taggers for full analysis coverage" { |_| noir_options[:all_taggers] = "yes" } parser.on "--use-taggers VALUES", "Activates specific taggers (e.g., --use-taggers hunt,oauth)" { |var| noir_options[:use_taggers] = var } parser.on "--list-taggers", "Lists all available taggers" do @@ -48,7 +49,7 @@ OptionParser.parse do |parser| exit end - parser.separator "\n Deliver:".colorize(:blue) + parser.separator "\n DELIVER:".colorize(:blue) parser.on "--send-req", "Send results to a web request" { |_| noir_options[:send_req] = "yes" } parser.on "--send-proxy http://proxy..", "Send results to a web request via an HTTP proxy" { |var| noir_options[:send_proxy] = var } parser.on "--send-es http://es..", "Send results to Elasticsearch" { |var| noir_options[:send_es] = var } @@ -62,7 +63,7 @@ OptionParser.parse do |parser| noir_options[:use_filters] += "#{var}::NOIR::FILTER::SPLIT::" end - parser.separator "\n Technologies:".colorize(:blue) + parser.separator "\n TECHNOLOGIES:".colorize(:blue) parser.on "-t TECHS", "--techs rails,php", "Specify the technologies to use" { |var| noir_options[:techs] = var } parser.on "--exclude-techs rails,php", "Specify the technologies to be excluded" { |var| noir_options[:exclude_techs] = var } parser.on "--list-techs", "Show all technologies" do @@ -77,11 +78,11 @@ OptionParser.parse do |parser| exit end - parser.separator "\n Config:".colorize(:blue) + parser.separator "\n CONFIG:".colorize(:blue) parser.on "--config-file ./config.yaml", "Specify the path to a configuration file in YAML format" { |var| noir_options[:config_file] = var } parser.on "--concurrency 100", "Set concurrency" { |var| noir_options[:concurrency] = var } - parser.separator "\n Others:".colorize(:blue) + parser.separator "\n OTHERS:".colorize(:blue) parser.on "-d", "--debug", "Show debug messages" do noir_options[:debug] = "yes" end @@ -91,6 +92,18 @@ OptionParser.parse do |parser| end parser.on "-h", "--help", "Show help" do puts parser + puts "" + puts "EXAMPLES:" + puts " Basic run of noir:".colorize(:green) + puts " $ noir -b ." + puts " Running noir targeting a specific URL and forwarding results through a proxy:".colorize(:green) + puts " $ noir -b . -u http://example.com" + puts " $ noir -b . -u http://example.com --send-proxy http://localhost:8090" + puts " Running noir for detailed analysis:".colorize(:green) + puts " $ noir -b . -T --include-path" + puts " Running noir with output limited to JSON or YAML format, without logs:".colorize(:green) + puts " $ noir -b . -f json --no-log" + puts " $ noir -b . -f yaml --no-log" exit end parser.invalid_option do |flag| From 1625d853ffca69a0404e46878e599f0eed629653 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sat, 11 May 2024 00:25:18 +0900 Subject: [PATCH 12/14] Update README --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7ba1ba68..b387f850 100644 --- a/README.md +++ b/README.md @@ -134,12 +134,14 @@ noir -h ``` ``` -Usage: noir - Basic: +USAGE: noir + +FLAGS: + BASE: -b PATH, --base-path ./app (Required) Set base path -u URL, --url http://.. Set base url for endpoints - Output: + OUTPUT: -f FORMAT, --format json Set output format * plain yaml json jsonl markdown-table * curl httpie oas2 oas3 @@ -150,12 +152,12 @@ Usage: noir --no-color Disable color output --no-log Displaying only the results - Tagger: + TAGGER: -T, --use-all-taggers Activates all taggers for full analysis coverage - --use-taggers VALUES Activates specific taggers (e.g., --use-taggers hunt,etc) + --use-taggers VALUES Activates specific taggers (e.g., --use-taggers hunt,oauth) --list-taggers Lists all available taggers - Deliver: + DELIVER: --send-req Send results to a web request --send-proxy http://proxy.. Send results to a web request via an HTTP proxy --send-es http://es.. Send results to Elasticsearch @@ -163,16 +165,16 @@ Usage: noir --use-matchers string Send URLs that match specific conditions to the Deliver --use-filters string Exclude URLs that match specified conditions and send the rest to Deliver - Technologies: + TECHNOLOGIES: -t TECHS, --techs rails,php Specify the technologies to use --exclude-techs rails,php Specify the technologies to be excluded --list-techs Show all technologies - Config: + CONFIG: --config-file ./config.yaml Specify the path to a configuration file in YAML format --concurrency 100 Set concurrency - Others: + OTHERS: -d, --debug Show debug messages -v, --version Show version -h, --help Show help From dcd0267ab70f77e6ada7be499665113c3ce3e738 Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 12 May 2024 00:22:32 +0900 Subject: [PATCH 13/14] Fixed bug in curl and httpie output builders --- src/output_builder/curl.cr | 12 ++++++------ src/output_builder/httpie.cr.cr | 13 +++++++------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/output_builder/curl.cr b/src/output_builder/curl.cr index 7fad930e..4a05bdd7 100644 --- a/src/output_builder/curl.cr +++ b/src/output_builder/curl.cr @@ -12,14 +12,14 @@ class OutputBuilderCurl < OutputBuilder if baked[:body_type] == "json" cmd += " -H \"Content-Type:application/json\"" end + end - baked[:header].each do |header| - cmd += " -H \"#{header}\"" - end + baked[:header].each do |header| + cmd += " -H \"#{header}\"" + end - baked[:cookie].each do |cookie| - cmd += " --cookie \"#{cookie}\"" - end + baked[:cookie].each do |cookie| + cmd += " --cookie \"#{cookie}\"" end ob_puts cmd diff --git a/src/output_builder/httpie.cr.cr b/src/output_builder/httpie.cr.cr index b440af72..3c7571f8 100644 --- a/src/output_builder/httpie.cr.cr +++ b/src/output_builder/httpie.cr.cr @@ -12,13 +12,14 @@ class OutputBuilderHttpie < OutputBuilder if baked[:body_type] == "json" cmd += " \"Content-Type:application/json\"" end - baked[:header].each do |header| - cmd += " \"#{header}\"" - end + end - baked[:cookie].each do |cookie| - cmd += " \"Cookie: #{cookie}\"" - end + baked[:header].each do |header| + cmd += " \"#{header}\"" + end + + baked[:cookie].each do |cookie| + cmd += " \"Cookie: #{cookie}\"" end ob_puts cmd From 1c163a0185e7a4a764a5da185f2332a5486fe39f Mon Sep 17 00:00:00 2001 From: HAHWUL Date: Sun, 12 May 2024 00:33:54 +0900 Subject: [PATCH 14/14] Tap 0.15.1 --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- shard.yml | 2 +- snap/snapcraft.yaml | 2 +- src/noir.cr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3093620b..f51ab7e1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -23,7 +23,7 @@ If applicable, add screenshots to help explain your problem. **Versions** - OS: [e.g. macos, linux] - - Version [e.g. v0.15.0] + - Version [e.g. v0.15.1] **Additional context** Add any other context about the problem here. diff --git a/shard.yml b/shard.yml index 0db2be34..c089fb5f 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: noir -version: 0.15.0 +version: 0.15.1 authors: - hahwul diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 947637fc..aa923a3f 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -1,6 +1,6 @@ name: noir base: core20 -version: 0.15.0 +version: 0.15.1 summary: Attack surface detector that identifies endpoints by static analysis. description: | Noir is an open-source project specializing in identifying attack surfaces for enhanced whitebox security testing and security pipeline. diff --git a/src/noir.cr b/src/noir.cr index b9b346cd..e86b8336 100644 --- a/src/noir.cr +++ b/src/noir.cr @@ -6,7 +6,7 @@ require "./options.cr" require "./techs/techs.cr" module Noir - VERSION = "0.15.0" + VERSION = "0.15.1" end noir_options = default_options()