From 72f72d64a422d6628c4796f5c0bf2e508f134214 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:05:14 +0900 Subject: Adding upstream version 0.5.1 --- istream.c | 723 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 723 insertions(+) create mode 100644 istream.c (limited to 'istream.c') diff --git a/istream.c b/istream.c new file mode 100644 index 0000000..fe5847b --- /dev/null +++ b/istream.c @@ -0,0 +1,723 @@ +/* $Id: istream.c,v 1.23 2003/10/20 16:41:56 ukai Exp $ */ +#include "fm.h" +#include "myctype.h" +#include "istream.h" +#include +#ifdef USE_SSL +#include +#endif + +#define uchar unsigned char + +#define STREAM_BUF_SIZE 8192 +#define SSL_BUF_SIZE 1536 + +#define MUST_BE_UPDATED(bs) ((bs)->stream.cur==(bs)->stream.next) + +#define POP_CHAR(bs) ((bs)->iseos?'\0':(bs)->stream.buf[(bs)->stream.cur++]) + +static void basic_close(int *handle); +static int basic_read(int *handle, char *buf, int len); + +static void file_close(struct file_handle *handle); +static int file_read(struct file_handle *handle, char *buf, int len); + +static int str_read(Str handle, char *buf, int len); + +#ifdef USE_SSL +static void ssl_close(struct ssl_handle *handle); +static int ssl_read(struct ssl_handle *handle, char *buf, int len); +#endif + +static int ens_read(struct ens_handle *handle, char *buf, int len); +static void ens_close(struct ens_handle *handle); + +static void +do_update(BaseStream base) +{ + int len; + base->stream.cur = base->stream.next = 0; + len = base->read(base->handle, base->stream.buf, base->stream.size); + if (len <= 0) + base->iseos = TRUE; + else + base->stream.next += len; +} + +static int +buffer_read(StreamBuffer sb, char *obuf, int count) +{ + int len = sb->next - sb->cur; + if (len > 0) { + if (len > count) + len = count; + bcopy((const void *)&sb->buf[sb->cur], obuf, len); + sb->cur += len; + } + return len; +} + +static void +init_buffer(BaseStream base, char *buf, int bufsize) +{ + StreamBuffer sb = &base->stream; + sb->size = bufsize; + sb->cur = 0; + if (buf) { + sb->buf = (uchar *) buf; + sb->next = bufsize; + } + else { + sb->buf = NewAtom_N(uchar, bufsize); + sb->next = 0; + } + base->iseos = FALSE; +} + +static void +init_base_stream(BaseStream base, int bufsize) +{ + init_buffer(base, NULL, bufsize); +} + +static void +init_str_stream(BaseStream base, Str s) +{ + init_buffer(base, s->ptr, s->length); +} + +InputStream +newInputStream(int des) +{ + InputStream stream; + if (des < 0) + return NULL; + stream = New(union input_stream); + init_base_stream(&stream->base, STREAM_BUF_SIZE); + stream->base.type = IST_BASIC; + stream->base.handle = New(int); + *(int *)stream->base.handle = des; + stream->base.read = (int (*)())basic_read; + stream->base.close = (void (*)())basic_close; + return stream; +} + +InputStream +newFileStream(FILE * f, void (*closep) ()) +{ + InputStream stream; + if (f == NULL) + return NULL; + stream = New(union input_stream); + init_base_stream(&stream->base, STREAM_BUF_SIZE); + stream->file.type = IST_FILE; + stream->file.handle = New(struct file_handle); + stream->file.handle->f = f; + if (closep) + stream->file.handle->close = closep; + else + stream->file.handle->close = (void (*)())fclose; + stream->file.read = (int (*)())file_read; + stream->file.close = (void (*)())file_close; + return stream; +} + +InputStream +newStrStream(Str s) +{ + InputStream stream; + if (s == NULL) + return NULL; + stream = New(union input_stream); + init_str_stream(&stream->base, s); + stream->str.type = IST_STR; + stream->str.handle = s; + stream->str.read = (int (*)())str_read; + stream->str.close = NULL; + return stream; +} + +#ifdef USE_SSL +InputStream +newSSLStream(SSL * ssl, int sock) +{ + InputStream stream; + if (sock < 0) + return NULL; + stream = New(union input_stream); + init_base_stream(&stream->base, SSL_BUF_SIZE); + stream->ssl.type = IST_SSL; + stream->ssl.handle = New(struct ssl_handle); + stream->ssl.handle->ssl = ssl; + stream->ssl.handle->sock = sock; + stream->ssl.read = (int (*)())ssl_read; + stream->ssl.close = (void (*)())ssl_close; + return stream; +} +#endif + +InputStream +newEncodedStream(InputStream is, char encoding) +{ + InputStream stream; + if (is == NULL || (encoding != ENC_QUOTE && encoding != ENC_BASE64 && + encoding != ENC_UUENCODE)) + return is; + stream = New(union input_stream); + init_base_stream(&stream->base, STREAM_BUF_SIZE); + stream->ens.type = IST_ENCODED; + stream->ens.handle = New(struct ens_handle); + stream->ens.handle->is = is; + stream->ens.handle->pos = 0; + stream->ens.handle->encoding = encoding; + stream->ens.handle->s = NULL; + stream->ens.read = (int (*)())ens_read; + stream->ens.close = (void (*)())ens_close; + return stream; +} + +int +ISclose(InputStream stream) +{ + MySignalHandler(*prevtrap) (); + if (stream == NULL || stream->base.close == NULL || + stream->base.type & IST_UNCLOSE) + return -1; + prevtrap = mySignal(SIGINT, SIG_IGN); + stream->base.close(stream->base.handle); + mySignal(SIGINT, prevtrap); + return 0; +} + +int +ISgetc(InputStream stream) +{ + BaseStream base; + if (stream == NULL) + return '\0'; + base = &stream->base; + if (!base->iseos && MUST_BE_UPDATED(base)) + do_update(base); + return POP_CHAR(base); +} + +int +ISundogetc(InputStream stream) +{ + StreamBuffer sb; + if (stream == NULL) + return -1; + sb = &stream->base.stream; + if (sb->cur > 0) { + sb->cur--; + return 0; + } + return -1; +} + +#define MARGIN_STR_SIZE 10 +Str +StrISgets(InputStream stream) +{ + BaseStream base; + StreamBuffer sb; + Str s = NULL; + uchar *p; + int len; + + if (stream == NULL) + return '\0'; + base = &stream->base; + sb = &base->stream; + + while (!base->iseos) { + if (MUST_BE_UPDATED(base)) { + do_update(base); + } + else { + if ((p = memchr(&sb->buf[sb->cur], '\n', sb->next - sb->cur))) { + len = p - &sb->buf[sb->cur] + 1; + if (s == NULL) + s = Strnew_size(len); + Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); + sb->cur += len; + return s; + } + else { + if (s == NULL) + s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); + Strcat_charp_n(s, (char *)&sb->buf[sb->cur], + sb->next - sb->cur); + sb->cur = sb->next; + } + } + } + + if (s == NULL) + return Strnew(); + return s; +} + +Str +StrmyISgets(InputStream stream) +{ + BaseStream base; + StreamBuffer sb; + Str s = NULL; + int i, len; + + if (stream == NULL) + return '\0'; + base = &stream->base; + sb = &base->stream; + + while (!base->iseos) { + if (MUST_BE_UPDATED(base)) { + do_update(base); + } + else { + if (s && Strlastchar(s) == '\r') { + if (sb->buf[sb->cur] == '\n') + Strcat_char(s, (char)sb->buf[sb->cur++]); + return s; + } + for (i = sb->cur; + i < sb->next && sb->buf[i] != '\n' && sb->buf[i] != '\r'; + i++) ; + if (i < sb->next) { + len = i - sb->cur + 1; + if (s == NULL) + s = Strnew_size(len + MARGIN_STR_SIZE); + Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); + sb->cur = i + 1; + if (sb->buf[i] == '\n') + return s; + } + else { + if (s == NULL) + s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); + Strcat_charp_n(s, (char *)&sb->buf[sb->cur], + sb->next - sb->cur); + sb->cur = sb->next; + } + } + } + + if (s == NULL) + return Strnew(); + return s; +} + +int +ISread(InputStream stream, Str buf, int count) +{ + int rest, len; + BaseStream base; + + if (stream == NULL || (base = &stream->base)->iseos) + return 0; + + len = buffer_read(&base->stream, buf->ptr, count); + rest = count - len; + if (MUST_BE_UPDATED(base)) { + len = base->read(base->handle, &buf->ptr[len], rest); + if (len <= 0) { + base->iseos = TRUE; + len = 0; + } + rest -= len; + } + Strtruncate(buf, count - rest); + if (buf->length > 0) + return 1; + return 0; +} + +int +ISfileno(InputStream stream) +{ + if (stream == NULL) + return -1; + switch (IStype(stream) & ~IST_UNCLOSE) { + case IST_BASIC: + return *(int *)stream->base.handle; + case IST_FILE: + return fileno(stream->file.handle->f); +#ifdef USE_SSL + case IST_SSL: + return stream->ssl.handle->sock; +#endif + case IST_ENCODED: + return ISfileno(stream->ens.handle->is); + default: + return -1; + } +} + +int +ISeos(InputStream stream) +{ + BaseStream base = &stream->base; + if (!base->iseos && MUST_BE_UPDATED(base)) + do_update(base); + return base->iseos; +} + +#ifdef USE_SSL +static Str accept_this_site; + +void +ssl_accept_this_site(char *hostname) +{ + if (hostname) + accept_this_site = Strnew_charp(hostname); + else + accept_this_site = NULL; +} + +static int +ssl_match_cert_ident(char *ident, int ilen, char *hostname) +{ + /* RFC2818 3.1. Server Identity + * Names may contain the wildcard + * character * which is considered to match any single domain name + * component or component fragment. E.g., *.a.com matches foo.a.com but + * not bar.foo.a.com. f*.com matches foo.com but not bar.com. + */ + int hlen = strlen(hostname); + int i, c; + + /* Is this an exact match? */ + if ((ilen == hlen) && strncasecmp(ident, hostname, hlen) == 0) + return TRUE; + + for (i = 0; i < ilen; i++) { + if (ident[i] == '*' && ident[i + 1] == '.') { + while ((c = *hostname++) != '\0') + if (c == '.') + break; + i++; + } + else { + if (ident[i] != *hostname++) + return FALSE; + } + } + return *hostname == '\0'; +} + +static Str +ssl_check_cert_ident(X509 * x, char *hostname) +{ + int i; + Str ret = NULL; + int match_ident = FALSE; + /* + * All we need to do here is check that the CN matches. + * + * From RFC2818 3.1 Server Identity: + * If a subjectAltName extension of type dNSName is present, that MUST + * be used as the identity. Otherwise, the (most specific) Common Name + * field in the Subject field of the certificate MUST be used. Although + * the use of the Common Name is existing practice, it is deprecated and + * Certification Authorities are encouraged to use the dNSName instead. + */ + i = X509_get_ext_by_NID(x, NID_subject_alt_name, -1); + if (i >= 0) { + X509_EXTENSION *ex; + STACK_OF(GENERAL_NAME) * alt; + + ex = X509_get_ext(x, i); + alt = X509V3_EXT_d2i(ex); + if (alt) { + int n; + GENERAL_NAME *gn; + X509V3_EXT_METHOD *method; + Str seen_dnsname = NULL; + + n = sk_GENERAL_NAME_num(alt); + for (i = 0; i < n; i++) { + gn = sk_GENERAL_NAME_value(alt, i); + if (gn->type == GEN_DNS) { + char *sn = ASN1_STRING_data(gn->d.ia5); + int sl = ASN1_STRING_length(gn->d.ia5); + + if (!seen_dnsname) + seen_dnsname = Strnew(); + Strcat_m_charp(seen_dnsname, sn, " ", NULL); + if (ssl_match_cert_ident(sn, sl, hostname)) + break; + } + } + method = X509V3_EXT_get(ex); + sk_GENERAL_NAME_free(alt); + if (i < n) /* Found a match */ + match_ident = TRUE; + else if (seen_dnsname) + /* FIXME: gettextize? */ + ret = Sprintf("Bad cert ident from %s: dNSName=%s", hostname, + seen_dnsname->ptr); + } + } + + if (match_ident == FALSE && ret == NULL) { + X509_NAME *xn; + char buf[2048]; + + xn = X509_get_subject_name(x); + + if (X509_NAME_get_text_by_NID(xn, NID_commonName, + buf, sizeof(buf)) == -1) + /* FIXME: gettextize? */ + ret = Strnew_charp("Unable to get common name from peer cert"); + else if (!ssl_match_cert_ident(buf, strlen(buf), hostname)) + /* FIXME: gettextize? */ + ret = Sprintf("Bad cert ident %s from %s", buf, hostname); + else + match_ident = TRUE; + } + return ret; +} + +Str +ssl_get_certificate(SSL * ssl, char *hostname) +{ + BIO *bp; + X509 *x; + X509_NAME *xn; + char *p; + int len; + Str s; + char buf[2048]; + Str amsg = NULL; + Str emsg; + char *ans; + + if (ssl == NULL) + return NULL; + x = SSL_get_peer_certificate(ssl); + if (x == NULL) { + if (accept_this_site + && strcasecmp(accept_this_site->ptr, hostname) == 0) + ans = "y"; + else { + /* FIXME: gettextize? */ + emsg = Strnew_charp("No SSL peer certificate: accept? (y/n)"); + ans = inputAnswer(emsg->ptr); + } + if (ans && TOLOWER(*ans) == 'y') + /* FIXME: gettextize? */ + amsg = Strnew_charp + ("Accept SSL session without any peer certificate"); + else { + /* FIXME: gettextize? */ + char *e = "This SSL session was rejected " + "to prevent security violation: no peer certificate"; + disp_err_message(e, FALSE); + free_ssl_ctx(); + return NULL; + } + if (amsg) + disp_err_message(amsg->ptr, FALSE); + ssl_accept_this_site(hostname); + /* FIXME: gettextize? */ + s = amsg ? amsg : Strnew_charp("valid certificate"); + return s; + } +#ifdef USE_SSL_VERIFY + /* check the cert chain. + * The chain length is automatically checked by OpenSSL when we + * set the verify depth in the ctx. + */ + if (ssl_verify_server) { + long verr; + if ((verr = SSL_get_verify_result(ssl)) + != X509_V_OK) { + const char *em = X509_verify_cert_error_string(verr); + if (accept_this_site + && strcasecmp(accept_this_site->ptr, hostname) == 0) + ans = "y"; + else { + /* FIXME: gettextize? */ + emsg = Sprintf("%s: accept? (y/n)", em); + ans = inputAnswer(emsg->ptr); + } + if (ans && TOLOWER(*ans) == 'y') { + /* FIXME: gettextize? */ + amsg = Sprintf("Accept unsecure SSL session: " + "unverified: %s", em); + } + else { + /* FIXME: gettextize? */ + char *e = + Sprintf("This SSL session was rejected: %s", em)->ptr; + disp_err_message(e, FALSE); + free_ssl_ctx(); + return NULL; + } + } + } +#endif + emsg = ssl_check_cert_ident(x, hostname); + if (emsg != NULL) { + if (accept_this_site + && strcasecmp(accept_this_site->ptr, hostname) == 0) + ans = "y"; + else { + Str ep = Strdup(emsg); + if (ep->length > COLS - 16) + Strshrink(ep, ep->length - (COLS - 16)); + Strcat_charp(ep, ": accept? (y/n)"); + ans = inputAnswer(ep->ptr); + } + if (ans && TOLOWER(*ans) == 'y') { + /* FIXME: gettextize? */ + amsg = Strnew_charp("Accept unsecure SSL session:"); + Strcat(amsg, emsg); + } + else { + /* FIXME: gettextize? */ + char *e = "This SSL session was rejected " + "to prevent security violation"; + disp_err_message(e, FALSE); + free_ssl_ctx(); + return NULL; + } + } + if (amsg) + disp_err_message(amsg->ptr, FALSE); + ssl_accept_this_site(hostname); + /* FIXME: gettextize? */ + s = amsg ? amsg : Strnew_charp("valid certificate"); + Strcat_charp(s, "\n"); + xn = X509_get_subject_name(x); + if (X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf)) == -1) + Strcat_charp(s, " subject="); + else + Strcat_m_charp(s, " subject=", buf, NULL); + xn = X509_get_issuer_name(x); + if (X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf)) == -1) + Strcat_charp(s, ": issuer="); + else + Strcat_m_charp(s, ": issuer=", buf, NULL); + Strcat_charp(s, "\n\n"); + + bp = BIO_new(BIO_s_mem()); + X509_print(bp, x); + len = (int)BIO_ctrl(bp, BIO_CTRL_INFO, 0, (char *)&p); + Strcat_charp_n(s, p, len); + BIO_free_all(bp); + X509_free(x); + return s; +} +#endif + +/* Raw level input stream functions */ + +static void +basic_close(int *handle) +{ + close(*(int *)handle); +} + +static int +basic_read(int *handle, char *buf, int len) +{ + return read(*(int *)handle, buf, len); +} + +static void +file_close(struct file_handle *handle) +{ + handle->close(handle->f); +} + +static int +file_read(struct file_handle *handle, char *buf, int len) +{ + return fread(buf, 1, len, handle->f); +} + +static int +str_read(Str handle, char *buf, int len) +{ + return 0; +} + +#ifdef USE_SSL +static void +ssl_close(struct ssl_handle *handle) +{ + close(handle->sock); + if (handle->ssl) + SSL_free(handle->ssl); +} + +static int +ssl_read(struct ssl_handle *handle, char *buf, int len) +{ + int status; + if (handle->ssl) { +#ifdef USE_SSL_VERIFY + for (;;) { + status = SSL_read(handle->ssl, buf, len); + if (status > 0) + break; + switch (SSL_get_error(handle->ssl, status)) { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: /* reads can trigger write errors; see SSL_get_error(3) */ + continue; + default: + break; + } + break; + } +#else /* if !defined(USE_SSL_VERIFY) */ + status = SSL_read(handle->ssl, buf, len); +#endif /* !defined(USE_SSL_VERIFY) */ + } + else + status = read(handle->sock, buf, len); + return status; +} +#endif /* USE_SSL */ + +static void +ens_close(struct ens_handle *handle) +{ + ISclose(handle->is); +} + +static int +ens_read(struct ens_handle *handle, char *buf, int len) +{ + if (handle->s == NULL || handle->pos == handle->s->length) { + char *p; + handle->s = StrmyISgets(handle->is); + if (handle->s->length == 0) + return 0; + cleanup_line(handle->s, PAGER_MODE); + if (handle->encoding == ENC_BASE64) + Strchop(handle->s); + else if (handle->encoding == ENC_UUENCODE) { + if (!strncmp(handle->s->ptr, "begin", 5)) + handle->s = StrmyISgets(handle->is); + Strchop(handle->s); + } + p = handle->s->ptr; + if (handle->encoding == ENC_QUOTE) + handle->s = decodeQP(&p); + else if (handle->encoding == ENC_BASE64) + handle->s = decodeB(&p); + else if (handle->encoding == ENC_UUENCODE) + handle->s = decodeU(&p); + handle->pos = 0; + } + + if (len > handle->s->length - handle->pos) + len = handle->s->length - handle->pos; + + bcopy(&handle->s->ptr[handle->pos], buf, len); + handle->pos += len; + return len; +} -- cgit v1.2.3 From 6db339b3d7a391f196e7c4b725a4ed0bd00f31cf Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:23:02 +0900 Subject: Adding upstream version 0.5.2 --- istream.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'istream.c') diff --git a/istream.c b/istream.c index fe5847b..773330c 100644 --- a/istream.c +++ b/istream.c @@ -1,4 +1,4 @@ -/* $Id: istream.c,v 1.23 2003/10/20 16:41:56 ukai Exp $ */ +/* $Id: istream.c,v 1.26 2007/05/23 15:06:05 inu Exp $ */ #include "fm.h" #include "myctype.h" #include "istream.h" @@ -6,6 +6,9 @@ #ifdef USE_SSL #include #endif +#ifdef __MINGW32_VERSION +#include +#endif #define uchar unsigned char @@ -617,13 +620,21 @@ ssl_get_certificate(SSL * ssl, char *hostname) static void basic_close(int *handle) { +#ifdef __MINGW32_VERSION + closesocket(*(int *)handle); +#else close(*(int *)handle); +#endif } static int basic_read(int *handle, char *buf, int len) { +#ifdef __MINGW32_VERSION + return recv(*(int *)handle, buf, len, 0); +#else return read(*(int *)handle, buf, len); +#endif } static void -- cgit v1.2.3 From 5397d09e585a1938fb64bc9c5cd5daed1959eb90 Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Wed, 4 May 2011 16:41:45 +0900 Subject: Adding upstream version 0.5.3 --- istream.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'istream.c') diff --git a/istream.c b/istream.c index 773330c..8967280 100644 --- a/istream.c +++ b/istream.c @@ -1,4 +1,4 @@ -/* $Id: istream.c,v 1.26 2007/05/23 15:06:05 inu Exp $ */ +/* $Id: istream.c,v 1.27 2010/07/18 13:43:23 htrb Exp $ */ #include "fm.h" #include "myctype.h" #include "istream.h" @@ -447,8 +447,17 @@ ssl_check_cert_ident(X509 * x, char *hostname) if (!seen_dnsname) seen_dnsname = Strnew(); + /* replace \0 to make full string visible to user */ + if (sl != strlen(sn)) { + int i; + for (i = 0; i < sl; ++i) { + if (!sn[i]) + sn[i] = '!'; + } + } Strcat_m_charp(seen_dnsname, sn, " ", NULL); - if (ssl_match_cert_ident(sn, sl, hostname)) + if (sl == strlen(sn) /* catch \0 in SAN */ + && ssl_match_cert_ident(sn, sl, hostname)) break; } } @@ -466,16 +475,27 @@ ssl_check_cert_ident(X509 * x, char *hostname) if (match_ident == FALSE && ret == NULL) { X509_NAME *xn; char buf[2048]; + int slen; xn = X509_get_subject_name(x); - if (X509_NAME_get_text_by_NID(xn, NID_commonName, - buf, sizeof(buf)) == -1) + slen = X509_NAME_get_text_by_NID(xn, NID_commonName, buf, sizeof(buf)); + if ( slen == -1) /* FIXME: gettextize? */ ret = Strnew_charp("Unable to get common name from peer cert"); - else if (!ssl_match_cert_ident(buf, strlen(buf), hostname)) + else if (slen != strlen(buf) + || !ssl_match_cert_ident(buf, strlen(buf), hostname)) { + /* replace \0 to make full string visible to user */ + if (slen != strlen(buf)) { + int i; + for (i = 0; i < slen; ++i) { + if (!buf[i]) + buf[i] = '!'; + } + } /* FIXME: gettextize? */ ret = Sprintf("Bad cert ident %s from %s", buf, hostname); + } else match_ident = TRUE; } -- cgit v1.2.3 From 1d0ba25a660483da1272a31dd077ed94441e3d9f Mon Sep 17 00:00:00 2001 From: Tatsuya Kinoshita Date: Sat, 2 Jan 2021 09:20:37 +0900 Subject: New upstream version 0.5.3+git20210102 --- istream.c | 248 ++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 127 insertions(+), 121 deletions(-) (limited to 'istream.c') diff --git a/istream.c b/istream.c index 8967280..74adac5 100644 --- a/istream.c +++ b/istream.c @@ -22,8 +22,8 @@ static void basic_close(int *handle); static int basic_read(int *handle, char *buf, int len); -static void file_close(struct file_handle *handle); -static int file_read(struct file_handle *handle, char *buf, int len); +static void file_close(struct io_file_handle *handle); +static int file_read(struct io_file_handle *handle, char *buf, int len); static int str_read(Str handle, char *buf, int len); @@ -35,12 +35,14 @@ static int ssl_read(struct ssl_handle *handle, char *buf, int len); static int ens_read(struct ens_handle *handle, char *buf, int len); static void ens_close(struct ens_handle *handle); +static void memchop(char *p, int *len); + static void do_update(BaseStream base) { int len; base->stream.cur = base->stream.next = 0; - len = base->read(base->handle, base->stream.buf, base->stream.size); + len = (*base->read) (base->handle, base->stream.buf, base->stream.size); if (len <= 0) base->iseos = TRUE; else @@ -66,12 +68,12 @@ init_buffer(BaseStream base, char *buf, int bufsize) StreamBuffer sb = &base->stream; sb->size = bufsize; sb->cur = 0; + sb->buf = NewWithoutGC_N(uchar, bufsize); if (buf) { - sb->buf = (uchar *) buf; + memcpy(sb->buf, buf, bufsize); sb->next = bufsize; } else { - sb->buf = NewAtom_N(uchar, bufsize); sb->next = 0; } base->iseos = FALSE; @@ -95,10 +97,10 @@ newInputStream(int des) InputStream stream; if (des < 0) return NULL; - stream = New(union input_stream); + stream = NewWithoutGC(union input_stream); init_base_stream(&stream->base, STREAM_BUF_SIZE); stream->base.type = IST_BASIC; - stream->base.handle = New(int); + stream->base.handle = NewWithoutGC(int); *(int *)stream->base.handle = des; stream->base.read = (int (*)())basic_read; stream->base.close = (void (*)())basic_close; @@ -111,10 +113,10 @@ newFileStream(FILE * f, void (*closep) ()) InputStream stream; if (f == NULL) return NULL; - stream = New(union input_stream); + stream = NewWithoutGC(union input_stream); init_base_stream(&stream->base, STREAM_BUF_SIZE); stream->file.type = IST_FILE; - stream->file.handle = New(struct file_handle); + stream->file.handle = NewWithoutGC(struct io_file_handle); stream->file.handle->f = f; if (closep) stream->file.handle->close = closep; @@ -131,10 +133,10 @@ newStrStream(Str s) InputStream stream; if (s == NULL) return NULL; - stream = New(union input_stream); + stream = NewWithoutGC(union input_stream); init_str_stream(&stream->base, s); stream->str.type = IST_STR; - stream->str.handle = s; + stream->str.handle = NULL; stream->str.read = (int (*)())str_read; stream->str.close = NULL; return stream; @@ -147,10 +149,10 @@ newSSLStream(SSL * ssl, int sock) InputStream stream; if (sock < 0) return NULL; - stream = New(union input_stream); + stream = NewWithoutGC(union input_stream); init_base_stream(&stream->base, SSL_BUF_SIZE); stream->ssl.type = IST_SSL; - stream->ssl.handle = New(struct ssl_handle); + stream->ssl.handle = NewWithoutGC(struct ssl_handle); stream->ssl.handle->ssl = ssl; stream->ssl.handle->sock = sock; stream->ssl.read = (int (*)())ssl_read; @@ -166,14 +168,14 @@ newEncodedStream(InputStream is, char encoding) if (is == NULL || (encoding != ENC_QUOTE && encoding != ENC_BASE64 && encoding != ENC_UUENCODE)) return is; - stream = New(union input_stream); + stream = NewWithoutGC(union input_stream); init_base_stream(&stream->base, STREAM_BUF_SIZE); stream->ens.type = IST_ENCODED; - stream->ens.handle = New(struct ens_handle); + stream->ens.handle = NewWithoutGC(struct ens_handle); stream->ens.handle->is = is; stream->ens.handle->pos = 0; stream->ens.handle->encoding = encoding; - stream->ens.handle->s = NULL; + growbuf_init_without_GC(&stream->ens.handle->gb); stream->ens.read = (int (*)())ens_read; stream->ens.close = (void (*)())ens_close; return stream; @@ -187,8 +189,10 @@ ISclose(InputStream stream) stream->base.type & IST_UNCLOSE) return -1; prevtrap = mySignal(SIGINT, SIG_IGN); - stream->base.close(stream->base.handle); + stream->base.close (stream->base.handle); mySignal(SIGINT, prevtrap); + xfree(stream->base.stream.buf); + xfree(stream); return 0; } @@ -218,122 +222,97 @@ ISundogetc(InputStream stream) return -1; } -#define MARGIN_STR_SIZE 10 Str -StrISgets(InputStream stream) +StrISgets2(InputStream stream, char crnl) { - BaseStream base; - StreamBuffer sb; - Str s = NULL; - uchar *p; - int len; + struct growbuf gb; if (stream == NULL) - return '\0'; - base = &stream->base; - sb = &base->stream; - - while (!base->iseos) { - if (MUST_BE_UPDATED(base)) { - do_update(base); - } - else { - if ((p = memchr(&sb->buf[sb->cur], '\n', sb->next - sb->cur))) { - len = p - &sb->buf[sb->cur] + 1; - if (s == NULL) - s = Strnew_size(len); - Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); - sb->cur += len; - return s; - } - else { - if (s == NULL) - s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); - Strcat_charp_n(s, (char *)&sb->buf[sb->cur], - sb->next - sb->cur); - sb->cur = sb->next; - } - } - } - - if (s == NULL) - return Strnew(); - return s; + return NULL; + growbuf_init(&gb); + ISgets_to_growbuf(stream, &gb, crnl); + return growbuf_to_Str(&gb); } -Str -StrmyISgets(InputStream stream) +void +ISgets_to_growbuf(InputStream stream, struct growbuf *gb, char crnl) { - BaseStream base; - StreamBuffer sb; - Str s = NULL; - int i, len; + BaseStream base = &stream->base; + StreamBuffer sb = &base->stream; + int i; - if (stream == NULL) - return '\0'; - base = &stream->base; - sb = &base->stream; + gb->length = 0; while (!base->iseos) { if (MUST_BE_UPDATED(base)) { do_update(base); + continue; } - else { - if (s && Strlastchar(s) == '\r') { - if (sb->buf[sb->cur] == '\n') - Strcat_char(s, (char)sb->buf[sb->cur++]); - return s; - } - for (i = sb->cur; - i < sb->next && sb->buf[i] != '\n' && sb->buf[i] != '\r'; - i++) ; - if (i < sb->next) { - len = i - sb->cur + 1; - if (s == NULL) - s = Strnew_size(len + MARGIN_STR_SIZE); - Strcat_charp_n(s, (char *)&sb->buf[sb->cur], len); - sb->cur = i + 1; - if (sb->buf[i] == '\n') - return s; + if (crnl && gb->length > 0 && gb->ptr[gb->length - 1] == '\r') { + if (sb->buf[sb->cur] == '\n') { + GROWBUF_ADD_CHAR(gb, '\n'); + ++sb->cur; } - else { - if (s == NULL) - s = Strnew_size(sb->next - sb->cur + MARGIN_STR_SIZE); - Strcat_charp_n(s, (char *)&sb->buf[sb->cur], - sb->next - sb->cur); - sb->cur = sb->next; + break; + } + for (i = sb->cur; i < sb->next; ++i) { + if (sb->buf[i] == '\n' || (crnl && sb->buf[i] == '\r')) { + ++i; + break; } } + growbuf_append(gb, &sb->buf[sb->cur], i - sb->cur); + sb->cur = i; + if (gb->length > 0 && gb->ptr[gb->length - 1] == '\n') + break; } - if (s == NULL) - return Strnew(); - return s; + growbuf_reserve(gb, gb->length + 1); + gb->ptr[gb->length] = '\0'; + return; } +#ifdef unused int ISread(InputStream stream, Str buf, int count) { - int rest, len; + int len; + + if (count + 1 > buf->area_size) { + char *newptr = GC_MALLOC_ATOMIC(count + 1); + memcpy(newptr, buf->ptr, buf->length); + newptr[buf->length] = '\0'; + buf->ptr = newptr; + buf->area_size = count + 1; + } + len = ISread_n(stream, buf->ptr, count); + buf->length = (len > 0) ? len : 0; + buf->ptr[buf->length] = '\0'; + return (len > 0) ? 1 : 0; +} +#endif + +int +ISread_n(InputStream stream, char *dst, int count) +{ + int len, l; BaseStream base; - if (stream == NULL || (base = &stream->base)->iseos) + if (stream == NULL || count <= 0) + return -1; + if ((base = &stream->base)->iseos) return 0; - len = buffer_read(&base->stream, buf->ptr, count); - rest = count - len; + len = buffer_read(&base->stream, dst, count); if (MUST_BE_UPDATED(base)) { - len = base->read(base->handle, &buf->ptr[len], rest); - if (len <= 0) { + l = (*base->read) (base->handle, &dst[len], count - len); + if (l <= 0) { base->iseos = TRUE; - len = 0; + } else { + len += l; } - rest -= len; } - Strtruncate(buf, count - rest); - if (buf->length > 0) - return 1; - return 0; + return len; } int @@ -442,7 +421,11 @@ ssl_check_cert_ident(X509 * x, char *hostname) for (i = 0; i < n; i++) { gn = sk_GENERAL_NAME_value(alt, i); if (gn->type == GEN_DNS) { +#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) char *sn = ASN1_STRING_data(gn->d.ia5); +#else + char *sn = ASN1_STRING_get0_data(gn->d.ia5); +#endif int sl = ASN1_STRING_length(gn->d.ia5); if (!seen_dnsname) @@ -496,8 +479,6 @@ ssl_check_cert_ident(X509 * x, char *hostname) /* FIXME: gettextize? */ ret = Sprintf("Bad cert ident %s from %s", buf, hostname); } - else - match_ident = TRUE; } return ret; } @@ -645,6 +626,7 @@ basic_close(int *handle) #else close(*(int *)handle); #endif + xfree(handle); } static int @@ -658,13 +640,14 @@ basic_read(int *handle, char *buf, int len) } static void -file_close(struct file_handle *handle) +file_close(struct io_file_handle *handle) { handle->close(handle->f); + xfree(handle); } static int -file_read(struct file_handle *handle, char *buf, int len) +file_read(struct io_file_handle *handle, char *buf, int len) { return fread(buf, 1, len, handle->f); } @@ -682,6 +665,7 @@ ssl_close(struct ssl_handle *handle) close(handle->sock); if (handle->ssl) SSL_free(handle->ssl); + xfree(handle); } static int @@ -717,38 +701,60 @@ static void ens_close(struct ens_handle *handle) { ISclose(handle->is); + growbuf_clear(&handle->gb); + xfree(handle); } static int ens_read(struct ens_handle *handle, char *buf, int len) { - if (handle->s == NULL || handle->pos == handle->s->length) { + if (handle->pos == handle->gb.length) { char *p; - handle->s = StrmyISgets(handle->is); - if (handle->s->length == 0) + struct growbuf gbtmp; + + ISgets_to_growbuf(handle->is, &handle->gb, TRUE); + if (handle->gb.length == 0) return 0; - cleanup_line(handle->s, PAGER_MODE); if (handle->encoding == ENC_BASE64) - Strchop(handle->s); + memchop(handle->gb.ptr, &handle->gb.length); else if (handle->encoding == ENC_UUENCODE) { - if (!strncmp(handle->s->ptr, "begin", 5)) - handle->s = StrmyISgets(handle->is); - Strchop(handle->s); + if (handle->gb.length >= 5 && + !strncmp(handle->gb.ptr, "begin", 5)) + ISgets_to_growbuf(handle->is, &handle->gb, TRUE); + memchop(handle->gb.ptr, &handle->gb.length); } - p = handle->s->ptr; + growbuf_init_without_GC(&gbtmp); + p = handle->gb.ptr; if (handle->encoding == ENC_QUOTE) - handle->s = decodeQP(&p); + decodeQP_to_growbuf(&gbtmp, &p); else if (handle->encoding == ENC_BASE64) - handle->s = decodeB(&p); + decodeB_to_growbuf(&gbtmp, &p); else if (handle->encoding == ENC_UUENCODE) - handle->s = decodeU(&p); + decodeU_to_growbuf(&gbtmp, &p); + growbuf_clear(&handle->gb); + handle->gb = gbtmp; handle->pos = 0; } - if (len > handle->s->length - handle->pos) - len = handle->s->length - handle->pos; + if (len > handle->gb.length - handle->pos) + len = handle->gb.length - handle->pos; - bcopy(&handle->s->ptr[handle->pos], buf, len); + memcpy(buf, &handle->gb.ptr[handle->pos], len); handle->pos += len; return len; } + +static void +memchop(char *p, int *len) +{ + char *q; + + for (q = p + *len; q > p; --q) { + if (q[-1] != '\n' && q[-1] != '\r') + break; + } + if (q != p + *len) + *q = '\0'; + *len = q - p; + return; +} -- cgit v1.2.3