#include <errno.h>
#include <stdarg.h>
#include <sys/stat.h>
+#include <sys/types.h>
+#include <regex.h>
#include "citadel.h"
#include "server.h"
#include "serv_extensions.h"
}
-void get_mm(void)
-{
- FILE *fp;
-
- fp = fopen(file_citadel_control, "r");
- if (fp == NULL) {
- lprintf(CTDL_CRIT, "Cannot open %s: %s\n",
- file_citadel_control,
- strerror(errno));
- exit(errno);
- }
- fread((char *) &CitControl, sizeof(struct CitControl), 1, fp);
- fclose(fp);
-}
-
-
/*
* Back end for the MSGS command: output message number only.
*/
int num_processed = 0;
long thismsg;
struct MetaData smi;
- struct CtdlMessage *msg;
+ struct CtdlMessage *msg = NULL;
int is_seen = 0;
long lastold = 0L;
int printed_lastold = 0;
int num_search_msgs = 0;
long *search_msgs = NULL;
+ regex_t re;
+ regmatch_t pm;
+
+ if (content_type) if (strlen(content_type) > 0) {
+ regcomp(&re, content_type, 0);
+ }
/* Learn about the user and room in question */
- get_mm();
getuser(&CC->user, CC->curr_user);
CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
*/
GetMetaData(&smi, msglist[a]);
- if (strcasecmp(smi.meta_content_type, content_type)) {
+ /* if (strcasecmp(smi.meta_content_type, content_type)) { old non-regex way */
+ if (regexec(&re, smi.meta_content_type, 1, &pm, 0) != 0) {
msglist[a] = 0L;
}
}
template = (struct CtdlMessage *)
malloc(sizeof(struct CtdlMessage));
memset(template, 0, sizeof(struct CtdlMessage));
+ template->cm_magic = CTDLMESSAGE_MAGIC;
+ template->cm_anon_type = MES_NORMAL;
+
while(client_getln(buf, sizeof buf), strcmp(buf,"000")) {
extract_token(tfield, buf, 0, '|', sizeof tfield);
extract_token(tvalue, buf, 1, '|', sizeof tvalue);
{
int i;
- if (is_valid_message(msg) == 0) return;
+ if (is_valid_message(msg) == 0)
+ {
+ if (msg != NULL) free (msg);
+ return;
+ }
for (i = 0; i < 256; ++i)
if (msg->cm_fields[i] != NULL) {
if (ma->is_ma > 0) {
for (i=0; i<num_tokens(CC->preferred_formats, '|'); ++i) {
extract_token(buf, CC->preferred_formats, i, '|', sizeof buf);
- lprintf(CTDL_DEBUG, "Is <%s> == <%s> ??\n", buf, cbtype);
if ( (!strcasecmp(buf, cbtype)) && (!ma->freeze) ) {
if (i < ma->chosen_pref) {
safestrncpy(ma->chosen_part, partnum, sizeof ma->chosen_part);
void cmd_msg3(char *cmdbuf)
{
long msgnum;
- struct CtdlMessage *msg;
+ struct CtdlMessage *msg = NULL;
struct ser_ret smr;
if (CC->internal_pgm == 0) {
lprintf(CTDL_DEBUG, "Delivering private local mail to <%s>\n",
recipient);
if (getuser(&userbuf, recipient) == 0) {
+ // Add a flag so the Funambol module knows its mail
+ msg->cm_fields['W'] = strdup(recipient);
MailboxName(actual_rm, sizeof actual_rm,
&userbuf, MAILROOM);
CtdlSaveMsgPointerInRoom(actual_rm, newmsgid, 0, msg);
BumpNewMailCounter(userbuf.usernum);
+ if (strlen(config.c_funambol_host) > 0) {
+ /* Generate a instruction message for the Funambol notification
+ server, in the same style as the SMTP queue */
+ instr = malloc(SIZ * 2);
+ snprintf(instr, SIZ * 2,
+ "Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
+ "bounceto|%s@%s\n",
+ SPOOLMIME, newmsgid, (long)time(NULL),
+ msg->cm_fields['A'], msg->cm_fields['N']
+ );
+
+ imsg = malloc(sizeof(struct CtdlMessage));
+ memset(imsg, 0, sizeof(struct CtdlMessage));
+ imsg->cm_magic = CTDLMESSAGE_MAGIC;
+ imsg->cm_anon_type = MES_NORMAL;
+ imsg->cm_format_type = FMT_RFC822;
+ imsg->cm_fields['A'] = strdup("Citadel");
+ imsg->cm_fields['J'] = strdup("do not journal");
+ imsg->cm_fields['M'] = instr;
+ imsg->cm_fields['W'] = strdup(recipient);
+ CtdlSubmitMsg(imsg, NULL, FNBL_QUEUE_ROOM);
+ CtdlFreeMessage(imsg);
+ }
}
else {
lprintf(CTDL_DEBUG, "No user <%s>\n", recipient);
int type, /* see MES_ types in header file */
int format_type, /* variformat, plain text, MIME... */
char *fake_name, /* who we're masquerading as */
+ char *my_email, /* which of my email addresses to use (empty is ok) */
char *subject, /* Subject (optional) */
char *supplied_euid, /* ...or NULL if this is irrelevant */
char *preformatted_text /* ...or NULL to read text from client */
) {
- char dest_node[SIZ];
- char buf[SIZ];
+ char dest_node[256];
+ char buf[1024];
struct CtdlMessage *msg;
msg = malloc(sizeof(struct CtdlMessage));
msg->cm_fields['D'] = strdup(dest_node);
}
- if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) {
+ if (strlen(my_email) > 0) {
+ msg->cm_fields['F'] = strdup(my_email);
+ }
+ else if ( (author == &CC->user) && (strlen(CC->cs_inet_email) > 0) ) {
msg->cm_fields['F'] = strdup(CC->cs_inet_email);
}
msg->cm_fields['M'] = preformatted_text;
}
else {
- msg->cm_fields['M'] = CtdlReadMessageBody("000",
- config.c_maxmsglen, NULL, 0);
+ msg->cm_fields['M'] = CtdlReadMessageBody("000", config.c_maxmsglen, NULL, 0);
}
return(msg);
* returns 0 on success.
*/
int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n) {
+ int ra;
if (!(CC->logged_in)) {
snprintf(errmsgbuf, n, "Not logged in.");
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
- 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->user.axlevel < 6)
- && (CC->room.QRflags & QR_READONLY)) {
- snprintf(errmsgbuf, n, "Sorry, this is a read-only room.");
+ CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
+ if (!(ra & UA_POSTALLOWED)) {
+ snprintf(errmsgbuf, n, "Higher access is required to post in this room.");
return (ERROR + HIGHER_ACCESS_REQUIRED);
}
char cc[SIZ];
char bcc[SIZ];
char supplied_euid[128];
- char masquerade_as[SIZ];
int anon_flag = 0;
int format_type = 0;
- char newusername[SIZ];
+ char newusername[256];
+ char newuseremail[256];
struct CtdlMessage *msg;
int anonymous = 0;
char errmsg[SIZ];
char subject[SIZ];
int do_confirm = 0;
long msgnum;
+ int i, j;
+ char buf[256];
+ int newuseremail_ok = 0;
unbuffer_output();
anon_flag = extract_int(entargs, 2);
format_type = extract_int(entargs, 3);
extract_token(subject, entargs, 4, '|', sizeof subject);
+ extract_token(newusername, entargs, 5, '|', sizeof newusername);
do_confirm = extract_int(entargs, 6);
extract_token(cc, entargs, 7, '|', sizeof cc);
extract_token(bcc, entargs, 8, '|', sizeof bcc);
supplied_euid[0] = 0;
break;
}
+ extract_token(newuseremail, entargs, 9, '|', sizeof newuseremail);
/* first check to make sure the request is valid. */
err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg);
- if (err) {
+ if (err)
+ {
cprintf("%d %s\n", err, errmsg);
return;
}
/* Check some other permission type things. */
- if (post == 2) {
- if (CC->user.axlevel < 6) {
- cprintf("%d You don't have permission to masquerade.\n",
- ERROR + HIGHER_ACCESS_REQUIRED);
- return;
+ if (strlen(newusername) == 0) {
+ strcpy(newusername, CC->user.fullname);
+ }
+ if ( (CC->user.axlevel < 6)
+ && (strcasecmp(newusername, CC->user.fullname))
+ && (strcasecmp(newusername, CC->cs_inet_fn))
+ ) {
+ cprintf("%d You don't have permission to author messages as '%s'.\n",
+ ERROR + HIGHER_ACCESS_REQUIRED,
+ newusername
+ );
+ return;
+ }
+
+
+ if (strlen(newuseremail) == 0) {
+ newuseremail_ok = 1;
+ }
+
+ if (strlen(newuseremail) > 0) {
+ if (!strcasecmp(newuseremail, CC->cs_inet_email)) {
+ newuseremail_ok = 1;
}
- extract_token(newusername, entargs, 5, '|', sizeof newusername);
- memset(CC->fake_postname, 0, sizeof(CC->fake_postname) );
- safestrncpy(CC->fake_postname, newusername,
- sizeof(CC->fake_postname) );
- cprintf("%d ok\n", CIT_OK);
+ else if (strlen(CC->cs_inet_other_emails) > 0) {
+ j = num_tokens(CC->cs_inet_other_emails, '|');
+ for (i=0; i<j; ++i) {
+ extract_token(buf, CC->cs_inet_other_emails, i, '|', sizeof buf);
+ if (!strcasecmp(newuseremail, buf)) {
+ newuseremail_ok = 1;
+ }
+ }
+ }
+ }
+
+ if (!newuseremail_ok) {
+ cprintf("%d You don't have permission to author messages as '%s'.\n",
+ ERROR + HIGHER_ACCESS_REQUIRED,
+ newuseremail
+ );
return;
}
+
CC->cs_flags |= CS_POSTING;
/* In the Mail> room we have to behave a little differently --
free(valid_cc);
free(valid_bcc);
- /* Handle author masquerading */
- if (CC->fake_postname[0]) {
- strcpy(masquerade_as, CC->fake_postname);
- }
- else if (CC->fake_username[0]) {
- strcpy(masquerade_as, CC->fake_username);
- }
- else {
- strcpy(masquerade_as, "");
- }
-
/* Read in the message from the client. */
if (do_confirm) {
cprintf("%d send message\n", START_CHAT_MODE);
msg = CtdlMakeMessage(&CC->user, recp, cc,
CC->room.QRname, anonymous, format_type,
- masquerade_as, subject,
+ newusername, newuseremail, subject,
((strlen(supplied_euid) > 0) ? supplied_euid : NULL),
NULL);
CtdlFreeMessage(msg);
}
- CC->fake_postname[0] = '\0';
if (valid != NULL) {
free(valid);
}
int CtdlDeleteMessages(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 */
+ char *content_type /* or "" for any. regular expressions expected. */
)
{
-
struct ctdlroom qrbuf;
struct cdbdata *cdbfr;
long *msglist = NULL;
int num_deleted = 0;
int delete_this;
struct MetaData smi;
+ regex_t re;
+ regmatch_t pm;
+ if (content_type) if (strlen(content_type) > 0) {
+ regcomp(&re, content_type, 0);
+ }
lprintf(CTDL_DEBUG, "CtdlDeleteMessages(%s, %d msgs, %s)\n",
room_name, num_dmsgnums, content_type);
delete_this |= 0x02;
} else {
GetMetaData(&smi, msglist[i]);
- if (!strcasecmp(smi.meta_content_type,
- content_type)) {
+ if (regexec(&re, smi.meta_content_type, 1, &pm, 0) == 0) {
delete_this |= 0x02;
}
}
* the current room (returns 1 for yes, 0 for no)
*/
int CtdlDoIHavePermissionToDeleteMessagesFromThisRoom(void) {
- 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);
- }
- return(1);
+ int ra;
+ CtdlRoomAccess(&CC->room, &CC->user, &ra, NULL);
+ if (ra & UA_DELETEALLOWED) return(1);
+ return(0);
}
+
/*
* Delete message from current room
*/