📄 nntp.c
字号:
/* 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 */void nntp_expunge (MAILSTREAM *stream){ if (!stream->silent) mm_log ("Expunge ignored on readonly mailbox",NIL);}/* 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; NETMBX mb; char tmp[MAILTMPLEN]; 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 || mb.secflag || mb.authuser[0]) { sprintf (tmp,"Invalid host specifier: %.80s",*hostlist); mm_log (tmp,ERROR); } else { /* light tryalt flag if requested */ mb.tryaltflag = (options & OP_TRYALT) ? T : NIL; if (netstream = /* try to open ordinary connection */ net_open (&mb,dv,nntp_port ? nntp_port : port, (NETDRIVER *) mail_parameters (NIL,GET_ALTDRIVER,NIL), (char *) mail_parameters (NIL,GET_ALTNNTPNAME,NIL), (unsigned long)mail_parameters(NIL,GET_ALTNNTPPORT,NIL))) { stream = (SENDSTREAM *) fs_get (sizeof (SENDSTREAM)); /* initialize stream */ memset ((void *) stream,0,sizeof (SENDSTREAM)); stream->netstream = netstream; stream->debug = (mb.dbgflag || (options & OP_DEBUG)) ? T : NIL; /* get server 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 */ if (options & OP_READONLY) { mm_notify (NIL,stream->reply + 4,(long) NIL); break; } /* falls through */ default: /* anything else is an error */ mm_log (stream->reply,ERROR); stream = nntp_close (stream); } } } } while (!stream && *++hostlist); /* have a session, log in if have user name */ if (mb.user[0] && !nntp_send_auth_work (stream,&mb,tmp)) { nntp_close (stream); /* punt stream */ return NIL; } /* in case server demands MODE READER */ if (stream) switch ((int) nntp_send_work (stream,"MODE","READER")) { case NNTPWANTAUTH: /* server wants auth first, do so and retry */ case NNTPWANTAUTH2: if (nntp_send_auth_work(stream,&mb,tmp)) nntp_send(stream,"MODE","READER"); else stream = nntp_close (stream); break; default: /* only authenticate if requested */ if (mb.user[0] && !nntp_send_auth_work (stream,&mb,tmp)) stream = nntp_close (stream); break; } return stream;}/* NNTP close connection * Accepts: SEND stream * Returns: NIL always */SENDSTREAM *nntp_close (SENDSTREAM *stream){ if (stream) { /* send "QUIT" */ if (stream->netstream) { /* only if a living stream */ nntp_send (stream,"QUIT",NIL); /* close NET connection */ net_close (stream->netstream); } 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; char *s,path[MAILTMPLEN],tmp[8*MAILTMPLEN]; /* 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 all that's needed, but without * proof, it's probably not safe to make assumptions. * * Second, we bop ourselves on the head with a ball-peen hammer. How * dare we be so presumptious as to insert a *comment* in a Date: * header line. Why, we were actually trying to be nice to a human * by giving a symbolic timezone (such as PST) in addition to a * numeric timezone (such as -0800). But the gods of news transport * will have none of this. Unix weenies, tried and true, rule!!! * * Third, Netscape Collabra server doesn't give the NNTPWANTAUTH error * until after requesting and receiving the entire message. So we can't * call rely upon nntp_send()'s to do the auth retry. */ /* RFC-1036 requires this cretinism */ sprintf (path,"Path: %s!%s\015\012",net_localhost (stream->netstream), env->sender ? env->sender->mailbox : (env->from ? env->from->mailbox : "not-for-mail")); /* here's another cretinism */ if (s = strstr (env->date," (")) *s = NIL; do if ((ret = nntp_send_work (stream,"POST",NIL)) == NNTPREADY) /* output data, return success status */ ret = (net_soutr (stream->netstream,path) && rfc822_output (tmp,env,body,nntp_soutr,stream->netstream,T)) ? nntp_send_work (stream,".",NIL) : nntp_fake (stream,NNTPSOFTFATAL, "NNTP connection broken (message text)"); while (((ret == NNTPWANTAUTH) || (ret == NNTPWANTAUTH2)) && nntp_send_auth (stream)); if (s) *s = ' '; /* put the comment in the date back */ if (ret == NNTPOK) return LONGT; else if (ret < 400) { /* if not an error reply */ sprintf (tmp,"Unexpected NNTP posting reply code %ld",ret); mm_log (tmp,WARN); /* so someone looks at this eventually */ if ((ret >= 200) && (ret < 300)) return LONGT; } return NIL;}/* NNTP send command * Accepts: SEND stream * text * Returns: reply code */long nntp_send (SENDSTREAM *stream,char *command,char *args){ long ret; switch ((int) (ret = nntp_send_work (stream,command,args))) { case NNTPWANTAUTH: /* authenticate and retry */ case NNTPWANTAUTH2: if (nntp_send_auth (stream)) ret = nntp_send_work (stream,command,args); else { /* we're probably hosed, nuke the session */ nntp_send (stream,"QUIT",NIL); /* close net connection */ net_close (stream->netstream); stream->netstream = NIL; } default: /* all others just return */ break; } return ret;}/* NNTP send command worker routine * Accepts: SEND stream * text * Returns: reply code */long nntp_send_work (SENDSTREAM *stream,char *command,char *args){ long ret; char *s = (char *) fs_get (strlen (command) + (args ? strlen (args) + 1 : 0) + 3); /* build the complete command */ if (args) sprintf (s,"%s %s",command,args); else strcpy (s,command); if (stream->debug) mm_dlog (s); strcat (s,"\015\012"); /* send the command */ ret = net_soutr (stream->netstream,s) ? nntp_reply (stream) : nntp_fake (stream,NNTPSOFTFATAL,"NNTP connection broken (command)"); fs_give ((void **) &s); return ret;}/* NNTP send authentication if needed * Accepts: SEND stream * Returns: T if need to redo command, NIL otherwise */long nntp_send_auth (SENDSTREAM *stream){ NETMBX mb; char tmp[MAILTMPLEN]; sprintf (tmp,"{%.200s/nntp",net_host (stream->netstream)); if (stream->netstream->dtb == (NETDRIVER *) mail_parameters (NIL,GET_ALTDRIVER,NIL)) sprintf (tmp + strlen (tmp),"/%.200s", (char *) mail_parameters (NIL,GET_ALTDRIVERNAME,NIL)); strcat (tmp,"}<none>"); mail_valid_net_parse (tmp,&mb); return nntp_send_auth_work (stream,&mb,tmp);}/* NNTP send authentication worker routine * Accepts: SEND stream * NETMBX structure * temporary buffer * Returns: T if authenticated, NIL otherwise */long nntp_send_auth_work (SENDSTREAM *stream,NETMBX *mb,char *tmp){ long i; long trial = 0; do { /* get user name and password */ mm_login (mb,mb->user,tmp,trial++); if (!*tmp) { /* abort if he refused to give password */ mm_log ("Login aborted",ERROR); break; } /* do the authentication */ if ((i = nntp_send_work (stream,"AUTHINFO USER",mb->user)) == NNTPWANTPASS) i = nntp_send_work (stream,"AUTHINFO PASS",tmp); /* successful authentication */ if (i == NNTPAUTHED) return T; mm_log (stream->reply,WARN); } while ((i != NNTPSOFTFATAL) && (trial < nntp_maxlogintrials)); mm_log ("Too many NNTP authentication failures",ERROR); return NIL; /* authentication failed */}/* NNTP get reply * Accepts: SEND stream * Returns: reply code */long nntp_reply (SENDSTREAM *stream){ /* flush old reply */ if (stream->reply) fs_give ((void **) &stream->reply); /* get reply */ if (!(stream->reply = net_getline (stream->netstream))) return nntp_fake(stream,NNTPSOFTFATAL,"NNTP connection broken (response)"); if (stream->debug) mm_dlog (stream->reply); /* handle continuation by recursion */ if (stream->reply[3] == '-') return nntp_reply (stream); /* return response code */ return stream->replycode = atol (stream->reply);}/* NNTP set fake error * Accepts: SEND stream * NNTP error code * error text * Returns: error code */long nntp_fake (SENDSTREAM *stream,long code,char *text){ /* flush any old reply */ if (stream->reply) fs_give ((void **) &stream->reply); /* set up pseudo-reply string */ stream->reply = (char *) fs_get (20+strlen (text)); sprintf (stream->reply,"%ld %s",code,text); return code; /* return error code */}/* NNTP filter mail * Accepts: stream * string * Returns: T on success, NIL on failure */long nntp_soutr (void *stream,char *s){ char c,*t; /* "." on first line */ if (s[0] == '.') net_soutr (stream,"."); /* find lines beginning with a "." */ while (t = strstr (s,"\015\012.")) { c = *(t += 3); /* remember next character after "." */ *t = '\0'; /* tie off string */ /* output prefix */ if (!net_soutr (stream,s)) return NIL; *t = c; /* restore delimiter */ s = t - 1; /* push pointer up to the "." */ } /* output remainder of text */ return *s ? net_soutr (stream,s) : T;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -