Skip to content

Commit ebf23c0

Browse files
grammmikejengelh
authored andcommitted
zcore: move autoreply/OOF handling to exmdb
Updated zcore to fetch and update Out of Office properties exclusively via these new RPC calls, eliminating its direct disk interactions. References: GXL-216
1 parent 65e8eaf commit ebf23c0

File tree

1 file changed

+11
-245
lines changed

1 file changed

+11
-245
lines changed

exch/zcore/store_object.cpp

Lines changed: 11 additions & 245 deletions
Original file line numberDiff line numberDiff line change
@@ -471,119 +471,15 @@ BOOL store_object::get_all_proptags(PROPTAG_ARRAY *pproptags)
471471
return TRUE;
472472
}
473473

474-
static constexpr struct cfg_directive oof_defaults[] = {
475-
{"allow_external_oof", "0", CFG_BOOL},
476-
{"external_audience", "0", CFG_BOOL},
477-
{"oof_state", "0"},
478-
CFG_TABLE_END,
479-
};
480-
481474
static void *store_object_get_oof_property(const char *maildir,
482-
proptag_t proptag) try
475+
proptag_t proptag)
483476
{
484-
int offset;
485-
char *pbuff;
486-
int buff_len;
487-
void *pvalue;
488-
const char *str_value;
489-
char subject[1024];
490-
MIME_FIELD mime_field;
491-
struct stat node_stat;
492-
static constexpr uint8_t fake_true = true;
493-
static constexpr uint8_t fake_false = false;
494-
std::string path;
495-
496-
switch (proptag) {
497-
case PR_EC_OUTOFOFFICE:
498-
case PR_EC_OUTOFOFFICE_FROM:
499-
case PR_EC_OUTOFOFFICE_UNTIL:
500-
case PR_EC_ALLOW_EXTERNAL:
501-
case PR_EC_EXTERNAL_AUDIENCE:
502-
path = maildir + "/config/autoreply.cfg"s;
503-
break;
504-
case PR_EC_OUTOFOFFICE_MSG:
505-
case PR_EC_OUTOFOFFICE_SUBJECT:
506-
path = maildir + "/config/internal-reply"s;
507-
break;
508-
case PR_EC_EXTERNAL_REPLY:
509-
case PR_EC_EXTERNAL_SUBJECT:
510-
path = maildir + "/config/external-reply"s;
511-
break;
512-
}
513-
514-
switch (proptag) {
515-
case PR_EC_OUTOFOFFICE: {
516-
auto oofstate = cu_alloc<uint32_t>();
517-
if (oofstate == nullptr)
518-
return NULL;
519-
pvalue = oofstate;
520-
auto pconfig = config_file_init(path.c_str(), oof_defaults);
521-
*oofstate = pconfig != nullptr ? pconfig->get_ll("oof_state") : 0;
522-
return pvalue;
523-
}
524-
case PR_EC_OUTOFOFFICE_MSG:
525-
case PR_EC_EXTERNAL_REPLY: {
526-
wrapfd fd = open(path.c_str(), O_RDONLY);
527-
if (fd.get() < 0 || fstat(fd.get(), &node_stat) != 0)
528-
return nullptr;
529-
buff_len = node_stat.st_size;
530-
pbuff = cu_alloc<char>(buff_len + 1);
531-
if (pbuff == nullptr || read(fd.get(), pbuff, buff_len) != buff_len)
532-
return NULL;
533-
pbuff[buff_len] = '\0';
534-
auto ptr = strstr(pbuff, "\r\n\r\n");
535-
return ptr != nullptr ? ptr + 4 : nullptr;
536-
}
537-
case PR_EC_OUTOFOFFICE_SUBJECT:
538-
case PR_EC_EXTERNAL_SUBJECT: {
539-
wrapfd fd = open(path.c_str(), O_RDONLY);
540-
if (fd.get() < 0 || fstat(fd.get(), &node_stat) != 0)
541-
return NULL;
542-
buff_len = node_stat.st_size;
543-
pbuff = cu_alloc<char>(buff_len);
544-
if (pbuff == nullptr || read(fd.get(), pbuff, buff_len) != buff_len)
545-
return NULL;
546-
offset = 0;
547-
size_t parsed_length;
548-
while ((parsed_length = parse_mime_field(pbuff + offset, buff_len - offset, &mime_field)) != 0) {
549-
offset += parsed_length;
550-
if (strcasecmp(mime_field.name.c_str(), "Subject") == 0 &&
551-
mime_field.value.size() < std::size(subject) &&
552-
mime_string_to_utf8("utf-8", mime_field.value.c_str(), subject,
553-
std::size(subject)))
554-
return common_util_dup(subject);
555-
if (pbuff[offset] == '\r' && pbuff[offset+1] == '\n')
556-
return NULL;
557-
}
558-
return NULL;
559-
}
560-
case PR_EC_OUTOFOFFICE_FROM:
561-
case PR_EC_OUTOFOFFICE_UNTIL: {
562-
auto pconfig = config_file_init(path.c_str(), oof_defaults);
563-
if (pconfig == nullptr)
564-
return NULL;
565-
pvalue = cu_alloc<uint64_t>();
566-
if (pvalue == nullptr)
567-
return NULL;
568-
str_value = pconfig->get_value(proptag == PR_EC_OUTOFOFFICE_FROM ? "START_TIME" : "END_TIME");
569-
if (str_value == nullptr)
570-
return NULL;
571-
*static_cast<uint64_t *>(pvalue) = rop_util_unix_to_nttime(strtoll(str_value, nullptr, 0));
572-
return pvalue;
573-
}
574-
case PR_EC_ALLOW_EXTERNAL:
575-
case PR_EC_EXTERNAL_AUDIENCE: {
576-
auto pconfig = config_file_init(path.c_str(), oof_defaults);
577-
if (pconfig == nullptr)
578-
return deconst(&fake_false);
579-
auto key = proptag == PR_EC_ALLOW_EXTERNAL ? "allow_external_oof" : "external_audience";
580-
pvalue = deconst(pconfig->get_ll(key) == 0 ? &fake_false : &fake_true);
581-
return pvalue;
582-
}
583-
}
584-
return NULL;
585-
} catch (const std::bad_alloc &) {
586-
return nullptr;
477+
const PROPTAG_ARRAY tags = {1, &proptag};
478+
TPROPVAL_ARRAY props{};
479+
if (!exmdb_client->autoreply_getprop(maildir, CP_UTF8, &tags, &props) ||
480+
props.count == 0 || props[0].proptag != proptag)
481+
return nullptr;
482+
return props[0].pvalue;
587483
}
588484

