diff options
| -rw-r--r-- | ChangeLog | 38 | ||||
| -rw-r--r-- | XMakefile | 6 | ||||
| -rw-r--r-- | file.c | 98 | ||||
| -rw-r--r-- | fm.h | 7 | ||||
| -rw-r--r-- | html.h | 7 | ||||
| -rw-r--r-- | main.c | 16 | ||||
| -rw-r--r-- | news.c | 438 | ||||
| -rw-r--r-- | proto.h | 7 | ||||
| -rw-r--r-- | rc.c | 18 | ||||
| -rw-r--r-- | url.c | 99 | 
10 files changed, 612 insertions, 122 deletions
| @@ -1,5 +1,41 @@  2002-12-28  Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp> +	* [w3m-dev 03608] news:<newsgroup> +	* XMakefile (LSRCS): add news.c +		(LOBJS): add news.o +	* file.c (loadSOmething): don't UFclose() for nntp/news +		(readHeader): remove . at beginning of line for news +			img link to file: +		(loadGeneralFile): add SCM_NEWS_GROUP +			don't UFclose() for nntp/news +		(loadHTMLstream): . line check for news +		(loadBuffer): . line check for news +	* fm.h (NNTP_server): added +		(NNTP_mode): added +		(MaxNewsMessage): added +	* html.h (SCM_NEWS_GROUP): added +	* main.c (main): NNTP_server or NNTPSERVER +			NNTP_mode or NNTPMODE +			add SCM_NEWS_GROUP +		(followA): remove news:..@.. check +		(cmd_loadURL): remove news:...@.. check +		(w3m_exit): disconnectNews +	* proto.h (openNewsStream): added +		(readNewsgroup): added +		(disconnectNews): added +	* rc.c (CMT_NNTP_SERVER): added +		(CMT_NNTP_MODE): added +		(CMT_MAX_NEWS): added +		(params9): add nntpserver, nntpmode, max_news +	* url.c (DefaultPort): add 119 for news group +		(parseURL2): news:..@... is SCM_NEWS_GROUP +		(_parsedURL2Str): add news for SCM_NEWS_GROUP +		(openURL): cleanup SCM_NEWS +			add SCM_NEWS_GROUP +	* news.c: added +	 +2002-12-28  Hironori SAKAMOTO <hsaka@mth.biglobe.ne.jp> +  	* [w3m-dev 03607] mymktime: time zone support  	* etc.c (get_zone): added  		(mymktime): parse timezone @@ -6103,4 +6139,4 @@ a	* [w3m-dev 03276] compile error on EWS4800  	* release-0-2-1  	* import w3m-0.2.1 -$Id: ChangeLog,v 1.651 2002/12/27 15:53:03 ukai Exp $ +$Id: ChangeLog,v 1.652 2002/12/27 16:07:44 ukai Exp $ @@ -1,4 +1,4 @@ -# $Id: XMakefile,v 1.33 2002/11/13 15:53:45 ukai Exp $ +# $Id: XMakefile,v 1.34 2002/12/27 16:07:44 ukai Exp $  SRCS=main.c file.c buffer.c display.c etc.c search.c linein.c table.c local.c \  	form.c map.c frame.c rc.c menu.c mailcap.c image.c\  	func.c cookie.c history.c backend.c $(KEYBIND_SRC) @@ -6,9 +6,9 @@ OBJS=main.o file.o buffer.o display.o etc.o search.o linein.o table.o local.o\  	form.o map.o frame.o rc.o menu.o mailcap.o image.o\  	func.o cookie.o history.o backend.o $(KEYBIND_OBJ)  LSRCS=terms.c conv.c url.c ftp.c anchor.c mimehead.c parsetagx.c\ -	tagtable.c istream.c +	tagtable.c istream.c news.c  LOBJS=terms.o conv.o url.o ftp.o anchor.o mimehead.o parsetagx.o\ -	tagtable.o istream.o +	tagtable.o istream.o news.o  LLOBJS=version.o  ALIBOBJS=Str.o indep.o regex.o textlist.o parsetag.o myctype.o entity.o hash.o  ALIB=libindep.a @@ -1,4 +1,4 @@ -/* $Id: file.c,v 1.171 2002/12/26 15:25:04 ukai Exp $ */ +/* $Id: file.c,v 1.172 2002/12/27 16:07:44 ukai Exp $ */  #include "fm.h"  #include <sys/types.h>  #include "myctype.h" @@ -222,7 +222,8 @@ loadSomething(URLFile *f,      buf->real_scheme = f->scheme;      if (f->scheme == SCM_LOCAL && buf->sourcefile == NULL)  	buf->sourcefile = path; -    UFclose(f); +    if (f->scheme != SCM_NNTP && f->scheme != SCM_NEWS) +	UFclose(f);      return buf;  } @@ -577,6 +578,10 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)  	    newBuf->header_source = tmpf->ptr;      }      while ((tmp = StrmyUFgets(uf))->length) { +#ifdef USE_NNTP +	if (uf->scheme == SCM_NEWS && tmp->ptr[0] == '.') +	    Strshrinkfirst(tmp, 1); +#endif  #ifdef HTTP_DEBUG  	{  	    FILE *ff; @@ -588,13 +593,7 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)  	if (src)  	    Strfputs(tmp, src);  	cleanup_line(tmp, HEADER_MODE); -	if ((tmp->ptr[0] == '\n' || tmp->ptr[0] == '\r' || tmp->ptr[0] == '\0') -#ifdef USE_NNTP -	    || -	    (uf->scheme == SCM_NEWS && -	     Str_news_endline(tmp) && (iseos(uf->stream) = TRUE)) -#endif				/* USE_NNTP */ -	    ) { +	if (tmp->ptr[0] == '\n' || tmp->ptr[0] == '\r' || tmp->ptr[0] == '\0') {  	    if (!lineBuf2)  		/* there is no header */  		break; @@ -651,7 +650,7 @@ readHeader(URLFile *uf, Buffer *newBuf, int thru, ParsedURL *pu)  		if (tmpf) {  		    src =  			Sprintf -			("<img src=\"%s\" alt=\"X-Face\" width=48 height=48>", +			("<img src=\"file:%s\" alt=\"X-Face\" width=48 height=48>",  			 html_quote(tmpf));  		    init_stream(&f, SCM_LOCAL, newStrStream(src));  		    loadHTMLstream(&f, newBuf, NULL, TRUE); @@ -1580,6 +1579,34 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  		}  	    }  	    break; +#ifdef USE_NNTP +	case SCM_NEWS_GROUP: +	    { +		Str group = readNewsgroup(&pu); +		if (group && group->length > 0) { +		    FILE *src; +		    tmp = tmpfname(TMPF_SRC, ".html"); +		    pushText(fileToDelete, tmp->ptr); +		    src = fopen(tmp->ptr, "w"); +		    if (src) { +			Strfputs(group, src); +			fclose(src); +		    } +		    b = loadHTMLString(group); +		    if (b) { +			b->real_type = "news:group"; +			if (b->currentURL.host == NULL +			    && b->currentURL.file == NULL) +			    copyParsedURL(&b->currentURL, &pu); +			b->real_scheme = pu.scheme; +			if (src) +			    b->sourcefile = tmp->ptr; +		    } +		    return b; +		} +	    } +	    break; +#endif  	case SCM_UNKNOWN:  #ifdef USE_EXTERNAL_URI_LOADER  	    tmp = searchURIMethods(&pu); @@ -1905,7 +1932,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  	doFileSave(f, file);  	if (f.scheme == SCM_FTP)  	    FTPhalfclose(f.stream); -	else +	else if (f.scheme != SCM_NNTP && f.scheme != SCM_NEWS)  	    UFclose(&f);  	return NO_BUFFER;      } @@ -1965,7 +1992,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  		if (b->currentURL.host == NULL && b->currentURL.file == NULL)  		    copyParsedURL(&b->currentURL, &pu);  	    } -	    UFclose(&f); +	    if (f.scheme != SCM_NNTP && f.scheme != SCM_NEWS) +		UFclose(&f);  	    if (fmInitialized)  		term_raw();  	    signal(SIGINT, prevtrap); @@ -1987,7 +2015,7 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,  		doFileSave(f, guess_save_name(t_buf, pu.file));  		if (f.scheme == SCM_FTP)  		    FTPhalfclose(f.stream); -		else +		else if (f.scheme != SCM_NNTP && f.scheme != SCM_NEWS)  		    UFclose(&f);  	    }  	    return NO_BUFFER; @@ -2005,7 +2033,8 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer,      frame_source = flag & RG_FRAME_SRC;      b = loadSomething(&f, pu.real_file ? pu.real_file : pu.file, proc, t_buf);      frame_source = 0; -    UFclose(&f); +    if (f.scheme != SCM_NNTP && f.scheme != SCM_NEWS) +        UFclose(&f);      if (b) {  	b->real_scheme = f.scheme;  	b->real_type = real_type; @@ -6343,6 +6372,7 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)      clen_t linelen = 0;      clen_t trbyte = 0;      Str lineBuf2 = Strnew(); +    char *p;      char code;      struct html_feed_environ htmlenv1;      struct readbuffer obuf; @@ -6424,6 +6454,18 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)      if (IStype(f->stream) != IST_ENCODED)  	f->stream = newEncodedStream(f->stream, f->encoding);      while ((lineBuf2 = StrmyUFgets(f))->length) { +#ifdef USE_NNTP +	if (f->scheme == SCM_NEWS && lineBuf2->ptr[0] == '.') { +	    Strshrinkfirst(lineBuf2, 1); +	    if (lineBuf2->ptr[0] == '\n' || lineBuf2->ptr[0] == '\r' || +	        lineBuf2->ptr[0] == '\0') { +/* +		iseos(f->stream) = TRUE; +*/ +		break; +	    } +	} +#endif				/* USE_NNTP */  	if (src)  	    Strfputs(lineBuf2, src);  	linelen += lineBuf2->length; @@ -6453,14 +6495,6 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal)  #endif  #endif  	} -#ifdef USE_NNTP -	if (f->scheme == SCM_NEWS) { -	    if (Str_news_endline(lineBuf2)) { -		iseos(f->stream) = TRUE; -		break; -	    } -	} -#endif				/* USE_NNTP */  	HTMLlineproc0(lineBuf2->ptr, &htmlenv1, internal);      }      if (obuf.status != R_ST_NORMAL) { @@ -6725,6 +6759,18 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf)      if (IStype(uf->stream) != IST_ENCODED)  	uf->stream = newEncodedStream(uf->stream, uf->encoding);      while ((lineBuf2 = StrmyISgets(uf->stream))->length) { +#ifdef USE_NNTP +	if (uf->scheme == SCM_NEWS && lineBuf2->ptr[0] == '.') { +	    Strshrinkfirst(lineBuf2, 1); +	    if (lineBuf2->ptr[0] == '\n' || lineBuf2->ptr[0] == '\r' || +	        lineBuf2->ptr[0] == '\0') { +/* +		iseos(uf->stream) = TRUE; +*/ +		break; +	    } +	} +#endif				/* USE_NNTP */  	if (src)  	    Strfputs(lineBuf2, src);  	linelen += lineBuf2->length; @@ -6742,14 +6788,6 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf)  	    pre_lbuf = lineBuf2->ptr[0];  	}  	++nlines; -#ifdef USE_NNTP -	if (uf->scheme == SCM_NEWS) { -	    if (Str_news_endline(lineBuf2)) { -		iseos(uf->stream) = TRUE; -		break; -	    } -	} -#endif				/* USE_NNTP */  	Strchop(lineBuf2);  	lineBuf2 = checkType(lineBuf2, propBuffer,  #ifdef USE_ANSI_COLOR @@ -1,4 +1,4 @@ -/* $Id: fm.h,v 1.99 2002/12/18 16:42:31 ukai Exp $ */ +/* $Id: fm.h,v 1.100 2002/12/27 16:07:44 ukai Exp $ */  /*    * w3m: WWW wo Miru utility   *  @@ -816,6 +816,11 @@ global char NoCache init(FALSE);  global char use_proxy init(TRUE);  #define Do_not_use_proxy (!use_proxy)  global int Do_not_use_ti_te init(FALSE); +#ifdef USE_NNTP +global char *NNTP_server init(NULL); +global char *NNTP_mode init(NULL); +global int MaxNewsMessage init(50); +#endif  global char *document_root init(NULL);  global char *personal_document_root init(NULL); @@ -1,4 +1,4 @@ -/* $Id: html.h,v 1.16 2002/12/14 15:18:38 ukai Exp $ */ +/* $Id: html.h,v 1.17 2002/12/27 16:07:44 ukai Exp $ */  #ifndef _HTML_H  #define _HTML_H  #ifdef USE_SSL @@ -362,9 +362,10 @@ struct environment {  #define SCM_EXEC	6  #define SCM_NNTP	7  #define SCM_NEWS	8 -#define SCM_MAILTO      9 +#define SCM_NEWS_GROUP	9 +#define SCM_MAILTO      10  #ifdef USE_SSL -#define SCM_HTTPS       10 +#define SCM_HTTPS       11  #endif				/* USE_SSL */  #endif				/* _HTML_H */ @@ -1,4 +1,4 @@ -/* $Id: main.c,v 1.182 2002/12/27 15:50:33 ukai Exp $ */ +/* $Id: main.c,v 1.183 2002/12/27 16:07:44 ukai Exp $ */  #define MAINPROGRAM  #include "fm.h"  #include <signal.h> @@ -445,6 +445,12 @@ main(int argc, char **argv, char **envp)  	((p = getenv("NO_PROXY")) ||  	 (p = getenv("no_proxy")) || (p = getenv("NO_proxy"))))  	NO_proxy = p; +#ifdef USE_NNTP +    if (!non_null(NNTP_server) && (p = getenv("NNTPSERVER")) != NULL) +	NNTP_server = p; +    if (!non_null(NNTP_mode) && (p = getenv("NNTPMODE")) != NULL) +	NNTP_mode = p; +#endif      if (!non_null(Editor) && (p = getenv("EDITOR")) != NULL)  	Editor = p; @@ -871,6 +877,7 @@ main(int argc, char **argv, char **envp)  #ifdef USE_NNTP  	    case SCM_NNTP:  	    case SCM_NEWS: +	    case SCM_NEWS_GROUP:  #endif				/* USE_NNTP */  	    case SCM_MAILTO:  		break; @@ -2869,7 +2876,7 @@ followA(void)  	pushHashHist(URLHist, a->url);  	return;      } -#ifdef USE_NNTP +#if 0      else if (!strncasecmp(a->url, "news:", 5) && strchr(a->url, '@') == NULL) {  	/* news:newsgroup is not supported */  	disp_err_message("news:newsgroup_name is not supported", TRUE); @@ -3824,7 +3831,7 @@ cmd_loadURL(char *url, ParsedURL *current, char *referer)  	pushHashHist(URLHist, url);  	return;      } -#ifdef USE_NNTP +#if 0      if (!strncasecmp(url, "news:", 5) && strchr(url, '@') == NULL) {  	/* news:newsgroup is not supported */  	disp_err_message("news:newsgroup_name is not supported", TRUE); @@ -5450,6 +5457,9 @@ w3m_exit(int i)  #ifdef USE_SSL      free_ssl_ctx();  #endif +#ifdef USE_NNTP +    disconnectNews(); +#endif      exit(i);  } @@ -0,0 +1,438 @@ +/* $Id: news.c,v 1.1 2002/12/27 16:07:44 ukai Exp $ */ +#include "fm.h" +#include "myctype.h" +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <signal.h> +#include <setjmp.h> + +#ifdef USE_NNTP + +#define NEWS_ENDLINE(p) \ +    ((*(p) == '.' && ((p)[1] == '\n' || (p)[1] == '\r' || (p)[1] == '\0')) || \ +    *(p) == '\n' || *(p) == '\r' || *(p) == '\0') + +typedef struct _News { +    char *host; +    int port; +    char *mode; +    InputStream rf; +    FILE *wf; +} News; + +static News current_news = { NULL, 0, NULL, NULL, NULL }; + +static JMP_BUF AbortLoading; + +static MySignalHandler +KeyAbort(SIGNAL_ARG) +{ +    LONGJMP(AbortLoading, 1); +    SIGNAL_RETURN; +} + +static Str +news_command(News *news, char *command, int *status) +{ +    Str tmp; +    char c; + +    if (!news->host) +	return NULL; +    if (command) { +	fprintf(news->wf, "%s\r\n", command); +	fflush(news->wf); +    } +    if (!status) +	return NULL; +    *status = -1; +    tmp = StrISgets(news->rf); +    if (tmp->length) +	sscanf(tmp->ptr, "%d", status); +    return tmp; +} + +static void +news_close(News *news) +{ +    if (!news->host) +	return; +    if (news->rf) { +	ISclose(news->rf); +	news->rf = NULL; +    } +    if (news->wf) { +	fclose(news->wf); +	news->wf = NULL; +    } +    news->host = NULL; +} + +static int +news_open(News *news) +{ +    Str tmp; +    int sock, status; + +    sock = openSocket(news->host, "nntp", news->port); +    if (sock < 0) +	goto open_err; +    news->rf = newInputStream(sock); +    news->wf = fdopen(dup(sock), "wb"); +    if (!news->rf || !news->wf) +	goto open_err; +    news_command(news, NULL, &status); +    if (status != 200 && status != 201) +	goto open_err; +    if (news->mode) { +	news_command(news, Sprintf("MODE %s", news->mode)->ptr, &status); +	if (status != 200 && status != 201) +	    goto open_err; +    } +    return TRUE; +  open_err: +    news_close(news); +    return FALSE; +} + +static void +news_quit(News *news) +{ +    news_command(news, "QUIT", NULL); +    news_close(news); +} + +static char * +name_from_address(char *str, int n) +{ +    char *s, *p; +    int i, l, space = TRUE; + +    s = allocStr(str, -1); +    SKIP_BLANKS(s); +    if (*s == '<' && (p = strchr(s, '>'))) { +	*p++ = '\0'; +	SKIP_BLANKS(p); +	if (*p == '\0')			/* <address> */ +	    s++; +	else				/* <address> name ? */ +	    s = p; +    } +    else if ((p = strchr(s, '<')))	/* name <address> */ +	*p = '\0'; +    else if ((p = strchr(s, '(')))	/* address (name) */ +	s = p; +    if (*s == '"' && (p = strchr(s + 1, '"'))) {	/* "name" */ +	*p = '\0'; +	s++; +    } +    else if (*s == '(' && (p = strchr(s + 1, ')'))) {	/* (name) */ +	*p = '\0'; +	s++; +    } +    for (p = s, l = 0; *p; p += i) { +	i = get_mclen(get_mctype(p)); +	if (IS_SPACE(*p)) { +	    if (space) +		continue; +	    space = TRUE; +	} +	else +	    space = FALSE; +	l += i; +	if (l > n) +	    break; +    } +    *p = '\0'; +    return s; +} + +static char * +html_quote_s(char *str) +{ +    Str tmp = NULL; +    char *p, *q; +    int space = TRUE; + +    for (p = str; *p; p++) { +	if (IS_SPACE(*p)) { +	    if (space) +		continue; +	    q = " "; +	    space = TRUE; +	} +	else { +	    q = html_quote_char(*p); +	    space = FALSE; +	} +	if (q) { +	    if (tmp == NULL) +		tmp = Strnew_charp_n(str, (int)(p - str)); +	    Strcat_charp(tmp, q); +	} +	else { +	    if (tmp) +		Strcat_char(tmp, *p); +	} +    } +    if (tmp) +	return tmp->ptr; +    return str; +} + +static void +add_news_message(Str str, int index, char *date, char *name, char *subject, +		 char *mid) +{ +    time_t t; +    struct tm *tm; + +    name = name_from_address(name, 16); +    t = mymktime(date); +    tm = localtime(&t); +    Strcat(str, +	   Sprintf("<tr valign=top><td>%d<td nowrap>(%02d/%02d)<td nowrap>%s<td><a href=\"news:%s\">%s</a>\n", +		   index, tm->tm_mon + 1, tm->tm_mday, html_quote_s(name), +		   html_quote(file_quote(mid)), html_quote(subject))); +} + +InputStream +openNewsStream(ParsedURL *pu) +{ +    char *host, *mode, *group, *p; +    Str tmp; +    int port, status; + +    if (pu->file == NULL || *pu->file == '\0') +	return NULL; +    if (pu->scheme == SCM_NNTP) +	host = pu->host; +    else +	host = NNTP_server; +    if (!host || *host == '\0') +	return NULL; +    if (pu->scheme != SCM_NNTP && (p = strchr(host, ':'))) { +	host = allocStr(host, p - host); +	port = atoi(p + 1); +    } +    else +	port = pu->port; +    if (NNTP_mode && *NNTP_mode) +	mode = NNTP_mode; +    else +	mode = NULL; +    if (current_news.host) { +	if (!strcmp(current_news.host, host) && +	    current_news.port == port) { +	    tmp = Sprintf("MODE %s", mode ? mode : "READER"); +	    tmp = news_command(¤t_news, tmp->ptr, &status); +	    if (status != 200 && status != 201) +		news_close(¤t_news); +	} +	else +	    news_quit(¤t_news); +    } +    if (!current_news.host) { +	current_news.host = allocStr(host, -1); +	current_news.port = port; +	current_news.mode = mode ? allocStr(mode, -1) : NULL; +	if (!news_open(¤t_news)) +	    return NULL; +    } +    if (pu->scheme == SCM_NNTP) { +	/* first char of pu->file is '/' */ +	group = file_unquote(Strnew_charp(pu->file + 1)->ptr); +	p = strchr(group, '/'); +	if (p == NULL) +	    return NULL; +	*p++ = '\0'; +	news_command(¤t_news, Sprintf("GROUP %s", group)->ptr, &status); +	if (status != 211) +	    return NULL; +	news_command(¤t_news, Sprintf("ARTICLE %s", p)->ptr, &status); +	if (status != 220) +	    return NULL; +	return current_news.rf; +    } +    else if (pu->scheme == SCM_NEWS) { +	tmp = Sprintf("ARTICLE <%s>", url_unquote(pu->file)); +	news_command(¤t_news, tmp->ptr, &status); +	if (status != 220) +	    return NULL; +	return current_news.rf; +    } +    return NULL; +} + +Str +readNewsgroup(ParsedURL *pu) +{ +    Str page, tmp; +    URLFile f; +    Buffer *buf; +    char *group, *qgroup, *p, *q, *s, *t, *n; +    int status, flag = 0, i, first, last, start = 0, end = 0; +#ifdef JP_CHARSET +    char code = '\0'; +#endif +    MySignalHandler(*volatile trap) (SIGNAL_ARG) = NULL; + +    if (current_news.host == NULL || !pu->file || *pu->file == '\0') +	return NULL; +    group = file_unquote(pu->file); +    qgroup = html_quote(group); + +    if (fmInitialized) { +	message(Sprintf("Reading newsgroup %s...", group)->ptr, 0, 0); +	refresh(); +    } +    if (SETJMP(AbortLoading) != 0) { +	news_close(¤t_news); +	Strcat_charp(page, "</table><p>Transfer Interrupted!\n"); +	goto news_end; +    } +    trap = signal(SIGINT, KeyAbort); +    if (fmInitialized) +	term_cbreak(); + +    page = Sprintf("<title>Newsgroup: %s</title>\n<h1>Newsgroup: %s</h1>\n<hr>\n", +			 qgroup, qgroup); + +    qgroup = html_quote(file_quote(group));	/* URL */ +    tmp = news_command(¤t_news, Sprintf("GROUP %s", group)->ptr, &status); +    if (status != 211) +	goto news_list; +    if (sscanf(tmp->ptr, "%d %d %d %d", &status, &i, &first, &last) != 4) +	goto news_list; +    if (pu->label) { +	start = atoi(pu->label); +	if (start > 0) { +	    if (start < first) +		start = first; +	    end = start + MaxNewsMessage; +	} +    } +    if (start <= 0) { +	start = first; +	end = last + 1; +	if (end - start > MaxNewsMessage) +	    start = end - MaxNewsMessage; +    } +    if (start > first) { +	i = start - MaxNewsMessage; +	if (i < first) +	    i = first; +	Strcat(page, Sprintf("<a href=\"news:%s#%d\">[%d-%d]</a>\n", +			     qgroup, i, i, start - 1)); +    } + +    Strcat_charp(page, "<table>\n"); +    news_command(¤t_news, Sprintf("XOVER %d-%d", start, end - 1)->ptr, +					&status); +    if (status == 224) { +	f.scheme = SCM_NEWS; +	while (1) { +	    tmp = StrISgets(current_news.rf); +	    if (NEWS_ENDLINE(tmp->ptr)) +		break; +	    if (sscanf(tmp->ptr, "%d", &i) != 1) +		continue; +	    if (!(s = strchr(tmp->ptr, '\t'))) +		continue; +	    s++; +	    if (!(n = strchr(s, '\t'))) +		continue; +	    *n++ = '\0'; +	    if (!(t = strchr(n, '\t'))) +		continue; +	    *t++ = '\0'; +	    if (!(p = strchr(t, '\t'))) +		continue; +	    *p++ = '\0'; +	    if (*p == '<') +		p++; +	    if (!(q = strchr(p, '>')) && !(q = strchr(p, '\t'))) +		continue; +	    *q = '\0'; +	    s = convertLine(&f, decodeMIME(s), &code, HEADER_MODE)->ptr; +	    n = convertLine(&f, decodeMIME(n), &code, HEADER_MODE)->ptr; +	    add_news_message(page, i, t, n, s, p); +	} +    } +    else { +	init_stream(&f, SCM_NEWS, current_news.rf);  +	buf = newBuffer(INIT_BUFFER_WIDTH); +	for (i = start; i < end && i <= last; i++) { +	    news_command(¤t_news, Sprintf("HEAD %d", i)->ptr, &status); +	    if (status != 221) +		continue; +	    readHeader(&f, buf, FALSE, NULL); +	    if (!(p = checkHeader(buf, "Message-ID:"))) +		continue; +	    if (*p == '<') +		p++; +	    if (!(q = strchr(p, '>')) && !(q = strchr(p, '\t'))) +		*q = '\0'; +	    if (!(s = checkHeader(buf, "Subject:"))) +		continue; +	    if (!(n = checkHeader(buf, "From:"))) +		continue; +	    if (!(t = checkHeader(buf, "Date:"))) +		continue; +	    add_news_message(page, i, t, n, s, p); +	} +    } +    Strcat_charp(page, "</table>\n"); + +    if (end <= last) { +	i = end + MaxNewsMessage - 1; +	if (i > last) +	    i = last; +	Strcat(page, Sprintf("<a href=\"news:%s#%d\">[%d-%d]</a>\n", +			     qgroup, end, end, i)); +    } +    flag = 1; + +  news_list: +    news_command(¤t_news, Sprintf("LIST ACTIVE %s.*", group)->ptr, +		 &status); +    if (status != 215) +	goto news_end; +    while (1) { +	tmp = StrISgets(current_news.rf); +	if (NEWS_ENDLINE(tmp->ptr)) +	    break; +	if (flag < 2) { +	    if (flag == 1) +		Strcat_charp(page, "<hr>\n"); +	    Strcat_charp(page, "<table>\n"); +	    flag = 2; +	} +	p = tmp->ptr; +	for (q = p; *q && !IS_SPACE(*q); q++) ; +	*(q++) = '\0'; +	i = 0; +	if (sscanf(q, "%d %d", &last, &first) == 2 && last >= first) +	    i = last - first + 1; +	Strcat(page, +	       Sprintf("<tr><td align=right>%d<td><a href=\"news:%s\">%s</a>\n", +		       i, html_quote(file_quote(p)), html_quote(p))); +    } +    if (flag == 2) +	Strcat_charp(page, "</table>\n"); + +  news_end: +    if (fmInitialized) +	term_raw(); +    signal(SIGINT, trap); +    return page; +} + +void +disconnectNews(void) +{ +    news_quit(¤t_news); +} + +#endif		/* USE_NNTP */ @@ -1,4 +1,4 @@ -/* $Id: proto.h,v 1.74 2002/12/24 17:28:49 ukai Exp $ */ +/* $Id: proto.h,v 1.75 2002/12/27 16:07:44 ukai Exp $ */  /*    *   This file was automatically generated by version 1.7 of cextract.   *   Manual editing not recommended. @@ -509,6 +509,11 @@ extern FILE *openFTP(ParsedURL *pu, URLFile *uf);  extern Str readFTPDir(ParsedURL *pu);  extern void closeFTP(FILE * f);  extern int Ftpfclose(FILE * f); +#ifdef USE_NNTP +extern InputStream openNewsStream(ParsedURL *pu); +extern Str readNewsgroup(ParsedURL *pu); +extern void disconnectNews(void); +#endif  extern AnchorList *putAnchor(AnchorList *al, char *url, char *target,  			     Anchor **anchor_return, char *referer,  			     char *title, unsigned char key, int line, @@ -1,4 +1,4 @@ -/* $Id: rc.c,v 1.73 2002/12/24 17:20:48 ukai Exp $ */ +/* $Id: rc.c,v 1.74 2002/12/27 16:07:44 ukai Exp $ */  /*    * Initialization file etc.   */ @@ -106,6 +106,11 @@ static char *config_file = NULL;  #define CMT_NO_PROXY     "プロキシから除外するドメイン"  #define CMT_NOPROXY_NETADDR	"ネットワークアドレスでプロキシ除外のチェック"  #define CMT_NO_CACHE     "Cache を使わない" +#ifdef USE_NNTP +#define CMT_NNTP_SERVER  "News サーバ" +#define CMT_NNTP_MODE    "News サーバのモード" +#define CMT_MAX_NEWS     "News を一覧表示する時の数" +#endif  #define CMT_DNS_ORDER	"名前解決の順序"  #define CMT_DROOT        "/ で表されるディレクトリ(document root)"  #define CMT_PDROOT       "/~user で表されるディレクトリ" @@ -264,6 +269,11 @@ static char *config_file = NULL;  #define CMT_NO_PROXY     "Domains to be accessed directly (no proxy)"  #define CMT_NOPROXY_NETADDR	"Check noproxy by network address"  #define CMT_NO_CACHE     "Disable cache" +#ifdef USE_NNTP +#define CMT_NNTP_SERVER  "News server" +#define CMT_NNTP_MODE    "Mode of news server" +#define CMT_MAX_NEWS     "Number of news messages" +#endif  #define CMT_DNS_ORDER	"Order of name resolution"  #define CMT_DROOT        "Directory corresponding to / (document root)"  #define CMT_PDROOT       "Directory corresponding to /~user" @@ -783,6 +793,12 @@ struct param_ptr params9[] = {      {"dns_order", P_INT, PI_SEL_C, (void *)&DNS_order, CMT_DNS_ORDER,       dnsorders},  #endif				/* INET6 */ +#ifdef USE_NNTP +    {"nntpserver", P_STRING, PI_TEXT, (void *)&NNTP_server, CMT_NNTP_SERVER, +     NULL}, +    {"nntpmode", P_STRING, PI_TEXT, (void *)&NNTP_mode, CMT_NNTP_MODE, NULL}, +    {"max_news", P_INT, PI_TEXT, (void *)&MaxNewsMessage, CMT_MAX_NEWS, NULL}, +#endif      {NULL, 0, 0, NULL, NULL, NULL},  }; @@ -1,4 +1,4 @@ -/* $Id: url.c,v 1.60 2002/12/14 16:09:51 ukai Exp $ */ +/* $Id: url.c,v 1.61 2002/12/27 16:07:45 ukai Exp $ */  #include "fm.h"  #include <sys/types.h>  #include <sys/socket.h> @@ -54,6 +54,7 @@ static int      0,				/* exec - not defined? */      119,			/* nntp */      119,			/* news */ +    119,			/* news group */      0,				/* mailto - not defined */  #ifdef USE_SSL      443,			/* https */ @@ -69,6 +70,7 @@ struct cmdtable schemetable[] = {      /*  {"exec", SCM_EXEC}, */      {"nntp", SCM_NNTP},      {"news", SCM_NEWS}, +    /*  {"news", SCM_NEWS_GROUP}, */  #ifndef USE_W3MMAILER      {"mailto", SCM_MAILTO},  #endif @@ -969,6 +971,11 @@ parseURL2(char *url, ParsedURL *pu, ParsedURL *current)      if (pu->scheme == SCM_MAILTO)  	return;  #endif +    if (pu->scheme == SCM_NEWS) { +	if (pu->file && !strchr(pu->file, '@')) +	    pu->scheme = SCM_NEWS_GROUP; +	return; +    }      if (pu->scheme == SCM_LOCAL)  	pu->file = expandName(pu->file); @@ -989,7 +996,7 @@ parseURL2(char *url, ParsedURL *pu, ParsedURL *current)  		   pu->scheme != SCM_GOPHER &&  #endif				/* USE_GOPHER */  #ifdef USE_NNTP -		   pu->scheme != SCM_NEWS && +		   pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP &&  #endif				/* USE_NNTP */  		   pu->file[0] != '/'  #ifdef SUPPORT_DOS_DRIVE_PREFIX @@ -1070,7 +1077,7 @@ parseURL2(char *url, ParsedURL *pu, ParsedURL *current)  		    pu->scheme != SCM_GOPHER &&  #endif				/* USE_GOPHER */  #ifdef USE_NNTP -		    pu->scheme != SCM_NEWS && +		    pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP &&  #endif				/* USE_NNTP */  		    pu->file[0] == '/') {  	    /* @@ -1102,7 +1109,7 @@ _parsedURL2Str(ParsedURL *pu, int pass)      Str tmp;      static char *scheme_str[] = {  	"http", "gopher", "ftp", "ftp", "file", "file", "exec", "nntp", "news", -	"mailto", +	"news", "mailto",  #ifdef USE_SSL  	"https",  #endif				/* USE_SSL */ @@ -1139,7 +1146,7 @@ _parsedURL2Str(ParsedURL *pu, int pass)      }  #endif  #ifdef USE_NNTP -    if (pu->scheme != SCM_NEWS) +    if (pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP)  #endif				/* USE_NNTP */      {  	Strcat_charp(tmp, "//"); @@ -1161,7 +1168,7 @@ _parsedURL2Str(ParsedURL *pu, int pass)      }      if (  #ifdef USE_NNTP -	   pu->scheme != SCM_NEWS && +	   pu->scheme != SCM_NEWS && pu->scheme != SCM_NEWS_GROUP &&  #endif				/* USE_NNTP */  	   (pu->file == NULL || (pu->file[0] != '/'  #ifdef SUPPORT_DOS_DRIVE_PREFIX @@ -1766,80 +1773,14 @@ openURL(char *url, ParsedURL *pu, ParsedURL *current,      case SCM_NNTP:  	/* nntp://<host>:<port>/<newsgroup-name>/<article-number> */      case SCM_NEWS: -        /* news:<newsgroup-name> XXX: not yet */          /* news:<unique>@<full_domain_name> */ -	if (pu->scheme == SCM_NNTP) { -	    p = pu->host; -	} -	else { -	    p = getenv("NNTPSERVER"); -	} -	r = getenv("NNTPMODE"); -	if (p == NULL) -	    return uf; -	sock = openSocket(p, "nntp", pu->port); -	if (sock < 0) -	    return uf; -	stream = newInputStream(sock); -	fw = fdopen(sock, "wb"); -	if (stream == NULL || fw == NULL) -	    return uf; -	tmp = StrISgets(stream); -	if (tmp->length == 0) -	    goto nntp_error; -	sscanf(tmp->ptr, "%d", &i); -	if (i != 200 && i != 201) -	    goto nntp_error; -	if (r && *r != '\0') { -	    fprintf(fw, "MODE %s\r\n", r); -	    fflush(fw); -	    tmp = StrISgets(stream); -	    if (tmp->length == 0) -		goto nntp_error; -	    sscanf(tmp->ptr, "%d", &i); -	    if (i != 200 && i != 201) -		goto nntp_error; -	} -	if (pu->scheme == SCM_NNTP) { -	    char *group; -	    if (pu->file == NULL || *pu->file == '\0') -		goto nntp_error; -	    /* first char of pu->file is '/' */ -	    group = url_unquote(Strnew_charp(pu->file + 1)->ptr); -	    p = strchr(group, '/'); -	    if (p == NULL) -		goto nntp_error; -	    *p++ = '\0'; -	    fprintf(fw, "GROUP %s\r\n", group); -	    fflush(fw); -	    tmp = StrISgets(stream); -	    if (tmp->length == 0) { -		goto nntp_error; -	    } -	    sscanf(tmp->ptr, "%d", &i); -	    if (i != 211) -		goto nntp_error; -	    fprintf(fw, "ARTICLE %s\r\n", p); -	} -	else { -	    if (pu->file == NULL || *pu->file == '\0') -		goto nntp_error; -	    /* pu-file contains '@' => news:<message-id> */ -	    fprintf(fw, "ARTICLE <%s>\r\n", url_unquote(pu->file)); -	} -	fflush(fw); -	tmp = StrISgets(stream); -	if (tmp->length == 0) -	    goto nntp_error; -	sscanf(tmp->ptr, "%d", &i); -	if (i != 220) -	    goto nntp_error; -	uf.scheme = SCM_NEWS;	/* XXX */ -	uf.stream = stream; -	return uf; -      nntp_error: -	ISclose(stream); -	fclose(fw); +    case SCM_NEWS_GROUP: +        /* news:<newsgroup-name> */ +	uf.stream = openNewsStream(pu); +	if (uf.stream) +	    uf.scheme = SCM_NEWS;	/* XXX */ +	else +	    uf.scheme = pu->scheme;  	return uf;  #endif				/* USE_NNTP */      case SCM_UNKNOWN: | 
