#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"
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);
+ (int)(length + add_newline) );
cprintf("Content-transfer-encoding: %s\n", encoding);
cprintf("\n");
client_write(content, length);
*/
/*
- * Fetch the message from disk. We also keep the most recently
- * read message in memory, in case we want to read it again, or fetch
- * MIME parts out of it, or whatever.
+ * Fetch the message from disk.
*/
- if ( (CC->cached_msg != NULL) && (CC->cached_msgnum == msg_num) ) {
- TheMessage = CC->cached_msg;
- }
- else {
- TheMessage = CtdlFetchMessage(msg_num);
- if (CC->cached_msg != NULL) {
- phree(CC->cached_msg);
- }
- CC->cached_msg = TheMessage;
- CC->cached_msgnum = msg_num;
- }
+ TheMessage = CtdlFetchMessage(msg_num);
if (TheMessage == NULL) {
if (do_proto) cprintf("%d Can't locate msg %ld on disk\n",
TheMessage, msg_num, mode,
headers_only, do_proto, crlf);
- /* don't free the memory; we're keeping it in the cache */
- /* CtdlFreeMessage(TheMessage); */
+ CtdlFreeMessage(TheMessage);
return(retcode);
}
) {
int i, k;
char buf[1024];
- CIT_UBYTE ch;
+ cit_uint8_t ch;
char allkeys[SIZ];
char display_name[SIZ];
char *mptr;
}
}
- strcpy(force_room, force);
+ if (force == NULL) {
+ strcpy(force_room, "");
+ }
+ else {
+ strcpy(force_room, force);
+ }
/* Learn about what's inside, because it's what's inside that counts */
lprintf(9, "Learning what's inside\n");
/*
* Convenience function for generating small administrative messages.
*/
-void quickie_message(char *from, char *to, char *room, char *text)
+void quickie_message(char *from, char *to, char *room, char *text,
+ int format_type, char *subject)
{
struct CtdlMessage *msg;
struct recptypes *recp = NULL;
memset(msg, 0, sizeof(struct CtdlMessage));
msg->cm_magic = CTDLMESSAGE_MAGIC;
msg->cm_anon_type = MES_NORMAL;
- msg->cm_format_type = 0;
+ msg->cm_format_type = format_type;
msg->cm_fields['A'] = strdoop(from);
- msg->cm_fields['O'] = strdoop(room);
+ if (room != NULL) msg->cm_fields['O'] = strdoop(room);
msg->cm_fields['N'] = strdoop(NODENAME);
if (to != NULL) {
msg->cm_fields['R'] = strdoop(to);
recp = validate_recipients(to);
}
+ if (subject != NULL) {
+ msg->cm_fields['U'] = strdoop(subject);
+ }
msg->cm_fields['M'] = strdoop(text);
CtdlSubmitMsg(msg, recp, room);
/*
- * 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 */
/* read in the lines of message text one by one */
while ( (client_gets(buf)>0) && strcmp(buf, terminator) ) {
- /* strip trailing newline type stuff */
- if (buf[strlen(buf)-1]==10) buf[strlen(buf)-1]=0;
- if (buf[strlen(buf)-1]==13) buf[strlen(buf)-1]=0;
-
+ /* 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) {
/*
* 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 CtdlMessage *CtdlMakeMessage(
struct usersupp *author, /* author's usersupp 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];
msg->cm_fields['D'] = strdoop(dest_node);
}
- if ( (author == &CC->usersupp) && (CC->cs_inet_email != NULL) ) {
+ if ( (author == &CC->usersupp) && (strlen(CC->cs_inet_email) > 0) ) {
msg->cm_fields['F'] = strdoop(CC->cs_inet_email);
}
}
}
- msg->cm_fields['M'] = CtdlReadMessageBody("000",
+ if (preformatted_text != NULL) {
+ msg->cm_fields['M'] = preformatted_text;
+ }
+ else {
+ msg->cm_fields['M'] = CtdlReadMessageBody("000",
config.c_maxmsglen, NULL);
+ }
return(msg);
}
}
+/*
+ * Check to see if the specified user has Internet mail permission
+ * (returns nonzero if permission is granted)
+ */
+int CtdlCheckInternetMailPermission(struct usersupp *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!!!!!
phree(valid);
return;
}
+ if (valid->num_internet > 0) {
+ if (CtdlCheckInternetMailPermission(&CC->usersupp)==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) ) {
/* Read in the message from the client. */
cprintf("%d send message\n", SEND_LISTING);
- msg = make_message(&CC->usersupp, recp,
+ msg = CtdlMakeMessage(&CC->usersupp, recp,
CC->quickroom.QRname, anonymous, format_type,
- masquerade_as, subject);
+ masquerade_as, subject, NULL);
if (msg != NULL) {
CtdlSubmitMsg(msg, valid, "");
)
{
- FILE *fp, *tempfp;
- char filename[PATH_MAX];
- char cmdbuf[SIZ];
- char ch;
+ FILE *fp;
struct quickroom 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);
+ 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_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) {
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->usersupp.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);
+ }
+
+}