This is news.c in view mode; [Download] [Up]
/* $Id$ */
#ifdef NNTPNEWS
#include "bbs.h"
int browsegroup(grouptyp *grouprecord, newsstattyp *newsrecord,
const confrecordtyp *confrecord)
{
int lang, art_anz, sel_anz, cnt, n, p;
char str[STRLEN+1], sstr[S_STRLEN+1], buf[2*STRLEN+1], gstr[ARG_MAX+1], file[PATH_MAX+1], maddr[STRLEN+1], raddr[STRLEN+1], article[STRLEN+1], *header, *sp, *bgbuf, *splits[MAXARGS+1], key, dokey;
boolean unread_only, bodyonly;
newsheadertyp newshdr;
chrootrecordtyp chrootrec;
tlistetyp *artliste = (tlistetyp *)0;
lang = confrecord->userrecord.lang;
unread_only = TRUE;
newsrecord->group_is_set = FALSE;
bbslog(LOG_FILE,confrecord,"group %s",grouprecord->groupname);
cnt = 0;
do {
cnt++;
bgbuf = showmsgline(msg("browsegroup",0,lang));
if (cnt == 2) unread_only = FALSE;
n = nntp_getoverview(grouprecord,unread_only,newsrecord,confrecord);
if (n == ERR_NONEXT && grouprecord->anz_article > 0) {
key = getkeyonprompt(msg("browsegroup",1,lang),"JYN",TRUE,FALSE,
NULL,confrecord);
if (key != 'N') unread_only = FALSE;
}
else if (n == ERR_NONEXT && grouprecord->anz_article == 0) {
writetouser(confrecord,msg("browsegroup",2,lang),
grouprecord->groupname);
}
else if (n != OK_NOV) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","browsegroup",
"cannot get overview for group %s",grouprecord->groupname);
}
} while (n == ERR_NONEXT && ! unread_only && cnt < 2);
if (n != OK_NOV) return -1;
art_anz = overviewtolist(&artliste,grouprecord,confrecord);
removeliste(&grouprecord->ov_liste,TRUE,TL_BLOCKLEN);
sprintf(sstr,msg("browsegroup",3,lang),grouprecord->groupname,art_anz);
while ((key=newspager_c(artliste,art_anz,sstr,NULL,FALSE,
"newsbrowser_artselect",
confrecord)) != ESCAPE_KEY) {
dokey = NO_KEY;
*gstr = '\0';
for (p=0,sel_anz=0; p<art_anz; p++) {
readliste(&artliste,FALSE,p,TL_BLOCKLEN,&sp,confrecord);
if (*sp == 'T') sel_anz++;
}
cnt = 0;
for (p=0; p<art_anz; p++) {
readliste(&artliste,FALSE,p,TL_BLOCKLEN,&sp,confrecord);
if (*sp == 'T') {
cnt++;
if (dokey == NO_KEY) {
dokey = getkeyonprompt(msg("browsegroup",4,lang),"LRAFHG",
TRUE,FALSE,"newsbrowser_doselect",
confrecord);
}
*sp = '!';
sp++;
strcpy(buf,sp);
splitstring(splits,buf,'\n',6);
strcpy(article,splits[1]);
n = atoi(splits[2]);
strmaxcpy(str,article,COLS-24);
bgbuf = showmsgline(msg("browsegroup",5,lang),str);
bbslog(LOG_FILE,confrecord,"article %s (%d)",article,n);
if (dokey == 'A' || dokey == 'F' || dokey == 'H') {
bodyonly = TRUE;
}
else {
bodyonly = FALSE;
}
if (nntp_getarticle(&header,file,bodyonly,n,newsrecord,
confrecord) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","browsegroup",
"cannot get article %s (%d), group %s",str,n,
grouprecord->groupname);
continue;
}
if (dokey == 'H') {
do_shownewsheader(header,confrecord);
}
else if (dokey == 'G') {
strmaxcat(gstr,file,ARG_MAX);
strmaxcat(gstr," ",ARG_MAX);
}
else if (dokey == 'R' || dokey == 'L') {
parsenewsheader(&newshdr,header);
mimerecode(file,newshdr.mime_encoding,confrecord);
parseaddrline(maddr,raddr,newshdr.from);
sprintf(str,"(%d/%d): ",cnt,sel_anz);
if (*raddr != '\0') {
strmaxcat(str,raddr,24);
}
else {
strmaxcat(str,maddr,24);
}
strcat(str,": ");
strmaxcat(str,article,COLS);
if (do_showfile(file,str,NULL,NULL,confrecord) == ESCAPE_KEY) {
key = getkeyonprompt(msg("browsegroup",6,lang),"JYN",TRUE,
FALSE,NULL,confrecord);
if (key != 'N') {
free(header);
unlink(file);
break;
}
}
}
else if (dokey == 'A' || dokey == 'F') {
parsenewsheader(&newshdr,header);
parseaddrline(maddr,raddr,newshdr.from);
if (*raddr != '\0') {
strmaxcpy(str,raddr,24);
}
else {
strmaxcpy(str,maddr,24);
}
move(0,0);
clear();
standout();
printw(msg("browsegroup",7,lang),str,article);
standend();
newsreply(&newshdr,file,newsrecord,confrecord);
}
free(header);
if (dokey != 'G') unlink(file);
}
}
if (dokey == 'G') {
strcpy(chrootrec.root,"/");
getcwd(chrootrec.cwd,PATH_MAX);
do_get(gstr,&chrootrec,protokollnamen,
confrecord->userrecord.protokoll,confrecord);
n = splitstring(splits,gstr,' ',MAXARGS);
for (p=0; p < n; p++) unlink(splits[p]);
}
}
return 0;
}
int newsreply(newsheadertyp *newshdr, const char *body,
newsstattyp *newsrecord, const confrecordtyp *confrecord)
{
int lang;
char zeile[STRLEN+1], groups[STRLEN+1], str[PATH_MAX+2*STRLEN+23],
scratch[PATH_MAX+1], subject[STRLEN+1], addr[ARG_MAX+1],
refs[STRLEN+1], path[PATH_MAX+1], key;
FILE *fp, *sfp;
lang = confrecord->userrecord.lang;
if ((fp=fopen(body,"r")) == NULL) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","newsreply",
"fopen %s: %m",body);
return -1;
}
scratchfilename(scratch,"newsreply.",NULL,confrecord->scratchdir);
if ((sfp=fopen(scratch,"w")) == NULL) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","newsreply",
"fopen %s: %m",scratch);
return -1;
}
fprintf(sfp,"In reply of:\n");
while (fgetnln(zeile,STRLEN,fp) >= 0) {
fputs("> ",sfp);
fputs(zeile,sfp);
putc('\n',sfp);
}
fclose(fp);
fclose(sfp);
if (*newshdr->references == '\0') {
strcpy(subject,"Re: ");
}
else {
*subject = '\0';
strcpy(refs,newshdr->references);
strcat(refs," ");
}
strmaxcat(subject,newshdr->subject,STRLEN-1);
strmaxcat(refs,newshdr->msg_id,STRLEN-1);
if (*newshdr->reply_to != '\0') {
strcpy(addr,newshdr->reply_to);
}
else {
strcpy(addr,newshdr->from);
}
if (*newshdr->followup_to != '\0') {
strcpy(groups,newshdr->followup_to);
}
else {
strcpy(groups,newshdr->newsgroups);
}
key = getkeyonprompt(msg("newsreply",0,lang),"EAB",TRUE,FALSE,NULL,
confrecord);
if (key == 'E' || key == 'B') {
*str = '\0';
if (sendmail_c(str,scratch,addr,subject,FALSE,NULL,confrecord) > 1) {
do_sendmail(str,path,NULL,NULL,confrecord);
}
}
if (key == 'A' || key == 'B') {
postarticle_c(scratch,groups,subject,refs,newsrecord,confrecord);
}
unlink(scratch);
return 0;
}
int getnewsgrpname(char *group, const confrecordtyp *confrecord)
{
int n;
*group = '\0';
do {
move(LINES-1,0);
clrtoeol();
standout();
addstr("Newsgroup:");
standend();
addch(' ');
n = readfromuser(group,group,STRLEN,TRUE,confrecord);
if (n == 0) return 0;
n = checkgroup(group,confrecord);
if (n == 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","getnewsgrpname",
"Newsgroup %s does not exist",group);
}
} while (n == 0);
return n;
}
int checknewsperms(const confrecordtyp *confrecord)
{
int n, rw = -1;
char *psplits[MAXARGS+1], pstr[STRLEN+1];
strmaxcpy(pstr,confrecord->userrecord.permittions,STRLEN);
splitstring(psplits,pstr,':',MAXARGS);
for (n=0; psplits[n] != NULL; n++) {
if (*psplits[n] == 'P') return 1;
if (*psplits[n] == 'N') rw = 0;
}
return rw;
}
int parsenewsheader(newsheadertyp *newshdr, char *hdrbuf)
{
int k;
char *sp, *key, *txt, *headers[101];
static char *nullchar = "";
newshdr->from = nullchar;
newshdr->newsgroups = nullchar;
newshdr->reply_to = nullchar;
newshdr->followup_to = nullchar;
newshdr->subject = nullchar;
newshdr->date = nullchar;
newshdr->msg_id = nullchar;
newshdr->references = nullchar;
newshdr->mime_encoding = nullchar;
splitstring(headers,hdrbuf,'\n',100);
for (k=0; headers[k] != NULL; k++) {
if ((sp=strchr(headers[k],':')) != NULL) {
*sp = '\0';
key = headers[k];
sp++;
while (*sp == ' ' && *sp) sp++;
txt = sp;
while (*sp) sp++;
if (sp > txt) sp--;
while (*sp == ' ' && sp > txt) *sp-- = '\0';
lowercases(key);
if (strcmp(key,"from") == 0) {
newshdr->from = txt;
}
else if (strcmp(key,"newsgroups") == 0) {
newshdr->newsgroups = txt;
}
else if (strcmp(key,"reply-to") == 0) {
newshdr->reply_to = txt;
}
else if (strcmp(key,"followup-to") == 0) {
newshdr->followup_to = txt;
}
else if (strcmp(key,"subject") == 0) {
newshdr->subject = txt;
}
else if (strcmp(key,"date") == 0) {
newshdr->date = txt;
}
else if (strcmp(key,"message-id") == 0) {
newshdr->msg_id = txt;
}
else if (strcmp(key,"references") == 0) {
newshdr->references = txt;
}
else if (strcmp(key,"content-transfer-encoding") == 0) {
newshdr->mime_encoding = txt;
}
}
}
return 0;
}
int updatenewsrc(DBASE_DB *newsrcdb, grouptyp *grouprecord,
const boolean sync_newsrc, const confrecordtyp *confrecord)
{
char sstr[81];
DBASE_DBT dbkey, dbdata;
DBASE_DATA(dbkey) = grouprecord->groupname;
DBASE_SIZE(dbkey) = strlen(grouprecord->groupname) + 1;
sprintf(sstr,"1-%d",grouprecord->last_article);
DBASE_DATA(dbdata) = sstr;
DBASE_SIZE(dbdata) = strlen(sstr) + 1;
if (newsrcdb->put(newsrcdb,&dbkey,&dbdata,0) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","updatenewsrc",
"cannot put new last_article into newsrc DB");
return -1;
}
if (sync_newsrc) {
if (syncnewsrcdb(newsrcdb,confrecord) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","updatenewsrc",
"cannot sync to newsrc");
return -1;
}
}
return 0;
}
int syncnewsrcdb(DBASE_DB *newsrcdb, const confrecordtyp *confrecord)
{
int anz, n;
U_INT flags = R_FIRST;
char str[2*S_STRLEN+3];
DBASE_DBT dbkey, dbdata;
tlistetyp *tliste = (tlistetyp *)0;
anz = 0;
while ((n = newsrcdb->seq(newsrcdb,&dbkey,&dbdata,flags)) != 1) {
if (n < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","syncnewsrcdb",
"seq failed: %m");
return -1;
}
flags = R_NEXT;
sprintf(str,"%s: %s",(char *)DBASE_DATA(dbkey),(char *)DBASE_DATA(dbdata));
addstrtoliste(&tliste,TRUE,anz++,TL_BLOCKLEN,str,confrecord);
}
n = savenewsrc(tliste,anz,confrecord);
removeliste(&tliste,TRUE,TL_BLOCKLEN);
return n;
}
DBASE_DB *createnewsrcdb(newsstattyp *newsrecord,
const confrecordtyp *confrecord)
{
int n, k, anz;
char *sp1, *sp2;
DBASE_DB *db;
DBASE_DBT dbkey, dbdata;
tlistetyp *newsrcliste = (tlistetyp *)0;
HASHINFO hinf = {256, 8, 1, 512000, NULL, 0};
newsrecord->subscribed_anz = -1;
newsrecord->newsrcdb = NULL;
if ((db=dbopen(NULL,O_CREAT|O_TRUNC|O_RDWR,0600,DB_HASH,&hinf)) == NULL) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","createnewsrcdb",
"cannot create newsrc-db: %m");
return NULL;
}
if ((anz=getnewsrc(&newsrcliste,confrecord)) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","createnewsrcdb",
"cannot get newsrc");
db->close(db);
return NULL;
}
for (k=0; k < anz; k++) {
readliste(&newsrcliste,FALSE,k,TL_BLOCKLEN,&sp1,confrecord);
for (sp2=sp1; *sp2 && *sp2!=':'; sp2++) ;
if (*sp2) *sp2++ = '\0';
while (*sp2==' ') sp2++;
DBASE_DATA(dbkey) = sp1;
DBASE_SIZE(dbkey) = strlen(sp1) + 1;
DBASE_DATA(dbdata) = sp2;
DBASE_SIZE(dbdata) = strlen(sp2) + 1;
n = db->put(db,&dbkey,&dbdata,R_NOOVERWRITE);
if (n > 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","createnewsrcdb",
"duplicate key %s",(char *)DBASE_DATA(dbkey));
}
else if (n < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","createnewsrcdb",
"error at key %s: %m",(char *)DBASE_DATA(dbkey));
}
}
removeliste(&newsrcliste,TRUE,TL_BLOCKLEN);
newsrecord->subscribed_anz = anz;
newsrecord->newsrcdb = db;
return db;
}
int lookupnewsrcdb(const DBASE_DB *newsrcdb, const void *key,
const SIZE_T keysize, void *data, SIZE_T *datasize,
const confrecordtyp *confrecord)
{
int n;
DBASE_DBT dbkey, dbval;
DBASE_SIZE(dbkey) = keysize;
if (keysize == 0) {
DBASE_SIZE(dbkey) = strlen((char *)key) + 1;
}
if ((DBASE_DATA(dbkey) = malloc(DBASE_SIZE(dbkey))) == NULL) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","lookupnewsrcdb","malloc: %m");
return -1;
}
memcpy(DBASE_DATA(dbkey),key,DBASE_SIZE(dbkey));
if (data != NULL) {
*datasize = 0;
BZERO(data,1);
}
n = newsrcdb->get(newsrcdb,&dbkey,&dbval,0);
if (n < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","lookupnewsrcdb","user %s: %m",
(char *)key);
}
else if (n == 0 && data != NULL) {
*datasize = DBASE_SIZE(dbval);
memcpy(data,DBASE_DATA(dbval),*datasize);
}
free(DBASE_DATA(dbkey));
return n;
}
int newsrcdbtolist(tlistetyp **tliste, const DBASE_DB *newsrcdb,
const confrecordtyp *confrecord)
{
int anz, n;
U_INT flags = R_FIRST;
char str[S_STRLEN+1];
DBASE_DBT dbkey, dbdata;
anz = 0;
*tliste = (tlistetyp *)0;
while ((n = newsrcdb->seq(newsrcdb,&dbkey,&dbdata,flags)) != 1) {
if (n < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","newsrcdbtolist",
"seq failed: %m");
return -1;
}
flags = R_NEXT;
strcpy(str,"F");
strmaxcat(str,(char *)DBASE_DATA(dbkey),S_STRLEN);
addstrtoliste(tliste,TRUE,anz++,TL_BLOCKLEN,str,confrecord);
}
return anz;
}
int overviewtolist(tlistetyp **tliste, const grouptyp *grouprecord,
const confrecordtyp *confrecord)
{
int anz, nr, n, k, p;
char str[2*STRLEN+1], rstr[STRLEN+1], sstr[21], buf[4*STRLEN+1],
subj[STRLEN+1], maddr[STRLEN+1], raddr[STRLEN+1], *splits[MAXARGS+1],
*sp, *sp2;
DBASE_DB *db;
DBASE_DBT dbkey, dbdata;
articletyp art;
tlistetyp *ov_liste, *sliste = (tlistetyp *)0;
int articlecmp(const char *, const char *);
HASHINFO hinf = {256, 8, 1, 1024000, NULL, 0};
ov_liste = grouprecord->ov_liste;
if ((db=dbopen(NULL,O_CREAT|O_TRUNC|O_RDWR,0600,DB_HASH,&hinf)) == NULL) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","overviewtolist",
"cannot create Id DB: %m");
return -1;
}
nr = 1;
for (p=0; p < grouprecord->ov_anz; p++) {
readliste(&ov_liste,FALSE,p,TL_BLOCKLEN,&sp,confrecord);
strcpy(buf,sp);
if (parseoverviewline(&art,buf) < 0) {
continue;
}
DBASE_DATA(dbkey) = art.msg_id;
DBASE_SIZE(dbkey) = strlen(art.msg_id) + 1;
sprintf(sstr,"%04d",nr++);
DBASE_DATA(dbdata) = sstr;
DBASE_SIZE(dbdata) = strlen(sstr) + 1;
if (db->put(db,&dbkey,&dbdata,0) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","overviewtolist",
"put failed: %m");
return -1;
}
}
for (p=0; p < grouprecord->ov_anz; p++) {
readliste(&ov_liste,FALSE,p,TL_BLOCKLEN,&sp,confrecord);
strcpy(buf,sp);
if (parseoverviewline(&art,buf) < 0) {
continue;
}
strcpy(rstr,art.references);
anz = splitstring(splits,rstr,' ',MAXARGS);
for (k=0; k < anz; k++) {
DBASE_DATA(dbkey) = splits[k];
DBASE_SIZE(dbkey) = strlen(splits[k]) + 1;
sprintf(sstr,"%04d",nr);
DBASE_DATA(dbdata) = sstr;
DBASE_SIZE(dbdata) = strlen(sstr) + 1;
n = db->put(db,&dbkey,&dbdata,R_NOOVERWRITE);
if (n < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","overviewtolist",
"put failed: %m");
return -1;
}
if (n == 0) nr++;
}
}
nr = 0;
for (p=0; p < grouprecord->ov_anz; p++) {
readliste(&ov_liste,FALSE,p,TL_BLOCKLEN,&sp,confrecord);
strcpy(buf,sp);
if (parseoverviewline(&art,buf) < 0) {
continue;
}
strcpy(rstr,art.references);
anz = splitstring(splits,rstr,' ',MAXARGS);
splits[anz++] = art.msg_id;
*str = '\0';
for (k=0; k < anz; k++) {
DBASE_DATA(dbkey) = splits[k];
DBASE_SIZE(dbkey) = strlen(splits[k]) + 1;
if (db->get(db,&dbkey,&dbdata,0) < 0) {
errormsg(E_LOGFILE|E_USER,confrecord,"bbs","overviewdbtolist",
"get failed: %m");
return -1;
}
strcat(str,DBASE_DATA(dbdata));
/*
strcat(str,",");
*/
}
strcat(str,"\n");
strcat(str,art.from);
strcat(str,"\n");
strcat(str,art.subject);
strcat(str,"\n");
sprintf(sstr,"%d",art.reflevel);
strcat(str,sstr);
strcat(str,"\n");
sprintf(sstr,"%d",art.nr);
strcat(str,sstr);
strcat(str,"\n");
strcat(str,art.date);
addstrtoliste(&sliste,TRUE,nr++,TL_BLOCKLEN,str,confrecord);
}
db->close(db);
anz = nr;
if (anz > 1) sort_liste(sliste,TL_BLOCKLEN,0,anz-1,articlecmp,confrecord);
*tliste = (tlistetyp *)0;
*subj = '\0';
for (k=0; k < anz; k++) {
readliste(&sliste,FALSE,k,TL_BLOCKLEN,&sp,confrecord);
splitstring(splits,sp,'\n',6);
parseaddrline(maddr,raddr,splits[1]);
if (*raddr != '\0') {
sprintf(str,"F%-18.18s ",raddr);
}
else {
sprintf(str,"F%-18.18s ",maddr);
}
sp2 = splits[2];
if (strncasecmp("re: ",sp2,4) == 0) sp2 += 4;
for (n=0; n < atoi(splits[3]) && n < 9; n++) strcat(str,">");
if (strcmp(sp2,subj) != 0) {
strcpy(subj,sp2);
strcat(str,subj);
}
strcat(str,"\n");
strcat(str,splits[2]);
strcat(str,"\n");
strcat(str,splits[4]);
strcat(str,"\n");
strcat(str,splits[5]);
addstrtoliste(tliste,TRUE,k,TL_BLOCKLEN,str,confrecord);
}
removeliste(&sliste,TRUE,TL_BLOCKLEN);
return anz;
}
int articlecmp(const char *s1, const char *s2)
{
return strcmp(s1,s2);
}
int parseoverviewline(articletyp *art, char *line)
{
int n;
char *splits[9], *sp1, *sp2;
n = 0;
sp1 = line;
splits[0] = sp1;
while (*sp1 && *sp1!='\n') {
if (*sp1 != '\t') {
sp1++;
}
else {
n++;
*sp1++ = '\0';
if (n < 9) splits[n] = sp1;
}
}
if (*sp1 == '\n') *sp1++ = '\0';
if (n >= 7) {
art->nr = atoi(splits[0]);
strmaxcpy(art->subject,splits[1],S_STRLEN);
strmaxcpy(art->from,splits[2],S_STRLEN);
strmaxcpy(art->date,splits[3],30);
strmaxcpy(art->msg_id,splits[4],S_STRLEN);
strmaxcpy(art->references,splits[5],STRLEN);
art->bytes = atoi(splits[6]);
art->lines = atoi(splits[7]);
art->reflevel = 0;
if (*art->references != '\0') art->reflevel++;
for (sp2=art->references; *sp2; sp2++) {
if (*sp2 == ' ') {
while (*sp2==' ') sp2++;
art->reflevel++;
}
}
art->read = 'F';
}
else {
n = -1;
}
return n;
}
#endif
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.