📄 nntp.c
字号:
LOCAL->txt = NIL; } LOCAL->msgno = msgno; /* note cached message */ if (!LOCAL->txt) { /* have file for this message? */ sprintf (tmp,"%lu",elt->private.uid); switch (nntp_send (LOCAL->nntpstream,"BODY",tmp)) { case NNTPBODY: if (LOCAL->txt = netmsg_slurp (LOCAL->nntpstream->netstream, &LOCAL->txtsize,NIL)) break; /* fall into default case */ default: /* failed, mark as deleted */ elt->deleted = T; case NNTPSOFTFATAL: /* don't mark deleted if stream dead */ return NIL; } } if (!(flags & FT_PEEK)) { /* mark seen if needed */ elt->seen = T; mm_flags (stream,elt->msgno); } INIT (bs,file_string,(void *) LOCAL->txt,LOCAL->txtsize); return T;}/* NNTP fetch article from message ID (for news: URL support) * Accepts: mail stream * message ID * pointer to return total message size * pointer to return file size * Returns: FILE * to message if successful, else NIL */FILE *nntp_article (MAILSTREAM *stream,char *msgid,unsigned long *size, unsigned long *hsiz){ return (nntp_send (LOCAL->nntpstream,"ARTICLE",msgid) == NNTPARTICLE) ? netmsg_slurp (LOCAL->nntpstream->netstream,size,hsiz) : NIL;}/* NNTP per-message modify flag * Accepts: MAIL stream * message cache element */void nntp_flagmsg (MAILSTREAM *stream,MESSAGECACHE *elt){ if (!LOCAL->dirty) { /* only bother checking if not dirty yet */ if (elt->valid) { /* if done, see if deleted changed */ if (elt->sequence != elt->deleted) LOCAL->dirty = T; elt->sequence = T; /* leave the sequence set */ } /* note current setting of deleted flag */ else elt->sequence = elt->deleted; }}/* NNTP search messages * Accepts: mail stream * character set * search program * option flags * Returns: T on success, NIL on failure */long nntp_search (MAILSTREAM *stream,char *charset,SEARCHPGM *pgm,long flags){ unsigned long i; MESSAGECACHE *elt; OVERVIEW ov; char *msg; /* make sure that charset is good */ if (msg = utf8_badcharset (charset)) { MM_LOG (msg,ERROR); /* output error */ fs_give ((void **) &msg); return NIL; } utf8_searchpgm (pgm,charset); if (flags & SO_OVERVIEW) { /* only if specified to use overview */ /* identify messages that will be searched */ for (i = 1; i <= stream->nmsgs; ++i) mail_elt (stream,i)->sequence = nntp_search_msg (stream,i,pgm,NIL); nntp_overview (stream,NIL); /* load the overview cache */ } /* init in case no overview at cleanup */ memset ((void *) &ov,0,sizeof (OVERVIEW)); /* otherwise do default search */ for (i = 1; i <= stream->nmsgs; ++i) { if (((flags & SO_OVERVIEW) && ((elt = mail_elt (stream,i))->sequence) && nntp_parse_overview (&ov,(char *) elt->private.spare.ptr,elt)) ? nntp_search_msg (stream,i,pgm,&ov) : mail_search_msg (stream,i,NIL,pgm)) { if (flags & SE_UID) mm_searched (stream,mail_uid (stream,i)); else { /* mark as searched, notify mail program */ mail_elt (stream,i)->searched = T; if (!stream->silent) mm_searched (stream,i); } } /* clean up overview data */ if (ov.from) mail_free_address (&ov.from); if (ov.subject) fs_give ((void **) &ov.subject); } return LONGT;}/* NNTP search message * Accepts: MAIL stream * message number * search program * overview to search (NIL means preliminary pass) * Returns: T if found, NIL otherwise */long nntp_search_msg (MAILSTREAM *stream,unsigned long msgno,SEARCHPGM *pgm, OVERVIEW *ov){ unsigned short d; unsigned long now = (unsigned long) time (0); MESSAGECACHE *elt = mail_elt (stream,msgno); SEARCHHEADER *hdr; SEARCHOR *or; SEARCHPGMLIST *not; if (pgm->msgno || pgm->uid) { /* message set searches */ SEARCHSET *set; /* message sequences */ if (set = pgm->msgno) { /* must be inside this sequence */ while (set) { /* run down until find matching range */ if (set->last ? ((msgno < set->first) || (msgno > set->last)) : msgno != set->first) set = set->next; else break; } if (!set) return NIL; /* not found within sequence */ } if (set = pgm->uid) { /* must be inside this sequence */ unsigned long uid = mail_uid (stream,msgno); while (set) { /* run down until find matching range */ if (set->last ? ((uid < set->first) || (uid > set->last)) : uid != set->first) set = set->next; else break; } if (!set) return NIL; /* not found within sequence */ } } /* Fast data searches */ /* message flags */ if ((pgm->answered && !elt->answered) || (pgm->unanswered && elt->answered) || (pgm->deleted && !elt->deleted) || (pgm->undeleted && elt->deleted) || (pgm->draft && !elt->draft) || (pgm->undraft && elt->draft) || (pgm->flagged && !elt->flagged) || (pgm->unflagged && elt->flagged) || (pgm->recent && !elt->recent) || (pgm->old && elt->recent) || (pgm->seen && !elt->seen) || (pgm->unseen && elt->seen)) return NIL; /* keywords */ if ((pgm->keyword && !mail_search_keyword (stream,elt,pgm->keyword,LONGT)) || (pgm->unkeyword && mail_search_keyword (stream,elt,pgm->unkeyword,NIL))) return NIL; if (ov) { /* only do this if real searching */ MESSAGECACHE delt; /* size ranges */ if ((pgm->larger && (ov->optional.octets <= pgm->larger)) || (pgm->smaller && (ov->optional.octets >= pgm->smaller))) return NIL; /* date ranges */ if ((pgm->sentbefore || pgm->senton || pgm->sentsince || pgm->before || pgm->on || pgm->since) && (!mail_parse_date (&delt,ov->date) || !(d = mail_shortdate (delt.year,delt.month,delt.day)) || (pgm->sentbefore && (d >= pgm->sentbefore)) || (pgm->senton && (d != pgm->senton)) || (pgm->sentsince && (d < pgm->sentsince)) || (pgm->before && (d >= pgm->before)) || (pgm->on && (d != pgm->on)) || (pgm->since && (d < pgm->since)))) return NIL; if (pgm->older || pgm->younger) { unsigned long msgd = mail_longdate (elt); if (pgm->older && msgd > (now - pgm->older)) return NIL; if (pgm->younger && msgd < (now - pgm->younger)) return NIL; } if ((pgm->from && !mail_search_addr (ov->from,pgm->from)) || (pgm->subject && !mail_search_header_text (ov->subject,pgm->subject))|| (pgm->message_id && !mail_search_header_text (ov->message_id,pgm->message_id)) || (pgm->references && !mail_search_header_text (ov->references,pgm->references))) return NIL; /* envelope searches */ if (pgm->bcc || pgm->cc || pgm->to || pgm->return_path || pgm->sender || pgm->reply_to || pgm->in_reply_to || pgm->newsgroups || pgm->followup_to) { ENVELOPE *env = mail_fetchenvelope (stream,msgno); if (!env) return NIL; /* no envelope obtained */ /* search headers */ if ((pgm->bcc && !mail_search_addr (env->bcc,pgm->bcc)) || (pgm->cc && !mail_search_addr (env->cc,pgm->cc)) || (pgm->to && !mail_search_addr (env->to,pgm->to))) return NIL; /* These criteria are not supported by IMAP and have to be emulated */ if ((pgm->return_path && !mail_search_addr (env->return_path,pgm->return_path)) || (pgm->sender && !mail_search_addr (env->sender,pgm->sender)) || (pgm->reply_to && !mail_search_addr (env->reply_to,pgm->reply_to)) || (pgm->in_reply_to && !mail_search_header_text (env->in_reply_to,pgm->in_reply_to)) || (pgm->newsgroups && !mail_search_header_text (env->newsgroups,pgm->newsgroups)) || (pgm->followup_to && !mail_search_header_text (env->followup_to,pgm->followup_to))) return NIL; } /* search header lines */ for (hdr = pgm->header; hdr; hdr = hdr->next) { char *t,*e,*v; SIZEDTEXT s; STRINGLIST sth,stc; sth.next = stc.next = NIL;/* only one at a time */ sth.text.data = hdr->line.data; sth.text.size = hdr->line.size; /* get the header text */ if ((t = mail_fetch_header (stream,msgno,NIL,&sth,&s.size, FT_INTERNAL | FT_PEEK)) && strchr (t,':')) { if (hdr->text.size) { /* anything matches empty search string */ /* non-empty, copy field data */ s.data = (unsigned char *) fs_get (s.size + 1); /* for each line */ for (v = (char *) s.data, e = t + s.size; t < e;) switch (*t) { default: /* non-continuation, skip leading field name */ while ((t < e) && (*t++ != ':')); if ((t < e) && (*t == ':')) t++; case '\t': case ' ': /* copy field data */ while ((t < e) && (*t != '\015') && (*t != '\012')) *v++ = *t++; *v++ = '\n'; /* tie off line */ while (((*t == '\015') || (*t == '\012')) && (t < e)) t++; } /* calculate true size */ s.size = v - (char *) s.data; *v = '\0'; /* tie off results */ stc.text.data = hdr->text.data; stc.text.size = hdr->text.size; /* search header */ if (mail_search_header (&s,&stc)) fs_give ((void **) &s.data); else { /* search failed */ fs_give ((void **) &s.data); return NIL; } } } else return NIL; /* no matching header text */ } /* search strings */ if ((pgm->text && !mail_search_text (stream,msgno,NIL,pgm->text,LONGT))|| (pgm->body && !mail_search_text (stream,msgno,NIL,pgm->body,NIL))) return NIL; } /* logical conditions */ for (or = pgm->or; or; or = or->next) if (!(nntp_search_msg (stream,msgno,or->first,ov) || nntp_search_msg (stream,msgno,or->second,ov))) return NIL; for (not = pgm->not; not; not = not->next) if (nntp_search_msg (stream,msgno,not->pgm,ov)) return NIL; return T;}/* NNTP sort messages * Accepts: mail stream * character set * search program * sort program * option flags * Returns: vector of sorted message sequences or NIL if error */unsigned long *nntp_sort (MAILSTREAM *stream,char *charset,SEARCHPGM *spg, SORTPGM *pgm,long flags){ unsigned long i,start,last; SORTCACHE **sc; mailcache_t mailcache = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL); unsigned long *ret = NIL; sortresults_t sr = (sortresults_t) mail_parameters (NIL,GET_SORTRESULTS,NIL); if (spg) { /* only if a search needs to be done */ int silent = stream->silent; stream->silent = T; /* don't pass up mm_searched() events */ /* search for messages */ mail_search_full (stream,charset,spg,NIL); stream->silent = silent; /* restore silence state */ } /* initialize progress counters */ pgm->nmsgs = pgm->progress.cached = 0; /* pass 1: count messages to sort */ for (i = 1,start = last = 0; i <= stream->nmsgs; ++i) if (mail_elt (stream,i)->searched) { pgm->nmsgs++; /* have this in the sortcache already? */ if (!((SORTCACHE *) (*mailcache) (stream,i,CH_SORTCACHE))->date) { /* no, record as last message */ last = mail_uid (stream,i); /* and as first too if needed */ if (!start) start = last; } } if (pgm->nmsgs) { /* pass 2: load sort cache */ sc = nntp_sort_loadcache (stream,pgm,start,last,flags); /* pass 3: sort messages */ if (!pgm->abort) ret = mail_sort_cache (stream,pgm,sc,flags); fs_give ((void **) &sc); /* don't need sort vector any more */ } /* empty sort results */ else ret = (unsigned long *) memset (fs_get (sizeof (unsigned long)),0, sizeof (unsigned long)); /* also return via callback if requested */ if (sr) (*sr) (stream,ret,pgm->nmsgs); return ret;}/* Mail load sortcache * Accepts: mail stream, already searched * sort program * first UID to OVER * last UID to OVER * option flags * Returns: vector of sortcache pointers matching search */SORTCACHE **nntp_sort_loadcache (MAILSTREAM *stream,SORTPGM *pgm, unsigned long start,unsigned long last, long flags){ unsigned long i; char c,*s,*t,*v,tmp[MAILTMPLEN]; SORTPGM *pg; SORTCACHE **sc,*r; MESSAGECACHE telt; ADDRESS *adr = NIL; mailcache_t mailcache = (mailcache_t) mail_parameters (NIL,GET_CACHE,NIL); /* verify that the sortpgm is OK */ for (pg = pgm; pg; pg = pg->next) switch (pg->function) { case SORTARRIVAL: /* sort by arrival date */ case SORTSIZE: /* sort by message size */ case SORTDATE: /* sort by date */ case SORTFROM: /* sort by first from */ case SORTSUBJECT: /* sort by subject */ break; case SORTTO: /* sort by first to */ mm_notify (stream,"[NNTPSORT] Can't do To-field sorting in NNTP",WARN); break; case SORTCC: /* sort by first cc */ mm_notify (stream,"[NNTPSORT] Can't do cc-field sorting in NNTP",WARN); break; default: fatal ("Unknown sort function"); } if (start) { /* messages need to be loaded in sortcache? */ /* yes, build range */ if (start != last) sprintf (tmp,"%lu-%lu",start,last); else sprintf (tmp,"%lu",start); /* get it from the NNTP server */ if (!nntp_over (stream,tmp)) return mail_sort_loadcache (stream,pgm); while ((s = net_getline (LOCAL->nntpstream->netstream)) && strcmp (s,".")){ /* death to embedded newlines */ for (t = v = s; c = *v++;) if ((c != '\012') && (c != '\015')) *t++ = c; *t++ = '\0'; /* tie off resulting string */ /* parse OVER response */ if ((i = mail_msgno (stream,atol (s))) && (t = strchr (s,'\t')) && (v = strchr (++t,'\t'))) { *v++ = '\0'; /* tie off subject */ /* put stripped subject in sortcache */ r = (SORTCACHE *) (*mailcache) (stream,i,CH_SORTCACHE); r->refwd = mail_strip_subject (t,&r->subject); if (t = strchr (v,'\t')) { *t++ = '\0'; /* tie off from */ if (adr = rfc822_parse_address (&adr,adr,&v,BADHOST,0)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -