From: Greg Ames Date: Thu, 7 Mar 2002 22:08:46 +0000 (+0000) Subject: ap_rgetline: fix folding and partial line handling on ebcdic boxes. The X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=df084162b068353c50dc70cf28f4764de033630a;p=apache ap_rgetline: fix folding and partial line handling on ebcdic boxes. The normal case worked OK, but due to the recursion and multiple exit points, input bytes could go thru charset translation multiple times or not at all. Suggested by: Justin Erenkrantz git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@93776 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/include/http_protocol.h b/include/http_protocol.h index fd76d70f20..2c01b479ae 100644 --- a/include/http_protocol.h +++ b/include/http_protocol.h @@ -541,6 +541,14 @@ AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold); /** * Get the next line of input for the request + * + * Note: on ASCII boxes, ap_rgetline is a macro which simply calls + * ap_rgetline_core to get the line of input. + * + * on EBCDIC boxes, ap_rgetline is a wrapper function which + * translates ASCII protocol lines to the local EBCDIC code page + * after getting the line of input. + * * @param s Pointer to the pointer to the buffer into which the line * should be read; if *s==NULL, a buffer of the necessary size * to hold the data will be allocated from the request pool @@ -552,9 +560,17 @@ AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold); * APR_ENOSPC, if the line is too big to fit in the buffer * Other errors where appropriate */ -AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, apr_size_t *read, +#if APR_CHARSET_EBCDIC +AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, + apr_size_t *read, request_rec *r, int fold); - +#else /* ASCII box */ +#define ap_rgetline(s, n, read, r, fold) \ + ap_rgetline_core((s), (n), (read), (r), (fold)) +#endif +AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, + apr_size_t *read, + request_rec *r, int fold); /** * Get the method number associated with the given string, assumed to * contain an HTTP method. Returns M_INVALID if not recognized. diff --git a/server/protocol.c b/server/protocol.c index d7ce8f50d0..081984c7a6 100644 --- a/server/protocol.c +++ b/server/protocol.c @@ -187,7 +187,7 @@ AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime) * caused by MIME folding (or broken clients) if fold != 0, and place it * in the buffer s, of size n bytes, without the ending newline. * - * If s is NULL, ap_rgetline will allocate necessary memory from r->pool. + * If s is NULL, ap_rgetline_core will allocate necessary memory from r->pool. * * Returns APR_SUCCESS if there are no problems and sets *read to be * the full length of s. @@ -204,9 +204,9 @@ AP_DECLARE(apr_time_t) ap_rationalize_mtime(request_rec *r, apr_time_t mtime) * If no LF is detected on the last line due to a dropped connection * or a full buffer, that's considered an error. */ -AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, - apr_size_t *read, request_rec *r, - int fold) +AP_DECLARE(apr_status_t) ap_rgetline_core(char **s, apr_size_t n, + apr_size_t *read, request_rec *r, + int fold) { apr_status_t rv; apr_bucket_brigade *b; @@ -323,7 +323,7 @@ AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, next_size = n - bytes_handled; - rv = ap_rgetline(&tmp, next_size, &next_len, r, fold); + rv = ap_rgetline_core(&tmp, next_size, &next_len, r, fold); if (rv != APR_SUCCESS) { return rv; @@ -456,7 +456,7 @@ AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, next_size = n - bytes_handled; - rv = ap_rgetline(&tmp, next_size, &next_len, r, fold); + rv = ap_rgetline_core(&tmp, next_size, &next_len, r, fold); if (rv != APR_SUCCESS) { return rv; @@ -483,11 +483,32 @@ AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, } } - /* FIXME: Can we optimize this at all by placing it a different layer? */ - ap_xlate_proto_from_ascii(*s, bytes_handled); *read = bytes_handled; return APR_SUCCESS; } + +#if APR_CHARSET_EBCDIC +AP_DECLARE(apr_status_t) ap_rgetline(char **s, apr_size_t n, + apr_size_t *read, request_rec *r, + int fold) +{ + /* on ASCII boxes, ap_rgetline is a macro which simply invokes + * ap_rgetline_core with the same parms + * + * on EBCDIC boxes, each complete http protocol input line needs to be + * translated into the code page used by the compiler. Since + * ap_rgetline_core uses recursion, we do the translation in a wrapper + * function to insure that each input character gets translated only once. + */ + apr_status_t rv; + + rv = ap_rgetline_core(s, n, read, r, fold); + if (rv == APR_SUCCESS) { + ap_xlate_proto_from_ascii(*s, *read); + } + return rv; +} +#endif AP_DECLARE(int) ap_getline(char *s, int n, request_rec *r, int fold) {