#pragma implementation #include #include #include #include #include #include #include #include #include #include #include "fetchmailconf.h" #include "fetchmailconf.m" #include "serveredit.h" #include "useridedit.h" static HELP_FILE help_userid ("fetchmailconf","users"); static PRIVILEGE p_userid ("fetchmailconf_userid" ,P_MSG_U(T_PRIVFETCHMAILUSERID,"Users") ,P_MSG_R(T_PRIVILEGE)); #define THIS_SERVER_NO 0 #define THIS_SERVER_YES 1 #define THIS_SERVER_DONE 2 /* * USERID */ PRIVATE void USERID::init() { //fprintf(stderr,"USERID::init\n"); local_user.setfrom( "" ); remote_user.setfrom( "" ); old_remote_user.setfrom( "" ); password.setfrom( "" ); fetchall = 0; keep = 0; flush = 0; limit = 0; warnings = 0; batchlimit = 0; fetchlimit = 0; stripcr = 0; forcecr = 0; pass8bits = 1; mimedecode = 1; rewrite = 1; dropstatus = 0; } PUBLIC USERID::USERID(const char *_remote_user) { //fprintf(stderr,"USERID::USERID _remote_user=%s\n", _remote_user); remote_user.setfrom (_remote_user); init(); } PUBLIC USERID::USERID( ) { //fprintf(stderr,"USERID::USERID\n"); init(); } PUBLIC int USERID::write( int button ) { //fprintf(stderr,"USERID::write\n"); int ret = -1; if ( ! perm_access( &p_userid, MSG_U(P_EDITUSERS, "change user configuration") ) ) { return( ret ); } VIEWITEMS items; items.read( *f_config_file ); // Read current version of config file FILE_CFG *fout = f_config_file->fopen (&p_userid,"w"); if ( fout == NULL ) return( ret ); char thisServer = false; char thisUser = false; char word[WORD]; KEYWORD *null = NULL; KEYWORD *keyword; KEYWORDLIST keywordlist; for ( int i=0; iline.get()); keywordlist.clean_option( ); keyword = keywordlist.option( word, item->line.get(), WORD ); if ( keyword == null ) { if ( ! thisServer && ! thisUser ) { //fprintf(stderr,"USERID::write: (null) write_item: %s\n", item->line.get()); write_item(fout,items,item,false); } continue; } //fprintf(stderr,"USERID::write:keyword->id=%d keyword->word=%s: %s %s %s\n", keyword->id,keyword->word.get(), word, thisServer?"":"", thisUser?"":""); switch ( keyword->id ) { case KEY_POLL: case KEY_SKIP: thisUser = false; if ( thisServer ) { if ( new_userid && button != MENU_DEL) { write_userid( fout ); new_userid = 0; } thisServer = false; break; } if ( strcmp( server->server_name.get(), word ) == 0 ) { thisServer = true; } break; case KEY_USERNAME: if ( thisUser ) { thisUser = false; break; } if ( ! thisServer ) { break; } if ( strcmp( remote_user.get(), word ) == 0 ) { thisUser = true; if ( button == MENU_ACCEPT ) { //comment_write (item->comment,fout); write_item(fout,items,item,true); write_userid( fout ); } } break; } if ( ! thisUser ) { write_item(fout,items,item,false); } } if ( new_userid && button != MENU_DEL) { write_userid( fout ); new_userid = 0; } keywordlist.clean_option( ); ret = fclose( fout ); return( ret ); } PUBLIC void USERID::write_item( FILE_CFG *fout, const VIEWITEMS &items, VIEWITEM *item, bool comments_only) { int virtpos = items.lookup(item); int realpos = items.lookup(item,-1); int prev_item = items.realpos(virtpos-1,VIEWITEM_VARIABLE); int next_item = items.realpos(virtpos+1,VIEWITEM_VARIABLE); if (prev_item == -1){ prev_item = 0; }else{ prev_item++; } if (next_item == -1){ next_item = items.getnb(); }else{ next_item--; } // Print comments before this item for (int i = prev_item; i < realpos; i++){ fprintf(fout, "%s\n", items.getitem(i,-1)->line.get()); } if (!comments_only){ // Print the item and... fprintf(fout, "%s\n", item->line.get()); // ...comments after it, if this is the last item for (int i = realpos+1; iline.get()); } } } /** * Write this userid entry */ PUBLIC int USERID::write_userid( FILE_CFG *fout ) { char word[WORD]; SSTRING line; int data = 0; fprintf( fout, "\tuser \"%s\" there", remote_user.get() ); if (! password.is_empty()) { fprintf( fout, " with password \"%s\"", password.get() ); } if ( local_user.is_empty()) local_user.setfrom( remote_user ); fprintf( fout, " is %s here\n", local_user.get() ); if (! folder.is_empty()) { sprintf( word, "folder %s ", folder.get() ); print_line( word, fout ); data++; } if (! smtphost.is_empty()) { sprintf( word, "smtphost %s ", smtphost.get() ); print_line( word, fout ); data++; } if (! smtpaddress.is_empty()) { sprintf( word, "smtpaddress %s ", smtpaddress.get() ); print_line( word, fout ); data++; } if (! mda.is_empty()) { sprintf( word, "mda %s ", mda.get() ); print_line( word, fout ); data++; } if ( data ) { print_line( "\n", fout ); data = 0; } sprintf( word, "with options " ); print_line( word, fout ); if ( keep ) { sprintf( word, "keep " ); print_line( word, fout ); } if ( rewrite ) { sprintf( word, "rewrite " ); print_line( word, fout ); } if ( mimedecode ) { sprintf( word, "mimedecode " ); print_line( word, fout ); } if ( flush ) { sprintf( word, "flush " ); print_line( word, fout ); } if ( fetchall ) { sprintf( word, "fetchall " ); print_line( word, fout ); } if ( forcecr ) { sprintf( word, "forcecr " ); print_line( word, fout ); } if ( stripcr ) { sprintf( word, "stripcr " ); print_line( word, fout ); } if ( pass8bits ) { sprintf( word, "pass8bits " ); print_line( word, fout ); } if ( dropstatus ) { sprintf( word, "dropstatus " ); print_line( word, fout ); } if ( limit ) { sprintf( word, "limit %d ", limit ); print_line( word, fout ); } if ( warnings ) { sprintf( word, "warnings %d ", warnings ); print_line( word, fout ); } if ( fetchlimit ) { sprintf( word, "fetchlimit %d ", fetchlimit ); print_line( word, fout ); } if ( batchlimit ) { sprintf( word, "batchlimit %d ", batchlimit ); print_line( word, fout ); } print_line( "\n", fout ); return( 0 ); } PUBLIC void USERID::print_line( char *word, FILE_CFG *fout ) { static SSTRING line; if ( word[0] == '\n' ) { fprintf( fout, "\t\t%s\n", line.get() ); line.setfrom( "" ); } else { line.append( word ); if ( line.getlen() > 50 ) { fprintf( fout, "\t\t%s\n", line.get() ); line.setfrom( "" ); } } } /** * Edit userid entry */ PUBLIC int USERID::edit() { //fprintf(stderr,"USERID::edit\n"); int ret = 0; if ( ! perm_access( &p_userid, MSG_U(P_SEEUSERS, "see user configuration") ) ) { return( ret ); } DIALOG dia; if ( new_userid ) dia.newf_str (MSG_U(F_REMOTEUSER,"Remote user name"),remote_user); else dia.newf_info (MSG_R(F_REMOTEUSER),remote_user.get()); dia.newf_str (MSG_U(F_USERPASSWORD,"Remote user password"),password); dia.newf_str (MSG_U(F_LOCALUSER,"Local user name(s)"),local_user); dia.newf_title ("",MSG_R(T_OPTIONAL)); dia.newf_title (MSG_U(T_FETCH,"Fetch"),1,"",MSG_R(T_FETCH)); dia.newf_title (MSG_U(T_FETCHHOW,"How"),2,"",MSG_R(T_FETCHHOW)); dia.newf_chk ("",fetchall,MSG_U(F_FETCHALL, "Fetch all messages")); dia.newf_chk ("",keep,MSG_U(F_KEEP, "Don't delete messages from server")); dia.newf_chk ("",flush,MSG_U(F_FLUSH, "Flush all seen messages first")); dia.newf_title (MSG_U(T_FETCHWHERE,"Where"),2,"",MSG_R(T_FETCHWHERE)); dia.newf_str (MSG_U(F_FOLDER,"Remote mailbox name(s)"),folder); dia.newf_title (MSG_U(T_FETCHLIMITS,"Limits"),2,"",MSG_R(T_FETCHLIMITS)); dia.newf_num (MSG_U(F_LIMIT,"Max message size limit"),limit); dia.newf_num (MSG_U(F_WARNINGS,"Size warning interval (seconds)"),warnings); dia.newf_num (MSG_U(F_FETCHLIMIT,"Max messages per session"),fetchlimit); dia.newf_title (MSG_U(T_MODIFY,"Modify"),1,"",MSG_R(T_MODIFY)); dia.newf_chk ("",stripcr,MSG_U(F_STRIPCR, "Strip carriage returns")); dia.newf_chk ("",forcecr,MSG_U(F_FORCECR, "Force carriage returns")); dia.newf_chk ("",pass8bits,MSG_U(F_PASS8BITS, "Force BODY=8BITMIME")); dia.newf_chk ("",mimedecode,MSG_U(F_MIMEDECODE, "Quoted-printable to 8-bit")); dia.newf_chk ("",rewrite,MSG_U(F_REWRITE, "Rewrite destination addresses")); dia.newf_chk ("",dropstatus,MSG_U(F_DROPSTATUS, "Strip Status")); dia.newf_title (MSG_U(T_DELIVERY,"Delivery"),1,"",MSG_R(T_DELIVERY)); dia.newf_title (MSG_U(T_DELIVERY_GENERAL,"General"),2,"",MSG_R(T_DELIVERY_GENERAL)); dia.newf_num (MSG_U(F_BATCHLIMIT,"Max messages per session"),batchlimit); dia.newf_title (MSG_U(T_DELIVERY_REMOTE,"Remote"),2,"",MSG_R(T_DELIVERY_REMOTE)); dia.newf_title (MSG_U(T_DELIVERYTITLE,"Final destination"),"-"); dia.newf_str (MSG_U(F_SMTPHOST,"Forward to other host(s)"),smtphost); dia.newf_str (MSG_U(F_SMTPADDRESS,"Different domain (RCPT TO)"),smtpaddress); dia.newf_str (MSG_U(F_MDA,"Local mail delivery agent"),mda); int buttons; if ( new_userid ) buttons = ( MENUBUT_CANCEL|MENUBUT_ACCEPT); else buttons = ( MENUBUT_DEL|MENUBUT_CANCEL|MENUBUT_ACCEPT); int nof = 0; while (1){ MENU_STATUS code = dia.edit( MSG_U(T_USERID,"Remote user mail retreival") ,MSG_U(I_USERID, "This is where you enter the name and password of\n" "a user to fetch mail from a remote mail server.\n" ) ,help_userid ,nof ,buttons); if (code == MENU_CANCEL || code == MENU_ESCAPE){ ret = -1; break; }else if (code == MENU_DEL){ if ( xconf_delok() ) { write( MENU_DEL ); ret = 1; break; } }else if (code == MENU_ACCEPT){ if ( input_error( ) ) continue; write ( MENU_ACCEPT ); ret = 0; break; } } return ret; } PUBLIC bool USERID::input_error() { if ( remote_user.is_empty() ) { xconf_error(MSG_U(E_REMOTEUSERNAME, "Remote user name in mail\n" "server must be supplied")); return( true ); } return( false ); } PUBLIC USERID *USERIDLIST::getitem (int no) const { return (USERID*)ARRAY::getitem (no); } PUBLIC USERID *USERIDLIST::getitem (const char *local_user) const { USERID *ret = NULL; int n = getnb(); for (int i=0; ilocal_user.cmp(local_user)==0){ ret = userid; break; } } return ret; } /** * USERIDLIST */ PUBLIC USERIDLIST::USERIDLIST( ) { //fprintf(stderr,"USERIDLIST::USERIDLIST\n"); } /** * Read config file and parse userids */ PUBLIC void USERIDLIST::read( SERVER *server ) { //fprintf(stderr,"USERIDLIST::read server=%s\n", server->server_name.get()); SSTRING string; VIEWITEMS items; items.read( *f_config_file ); // Read config file for ( int i=0; iline.get() ); // Concatenate all lines string.append( " " ); // with spaces } KEYWORD *null = NULL; KEYWORD *keyword; KEYWORDLIST keywordlist; const char *config = string.get(); char word[WORD]; char thisServer = THIS_SERVER_NO; while ( 1 ) { keyword = keywordlist.option( word, config, WORD ); if ( keyword == null ) break; //fprintf(stderr,"read:keyword->id=%d keyword->word=%s: %s %s\n", keyword->id,keyword->word.get(), word, keyword->value?"":""); switch ( keyword->id ) { case KEY_POLL: case KEY_SKIP: if ( strcmp( server->server_name.get(), word ) == 0 ) { thisServer = THIS_SERVER_YES; } break; case KEY_USERNAME: if ( thisServer == THIS_SERVER_YES ) { read_users( &keywordlist, keyword, word, server ); thisServer = THIS_SERVER_DONE; } break; } if ( thisServer == THIS_SERVER_DONE ) { break; } } keywordlist.clean_option( ); } // From "man fetchmail": // The words `here' and `there' have useful English-like significance. // Normally `user eric is esr' would mean that mail for the remote user // `eric' is to be delivered to `esr', but you can make this clearer by // saying `user eric there is esr here', or reverse it by saying `user // esr here is eric there' PUBLIC void USERIDLIST::read_users( KEYWORDLIST *keywordlist, KEYWORD *keyword, char *word, SERVER *server ) { KEYWORD *null = NULL; USERID *userid = NULL; bool add_userid = true; bool key_here = false; while ( 1 ) { switch ( keyword->id ) { case KEY_POLL: case KEY_SKIP: return; case KEY_USERNAME: key_here = false; if ( add_userid ) { userid = new USERID( ); add( userid ); userid->remote_user.setfrom( word ); add_userid = false; } else { userid->remote_user.append( " " ); userid->remote_user.append( word ); } break; case KEY_THERE: break; case KEY_HERE: key_here = true; break; case KEY_IS: if ( key_here ) { /* * Do the switch */ userid->local_user.setfrom( userid->remote_user ); userid->remote_user.setfrom( word ); } else { if ( userid->local_user.is_empty() ) userid->local_user.setfrom( word ); else { userid->local_user.append( " " ); userid->local_user.append( word ); } } add_userid = true; break; case KEY_PASSWORD: userid->password.setfrom( word ); break; case KEY_FOLDER: if ( userid->folder.is_empty() ) userid->folder.setfrom( word ); else { userid->folder.append( " " ); userid->folder.append( word ); } break; case KEY_SMTPHOST: if ( userid->smtphost.is_empty() ) userid->smtphost.setfrom( word ); else { userid->smtphost.append( " " ); userid->smtphost.append( word ); } break; case KEY_SMTPADDRESS: userid->smtpaddress.setfrom( word ); break; case KEY_MDA: userid->mda.setfrom( word ); break; case KEY_KEEP: userid->keep = keyword->value; break; case KEY_FLUSH: userid->flush = keyword->value; break; case KEY_FETCHALL: userid->fetchall = keyword->value; break; case KEY_REWRITE: userid->rewrite = keyword->value; break; case KEY_STRIPCR: userid->stripcr = keyword->value; break; case KEY_FORCECR: userid->forcecr = keyword->value; break; case KEY_PASS8BITS: userid->pass8bits = keyword->value; break; case KEY_DROPSTATUS: userid->dropstatus = keyword->value; break; case KEY_MIMEDECODE: userid->mimedecode = keyword->value; break; case KEY_LIMIT: userid->limit = atoi( word ); break; case KEY_WARNINGS: userid->warnings = atoi( word ); break; case KEY_BATCHLIMIT: userid->batchlimit = atoi( word ); break; case KEY_FETCHLIMIT: userid->fetchlimit = atoi( word ); break; } if ( (keyword = keywordlist->option( word, NULL, WORD)) == null ) { return; } //fprintf(stderr,"read_users:keyword->id=%d keyword->word=%s: %s %s\n", keyword->id,keyword->word.get(), word, keyword->value?"":""); } return; } /** * Edit useridlist */ PUBLIC int USERIDLIST::edit( SERVER *server ) { //fprintf(stderr,"USERIDLIST::edit\n"); DIALOG_LISTE *dia = NULL; int nof = 0; while (1) { if (dia == NULL) { dia = new DIALOG_LISTE; dia->newf_head ("",MSG_U(H_USERID,"Remote user\tLocal user")); for (int i=0; inew_menuitem (userid->remote_user, userid->local_user); } dia->addwhat (MSG_U(I_ADDUSERID,"Select [Add] to add a new user")); } MENU_STATUS code = dia->editmenu (MSG_U(T_USERIDLIST,"Mail user list") ,MSG_U(I_USERIDLIST, "This is the list of all configured mail users\n" "on this mail server.\n" ) ,help_userid ,nof,0); bool mustdelete=false; if (code == MENU_QUIT || code == MENU_ESCAPE) { break; } else if (code == MENU_ADD) { USERID *userid = new USERID; userid->new_userid = true; userid->server = server; if ( editone(userid) != -1 ) mustdelete = true; } else { USERID *userid = getitem( nof ); userid->new_userid = false; userid->server = server; if ( editone(nof) != -1 ) mustdelete = true; } if (mustdelete){ delete dia; dia = NULL; } } delete dia; return 0; }