commit 42e1c8d: rspamc: add action number in first line and improve code

Amish contact at via.aur
Sat Jan 21 12:21:04 UTC 2023


Author: Amish
Date: 2023-01-21 16:10:21 +0530
URL: https://github.com/rspamd/rspamd/commit/42e1c8d507f72adc2a7390ac4baf1248067cf40b (refs/pull/4377/head)

rspamc: add action number in first line and improve code

---
 doc/rspamc.1          |  10 +++-
 doc/rspamc.1.md       |   3 +-
 src/client/rspamc.cxx | 152 ++++++++++++++++++++++++++++++++++++++------------
 3 files changed, 127 insertions(+), 38 deletions(-)

diff --git a/doc/rspamc.1 b/doc/rspamc.1
index 8989f98b2..0f823e64b 100644
--- a/doc/rspamc.1
+++ b/doc/rspamc.1
@@ -150,7 +150,15 @@ Bind to specified ip address
 .RE
 .TP
 .B \-R, \-\-human
-Output human readable report
+Output human readable report.
+The first line of the output contains the message score and three 
+threshold scores, in this format:
+.IP
+.nf
+\f[C]
+    score/greylist/addheader/reject,action=N:ACTION,spam=0|1,skipped=0|1
+\f[]
+.fi
 .RS
 .RE
 .TP
diff --git a/doc/rspamc.1.md b/doc/rspamc.1.md
index c6baa939c..335c22513 100644
--- a/doc/rspamc.1.md
+++ b/doc/rspamc.1.md
@@ -87,7 +87,8 @@ requires input.
 :	Bind to specified ip address
 
 -R, \--human
-:	Output human readable report
+:	Output human readable report. The first line of the output contains the message score and three threshold scores, in this format:
+:           score/greylist/addheader/reject,action=N:ACTION,spam=0|1,skipped=0|1
 
 -j, \--json
 :	Output formatted JSON
diff --git a/src/client/rspamc.cxx b/src/client/rspamc.cxx
index 57505cf66..5bb75ef38 100644
--- a/src/client/rspamc.cxx
+++ b/src/client/rspamc.cxx
@@ -826,14 +826,18 @@ add_options(GQueue *opts)
 }
 
 static void
-print_indented_line(FILE *out, std::string line, size_t maxlen, size_t indent)
+print_indented_line(FILE *out, std::string_view line, size_t maxlen, size_t indent)
 {
-	if (maxlen < 1) return;
+	if (maxlen < 1) {
+		return;
+	}
 
-	std::string s;
-	for (size_t pos = 0; pos < line.length(); pos += s.length()) {
+	std::string_view s;
+	for (size_t pos = 0; pos < line.size(); pos += s.size()) {
 		s = line.substr(pos, pos ? (maxlen-indent) : maxlen);
-		if (indent && pos) fmt::print(out, "{:>{}}", " ", indent);
+		if (indent && pos) {
+			fmt::print(out, "{:>{}}", " ", indent);
+		}
 		fmt::print(out, "{}\n", s);
 	}
 }
@@ -842,21 +846,27 @@ static void
 rspamc_symbol_human_output(FILE *out, const ucl_object_t *obj)
 {
 	auto first = true;
-	double score = 0;
-	const char *key = nullptr, *desc = nullptr;
+	auto score = 0.0;
+	const char *desc = nullptr;
 
+	const auto *key = ucl_object_key(obj);
 	const auto *val = ucl_object_lookup(obj, "score");
-	if (val != nullptr) score = ucl_object_todouble(val);
+	if (val != nullptr) {
+		score = ucl_object_todouble(val);
+	}
 
-	key = ucl_object_key(obj);
 	val = ucl_object_lookup(obj, "description");
-	if (val != nullptr) desc = ucl_object_tostring(val);
+	if (val != nullptr) {
+		desc = ucl_object_tostring(val);
+	}
 
-	std::string line = fmt::format("{:>4.1f} {:<22} ", score, key);
-	if (desc != nullptr) line += desc;
+	auto line = fmt::format("{:>4.1f} {:<22} ", score, key);
+	if (desc != nullptr) {
+		line += desc;
+	}
 
 	val = ucl_object_lookup(obj, "options");
-	if (val != nullptr && val->type == UCL_ARRAY) {
+	if (val != nullptr && ucl_object_type(val) == UCL_ARRAY) {
 		ucl_object_iter_t it = nullptr;
 		const ucl_object_t *cur;
 
@@ -873,7 +883,9 @@ rspamc_symbol_human_output(FILE *out, const ucl_object_t *obj)
 		}
 		line += ']';
 	}
-	else if (desc == nullptr) line += '\n';
+	else if (desc == nullptr) {
+		line += '\n';
+	}
 
 	print_indented_line(out, line, 78, 28);
 }
@@ -890,7 +902,7 @@ rspamc_symbol_output(FILE *out, const ucl_object_t *obj)
 		fmt::print(out, "({:.2f})", ucl_object_todouble(val));
 	}
 	val = ucl_object_lookup(obj, "options");
