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.