Commit 5ea459df authored by rswindell's avatar rswindell
Browse files

Introduced 2 new poll concepts:

- Closures (polls can be closed for new voting by the pollster)
- Results can have configurable visibility:
  a. Only to voters (and the pollster) - the default
  b. Everyone
  c. Everyone once the poll has closed
  d. Only the pollster

Changes to smb_getmsgtxt():
Main change: poll questions can now be quoted when replying to a posted poll
(the results cannot be quoted).
Also: there's now automatically a blank line inserted between comment header
fields and poll answers or the msg body text.
Also: upon any malloc failure, the function now returns NULL.
New functions: smb_msg_is_from() and smb_addpollclosure().
parent b602f110
......@@ -385,3 +385,64 @@ int SMBCALL smb_addpoll(smb_t* smb, smbmsg_t* msg, int storage)
return retval;
}
int SMBCALL smb_addpollclosure(smb_t* smb, smbmsg_t* msg, int storage)
{
smbmsg_t remsg;
int retval;
if(!SMB_IS_OPEN(smb)) {
safe_snprintf(smb->last_error, sizeof(smb->last_error), "msgbase not open");
return SMB_ERR_NOT_OPEN;
}
if(filelength(fileno(smb->shd_fp)) < 1)
return SMB_ERR_NOT_FOUND;
if(msg->hdr.thread_back == 0)
return SMB_ERR_HDR_FIELD;
memset(&remsg, 0, sizeof(remsg));
remsg.hdr.number = msg->hdr.thread_back;
if((retval = smb_getmsgidx(smb, &remsg)) != SMB_SUCCESS)
return retval;
if((retval = smb_lockmsghdr(smb,&remsg)) != SMB_SUCCESS)
return retval;
if((retval = smb_getmsghdr(smb, &remsg)) != SMB_SUCCESS) {
smb_unlockmsghdr(smb, &remsg);
return retval;
}
if(remsg.hdr.auxattr&POLL_CLOSED) {
smb_freemsgmem(&remsg);
smb_unlockmsghdr(smb, &remsg);
return SMB_CLOSED;
}
if(!smb_msg_is_from(&remsg, msg->from, msg->from_net.type, msg->from_net.addr)) {
smb_freemsgmem(&remsg);
smb_unlockmsghdr(smb, &remsg);
return SMB_UNAUTHORIZED;
}
remsg.hdr.auxattr |= POLL_CLOSED;
retval = smb_putmsghdr(smb, &remsg);
smb_freemsgmem(&remsg);
smb_unlockmsghdr(smb, &remsg);
if(retval != SMB_SUCCESS)
return retval;
msg->hdr.attr |= MSG_POLL_CLOSURE;
msg->hdr.type = SMB_MSG_TYPE_POLL_CLOSURE;
if(msg->hdr.when_imported.time == 0) {
msg->hdr.when_imported.time = (uint32_t)time(NULL);
msg->hdr.when_imported.zone = 0;
}
if(msg->hdr.when_written.time == 0) /* Uninitialized */
msg->hdr.when_written = msg->hdr.when_imported;
retval = smb_addmsghdr(smb, msg, storage);
return retval;
}
......@@ -316,7 +316,9 @@
#define MSG_DOWNVOTE (1<<12) /* This message is a downvote */
#define MSG_POLL (1<<13) /* This message is a poll */
#define MSG_VOTE (MSG_UPVOTE|MSG_DOWNVOTE) /* this message is a poll-vote */
#define MSG_VOTE (MSG_UPVOTE|MSG_DOWNVOTE) /* This message is a poll-vote */
#define MSG_POLL_CLOSURE (MSG_POLL|MSG_VOTE) /* This message is a poll-closure */
#define MSG_POLL_VOTE_MASK MSG_POLL_CLOSURE
#define MSG_POLL_MAX_ANSWERS 16
......@@ -328,6 +330,13 @@
#define MSG_RECEIPTREQ (1<<4) /* Return receipt requested */
#define MSG_CONFIRMREQ (1<<5) /* Confirmation receipt requested */
#define MSG_NODISP (1<<6) /* Msg may not be displayed to user */
#define POLL_CLOSED (1<<24) /* Closed to voting */
#define POLL_RESULTS_MASK (3<<30) /* 4 possible values: */
#define POLL_RESULTS_SECRET (3<<30) /* No one but pollster can see results */
#define POLL_RESULTS_CLOSED (2<<30) /* No one but pollster can see results until poll is closed */
#define POLL_RESULTS_OPEN (1<<30) /* Results are visible to everyone always */
#define POLL_RESULTS_VOTERS (0<<30) /* Voters can see results right away, everyone else when closed */
#define POLL_RESULTS_SHIFT 30
/* Message network attributes */
#define MSG_LOCAL (1<<0) /* Msg created locally */
......@@ -508,6 +517,7 @@ enum smb_msg_type {
SMB_MSG_TYPE_NORMAL /* Classic message (for reading) */
,SMB_MSG_TYPE_POLL /* A poll question */
,SMB_MSG_TYPE_BALLOT /* Voter response to poll or normal message */
,SMB_MSG_TYPE_POLL_CLOSURE /* Closure of an existing poll */
};
typedef struct _PACK { /* Message header */
......
......@@ -747,9 +747,15 @@ ulong SMBCALL smb_getmsgtxtlen(smbmsg_t* msg)
int i;
ulong length=0L;
for(i=0;i<msg->total_hfields;i++)
if(msg->hfield[i].type==SMB_COMMENT || msg->hfield[i].type==SMTPSYSMSG)
for(i=0;i<msg->total_hfields;i++) {
switch(msg->hfield[i].type) {
case SMB_COMMENT:
case SMTPSYSMSG:
case SMB_POLL_ANSWER:
length+=msg->hfield[i].length+2;
break;
}
}
for(i=0;i<msg->hdr.total_dfields;i++)
if(msg->dfield[i].type==TEXT_BODY || msg->dfield[i].type==TEXT_TAIL)
length+=msg->dfield[i].length;
......@@ -1652,6 +1658,25 @@ int SMBCALL smb_init_idx(smb_t* smb, smbmsg_t* msg)
return(SMB_SUCCESS);
}
BOOL SMBCALL smb_msg_is_from(smbmsg_t* msg, const char* name, enum smb_net_type net_type, const void* net_addr)
{
if(stricmp(msg->from, name) != 0)
return FALSE;
if(msg->from_net.type != net_type)
return FALSE;
switch(net_type) {
case NET_NONE:
return TRUE;
case NET_FIDO:
return memcmp(msg->from_net.addr, net_addr, sizeof(fidoaddr_t)) == 0;
default:
return stricmp(msg->from_net.addr, net_addr) == 0;
}
}
uint16_t SMBCALL smb_voted_already(smb_t* smb, uint32_t msgnum, const char* name, enum smb_net_type net_type, void* net_addr)
{
uint16_t votes = 0;
......@@ -1675,26 +1700,11 @@ uint16_t SMBCALL smb_voted_already(smb_t* smb, uint32_t msgnum, const char* name
continue;
if(smb_getmsghdr(smb, &msg) != SMB_SUCCESS)
continue;
if(stricmp(msg.from, name) == 0) {
BOOL result = FALSE;
if(msg.from_net.type == net_type)
switch(net_type) {
case NET_NONE:
result = TRUE;
break;
case NET_FIDO:
result = memcmp(msg.from_net.addr, net_addr, sizeof(fidoaddr_t)) == 0;
break;
default:
result = stricmp(msg.from_net.addr, net_addr) == 0;
break;
}
if(result) {
if((msg.idx.attr&MSG_VOTE) == MSG_VOTE)
votes = msg.hdr.votes;
else
votes++;
}
if(smb_msg_is_from(&msg, name, net_type, net_addr)) {
if((msg.idx.attr&MSG_VOTE) == MSG_VOTE)
votes = msg.hdr.votes;
else
votes++;
}
smb_freemsgmem(&msg);
}
......
......@@ -93,6 +93,8 @@
#define SMB_ERR_MEM -300 /* Memory allocation error */
#define SMB_DUPE_MSG 1 /* Duplicate message detected by smb_addcrc() */
#define SMB_CLOSED 2 /* Poll/thread is closed to replies/votes */
#define SMB_UNAUTHORIZED 3 /* Poll was posted by someone else */
#define SMB_STACK_LEN 4 /* Max msg bases in smb_stack() */
#define SMB_STACK_POP 0 /* Pop a msg base off of smb_stack()*/
......@@ -182,12 +184,14 @@ SMBEXPORT int SMBCALL smb_updatemsg(smb_t* smb, smbmsg_t* msg);
SMBEXPORT BOOL SMBCALL smb_valid_hdr_offset(smb_t* smb, ulong offset);
SMBEXPORT int SMBCALL smb_init_idx(smb_t* smb, smbmsg_t* msg);
SMBEXPORT uint16_t SMBCALL smb_voted_already(smb_t*, uint32_t msgnum, const char* name, enum smb_net_type, void* net_addr);
SMBEXPORT BOOL SMBCALL smb_msg_is_from(smbmsg_t* msg, const char* name, enum smb_net_type net_type, const void* net_addr);
/* smbadd.c */
SMBEXPORT int SMBCALL smb_addmsg(smb_t* smb, smbmsg_t* msg, int storage, long dupechk_hashes
,uint16_t xlat, const uchar* body, const uchar* tail);
SMBEXPORT int SMBCALL smb_addvote(smb_t* smb, smbmsg_t* msg, int storage);
SMBEXPORT int SMBCALL smb_addpoll(smb_t* smb, smbmsg_t* msg, int storage);
SMBEXPORT int SMBCALL smb_addpollclosure(smb_t* smb, smbmsg_t* msg, int storage);
/* smballoc.c */
SMBEXPORT long SMBCALL smb_allochdr(smb_t* smb, ulong length);
......
/* smbtxt.c */
/* Synchronet message base (SMB) message text library routines */
/* $Id$ */
......@@ -71,11 +69,41 @@ char* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode)
sprintf(smb->last_error
,"realloc failure of %ld bytes for comment buffer"
,l+length+1);
return(buf);
free(buf);
return(NULL);
}
buf=p;
l+=sprintf(buf+l,"%s\r\n",str);
}
if(l) { /* Add a blank line after comments */
if((p=(char*)realloc(buf,l+3))==NULL) {
sprintf(smb->last_error
,"realloc failure of %ld bytes for comment buffer"
,l+3);
free(buf);
return(NULL);
}
buf=p;
l+=sprintf(buf+l,"\r\n");
}
unsigned answers = 0;
for(i=0;i<(uint)msg->total_hfields;i++) { /* Poll Answers are part of text */
if(msg->hfield[i].type!=SMB_POLL_ANSWER)
continue;
char tmp[128];
length = safe_snprintf(tmp, sizeof(tmp), "%2u: %s\r\n", ++answers, (char*)msg->hfield_dat[i]);
if((p=(char*)realloc(buf,l+length+1))==NULL) {
sprintf(smb->last_error
,"realloc failure of %ld bytes for comment buffer"
,l+length+1);
free(buf);
return(NULL);
}
buf=p;
memcpy(buf+l, tmp, length);
l += length;
buf[l] = 0;
}
}
for(i=0;i<(uint)msg->hdr.total_dfields;i++) {
......@@ -113,7 +141,8 @@ char* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode)
sprintf(smb->last_error
,"malloc failure of %ld bytes for LZH buffer"
,length);
return(buf);
free(buf);
return(NULL);
}
smb_fread(smb,lzhbuf,length,smb->sdt_fp);
lzhlen=*(int32_t*)lzhbuf;
......@@ -122,7 +151,8 @@ char* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode)
,"realloc failure of %ld bytes for text buffer"
,l+lzhlen+3L);
free(lzhbuf);
return(buf);
free(buf);
return(NULL);
}
buf=p;
lzh_decode((uint8_t *)lzhbuf,length,(uint8_t *)buf+l);
......@@ -134,7 +164,8 @@ char* SMBCALL smb_getmsgtxt(smb_t* smb, smbmsg_t* msg, ulong mode)
sprintf(smb->last_error
,"realloc failure of %ld bytes for text buffer"
,l+length+3L);
return(buf);
free(buf);
return(NULL);
}
buf=p;
p=buf+l;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment