#include <sys/stat.h>
#include "citadel.h"
#include "server.h"
-#include "dynloader.h"
+#include "serv_extensions.h"
#include "database.h"
#include "msgbase.h"
#include "support.h"
struct visit vbuf;
/* Learn about the user and room in question */
- CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
safestrncpy(buf, vbuf.v_seen, SIZ);
}
int num_msgs = 0;
/* Learn about the user and room in question */
- CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
/* Load the message list */
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->quickroom.QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
if (cdbfr != NULL) {
msglist = mallok(cdbfr->len);
memcpy(msglist, cdbfr->ptr, cdbfr->len);
safestrncpy(vbuf.v_seen, newseen, SIZ);
lprintf(9, " after optimize: %s\n", vbuf.v_seen);
phree(msglist);
- CtdlSetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ CtdlSetRelationship(&vbuf, &CC->user, &CC->room);
}
/* Learn about the user and room in question */
get_mm();
- getuser(&CC->usersupp, CC->curr_user);
- CtdlGetRelationship(&vbuf, &CC->usersupp, &CC->quickroom);
+ getuser(&CC->user, CC->curr_user);
+ CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
/* Load the message list */
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->quickroom.QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
if (cdbfr != NULL) {
msglist = mallok(cdbfr->len);
memcpy(msglist, cdbfr->ptr, cdbfr->len);
|| ((mode == MSGS_EQ) && (thismsg == ref))
)
) {
- if ((mode == MSGS_NEW) && (CC->usersupp.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) {
+ if ((mode == MSGS_NEW) && (CC->user.flags & US_LASTOLD) && (lastold > 0L) && (printed_lastold == 0) && (!is_seen)) {
if (CallBack)
CallBack(lastold, userdata);
printed_lastold = 1;
help_subst(buffer, "^nodename", config.c_nodename);
help_subst(buffer, "^humannode", config.c_humannode);
help_subst(buffer, "^fqdn", config.c_fqdn);
- help_subst(buffer, "^username", CC->usersupp.fullname);
- snprintf(buf2, sizeof buf2, "%ld", CC->usersupp.usernum);
+ help_subst(buffer, "^username", CC->user.fullname);
+ snprintf(buf2, sizeof buf2, "%ld", CC->user.usernum);
help_subst(buffer, "^usernum", buf2);
help_subst(buffer, "^sysadm", config.c_sysadm);
help_subst(buffer, "^variantname", CITADEL);
snprintf(buf2, sizeof buf2, "%d", config.c_maxsessions);
help_subst(buffer, "^maxsessions", buf2);
+ help_subst(buffer, "^bbsdir", BBSDIR);
}
int a, b, c;
int real = 0;
int old = 0;
- CIT_UBYTE ch;
+ cit_uint8_t ch;
char aaa[140];
char buffer[SIZ];
struct cdbdata *dmsgtext;
struct CtdlMessage *ret = NULL;
char *mptr;
- CIT_UBYTE ch;
- CIT_UBYTE field_header;
+ cit_uint8_t ch;
+ cit_uint8_t field_header;
size_t field_length;
dmsgtext = cdb_fetch(CDB_MSGMAIN, &msgnum, sizeof(long));
cprintf("Content-type: %s\n", cbtype);
cprintf("Content-length: %d\n",
- length + add_newline);
- cprintf("Content-transfer-encoding: %s\n", encoding);
+ (int)(length + add_newline) );
+ if (strlen(encoding) > 0) {
+ cprintf("Content-transfer-encoding: %s\n", encoding);
+ }
+ else {
+ cprintf("Content-transfer-encoding: 7bit\n");
+ }
cprintf("\n");
client_write(content, length);
if (add_newline) cprintf("\n");
) {
int i, k;
char buf[1024];
- CIT_UBYTE ch;
+ cit_uint8_t ch;
char allkeys[SIZ];
char display_name[SIZ];
char *mptr;
char *nl; /* newline string */
int suppress_f = 0;
+ int subject_found = 0;
/* buffers needed for RFC822 translation */
char suser[SIZ];
return((CC->download_fp != NULL) ? om_ok : om_mime_error);
}
- /* Does the caller want to skip the headers? */
- if (headers_only == HEADERS_NONE) goto START_TEXT;
-
/* now for the user-mode message reading loops */
if (do_proto) cprintf("%d Message %ld:\n", LISTING_FOLLOWS, msg_num);
+ /* Does the caller want to skip the headers? */
+ if (headers_only == HEADERS_NONE) goto START_TEXT;
+
/* Tell the client which format type we're using. */
if ( (mode == MT_CITADEL) && (do_proto) ) {
cprintf("type=%d\n", TheMessage->cm_format_type);
cprintf("Path: %s%s", mptr, nl);
}
****/
- else if (i == 'U')
+ else if (i == 'U') {
cprintf("Subject: %s%s", mptr, nl);
+ subject_found = 1;
+ }
else if (i == 'I')
safestrncpy(mid, mptr, sizeof mid);
else if (i == 'H')
}
}
}
+ if (subject_found == 0) {
+ cprintf("Subject: (no subject)%s", nl);
+ }
}
for (i=0; i<strlen(suser); ++i) {
}
cprintf("Organization: %s%s", lnode, nl);
+
+ /* Blank line signifying RFC822 end-of-headers */
+ if (TheMessage->cm_format_type != FMT_RFC822) {
+ cprintf("%s", nl);
+ }
}
/* end header processing loop ... at this point, we're in the text */
* Citadel and RFC822 headers exist. Preference should
* probably be given to the RFC822 headers.
*/
+ int done_rfc822_hdrs = 0;
while (ch=*(mptr++), ch!=0) {
- if (ch==13) ;
- else if (ch==10) cprintf("%s", nl);
- else cprintf("%c", ch);
+ if (ch==13) {
+ /* do nothing */
+ }
+ else if (ch==10) {
+ if (!done_rfc822_hdrs) {
+ if (headers_only != HEADERS_NONE) {
+ cprintf("%s", nl);
+ }
+ }
+ else {
+ if (headers_only != HEADERS_ONLY) {
+ cprintf("%s", nl);
+ }
+ }
+ if ((*(mptr) == 13) || (*(mptr) == 10)) {
+ done_rfc822_hdrs = 1;
+ }
+ }
+ else {
+ if (done_rfc822_hdrs) {
+ if (headers_only != HEADERS_NONE) {
+ cprintf("%c", ch);
+ }
+ }
+ else {
+ if (headers_only != HEADERS_ONLY) {
+ cprintf("%c", ch);
+ }
+ }
+ if ((*mptr == 13) || (*mptr == 10)) {
+ done_rfc822_hdrs = 1;
+ }
+ }
}
- if (do_proto) cprintf("000\n");
- return(om_ok);
+ goto DONE;
}
}
if (headers_only == HEADERS_ONLY) {
- if (do_proto) cprintf("000\n");
- return(om_ok);
+ goto DONE;
}
/* signify start of msg text */
if ( (mode == MT_CITADEL) || (mode == MT_MIME) ) {
if (do_proto) cprintf("text\n");
}
- if (mode == MT_RFC822) {
- if (TheMessage->cm_fields['U'] == NULL) {
- cprintf("Subject: (no subject)%s", nl);
- }
- cprintf("%s", nl);
- }
/* If the format type on disk is 1 (fixed-format), then we want
* everything to be output completely literally ... regardless of
}
}
- /* now we're done */
+DONE: /* now we're done */
if (do_proto) cprintf("000\n");
return(om_ok);
}
lprintf(9, "CtdlSaveMsgPointerInRoom(%s, %ld, %d)\n",
roomname, msgid, flags);
- strcpy(hold_rm, CC->quickroom.QRname);
+ strcpy(hold_rm, CC->room.QRname);
/* We may need to check to see if this message is real */
if ( (flags & SM_VERIFY_GOODNESS)
/* Perform replication checks if necessary */
if ( (flags & SM_DO_REPL_CHECK) && (msg != NULL) ) {
- if (getroom(&CC->quickroom,
- ((roomname != NULL) ? roomname : CC->quickroom.QRname) )
+ if (getroom(&CC->room,
+ ((roomname != NULL) ? roomname : CC->room.QRname) )
!= 0) {
lprintf(9, "No such room <%s>\n", roomname);
if (msg != NULL) CtdlFreeMessage(msg);
}
if (ReplicationChecks(msg) != 0) {
- getroom(&CC->quickroom, hold_rm);
+ getroom(&CC->room, hold_rm);
if (msg != NULL) CtdlFreeMessage(msg);
lprintf(9, "Did replication, and newer exists\n");
return(0);
}
/* Now the regular stuff */
- if (lgetroom(&CC->quickroom,
- ((roomname != NULL) ? roomname : CC->quickroom.QRname) )
+ if (lgetroom(&CC->room,
+ ((roomname != NULL) ? roomname : CC->room.QRname) )
!= 0) {
lprintf(9, "No such room <%s>\n", roomname);
if (msg != NULL) CtdlFreeMessage(msg);
return(ERROR + ROOM_NOT_FOUND);
}
- cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->quickroom.QRnumber, sizeof(long));
+ cdbfr = cdb_fetch(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long));
if (cdbfr == NULL) {
msglist = NULL;
num_msgs = 0;
*/
if (num_msgs > 0) for (i=0; i<num_msgs; ++i) {
if (msglist[i] == msgid) {
- lputroom(&CC->quickroom); /* unlock the room */
- getroom(&CC->quickroom, hold_rm);
+ lputroom(&CC->room); /* unlock the room */
+ getroom(&CC->room, hold_rm);
if (msg != NULL) CtdlFreeMessage(msg);
return(ERROR + ALREADY_EXISTS);
}
highest_msg = msglist[num_msgs - 1];
/* Write it back to disk. */
- cdb_store(CDB_MSGLISTS, &CC->quickroom.QRnumber, sizeof(long),
+ cdb_store(CDB_MSGLISTS, &CC->room.QRnumber, sizeof(long),
msglist, num_msgs * sizeof(long));
/* Free up the memory we used. */
phree(msglist);
/* Update the highest-message pointer and unlock the room. */
- CC->quickroom.QRhighest = highest_msg;
- lputroom(&CC->quickroom);
- getroom(&CC->quickroom, hold_rm);
+ CC->room.QRhighest = highest_msg;
+ lputroom(&CC->room);
+ getroom(&CC->room, hold_rm);
/* Bump the reference count for this message. */
if ((flags & SM_DONT_BUMP_REF)==0) {
lprintf(9, "older!\n");
/* Existing isn't newer? Then delete the old one(s). */
- CtdlDeleteMessages(CC->quickroom.QRname, msgnum, "");
+ CtdlDeleteMessages(CC->room.QRname, msgnum, "");
}
char recipient[SIZ];
long newmsgid;
char *mptr = NULL;
- struct usersupp userbuf;
+ struct user userbuf;
int a, i;
struct MetaData smi;
FILE *network_fp = NULL;
/* Goto the correct room */
lprintf(9, "Switching rooms\n");
- strcpy(hold_rm, CC->quickroom.QRname);
- strcpy(actual_rm, CC->quickroom.QRname);
+ strcpy(hold_rm, CC->room.QRname);
+ strcpy(actual_rm, CC->room.QRname);
if (recps != NULL) {
strcpy(actual_rm, SENTITEMS);
}
/* If the user is a twit, move to the twit room for posting */
lprintf(9, "Handling twit stuff\n");
if (TWITDETECT) {
- if (CC->usersupp.axlevel == 2) {
+ if (CC->user.axlevel == 2) {
strcpy(hold_rm, actual_rm);
strcpy(actual_rm, config.c_twitroom);
}
}
lprintf(9, "Possibly relocating\n");
- if (strcasecmp(actual_rm, CC->quickroom.QRname)) {
- getroom(&CC->quickroom, actual_rm);
+ if (strcasecmp(actual_rm, CC->room.QRname)) {
+ getroom(&CC->room, actual_rm);
}
/*
* If this message has no O (room) field, generate one.
*/
if (msg->cm_fields['O'] == NULL) {
- msg->cm_fields['O'] = strdoop(CC->quickroom.QRname);
+ msg->cm_fields['O'] = strdoop(CC->room.QRname);
}
/* Perform "before save" hooks (aborting if any return nonzero) */
/* Bump this user's messages posted counter. */
lprintf(9, "Updating user\n");
- lgetuser(&CC->usersupp, CC->curr_user);
- CC->usersupp.posted = CC->usersupp.posted + 1;
- lputuser(&CC->usersupp);
+ lgetuser(&CC->user, CC->curr_user);
+ CC->user.posted = CC->user.posted + 1;
+ lputuser(&CC->user);
/* If this is private, local mail, make a copy in the
* recipient's mailbox and bump the reference count.
/* Go back to the room we started from */
lprintf(9, "Returning to original room\n");
- if (strcasecmp(hold_rm, CC->quickroom.QRname))
- getroom(&CC->quickroom, hold_rm);
+ if (strcasecmp(hold_rm, CC->room.QRname))
+ getroom(&CC->room, hold_rm);
/* For internet mail, generate delivery instructions.
* Yes, this is recursive. Deal with it. Infinite recursion does
/*
- * Back end function used by make_message() and similar functions
+ * Back end function used by CtdlMakeMessage() and similar functions
*/
char *CtdlReadMessageBody(char *terminator, /* token signalling EOT */
size_t maxlen, /* maximum message length */
- char *exist /* if non-null, append to it;
+ char *exist, /* if non-null, append to it;
exist is ALWAYS freed */
+ int crlf /* CRLF newlines instead of LF */
) {
char buf[SIZ];
int linelen;
size_t buffer_len = 0;
char *ptr;
char *m;
+ int flushing = 0;
+ int finished = 0;
if (exist == NULL) {
m = mallok(4096);
/* flush the input if we have nowhere to store it */
if (m == NULL) {
- while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) ;;
- return(NULL);
+ flushing = 1;
}
/* read in the lines of message text one by one */
- while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) {
-
- /* Measure the line and strip trailing newline characters */
- linelen = strlen(buf);
- if (linelen > 0) if (buf[linelen-1]==13) buf[linelen--]=0;
- if (linelen > 0) if (buf[linelen-1]==10) buf[linelen--]=0;
-
- /* augment the buffer if we have to */
- if ((message_len + linelen + 2) > buffer_len) {
- lprintf(9, "realloking\n");
- ptr = reallok(m, (buffer_len * 2) );
- if (ptr == NULL) { /* flush if can't allocate */
- while ( (client_gets(buf)>0) &&
- strcmp(buf, terminator)) ;;
- return(m);
- } else {
- buffer_len = (buffer_len * 2);
- m = ptr;
- lprintf(9, "buffer_len is %ld\n", (long)buffer_len);
- }
+ do {
+ if (client_gets(buf) < 1) finished = 1;
+ if (!strcmp(buf, terminator)) finished = 1;
+ if (crlf) {
+ strcat(buf, "\r\n");
+ }
+ else {
+ strcat(buf, "\n");
}
- /* Add the new line to the buffer. NOTE: this loop must avoid
- * using functions like strcat() and strlen() because they
- * traverse the entire buffer upon every call, and doing that
- * for a multi-megabyte message slows it down beyond usability.
- */
- strcpy(&m[message_len], buf);
- m[message_len + linelen] = '\n';
- m[message_len + linelen + 1] = 0;
- message_len = message_len + linelen + 1;
+ if ( (!flushing) && (!finished) ) {
+ /* Measure the line */
+ linelen = strlen(buf);
+
+ /* augment the buffer if we have to */
+ if ((message_len + linelen) >= buffer_len) {
+ ptr = reallok(m, (buffer_len * 2) );
+ if (ptr == NULL) { /* flush if can't allocate */
+ flushing = 1;
+ } else {
+ buffer_len = (buffer_len * 2);
+ m = ptr;
+ lprintf(9, "buffer_len is now %ld\n", (long)buffer_len);
+ }
+ }
+
+ /* Add the new line to the buffer. NOTE: this loop must avoid
+ * using functions like strcat() and strlen() because they
+ * traverse the entire buffer upon every call, and doing that
+ * for a multi-megabyte message slows it down beyond usability.
+ */
+ strcpy(&m[message_len], buf);
+ message_len += linelen;
+ }
/* if we've hit the max msg length, flush the rest */
- if (message_len >= maxlen) {
- while ( (client_gets(buf)>0)
- && strcmp(buf, terminator)) ;;
- return(m);
- }
- }
+ if (message_len >= maxlen) flushing = 1;
+
+ } while (!finished);
return(m);
}
/*
* Build a binary message to be saved on disk.
+ * (NOTE: if you supply 'preformatted_text', the buffer you give it
+ * will become part of the message. This means you are no longer
+ * responsible for managing that memory -- it will be freed along with
+ * the rest of the fields when CtdlFreeMessage() is called.)
*/
-static struct CtdlMessage *make_message(
- struct usersupp *author, /* author's usersupp structure */
+struct CtdlMessage *CtdlMakeMessage(
+ struct user *author, /* author's user structure */
char *recipient, /* NULL if it's not mail */
char *room, /* room where it's going */
int type, /* see MES_ types in header file */
int format_type, /* variformat, plain text, MIME... */
char *fake_name, /* who we're masquerading as */
- char *subject /* Subject (optional) */
+ char *subject, /* Subject (optional) */
+ char *preformatted_text /* ...or NULL to read text from client */
) {
char dest_node[SIZ];
char buf[SIZ];
else
msg->cm_fields['A'] = strdoop(author->fullname);
- if (CC->quickroom.QRflags & QR_MAILBOX) { /* room */
- msg->cm_fields['O'] = strdoop(&CC->quickroom.QRname[11]);
+ if (CC->room.QRflags & QR_MAILBOX) { /* room */
+ msg->cm_fields['O'] = strdoop(&CC->room.QRname[11]);
}
else {
- msg->cm_fields['O'] = strdoop(CC->quickroom.QRname);
+ msg->cm_fields['O'] = strdoop(CC->room.QRname);
}
msg->cm_fields['N'] = strdoop(NODENAME); /* nodename */
msg->cm_fields['D'] = strdoop(dest_node);
}
- if ( (author == &CC->usersupp) && (CC->cs_inet_email != NULL) ) {
+ if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) {
msg->cm_fields['F'] = strdoop(CC->cs_inet_email);
}
}
}
- msg->cm_fields['M'] = CtdlReadMessageBody("000",
- config.c_maxmsglen, NULL);
+ if (preformatted_text != NULL) {
+ msg->cm_fields['M'] = preformatted_text;
+ }
+ else {
+ msg->cm_fields['M'] = CtdlReadMessageBody("000",
+ config.c_maxmsglen, NULL, 0);
+ }
return(msg);
}
return (ERROR + NOT_LOGGED_IN);
}
- if ((CC->usersupp.axlevel < 2)
- && ((CC->quickroom.QRflags & QR_MAILBOX) == 0)) {
+ if ((CC->user.axlevel < 2)
+ && ((CC->room.QRflags & QR_MAILBOX) == 0)) {
snprintf(errmsgbuf, n, "Need to be validated to enter "
"(except in %s> to sysop)", MAILROOM);
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
- if ((CC->usersupp.axlevel < 4)
- && (CC->quickroom.QRflags & QR_NETWORK)) {
+ if ((CC->user.axlevel < 4)
+ && (CC->room.QRflags & QR_NETWORK)) {
snprintf(errmsgbuf, n, "Need net privileges to enter here.");
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
- if ((CC->usersupp.axlevel < 6)
- && (CC->quickroom.QRflags & QR_READONLY)) {
+ if ((CC->user.axlevel < 6)
+ && (CC->room.QRflags & QR_READONLY)) {
snprintf(errmsgbuf, n, "Sorry, this is a read-only room.");
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
}
+/*
+ * Check to see if the specified user has Internet mail permission
+ * (returns nonzero if permission is granted)
+ */
+int CtdlCheckInternetMailPermission(struct user *who) {
+
+ /* Globally enabled? */
+ if (config.c_restrict == 0) return(1);
+
+ /* User flagged ok? */
+ if (who->flags & US_INTERNET) return(2);
+
+ /* Aide level access? */
+ if (who->axlevel >= 6) return(3);
+
+ /* No mail for you! */
+ return(0);
+}
+
+
+
/*
* Validate recipients, count delivery types and errors, and handle aliasing
* FIXME check for dupes!!!!!
int i, j;
int mailtype;
int invalid;
- struct usersupp tempUS;
- struct quickroom tempQR;
+ struct user tempUS;
+ struct room tempQR;
/* Initialize */
ret = (struct recptypes *) malloc(sizeof(struct recptypes));
}
break;
case MES_INTERNET:
- ++ret->num_internet;
- if (strlen(ret->recp_internet) > 0) {
- strcat(ret->recp_internet, "|");
+ /* Yes, you're reading this correctly: if the target
+ * domain points back to the local system or an attached
+ * Citadel directory, the address is invalid. That's
+ * because if the address were valid, we would have
+ * already translated it to a local address by now.
+ */
+ if (IsDirectory(this_recp)) {
+ ++ret->num_error;
+ invalid = 1;
+ }
+ else {
+ ++ret->num_internet;
+ if (strlen(ret->recp_internet) > 0) {
+ strcat(ret->recp_internet, "|");
+ }
+ strcat(ret->recp_internet, this_recp);
}
- strcat(ret->recp_internet, this_recp);
break;
case MES_IGNET:
++ret->num_ignet;
/* Check some other permission type things. */
if (post == 2) {
- if (CC->usersupp.axlevel < 6) {
+ if (CC->user.axlevel < 6) {
cprintf("%d You don't have permission to masquerade.\n",
ERROR + HIGHER_ACCESS_REQUIRED);
return;
}
- extract(newusername, entargs, 4);
+ extract(newusername, entargs, 5);
memset(CC->fake_postname, 0, sizeof(CC->fake_postname) );
safestrncpy(CC->fake_postname, newusername,
sizeof(CC->fake_postname) );
* make sure the user has specified at least one recipient. Then
* validate the recipient(s).
*/
- if ( (CC->quickroom.QRflags & QR_MAILBOX)
- && (!strcasecmp(&CC->quickroom.QRname[11], MAILROOM)) ) {
+ if ( (CC->room.QRflags & QR_MAILBOX)
+ && (!strcasecmp(&CC->room.QRname[11], MAILROOM)) ) {
- if (CC->usersupp.axlevel < 2) {
+ if (CC->user.axlevel < 2) {
strcpy(recp, "sysop");
}
phree(valid);
return;
}
+ if (valid->num_internet > 0) {
+ if (CtdlCheckInternetMailPermission(&CC->user)==0) {
+ cprintf("%d You do not have permission "
+ "to send Internet mail.\n",
+ ERROR + HIGHER_ACCESS_REQUIRED);
+ phree(valid);
+ return;
+ }
+ }
if ( ( (valid->num_internet + valid->num_ignet) > 0)
- && (CC->usersupp.axlevel < 4) ) {
+ && (CC->user.axlevel < 4) ) {
cprintf("%d Higher access required for network mail.\n",
ERROR + HIGHER_ACCESS_REQUIRED);
phree(valid);
}
if ((RESTRICT_INTERNET == 1) && (valid->num_internet > 0)
- && ((CC->usersupp.flags & US_INTERNET) == 0)
+ && ((CC->user.flags & US_INTERNET) == 0)
&& (!CC->internal_pgm)) {
cprintf("%d You don't have access to Internet mail.\n",
ERROR + HIGHER_ACCESS_REQUIRED);
/* Is this a room which has anonymous-only or anonymous-option? */
anonymous = MES_NORMAL;
- if (CC->quickroom.QRflags & QR_ANONONLY) {
+ if (CC->room.QRflags & QR_ANONONLY) {
anonymous = MES_ANONONLY;
}
- if (CC->quickroom.QRflags & QR_ANONOPT) {
+ if (CC->room.QRflags & QR_ANONOPT) {
if (anon_flag == 1) { /* only if the user requested it */
anonymous = MES_ANONOPT;
}
}
- if ((CC->quickroom.QRflags & QR_MAILBOX) == 0) {
+ if ((CC->room.QRflags & QR_MAILBOX) == 0) {
recp[0] = 0;
}
/* Read in the message from the client. */
cprintf("%d send message\n", SEND_LISTING);
- msg = make_message(&CC->usersupp, recp,
- CC->quickroom.QRname, anonymous, format_type,
- masquerade_as, subject);
+ msg = CtdlMakeMessage(&CC->user, recp,
+ CC->room.QRname, anonymous, format_type,
+ masquerade_as, subject, NULL);
if (msg != NULL) {
CtdlSubmitMsg(msg, valid, "");
)
{
- struct quickroom qrbuf;
+ struct room qrbuf;
struct cdbdata *cdbfr;
long *msglist = NULL;
long *dellist = NULL;
* was in, the reference count will reach zero and the message will
* automatically be deleted from the database. We do this in a
* separate pass because there might be plug-in hooks getting called,
- * and we don't want that happening during an S_QUICKROOM critical
+ * and we don't want that happening during an S_ROOMS critical
* section.
*/
if (num_deleted) for (i=0; i<num_deleted; ++i) {
* the current room (returns 1 for yes, 0 for no)
*/
int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void) {
- getuser(&CC->usersupp, CC->curr_user);
- if ((CC->usersupp.axlevel < 6)
- && (CC->usersupp.usernum != CC->quickroom.QRroomaide)
- && ((CC->quickroom.QRflags & QR_MAILBOX) == 0)
+ getuser(&CC->user, CC->curr_user);
+ if ((CC->user.axlevel < 6)
+ && (CC->user.usernum != CC->room.QRroomaide)
+ && ((CC->room.QRflags & QR_MAILBOX) == 0)
&& (!(CC->internal_pgm))) {
return(0);
}
}
delnum = extract_long(delstr, 0);
- num_deleted = CtdlDeleteMessages(CC->quickroom.QRname, delnum, "");
+ num_deleted = CtdlDeleteMessages(CC->room.QRname, delnum, "");
if (num_deleted) {
cprintf("%d %d message%s deleted.\n", CIT_OK,
{
long num;
char targ[SIZ];
- struct quickroom qtemp;
+ struct room qtemp;
int err;
int is_copy = 0;
return;
}
- getuser(&CC->usersupp, CC->curr_user);
+ getuser(&CC->user, CC->curr_user);
/* Aides can move/copy */
- if ((CC->usersupp.axlevel < 6)
+ if ((CC->user.axlevel < 6)
/* Roomaides can move/copy */
- && (CC->usersupp.usernum != CC->quickroom.QRroomaide)
+ && (CC->user.usernum != CC->room.QRroomaide)
/* Permit move/copy to/from personal rooms */
- && (!((CC->quickroom.QRflags & QR_MAILBOX)
+ && (!((CC->room.QRflags & QR_MAILBOX)
&& (qtemp.QRflags & QR_MAILBOX)))
/* Permit only copy from public to personal room */
- && (!(is_copy && !(CC->quickroom.QRflags & QR_MAILBOX)
+ && (!(is_copy && !(CC->room.QRflags & QR_MAILBOX)
&& (qtemp.QRflags & QR_MAILBOX)))) {
cprintf("%d Higher access required.\n",
ERROR + HIGHER_ACCESS_REQUIRED);
* if this is a 'move' rather than a 'copy' operation.
*/
if (is_copy == 0) {
- CtdlDeleteMessages(CC->quickroom.QRname, num, "");
+ CtdlDeleteMessages(CC->room.QRname, num, "");
}
cprintf("%d Message %s.\n", CIT_OK, (is_copy ? "copied" : "moved") );
void CtdlWriteObject(char *req_room, /* Room to stuff it in */
char *content_type, /* MIME type of this object */
char *tempfilename, /* Where to fetch it from */
- struct usersupp *is_mailbox, /* Mailbox room? */
+ struct user *is_mailbox, /* Mailbox room? */
int is_binary, /* Is encoding necessary? */
int is_unique, /* Del others of this type? */
unsigned int flags /* Internal save flags */
)
{
- FILE *fp, *tempfp;
- char filename[PATH_MAX];
- char cmdbuf[SIZ];
- char ch;
- struct quickroom qrbuf;
+ FILE *fp;
+ struct room qrbuf;
char roomname[ROOMNAMELEN];
struct CtdlMessage *msg;
- size_t len;
+
+ char *raw_message = NULL;
+ char *encoded_message = NULL;
+ off_t raw_length = 0;
if (is_mailbox != NULL)
MailboxName(roomname, sizeof roomname, is_mailbox, req_room);
safestrncpy(roomname, req_room, sizeof(roomname));
lprintf(9, "CtdlWriteObject() to <%s> (flags=%d)\n", roomname, flags);
- strcpy(filename, tmpnam(NULL));
- fp = fopen(filename, "w");
- if (fp == NULL)
- return;
- tempfp = fopen(tempfilename, "r");
- if (tempfp == NULL) {
- fclose(fp);
- unlink(filename);
+ fp = fopen(tempfilename, "rb");
+ if (fp == NULL) {
+ lprintf(5, "Cannot open %s: %s\n",
+ tempfilename, strerror(errno));
return;
}
+ fseek(fp, 0L, SEEK_END);
+ raw_length = ftell(fp);
+ rewind(fp);
+ lprintf(9, "Raw length is %ld\n", (long)raw_length);
- fprintf(fp, "Content-type: %s\n", content_type);
- lprintf(9, "Content-type: %s\n", content_type);
+ raw_message = mallok((size_t)raw_length + 2);
+ fread(raw_message, (size_t)raw_length, 1, fp);
+ fclose(fp);
- if (is_binary == 0) {
- fprintf(fp, "Content-transfer-encoding: 7bit\n\n");
- while (ch = getc(tempfp), ch > 0)
- putc(ch, fp);
- fclose(tempfp);
- putc(0, fp);
- fclose(fp);
- } else {
- fprintf(fp, "Content-transfer-encoding: base64\n\n");
- fclose(tempfp);
- fclose(fp);
- snprintf(cmdbuf, sizeof cmdbuf, "./base64 -e <%s >>%s",
- tempfilename, filename);
- system(cmdbuf);
+ if (is_binary) {
+ encoded_message = mallok((size_t)
+ (((raw_length * 134) / 100) + 4096 ) );
+ }
+ else {
+ encoded_message = mallok((size_t)(raw_length + 4096));
+ }
+
+ sprintf(encoded_message, "Content-type: %s\n", content_type);
+
+ if (is_binary) {
+ sprintf(&encoded_message[strlen(encoded_message)],
+ "Content-transfer-encoding: base64\n\n"
+ );
+ }
+ else {
+ sprintf(&encoded_message[strlen(encoded_message)],
+ "Content-transfer-encoding: 7bit\n\n"
+ );
+ }
+
+ if (is_binary) {
+ CtdlEncodeBase64(
+ &encoded_message[strlen(encoded_message)],
+ raw_message,
+ (int)raw_length
+ );
+ }
+ else {
+ raw_message[raw_length] = 0;
+ memcpy(
+ &encoded_message[strlen(encoded_message)],
+ raw_message,
+ (int)(raw_length+1)
+ );
}
+ phree(raw_message);
+
lprintf(9, "Allocating\n");
msg = mallok(sizeof(struct CtdlMessage));
memset(msg, 0, sizeof(struct CtdlMessage));
msg->cm_magic = CTDLMESSAGE_MAGIC;
msg->cm_anon_type = MES_NORMAL;
msg->cm_format_type = 4;
- msg->cm_fields['A'] = strdoop(CC->usersupp.fullname);
+ msg->cm_fields['A'] = strdoop(CC->user.fullname);
msg->cm_fields['O'] = strdoop(req_room);
msg->cm_fields['N'] = strdoop(config.c_nodename);
msg->cm_fields['H'] = strdoop(config.c_humannode);
msg->cm_flags = flags;
- lprintf(9, "Loading\n");
- fp = fopen(filename, "rb");
- fseek(fp, 0L, SEEK_END);
- len = ftell(fp);
- rewind(fp);
- msg->cm_fields['M'] = mallok(len);
- fread(msg->cm_fields['M'], len, 1, fp);
- fclose(fp);
- unlink(filename);
+ msg->cm_fields['M'] = encoded_message;
/* Create the requested room if we have to. */
if (getroom(&qrbuf, roomname) != 0) {
struct CtdlMessage *msg;
char buf[SIZ];
- strcpy(hold_rm, CC->quickroom.QRname);
- if (getroom(&CC->quickroom, SYSCONFIGROOM) != 0) {
- getroom(&CC->quickroom, hold_rm);
+ strcpy(hold_rm, CC->room.QRname);
+ if (getroom(&CC->room, SYSCONFIGROOM) != 0) {
+ getroom(&CC->room, hold_rm);
return NULL;
}
}
}
- getroom(&CC->quickroom, hold_rm);
+ getroom(&CC->room, hold_rm);
if (conf != NULL) do {
extract_token(buf, conf, 0, '\n');
CtdlWriteObject(SYSCONFIGROOM, sysconfname, temp, NULL, 0, 1, 0);
unlink(temp);
}
+
+
+/*
+ * Determine whether a given Internet address belongs to the current user
+ */
+int CtdlIsMe(char *addr) {
+ struct recptypes *recp;
+ int i;
+
+ recp = validate_recipients(addr);
+ if (recp == NULL) return(0);
+
+ if (recp->num_local == 0) {
+ phree(recp);
+ return(0);
+ }
+
+ for (i=0; i<recp->num_local; ++i) {
+ extract(addr, recp->recp_local, i);
+ if (!strcasecmp(addr, CC->user.fullname)) {
+ phree(recp);
+ return(1);
+ }
+ }
+
+ phree(recp);
+ return(0);
+}
+
+
+/*
+ * Citadel protocol command to do the same
+ */
+void cmd_isme(char *argbuf) {
+ char addr[SIZ];
+
+ if (CtdlAccessCheck(ac_logged_in)) return;
+ extract(addr, argbuf, 0);
+
+ if (CtdlIsMe(addr)) {
+ cprintf("%d %s\n", CIT_OK, addr);
+ }
+ else {
+ cprintf("%d Not you.\n", ERROR);
+ }
+
+}