diff --git a/src/sbbs3/atcodes.cpp b/src/sbbs3/atcodes.cpp index 06ff5b7939b201ae757a4aa2cf6fea6616e146f6..52aa402e7c3f8e9ddf1462d59144a724fb123586 100644 --- a/src/sbbs3/atcodes.cpp +++ b/src/sbbs3/atcodes.cpp @@ -996,18 +996,23 @@ const char* sbbs_t::atcode(char* sp, char* str, size_t maxlen) if(!strcmp(sp,"MSG_TIMEZONE") && current_msg!=NULL) return(smb_zonestr(current_msg->hdr.when_written.zone,NULL)); if(!strcmp(sp,"MSG_ATTR") && current_msg!=NULL) { - safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s%s%s%s%s" - ,current_msg->hdr.attr&MSG_PRIVATE ? "Private " :nulstr - ,current_msg->hdr.attr&MSG_READ ? "Read " :nulstr - ,current_msg->hdr.attr&MSG_DELETE ? "Deleted " :nulstr - ,current_msg->hdr.attr&MSG_KILLREAD ? "Kill " :nulstr - ,current_msg->hdr.attr&MSG_ANONYMOUS ? "Anonymous " :nulstr - ,current_msg->hdr.attr&MSG_LOCKED ? "Locked " :nulstr - ,current_msg->hdr.attr&MSG_PERMANENT ? "Permanent " :nulstr - ,current_msg->hdr.attr&MSG_MODERATED ? "Moderated " :nulstr - ,current_msg->hdr.attr&MSG_VALIDATED ? "Validated " :nulstr - ,current_msg->hdr.attr&MSG_REPLIED ? "Replied " :nulstr - ,current_msg->hdr.attr&MSG_NOREPLY ? "NoReply " :nulstr + uint16_t attr = current_msg->hdr.attr; + uint16_t poll = attr&MSG_POLL_VOTE_MASK; + uint32_t auxattr = current_msg->hdr.auxattr; + safe_snprintf(str,maxlen,"%s%s%s%s%s%s%s%s%s%s%s%s%s" + ,attr&MSG_PRIVATE ? "Private " :nulstr + ,attr&MSG_READ ? "Read " :nulstr + ,attr&MSG_DELETE ? "Deleted " :nulstr + ,attr&MSG_KILLREAD ? "Kill " :nulstr + ,attr&MSG_ANONYMOUS ? "Anonymous " :nulstr + ,attr&MSG_LOCKED ? "Locked " :nulstr + ,attr&MSG_PERMANENT ? "Permanent " :nulstr + ,attr&MSG_MODERATED ? "Moderated " :nulstr + ,attr&MSG_VALIDATED ? "Validated " :nulstr + ,attr&MSG_REPLIED ? "Replied " :nulstr + ,attr&MSG_NOREPLY ? "NoReply " :nulstr + ,poll == MSG_POLL ? "Poll " :nulstr + ,poll == MSG_POLL && auxattr&POLL_CLOSED ? "(Closed) " :nulstr ); return(str); } diff --git a/src/sbbs3/getmsg.cpp b/src/sbbs3/getmsg.cpp index d75049c496a5b3de49b9e14d9a927083022f6bc1..ee626cb2bcc06f0407f774c10ef630a7c1566c49 100644 --- a/src/sbbs3/getmsg.cpp +++ b/src/sbbs3/getmsg.cpp @@ -88,8 +88,11 @@ int sbbs_t::loadmsg(smbmsg_t *msg, ulong number) } -void sbbs_t::show_msgattr(ushort attr) +void sbbs_t::show_msgattr(smbmsg_t* msg) { + uint16_t attr = msg->hdr.attr; + uint16_t poll = attr&MSG_POLL_VOTE_MASK; + uint32_t auxattr = msg->hdr.auxattr; bprintf(text[MsgAttr] ,attr&MSG_PRIVATE ? "Private " :nulstr @@ -103,7 +106,8 @@ void sbbs_t::show_msgattr(ushort attr) ,attr&MSG_VALIDATED ? "Validated " :nulstr ,attr&MSG_REPLIED ? "Replied " :nulstr ,attr&MSG_NOREPLY ? "NoReply " :nulstr - ,attr&MSG_POLL ? "Poll " :nulstr + ,poll == MSG_POLL ? "Poll " :nulstr + ,poll == MSG_POLL && auxattr&POLL_CLOSED ? "(Closed) " :nulstr ,nulstr ,nulstr ,nulstr @@ -135,7 +139,7 @@ void sbbs_t::show_msghdr(smbmsg_t* msg) bprintf(text[MsgSubj],msg->subj); if(msg->hdr.attr) - show_msgattr(msg->hdr.attr); + show_msgattr(msg); if(msg->to && *msg->to) { bprintf(text[MsgTo],msg->to); if(msg->to_net.addr!=NULL) @@ -186,7 +190,7 @@ void sbbs_t::show_msg(smbmsg_t* msg, long mode, post_t* post) show_msghdr(msg); - if(msg->hdr.type == SMB_MSG_TYPE_POLL && post != NULL) { + if(msg->hdr.type == SMB_MSG_TYPE_POLL && post != NULL && smb.subnum < cfg.total_subs) { char* answer; int longest_answer = 0; uint16_t votes = smb_voted_already(&smb, msg->hdr.number @@ -222,7 +226,16 @@ void sbbs_t::show_msg(smbmsg_t* msg, long mode, post_t* post) else if(width > cols-20) width = cols-20; bprintf(text[PollAnswerNumber], answers+1); - if(votes || sub_op(smb.subnum)) { + bool results_visible = false; + if((msg->hdr.auxattr&POLL_RESULTS_MASK) == POLL_RESULTS_OPEN) + results_visible = true; + else if(smb_msg_is_from(msg, cfg.sub[smb.subnum]->misc&SUB_NAME ? useron.name : useron.alias, NET_NONE, NULL)) + results_visible = true; + else if((msg->hdr.auxattr&POLL_RESULTS_MASK) == POLL_RESULTS_CLOSED) + results_visible = (msg->hdr.auxattr&POLL_CLOSED) ? true : false; + else if((msg->hdr.auxattr&POLL_RESULTS_MASK) != POLL_RESULTS_SECRET) + results_visible = votes ? true : false; + if(results_visible) { safe_snprintf(str, sizeof(str), text[PollAnswerFmt] ,width, width, answer, post->votes[answers], pct); backfill(str, pct); @@ -235,6 +248,8 @@ void sbbs_t::show_msg(smbmsg_t* msg, long mode, post_t* post) CRLF; answers++; } + if(!votes && !(useron.misc&EXPERT) && !(msg->hdr.auxattr&POLL_CLOSED) && !(useron.rest&FLAG('V'))) + mnemonics("\r\nTo vote in this poll, hit ~V now.\r\n"); return; } if((txt=smb_getmsgtxt(&smb,msg,(console&CON_RAW_IN) ? 0:GETMSGTXT_PLAIN)) != NULL) { diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c index 3a6ca1f950d445a0664186f20189e13fd7794431..dbeeb5167882e5080e66f4a50287c17836f5515c 100644 --- a/src/sbbs3/mailsrvr.c +++ b/src/sbbs3/mailsrvr.c @@ -4425,7 +4425,7 @@ BOOL bounce(SOCKET sock, smb_t* smb, smbmsg_t* msg, char* err, BOOL immediate) strcpy(str,"Reason:"); smb_hfield_str(&newmsg, SMB_COMMENT, str); smb_hfield_str(&newmsg, SMB_COMMENT, err); - smb_hfield_str(&newmsg, SMB_COMMENT, "\r\nOriginal message text follows:\r\n"); + smb_hfield_str(&newmsg, SMB_COMMENT, "\r\nOriginal message text follows:"); if((i=smb_addmsghdr(smb,&newmsg,SMB_SELFPACK))!=SMB_SUCCESS) lprintf(LOG_ERR,"%04d !BOUNCE ERROR %d (%s) adding message header" diff --git a/src/sbbs3/msgtoqwk.cpp b/src/sbbs3/msgtoqwk.cpp index 4bb03e8ca3d417e6ddd14b698c9520419b500ee0..a9a336f645071e9222411316c51d38cc40474cff 100644 --- a/src/sbbs3/msgtoqwk.cpp +++ b/src/sbbs3/msgtoqwk.cpp @@ -58,32 +58,43 @@ ulong sbbs_t::msgtoqwk(smbmsg_t* msg, FILE *qwk_fp, long mode, uint subnum get_msgid(&cfg, subnum, msg, msgid, sizeof(msgid)); - if(msg->hdr.type == SMB_MSG_TYPE_POLL || msg->hdr.type == SMB_MSG_TYPE_BALLOT) { + if(msg->hdr.type != SMB_MSG_TYPE_NORMAL) { if(voting == NULL) return 0; - if(msg->hdr.type == SMB_MSG_TYPE_BALLOT) { + switch(msg->hdr.type) { + case SMB_MSG_TYPE_BALLOT: fprintf(voting, "[vote:%s]\n", msgid); - if((p = msg->reply_id) != NULL) - fprintf(voting, "%s: %s\n", smb_hfieldtype(RFC822REPLYID), p); if((msg->hdr.attr&MSG_VOTE) == MSG_VOTE) fprintf(voting, "Votes = 0x%hx\n", msg->hdr.votes); else fprintf(voting, "%sVote = true\n", msg->hdr.attr&MSG_UPVOTE ? "Up" : "Down"); - } else { + break; + case SMB_MSG_TYPE_POLL: + { + unsigned comments = 0; + unsigned answers = 0; fprintf(voting, "[poll:%s]\n", msgid); if(msg->hdr.votes) fprintf(voting, "MaxVotes = %hd\n", msg->hdr.votes); - unsigned comments = 0; - unsigned answers = 0; + if(msg->hdr.auxattr&POLL_RESULTS_MASK) + fprintf(voting , "Results = %u\n", (msg->hdr.auxattr&POLL_RESULTS_MASK) >> POLL_RESULTS_SHIFT); for(i=0; i < msg->total_hfields; i++) { if(msg->hfield[i].type == SMB_COMMENT) fprintf(voting, "%s%u = %s\n", smb_hfieldtype(msg->hfield[i].type), comments++, (char*)msg->hfield_dat[i]); else if(msg->hfield[i].type == SMB_POLL_ANSWER) fprintf(voting, "%s%u = %s\n", smb_hfieldtype(msg->hfield[i].type), answers++, (char*)msg->hfield_dat[i]); } + break; + } + case SMB_MSG_TYPE_POLL_CLOSURE: + fprintf(voting, "[close:%s]\n", msgid); + break; } if(msg->subj && *msg->subj) fprintf(voting, "%s: %s\n",smb_hfieldtype(SUBJECT), msg->subj); + if(msg->reply_id) + fprintf(voting, "%s: %s\n", smb_hfieldtype(RFC822REPLYID), msg->reply_id); + /* SENDER */ fprintf(voting, "%s: %s\n", smb_hfieldtype(SENDER), msg->from); if(msg->from_net.type) diff --git a/src/sbbs3/postmsg.cpp b/src/sbbs3/postmsg.cpp index 23913932a7e655402fd977c97a2db647876f243f..37898aaebce9f6b0440d35725e986d4b878ad99c 100644 --- a/src/sbbs3/postmsg.cpp +++ b/src/sbbs3/postmsg.cpp @@ -565,40 +565,60 @@ extern "C" int DLLCALL votemsg(scfg_t* cfg, smb_t* smb, smbmsg_t* msg, const cha /* Look-up thread_back if RFC822 Reply-ID was specified */ if(msg->hdr.thread_back == 0 && msg->reply_id != NULL) { if(smb_getmsgidx_by_msgid(smb, &remsg, msg->reply_id) == SMB_SUCCESS) - msg->hdr.thread_back = remsg.idx.number; /* needed for threading backward */ + msg->hdr.thread_back = remsg.idx.number; /* poll or message being voted on */ } if(smb_voted_already(smb, msg->hdr.thread_back, msg->from, (enum smb_net_type)msg->from_net.type, msg->from_net.addr)) return SMB_DUPE_MSG; - result = smb_addvote(smb, msg, smb_storage_mode(cfg, smb)); - if(result == SMB_SUCCESS && smsgfmt != NULL) { - remsg.hdr.number = msg->hdr.thread_back; - if(smb_getmsgidx(smb, &remsg) == SMB_SUCCESS - && smb_getmsghdr(smb, &remsg) == SMB_SUCCESS) { - if(remsg.from_ext != NULL) { - user_t user; - ZERO_VAR(user); - user.number = atoi(remsg.from_ext); - if(getuserdat(cfg, &user) == 0 && - (stricmp(remsg.from, user.alias) == 0 || stricmp(remsg.from, user.name) == 0)) { - char from[256]; - char tstr[128]; - char smsg[256]; - if(msg->from_net.type) - safe_snprintf(from, sizeof(from), "%s (%s)", msg->from, smb_netaddr(&msg->from_net)); - else - SAFECOPY(from, msg->from); - safe_snprintf(smsg, sizeof(smsg), smsgfmt - ,timestr(cfg, msg->hdr.when_written.time, tstr) - ,cfg->grp[cfg->sub[smb->subnum]->grp]->sname - ,cfg->sub[smb->subnum]->sname - ,from - ,remsg.subj); - putsmsg(cfg, user.number, smsg); - } - } - smb_freemsgmem(&remsg); + remsg.hdr.number = msg->hdr.thread_back; + if((result = smb_getmsgidx(smb, &remsg)) != SMB_SUCCESS) + return result; + if((result = smb_getmsghdr(smb, &remsg)) != SMB_SUCCESS) + return result; + if(remsg.hdr.auxattr&POLL_CLOSED) + result = SMB_CLOSED; + else + result = smb_addvote(smb, msg, smb_storage_mode(cfg, smb)); + if(result == SMB_SUCCESS && smsgfmt != NULL && remsg.from_ext != NULL) { + user_t user; + ZERO_VAR(user); + user.number = atoi(remsg.from_ext); + if(getuserdat(cfg, &user) == 0 && + (stricmp(remsg.from, user.alias) == 0 || stricmp(remsg.from, user.name) == 0)) { + char from[256]; + char tstr[128]; + char smsg[256]; + if(msg->from_net.type) + safe_snprintf(from, sizeof(from), "%s (%s)", msg->from, smb_netaddr(&msg->from_net)); + else + SAFECOPY(from, msg->from); + safe_snprintf(smsg, sizeof(smsg), smsgfmt + ,timestr(cfg, msg->hdr.when_written.time, tstr) + ,cfg->grp[cfg->sub[smb->subnum]->grp]->sname + ,cfg->sub[smb->subnum]->sname + ,from + ,remsg.subj); + putsmsg(cfg, user.number, smsg); } } + smb_freemsgmem(&remsg); + return result; +} + +extern "C" int DLLCALL closepoll(scfg_t* cfg, smb_t* smb, uint32_t msgnum, const char* username) +{ + int result; + smbmsg_t msg; + + ZERO_VAR(msg); + + msg.hdr.when_imported.time = time32(NULL); + msg.hdr.when_imported.zone = sys_timezone(cfg); + msg.hdr.when_written = msg.hdr.when_imported; + msg.hdr.thread_back = msgnum; + smb_hfield_str(&msg, SENDER, username); + result = smb_addpollclosure(smb, &msg, smb_storage_mode(cfg, smb)); + + smb_freemsgmem(&msg); return result; -} \ No newline at end of file +} diff --git a/src/sbbs3/qwk.cpp b/src/sbbs3/qwk.cpp index 3589b83b3d9af996beab40350570296fda50202e..a9747cc0f635f1f9b3373f784cad6364761c785d 100644 --- a/src/sbbs3/qwk.cpp +++ b/src/sbbs3/qwk.cpp @@ -1002,12 +1002,57 @@ int sbbs_t::set_qwk_flag(ulong flag) return putuserrec(&cfg,useron.number,U_QWK,8,ultoa(useron.qwk,str,16)); } +static void parse_common_header_fields(str_list_t ini, const char* section, smbmsg_t* msg, smb_net_type_t net_type, const char* qnet_id) +{ + char* p; + char zone[32]; + + if((p=iniGetString(ini, section, "WhenWritten", NULL, NULL)) != NULL) { + xpDateTime_t dt=isoDateTimeStr_parse(p); + msg->hdr.when_written.time=(uint32_t)xpDateTime_to_localtime(dt); + msg->hdr.when_written.zone=dt.zone; + sscanf(p,"%*s %s",zone); + if(zone[0]) + msg->hdr.when_written.zone=(ushort)strtoul(zone,NULL,16); + } + + if((p=iniGetString(ini, section, smb_hfieldtype(SENDER), NULL, NULL)) != NULL) + smb_hfield_str(msg, SENDER, p); + + if(net_type == NET_QWK) { + char fulladdr[256]; + const char* netaddr = iniGetString(ini, section, smb_hfieldtype(SENDERNETADDR), NULL, NULL); + if(netaddr == NULL) + netaddr = qnet_id; + else { + SAFEPRINTF2(fulladdr, "%s/%s", qnet_id, netaddr); + netaddr = fulladdr; + } + if(netaddr != NULL) { + smb_hfield_netaddr(msg, SENDERNETADDR, netaddr, &net_type); + smb_hfield(msg, SENDERNETTYPE, sizeof(net_type), &net_type); + } + } + + if((p=iniGetString(ini, section, smb_hfieldtype(RFC822REPLYID), NULL, NULL)) != NULL) + smb_hfield_str(msg, RFC822REPLYID, p); + + /* Trace header fields */ + while((p=iniGetString(ini, section, smb_hfieldtype(SENDERIPADDR), NULL, NULL)) != NULL) + smb_hfield_str(msg, SENDERIPADDR, p); + while((p=iniGetString(ini, section, smb_hfieldtype(SENDERHOSTNAME), NULL, NULL)) != NULL) + smb_hfield_str(msg, SENDERHOSTNAME, p); + while((p=iniGetString(ini, section, smb_hfieldtype(SENDERPROTOCOL), NULL, NULL)) != NULL) + smb_hfield_str(msg, SENDERPROTOCOL, p); + while((p=iniGetString(ini,section, smb_hfieldtype(SENDERORG), NULL, NULL)) != NULL) + smb_hfield_str(msg, SENDERORG, p); +} + bool sbbs_t::qwk_voting(const char* fname, smb_net_type_t net_type, const char* qnet_id) { FILE *fp; str_list_t ini; - str_list_t poll_list; - str_list_t ballot_list; + str_list_t list; if((fp=fopen(fname,"r")) == NULL) { errormsg(WHERE, ERR_OPEN, fname, 0); @@ -1016,31 +1061,32 @@ bool sbbs_t::qwk_voting(const char* fname, smb_net_type_t net_type, const char* ini = iniReadFile(fp); fclose(fp); - if((poll_list = iniGetSectionList(ini, "poll:")) != NULL) { + if((list = iniGetSectionList(ini, "poll:")) != NULL) { smb_t smb; unsigned u; ZERO_VAR(smb); smb.subnum = INVALID_SUB; - for(u = 0; poll_list[u] != NULL; u++) { + for(u = 0; list[u] != NULL; u++) { + uint subnum = resolve_qwkconf(iniGetInteger(ini, list[u], "Conference", 0)); + if(subnum == INVALID_SUB) + continue; + if(cfg.sub[subnum]->misc&SUB_NOVOTING) + continue; + smbmsg_t msg; ZERO_VAR(msg); - smb_hfield_str(&msg, RFC822MSGID, poll_list[u] + 5); - smb_hfield_str(&msg, SENDER, iniGetString(ini, poll_list[u], smb_hfieldtype(SENDER), NULL, NULL)); - msg.hdr.votes = iniGetShortInt(ini, poll_list[u], "votes", 0); - if(net_type != NET_NONE) { - const char* netaddr = iniGetString(ini, poll_list[u], smb_hfieldtype(SENDERNETADDR), NULL, NULL); - if(netaddr == NULL) - netaddr = qnet_id; - smb_hfield_netaddr(&msg, SENDERNETADDR, netaddr, &net_type); - smb_hfield(&msg, SENDERNETTYPE, sizeof(net_type), &net_type); - } + smb_hfield_str(&msg, RFC822MSGID, list[u] + 5); + parse_common_header_fields(ini, list[u], &msg, net_type, qnet_id); + msg.hdr.votes = iniGetShortInt(ini, list[u], "votes", 0); + ulong results = iniGetLongInt(ini, list[u], "results", 0); + msg.hdr.auxattr = (results << POLL_RESULTS_SHIFT) & POLL_RESULTS_MASK; for(int i=0;;i++) { char str[128]; SAFEPRINTF2(str, "%s%u", smb_hfieldtype(SMB_COMMENT), i); - const char* comment = iniGetString(ini, poll_list[u], str, NULL, NULL); + const char* comment = iniGetString(ini, list[u], str, NULL, NULL); if(comment == NULL) break; smb_hfield_str(&msg, SMB_COMMENT, comment); @@ -1048,89 +1094,115 @@ bool sbbs_t::qwk_voting(const char* fname, smb_net_type_t net_type, const char* for(int i=0;;i++) { char str[128]; SAFEPRINTF2(str, "%s%u", smb_hfieldtype(SMB_POLL_ANSWER), i); - const char* answer = iniGetString(ini, poll_list[u], str, NULL, NULL); + const char* answer = iniGetString(ini, list[u], str, NULL, NULL); if(answer == NULL) break; smb_hfield_str(&msg, SMB_POLL_ANSWER, answer); } - uint subnum = resolve_qwkconf(iniGetInteger(ini, poll_list[u], "Conference", 0)); - if(subnum == INVALID_SUB) - continue; - if(cfg.sub[subnum]->misc&SUB_NOVOTING) - continue; if(subnum != smb.subnum) { if(smb.subnum != INVALID_SUB) { smb_close(&smb); smb.subnum = INVALID_SUB; } - if(smb_open_sub(&cfg, &smb, subnum) != SMB_SUCCESS) - continue; + smb_open_sub(&cfg, &smb, subnum); } int i; if((i=smb_addpoll(&smb, &msg, smb_storage_mode(&cfg, &smb))) != SMB_SUCCESS) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); + smb_freemsgmem(&msg); } if(smb.subnum != INVALID_SUB) smb_close(&smb); - iniFreeStringList(poll_list); + iniFreeStringList(list); } - if((ballot_list = iniGetSectionList(ini, "vote:")) != NULL) { + if((list = iniGetSectionList(ini, "vote:")) != NULL) { smb_t smb; unsigned u; ZERO_VAR(smb); smb.subnum = INVALID_SUB; - for(u = 0; ballot_list[u] != NULL; u++) { + for(u = 0; list[u] != NULL; u++) { + uint subnum = resolve_qwkconf(iniGetInteger(ini, list[u], "Conference", 0)); + if(subnum == INVALID_SUB) + continue; + if(cfg.sub[subnum]->misc&SUB_NOVOTING) + continue; + smbmsg_t msg; const char* notice = NULL; ZERO_VAR(msg); - smb_hfield_str(&msg, RFC822MSGID, ballot_list[u] + 5); - smb_hfield_str(&msg, RFC822REPLYID, iniGetString(ini, ballot_list[u], smb_hfieldtype(RFC822REPLYID), NULL, NULL)); - smb_hfield_str(&msg, SENDER, iniGetString(ini, ballot_list[u], smb_hfieldtype(SENDER), NULL, NULL)); - if(iniGetBool(ini, ballot_list[u], "upvote", FALSE)) { + smb_hfield_str(&msg, RFC822MSGID, list[u] + 5); + parse_common_header_fields(ini, list[u], &msg, net_type, qnet_id); + if(iniGetBool(ini, list[u], "upvote", FALSE)) { msg.hdr.attr = MSG_UPVOTE; notice = text[MsgUpVoteNotice]; } - else if(iniGetBool(ini, ballot_list[u], "downvote", FALSE)) { + else if(iniGetBool(ini, list[u], "downvote", FALSE)) { msg.hdr.attr = MSG_DOWNVOTE; notice = text[MsgDownVoteNotice]; } else { msg.hdr.attr = MSG_VOTE; - msg.hdr.votes = iniGetShortInt(ini, ballot_list[u], "votes", 0); + msg.hdr.votes = iniGetShortInt(ini, list[u], "votes", 0); notice = text[PollVoteNotice]; } - if(net_type != NET_NONE) { - const char* netaddr = iniGetString(ini,ballot_list[u], smb_hfieldtype(SENDERNETADDR), NULL, NULL); - if(netaddr == NULL) - netaddr = qnet_id; - smb_hfield_netaddr(&msg, SENDERNETADDR, netaddr, &net_type); - smb_hfield(&msg, SENDERNETTYPE, sizeof(net_type), &net_type); + if(subnum != smb.subnum) { + if(smb.subnum != INVALID_SUB) { + smb_close(&smb); + smb.subnum = INVALID_SUB; + } + smb_open_sub(&cfg, &smb, subnum); } - uint subnum = resolve_qwkconf(iniGetInteger(ini, ballot_list[u], "Conference", 0)); + int i; + if((i=votemsg(&cfg, &smb, &msg, notice)) != SMB_SUCCESS) + errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); + smb_freemsgmem(&msg); + } + if(smb.subnum != INVALID_SUB) + smb_close(&smb); + iniFreeStringList(list); + } + + if((list = iniGetSectionList(ini, "close:")) != NULL) { + smb_t smb; + unsigned u; + + ZERO_VAR(smb); + smb.subnum = INVALID_SUB; + + for(u = 0; list[u] != NULL; u++) { + uint subnum = resolve_qwkconf(iniGetInteger(ini, list[u], "Conference", 0)); if(subnum == INVALID_SUB) continue; if(cfg.sub[subnum]->misc&SUB_NOVOTING) continue; + + smbmsg_t msg; + const char* notice = NULL; + + ZERO_VAR(msg); + smb_hfield_str(&msg, RFC822MSGID, list[u] + 6); + parse_common_header_fields(ini, list[u], &msg, net_type, qnet_id); if(subnum != smb.subnum) { if(smb.subnum != INVALID_SUB) { smb_close(&smb); smb.subnum = INVALID_SUB; } - if(smb_open_sub(&cfg, &smb, subnum) != SMB_SUCCESS) - continue; + smb_open_sub(&cfg, &smb, subnum); } int i; - if((i=votemsg(&cfg, &smb, &msg, notice)) != SMB_SUCCESS) + if((i=smb_addpollclosure(&smb, &msg, smb_storage_mode(&cfg, &smb))) != SMB_SUCCESS) errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); + smb_freemsgmem(&msg); } if(smb.subnum != INVALID_SUB) smb_close(&smb); - iniFreeStringList(ballot_list); + iniFreeStringList(list); } + iniFreeStringList(ini); return true; } diff --git a/src/sbbs3/qwktomsg.cpp b/src/sbbs3/qwktomsg.cpp index f581b5a718cbf2ff168a6147b899342cf68ca48c..123820d272e8fe9ebed5ddbb1683cbd35fdc5e53 100644 --- a/src/sbbs3/qwktomsg.cpp +++ b/src/sbbs3/qwktomsg.cpp @@ -110,9 +110,9 @@ static void qwk_parse_header_list(ulong confnum, smbmsg_t* msg, str_list_t* head if(parse_sender_hfields) smb_hfield_str(msg,hfield_type,p); } - while((p=iniPopKey(headers,ROOT_SECTION,"Organization",value))!=NULL) { + while((p=iniPopKey(headers,ROOT_SECTION,smb_hfieldtype(hfield_type=SENDERORG),value))!=NULL) { if(parse_sender_hfields) - smb_hfield_str(msg,SENDERORG,p); + smb_hfield_str(msg,hfield_type,p); } /* FidoNet header fields */ diff --git a/src/sbbs3/readmail.cpp b/src/sbbs3/readmail.cpp index 20f9fbe6ff948bb6dd7da25d73b6c478b66467cf..59496c8e18f6c9c584e69f1ccddd8bf6fa99856a 100644 --- a/src/sbbs3/readmail.cpp +++ b/src/sbbs3/readmail.cpp @@ -575,7 +575,7 @@ void sbbs_t::readmail(uint usernumber, int which) done=1; break; case 'C': /* Change attributes of last piece */ - i=chmsgattr(msg.hdr.attr); + i=chmsgattr(msg); if(msg.hdr.attr==i) break; if(msg.total_hfields) diff --git a/src/sbbs3/readmsgs.cpp b/src/sbbs3/readmsgs.cpp index 037d1e536bdacaa4f4159f5552a01bd05565b2de..458384d8ad1fabda252fb26c302b26aa80e6d72a 100644 --- a/src/sbbs3/readmsgs.cpp +++ b/src/sbbs3/readmsgs.cpp @@ -40,7 +40,7 @@ int sbbs_t::sub_op(uint subnum) return(is_user_subop(&cfg, subnum, &useron, &client)); } -char sbbs_t::msg_listing_flag(uint subnum, smbmsg_t* msg, post_t* post) +uchar sbbs_t::msg_listing_flag(uint subnum, smbmsg_t* msg, post_t* post) { if(msg->hdr.attr&MSG_DELETE) return '-'; if((stricmp(msg->to,useron.alias)==0 || stricmp(msg->to,useron.name)==0) @@ -52,7 +52,7 @@ char sbbs_t::msg_listing_flag(uint subnum, smbmsg_t* msg, post_t* post) if(msg->hdr.number > subscan[subnum].ptr) return '*'; if(msg->hdr.attr&MSG_PRIVATE) return 'P'; if(msg->hdr.attr&MSG_POLL) return '?'; - if(post->upvotes > post->downvotes) return 'V'; + if(post->upvotes > post->downvotes) return 251; if(post->upvotes || post->downvotes) return 'v'; if(msg->hdr.attr&MSG_REPLIED) return 'R'; if(sub_op(subnum) && msg->hdr.attr&MSG_ANONYMOUS) return 'A'; @@ -266,8 +266,12 @@ post_t * sbbs_t::loadposts(uint32_t *posts, uint subnum, ulong ptr, long mode, u if(mode&LP_REP || !sub_op(subnum)) break; } - - if(idx.attr&MSG_VOTE) { + + switch(idx.attr&MSG_POLL_VOTE_MASK) { + case MSG_VOTE: + case MSG_UPVOTE: + case MSG_DOWNVOTE: + { ulong u; for(u = 0; u < l; u++) if(post[u].idx.number == idx.remsg) @@ -289,10 +293,16 @@ post_t * sbbs_t::loadposts(uint32_t *posts, uint subnum, ulong ptr, long mode, u } if(!(mode&LP_VOTES)) continue; + break; } - if(idx.attr&MSG_POLL) { + case MSG_POLL: if(!(mode&LP_POLLS)) continue; + break; + case MSG_POLL_CLOSURE: + if(!(mode&LP_VOTES)) + continue; + break; } if(idx.attr&MSG_PRIVATE && !(mode&LP_PRIVATE) @@ -824,6 +834,18 @@ int sbbs_t::scanposts(uint subnum, long mode, const char *find) else done=1; break; case 'D': /* Delete message on sub-board */ + if(!(msg.hdr.attr&MSG_DELETE) && msg.hdr.type == SMB_MSG_TYPE_POLL + && smb_msg_is_from(&msg, cfg.sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias, NET_NONE, NULL) + && !(msg.hdr.auxattr&POLL_CLOSED)) { + if(noyes("Close Poll")) { + domsg=false; + break; + } + i=closepoll(&cfg, &smb, msg.hdr.number, cfg.sub[subnum]->misc&SUB_NAME ? useron.name : useron.alias); + if(i != SMB_SUCCESS) + errormsg(WHERE,ERR_WRITE,smb.file,i,smb.last_error); + break; + } domsg=0; if(!sub_op(subnum)) { if(!(cfg.sub[subnum]->misc&SUB_DEL)) { @@ -1055,8 +1077,15 @@ int sbbs_t::scanposts(uint subnum, long mode, const char *find) domsg = false; break; } + + if(msg.hdr.auxattr&POLL_CLOSED) { + bputs(text[CantReplyToMsg]); + domsg = false; + break; + } + ZERO_VAR(vote); - if(msg.hdr.attr&MSG_POLL) { + if(msg.hdr.type == SMB_MSG_TYPE_POLL) { unsigned answers=0; for(i=0; i<msg.total_hfields; i++) { if(msg.hfield[i].type != SMB_POLL_ANSWER) @@ -1131,7 +1160,7 @@ int sbbs_t::scanposts(uint subnum, long mode, const char *find) : matchuser(&cfg,msg.from,FALSE)); break; case 'C': /* Change message attributes */ - i=chmsgattr(msg.hdr.attr); + i=chmsgattr(msg); if(msg.hdr.attr==i) break; if(msg.total_hfields) diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index 64abe465e6818ae645216d81aecefbefadd11359..73c34795197007710bd2fe7f3ee1b2b20e23c3f7 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -621,7 +621,7 @@ public: void removeline(char *str, char *str2, char num, char skip); ulong msgeditor(char *buf, const char *top, char *title); bool editfile(char *path, bool msg=false); - ushort chmsgattr(ushort attr); + ushort chmsgattr(smbmsg_t); void quotemsg(smbmsg_t* msg, int tails); void editmsg(smbmsg_t* msg, uint subnum); void editor_inf(int xeditnum, const char *to, const char* from, const char *subj, long mode @@ -641,7 +641,7 @@ public: /* getmsg.cpp */ int loadmsg(smbmsg_t *msg, ulong number); - void show_msgattr(ushort attr); + void show_msgattr(smbmsg_t*); void show_msghdr(smbmsg_t* msg); void show_msg(smbmsg_t* msg, long mode, post_t* post = NULL); void msgtotxt(smbmsg_t* msg, char *str, bool header, ulong mode); @@ -757,7 +757,7 @@ public: long searchposts(uint subnum, post_t* post, long start, long msgs, const char* find); long showposts_toyou(uint subnum, post_t* post, ulong start, long posts, long mode=0); void msghdr(smbmsg_t* msg); - char msg_listing_flag(uint subnum, smbmsg_t*, post_t*); + uchar msg_listing_flag(uint subnum, smbmsg_t*, post_t*); /* chat.cpp */ void chatsection(void); @@ -1007,6 +1007,7 @@ extern "C" { /* postmsg.cpp */ DLLEXPORT int DLLCALL savemsg(scfg_t*, smb_t*, smbmsg_t*, client_t*, const char* server, char* msgbuf); DLLEXPORT int DLLCALL votemsg(scfg_t*, smb_t*, smbmsg_t*, const char* msgfmt); + DLLEXPORT int DLLCALL closepoll(scfg_t*, smb_t*, uint32_t msgnum, const char* username); DLLEXPORT void DLLCALL signal_sub_sem(scfg_t*, uint subnum); DLLEXPORT int DLLCALL msg_client_hfields(smbmsg_t*, client_t*); DLLEXPORT char* DLLCALL msg_program_id(char* pid); diff --git a/src/sbbs3/sbbsecho.c b/src/sbbs3/sbbsecho.c index ad97995718086cf9ccd7d19f3dc9c9e4aa005e1f..37066cce8ed1f3525cd42725a9c7b29c06f08ad0 100644 --- a/src/sbbs3/sbbsecho.c +++ b/src/sbbs3/sbbsecho.c @@ -2228,7 +2228,7 @@ ulong loadmsgs(post_t** post, ulong ptr) if(idx.number==0) /* invalid message number, ignore */ continue; - if(idx.attr&(MSG_VOTE|MSG_POLL)) + if(idx.attr&MSG_POLL_VOTE_MASK) continue; if(idx.number<=ptr || (idx.attr&MSG_DELETE)) diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp index 948284c7f222294a5513ad8dbebf85beed458f7a..b8b8d466dce644e435466e6ba3db80bd9ab5daef 100644 --- a/src/sbbs3/writemsg.cpp +++ b/src/sbbs3/writemsg.cpp @@ -1,5 +1,3 @@ -/* writemsg.cpp */ - /* Synchronet message creation routines */ /* $Id$ */ @@ -1537,13 +1535,14 @@ bool sbbs_t::movemsg(smbmsg_t* msg, uint subnum) return(true); } -ushort sbbs_t::chmsgattr(ushort attr) +ushort sbbs_t::chmsgattr(smbmsg_t msg) { int ch; + uint16_t attr = msg.hdr.attr; while(online && !(sys_status&SS_ABORT)) { CRLF; - show_msgattr(attr); + show_msgattr(&msg); menu("msgattr"); ch=getkey(K_UPPER); if(ch) @@ -1576,6 +1575,9 @@ ushort sbbs_t::chmsgattr(ushort attr) case 'L': attr^=MSG_LOCKED; break; + case 'C': + attr^=MSG_NOREPLY; + break; default: return(attr); }