#include #include #include #include "../paths.h" #include #include #include #include "internal.h" #include "mailconf.m" #include #include #include static MAILCONF_HELP_FILE help_mailfax ("mailfax"); static MAILCONF_HELP_FILE help_faxbasic ("faxbasic"); static MAILCONF_HELP_FILE help_faxalias ("faxalias"); static MAILCONF_HELP_FILE help_faxrules ("faxrules"); static MAILCONF_HELP_FILE help_faxzone ("faxzone"); static MAILCONF_HELP_FILE help_faxuser ("faxuser"); static const char subsys_fax[]="mail2fax"; static LINUXCONF_SUBSYS subb (subsys_fax ,P_MSG_U(M_FAXSUBSYS,"Mail to fax gateway")); static CONFIG_FILE f_aliases (ETC_FAX_ALIASES,help_faxalias ,CONFIGF_OPTIONAL|CONFIGF_MANAGED,subsys_fax); static CONFIG_FILE f_users (ETC_FAX_USERS,help_faxuser ,CONFIGF_OPTIONAL|CONFIGF_MANAGED,subsys_fax); static CONFIG_FILE f_zones (ETC_FAX_ZONES,help_mailfax ,CONFIGF_OPTIONAL|CONFIGF_MANAGED,subsys_fax); static CONFIG_FILE f_rules (ETC_FAX_RULES,help_faxrules ,CONFIGF_OPTIONAL|CONFIGF_MANAGED,subsys_fax); static PRIVILEGE privi ("managefax" ,P_MSG_U(F_MANAGEFAX,"Mail to Fax manager") ,P_MSG_U(T_SERVICES,"1-Services")); static const char K_MAILFAX[]="mailfax"; static const char K_ENABLE[]="enable"; static const char K_FAXCMD[]="faxcmd"; static const char K_FAXLOG[]="faxlog"; static const char K_FAXLOGCMD[]="faxlogcmd"; static const char K_INDEX[]="index"; static const char K_ID[]="id"; static const char K_LEN[]="len"; static const char K_ACCUSER[]="accuser"; static const char K_ACCPGP[]="accpgp"; static const char K_ACCORIGIN[]="accorigin"; static const char K_ZONE[]="zone"; static const char K_USER[]="user"; PUBLIC FAXALIAS::FAXALIAS(const char *buf) { char tb[4][100]; str_splitline (buf,':',tb,4); alias.setfrom (tb[0]); name.setfrom (tb[1]); phone.setfrom (tb[2]); rule.setfrom (tb[3]); } PUBLIC FAXALIAS::FAXALIAS() { } static FAXRULES *ptrules=NULL; static FAXUSERS *ptusers=NULL; static void mailfax_setrule (DIALOG &dia, SSTRING &rule) { FIELD_COMBO *comb = dia.newf_list (MSG_U(F_RULE,"Access rule"),rule); for (int i=0; igetnb(); i++){ FAXRULE *r = ptrules->getitem(i); comb->addopt (r->getid()); } } PUBLIC int FAXALIAS::edit() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_FAXALIASE,"Alias"),alias); dia.newf_str (MSG_U(F_FAXALIASENAME,"Full name"),name); dia.newf_str (MSG_U(F_FAXPHONE,"Phone number"),phone); mailfax_setrule (dia,rule); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_FAXALIAS,"Fax alias") ,MSG_U(I_FAXALIAS ,"You define an email alias") ,help_faxalias ,nof,MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); if (code == MENU_ESCAPE || code == MENU_CANCEL){ dia.restore(); break; }else if (code == MENU_DEL){ ret = 1; break; }else{ ret = 0; break; } } return ret; } PUBLIC FAXALIASES::FAXALIASES() { FILE_CFG *fin = f_aliases.fopen ("r"); if (fin != NULL){ char buf[300]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ strip_end (buf); if (buf[0] != '\0') add (new FAXALIAS(buf)); } fclose (fin); } } PUBLIC int FAXALIASES::write() { int ret = -1; FILE_CFG *fout = f_aliases.fopen (&privi,"w"); if (fout != NULL){ int n = getnb(); for (int i=0; ialias.get(),a->name.get() ,a->phone.get(),a->rule.get()); } ret = fclose (fout); } return ret; } PUBLIC FAXALIAS *FAXALIASES::getitem (int no) { return (FAXALIAS*)ARRAY::getitem (no); } static int cmp_by_alias (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { FAXALIAS *u1 = (FAXALIAS*)o1; FAXALIAS *u2 = (FAXALIAS*)o2; return u1->alias.cmp(u2->alias); } /* Return -1 if escape, 0 if edit ok 1 if the record must be deleted */ PUBLIC int FAXALIASES::edit() { int nof = 0; DIALOG_LISTE dia; dia.newf_head ("",MSG_U(H_ALIASES,"Alias\tName\tPhone\tRule")); while (1){ sort (cmp_by_alias); int n = getnb(); for (int i=0; iname.get() ,u->phone.get(),u->rule.get()); dia.set_menuitem(i,u->alias.get(),buf); } dia.remove_last (n+1); MENU_STATUS code = dia.editmenu ( MSG_U(T_FAXALIASES,"List of fax aliases") ,"" ,help_faxalias ,nof,MENUBUT_ADD); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (code == MENU_ADD){ FAXALIAS *u = new FAXALIAS; editone (u); }else{ editone (nof); } } return 0; } PUBLIC FAXUSER::FAXUSER(const char *buf) { char tb[3][100]; str_splitline (buf,':',tb,3); email.setfrom (tb[0]); name.setfrom (tb[1]); pgp.setfrom (tb[2]); } PUBLIC FAXUSER::FAXUSER() { } /* Return -1 if escape, 0 if edit ok (must save) and 1 if must delete */ PUBLIC int FAXUSER::edit() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_FAXUSERID,"User email address"),email); dia.newf_str (MSG_U(F_FAXUSERNAME,"User name"),name); dia.newf_str (MSG_U(F_FAXUSERPGP,"PGP public key (opt)"),pgp); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_FAXUSER,"Fax user") ,MSG_U(I_FAXUSER ,"You define the minimal information to\n" "setup a fax account for privilege user\n") ,help_faxuser ,nof,MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); if (code == MENU_ESCAPE || code == MENU_CANCEL){ dia.restore(); break; }else if (code == MENU_DEL){ ret = 1; break; }else{ ret = 0; break; } } return ret; } PUBLIC FAXUSERS::FAXUSERS() { FILE_CFG *fin = f_users.fopen ("r"); if (fin != NULL){ char buf[300]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ strip_end (buf); if (buf[0] != '\0') add (new FAXUSER(buf)); } fclose (fin); } } PUBLIC int FAXUSERS::write() { int ret = -1; FILE_CFG *fout = f_users.fopen (&privi,"w"); if (fout != NULL){ int n = getnb(); for (int i=0; iemail.get(),u->name.get() ,u->pgp.get()); } ret = fclose (fout); } return ret; } PUBLIC FAXUSER *FAXUSERS::getitem (int no) { return (FAXUSER*)ARRAY::getitem (no); } static int cmp_by_users (const ARRAY_OBJ *o1, const ARRAY_OBJ *o2) { FAXUSER *u1 = (FAXUSER*)o1; FAXUSER *u2 = (FAXUSER*)o2; return u1->name.cmp(u2->name); } PUBLIC int FAXUSERS::edit() { int nof = 0; DIALOG_LISTE dia; dia.newf_head ("",MSG_U(H_FAXUSERS,"Email\tName")); while (1){ sort (cmp_by_users); int n = getnb(); for (int i=0; iemail.get(),u->name.get()); } dia.remove_last (n+1); MENU_STATUS code = dia.editmenu ( MSG_U(T_FAXUSERS,"List of fax users") ,MSG_U(I_FAXUSERS ,"You can enter here the list of privileged\n" "users. They may fax from remote locate to some\n" "phone zone.") ,help_faxuser ,nof,MENUBUT_ADD); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (code == MENU_ADD){ FAXUSER *u = new FAXUSER; editone (u); }else{ editone (nof); } } return 0; } PUBLIC const char *FAXRULE::getid() { return id.get(); } PRIVATE void FAXRULE::init() { user = pgp = origin = 0; } PUBLIC FAXRULE::FAXRULE(CONFDB &db, const char *id) { init(); this->id.setfrom (id); user = db.getvalnum (id,K_ACCUSER,0); pgp = db.getvalnum (id,K_ACCPGP,0); origin = db.getvalnum (id,K_ACCORIGIN,0); db.getall (id,K_USER,users,1); } PUBLIC FAXRULE::FAXRULE() { init(); } PUBLIC void FAXRULE::write (CONFDB &db) { const char *pid = id.get(); db.replace (pid,K_ACCORIGIN,origin); db.replace (pid,K_ACCUSER,user); db.replace (pid,K_ACCPGP,pgp); db.replace (pid,K_USER,users); } PUBLIC FAXRULES::FAXRULES() { CONFDB db (f_rules); SSTRINGS ids; int n = db.getall (K_ID,K_INDEX,ids,0); for (int i=0; iget(); add (new FAXRULE(db,id)); } } PUBLIC int FAXRULES::write() { CONFDB db (f_rules); db.removeall (K_ID,K_INDEX); int n = getnb(); for (int i=0; iid); z->write (db); } return db.save(&privi); } PUBLIC FAXRULE *FAXRULES::getitem (int no) { return (FAXRULE*)ARRAY::getitem (no); } /* Return -1 if escape, 0 if accept changes, 1 if request deletion of the record */ PUBLIC int FAXRULE::edit() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_RULEID,"Rule id"),id); dia.last_noempty(); dia.newf_title ("",""); dia.newf_radio (MSG_U(F_ACCESSCTL,"Access control"),origin,0 ,MSG_U(F_ACCESSZONEUSERS,"Only rule's users accepted")); dia.newf_radio ("",origin,1 ,MSG_U(F_ACCESSUSERS,"All fax users accepted")); dia.newf_radio ("",origin,2 ,MSG_U(F_ACCESSLOCAL,"Local email only")); dia.newf_radio ("",origin,3 ,MSG_U(F_ACCESSANY,"email from anywhere")); dia.newf_title ("",""); dia.newf_radio (MSG_U(F_USERAUTH,"User authentification"),user,0 ,MSG_U(I_PRIVPGPUSER,"required PGP signature")); dia.newf_radio ("",user,1 ,MSG_U(I_PRIVUSER,"PGP optionnal")); dia.newf_title ("",MSG_U(T_USERS,"users allowed to fax")); // Add 3 empty field in the dialog int i; { int nbempty = 0; for (i=0; iis_empty()) nbempty ++; } for ( ; nbempty < 3; nbempty++) users.add (new SSTRING); } for (i=0; igetnb(); comb->addopt ("",""); for (int u=0; ugetitem(u); comb->addopt (user->email.get(),user->name.get()); } } int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_RULE,"One access rule") ,MSG_U(I_RULE ,"You can define one access rule which will be\n" "used to limit access to zone and fax aliases") ,help_faxrules ,nof,MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ if (xconf_areyousure(MSG_U(Q_DELRECORD,"Delete this record"))){ ret = 1; break; } }else{ ret = 0; break; } } users.remove_empty(); return ret; } PUBLIC int FAXRULES::edit() { int ret = 0; int nof=0; DIALOG_RECORDS dia; dia.newf_head ("",MSG_U(H_RULES,"Rule ID\tAccess\tUser list")); dia.addwhat (MSG_U(M_ADDRULE,"Select [Add] to define a new fax rule")); while (1){ for (int i=0; iorigin == 0){ accstr[0] = 'R'; }else if (z->origin == 1){ accstr[0] = 'U'; }else if (z->origin == 2){ accstr[0] = 'L'; } if (z->pgp) accstr[2] = 'P'; sprintf (buf," %s \t%s" ,accstr ,z->users.getnb() > 0 ? "..." : ""); dia.set_menuitem (i,z->id.get(),buf); } dia.remove_last (getnb()+1); MENU_STATUS code = dia.editmenu (MSG_U(T_RULES,"Fax rules") ,MSG_U(I_RULES ,"You can specify access rules needed to setup\n" "various fax zones and fax aliases") ,help_faxrules ,nof,0); if (code == MENU_ESCAPE || code == MENU_QUIT){ break; }else if (code == MENU_ADD){ FAXRULE *z = new FAXRULE; ret |= editone (z); }else{ ret |= editone (nof); } } return ret; } PRIVATE void FAXZONE::init() { len = 0; } PUBLIC FAXZONE::FAXZONE(const char *buf) { init(); char tb[4][100]; str_splitline (buf,':',tb,4); id.setfrom (tb[0]); zone.setfrom (tb[1]); len = atoi (tb[2]); rule.setfrom (tb[3]); } PUBLIC FAXZONE::FAXZONE() { init(); } PUBLIC FAXZONES::FAXZONES() { FILE_CFG *fin = f_zones.fopen ("r"); if (fin != NULL){ char buf[300]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ strip_end (buf); if (buf[0] != '\0') add (new FAXZONE(buf)); } fclose (fin); } } PUBLIC int FAXZONES::write() { int ret = -1; FILE_CFG *fout = f_zones.fopen (&privi,"w"); if (fout != NULL){ int n = getnb(); for (int i=0; iid.get(),u->zone.get() ,u->len,u->rule.get()); } ret = fclose (fout); } return ret; } PUBLIC FAXZONE *FAXZONES::getitem (int no) { return (FAXZONE*)ARRAY::getitem (no); } /* Return -1 if escape, 0 if accept changes, 1 if request deletion of the record */ PUBLIC int FAXZONE::edit() { int ret = -1; DIALOG dia; dia.newf_str (MSG_U(F_ZONEID,"Zone id"),id); dia.last_noempty(); dia.newf_str (MSG_U(F_ZONE,"Phone zone prefix"),zone); dia.newf_num (MSG_U(F_LEN,"phone number length"),len); mailfax_setrule (dia,rule); int nof = 0; while (1){ MENU_STATUS code = dia.edit (MSG_U(T_ZONE,"One fax zone") ,MSG_U(I_ZONE,"You can define the specification of one fax zone") ,help_faxzone ,nof,MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); if (code == MENU_CANCEL || code == MENU_ESCAPE){ break; }else if (code == MENU_DEL){ if (xconf_areyousure(MSG_R(Q_DELRECORD))){ ret = 1; break; } }else{ ret = 0; break; } } return ret; } PUBLIC int FAXZONES::edit() { int ret = 0; int nof=0; DIALOG_RECORDS dia; dia.newf_head ("",MSG_U(H_ZONES,"Zone ID\tZone prefix\tLen\tRule")); dia.addwhat (MSG_U(M_ADDZONE,"Select [Add] to define a new fax zone")); while (1){ for (int i=0; izone.get(),z->len,z->rule.get()); dia.set_menuitem (i,z->id.get(),buf); } dia.remove_last (getnb()+1); MENU_STATUS code = dia.editmenu (MSG_U(T_ZONES,"Fax zones") ,MSG_U(I_ZONES ,"You can specify which telephone zones are\n" "available for faxing.") ,help_faxzone ,nof,0); if (code == MENU_ESCAPE || code == MENU_QUIT){ break; }else if (code == MENU_ADD){ FAXZONE *z = new FAXZONE; ret |= editone (z); }else{ ret |= editone (nof); } } return ret; } PUBLIC MAILFAX::MAILFAX() { enable = linuxconf_getvalnum(K_MAILFAX,K_ENABLE,0); faxcmd.setfrom (linuxconf_getval(K_MAILFAX,K_FAXCMD)); log.setfrom (linuxconf_getval(K_MAILFAX,K_FAXLOG)); logcmd.setfrom (linuxconf_getval(K_MAILFAX,K_FAXLOGCMD)); } PUBLIC int MAILFAX::write() { linuxconf_setcursys (subsys_fax); linuxconf_replace (K_MAILFAX,K_ENABLE,enable); linuxconf_replace (K_MAILFAX,K_FAXCMD,faxcmd); linuxconf_replace (K_MAILFAX,K_FAXLOG,log); linuxconf_replace (K_MAILFAX,K_FAXLOGCMD,logcmd); return linuxconf_save(&privi); #if 0 int ret1 = users.write(); int ret2 = aliases.write(); int ret3 = zones.write(); return ret0 == -1 || ret1 == -1 || ret2 == -1 || ret3 == -3 ? -1 : 0; #endif } PUBLIC int MAILFAX::edit() { int ret = 0; DIALOG dia; dia.newf_chk (MSG_U(F_FAXGTW,"Mail to Fax gateway"),enable ,MSG_U(F_ENABLE,"is active")); FIELD_COMBO *comb = dia.newf_combo (MSG_U(F_FAXSPOOL,"Spool command") ,faxcmd); comb->addopt (USR_LIB_LINUXCONF "/lib/fax_to_mgetty+sendfax.sh",""); dia.newf_str (MSG_U(F_FAXLOG,"Log file"),log); dia.newf_str (MSG_U(F_FAXLOGC,"Log command"),logcmd); int nof = 0; if (dia.edit(MSG_U(T_MAILFAX,"Mail to Fax gateway configuration") ,MSG_U(I_MAILFAX ,"You can control the operation of the mail to fax\n" "gateway") ,help_faxbasic ,nof)==MENU_ACCEPT){ ret = 1; } return ret; } int mailfax_edit () { int ret = 0; int choice = 0; /* #Specification: /etc/fax / directory creation The directory /etc/fax is created on the fly by the module. */ if (file_type (ETC_FAX)!=1){ file_mkdir (ETC_FAX,0,0,0755,NULL); } static const char *basic = MSG_R(M_BASIC); static const char *rules = MSG_U(M_FAXRULES,"Fax access rules"); static const char *users = MSG_U(M_FAXUSERS,"Fax users"); static const char *zones = MSG_U(M_FAXZONES,"Fax zones"); static const char *aliases = MSG_U(M_FAXALIASES,"Fax aliases"); static const char *menuopt[]={ "", basic, "", rules, "", users, "", zones, "", aliases, NULL }; DIALOG_MENU dia; dia.new_menuitems(menuopt); while (1){ MENU_STATUS code = dia.editmenu ( MSG_R(T_MAILFAX) ,MSG_U(I_MAINMAILFAX ,"This menu let you configure how the gateway operates\n" "This controls who can fax, how and where") ,help_mailfax ,choice,0); if (code == MENU_QUIT || code == MENU_ESCAPE){ break; }else if (perm_access(&privi ,MSG_U(P_MAILFAX,"manage the mail to fax gateway"))){ MAILFAX mfax; const char *key = menuopt[choice*2+1]; ptrules = &mfax.rules; ptusers = &mfax.users; if (key == basic){ if (mfax.edit()){ mfax.write(); ret = 1; } }else if (key == rules){ mfax.rules.edit(); }else if (key == users){ mfax.users.edit(); }else if (key == zones){ mfax.zones.edit(); }else if (key == aliases){ mfax.aliases.edit(); } ptrules = NULL; ptusers = NULL; } } return ret; }