]> granicus.if.org Git - apache/commitdiff
ap_rgetline: fix folding and partial line handling on ebcdic boxes. The
authorGreg Ames <gregames@apache.org>
Thu, 7 Mar 2002 22:08:46 +0000 (22:08 +0000)
committerGreg Ames <gregames@apache.org>
Thu, 7 Mar 2002 22:08:46 +0000 (22:08 +0000)
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

include/http_protocol.h
server/protocol.c

index fd76d70f206f954096a9207185b33ea29dab8942..2c01b479ae0ddaea212a8146650d557b201a7e86 100644 (file)
@@ -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.
index d7ce8f50d0e7018096229aa8a817c61b13057310..081984c7a63c1bc17254b6ae82a04393afff5feb 100644 (file)
@@ -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)
 {