#include "query.h"
#include "policy_tokens.h"
+#include "str.h"
bool query_parse(query_t *query, char *p)
{
#define PARSE_CHECK(expr, error, ...) \
do { \
if (!(expr)) { \
- syslog(LOG_ERR, error, ##__VA_ARGS__); \
+ err(error, ##__VA_ARGS__); \
return false; \
} \
} while (0)
#define CASE(up, low) case PTK_##up: query->low = v; v[vlen] = '\0'; break;
CASE(HELO_NAME, helo_name);
CASE(QUEUE_ID, queue_id);
- CASE(SENDER, sender);
- CASE(RECIPIENT, recipient);
CASE(RECIPIENT_COUNT, recipient_count);
CASE(CLIENT_ADDRESS, client_address);
CASE(CLIENT_NAME, client_name);
CASE(STRESS, stress);
#undef CASE
+ case PTK_SENDER:
+ query->sender = v;
+ v[vlen] = '\0';
+ query->sender_domain = memchr(query->sender, '@', vlen);
+ if (query->sender_domain != NULL) {
+ ++query->sender_domain;
+ }
+ break;
+
+ case PTK_RECIPIENT:
+ query->recipient = v;
+ v[vlen] = '\0';
+ query->recipient_domain = memchr(query->recipient, '@', vlen);
+ if (query->recipient_domain != NULL) {
+ ++query->recipient_domain;
+ }
+ break;
+
case PTK_REQUEST:
PARSE_CHECK(vtk == PTK_SMTPD_ACCESS_POLICY,
"unexpected `request' value: %.*s", vlen, v);
break;
default:
- syslog(LOG_WARNING, "unexpected key, skipped: %.*s", klen, k);
+ warn("unexpected key, skipped: %.*s", klen, k);
continue;
}
}
#undef PARSE_CHECK
}
+const char *query_field_for_id(const query_t *query, postlicyd_token id)
+{
+ switch (id) {
+#define CASE(Up, Low) \
+ case PTK_ ## Up: return query->Low;
+ CASE(HELO_NAME, helo_name)
+ CASE(QUEUE_ID, queue_id)
+ CASE(SENDER, sender)
+ CASE(SENDER_DOMAIN, sender_domain)
+ CASE(RECIPIENT, recipient)
+ CASE(RECIPIENT_DOMAIN, recipient_domain)
+ CASE(RECIPIENT_COUNT, recipient_count)
+ CASE(CLIENT_ADDRESS, client_address)
+ CASE(CLIENT_NAME, client_name)
+ CASE(REVERSE_CLIENT_NAME, reverse_client_name)
+ CASE(INSTANCE, instance)
+ CASE(SASL_METHOD, sasl_method)
+ CASE(SASL_USERNAME, sasl_username)
+ CASE(SASL_SENDER, sasl_sender)
+ CASE(SIZE, size)
+ CASE(CCERT_SUBJECT, ccert_subject)
+ CASE(CCERT_ISSUER, ccert_issuer)
+ CASE(CCERT_FINGERPRINT, ccert_fingerprint)
+ CASE(ENCRYPTION_PROTOCOL, encryption_protocol)
+ CASE(ENCRYPTION_CIPHER, encryption_cipher)
+ CASE(ENCRYPTION_KEYSIZE, encryption_keysize)
+ CASE(ETRN_DOMAIN, etrn_domain)
+ CASE(STRESS, stress)
+#undef CASE
+ default: return NULL;
+ }
+}
+
+const char *query_field_for_name(const query_t *query, const char *name)
+{
+ postlicyd_token id = policy_tokenize(name, strlen(name));
+ if (id == PTK_UNKNOWN) {
+ warn("unknown query field %s", name);
+ return NULL;
+ }
+ return query_field_for_id(query, id);
+}
+
+ssize_t query_format(char *dest, size_t len, const char *fmt, const query_t *query)
+{
+ size_t written = 0;
+ size_t pos = 0;
+ const char *end = fmt + m_strlen(fmt);
+
+#define WRITE(Src, Len) \
+ do { \
+ size_t __len = (Len); \
+ if (written < len) { \
+ size_t __to_write = MIN(len - written - 1, __len); \
+ memcpy(dest + written, (Src), __to_write); \
+ written += __to_write; \
+ } \
+ pos += __len; \
+ } while (0)
+ while (*fmt != '\0') {
+ const char *next_format = strstr(fmt, "${");
+ if (next_format == NULL) {
+ next_format = end;
+ }
+ WRITE(fmt, next_format - fmt);
+ fmt = next_format;
+ if (*fmt != '\0') {
+ fmt += 2;
+ next_format = strchr(fmt, '}');
+ if (next_format == NULL) {
+ return -1;
+ }
+
+ postlicyd_token tok = policy_tokenize(fmt, next_format - fmt);
+ if (tok == PTK_UNKNOWN) {
+ warn("unknown field name \"%.*s\"", (int)(next_format - fmt), fmt);
+ }
+ const char *field = query == NULL ? NULL : query_field_for_id(query, tok);
+ if (field == NULL) {
+ WRITE("(null)", 6);
+ } else {
+ WRITE(field, m_strlen(field));
+ }
+ fmt = next_format + 1;
+ }
+ }
+
+ if (written > 0 && len > 0) {
+ dest[written] = '\0';
+ }
+ return pos;
+}