]> source.dussan.org Git - rspamd.git/commitdiff
rspamc: add action number in first line and improve code 4377/head
authorAmish <contact@via.aur>
Sat, 21 Jan 2023 10:40:21 +0000 (16:10 +0530)
committerAmish <contact@via.aur>
Sat, 21 Jan 2023 10:40:21 +0000 (16:10 +0530)
doc/rspamc.1
doc/rspamc.1.md
src/client/rspamc.cxx

index 8989f98b2a9a21845300a5413aec633e4840242f..0f823e64bfd7417a06e5e588d93771f43db6d95b 100644 (file)
@@ -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
index c6baa939cf0586abe03d3c3b910575f741fc986b..335c22513757ae91ed7d4abda17fa8b1f2bd251f 100644 (file)
@@ -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
index 57505cf66d98639542e7ba1e66f14ebb3f9ca77e..5bb75ef38d49fb739997c77506638a1fc28b922e 100644 (file)
@@ -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) {