conf = NULL;
}
else {
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg != NULL) {
conf = strdup(msg->cm_fields[eMesageText]);
CM_Free(msg);
}
-
-
-
/*
* check_control - check the control record has sensible values for message, user and room numbers
*/
else
{
if (cdbut) cdb_free(cdbut);
-
+
SEENM_syslog(LOG_DEBUG, "not Found");
+ if (cType == eCheckUpdate)
+ return 0;
}
if (cType == eCheckExist)
};
typedef enum __eCheckType {
- eCheckExist,
- eCheckUpdate,
- eUpdate,
- eWrite
+ eCheckExist, /* look up the item, return the timestamp if its there, 0 if not. */
+ eCheckUpdate, /* if it exists, refresh in db timestamp. return the timstamp if its there, 0 if not. */
+ eUpdate, /* insert/update the new value, return the old if its there, 0 if not. */
+ eWrite /* write this to DB, unconditional. */
}eCheckType;
time_t CheckIfAlreadySeen(const char *Facility,
void rebuild_euid_index_for_msg(long msgnum, void *userdata) {
struct CtdlMessage *msg = NULL;
- msg = CtdlFetchMessage(msgnum, 0);
+ msg = CtdlFetchMessage(msgnum, 0, 1);
if (msg == NULL) return;
if (!CM_IsEmpty(msg, eExclusiveID)) {
index_message_by_euid(msg->cm_fields[eExclusiveID], &CC->room, msgnum);
* Function to go through an ical component set and convert all non-UTC
* date/time properties to UTC. It also strips out any VTIMEZONE
* subcomponents afterwards, because they're irrelevant.
- *
- * Copyright (c) 1987-2015 by the citadel.org team
- *
- * This program is open source software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*/
int avoid_access,
int new_room_view);
int CtdlGetRoom(struct ctdlroom *qrbuf, const char *room_name);
-int CtdlGetRoomLock(struct ctdlroom *qrbuf, char *room_name);
+int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name);
int CtdlDoIHavePermissionToDeleteThisRoom(struct ctdlroom *qr);
void CtdlRoomAccess(struct ctdlroom *roombuf, struct ctdluser *userbuf, int *result, int *view);
void CtdlPutRoomLock(struct ctdlroom *qrbuf);
int i = 0;
char *nnn = NULL;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
v = vcard_load(msg->cm_fields[eMesageText]);
return;
}
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + ILLEGAL_VALUE,
* us the ability to load the event into memory so we can diddle the
* attendees.
*/
- msg = CtdlFetchMessage(msgnum_being_replaced, 1);
+ msg = CtdlFetchMessage(msgnum_being_replaced, 1, 1);
if (msg == NULL) {
return(2); /* internal error */
}
return;
}
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + ILLEGAL_VALUE,
proposed_event = (icalcomponent *)data;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
memset(&ird, 0, sizeof ird);
strcpy(ird.desired_partnum, "_HUNT_");
struct CtdlMessage *msg = NULL;
struct ical_respond_data ird;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found\n",
ERROR + ILLEGAL_VALUE,
fb = (icalcomponent *)data; /* User-supplied data will be the VFREEBUSY component */
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
memset(&ird, 0, sizeof ird);
strcpy(ird.desired_partnum, "_HUNT_");
/* Look for the calendar event... */
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
memset(&ird, 0, sizeof ird);
strcpy(ird.desired_partnum, "_HUNT_");
{
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum, 0);
+ msg = CtdlFetchMessage(msgnum, 0, 1);
if (msg == NULL) {
cprintf("%ld|0|||||\n", msgnum);
return;
{
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum, 0);
+ msg = CtdlFetchMessage(msgnum, 0, 1);
if (msg == NULL) {
cprintf("%ld||\n", msgnum);
return;
}
msgnum = extract_long(cmdbuf, 0);
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
cprintf("%d Message %ld not found.\n",
ERROR + MESSAGE_NOT_FOUND, msgnum);
for (a=0; a<num_msgs; ++a) {
delnum = msglist[a];
- msg = CtdlFetchMessage(delnum, 0); /* dont need body */
+ msg = CtdlFetchMessage(delnum, 0, 1); /* dont need body */
if (msg != NULL) {
xtime = atol(msg->cm_fields[eTimestamp]);
CM_Free(msg);
memcpy(&msgnum, cdbei->ptr, sizeof(long));
- msg = CtdlFetchMessage(msgnum, 0);
+ msg = CtdlFetchMessage(msgnum, 0, 1);
if (msg != NULL) {
CM_Free(msg); /* it still exists, so do nothing */
}
return eNone; /* No messages at all? No further action. */
}
for (a = 0; a < num_msgs; ++a) {
- msg = CtdlFetchMessage(msglist[a], 1);
+ msg = CtdlFetchMessage(msglist[a], 1, 1);
if (msg != NULL) {
if (!CM_IsEmpty(msg, eMsgSubject) &&
(strncasecmp(msg->cm_fields[eMsgSubject],
Ctx = (NotifyContext*) usrdata;
- msg = CtdlFetchMessage(NotifyMsgnum, 1);
+ msg = CtdlFetchMessage(NotifyMsgnum, 1, 1);
if (!CM_IsEmpty(msg, eExtnotify))
{
Type = extNotify_getConfigMessage(
int tok;
struct CtdlMessage *msg = NULL;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
syslog(LOG_ERR, "ft_index_message() could not load msg %ld", msgnum);
return;
if (Imap->cached_body == NULL) {
CCC->redirect_buffer = NewStrBufPlain(NULL, SIZ);
loading_body_now = 1;
- msg = CtdlFetchMessage(msgnum, (need_body ? 1 : 0));
+ msg = CtdlFetchMessage(msgnum, (need_body ? 1 : 0), 1);
}
/* Now figure out what the client wants, and get it */
msg = NULL;
}
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
body_loaded = 1;
}
imap_fetch_bodystructure(Imap->msgids[seq-1],
}
else if (!strcasecmp(Cmd->Params[i].Key, "ENVELOPE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 0);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 0, 1);
body_loaded = 0;
}
imap_fetch_envelope(msg);
}
else if (!strcasecmp(Cmd->Params[i].Key, "INTERNALDATE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 0);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 0, 1);
body_loaded = 0;
}
imap_fetch_internaldate(msg);
else if (!strcasecmp(itemlist[pos].Key, "BCC")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "BEFORE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
/* Otherwise, we have to do a slow search. */
else {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "CC")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "FROM")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
* examining the message body.
*/
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
else if (!strcasecmp(itemlist[pos].Key, "LARGER")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "ON")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SENTBEFORE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SENTON")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SENTSINCE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SINCE")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SMALLER")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "SUBJECT")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "TEXT")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
else if (!strcasecmp(itemlist[pos].Key, "TO")) {
if (msg == NULL) {
- msg = CtdlFetchMessage(Imap->msgids[seq-1], 1);
+ msg = CtdlFetchMessage(Imap->msgids[seq-1], 1, 1);
need_to_free_msg = 1;
}
if (msg != NULL) {
void inetcfg_init_backend(long msgnum, void *userdata) {
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg != NULL) {
inetcfg_setTo(msg);
CM_Free(msg);
FILE *migr_global_message_list;
int total_msgs = 0;
-/*
- * Code which implements the export appears in this section
- */
+
+/******************************************************************************
+ * Code which implements the export appears in this section *
+ ******************************************************************************/
/*
* Output a string to the client with these characters escaped: & < >
while (*c != 0) {
if (*c == '\"') {
- client_write(""", 6);
+ client_write(HKEY("""));
}
else if (*c == '\'') {
- client_write("'", 6);
+ client_write(HKEY("'"));
}
else if (*c == '<') {
- client_write("<", 4);
+ client_write(HKEY("<"));
}
else if (*c == '>') {
- client_write(">", 4);
+ client_write(HKEY(">"));
}
else if (*c == '&') {
- client_write("&", 5);
+ client_write(HKEY("&"));
}
else {
client_write(c, 1);
* Export a user record as XML
*/
void migr_export_users_backend(struct ctdluser *buf, void *data) {
- client_write("<user>\n", 7);
+ client_write(HKEY("<user>\n"));
cprintf("<u_version>%d</u_version>\n", buf->version);
cprintf("<u_uid>%ld</u_uid>\n", (long)buf->uid);
- client_write("<u_password>", 12); xml_strout(buf->password); client_write("</u_password>\n", 14);
+ client_write(HKEY("<u_password>")); xml_strout(buf->password); client_write(HKEY("</u_password>\n"));
cprintf("<u_flags>%u</u_flags>\n", buf->flags);
cprintf("<u_timescalled>%ld</u_timescalled>\n", buf->timescalled);
cprintf("<u_posted>%ld</u_posted>\n", buf->posted);
cprintf("<u_usernum>%ld</u_usernum>\n", buf->usernum);
cprintf("<u_lastcall>%ld</u_lastcall>\n", (long)buf->lastcall);
cprintf("<u_USuserpurge>%d</u_USuserpurge>\n", buf->USuserpurge);
- client_write("<u_fullname>", 12); xml_strout(buf->fullname); client_write("</u_fullname>\n", 14);
- client_write("</user>\n", 8);
+ client_write(HKEY("<u_fullname>")); xml_strout(buf->fullname); client_write(HKEY("</u_fullname>\n"));
+ client_write(HKEY("</user>\n"));
}
void migr_export_rooms_backend(struct ctdlroom *buf, void *data) {
- client_write("<room>\n", 7);
- client_write("<QRname>", 8); xml_strout(buf->QRname); client_write("</QRname>\n", 10);
- client_write("<QRpasswd>", 10); xml_strout(buf->QRpasswd); client_write("</QRpasswd>\n", 12);
+ client_write(HKEY("<room>\n"));
+ client_write(HKEY("<QRname>")); xml_strout(buf->QRname); client_write(HKEY("</QRname>\n"));
+ client_write(HKEY("<QRpasswd>")); xml_strout(buf->QRpasswd); client_write(HKEY("</QRpasswd>\n"));
cprintf("<QRroomaide>%ld</QRroomaide>\n", buf->QRroomaide);
cprintf("<QRhighest>%ld</QRhighest>\n", buf->QRhighest);
cprintf("<QRgen>%ld</QRgen>\n", (long)buf->QRgen);
cprintf("<QRflags>%u</QRflags>\n", buf->QRflags);
if (buf->QRflags & QR_DIRECTORY) {
- client_write("<QRdirname>", 11);
+ client_write(HKEY("<QRdirname>"));
xml_strout(buf->QRdirname);
- client_write("</QRdirname>\n", 13);
+ client_write(HKEY("</QRdirname>\n"));
}
cprintf("<QRinfo>%ld</QRinfo>\n", buf->QRinfo);
cprintf("<QRfloor>%d</QRfloor>\n", buf->QRfloor);
cprintf("<QRorder>%d</QRorder>\n", buf->QRorder);
cprintf("<QRflags2>%u</QRflags2>\n", buf->QRflags2);
cprintf("<QRdefaultview>%d</QRdefaultview>\n", buf->QRdefaultview);
- client_write("</room>\n", 8);
+ client_write(HKEY("</room>\n"));
/* message list goes inside this tag */
CtdlGetRoom(&CC->room, buf->QRname);
- client_write("<room_messages>", 15);
- client_write("<FRname>", 8); xml_strout(CC->room.QRname); client_write("</FRname>\n", 10);
- client_write("<FRmsglist>", 11);
+ client_write(HKEY("<room_messages>"));
+ client_write(HKEY("<FRname>")); xml_strout(CC->room.QRname); client_write(HKEY("</FRname>\n"));
+ client_write(HKEY("<FRmsglist>"));
CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, migr_export_room_msg, NULL);
- client_write("</FRmsglist>\n", 13);
- client_write("</room_messages>\n", 17);
+ client_write(HKEY("</FRmsglist>\n"));
+ client_write(HKEY("</room_messages>\n"));
}
int i;
for (i=0; i < MAXFLOORS; ++i) {
- client_write("<floor>\n", 8);
+ client_write(HKEY("<floor>\n"));
cprintf("<f_num>%d</f_num>\n", i);
CtdlGetFloor(&qfbuf, i);
buf = &qfbuf;
cprintf("<f_flags>%u</f_flags>\n", buf->f_flags);
- client_write("<f_name>", 8); xml_strout(buf->f_name); client_write("</f_name>\n", 10);
+ client_write(HKEY("<f_name>")); xml_strout(buf->f_name); client_write(HKEY("</f_name>\n"));
cprintf("<f_ref_count>%d</f_ref_count>\n", buf->f_ref_count);
cprintf("<f_ep_expire_mode>%d</f_ep_expire_mode>\n", buf->f_ep.expire_mode);
cprintf("<f_ep_expire_value>%d</f_ep_expire_value>\n", buf->f_ep.expire_value);
- client_write("</floor>\n", 9);
+ client_write(HKEY("</floor>\n"));
}
}
sizeof(visit) : cdbv->len));
cdb_free(cdbv);
- client_write("<visit>\n", 8);
+ client_write(HKEY("<visit>\n"));
cprintf("<v_roomnum>%ld</v_roomnum>\n", vbuf.v_roomnum);
cprintf("<v_roomgen>%ld</v_roomgen>\n", vbuf.v_roomgen);
cprintf("<v_usernum>%ld</v_usernum>\n", vbuf.v_usernum);
- client_write("<v_seen>", 8);
+ client_write(HKEY("<v_seen>"));
if ( (!IsEmptyStr(vbuf.v_seen)) && (is_sequence_set(vbuf.v_seen)) ) {
xml_strout(vbuf.v_seen);
}
else {
cprintf("%ld", vbuf.v_lastseen);
}
- client_write("</v_seen>", 9);
+ client_write(HKEY("</v_seen>"));
if ( (!IsEmptyStr(vbuf.v_answered)) && (is_sequence_set(vbuf.v_answered)) ) {
- client_write("<v_answered>", 12);
+ client_write(HKEY("<v_answered>"));
xml_strout(vbuf.v_answered);
- client_write("</v_answered>\n", 14);
+ client_write(HKEY("</v_answered>\n"));
}
cprintf("<v_flags>%u</v_flags>\n", vbuf.v_flags);
cprintf("<v_view>%d</v_view>\n", vbuf.v_view);
- client_write("</visit>\n", 9);
+ client_write(HKEY("</visit>\n"));
}
}
/* Ok, here we go ... */
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 0);
if (msg == NULL) return; /* fail silently */
- client_write("<message>\n", 10);
+ client_write(HKEY("<message>\n"));
GetMetaData(&smi, msgnum);
cprintf("<msg_msgnum>%ld</msg_msgnum>\n", msgnum);
cprintf("<msg_meta_refcount>%d</msg_meta_refcount>\n", smi.meta_refcount);
- client_write("<msg_meta_content_type>", 23); xml_strout(smi.meta_content_type); client_write("</msg_meta_content_type>\n", 25);
+ cprintf("<msg_meta_rfc822_length>%ld</msg_meta_rfc822_length>\n", smi.meta_rfc822_length);
+ client_write(HKEY("<msg_meta_content_type>")); xml_strout(smi.meta_content_type); client_write(HKEY("</msg_meta_content_type>\n"));
+ client_write(HKEY("<msg_mimetype>")); xml_strout(smi.mimetype); client_write(HKEY("</msg_mimetype>\n"));
- client_write("<msg_text>", 10);
+ client_write(HKEY("<msg_text>"));
CtdlSerializeMessage(&smr, msg);
CM_Free(msg);
free(smr.ser);
- client_write("</msg_text>\n", 12);
- client_write("</message>\n", 11);
+ client_write(HKEY("</msg_text>\n"));
+ client_write(HKEY("</message>\n"));
}
cdb_rewind(CDB_OPENID);
while (cdboi = cdb_next_item(CDB_OPENID), cdboi != NULL) {
if (cdboi->len > sizeof(long)) {
- client_write("<openid>\n", 9);
+ client_write(HKEY("<openid>\n"));
memcpy(&usernum, cdboi->ptr, sizeof(long));
snprintf(url, sizeof url, "%s", (cdboi->ptr)+sizeof(long) );
- client_write("<oid_url>", 9);
+ client_write(HKEY("<oid_url>"));
xml_strout(url);
- client_write("</oid_url>\n", 11);
+ client_write(HKEY("</oid_url>\n"));
cprintf("<oid_usernum>%ld</oid_usernum>\n", usernum);
- client_write("</openid>\n", 10);
+ client_write(HKEY("</openid>\n"));
}
cdb_free(cdboi);
}
cprintf("%d Exporting all Citadel databases.\n", LISTING_FOLLOWS);
Ctx->dont_term = 1;
- client_write("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", 40);
- client_write("<citadel_migrate_data>\n", 23);
+ client_write(HKEY("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"));
+ client_write(HKEY("<citadel_migrate_data>\n"));
cprintf("<version>%d</version>\n", REV_LEVEL);
cprintf("<progress>%d</progress>\n", 0);
if (Ctx->kill_me == 0) migr_export_visits();
cprintf("<progress>%d</progress>\n", 25);
if (Ctx->kill_me == 0) migr_export_messages();
- client_write("</citadel_migrate_data>\n", 24);
+ client_write(HKEY("</citadel_migrate_data>\n"));
cprintf("<progress>%d</progress>\n", 100);
- client_write("000\n", 4);
+ client_write(HKEY("000\n"));
Ctx->dont_term = 0;
}
-
-/*
- * Here's the code that implements the import side. It's going to end up being
- * one big loop with lots of global variables. I don't care. You wouldn't run
- * multiple concurrent imports anyway. If this offends your delicate sensibilities
- * then go rewrite it in Ruby on Rails or something.
- */
+/******************************************************************************
+ * Import code *
+ * Here's the code that implements the import side. It's going to end up *
+ * being one big loop with lots of global variables. I don't care. *
+ * You wouldn't run multiple concurrent imports anyway. If this offends your *
+ * delicate sensibilities then go rewrite it in Ruby on Rails or something. *
+ ******************************************************************************/
int citadel_migrate_data = 0; /* Are we inside a <citadel_migrate_data> tag pair? */
/*** MESSAGES ***/
- else if (!strcasecmp(el, "msg_msgnum")) import_msgnum = atol(ChrPtr(migr_chardata));
+ else if (!strcasecmp(el, "msg_msgnum")) smi.meta_msgnum = import_msgnum = atol(ChrPtr(migr_chardata));
else if (!strcasecmp(el, "msg_meta_refcount")) smi.meta_refcount = atoi(ChrPtr(migr_chardata));
+ else if (!strcasecmp(el, "msg_meta_rfc822_length")) smi.meta_rfc822_length = atoi(ChrPtr(migr_chardata));
else if (!strcasecmp(el, "msg_meta_content_type")) safestrncpy(smi.meta_content_type, ChrPtr(migr_chardata), sizeof smi.meta_content_type);
+ else if (!strcasecmp(el, "msg_mimetype")) safestrncpy(smi.mimetype, ChrPtr(migr_chardata), sizeof smi.mimetype);
else if (!strcasecmp(el, "msg_text"))
{
+ long rc;
+ struct CtdlMessage *msg;
FlushStrBuf(migr_MsgData);
- StrBufDecodeBase64To(migr_MsgData, migr_MsgData);
-
- cdb_store(CDB_MSGMAIN,
- &import_msgnum,
- sizeof(long),
- ChrPtr(migr_MsgData),
- StrLength(migr_MsgData) + 1);
-
- smi.meta_msgnum = import_msgnum;
- PutMetaData(&smi);
+ StrBufDecodeBase64To(migr_chardata, migr_MsgData);
+
+ msg = CtdlDeserializeMessage(import_msgnum, -1,
+ ChrPtr(migr_MsgData),
+ StrLength(migr_MsgData));
+ if (msg != NULL) {
+ rc = CtdlSaveThisMessage(msg, import_msgnum, 0);
+ if (rc == 0) {
+ PutMetaData(&smi);
+ }
+ CM_Free(msg);
+ }
+ else {
+ rc = -1;
+ }
syslog(LOG_INFO,
- "Imported message #%ld, size=%d, refcount=%d, content-type: %s\n",
+ "%s message #%ld, size=%d, refcount=%d, bodylength=%ld, content-type: %s / %s \n",
+ (rc!= 0)?"failed to import ":"Imported ",
import_msgnum,
StrLength(migr_MsgData),
smi.meta_refcount,
- smi.meta_content_type);
+ smi.meta_rfc822_length,
+ smi.meta_content_type,
+ smi.mimetype);
+ memset(&smi, 0, sizeof(smi));
}
/*** MORE GENERAL STUFF ***/
+/******************************************************************************
+ * Dispatcher, Common code *
+ ******************************************************************************/
/*
* Dump out the pathnames of directories which can be copied "as is"
*/
cprintf("000\n");
}
+/******************************************************************************
+ * Repair database integrity *
+ ******************************************************************************/
-/*
- * Common code appears in this section
- */
+StrBuf *PlainMessageBuf = NULL;
+HashList *UsedMessageIDS = NULL;
+int migr_restore_message_metadata(long msgnum, int refcount)
+{
+ CitContext *CCC = MyContext();
+ struct MetaData smi;
+ struct CtdlMessage *msg;
+ char *mptr = NULL;
+
+ /* We can use a static buffer here because there will never be more than
+ * one of this operation happening at any given time, and it's really best
+ * to just keep it allocated once instead of torturing malloc/free.
+ * Call this function with msgnum "-1" to free the buffer when finished.
+ */
+ static int encoded_alloc = 0;
+ static char *encoded_msg = NULL;
+
+ if (msgnum < 0) {
+ if ((encoded_alloc == 0) && (encoded_msg != NULL)) {
+ free(encoded_msg);
+ encoded_alloc = 0;
+ encoded_msg = NULL;
+ // todo FreeStrBuf(&PlainMessageBuf); PlainMessageBuf = NULL;
+ }
+ return 0;
+ }
+
+ if (PlainMessageBuf == NULL) {
+ PlainMessageBuf = NewStrBufPlain(NULL, 10*SIZ);
+ }
+
+ /* Ok, here we go ... */
+
+ msg = CtdlFetchMessage(msgnum, 1, 0);
+ if (msg == NULL) {
+ return 1;
+ }
+
+ GetMetaData(&smi, msgnum);
+ smi.meta_msgnum = msgnum;
+ smi.meta_refcount = refcount;
+
+ /* restore the content type from the message body: */
+ mptr = bmstrcasestr(msg->cm_fields[eMesageText], "Content-type:");
+ if (mptr != NULL) {
+ char *aptr;
+ safestrncpy(smi.meta_content_type, &mptr[13], sizeof smi.meta_content_type);
+ striplt(smi.meta_content_type);
+ aptr = smi.meta_content_type;
+ while (!IsEmptyStr(aptr)) {
+ if ((*aptr == ';')
+ || (*aptr == ' ')
+ || (*aptr == 13)
+ || (*aptr == 10)) {
+ memset(aptr, 0, sizeof(smi.meta_content_type) - (aptr - smi.meta_content_type));
+ }
+ else aptr++;
+ }
+ }
+
+ CCC->redirect_buffer = PlainMessageBuf;
+ CtdlOutputPreLoadedMsg(msg, MT_RFC822, HEADERS_ALL, 0, 1, QP_EADDR);
+ smi.meta_rfc822_length = StrLength(CCC->redirect_buffer);
+ CCC->redirect_buffer = NULL;
+
+
+ syslog(LOG_INFO,
+ "Setting message #%ld meta data to: refcount=%d, bodylength=%ld, content-type: %s / %s \n",
+ smi.meta_msgnum,
+ smi.meta_refcount,
+ smi.meta_rfc822_length,
+ smi.meta_content_type,
+ smi.mimetype);
+
+ PutMetaData(&smi);
+
+ CM_Free(msg);
+
+ return 0;
+}
+
+void migr_check_room_msg(long msgnum, void *userdata) {
+ fprintf(migr_global_message_list, "%ld %s\n", msgnum, CC->room.QRname);
+}
+
+void migr_check_rooms_backend(struct ctdlroom *buf, void *data) {
+
+ /* message list goes inside this tag */
+
+ CtdlGetRoom(&CC->room, buf->QRname);
+ CtdlForEachMessage(MSGS_ALL, 0L, NULL, NULL, NULL, migr_check_room_msg, NULL);
+}
+
+void RemoveMessagesFromRooms(StrBuf *RoomNameVec, long msgnum) {
+ struct MetaData smi;
+ const char *Pos = NULL;
+ StrBuf *oneRoom = NewStrBuf();
+
+ syslog(LOG_INFO, "removing message pointer %ld from these rooms: %s", msgnum, ChrPtr(RoomNameVec));
+
+ while (Pos != StrBufNOTNULL){
+ StrBufExtract_NextToken(oneRoom, RoomNameVec, &Pos, '|');
+ CtdlDeleteMessages(ChrPtr(oneRoom), &msgnum, 1, "");
+ };
+ GetMetaData(&smi, msgnum);
+ TDAP_AdjRefCount(msgnum, -smi.meta_refcount);
+}
+
+void migr_do_restore_meta(void) {
+ char buf[SIZ];
+ int failGetMessage;
+ long msgnum;
+ int lastnum = 0;
+ int refcount = 0;
+ CitContext *Ctx;
+ char *prn;
+ StrBuf *RoomNames;
+ char cmd[SIZ];
+
+ migr_global_message_list = fopen(migr_tempfilename1, "w");
+ if (migr_global_message_list != NULL) {
+ CtdlForEachRoom(migr_check_rooms_backend, NULL);
+ fclose(migr_global_message_list);
+ }
+
+ /*
+ * Process the 'global' message list. (Sort it and remove dups.
+ * Dups are ok because a message may be in more than one room, but
+ * this will be handled by exporting the reference count, not by
+ * exporting the message multiple times.)
+ */
+ snprintf(cmd, sizeof cmd, "sort -n <%s >%s", migr_tempfilename1, migr_tempfilename2);
+ if (system(cmd) != 0) syslog(LOG_ALERT, "Error %d\n", errno);
+
+ RoomNames = NewStrBuf();
+ Ctx = CC;
+ migr_global_message_list = fopen(migr_tempfilename2, "r");
+ if (migr_global_message_list != NULL) {
+ syslog(LOG_INFO, "Opened %s\n", migr_tempfilename1);
+ while ((Ctx->kill_me == 0) &&
+ (fgets(buf, sizeof(buf), migr_global_message_list) != NULL)) {
+ msgnum = atol(buf);
+ if (msgnum == 0L)
+ continue;
+ if (lastnum == 0) {
+ lastnum = msgnum;
+ }
+ prn = strchr(buf, ' ');
+ if (lastnum != msgnum) {
+ failGetMessage = migr_restore_message_metadata(lastnum, refcount);
+ if (failGetMessage) {
+ RemoveMessagesFromRooms(RoomNames, lastnum);
+ }
+ refcount = 1;
+ lastnum = msgnum;
+ if (prn != NULL)
+ StrBufPlain(RoomNames, prn + 1, -1);
+ StrBufTrim(RoomNames);
+ }
+ else {
+ if (prn != NULL) {
+ if (StrLength(RoomNames) > 0)
+ StrBufAppendBufPlain(RoomNames, HKEY("|"), 0);
+ StrBufAppendBufPlain(RoomNames, prn, -1, 1);
+ StrBufTrim(RoomNames);
+ }
+ refcount ++;
+ }
+ lastnum = msgnum;
+ }
+ failGetMessage = migr_restore_message_metadata(msgnum, refcount);
+ if (failGetMessage) {
+ RemoveMessagesFromRooms(RoomNames, lastnum);
+ }
+ fclose(migr_global_message_list);
+ }
+
+ migr_restore_message_metadata(-1L, -1); /* This frees the encoding buffer */
+ cprintf("%d system analysis completed", CIT_OK);
+ Ctx->kill_me = 1;
+}
+
+
+
+
+/******************************************************************************
+ * Dispatcher, Common code *
+ ******************************************************************************/
void cmd_migr(char *cmdbuf) {
char cmd[32];
else if (!strcasecmp(cmd, "listdirs")) {
migr_do_listdirs();
}
+ else if (!strcasecmp(cmd, "restoremeta")) {
+ migr_do_restore_meta();
+ }
else {
cprintf("%d illegal command\n", ERROR + ILLEGAL_VALUE);
}
}
}
+/******************************************************************************
+ * Module Hook *
+ ******************************************************************************/
CTDL_MODULE_INIT(migrate)
{
sc = (SpoolControl *)userdata;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL)
{
#endif
+/*
+ * Bounce a message back to the sender
+ */
+void network_bounce(struct CtdlMessage **pMsg, char *reason)
+{
+ struct CitContext *CCC = CC;
+ char buf[SIZ];
+ char bouncesource[SIZ];
+ char recipient[SIZ];
+ recptypes *valid = NULL;
+ char force_room[ROOMNAMELEN];
+ static int serialnum = 0;
+ long len;
+ struct CtdlMessage *msg = *pMsg;
+ *pMsg = NULL;
+ QNM_syslog(LOG_DEBUG, "entering network_bounce()\n");
+
+ if (msg == NULL) return;
+
+ snprintf(bouncesource, sizeof bouncesource, "%s@%s", BOUNCESOURCE, CtdlGetConfigStr("c_nodename"));
+
+ /*
+ * Give it a fresh message ID
+ */
+ len = snprintf(buf, sizeof(buf),
+ "%ld.%04lx.%04x@%s",
+ (long)time(NULL),
+ (long)getpid(),
+ ++serialnum,
+ CtdlGetConfigStr("c_fqdn"));
+
+ CM_SetField(msg, emessageId, buf, len);
+
+ /*
+ * FIXME ... right now we're just sending a bounce; we really want to
+ * include the text of the bounced message.
+ */
+ CM_SetField(msg, eMesageText, reason, strlen(reason));
+ msg->cm_format_type = 0;
+
+ /*
+ * Turn the message around
+ */
+ CM_FlushField(msg, eRecipient);
+ CM_FlushField(msg, eDestination);
+
+ len = snprintf(recipient, sizeof(recipient), "%s@%s",
+ msg->cm_fields[eAuthor],
+ msg->cm_fields[eNodeName]);
+
+ CM_SetField(msg, eAuthor, HKEY(BOUNCESOURCE));
+ CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename")));
+ CM_SetField(msg, eMsgSubject, HKEY("Delivery Status Notification (Failure)"));
+
+ Netmap_AddMe(msg, HKEY("unknown_user"));
+
+ /* Now submit the message */
+ valid = validate_recipients(recipient, NULL, 0);
+ if (valid != NULL) if (valid->num_error != 0) {
+ free_recipients(valid);
+ valid = NULL;
+ }
+ if ( (valid == NULL) || (!strcasecmp(recipient, bouncesource)) ) {
+ strcpy(force_room, CtdlGetConfigStr("c_aideroom"));
+ }
+ else {
+ strcpy(force_room, "");
+ }
+ if ( (valid == NULL) && IsEmptyStr(force_room) ) {
+ strcpy(force_room, CtdlGetConfigStr("c_aideroom"));
+ }
+ CtdlSubmitMsg(msg, valid, force_room, 0);
+
+ /* Clean up */
+ if (valid != NULL) free_recipients(valid);
+ CM_Free(msg);
+ QNM_syslog(LOG_DEBUG, "leaving network_bounce()\n");
+}
+
+
void ParseLastSent(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG)
{
RoomNetCfgLine *nptr;
}
else
{
- snprintf(buf, sizeof buf, "room_%s@%s", CCC->room.QRname, CtdlGetConfigStr("c_fqdn"));
+ snprintf(buf, sizeof buf, "room_%s@%s",
+ CCC->room.QRname, CtdlGetConfigStr("c_fqdn"));
}
for (i=0; buf[i]; ++i) {
}
}
+
+/*
+ * Check the use table. This is a list of messages which have recently
+ * arrived on the system. It is maintained and queried to prevent the same
+ * message from being entered into the database multiple times if it happens
+ * to arrive multiple times by accident.
+ */
+int network_usetable(struct CtdlMessage *msg)
+{
+ StrBuf *msgid;
+ struct CitContext *CCC = CC;
+ time_t now;
+
+ /* Bail out if we can't generate a message ID */
+ if ((msg == NULL) || CM_IsEmpty(msg, emessageId))
+ {
+ return(0);
+ }
+
+ /* Generate the message ID */
+ msgid = NewStrBufPlain(CM_KEY(msg, emessageId));
+ if (haschar(ChrPtr(msgid), '@') == 0) {
+ StrBufAppendBufPlain(msgid, HKEY("@"), 0);
+ if (!CM_IsEmpty(msg, eNodeName)) {
+ StrBufAppendBufPlain(msgid, CM_KEY(msg, eNodeName), 0);
+ }
+ else {
+ FreeStrBuf(&msgid);
+ return(0);
+ }
+ }
+ now = time(NULL);
+ if (CheckIfAlreadySeen("Networker Import",
+ msgid,
+ now, 0,
+ eUpdate,
+ CCC->cs_pid, 0) != 0)
+ {
+ FreeStrBuf(&msgid);
+ return(1);
+ }
+ FreeStrBuf(&msgid);
+
+ return(0);
+}
+
+
/*
* Process a buffer containing a single message from a single file
* from the inbound queue
else { /* invalid destination node name */
FreeStrBuf(&Buf);
- network_bounce(msg,
+ network_bounce(&msg,
"A message you sent could not be delivered due to an invalid destination node"
" name. Please check the address and try sending the message again.\n");
- msg = NULL;
return;
}
else if (!CM_IsEmpty(msg, eRecipient)) {
recp = validate_recipients(msg->cm_fields[eRecipient], NULL, 0);
if (recp != NULL) if (recp->num_error != 0) {
- network_bounce(msg,
+ network_bounce(&msg,
"A message you sent could not be delivered due to an invalid address.\n"
"Please check the address and try sending the message again.\n");
- msg = NULL;
free_recipients(recp);
QNM_syslog(LOG_DEBUG, "Bouncing message due to invalid recipient address.\n");
return;
struct RoomProcList *rplist = NULL;
-
-/*
- * Check the use table. This is a list of messages which have recently
- * arrived on the system. It is maintained and queried to prevent the same
- * message from being entered into the database multiple times if it happens
- * to arrive multiple times by accident.
- */
-int network_usetable(struct CtdlMessage *msg)
-{
- StrBuf *msgid;
- struct CitContext *CCC = CC;
- time_t now;
-
- /* Bail out if we can't generate a message ID */
- if ((msg == NULL) || CM_IsEmpty(msg, emessageId))
- {
- return(0);
- }
-
- /* Generate the message ID */
- msgid = NewStrBufPlain(CM_KEY(msg, emessageId));
- if (haschar(ChrPtr(msgid), '@') == 0) {
- StrBufAppendBufPlain(msgid, HKEY("@"), 0);
- if (!CM_IsEmpty(msg, eNodeName)) {
- StrBufAppendBufPlain(msgid, CM_KEY(msg, eNodeName), 0);
- }
- else {
- FreeStrBuf(&msgid);
- return(0);
- }
- }
- now = time(NULL);
- if (CheckIfAlreadySeen("Networker Import",
- msgid,
- now, 0,
- eCheckUpdate,
- CCC->cs_pid, 0) != 0)
- {
- FreeStrBuf(&msgid);
- return(1);
- }
- FreeStrBuf(&msgid);
-
- return(0);
-}
-
-
-
/*
* Send the *entire* contents of the current room to one specific network node,
* ignoring anything we know about which messages have already undergone
}
-
-/*
- * Bounce a message back to the sender
- */
-void network_bounce(struct CtdlMessage *msg, char *reason)
-{
- struct CitContext *CCC = CC;
- char buf[SIZ];
- char bouncesource[SIZ];
- char recipient[SIZ];
- recptypes *valid = NULL;
- char force_room[ROOMNAMELEN];
- static int serialnum = 0;
- long len;
-
- QNM_syslog(LOG_DEBUG, "entering network_bounce()\n");
-
- if (msg == NULL) return;
-
- snprintf(bouncesource, sizeof bouncesource, "%s@%s", BOUNCESOURCE, CtdlGetConfigStr("c_nodename"));
-
- /*
- * Give it a fresh message ID
- */
- len = snprintf(buf, sizeof(buf),
- "%ld.%04lx.%04x@%s",
- (long)time(NULL),
- (long)getpid(),
- ++serialnum,
- CtdlGetConfigStr("c_fqdn")
- );
-
- CM_SetField(msg, emessageId, buf, len);
-
- /*
- * FIXME ... right now we're just sending a bounce; we really want to
- * include the text of the bounced message.
- */
- CM_SetField(msg, eMesageText, reason, strlen(reason));
- msg->cm_format_type = 0;
-
- /*
- * Turn the message around
- */
- CM_FlushField(msg, eRecipient);
- CM_FlushField(msg, eDestination);
-
- len = snprintf(recipient, sizeof(recipient), "%s@%s",
- msg->cm_fields[eAuthor],
- msg->cm_fields[eNodeName]);
-
- CM_SetField(msg, eAuthor, HKEY(BOUNCESOURCE));
- CM_SetField(msg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename")));
- CM_SetField(msg, eMsgSubject, HKEY("Delivery Status Notification (Failure)"));
-
- Netmap_AddMe(msg, HKEY("unknown_user"));
-
- /* Now submit the message */
- valid = validate_recipients(recipient, NULL, 0);
- if (valid != NULL) if (valid->num_error != 0) {
- free_recipients(valid);
- valid = NULL;
- }
- if ( (valid == NULL) || (!strcasecmp(recipient, bouncesource)) )
- {
- strcpy(force_room, CtdlGetConfigStr("c_aideroom"));
- }
- else {
- strcpy(force_room, "");
- }
- if ( (valid == NULL) && IsEmptyStr(force_room) ) {
- strcpy(force_room, CtdlGetConfigStr("c_aideroom"));
- }
- CtdlSubmitMsg(msg, valid, force_room, 0);
-
- /* Clean up */
- if (valid != NULL) free_recipients(valid);
- CM_Free(msg);
- QNM_syslog(LOG_DEBUG, "leaving network_bounce()\n");
-}
-
-
-
/*
* network_do_queue()
*
void network_queue_room(struct ctdlroom *, void *);
////void destroy_network_queue_room(void);
-void network_bounce(struct CtdlMessage *msg, char *reason);
-int network_usetable(struct CtdlMessage *msg);
if (msgnum < lr->lo) return;
if ((lr->hi != 0) && (msgnum > lr->hi)) return;
- struct CtdlMessage *msg = CtdlFetchMessage(msgnum, 0);
+ struct CtdlMessage *msg = CtdlFetchMessage(msgnum, 0, 1);
if (msg == NULL) {
return;
}
const char *HKey;
void *vData;
pop3aggr *RecvMsg = (pop3aggr *) IO->Data;
+ time_t seenstamp = 0;
SetPOP3State(IO, eUseTable);
if (server_shutting_down)
return eAbort;
- if (CheckIfAlreadySeen("POP3 Item Seen",
- RecvMsg->CurrMsg->MsgUID,
- EvGetNow(IO),
- EvGetNow(IO) - USETABLE_ANTIEXPIRE,
- eCheckUpdate,
- IO->ID, CCID)
- != 0)
+ RecvMsg->CurrMsg = (FetchItem*)vData;
+
+ seenstamp = CheckIfAlreadySeen("POP3 Item Seen",
+ RecvMsg->CurrMsg->MsgUID,
+ EvGetNow(IO),
+ EvGetNow(IO) - USETABLE_ANTIEXPIRE,
+ eCheckUpdate,
+ IO->ID, CCID);
+ if (seenstamp != 0)
{
/* Item has already been seen */
RecvMsg->CurrMsg->NeedFetch = 0;
SetPOP3State(IO, eGetMsg);
+ EVP3CM_syslog(LOG_DEBUG, "fast forwarding to the next unknown message");
+
RecvMsg->CurrMsg = NULL;
while ((RecvMsg->Pos != NULL) &&
GetNextHashPos(RecvMsg->MsgNumbers,
if ((RecvMsg->CurrMsg != NULL ) && (RecvMsg->CurrMsg->NeedFetch == 1))
{
+ EVP3CM_syslog(LOG_DEBUG, "fetching next");
/* Message has not been seen.
* Tell the server to fetch the message... */
StrBufPrintf(RecvMsg->IO.SendBuf.Buf,
return eReadMessage;
}
else {
+ EVP3CM_syslog(LOG_DEBUG, "no more messages to fetch.");
RecvMsg->State = ReadQuitState;
return POP3_C_DispatchWriteDone(&RecvMsg->IO);
}
AsyncIO *IO = &RecvMsg->IO;
POP3C_DBG_READ();
RecvMsg->State = GetOneMessageIDState;
- return eReadMessage;
+ return POP3_C_DispatchWriteDone(&RecvMsg->IO);
}
eNextState POP3C_SendQuit(pop3aggr *RecvMsg)
guid,
EvGetNow(IO),
EvGetNow(IO) - USETABLE_ANTIEXPIRE,
- eCheckUpdate,
+ eUpdate,
CCID, IO->ID)
!= 0)
{
return SIEVE2_ERROR_BADARGS;
}
- msg = CtdlFetchMessage(cs->msgnum, 1);
+ msg = CtdlFetchMessage(cs->msgnum, 1, 1);
if (msg == NULL) {
SV_syslog(LOG_WARNING, "REDIRECT failed: unable to fetch msg %ld", cs->msgnum);
free_recipients(valid);
/*
* Make sure you include message body so you can get those second-level headers ;)
*/
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
/*
long conflen;
u->config_msgnum = msgnum;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
u->config_msgnum = (-1) ;
return;
return; // already got it
}
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
return;
}
SMTPC_syslog(LOG_DEBUG, "smtp_do_procmsg(%ld)\n", msgnum);
///strcpy(envelope_from, "");
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
SMTPC_syslog(LOG_ERR, "tried %ld but no such message!\n",
msgnum);
void vcard_add_to_directory(long msgnum, void *data) {
struct CtdlMessage *msg;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg != NULL) {
vcard_extract_internet_addresses(msg, vcard_directory_add_user);
}
if (VCmsgnum < 0L) return vcard_new();
- msg = CtdlFetchMessage(VCmsgnum, 1);
+ msg = CtdlFetchMessage(VCmsgnum, 1, 1);
if (msg == NULL) return vcard_new();
v = vcard_load(msg->cm_fields[eMesageText]);
return;
}
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
if (CM_IsEmpty(msg, eMesageText))
void dvca_callback(long msgnum, void *userdata) {
struct CtdlMessage *msg = NULL;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
mime_parser(CM_RANGE(msg, eMesageText),
*dvca_mime_callback, /* callback function */
collected_addresses = (char *)userdata;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) return;
v = vcard_load(msg->cm_fields[eMesageText]);
CM_Free(msg);
/* See if we can retrieve the previous version. */
old_msgnum = CtdlLocateMessageByEuid(msg->cm_fields[eExclusiveID], &CCC->room);
if (old_msgnum > 0L) {
- old_msg = CtdlFetchMessage(old_msgnum, 1);
+ old_msg = CtdlFetchMessage(old_msgnum, 1, 1);
}
else {
old_msg = NULL;
history_msgnum = CtdlLocateMessageByEuid(history_page, &CCC->room);
history_msg = NULL;
if (history_msgnum > 0L) {
- history_msg = CtdlFetchMessage(history_msgnum, 1);
+ history_msg = CtdlFetchMessage(history_msgnum, 1, 1);
}
/* Create a new history message if necessary */
snprintf(history_page_name, sizeof history_page_name, "%s_HISTORY_", pagename);
msgnum = CtdlLocateMessageByEuid(history_page_name, &CC->room);
if (msgnum > 0L) {
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
}
else {
msg = NULL;
*/
msgnum = CtdlLocateMessageByEuid(pagename, &CCC->room);
if (msgnum > 0L) {
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
}
else {
msg = NULL;
snprintf(history_page_name, sizeof history_page_name, "%s_HISTORY_", pagename);
msgnum = CtdlLocateMessageByEuid(history_page_name, &CCC->room);
if (msgnum > 0L) {
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
}
else {
msg = NULL;
char *ptr = NULL;
char *lasts = NULL;
- msg = CtdlFetchMessage(msgnum, 1);
+ msg = CtdlFetchMessage(msgnum, 1, 1);
if (msg == NULL) {
return;
}
free(msglist);
return -1;
}
- msg = CtdlFetchMessage(msglist[a], 1);
+ msg = CtdlFetchMessage(msglist[a], 1, 1);
if (msg != NULL) {
if (CtdlMsgCmp(msg, compare)) {
msglist[a] = 0L;
}
}
-
-/*
- * Load a message from disk into memory.
- * This is used by CtdlOutputMsg() and other fetch functions.
- *
- * NOTE: Caller is responsible for freeing the returned CtdlMessage struct
- * using the CtdlMessageFree() function.
- */
-struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body)
+struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const char *Buffer, long Length)
{
struct CitContext *CCC = CC;
- struct cdbdata *dmsgtext;
struct CtdlMessage *ret = NULL;
- char *mptr;
- char *upper_bound;
+ const char *mptr;
+ const char *upper_bound;
cit_uint8_t ch;
cit_uint8_t field_header;
eMsgField which;
- MSG_syslog(LOG_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body);
- dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
- if (dmsgtext == NULL) {
- MSG_syslog(LOG_ERR, "CtdlFetchMessage(%ld, %d) Failed!\n", msgnum, with_body);
- return NULL;
- }
- mptr = dmsgtext->ptr;
- upper_bound = mptr + dmsgtext->len;
+ mptr = Buffer;
+ upper_bound = Buffer + Length;
/* Parse the three bytes that begin EVERY message on disk.
* The first is always 0xFF, the on-disk magic number.
ch = *mptr++;
if (ch != 255) {
MSG_syslog(LOG_ERR, "Message %ld appears to be corrupted.\n", msgnum);
- cdb_free(dmsgtext);
return NULL;
}
ret = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage));
ret->cm_anon_type = *mptr++; /* Anon type byte */
ret->cm_format_type = *mptr++; /* Format type byte */
-
- if (dmsgtext->ptr[dmsgtext->len - 1] != '\0')
- {
- MSG_syslog(LOG_ERR, "CtdlFetchMessage(%ld, %d) Forcefully terminating message!!\n", msgnum, with_body);
- dmsgtext->ptr[dmsgtext->len - 1] = '\0';
- }
-
/*
* The rest is zero or more arbitrary fields. Load them in.
* We're done when we encounter either a zero-length field or
} while ((mptr < upper_bound) && (field_header != 'M'));
+ return (ret);
+}
+
+
+/*
+ * Load a message from disk into memory.
+ * This is used by CtdlOutputMsg() and other fetch functions.
+ *
+ * NOTE: Caller is responsible for freeing the returned CtdlMessage struct
+ * using the CtdlMessageFree() function.
+ */
+struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hooks)
+{
+ struct CitContext *CCC = CC;
+ struct cdbdata *dmsgtext;
+ struct CtdlMessage *ret = NULL;
+
+ MSG_syslog(LOG_DEBUG, "CtdlFetchMessage(%ld, %d)\n", msgnum, with_body);
+ dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
+ if (dmsgtext == NULL) {
+ MSG_syslog(LOG_ERR, "CtdlFetchMessage(%ld, %d) Failed!\n", msgnum, with_body);
+ return NULL;
+ }
+
+ if (dmsgtext->ptr[dmsgtext->len - 1] != '\0')
+ {
+ MSG_syslog(LOG_ERR, "CtdlFetchMessage(%ld, %d) Forcefully terminating message!!\n", msgnum, with_body);
+ dmsgtext->ptr[dmsgtext->len - 1] = '\0';
+ }
+
+ ret = CtdlDeserializeMessage(msgnum, with_body, dmsgtext->ptr, dmsgtext->len);
+
cdb_free(dmsgtext);
+ if (ret == NULL) {
+ return NULL;
+ }
+
/* Always make sure there's something in the msg text field. If
* it's NULL, the message text is most likely stored separately,
* so go ahead and fetch that. Failing that, just set a dummy
}
/* Perform "before read" hooks (aborting if any return nonzero) */
- if (PerformMessageHooks(ret, NULL, EVT_BEFOREREAD) > 0) {
+ if (run_msg_hooks && (PerformMessageHooks(ret, NULL, EVT_BEFOREREAD) > 0)) {
CM_Free(ret);
return NULL;
}
* request that we don't even bother loading the body into memory.
*/
if (headers_only == HEADERS_FAST) {
- TheMessage = CtdlFetchMessage(msg_num, 0);
+ TheMessage = CtdlFetchMessage(msg_num, 0, 1);
}
else {
- TheMessage = CtdlFetchMessage(msg_num, 1);
+ TheMessage = CtdlFetchMessage(msg_num, 1, 1);
}
if (TheMessage == NULL) {
msg = supplied_msg;
}
else {
- msg = CtdlFetchMessage(msgid, 0);
+ msg = CtdlFetchMessage(msgid, 0, 1);
}
if (msg != NULL) {
* called by server-side modules.
*
*/
-long send_message(struct CtdlMessage *msg) {
+long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply) {
struct CitContext *CCC = CC;
- long newmsgid;
long retval;
- char msgidbuf[256];
- long msgidbuflen;
struct ser_ret smr;
int is_bigmsg = 0;
char *holdM = NULL;
long holdMLen = 0;
- /* Get a new message number */
- newmsgid = get_new_message_number();
- msgidbuflen = snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s",
- (long unsigned int) time(NULL),
- (long unsigned int) newmsgid,
- CtdlGetConfigStr("c_fqdn")
- );
-
- /* Generate an ID if we don't have one already */
- if (CM_IsEmpty(msg, emessageId)) {
- CM_SetField(msg, emessageId, msgidbuf, msgidbuflen);
- }
-
- /* If the message is big, set its body aside for storage elsewhere */
- if (!CM_IsEmpty(msg, eMesageText)) {
- if (msg->cm_lengths[eMesageText] > BIGMSG) {
- is_bigmsg = 1;
- holdM = msg->cm_fields[eMesageText];
- msg->cm_fields[eMesageText] = NULL;
- holdMLen = msg->cm_lengths[eMesageText];
- msg->cm_lengths[eMesageText] = 0;
- }
+ /*
+ * If the message is big, set its body aside for storage elsewhere
+ * and we hide the message body from the serializer
+ */
+ if (!CM_IsEmpty(msg, eMesageText) && msg->cm_lengths[eMesageText] > BIGMSG)
+ {
+ is_bigmsg = 1;
+ holdM = msg->cm_fields[eMesageText];
+ msg->cm_fields[eMesageText] = NULL;
+ holdMLen = msg->cm_lengths[eMesageText];
+ msg->cm_lengths[eMesageText] = 0;
}
/* Serialize our data structure for storage in the database */
CtdlSerializeMessage(&smr, msg);
if (is_bigmsg) {
+ /* put the message body back into the message */
msg->cm_fields[eMesageText] = holdM;
msg->cm_lengths[eMesageText] = holdMLen;
}
if (smr.len == 0) {
- cprintf("%d Unable to serialize message\n",
- ERROR + INTERNAL_ERROR);
+ if (Reply) {
+ cprintf("%d Unable to serialize message\n",
+ ERROR + INTERNAL_ERROR);
+ }
+ else {
+ MSGM_syslog(LOG_ERR, "CtdlSaveMessage() unable to serialize message");
+
+ }
return (-1L);
}
/* Write our little bundle of joy into the message base */
- if (cdb_store(CDB_MSGMAIN, &newmsgid, (int)sizeof(long),
- smr.ser, smr.len) < 0) {
- MSGM_syslog(LOG_ERR, "Can't store message\n");
- retval = 0L;
- } else {
+ retval = cdb_store(CDB_MSGMAIN, &msgid, (int)sizeof(long),
+ smr.ser, smr.len);
+ if (retval < 0) {
+ MSG_syslog(LOG_ERR, "Can't store message %ld: %ld", msgid, retval);
+ }
+ else {
if (is_bigmsg) {
- cdb_store(CDB_BIGMSGS,
- &newmsgid,
- (int)sizeof(long),
- holdM,
- (holdMLen + 1)
+ retval = cdb_store(CDB_BIGMSGS,
+ &msgid,
+ (int)sizeof(long),
+ holdM,
+ (holdMLen + 1)
);
+ if (retval < 0) {
+ MSG_syslog(LOG_ERR, "failed to store message body for msgid %ld: %ld",
+ msgid, retval);
+ }
}
- retval = newmsgid;
}
/* Free the memory we used for the serialized message */
free(smr.ser);
+ return(retval);
+}
+
+long send_message(struct CtdlMessage *msg) {
+ long newmsgid;
+ long retval;
+ char msgidbuf[256];
+ long msgidbuflen;
+
+ /* Get a new message number */
+ newmsgid = get_new_message_number();
+
+ /* Generate an ID if we don't have one already */
+ if (CM_IsEmpty(msg, emessageId)) {
+ msgidbuflen = snprintf(msgidbuf, sizeof msgidbuf, "%08lX-%08lX@%s",
+ (long unsigned int) time(NULL),
+ (long unsigned int) newmsgid,
+ CtdlGetConfigStr("c_fqdn")
+ );
+
+ CM_SetField(msg, emessageId, msgidbuf, msgidbuflen);
+ }
+
+ retval = CtdlSaveThisMessage(msg, newmsgid, 1);
+
+ if (retval == 0) {
+ retval = newmsgid;
+ }
+
/* Return the *local* message ID to the caller
* (even if we're storing an incoming network message)
*/
* serialized message in memory. THE LATTER MUST BE FREED BY THE CALLER.
*/
void CtdlSerializeMessage(struct ser_ret *ret, /* return values */
- struct CtdlMessage *msg) /* unserialized msg */
+ struct CtdlMessage *msg) /* unserialized msg */
{
struct CitContext *CCC = CC;
size_t wlen;
* API function to delete messages which match a set of criteria
* (returns the actual number of messages deleted)
*/
-int CtdlDeleteMessages(char *room_name, /* which room */
+int CtdlDeleteMessages(const char *room_name, /* which room */
long *dmsgnums, /* array of msg numbers to be deleted */
int num_dmsgnums, /* number of msgs to be deleted, or 0 for "any" */
char *content_type /* or "" for any. regular expressions expected. */
struct CtdlMessage *compare,
ForEachMsgCallback CallBack,
void *userdata);
-int CtdlDeleteMessages(char *, long *, int, char *);
+int CtdlDeleteMessages(const char *, long *, int, char *);
void CtdlWriteObject(char *req_room, /* Room to stuff it in */
char *content_type, /* MIME type of this object */
char *raw_message, /* Data to be written */
int is_unique, /* Del others of this type? */
unsigned int flags /* Internal save flags */
);
-struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body);
+struct CtdlMessage *CtdlFetchMessage(long msgnum, int with_body, int run_msg_hooks);
struct CtdlMessage * CM_Duplicate
(struct CtdlMessage *OrgMsg);
int CM_IsEmpty (struct CtdlMessage *Msg, eMsgField which);
Message->cm_fields[Which] + Message->cm_lengths[Which]
void CtdlSerializeMessage(struct ser_ret *, struct CtdlMessage *);
+struct CtdlMessage *CtdlDeserializeMessage(long msgnum, int with_body, const char *Buffer, long Length);
void ReplicationChecks(struct CtdlMessage *);
int CtdlSaveMsgPointersInRoom(char *roomname, long newmsgidlist[], int num_newmsgs,
- int do_repl_check, struct CtdlMessage *supplied_msg, int suppress_refcount_adj);
+ int do_repl_check, struct CtdlMessage *supplied_msg, int suppress_refcount_adj);
int CtdlSaveMsgPointerInRoom(char *roomname, long msgid, int do_repl_check, struct CtdlMessage *msg);
+long CtdlSaveThisMessage(struct CtdlMessage *msg, long msgid, int Reply);
char *CtdlReadMessageBody(char *terminator, long tlen, size_t maxlen, StrBuf *exist, int crlf, int *sock);
StrBuf *CtdlReadMessageBodyBuf(char *terminator, /* token signalling EOT */
long tlen,
#define CCCID CCC->cs_pid
#define MSG_syslog(LEVEL, FORMAT, ...) \
MSGDBGLOG(LEVEL) syslog(LEVEL, \
- "CC[%d]MSG" FORMAT, \
+ "CC[%d]MSG " FORMAT, \
CCCID, __VA_ARGS__)
#define MSGM_syslog(LEVEL, FORMAT) \
MSGDBGLOG(LEVEL) syslog(LEVEL, \
- "CC[%d]MSG" FORMAT, \
+ "CC[%d]MSG " FORMAT, \
CCCID)
/*
* CtdlGetRoomLock() - same as getroom() but locks the record (if supported)
*/
-int CtdlGetRoomLock(struct ctdlroom *qrbuf, char *room_name)
+int CtdlGetRoomLock(struct ctdlroom *qrbuf, const char *room_name)
{
register int retval;
retval = CtdlGetRoom(qrbuf, room_name);
uid_t ctdluid = 0;
const char *CitadelServiceUDS="citadel-UDS";
const char *CitadelServiceTCP="citadel-TCP";
+
+
+
void go_threading(void);
/*
The type bytes currently defined are:
-BYTE Mnemonic Enum / Comments
-
-A Author eAuthor
- Name of originator of message.
-B Big message eBig_message
- This is a flag which indicates that the message is
- big, and Citadel is storing the body in a separate
- record. You will never see this field because the
- internal API handles it.
-C RemoteRoom eRemoteRoom
- when sent via Citadel Networking, this is the room
- its going to be put on the remote site.
-D Destination eDestination
- Contains name of the system this message should
- be sent to, for mail routing (private mail only).
-E Exclusive ID eExclusiveID
- A persistent alphanumeric Message ID used for
- network replication. When a message arrives that
- contains an Exclusive ID, any existing messages which
- contain the same Exclusive ID and are *older* than this
- message should be deleted. If there exist any messages
- with the same Exclusive ID that are *newer*, then this
- message should be dropped.
-F rFc822 address erFc822Addr
- For Internet mail, this is the delivery address of the
- message author.
-H Human node name eHumanNode
- Human-readable name of system message originated on.
-I Message ID emessageId
- An RFC822-compatible message ID for this message.
-J Journal eJournal
- The presence of this field indicates that the message
- is disqualified from being journaled, perhaps because
- it is itself a journalized message and we wish to
- avoid double journaling.
-K Reply-To eReplyTo
- the Reply-To header for mailinglist outbound messages
-L List-ID eListID
- Mailing list identification, as per RFC 2919
-M Message Text eMesageText
- Normal ASCII, newlines seperated by CR's or LF's,
- null terminated as always.
-N Nodename eNodeName
- Contains node name of system message originated on.
-O Room eOriginalRoom - Room of origin.
-P Path eMessagePath
- Complete path of message, as in the UseNet news
- standard. A user should be able to send Internet mail
- to this path. (Note that your system name will not be
- tacked onto this until you're sending the message to
- someone else)
-R Recipient eRecipient - Only present in Mail messages.
-S Special field eSpecialField
- Only meaningful for messages being spooled over a
- network. Usually means that the message isn't really
- a message, but rather some other network function:
- -> "S" followed by "FILE" (followed by a null, of
- course) means that the message text is actually an
- IGnet/Open file transfer. (OBSOLETE)
- -> "S" followed by "CANCEL" means that this message
- should be deleted from the local message base once
- it has been replicated to all network systems.
-T date/Time eTimestamp
- Unix timestamp containing the creation date/time of
- the message.
-U sUbject eMsgSubject - Optional.
- Developers may choose whether they wish to
- generate or display subject fields.
-V enVelope-to eenVelopeTo
- The recipient specified in incoming SMTP messages.
-W Wefewences eWeferences
- Previous message ID's for conversation threading. When
- converting from RFC822 we use References: if present, or
- In-Reply-To: otherwise.
- (Who in extnotify spool messages which don't need to know
- other message ids)
-Y carbon copY eCarbonCopY
- Optional, and only in Mail messages.
-0 Error eErrorMsg
- This field is typically never found in a message on
- disk or in transit. Message scanning modules are
- expected to fill in this field when rejecting a message
- with an explanation as to what happened (virus found,
- message looks like spam, etc.)
-1 suppress index eSuppressIdx
- The presence of this field indicates that the message is
- disqualified from being added to the full text index.
-2 extnotify eExtnotify - Used internally by the serv_extnotify module.
-3 msgnum eVltMsgNum
- Used internally to pass the local message number in the
- database to after-save hooks. Discarded afterwards.
+BYTE Enum Mnemonic Enum / Comments
+
+A eAuthor Author eAuthor
+ Name of originator of message.
+B eBig_message Big message eBig_message
+ This is a flag which indicates that the message is
+ big, and Citadel is storing the body in a separate
+ record. You will never see this field because the
+ internal API handles it.
+C eRemoteRoom RemoteRoom eRemoteRoom
+ when sent via Citadel Networking, this is the room
+ its going to be put on the remote site.
+D eDestination Destination eDestination
+ Contains name of the system this message should
+ be sent to, for mail routing (private mail only).
+E eExclusiveID Exclusive ID eExclusiveID
+ A persistent alphanumeric Message ID used for
+ network replication. When a message arrives that
+ contains an Exclusive ID, any existing messages which
+ contain the same Exclusive ID and are *older* than this
+ message should be deleted. If there exist any messages
+ with the same Exclusive ID that are *newer*, then this
+ message should be dropped.
+F erFc822Addr rFc822 address erFc822Addr
+ For Internet mail, this is the delivery address of the
+ message author.
+H eHumanNode Human node name eHumanNode
+ Human-readable name of system message originated on.
+I emessageId Message ID emessageId
+ An RFC822-compatible message ID for this message.
+J eJournal Journal eJournal
+ The presence of this field indicates that the message
+ is disqualified from being journaled, perhaps because
+ it is itself a journalized message and we wish to
+ avoid double journaling.
+K eReplyTo Reply-To eReplyTo
+ the Reply-To header for mailinglist outbound messages
+L eListID List-ID eListID
+ Mailing list identification, as per RFC 2919
+M eMesageText Message Text eMesageText
+ Normal ASCII, newlines seperated by CR's or LF's,
+ null terminated as always.
+N eNodeName Nodename eNodeName
+ Contains node name of system message originated on.
+O eOriginalRoom Room eOriginalRoom - Room of origin.
+P eMessagePath Path eMessagePath
+ Complete path of message, as in the UseNet news
+ standard. A user should be able to send Internet mail
+ to this path. (Note that your system name will not be
+ tacked onto this until you're sending the message to
+ someone else)
+R eRecipient Recipient eRecipient - Only present in Mail messages.
+S eSpecialField Special field eSpecialField
+ Only meaningful for messages being spooled over a
+ network. Usually means that the message isn't really
+ a message, but rather some other network function:
+ -> "S" followed by "FILE" (followed by a null, of
+ course) means that the message text is actually an
+ IGnet/Open file transfer. (OBSOLETE)
+ -> "S" followed by "CANCEL" means that this message
+ should be deleted from the local message base once
+ it has been replicated to all network systems.
+T eTimestamp date/Time eTimestamp
+ Unix timestamp containing the creation date/time of
+ the message.
+U eMsgSubject sUbject eMsgSubject - Optional.
+ Developers may choose whether they wish to
+ generate or display subject fields.
+V eenVelopeTo enVelope-to eenVelopeTo
+ The recipient specified in incoming SMTP messages.
+W eWeferences Wefewences eWeferences
+ Previous message ID's for conversation threading. When
+ converting from RFC822 we use References: if present, or
+ In-Reply-To: otherwise.
+ (Who in extnotify spool messages which don't need to know
+ other message ids)
+Y eCarbonCopY carbon copY eCarbonCopY
+ Optional, and only in Mail messages.
+0 eErrorMsg Error eErrorMsg
+ This field is typically never found in a message on
+ disk or in transit. Message scanning modules are
+ expected to fill in this field when rejecting a message
+ with an explanation as to what happened (virus found,
+ message looks like spam, etc.)
+1 eSuppressIdx suppress index eSuppressIdx
+ The presence of this field indicates that the message is
+ disqualified from being added to the full text index.
+2 eExtnotify extnotify eExtnotify - Used internally by the serv_extnotify module.
+3 eVltMsgNum msgnum eVltMsgNum
+ Used internally to pass the local message number in the
+ database to after-save hooks. Discarded afterwards.
EXAMPLE
"(example: ctdl.foo.org)\n"
"--> ");
getz(remote_host);
+
+get_remote_user:
printf("\nEnter the name of a user on %s who has full access to Citadel files\n"
"(usually root)\n--> ",
remote_host);
getz(remote_user);
+ if (IsEmptyStr(remote_user))
+ goto get_remote_user;
printf("\nEstablishing an SSH connection to the source system...\n\n");
unlink(socket_path);
}
printf("ctdlmigrate will now begin a database migration...\n");
+ printf(" if the system doesn't start working, \n");
+ printf(" have a look at the syslog for pending jobs needing to be terminated.\n");
snprintf(cmd, sizeof cmd, "ssh -S %s %s@%s %s -w3600 MIGR export",
socket_path, remote_user, remote_host, remote_sendcommand);
activity = _("Setting file permissions");
progress(activity, 0, 2);
+ //chown(file_citadel_config, config.c_ctdluid, gid);
progress(activity, 1, 2);
chmod(file_citadel_config, S_IRUSR | S_IWUSR);
progress(activity, 2, 2);
return -1;
if (BufOut->BufSize < BufIn->BufUsed)
- IncreaseBuf(BufOut, BufIn->BufUsed, 0);
+ IncreaseBuf(BufOut, 0, BufIn->BufUsed);
BufOut->BufUsed = CtdlDecodeBase64(BufOut->buf,
BufIn->buf,
/* Server isn't ready for us? */
if (short_status != 2) {
- if (Status == 571) {
+ if (Status == 551) {
hprintf("HTTP/1.1 503 Service Unavailable\r\n");
hprintf("Content-type: text/plain; charset=utf-8\r\n");
wc_printf(_("This server is already serving its maximum number of users and cannot accept any additional logins at this time. Please try again later or contact your system administrator."));