📄 htnews.c
字号:
BOOL skip_this_line = NO; BOOL skip_rest_of_line = NO; int listing = 0; char *pattern = NULL; int len = 0; /* ** Support head or tail matches for groups to list. - FM */ if (arg && strlen(arg) > 1) { if (*arg == '*') { tail = YES; StrAllocCopy(pattern, (arg+1)); } else if (arg[strlen(arg)-1] == '*') { head = YES; StrAllocCopy(pattern, arg); pattern[strlen(pattern)-1] = '\0'; } if (tail || head) { len = strlen(pattern); } } /* ** Read the server's reply. ** ** The lines are scanned for newsgroup ** names and descriptions. */ START(HTML_HEAD); PUTC('\n'); START(HTML_TITLE); PUTS("Newsgroups"); END(HTML_TITLE); PUTC('\n'); END(HTML_HEAD); PUTC('\n'); START(HTML_H1); PUTS( "Newsgroups"); END(HTML_H1); PUTC('\n'); p = line; START(HTML_DLC); PUTC('\n'); while (!done) { int ich = NEXT_CHAR; char ch = (char) ich; if (ich == EOF) { if (interrupted_in_htgetcharacter) { interrupted_in_htgetcharacter = 0; CTRACE((tfp, "HTNews: Interrupted on read, closing socket %d\n", s)); NEWS_NETCLOSE(s); s = -1; return(HT_INTERRUPTED); } abort_socket(); /* End of file, close socket */ FREE(pattern); return(HT_LOADED); /* End of file on response */ } else if (skip_this_line) { if (ch == LF) { skip_this_line = skip_rest_of_line = NO; p = line; } continue; } else if (skip_rest_of_line) { if (ch != LF) { continue; } } else if (p == &line[LINE_LENGTH]) { CTRACE((tfp, "b %.*s%c[...]\n", (LINE_LENGTH), line, ch)); *p = '\0'; if (ch == LF) { ; /* Will be dealt with below */ } else if (WHITE(ch)) { ch = LF; /* May treat as line without description */ skip_this_line = YES; /* ...and ignore until LF */ } else if (strchr(line, ' ') == NULL && strchr(line, '\t') == NULL) { /* No separator found */ CTRACE((tfp, "HTNews..... group name too long, discarding.\n")); skip_this_line = YES; /* ignore whole line */ continue; } else { skip_rest_of_line = YES; /* skip until ch == LF found */ } } else { *p++ = ch; } if (ch == LF) { skip_rest_of_line = NO; /* done, reset flag */ *p = '\0'; /* Terminate the string */ CTRACE((tfp, "B %s", line)); if (line[0] == '.') { /* ** End of article? */ if (UCH(line[1]) < ' ') { done = YES; break; } else { /* Line starts with dot */ START(HTML_DT); PUTS(&line[1]); MAYBE_END(HTML_DT); } } else if (line[0] == '#') { /* Comment? */ p = line; /* Restart at beginning */ continue; } else { /* ** Normal lines are scanned for references to newsgroups. */ int i = 0; /* find whitespace if it exits */ for (; line[i] != '\0' && !WHITE(line[i]); i++) ; /* null body */ if (line[i] != '\0') { line[i] = '\0'; if ((head && strncasecomp(line, pattern, len)) || (tail && (i < len || strcasecomp((line + (i - len)), pattern)))) { p = line; /* Restart at beginning */ continue; } START(HTML_DT); write_anchor(line, line); listing++; MAYBE_END(HTML_DT); PUTC('\n'); START(HTML_DD); PUTS(&line[i+1]); /* put description */ MAYBE_END(HTML_DD); } else { if ((head && strncasecomp(line, pattern, len)) || (tail && (i < len || strcasecomp((line + (i - len)), pattern)))) { p = line; /* Restart at beginning */ continue; } START(HTML_DT); write_anchor(line, line); MAYBE_END(HTML_DT); listing++; } } /* if not dot */ p = line; /* Restart at beginning */ } /* if end of line */ } /* Loop over characters */ if (!listing) { char *msg = NULL; START(HTML_DT); HTSprintf0(&msg, gettext("No matches for: %s"), arg); PUTS(msg); MAYBE_END(HTML_DT); FREE(msg); } END(HTML_DLC); PUTC('\n'); FREE(pattern); return(HT_LOADED);}/* Read in a Newsgroup** -------------------**** Unfortunately, we have to ask for each article one by one if we** want more than one field.***/PRIVATE int read_group ARGS3( CONST char *, groupName, int, first_required, int, last_required){ char line[LINE_LENGTH+1]; char author[LINE_LENGTH+1]; char subject[LINE_LENGTH+1]; char *date = NULL; int i; char *p; BOOL done; char buffer[LINE_LENGTH+1]; char *temp = NULL; char *reference = NULL; /* Href for article */ int art; /* Article number WITHIN GROUP */ int status, count, first, last; /* Response fields */ /* count is only an upper limit */ author[0] = '\0'; START(HTML_HEAD); PUTC('\n'); START(HTML_TITLE); PUTS("Newsgroup "); PUTS(groupName); END(HTML_TITLE); PUTC('\n'); END(HTML_HEAD); PUTC('\n'); sscanf(response_text, " %d %d %d %d", &status, &count, &first, &last); CTRACE((tfp, "Newsgroup status=%d, count=%d, (%d-%d) required:(%d-%d)\n", status, count, first, last, first_required, last_required)); if (last == 0) { PUTS(gettext("\nNo articles in this group.\n")); goto add_post; }#define FAST_THRESHOLD 100 /* Above this, read IDs fast */#define CHOP_THRESHOLD 50 /* Above this, chop off the rest */ if (first_required < first) first_required = first; /* clip */ if ((last_required == 0) || (last_required > last)) last_required = last; if (last_required < first_required) { PUTS(gettext("\nNo articles in this range.\n")); goto add_post; } if (last_required-first_required+1 > HTNewsMaxChunk) { /* Trim this block */ first_required = last_required-HTNewsChunkSize+1; } CTRACE((tfp, " Chunk will be (%d-%d)\n", first_required, last_required)); /* ** Set window title. */ HTSprintf0(&temp, gettext("%s, Articles %d-%d"), groupName, first_required, last_required); START(HTML_H1); PUTS(temp); FREE(temp); END(HTML_H1); PUTC('\n'); /* ** Link to earlier articles. */ if (first_required > first) { int before; /* Start of one before */ if (first_required-HTNewsMaxChunk <= first) before = first; else before = first_required-HTNewsChunkSize; HTSprintf0(&dbuf, "%s%s/%d-%d", NewsHREF, groupName, before, first_required-1); CTRACE((tfp, " Block before is %s\n", dbuf)); PUTC('('); start_anchor(dbuf); PUTS(gettext("Earlier articles")); END(HTML_A); PUTS("...)\n"); START(HTML_P); PUTC('\n'); } done = NO;/*#define USE_XHDR*/#ifdef USE_XHDR if (count > FAST_THRESHOLD) { HTSprintf0(&temp, gettext("\nThere are about %d articles currently available in %s, IDs as follows:\n\n"), count, groupName); PUTS(temp); FREE(temp); sprintf(buffer, "XHDR Message-ID %d-%d%c%c", first, last, CR, LF); status = response(buffer); if (status == 221) { p = line; while (!done) { int ich = NEXT_CHAR; *p++ = ich; if (ich == EOF) { if (interrupted_in_htgetcharacter) { interrupted_in_htgetcharacter = 0; CTRACE((tfp, "HTNews: Interrupted on read, closing socket %d\n", s)); NEWS_NETCLOSE(s); s = -1; return(HT_INTERRUPTED); } abort_socket(); /* End of file, close socket */ return(HT_LOADED); /* End of file on response */ } if (((char)ich == '\n') || (p == &line[LINE_LENGTH])) { *p = '\0'; /* Terminate the string */ CTRACE((tfp, "X %s", line)); if (line[0] == '.') { /* ** End of article? */ if (UCH(line[1]) < ' ') { done = YES; break; } else { /* Line starts with dot */ /* Ignore strange line */ } } else { /* ** Normal lines are scanned for ** references to articles. */ char * space = strchr(line, ' '); if (space++) write_anchor(space, space); } /* if not dot */ p = line; /* Restart at beginning */ } /* if end of line */ } /* Loop over characters */ /* leaving loop with "done" set */ } /* Good status */ }#endif /* USE_XHDR */ /* ** Read newsgroup using individual fields. */ if (!done) { START(HTML_B); if (first == first_required && last == last_required) PUTS(gettext("All available articles in ")); else PUTS("Articles in "); PUTS(groupName); END(HTML_B); PUTC('\n'); if (LYListNewsNumbers) start_list(first_required); else START(HTML_UL); for (art = first_required; art <= last_required; art++) {/*#define OVERLAP*/#ifdef OVERLAP /* ** With this code we try to keep the server running flat out ** by queuing just one extra command ahead of time. ** We assume (1) that the server won't abort if it gets input ** during output, and (2) that TCP buffering is enough for the ** two commands. Both these assumptions seem very reasonable. ** However, we HAVE had a hangup with a loaded server. */ if (art == first_required) { if (art == last_required) { /* Only one */ sprintf(buffer, "HEAD %d%c%c", art, CR, LF); status = response(buffer); } else { /* First of many */ sprintf(buffer, "HEAD %d%c%cHEAD %d%c%c", art, CR, LF, art+1, CR, LF); status = response(buffer); } } else if (art == last_required) { /* Last of many */ status = response(NULL); } else { /* Middle of many */ sprintf(buffer, "HEAD %d%c%c", art+1, CR, LF); status = response(buffer); }#else /* Not OVERLAP: */ sprintf(buffer, "HEAD %d%c%c", art, CR, LF); status = response(buffer);#endif /* OVERLAP */ /* ** Check for a good response (221) for the HEAD request, ** and if so, parse it. Otherwise, indicate the error ** so that the number of listings corresponds to what's ** claimed for the range, and if we are listing numbers ** via an ordered list, they stay in synchrony with the ** article numbers. - FM */ if (status == 221) { /* Head follows - parse it:*/ p = line; /* Write pointer */ done = NO; while( !done ) { int ich = NEXT_CHAR; *p++ = (char) ich; if (ich == EOF) { if (interrupted_in_htgetcharacter) { interrupted_in_htgetcharacter = 0; CTRACE((tfp, "HTNews: Interrupted on read, closing socket %d\n", s)); NEWS_NETCLOSE(s); s = -1; return(HT_INTERRUPTED); } abort_socket(); /* End of file, close socket */ return(HT_LOADED); /* End of file on response */ } if (((char)ich == LF) || (p == &line[LINE_LENGTH])) { *--p = '\0'; /* Terminate & chop LF*/ p = line; /* Restart at beginning */ CTRACE((tfp, "G %s\n", line)); switch(line[0]) { case '.': /* ** End of article? */ done = (BOOL) (UCH(line[1]) < ' '); break; case 'S': case 's': if (match(line, "SUBJECT:")) { LYstrncpy(subject, line+9, sizeof(subject)-1);/* Save subject */ decode_mime(subject); } break; case 'M': case 'm': if (match(line, "MESSAGE-ID:")) { char * addr = HTStrip(line+11) +1; /* Chop < */ addr[strlen(addr)-1] = '\0'; /* Chop > */ StrAllocCopy(reference, addr); } break; case 'f': case 'F': if (match(line, "FROM:")) { char * p2; LYstrncpy(author, author_name(strchr(line,':')+1), sizeof(author)-1); decode_mime(author); p2 = author + strlen(author) - 1; if (*p2==LF) *p2 = '\0'; /* Chop off newline */ } break; case 'd': case 'D': if (LYListNewsDates && match(line, "DATE:")) { StrAllocCopy(date, HTStrip(strchr(line,':')+1)); } break; } /* end switch on first character */ } /* if end of line */ } /* Loop over characters */ PUTC('\n'); START(HTML_LI);#ifdef SH_EX /* for MIME */ HTSprintf0(&temp, "\"%s\"", decode_mime(subject));#else HTSprintf0(&temp, "\"%s\"", subject);#endif if (reference) { write_anchor(temp, reference); FREE(reference); } else { PUTS(temp); } FREE(temp); if (author[0] != '\0') { PUTS(" - "); if (LYListNewsDates) START(HTML_I);#ifdef SH_EX /* for MIME */ PUTS(decode_mime(author));#else PUTS(author);#endif if (LYListNewsDates) END(HTML_I); author[0] = '\0'; } if (date) { if (!diagnostic) { for (i = 0; date[i]; i++) { if (date[i] == ' ') { date[i] = HT_NON_BREAK_SPACE; } } } sprintf(buffer, " [%.*s]", (int)(sizeof(buffer) - 4), date); PUTS(buffer); FREE(date); } MAYBE_END(HTML_LI); /* ** Indicate progress! @@@@@@ */ } else if (status == HT_INTERRUPTED) { interrupted_in_htgetcharacter = 0; CTRACE((tfp, "HTNews: Interrupted on read, closing socket %d\n", s)); NEWS_NETCLOSE(s); s = -1; return(HT_INTERRUPTED); } else { /* ** Use the response text on error. - FM */ PUTC('\n'); START(HTML_LI); START(HTML_I); if (LYListNewsNumbers)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -