text_tokens = cmsgpack.unpack(ARGV[5])
end
--- Handle backward compatibility for boolean values
-if class_label == 'true' then
- class_label = 'S' -- spam
-elseif class_label == 'false' then
- class_label = 'H' -- ham
+-- Handle RS_<ID> HASH booleans and full class name strings for backward compatibility
+if class_label == 'true' or class_label == 'spam' then
+ class_label = 'S'
+elseif class_label == 'false' or class_label == 'ham' then
+ class_label = 'H'
end
local hash_key = class_label
local learned_key = 'learns_' .. string.lower(class_label)
--- Handle legacy keys for backward compatibility
+-- Handle RS HASH keys for backward compatibility
if class_label == 'S' then
learned_key = 'learns_spam'
elseif class_label == 'H' then
/*
* Get the class label for a statfile (for multi-class support)
+ * Returns the Redis hash field name to use for this class. "spam" and "ham"
+ * always map to the legacy single-char labels "S" and "H" so that existing
+ * Redis token data (stored under those field names) remains readable after a
+ * config migration from `spam = true/false` to explicit `class = "spam"/"ham"`.
*/
static const char *
get_class_label(struct rspamd_statfile_config *stcf)
if (label) {
return label;
}
- /* If no label mapping found, use class name directly */
- return stcf->class_name;
+ /* No mapping found — fall through to backward-compat checks below */
}
- /* For multiclass without explicit label mapping, use class_name directly */
- if (stcf->class_name && !stcf->is_spam_converted) {
- return stcf->class_name;
+ if (stcf->class_name) {
+ /* Map canonical binary class names to their legacy Redis field names */
+ if (strcmp(stcf->class_name, "spam") == 0) {
+ return "S";
+ }
+ if (strcmp(stcf->class_name, "ham") == 0) {
+ return "H";
+ }
+
+ /* True multiclass name (not spam/ham) — use the class name as the field */
+ if (!stcf->is_spam_converted) {
+ return stcf->class_name;
+ }
}
- /* Fallback to legacy binary classification */
+ /* Final fallback: legacy binary is_spam flag */
return stcf->is_spam ? "S" : "H";
}
if class_name then
class_symbols[class_name] = symbol
+ logger.debugm(N, rspamd_config,
+ 'check_statfile_table: found class_name=%s and its symbol=%s', class_name, symbol)
end
end
-- Parse hash data into class counts
for i = 1, #hash_data, 2 do
local class_label = hash_data[i]
+ -- Handle RS_<ID> HASH short class names for backward compatibility
+ if class_label == 'S' then
+ class_label = 'spam'
+ elseif class_label == 'H' then
+ class_label = 'ham'
+ end
local count = tonumber(hash_data[i + 1]) or 0
class_counts[class_label] = count
total = total + count