-	if (val != nullptr && val->type == UCL_ARRAY) {
+	if (val != nullptr && ucl_object_type(val) == UCL_ARRAY) {
 		ucl_object_iter_t it = nullptr;
 		const ucl_object_t *cur;
 
@@ -913,37 +925,56 @@ rspamc_symbol_output(FILE *out, const ucl_object_t *obj)
 static void
 rspamc_metric_output(FILE *out, const ucl_object_t *obj)
 {
-	double score = 0, required_score = 0;
 	int got_scores = 0;
+	bool is_spam = false, is_skipped = false;
+	double score = 0, required_score = 0, greylist_score =0, addheader_score = 0;
 
 	auto print_protocol_string = [&](const char *ucl_name, const char *output_message) {
 		auto *elt = ucl_object_lookup(obj, ucl_name);
 		if (elt) {
-			fmt::print(out, fmt::runtime(humanreport ? ",{}={}" : "{}: {}\n"), output_message,
-					emphasis_argument(ucl_object_tostring(elt)));
+			if (humanreport) {
+				fmt::print(out, ",{}={}", output_message, emphasis_argument(ucl_object_tostring(elt)));
+			}
+			else {
+				fmt::print(out, "{}: {}\n", output_message, emphasis_argument(ucl_object_tostring(elt)));
+			}
 		}
 	};
 
-	if (!humanreport) fmt::print(out, "[Metric: default]\n");
+	if (!humanreport) {
+		fmt::print(out, "[Metric: default]\n");
+	}
 
 	const auto *elt = ucl_object_lookup(obj, "required_score");
-
 	if (elt) {
 		required_score = ucl_object_todouble(elt);
 		got_scores++;
 	}
 
 	elt = ucl_object_lookup(obj, "score");
-
 	if (elt) {
 		score = ucl_object_todouble(elt);
 		got_scores++;
 	}
 
+	/* XXX: greylist_score is not yet in checkv2 */
+	elt = ucl_object_lookup(obj, "greylist_score");
+	if (elt) {
+		greylist_score = ucl_object_todouble(elt);
+	}
+
+	/* XXX: addheader_score is not yet in checkv2 */
+	elt = ucl_object_lookup(obj, "addheader_score");
+	if (elt) {
+		addheader_score = ucl_object_todouble(elt);
+	}
+
 	if (humanreport) {
 		fmt::print(out,
-				"{}/{}",
+				"{}/{}/{}/{}",
 				emphasis_argument(score, 2),
+				emphasis_argument(greylist_score, 2),
+				emphasis_argument(addheader_score, 2),
 				emphasis_argument(required_score, 2));
 	}
 
@@ -953,7 +984,12 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
 
 		if (act.has_value()) {
 			if (!tty) {
-				print_protocol_string("action", "Action");
+				if (humanreport) {
+					fmt::print(out, ",action={}:{}", act.value(), ucl_object_tostring(elt));
+				}
+				else {
+					print_protocol_string("action", "Action");
+				}
 			}
 			else {
 				/* Colorize action type */
@@ -977,21 +1013,48 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
 					colorized_action = fmt::format(fmt::emphasis::bold, ucl_object_tostring(elt));
 					break;
 				}
-				fmt::print(out, fmt::runtime(humanreport ? ",Action={}" : "Action: {}\n"), colorized_action);
+
+				if (humanreport) {
+					fmt::print(out, ",action={}:{}", act.value(), colorized_action);
+				}
+				else {
+					fmt::print(out, "Action: {}\n", colorized_action);
+				}
 			}
 
-			fmt::print(out, fmt::runtime(humanreport ? ",Spam={}" : "Spam: {}\n"),
-								emphasis_argument(act.value() < METRIC_ACTION_GREYLIST ?
-												"true" : "false"));
+			is_spam = act.value() < METRIC_ACTION_GREYLIST ? true : false;
+			if (!humanreport) {
+				fmt::print(out, "Spam: {}\n", is_spam ?	"true" : "false");
+			}
 		}
 		else {
-			print_protocol_string("action", "Action");
+			if (humanreport) {
+				fmt::print(out, ",action={}:{}", METRIC_ACTION_NOACTION, ucl_object_tostring(elt));
+			}
+			else {
+				print_protocol_string("action", "Action");
+			}
 		}
 	}
 
-	if (!humanreport) print_protocol_string("subject", "Subject");
+	if (!humanreport) {
+		print_protocol_string("subject", "Subject");
+	}
+
+	if (humanreport) {
+		/* XXX: why checkv2 does not provide "is_spam"? */
+		elt = ucl_object_lookup(obj, "is_spam");
+		if (elt) {
+			is_spam = ucl_object_toboolean(elt);
+		}
+
+		elt = ucl_object_lookup(obj, "is_skipped");
+		if (elt) {
+			is_skipped = ucl_object_toboolean(elt);
+		}
 
-	if (humanreport) fmt::print(out, "\n");
+		fmt::print(out, ",spam={},skipped={}\n", is_spam ? 1 : 0, is_skipped ? 1 : 0);
+	}
 	else if (got_scores == 2) {
 		fmt::print(out,
 				"Score: {} / {}\n",
@@ -1021,11 +1084,12 @@ rspamc_metric_output(FILE *out, const ucl_object_t *obj)
 		sort_ucl_container_with_default(symbols, "name");
 
 		for (const auto *sym_obj : symbols) {
-			if (humanreport) rspamc_symbol_human_output(out, sym_obj);
-			else rspamc_symbol_output(out, sym_obj);
+			humanreport ? rspamc_symbol_human_output(out, sym_obj) : rspamc_symbol_output(out, sym_obj);
 		}
 	}
-	if (humanreport) fmt::print(out, "\n");
+	if (humanreport) {
+		fmt::print(out, "\n");
+	}
 }
 
 static void
@@ -1079,7 +1143,14 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
 			emitted = (char *)ucl_object_emit(elt, UCL_EMIT_JSON);
 		}
 
