+static const long NDiskFields = sizeof(FieldOrder) / sizeof(eMsgField);
+
+int CM_IsEmpty(struct CtdlMessage *Msg, eMsgField which)
+{
+ return !((Msg->cm_fields[which] != NULL) &&
+ (Msg->cm_fields[which][0] != '\0'));
+}
+
+void CM_SetField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+ Msg->cm_fields[which] = malloc(length + 1);
+ memcpy(Msg->cm_fields[which], buf, length);
+ Msg->cm_fields[which][length] = '\0';
+}
+
+void CM_SetFieldLONG(struct CtdlMessage *Msg, eMsgField which, long lvalue)
+{
+ char buf[128];
+ long len;
+ len = snprintf(buf, sizeof(buf), "%ld", lvalue);
+ CM_SetField(Msg, which, buf, len);
+}
+void CM_CutFieldAt(struct CtdlMessage *Msg, eMsgField WhichToCut, long maxlen)
+{
+ if (Msg->cm_fields[WhichToCut] == NULL)
+ return;
+
+ if (strlen(Msg->cm_fields[WhichToCut]) > maxlen)
+ Msg->cm_fields[WhichToCut][maxlen] = '\0';
+}
+
+void CM_FlushField(struct CtdlMessage *Msg, eMsgField which)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+ Msg->cm_fields[which] = NULL;
+}
+
+void CM_CopyField(struct CtdlMessage *Msg, eMsgField WhichToPutTo, eMsgField WhichtToCopy)
+{
+ long len;
+ if (Msg->cm_fields[WhichToPutTo] != NULL)
+ free (Msg->cm_fields[WhichToPutTo]);
+
+ if (Msg->cm_fields[WhichtToCopy] != NULL)
+ {
+ len = strlen(Msg->cm_fields[WhichtToCopy]);
+ Msg->cm_fields[WhichToPutTo] = malloc(len + 1);
+ memcpy(Msg->cm_fields[WhichToPutTo], Msg->cm_fields[WhichToPutTo], len);
+ Msg->cm_fields[WhichToPutTo][len] = '\0';
+ }
+ else
+ Msg->cm_fields[WhichToPutTo] = NULL;
+}
+
+
+void CM_PrependToField(struct CtdlMessage *Msg, eMsgField which, const char *buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL) {
+ long oldmsgsize;
+ long newmsgsize;
+ char *new;
+
+ oldmsgsize = strlen(Msg->cm_fields[which]) + 1;
+ newmsgsize = length + oldmsgsize;
+
+ new = malloc(newmsgsize);
+ memcpy(new, buf, length);
+ memcpy(new + length, Msg->cm_fields[which], oldmsgsize);
+ free(Msg->cm_fields[which]);
+ Msg->cm_fields[which] = new;
+ }
+ else {
+ Msg->cm_fields[which] = malloc(length + 1);
+ memcpy(Msg->cm_fields[which], buf, length);
+ Msg->cm_fields[which][length] = '\0';
+ }
+}
+
+void CM_SetAsField(struct CtdlMessage *Msg, eMsgField which, char **buf, long length)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+
+ Msg->cm_fields[which] = *buf;
+ *buf = NULL;
+}
+
+void CM_SetAsFieldSB(struct CtdlMessage *Msg, eMsgField which, StrBuf **buf)
+{
+ if (Msg->cm_fields[which] != NULL)
+ free (Msg->cm_fields[which]);
+
+ Msg->cm_fields[which] = SmashStrBuf(buf);
+}
+
+void CM_GetAsField(struct CtdlMessage *Msg, eMsgField which, char **ret, long *retlen)
+{
+ if (Msg->cm_fields[which] != NULL)
+ {
+ *retlen = strlen(Msg->cm_fields[which]);
+ *ret = Msg->cm_fields[which];
+ Msg->cm_fields[which] = NULL;
+ }
+ else
+ {
+ *ret = NULL;
+ *retlen = 0;
+ }
+}
+
+/*
+ * Returns 1 if the supplied pointer points to a valid Citadel message.
+ * If the pointer is NULL or the magic number check fails, returns 0.
+ */
+int is_valid_message(struct CtdlMessage *msg) {
+ if (msg == NULL)
+ return 0;
+ if ((msg->cm_magic) != CTDLMESSAGE_MAGIC) {
+ struct CitContext *CCC = CC;
+ MSGM_syslog(LOG_WARNING, "is_valid_message() -- self-check failed\n");
+ return 0;
+ }
+ return 1;
+}
+
+void CtdlFreeMessageContents(struct CtdlMessage *msg)
+{
+ int i;
+
+ for (i = 0; i < 256; ++i)
+ if (msg->cm_fields[i] != NULL) {
+ free(msg->cm_fields[i]);
+ }
+
+ msg->cm_magic = 0; /* just in case */
+}
+/*
+ * 'Destructor' for struct CtdlMessage
+ */
+void CtdlFreeMessage(struct CtdlMessage *msg)
+{
+ if (is_valid_message(msg) == 0)
+ {
+ if (msg != NULL) free (msg);
+ return;
+ }
+ CtdlFreeMessageContents(msg);
+ free(msg);
+}
+
+int DupCMField(eMsgField i, struct CtdlMessage *OrgMsg, struct CtdlMessage *NewMsg)
+{
+ long len;
+ len = strlen(OrgMsg->cm_fields[i]);
+ NewMsg->cm_fields[i] = malloc(len + 1);
+ if (NewMsg->cm_fields[i] == NULL)
+ return 0;
+ memcpy(NewMsg->cm_fields[i], OrgMsg->cm_fields[i], len);
+ NewMsg->cm_fields[i][len] = '\0';
+ return 1;
+}
+
+struct CtdlMessage * CtdlDuplicateMessage(struct CtdlMessage *OrgMsg)
+{
+ int i;
+ struct CtdlMessage *NewMsg;
+
+ if (is_valid_message(OrgMsg) == 0)
+ return NULL;
+ NewMsg = (struct CtdlMessage *)malloc(sizeof(struct CtdlMessage));
+ if (NewMsg == NULL)
+ return NULL;
+
+ memcpy(NewMsg, OrgMsg, sizeof(struct CtdlMessage));
+
+ memset(&NewMsg->cm_fields, 0, sizeof(char*) * 256);
+
+ for (i = 0; i < 256; ++i)
+ {
+ if (OrgMsg->cm_fields[i] != NULL)
+ {
+ if (!DupCMField(i, OrgMsg, NewMsg))
+ {
+ CtdlFreeMessage(NewMsg);
+ return NULL;
+ }
+ }
+ }
+
+ return NewMsg;
+}
+
+
+