html_to_ascii() moved into libcitadel
[citadel.git] / citadel / msgbase.c
index 15957eb24d18de53dd865a253b4a9a440b900b88..10ec60887d068f470c6e667aea2a166a9f33af69 100644 (file)
 #include "file_ops.h"
 #include "config.h"
 #include "control.h"
-#include "html.h"
 #include "genstamp.h"
 #include "internet_addressing.h"
 #include "euidindex.h"
 #include "journaling.h"
 #include "citadel_dirs.h"
 #include "clientsocket.h"
-
+#include "serv_network.h"
+#include "threads.h"
 
 long config_msgnum;
 struct addresses_to_be_filed *atbf = NULL;
@@ -805,7 +805,7 @@ void do_help_subst(char *buffer)
        help_subst(buffer, "^variantname", CITADEL);
        snprintf(buf2, sizeof buf2, "%d", config.c_maxsessions);
        help_subst(buffer, "^maxsessions", buf2);
-       help_subst(buffer, "^bbsdir", ctdl_bbsbase_dir);
+       help_subst(buffer, "^bbsdir", ctdl_message_dir);
 }
 
 
@@ -1707,7 +1707,7 @@ int CtdlOutputPreLoadedMsg(
                }
 
                /* Construct a fun message id */
-               cprintf("Message-ID: <%s", mid);
+               cprintf("Message-ID: <%s", mid);/// todo: this possibly breaks threadding mails.
                if (strchr(mid, '@')==NULL) {
                        cprintf("@%s", snode);
                }
@@ -2472,15 +2472,18 @@ long CtdlSubmitMsg(struct CtdlMessage *msg,     /* message to save */
                strcpy(content_type, "text/plain");
                mptr = bmstrcasestr(msg->cm_fields['M'], "Content-type:");
                if (mptr != NULL) {
+                       char *aptr;
                        safestrncpy(content_type, &mptr[13], sizeof content_type);
                        striplt(content_type);
-                       for (a = 0; a < strlen(content_type); ++a) {
-                               if ((content_type[a] == ';')
-                                   || (content_type[a] == ' ')
-                                   || (content_type[a] == 13)
-                                   || (content_type[a] == 10)) {
-                                       content_type[a] = 0;
+                       aptr = content_type;
+                       while (!IsEmptyStr(aptr)) {
+                               if ((*aptr == ';')
+                                   || (*aptr == ' ')
+                                   || (*aptr == 13)
+                                   || (*aptr == 10)) {
+                                       *aptr = 0;
                                }
+                               else aptr++;
                        }
                }
        }
@@ -2841,7 +2844,7 @@ void quickie_message(char *from, char *fromaddr, char *to, char *room, char *tex
        msg->cm_fields['N'] = strdup(NODENAME);
        if (to != NULL) {
                msg->cm_fields['R'] = strdup(to);
-               recp = validate_recipients(to);
+               recp = validate_recipients(to, NULL, 0);
        }
        if (subject != NULL) {
                msg->cm_fields['U'] = strdup(subject);
@@ -3090,7 +3093,10 @@ struct CtdlMessage *CtdlMakeMessage(
  * room.  Returns a *CITADEL ERROR CODE* and puts a message in errmsgbuf, or
  * returns 0 on success.
  */
-int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n, int PostPublic) {
+int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, 
+                                         size_t n, 
+                                         const char* RemoteIdentifier,
+                                         int PostPublic) {
        int ra;
 
        if (!(CC->logged_in) && 
@@ -3099,20 +3105,51 @@ int CtdlDoIHavePermissionToPostInThisRoom(char *errmsgbuf, size_t n, int PostPub
                return (ERROR + NOT_LOGGED_IN);
        }
        else if (PostPublic == CHECK_EXISTANCE) {
-               return (0);
+               return (0); // We're Evaling whether a recipient exists
        }
        else if (!(CC->logged_in)) {
+               
                if ((CC->room.QRflags & QR_READONLY)) {
                        snprintf(errmsgbuf, n, "Not logged in.");
                        return (ERROR + NOT_LOGGED_IN);
                }
-               else if (CC->room.QRflags2 & QR2_SUBSONLY){
-                       ////TODO: check if we're in that list...
-                       return (0);
+               if (CC->room.QRflags2 & QR2_MODERATED) {
+                       snprintf(errmsgbuf, n, "Not logged in Moderation feature not yet implemented!");
+                       return (ERROR + NOT_LOGGED_IN);
                }
-               else if (CC->room.QRflags2 & QR2_MODERATED) {
-                       return (0);
+               if ((PostPublic!=POST_LMTP) &&(CC->room.QRflags2 & QR2_SMTP_PUBLIC) == 0) {
+                       SpoolControl *sc;
+                       char filename[SIZ];
+                       int found;
+
+                       if (RemoteIdentifier == NULL)
+                       {
+                               snprintf(errmsgbuf, n, "Need sender to permit access.");
+                               return (ERROR + USERNAME_REQUIRED);
+                       }
+
+                       assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
+                       begin_critical_section(S_NETCONFIGS);
+                       if (!read_spoolcontrol_file(&sc, filename))
+                       {
+                               end_critical_section(S_NETCONFIGS);
+                               snprintf(errmsgbuf, n,
+                                       "This mailing list only accepts posts from subscribers.");
+                               return (ERROR + NO_SUCH_USER);
+                       }
+                       end_critical_section(S_NETCONFIGS);
+                       found = is_recipient (sc, RemoteIdentifier);
+                       free_spoolcontrol_struct(&sc);
+                       if (found) {
+                               return (0);
+                       }
+                       else {
+                               snprintf(errmsgbuf, n,
+                                       "This mailing list only accepts posts from subscribers.");
+                               return (ERROR + NO_SUCH_USER);
+                       }
                }
+               return (0);
 
        }
 
@@ -3166,7 +3203,9 @@ int CtdlCheckInternetMailPermission(struct ctdluser *who) {
  *
  * Caller needs to free the result using free_recipients()
  */
-struct recptypes *validate_recipients(char *supplied_recipients) {
+struct recptypes *validate_recipients(char *supplied_recipients, 
+                                     const char *RemoteIdentifier, 
+                                     int Flags) {
        struct recptypes *ret;
        char *recipients = NULL;
        char this_recp[256];
@@ -3245,6 +3284,8 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                }
 
                striplt(this_recp);
+               if (IsEmptyStr(this_recp))
+                       break;
                lprintf(CTDL_DEBUG, "Evaluating recipient #%d: %s\n", num_recps, this_recp);
                ++num_recps;
                mailtype = alias(this_recp);
@@ -3261,6 +3302,7 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                }
                this_recp_cooked[j] = '\0';
                invalid = 0;
+               errmsg[0] = 0;
                switch(mailtype) {
                        case MES_LOCAL:
                                if (!strcasecmp(this_recp, "sysop")) {
@@ -3295,11 +3337,13 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                                        CC->room = tempQR;
                                        
                                        /* Check permissions to send mail to this room */
-                                       err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg, POST_EXTERNAL);
-                                       //// TODO: CHECK_EXISTANCE for dict_tcp
+                                       err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, 
+                                                                                   sizeof errmsg, 
+                                                                                   RemoteIdentifier,
+                                                                                   Flags
+                                       );
                                        if (err)
                                        {
-                                               cprintf("%d %s\n", err, errmsg);
                                                ++ret->num_error;
                                                invalid = 1;
                                        } 
@@ -3352,15 +3396,16 @@ struct recptypes *validate_recipients(char *supplied_recipients) {
                                break;
                }
                if (invalid) {
-                       if (IsEmptyStr(ret->errormsg)) {
-                               snprintf(append, sizeof append,
-                                        "Invalid recipient: %s",
-                                        this_recp);
+                       if (IsEmptyStr(errmsg)) {
+                               snprintf(append, sizeof append, "Invalid recipient: %s", this_recp);
                        }
                        else {
-                               snprintf(append, sizeof append, ", %s", this_recp);
+                               snprintf(append, sizeof append, "%s", errmsg);
                        }
-                       if ( (strlen(ret->errormsg) + strlen(append)) < SIZ) {
+                       if ( (strlen(ret->errormsg) + strlen(append) + 3) < SIZ) {
+                               if (!IsEmptyStr(ret->errormsg)) {
+                                       strcat(ret->errormsg, "; ");
+                               }
                                strcat(ret->errormsg, append);
                        }
                }
@@ -3474,7 +3519,7 @@ void cmd_ent0(char *entargs)
 
        /* first check to make sure the request is valid. */
 
-       err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg, POST_LOGGED_IN);
+       err = CtdlDoIHavePermissionToPostInThisRoom(errmsg, sizeof errmsg, NULL, POST_LOGGED_IN);
        if (err)
        {
                cprintf("%d %s\n", err, errmsg);
@@ -3542,24 +3587,24 @@ void cmd_ent0(char *entargs)
                        strcpy(bcc, "");
                }
 
-               valid_to = validate_recipients(recp);
+               valid_to = validate_recipients(recp, NULL, 0);
                if (valid_to->num_error > 0) {
-                       cprintf("%d Invalid recipient (To)\n", ERROR + NO_SUCH_USER);
+                       cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_to->errormsg);
                        free_recipients(valid_to);
                        return;
                }
 
-               valid_cc = validate_recipients(cc);
+               valid_cc = validate_recipients(cc, NULL, 0);
                if (valid_cc->num_error > 0) {
-                       cprintf("%d Invalid recipient (CC)\n", ERROR + NO_SUCH_USER);
+                       cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_cc->errormsg);
                        free_recipients(valid_to);
                        free_recipients(valid_cc);
                        return;
                }
 
-               valid_bcc = validate_recipients(bcc);
+               valid_bcc = validate_recipients(bcc, NULL, 0);
                if (valid_bcc->num_error > 0) {
-                       cprintf("%d Invalid recipient (BCC)\n", ERROR + NO_SUCH_USER);
+                       cprintf("%d %s\n", ERROR + NO_SUCH_USER, valid_bcc->errormsg);
                        free_recipients(valid_to);
                        free_recipients(valid_cc);
                        free_recipients(valid_bcc);
@@ -3684,7 +3729,7 @@ void cmd_ent0(char *entargs)
                strcat(all_recps, bcc);
        }
        if (!IsEmptyStr(all_recps)) {
-               valid = validate_recipients(all_recps);
+               valid = validate_recipients(all_recps, NULL, 0);
        }
        else {
                valid = NULL;
@@ -3970,6 +4015,10 @@ void cmd_move(char *args)
        /* Permit message removal from collaborative delete rooms */
        if (CC->room.QRflags2 & QR2_COLLABDEL) permit = 1;
 
+       /* Users allowed to post into the target room may move into it too. */
+       if ((CC->room.QRflags & QR_MAILBOX) && 
+           (qtemp.QRflags & UA_POSTALLOWED))  permit = 1;
+
        /* User must have access to target room */
        if (!(ra & UA_KNOWN))  permit = 0;
 
@@ -4402,7 +4451,7 @@ int CtdlIsMe(char *addr, int addr_buf_len)
        struct recptypes *recp;
        int i;
 
-       recp = validate_recipients(addr);
+       recp = validate_recipients(addr, NULL, 0);
        if (recp == NULL) return(0);
 
        if (recp->num_local == 0) {