-		if (emitted && strcmp(emitted, "[]")) fmt::print(out, "Urls: {}\n", emitted);
+		if (humanreport) {
+		       if (emitted && strcmp(emitted, "[]")) {
+			       print_indented_line(out, fmt::format("Domains found: {}", emitted), 78, 4);
+		       }
+		}
+		else {
+			fmt::print(out, "Urls: {}\n", emitted);
+		}
 		free(emitted);
 	}
 
@@ -1094,12 +1165,21 @@ rspamc_symbols_output(FILE *out, ucl_object_t *obj)
 			emitted = (char *)ucl_object_emit(elt, UCL_EMIT_JSON);
 		}
 
-		if (emitted && strcmp(emitted, "[]")) fmt::print(out, "Emails: {}\n", emitted);
+		if (humanreport) {
+			if (emitted && strcmp(emitted, "[]")) {
+			       print_indented_line(out, fmt::format("Emails found: {}", emitted), 78, 4);
+			}
+		}
+		else {
+			fmt::print(out, "Emails: {}\n", emitted);
+		}
 		free(emitted);
 	}
 
 	print_protocol_string("error", "Scan error");
-	if (humanreport) return;
+	if (humanreport) {
+		return;
+	}
 
 	elt = ucl_object_lookup(obj, "messages");
 	if (elt && elt->type == UCL_OBJECT) {


More information about the Commits mailing list