📄 nntp.c
字号:
r->from = adr->mailbox; adr->mailbox = NIL; mail_free_address (&adr); } if (v = strchr (t,'\t')) { *v++ = '\0'; /* tie off date */ if (mail_parse_date (&telt,t)) r->date = mail_longdate (&telt); if ((v = strchr (v,'\t')) && (v = strchr (++v,'\t'))) r->size = atol (++v); } } } fs_give ((void **) &s); } if (s) fs_give ((void **) &s); } /* calculate size of sortcache index */ i = pgm->nmsgs * sizeof (SORTCACHE *); /* instantiate the index */ sc = (SORTCACHE **) memset (fs_get ((size_t) i),0,(size_t) i); /* see what needs to be loaded */ for (i = 1; !pgm->abort && (i <= stream->nmsgs); i++) if ((mail_elt (stream,i))->searched) { sc[pgm->progress.cached++] = r = (SORTCACHE *) (*mailcache) (stream,i,CH_SORTCACHE); r->pgm = pgm; /* note sort program */ r->num = (flags & SE_UID) ? mail_uid (stream,i) : i; if (!r->date) r->date = r->num; if (!r->arrival) r->arrival = mail_uid (stream,i); if (!r->size) r->size = 1; if (!r->from) r->from = cpystr (""); if (!r->to) r->to = cpystr (""); if (!r->cc) r->cc = cpystr (""); if (!r->subject) r->subject = cpystr (""); } return sc;}/* NNTP thread messages * Accepts: mail stream * thread type * character set * search program * option flags * Returns: thread node tree */THREADNODE *nntp_thread (MAILSTREAM *stream,char *type,char *charset, SEARCHPGM *spg,long flags){ return mail_thread_msgs (stream,type,charset,spg,flags,nntp_sort);}/* NNTP ping mailbox * Accepts: MAIL stream * Returns: T if stream alive, else NIL */long nntp_ping (MAILSTREAM *stream){ return (nntp_send (LOCAL->nntpstream,"STAT",NIL) != NNTPSOFTFATAL);}/* NNTP check mailbox * Accepts: MAIL stream */void nntp_check (MAILSTREAM *stream){ /* never do if no updates */ if (LOCAL->dirty) newsrc_write (LOCAL->name,stream); LOCAL->dirty = NIL;}/* NNTP expunge mailbox * Accepts: MAIL stream * sequence to expunge if non-NIL * expunge options * Returns: T if success, NIL if failure */long nntp_expunge (MAILSTREAM *stream,char *sequence,long options){ if (!stream->silent) mm_log ("Expunge ignored on readonly mailbox",NIL); return LONGT;}/* NNTP copy message(s) * Accepts: MAIL stream * sequence * destination mailbox * option flags * Returns: T if copy successful, else NIL */long nntp_copy (MAILSTREAM *stream,char *sequence,char *mailbox,long options){ mailproxycopy_t pc = (mailproxycopy_t) mail_parameters (stream,GET_MAILPROXYCOPY,NIL); if (pc) return (*pc) (stream,sequence,mailbox,options); mm_log ("Copy not valid for NNTP",ERROR); return NIL;}/* NNTP append message from stringstruct * Accepts: MAIL stream * destination mailbox * append callback * data for callback * Returns: T if append successful, else NIL */long nntp_append (MAILSTREAM *stream,char *mailbox,append_t af,void *data){ mm_log ("Append not valid for NNTP",ERROR); return NIL;}/* NNTP open connection * Accepts: network driver * service host list * port number * service name * NNTP open options * Returns: SEND stream on success, NIL on failure */SENDSTREAM *nntp_open_full (NETDRIVER *dv,char **hostlist,char *service, unsigned long port,long options){ SENDSTREAM *stream = NIL; NETSTREAM *netstream = NIL; NETMBX mb; char tmp[MAILTMPLEN]; long extok = LONGT; NETDRIVER *ssld = (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL); sslstart_t stls = (sslstart_t) mail_parameters (NIL,GET_SSLSTART,NIL); if (!(hostlist && *hostlist)) mm_log ("Missing NNTP service host",ERROR); else do { /* try to open connection */ sprintf (tmp,"{%.200s/%.20s}",*hostlist,service ? service : "nntp"); if (!mail_valid_net_parse (tmp,&mb) || mb.anoflag) { sprintf (tmp,"Invalid host specifier: %.80s",*hostlist); mm_log (tmp,ERROR); } else { /* light tryssl flag if requested */ mb.trysslflag = (options & NOP_TRYSSL) ? T : NIL; /* default port */ if (mb.port) port = mb.port; else if (!port) port = nntp_port ? nntp_port : NNTPTCPPORT; if (netstream = /* try to open ordinary connection */ net_open (&mb,dv,port, (NETDRIVER *) mail_parameters (NIL,GET_SSLDRIVER,NIL), "*nntps",nntp_sslport ? nntp_sslport : NNTPSSLPORT)) { stream = (SENDSTREAM *) fs_get (sizeof (SENDSTREAM)); /* initialize stream */ memset ((void *) stream,0,sizeof (SENDSTREAM)); stream->netstream = netstream; stream->host = cpystr ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL) ? net_host (netstream) : mb.host); stream->debug = (mb.dbgflag || (options & NOP_DEBUG)) ? T : NIL; if (mb.loser) stream->loser = T; /* process greeting */ switch ((int) nntp_reply (stream)) { case NNTPGREET: /* allow posting */ NNTP.post = T; mm_notify (NIL,stream->reply + 4,(long) NIL); break; case NNTPGREETNOPOST: /* posting not allowed, must be readonly */ NNTP.post = NIL; break; default: mm_log (stream->reply,ERROR); stream = nntp_close (stream); break; } } } } while (!stream && *++hostlist); /* get extensions */ if (stream && extok) extok = nntp_extensions (stream,(mb.secflag ? AU_SECURE : NIL) | (mb.authuser[0] ? AU_AUTHUSER : NIL)); if (stream && !dv && stls && NNTP.ext.starttls && !mb.sslflag && !mb.notlsflag && (nntp_send_work (stream,"STARTTLS",NNTP.ext.multidomain ? mb.host : NIL) == NNTPTLSSTART)) { mb.tlsflag = T; /* TLS OK, get into TLS at this end */ stream->netstream->dtb = ssld; /* negotiate TLS */ if (stream->netstream->stream = (*stls) (stream->netstream->stream,mb.host, (mb.tlssslv23 ? NIL : NET_TLSCLIENT) | (mb.novalidate ? NET_NOVALIDATECERT:NIL))) extok = nntp_extensions (stream,(mb.secflag ? AU_SECURE : NIL) | (mb.authuser[0] ? AU_AUTHUSER : NIL)); else { sprintf (tmp,"Unable to negotiate TLS with this server: %.80s",mb.host); mm_log (tmp,ERROR); /* close without doing QUIT */ if (stream->netstream) net_close (stream->netstream); stream->netstream = NIL; stream = nntp_close (stream); } } else if (mb.tlsflag) { /* user specified /tls but can't do it */ mm_log ("Unable to negotiate TLS with this server",ERROR); return NIL; } if (stream) { /* have a session? */ if (mb.user[0]) { /* yes, have user name? */ if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) { /* remote name for authentication */ strncpy (mb.host,(long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (netstream) : net_host (netstream), NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } if (!nntp_send_auth_work (stream,&mb,tmp,NIL)) stream = nntp_close (stream); } /* authenticate if no-post and not readonly */ else if (!(NNTP.post || (options & NOP_READONLY) || nntp_send_auth (stream,NIL))) stream = nntp_close (stream); } /* in case server demands MODE READER */ if (stream) switch ((int) nntp_send_work (stream,"MODE","READER")) { case NNTPGREET: NNTP.post = T; break; case NNTPGREETNOPOST: NNTP.post = NIL; break; case NNTPWANTAUTH: /* server wants auth first, do so and retry */ case NNTPWANTAUTH2: /* remote name for authentication */ if ((long) mail_parameters (NIL,GET_TRUSTDNS,NIL)) { strncpy (mb.host,(long) mail_parameters (NIL,GET_SASLUSESPTRNAME,NIL) ? net_remotehost (netstream) : net_host (netstream),NETMAXHOST-1); mb.host[NETMAXHOST-1] = '\0'; } if (nntp_send_auth_work (stream,&mb,tmp,NIL)) switch ((int) nntp_send (stream,"MODE","READER")) { case NNTPGREET: NNTP.post = T; break; case NNTPGREETNOPOST: NNTP.post = NIL; break; } else stream = nntp_close (stream); break; } if (stream) { /* looks like we have a stream? */ /* yes, make sure can post if not readonly */ if (!(NNTP.post || (options & NOP_READONLY))) stream = nntp_close (stream); else if (extok) nntp_extensions (stream,(mb.secflag ? AU_SECURE : NIL) | (mb.authuser[0] ? AU_AUTHUSER : NIL)); } return stream;}/* NNTP extensions * Accepts: stream * authenticator flags * Returns: T on success, NIL on failure */long nntp_extensions (SENDSTREAM *stream,long flags){ unsigned long i; char *t,*r,*args; /* zap all old extensions */ memset (&NNTP.ext,0,sizeof (NNTP.ext)); if (stream->loser) return NIL;/* nothing at all for losers */ /* get server extensions */ switch ((int) nntp_send_work (stream,"LIST","EXTENSIONS")) { case NNTPEXTOK: /* what NNTP base spec says */ case NNTPGLIST: /* some servers do this instead */ break; default: /* no LIST EXTENSIONS on this server */ return NIL; } NNTP.ext.ok = T; /* server offers extensions */ while ((t = net_getline (stream->netstream)) && (t[1] || (*t != '.'))) { if (stream->debug) mm_dlog (t); /* get optional capability arguments */ if (args = strchr (t,' ')) *args++ = '\0'; if (!compare_cstring (t,"LISTGROUP")) NNTP.ext.listgroup = T; else if (!compare_cstring (t,"OVER")) NNTP.ext.over = T; else if (!compare_cstring (t,"HDR")) NNTP.ext.hdr = T; else if (!compare_cstring (t,"PAT")) NNTP.ext.pat = T; else if (!compare_cstring (t,"STARTTLS")) NNTP.ext.starttls = T; else if (!compare_cstring (t,"MULTIDOMAIN")) NNTP.ext.multidomain = T; else if (!compare_cstring (t,"AUTHINFO") && args) { char *sasl = NIL; for (args = strtok_r (args," ",&r); args; args = strtok_r (NIL," ",&r)) { if (!compare_cstring (args,"USER")) NNTP.ext.authuser = T; else if (((args[0] == 'S') || (args[0] == 's')) && ((args[1] == 'A') || (args[1] == 'a')) && ((args[2] == 'S') || (args[2] == 's')) && ((args[3] == 'L') || (args[3] == 'l')) && (args[4] == ':')) sasl = args + 5; } if (sasl) { /* if SASL, look up authenticators */ for (sasl = strtok_r (sasl,",",&r); sasl; sasl = strtok_r (NIL,",",&r)) if ((i = mail_lookup_auth_name (sasl,flags)) && (--i < MAXAUTHENTICATORS)) NNTP.ext.sasl |= (1 << i); /* disable LOGIN if PLAIN also advertised */ if ((i = mail_lookup_auth_name ("PLAIN",NIL)) && (--i < MAXAUTHENTICATORS) && (NNTP.ext.sasl & (1 << i)) && (i = mail_lookup_auth_name ("LOGIN",NIL)) && (--i < MAXAUTHENTICATORS)) NNTP.ext.sasl &= ~(1 << i); } } fs_give ((void **) &t); } if (t) { /* flush end of text indicator */ if (stream->debug) mm_dlog (t); fs_give ((void **) &t); } return LONGT;}/* NNTP close connection * Accepts: SEND stream * Returns: NIL always */SENDSTREAM *nntp_close (SENDSTREAM *stream){ if (stream) { /* send "QUIT" */ if (stream->netstream) nntp_send (stream,"QUIT",NIL); /* do close actions */ if (stream->netstream) net_close (stream->netstream); if (stream->host) fs_give ((void **) &stream->host); if (stream->reply) fs_give ((void **) &stream->reply); fs_give ((void **) &stream);/* flush the stream */ } return NIL;}/* NNTP deliver news * Accepts: SEND stream * message envelope * message body * Returns: T on success, NIL on failure */long nntp_mail (SENDSTREAM *stream,ENVELOPE *env,BODY *body){ long ret; RFC822BUFFER buf; char *s,path[MAILTMPLEN],tmp[SENDBUFLEN+1]; long error = NIL; long retry = NIL; buf.f = nntp_soutr; /* initialize buffer */ buf.s = stream->netstream; buf.end = (buf.beg = buf.cur = tmp) + SENDBUFLEN; tmp[SENDBUFLEN] = '\0'; /* must have additional null guard byte */ /* Gabba gabba hey, we need some brain damage to send netnews!!! * * First, we give ourselves a frontal lobotomy, and put in some UUCP * syntax. It doesn't matter that it's completely bogus UUCP, and * that UUCP has nothing to do with anything we're doing. It's been * alleged that "Path: not-for-mail" is also acceptable, but we won't * make assumptions unless the user says so. * * Second, we bop ourselves on the head with a ball-peen hammer. How
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -