#include #include #include #include #include #include #include #include "mailconf.h" #include "mailconf.m" #include "internal.h" #include #include "../paths.h" static MAILCONF_HELP_FILE help_spam ("spam"); const char subsys_relaycontrol[]="relaycontrol"; static LINUXCONF_SUBSYS sub0 (subsys_relaycontrol ,P_MSG_U(M_SUBRELAYCTRL,"Mail relay controls")); static const char subsys_spammers[]="spammers"; static LINUXCONF_SUBSYS sub1 (subsys_spammers ,P_MSG_U(M_SUBSPAMMERS,"List of well known spammers")); CONFIG_FILE f_spam_ip_allow (ETC_MAIL_IP_ALLOW,help_spam ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,subsys_relaycontrol); CONFIG_FILE f_spam_name_allow (ETC_MAIL_NAME_ALLOW,help_spam ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,subsys_relaycontrol); CONFIG_FILE f_spam_relay_allow (ETC_MAIL_RELAY_ALLOW,help_spam ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,subsys_relaycontrol); CONFIG_FILE f_spam_deny (ETC_MAIL_DENY,help_spam ,CONFIGF_OPTIONAL|CONFIGF_MANAGED ,subsys_spammers); class SPAM_ITEM: public ARRAY_OBJ{ public: SSTRING comment; SSTRING val; /*~PROTOBEG~ SPAM_ITEM */ public: SPAM_ITEM (const char *line); virtual int edit (const char *title, const char *intro, const char *field); virtual void format (char buf1[100], char buf2[100]); virtual int write (FILE_CFG *fout); /*~PROTOEND~ SPAM_ITEM */ }; PUBLIC SPAM_ITEM::SPAM_ITEM( const char *line) { val.setfrom (line); } PUBLIC VIRTUAL int SPAM_ITEM::edit( const char *title, const char *intro, const char *field) { DIALOG dia; dia.newf_str (field,val); int ret = -1; int nof = 0; while (1){ MENU_STATUS code = dia.edit (title,intro,help_spam ,nof,MENUBUT_DEL|MENUBUT_ACCEPT|MENUBUT_CANCEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ if (xconf_delok()){ ret = 1; break; } }else if(code == MENU_ACCEPT){ ret = 0; break; } } return ret; } class SPAM_ITEMS: public ARRAY{ SSTRING last_comments; CONFIG_FILE &fconf; /*~PROTOBEG~ SPAM_ITEMS */ public: SPAM_ITEMS (CONFIG_FILE&_fconf); int edit (const char *title, const char *intro, const char *head, const char *subtitle, const char *subintro, const char *subfield); SPAM_ITEM *getitem (int no)const; virtual SPAM_ITEM *new_spam_item (const char *line); private: void read (void); public: int write (void); /*~PROTOEND~ SPAM_ITEMS */ }; PUBLIC VIRTUAL SPAM_ITEM *SPAM_ITEMS::new_spam_item ( const char *line) { return new SPAM_ITEM (line); } PUBLIC SPAM_ITEMS::SPAM_ITEMS (CONFIG_FILE &_fconf) : fconf (_fconf) { } /* We are using a separate function to read the config file because we are using virtual functions. */ PRIVATE void SPAM_ITEMS::read() { FILE_CFG *fin = fconf.fopen ("r"); if (fin != NULL){ char buf[1000]; SSTRING comments; while (fgets_comments(buf,sizeof(buf)-1,fin,comments,'#')!=NULL){ strip_end (buf); if (buf[0] != '\0'){ SPAM_ITEM *item = new_spam_item(buf); add (item); item->comment.setfrom (comments); comments.setfrom (""); } } last_comments.setfrom (comments); fclose (fin); } } PUBLIC SPAM_ITEM* SPAM_ITEMS::getitem (int no) const { return (SPAM_ITEM*)ARRAY::getitem (no); } PUBLIC VIRTUAL int SPAM_ITEM::write (FILE_CFG *fout) { comment_write (comment,fout); fprintf (fout,"%s\n",val.get()); return 0; } PUBLIC VIRTUAL void SPAM_ITEM::format (char buf1[100],char buf2[100]) { snprintf (buf1,100-1,"%s",val.get()); buf2[0] = '\0'; } PUBLIC int SPAM_ITEMS::write () { context_mkdir (ETC_MAIL,"root","root",0755); FILE_CFG *fout = fconf.fopen ("w"); int ret = -1; if (fout != NULL){ for (int i=0; iwrite (fout); } comment_write (last_comments,fout); ret = fclose (fout); } return ret; } PUBLIC int SPAM_ITEMS::edit ( const char *title, const char *intro, const char *head, const char *subtitle, // Titles for one item dialog const char *subintro, const char *subfield) { read(); DIALOG_LISTE dia; dia.newf_head ("",head); dia.addwhat (MSG_U(I_ADDENTRY,"Select [Add] to add a new entry")); int nof = 0; while (1){ for (int i=0; iformat(buf1,buf2); dia.set_menuitem (i,buf1,buf2); } dia.remove_last (getnb()+1); MENU_STATUS code = dia.editmenu (title,intro,help_spam ,nof,MENUBUT_ADD); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (code == MENU_ADD){ SPAM_ITEM *n = new_spam_item (""); int code = n->edit(subtitle,subintro,subfield); manage_edit (n,code); }else{ SPAM_ITEM *s = getitem(nof); if (s != NULL){ int code = s->edit(subtitle,subintro,subfield); manage_edit (s,code); } } } return 0; } class SPAM_ITEM_DENY: public SPAM_ITEM{ SSTRING error; /*~PROTOBEG~ SPAM_ITEM_DENY */ public: SPAM_ITEM_DENY (const char *line); int edit (const char *, const char *, const char *); void format (char buf1[100], char buf2[100]); int write (FILE_CFG *fout); /*~PROTOEND~ SPAM_ITEM_DENY */ }; PUBLIC int SPAM_ITEM_DENY::write (FILE_CFG *fout) { fprintf (fout,"%s\t%s\n",val.get(),error.get()); return 0; } PUBLIC void SPAM_ITEM_DENY::format (char buf1[100],char buf2[100]) { snprintf (buf1,100-1,"%s",val.get()); snprintf (buf2,100-1,"%s",error.get()); } PUBLIC SPAM_ITEM_DENY::SPAM_ITEM_DENY ( const char *line) : SPAM_ITEM ("") { const char *pt = strchr(line,'\t'); if (pt != NULL){ error.setfrom (pt+1); int len = (int)(pt-line); char buf[len+1]; memcpy (buf,line,len); buf[len] = '\0'; val.setfrom (buf); }else{ val.setfrom (line); } } PUBLIC int SPAM_ITEM_DENY::edit( const char *, const char *, const char *) { DIALOG dia; dia.newf_str (MSG_U(F_EMAILORIGIN,"Email origin"),val); dia.newf_str (MSG_U(F_ERRMSG,"Error message"),error); int ret = -1; int nof = 0; while (1){ MENU_STATUS code = dia.edit ( MSG_U(T_DENYSPAM,"Rejected message") ,MSG_U(I_DENYSPAM ,"You enter the sender address you want\n" "to filter out.\n" "You may enter a complete email address,\n" "a domain, a host name or a network address") ,help_spam ,nof,MENUBUT_DEL|MENUBUT_ACCEPT|MENUBUT_CANCEL); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ if (xconf_delok()){ ret = 1; break; } }else if(code == MENU_ACCEPT){ ret = 0; break; } } return ret; } class SPAM_ITEMS_DENY: public SPAM_ITEMS{ /*~PROTOBEG~ SPAM_ITEMS_DENY */ public: SPAM_ITEMS_DENY (CONFIG_FILE&_fconf); SPAM_ITEM *new_spam_item (const char *line); int write (void); /*~PROTOEND~ SPAM_ITEMS_DENY */ }; PUBLIC SPAM_ITEM *SPAM_ITEMS_DENY::new_spam_item (const char *line) { return new SPAM_ITEM_DENY (line); } PUBLIC SPAM_ITEMS_DENY::SPAM_ITEMS_DENY (CONFIG_FILE &_fconf) : SPAM_ITEMS (_fconf) { } PUBLIC int SPAM_ITEMS_DENY::write () { int ret = SPAM_ITEMS::write(); mtable_makemap(f_spam_deny); return ret; } void spam_edit_deny() { SPAM_ITEMS_DENY items (f_spam_deny); items.edit(MSG_U(T_REJECTFROM,"Mail rejected from") ,MSG_U(I_REJECTFROM ,"Any mail received from one of the following persons\n" "or domains will be dropped\n") ,MSG_U(H_REJECTFROM,"Sender\tMessage") ,"","",""); } void spam_edit_ip_allow() { SPAM_ITEMS items (f_spam_ip_allow); items.edit(MSG_U(T_ALLOW,"May relay mail for") ,MSG_U(I_IPALLOW ,"This is the list of hosts or networks which\n" "are allowed to use your server as a mail relay\n" "You must enter either complete IP numbers\n" "for host, or partial IP for networks.\n" "\n" "Partial IP must be followed by a dot. For example\n" "network 192.168.1.0 is represented by 192.168.1.") ,MSG_U(I_HOSTIPORNET,"Host IP or network") ,MSG_U(T_IPALLOWTHIS,"Allow this host/domain to use your server(IP)") ,"" ,MSG_R(I_HOSTIPORNET)); } void spam_edit_name_allow() { SPAM_ITEMS items (f_spam_name_allow); items.edit(MSG_R(T_ALLOW) ,MSG_U(I_NAMEALLOW ,"This is the list of hosts or domains which\n" "are allowed to use your server as a mail relay") ,MSG_U(H_HOSTORDOMAIN,"Host or domain name") ,MSG_U(T_ALLOWTHIS,"Allow this host/domain to use your server") ,"" ,MSG_R(H_HOSTORDOMAIN)); } void spam_edit_relay_allow() { SPAM_ITEMS items (f_spam_relay_allow); items.edit(MSG_U(T_RELAY,"May relay mail to") ,MSG_U(I_RELAY,"Enter the list of host or network\n" "to which you intend to relay mail") ,MSG_U(H_NAMEORNET,"Name or network address") ,MSG_U(T_RELAYTHIS,"Relay to this host/network") ,"" ,MSG_R(H_NAMEORNET)); }