589485
static BOOL store_object_get_calculated_property(store_object *pstore,
@@ -1060,140 +956,10 @@ BOOL store_object::get_properties(const PROPTAG_ARRAY *pproptags,
1060956
static BOOL store_object_set_oof_property(const char *maildir,
1061957
proptag_t proptag, const void *pvalue)
1062958
{
1063-
char *pbuff;
1064-
int buff_len;
1065-
char *ptoken;
1066-
std::string autoreply_path;
1067-
1068-
try {
1069-
autoreply_path = maildir + "/config/autoreply.cfg"s;
1070-
} catch (const std::bad_alloc &) {
1071-
mlog(LV_ERR, "E-1483: ENOMEM");
1072-
return false;
1073-
}
1074-
/* Ensure file exists for config_file_prg */
1075-
auto fdtest = open(autoreply_path.c_str(), O_CREAT | O_WRONLY, FMODE_PUBLIC);
1076-
if (fdtest < 0)
1077-
return false;
1078-
close(fdtest);
1079-
switch (proptag) {
1080-
case PR_EC_OUTOFOFFICE: {
1081-
auto pconfig = config_file_init(autoreply_path.c_str(), oof_defaults);
1082-
if (pconfig == nullptr)
1083-
return FALSE;
1084-
auto v = *static_cast<const uint32_t *>(pvalue);
1085-
pconfig->set_value("OOF_STATE", v == 1 ? "1" : v == 2 ? "2" : "0");
1086-
return pconfig->save();
1087-
}
1088-
case PR_EC_OUTOFOFFICE_FROM:
1089-
case PR_EC_OUTOFOFFICE_UNTIL: {
1090-
auto pconfig = config_file_init(autoreply_path.c_str(), oof_defaults);
1091-
if (pconfig == nullptr)
1092-
return FALSE;
1093-
long long t = rop_util_nttime_to_unix(*static_cast<const uint64_t *>(pvalue));
1094-
pconfig->set_value(proptag == PR_EC_OUTOFOFFICE_FROM ?
1095-
"START_TIME" : "END_TIME", std::to_string(t).c_str());
1096-
return pconfig->save();
1097-
}
1098-
case PR_EC_OUTOFOFFICE_MSG:
1099-
case PR_EC_EXTERNAL_REPLY: {
1100-
try {
1101-
autoreply_path = maildir;
1102-
autoreply_path += proptag == PR_EC_OUTOFOFFICE_MSG ?
1103-
"/config/internal-reply" : "/config/external-reply";
1104-
} catch (const std::bad_alloc &) {
1105-
mlog(LV_ERR, "E-1484: ENOMEM");
1106-
return false;
1107-
}
1108-
wrapfd fd = open(autoreply_path.c_str(), O_RDONLY);
1109-
struct stat node_stat;
1110-
if (fd.get() < 0 || fstat(fd.get(), &node_stat) != 0) {
1111-
buff_len = strlen(static_cast<const char *>(pvalue));
1112-
pbuff = cu_alloc<char>(buff_len + 256);
1113-
if (pbuff == nullptr)
1114-
return FALSE;
1115-
buff_len = gx_snprintf(pbuff, buff_len + 256,
1116-
"Content-Type: text/html; charset=\"utf-8\"\r\n\r\n%s",
1117-
static_cast<const char *>(pvalue));
1118-
} else {
1119-
buff_len = node_stat.st_size;
1120-
pbuff = cu_alloc<char>(buff_len + strlen(static_cast<const char *>(pvalue)) + 1);
1121-
if (pbuff == nullptr || read(fd.get(), pbuff, buff_len) != buff_len)
1122-
return FALSE;
1123-
pbuff[buff_len] = '\0';
1124-
ptoken = strstr(pbuff, "\r\n\r\n");
1125-
if (NULL != ptoken) {
1126-
strcpy(ptoken + 4, static_cast<const char *>(pvalue));
1127-
buff_len = strlen(pbuff);
1128-
} else {
1129-
buff_len = sprintf(pbuff, "Content-Type: text/html;\r\n"
1130-
"\tcharset=\"utf-8\"\r\n\r\n%s",
1131-
static_cast<const char *>(pvalue));
1132-
}
1133-
}
1134-
fd = open(autoreply_path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PUBLIC);
1135-
if (fd.get() < 0 || write(fd.get(), pbuff, buff_len) != buff_len)
1136-
return FALSE;
1137-
return TRUE;
1138-
}
1139-
case PR_EC_OUTOFOFFICE_SUBJECT:
1140-
case PR_EC_EXTERNAL_SUBJECT: {
1141-
try {
1142-
autoreply_path = maildir;
1143-
autoreply_path += proptag == PR_EC_OUTOFOFFICE_SUBJECT ?
1144-
"/config/internal-reply" : "/config/external-reply";
1145-
} catch (const std::bad_alloc &) {
1146-
mlog(LV_ERR, "E-1485: ENOMEM");
1147-
return false;
1148-
}
1149-
struct stat node_stat;
1150-
wrapfd fd = open(autoreply_path.c_str(), O_RDONLY);
1151-
if (fd.get() < 0 || fstat(fd.get(), &node_stat) != 0) {
1152-
buff_len = strlen(static_cast<const char *>(pvalue));
1153-
pbuff = cu_alloc<char>(buff_len + 256);
1154-
if (pbuff == nullptr)
1155-
return FALSE;
1156-
buff_len = sprintf(pbuff, "Content-Type: text/html;\r\n\t"
1157-
"charset=\"utf-8\"\r\nSubject: %s\r\n\r\n",
1158-
static_cast<const char *>(pvalue));
1159-
} else {
1160-
buff_len = node_stat.st_size;
1161-
pbuff = cu_alloc<char>(buff_len + strlen(static_cast<const char *>(pvalue)) + 16);
1162-
if (pbuff == nullptr)
1163-
return FALSE;
1164-
ptoken = cu_alloc<char>(buff_len + 1);
1165-
if (ptoken == nullptr)
1166-
return FALSE;
1167-
if (read(fd.get(), ptoken, buff_len) != buff_len)
1168-
return FALSE;
1169-
ptoken[buff_len] = '\0';
1170-
ptoken = strstr(ptoken, "\r\n\r\n");
1171-
if (ptoken == nullptr)
1172-
buff_len = sprintf(pbuff, "Content-Type: text/html;\r\n\t"
1173-
"charset=\"utf-8\"\r\nSubject: %s\r\n\r\n",
1174-
static_cast<const char *>(pvalue));
1175-
else
1176-
buff_len = sprintf(pbuff, "Content-Type: text/html;\r\n\t"
1177-
"charset=\"utf-8\"\r\nSubject: %s%s",
1178-
static_cast<const char *>(pvalue), ptoken);
1179-
}
1180-
fd = open(autoreply_path.c_str(), O_CREAT | O_TRUNC | O_WRONLY, FMODE_PUBLIC);
1181-
if (fd.get() < 0 || write(fd.get(), pbuff, buff_len) != buff_len)
1182-
return FALSE;
1183-
return TRUE;
1184-
}
1185-
case PR_EC_ALLOW_EXTERNAL:
1186-
case PR_EC_EXTERNAL_AUDIENCE: {
1187-
auto pconfig = config_file_init(autoreply_path.c_str(), oof_defaults);
1188-
if (pconfig == nullptr)
1189-
return FALSE;
1190-
pconfig->set_value(proptag == PR_EC_ALLOW_EXTERNAL ?
1191-
"ALLOW_EXTERNAL_OOF" : "EXTERNAL_AUDIENCE",
1192-
*static_cast<const uint8_t *>(pvalue) == 0 ? "0" : "1");
1193-
return pconfig->save();
1194-
}
1195-
}
1196-
return FALSE;
959+
const TAGGED_PROPVAL pv = {proptag, deconst(pvalue)};
960+
const TPROPVAL_ARRAY vals = {1, deconst(&pv)};
961+
PROBLEM_ARRAY status{};
962+
return exmdb_client->autoreply_setprop(maildir, CP_UTF8, &vals, &status);
1197963
}
1198964

1199965
static BOOL store_object_set_folder_name(store_object *pstore,

0 commit comments

Comments
 (0)