Skip to content

Commit d464afe

Browse files
Update soap.c
1 parent 84acdd6 commit d464afe

File tree

1 file changed

+56
-14
lines changed

1 file changed

+56
-14
lines changed

code/logic/soap.c

Lines changed: 56 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include <stdio.h>
2020
#include <math.h>
2121

22-
#define FOSSIL_JELLYFISH_HASH_SIZE 16
2322
#define MAX_CUSTOM_FILTERS 64
2423

2524
/** Lookup table for rot-brain words and their suggested replacements */
@@ -131,6 +130,55 @@ static const char *SKIP_WORDS[] = {
131130
NULL // Sentinel to mark the end
132131
};
133132

133+
#define FNV_PRIME 0x01000193
134+
#define FNV_BASIS 0x811c9dc5
135+
136+
void fossil_io_soap_jellyfish_hash(const char *input, const char *output, uint8_t *hash_out) {
137+
uint32_t hash = FNV_BASIS;
138+
size_t in_len = strlen(input);
139+
size_t out_len = strlen(output);
140+
141+
// Mix lengths
142+
hash ^= in_len;
143+
hash *= FNV_PRIME;
144+
hash ^= out_len;
145+
hash *= FNV_PRIME;
146+
147+
// Mix input string
148+
for (size_t i = 0; i < in_len; ++i) {
149+
hash ^= (uint8_t)input[i];
150+
hash *= FNV_PRIME;
151+
hash ^= (hash >> 5);
152+
}
153+
154+
// Mix output string
155+
for (size_t i = 0; i < out_len; ++i) {
156+
hash ^= (uint8_t)output[i];
157+
hash *= FNV_PRIME;
158+
hash ^= (hash >> 5);
159+
}
160+
161+
// Final avalanche
162+
hash ^= (hash << 7);
163+
hash ^= (hash >> 3);
164+
165+
// Expand to fixed size
166+
uint32_t h = hash;
167+
for (size_t i = 0; i < FOSSIL_JELLYFISH_HASH_SIZE; ++i) {
168+
h ^= (h >> 13);
169+
h *= FNV_PRIME;
170+
h ^= (h << 11);
171+
hash_out[i] = (uint8_t)((h >> (8 * (i % 4))) & 0xFF);
172+
}
173+
}
174+
175+
static void hash_to_hex(const uint8_t *hash, size_t len, char *out_hex) {
176+
for (size_t i = 0; i < len; ++i) {
177+
sprintf(out_hex + i * 2, "%02x", hash[i]);
178+
}
179+
out_hex[len * 2] = '\0';
180+
}
181+
134182
/**
135183
* @brief Convert leetspeak to normal letters.
136184
*/
@@ -427,25 +475,19 @@ char *fossil_io_soap_generate_audit_block(const char *text) {
427475
char *sanitized = fossil_io_soap_sanitize(text);
428476
if (!sanitized) return NULL;
429477

430-
// Compute Jellyfish-style hash
431-
uint8_t hash_out[FOSSIL_JELLYFISH_HASH_SIZE];
432-
fossil_jellyfish_hash(text, sanitized, hash_out);
478+
uint8_t hash[FOSSIL_JELLYFISH_HASH_SIZE];
479+
char hash_hex[FOSSIL_JELLYFISH_HASH_SIZE * 2 + 1];
433480

434-
// Convert hash to hex string
435-
char hash_hex[FOSSIL_JELLYFISH_HASH_SIZE * 2 + 1] = {0};
436-
for (size_t i = 0; i < FOSSIL_JELLYFISH_HASH_SIZE; ++i) {
437-
sprintf(hash_hex + i * 2, "%02x", hash_out[i]);
438-
}
481+
fossil_io_soap_jellyfish_hash(text, sanitized, hash);
482+
hash_to_hex(hash, FOSSIL_JELLYFISH_HASH_SIZE, hash_hex);
439483

440-
// Allocate JSON audit block
441-
size_t needed = strlen(text) + strlen(sanitized) + strlen(hash_hex) + 64;
442-
char *audit_block = malloc(needed);
484+
char *audit_block = malloc(1024);
443485
if (!audit_block) {
444486
free(sanitized);
445487
return NULL;
446488
}
447489

448-
snprintf(audit_block, needed,
490+
snprintf(audit_block, 1024,
449491
"{ \"original\": \"%s\", \"sanitized\": \"%s\", \"hash\": \"%s\" }",
450492
text, sanitized, hash_hex);
451493

@@ -490,7 +532,7 @@ char *fossil_io_soap_flag_ethics(const char *text) {
490532
// Simulate simple filter
491533
const char *bad_words[] = {"stupid", "idiot", "hate", "kill", NULL};
492534

493-
char *flagged = strdup(text);
535+
char *flagged = fossil_io_cstring_dup(text);
494536
if (!flagged) return NULL;
495537

496538
for (size_t i = 0; bad_words[i]; i++) {

0 commit comments

Comments
 (0)