/* * Read/Write a Pandora message base * (LazyBBS Project) * * Public Domain: may be copied and sold freely */ #include #include #include /*#include */ #include #include #include /* for (empty) display in echolist */ #include #include "qbbs.h" #include "bbs.h" #include "login.h" #include "miscio.h" #include "msg.h" #include "linedit.h" /* edit_file() */ #include "sysdep.h" /* timenix() */ #define MAXLINE 23 /* max line / screen */ #define HEADLEN 6 /* displayed message header len */ #define MLINLEN 79 /* display message line len */ #define MSGSIZE 32000 /* Max message size */ #define MSGLINE (MSGSIZE/(MLINLEN+1)) #define BUFSIZE 1024 /* Copy buffer */ #define USEPID /* define to use ^PID kludge */ #define PIDSTR LAZYNAME /* PID name */ #define PIDVER LAZYVERS /* PID version */ /* ===================================================== ECHOLIST */ ECHOLIST *el=NULL; int maxel=0; void close_areas(void ) { if(el) free(el); } ECHOLIST *choose_area(char *group) { char temp[BBSSTR]; int i; int j=1; int empty=0; struct stat mystat; ECHOLIST *found=NULL; int *numbers=malloc((maxel+1)*sizeof(int)); if(!numbers) { logline(1,"Can't malloc in choose_area"); return NULL; } if(!el) { free(numbers); return NULL; } out_printf(CLS_STRING); out_printf(" # | Area | Description\n" "----+-------------------+------------------------------------\n"); for(i=0;i to exit: "); if(getstring(temp)==BBSOK) { int tt; tt=atoi(temp); if(tt>0 && tt8) ptr[8]=0; strlwr(ptr); strspacecpy(curgroup,ptr); } } if(strnicmp(buffer,"-desc",(size_t) strlen("-desc"))==0) { /* got desc */ ptr=nextstr(buffer); if(ptr) { if(strlen(ptr)>=BBSSTR-1) ptr[BBSSTR-2]=0; strcpy(curdesc,ptr); } } } else /* got an area */ { if(strnicmp(buffer,"passthru",strlen("passthru"))) { /* !passthru area */ strspacecpy(el[curarea].file,buffer); ptr=nextstr(buffer); if(ptr) { strcpy(el[curarea].group,curgroup); strcpy(el[curarea].desc,curdesc); strspacecpy(el[curarea].name,ptr); #ifdef RESERVED_FOR_FUTURE /* search zone number */ el[curarea].zone=defzone; ptr=nextstr(ptr); if(ptr) { if((ptr[1]==':') || (ptr[2]==':') || (ptr[3]==':') || (ptr[4]==':')) { if(isdigit(*ptr)) el[curarea].zone=atoi(ptr); } } #endif /* next area */ if(curarea<(MAXECHO-2)) curarea++; } } /* passthru */ /* reset desc */ strcpy(curdesc,"No description."); } /* got */ } } fclose(abbs); el[curarea].file[0]=0; /* end of list marker */ } else return BBSFAIL; /* reset desc for(i=0;i=BBSSTR-1) ptr[BBSSTR-2]='\0'; for(i=0;i0) { msgsize+=max; if(fwrite(zebuffer,1,max,msg)!=max) error++; } else if(max<0) error++; /* copy only the first MSGSIZE bytes */ } while((max==BUFSIZE) && (error==0) && msgsize=0) { if(fread(buffer,min(MSGSIZE-1,len),1,ms)!=1) { logline(1,"fread error while loading message text"); *buffer=0; line=-1; } else { /* succesfully read */ int lastspace=0; int mysize=0; line=1; xbufline[0]=0; while(mysize=MLINLEN) { xbufline[line]=max(lastspace,mysize-(MLINLEN/3))+1; buffer[xbufline[line]-1]=0; line++; } /* clean */ if(buffer[mysize]<0x20 && buffer[mysize]>1) buffer[mysize]='@'; if(line>=MSGLINE-2) break; /* max # of lines */ mysize++; } } } fclose(ms); } else line=-1; return line-1; /*fixed?*/ } /* new mail */ int is_newmail(char *netarea, int *newm, int *newnewm) { char fnam[BBSSTR]; char user[BBSSTR]; FILE *myfp; QBBS_MHEADER curhead; strcpy(fnam,netarea); strcat(fnam,".HDR"); strcpy(user,get_uname()); *newm=*newnewm=0; myfp=fopen(fnam,"rb"); if(!myfp) { logline(4,"Can't open netmail header %s",fnam); return BBSFAIL; } while(fread(&curhead,sizeof(QBBS_MHEADER),1,myfp)==1) { if(stricmp(curhead.to,user)==0) { (*newm)++; if((curhead.attrib & RCVDFLAG)==0) (*newnewm)++; } } fclose(myfp); return BBSOK; } /* ============================================= display list of messages */ void list_messages(FILE *hd, char *from, int counter) { QBBS_MHEADER header; char anskey; int end=0; int i; out_printf(CLS_STRING); out_printf("Nb From To Subject\n" "--------------------------------------------------------------------------\n"); while(1) { i=2; while(i0) { nbmsg=nbmsg/sizeof(QBBS_MHEADER); rewind(hd); msgidx=0; /* find "lastread", place on stamp based on last login */ if(!pvt) /* echomail: first new message since last login (DAY(stamp)>LAST_LOGIN) */ { int idx=0; int last=get_ulastlogin(); while(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)==1) { if(curhead.stamp/86400>=last) { msgidx=idx; break; } idx++; } } else /* pvt: 1st message !rcv */ { int idx=0; while(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)==1) { if( ((curhead.attrib & RCVDFLAG)==0) && (stricmp(from,curhead.to)==0) ) { msgidx=idx; break; } idx++; } } out_printf(CLS_STRING); /* message loop */ do { nodisplay=0; /* read header msgidx */ if(fseek(hd,sizeof(QBBS_MHEADER)*msgidx,SEEK_SET)<0) { logline(4,"fseek() error on %s",areahdr); break; } if(fread(&curhead,sizeof(QBBS_MHEADER),1,hd)!=1) { logline(4,"fread() error on %s",areahdr); break; } if(pvt) /* netmail */ { if( !isgod() && ( ((curhead.attrib & PRVTFLAG)==0) || ((curhead.attrib & KILLFLAG)!=0) || ( (stricmp(from,curhead.from)!=0) && (stricmp(from,curhead.to)!=0) ) ) ) nodisplay++; /*{ if(msgidx0 && previous) msgidx--; else break; } else { /* display message */ previous=0; /* we finally got one backwards, can reset flag */ havedisplayed++; if(pvt) /* netmail: log & update rcvd flag */ { if( ((curhead.attrib & RCVDFLAG)==0) && (stricmp(from,curhead.to)==0) ) { logline(1,"User reading netmail from %s to %s", curhead.from,curhead.to); curhead.attrib|=RCVDFLAG; /* update header */ if(fseek(hd,sizeof(QBBS_MHEADER)*msgidx,SEEK_SET)<0) { logline(4,"fseek() error on %s",areahdr); break; } if(fwrite(&curhead,sizeof(QBBS_MHEADER),1,hd)!=1) logline(4,"Write error during rcvd flag update"); } } /* end update rcvd flag */ out_printf(CLS_STRING); /* display header */ out_printf("[message %d/%d of %s]\n", msgidx+1,(int)nbmsg,area); if(pvt) { out_printf("From : %s on %d:%d/%d.%d\n", curhead.from,curhead.o_zone,curhead.o_net, curhead.o_node,curhead.o_point); out_printf("To : %s on %d:%d/%d.%d\n", curhead.to,curhead.d_zone,curhead.d_net, curhead.d_node,curhead.d_point); } else out_printf("From : %s\nTo : %s\n",curhead.from,curhead.to); out_printf("Date : %s\nSubj.: %s\n" "==========================================================================\n", curhead.time,curhead.subject); /* display message */ true=1; curline=0; /* load the message */ maxline=load_msgbuf(areamsg,curhead.msgoffset, (unsigned int)curhead.size,buffer); if(maxline<=0) { out_printf(CLS_STRING); out_printf("No message.\n"); break; } curline=i=0; while(i<(MAXLINE-HEADLEN)) { if(curline>=maxline) break; if(IsNotKludge(BufLine(curline)) || isgod()) { out_string(BufLine(curline)); out_printf("\n"); i++; } curline++; } true=1; while(true) /* scroll loop inside message */ { if(okwrite) out_printf("[M]ore [H]ome / [P]revious [N]ext [G]oto msg / [L]ist [R]eply [Q]uit ?"); else out_printf("[M]ore [H]ome / [P]revious [N]ext [G]oto message / [L]ist [Q]uit ?"); retchar=getkey(); retchar=toupper(retchar); out_printf(ERASE_LINE); switch(retchar) { /* MORE of the message */ case 'M': case ' ': case '\r': /* cr */ did=0; for(i=0;i, %s writes:\n\n", curhead.time,curhead.from); for(i=0;i %-65.65s\n",BufLine(i)); } fclose(quotef); } else logline(3,"Can't open tempfile."); } /* end of processing after fclose()s */ case 'P': case '<': /*case LEFTARROW:*/ case 'N': case '>': /*case RIGHTARROW:*/ case 'G': case 'Q': case '!': case 'H': case 'L': case '-': case '*': case 3: /* ctrl+C */ true=0; break; } } /* end scroll loop inside message */ if(retchar=='Q' || retchar=='\03' || retchar=='!' || retchar=='R') break; /* bye */ else switch(retchar) { /* list messages */ case 'L': list_messages(hd,from,msgidx+1); /* HOME */ case '*': case 'H': case '-': out_printf(CLS_STRING); break; /* previous message */ case 'P': case '<': /* case LEFTARROW:*/ if(msgidx>0) { msgidx--; previous++; } else out_printf("\7"); break; /* next message */ case 'N': case '>': /* case RIGHTARROW:*/ if(msgidx to cancel)?"); if(getstring(entb)==BBSOK) { msgidx=atoi(entb)-1; if(msgidx<0 || msgidx>=nbmsg) msgidx=0; } out_printf("\n"); break; } } /* nodisplay */ } while(retchar!='Q' && retchar!='\03' && retchar!='!'); /* ctrl+C, Q */ } else no++; fclose(hd); } else no++; /* finish quote processing */ if(doquote) { char toaddr[BBSSTR]; if(is_uguest()) { out_printf(CLS_STRING); out_printf("Guest user can't quote mail.\n\n[Return]\n"); getkey(); } else { logline(5,"User trying to quote mail (%s)",area); out_printf("\n\nDo you really want to quote mail? [Y/n]"); if(tolower(getkey())!='n') { out_printf(CLS_STRING); out_printf(" This will be a %s message to %s.\n", pvt ? "PRIVATE" : "*PUBLIC*", pvt ? curhead.from : area); out_printf(" Subject: %s.\n",curhead.subject); sprintf(toaddr,"%d:%d/%d.%d", curhead.o_zone,curhead.o_net, curhead.o_node,curhead.o_point); if(edit_file(tempfile())==BBSOK) { out_printf("\n\nDo you want to send your mail to %s on %s [y/N]?\n", curhead.from, pvt ? toaddr : area); if(tolower(getkey())=='y') { if(pvt) logline(2,"User wrote netmail to %s",curhead.from); else logline(2,"User wrote echomail in area %s",area); postmsg(get_uname(),fromaddr,curhead.from,toaddr, curhead.subject,path,tempfile(),pvt); } } } } remove(tempfile()); } /* quote */ if(no) { logline(3,"No message base %s",areahdr); out_printf(CLS_STRING); out_printf("No message base!\n\n"); out_printf("Type a key.\n"); getkey(); } if(pvt && !havedisplayed) { out_printf("You have no mail waiting! Hit [Return].\n"); getkey(); } free(buffer); } else logline(4,"Can't allocate message buffer"); }