summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndré Malo <nd@apache.org>2003-03-11 00:36:18 +0100
committerAndré Malo <nd@apache.org>2003-03-11 00:36:18 +0100
commit3cbaec5d044c29b0c015377273b0f3fcb139c3a4 (patch)
treee978433850cfafe2b303a2e8d342cf11d74b2845
parentthe symbols target in apr-iconv disappeared... (diff)
downloadapache2-3cbaec5d044c29b0c015377273b0f3fcb139c3a4.tar.xz
apache2-3cbaec5d044c29b0c015377273b0f3fcb139c3a4.zip
mod_negotiation: quality values are now parsed independent from
the current locale. level values are now really parsed as integers. PR: 17564 Reviewed by: Dirk-Willem van Gulik git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@98964 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES4
-rw-r--r--modules/mappers/mod_negotiation.c63
2 files changed, 65 insertions, 2 deletions
diff --git a/CHANGES b/CHANGES
index 44d8a615d6..75564a1c63 100644
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,10 @@ Changes with Apache 2.1.0-dev
[Remove entries to the current 2.0 section below, when backported]
+ *) mod_negotiation: quality values are now parsed independent from
+ the current locale. level values are now really parsed as integers.
+ PR 17564. [André Malo]
+
*) mod_deflate: Check also err_headers_out for an already set
Content-Encoding: gzip header. This prevents gzip compressed content
from a CGI script from being compressed once more. PR 17797.
diff --git a/modules/mappers/mod_negotiation.c b/modules/mappers/mod_negotiation.c
index 6f439e757f..b2db9f4d81 100644
--- a/modules/mappers/mod_negotiation.c
+++ b/modules/mappers/mod_negotiation.c
@@ -385,6 +385,65 @@ static void set_vlist_validator(request_rec *r, request_rec *vlistr)
*/
/*
+ * parse quality value. atof(3) is not well-usable here, because it
+ * depends on the locale (argh).
+ *
+ * However, RFC 2616 states:
+ * 3.9 Quality Values
+ *
+ * [...] HTTP/1.1 applications MUST NOT generate more than three digits
+ * after the decimal point. User configuration of these values SHOULD also
+ * be limited in this fashion.
+ *
+ * qvalue = ( "0" [ "." 0*3DIGIT ] )
+ * | ( "1" [ "." 0*3("0") ] )
+ *
+ * This is quite easy. If the supplied string doesn't match the above
+ * definition (loosely), we simply return 1 (same as if there's no qvalue)
+ */
+
+static float atoq(const char *string)
+{
+ if (!string || !*string) {
+ return 1.0f;
+ }
+
+ while (*string && apr_isspace(*string)) {
+ ++string;
+ }
+
+ /* be tolerant and accept qvalues without leading zero
+ * (also for backwards compat, where atof() was in use)
+ */
+ if (*string != '.' && *string++ != '0') {
+ return 1.0f;
+ }
+
+ if (*string == '.') {
+ /* better only one division later, than dealing with fscking
+ * IEEE format 0.1 factors ...
+ */
+ int i = 0;
+
+ if (*++string >= '0' && *string <= '9') {
+ i += (*string - '0') * 100;
+
+ if (*++string >= '0' && *string <= '9') {
+ i += (*string - '0') * 10;
+
+ if (*++string > '0' && *string <= '9') {
+ i += (*string - '0');
+ }
+ }
+ }
+
+ return (float)i / 1000.0f;
+ }
+
+ return 0.0f;
+}
+
+/*
* Get a single mime type entry --- one media type and parameters;
* enter the values we recognize into the argument accept_rec
*/
@@ -467,10 +526,10 @@ static const char *get_entry(apr_pool_t *p, accept_rec *result,
if (parm[0] == 'q'
&& (parm[1] == '\0' || (parm[1] == 's' && parm[2] == '\0'))) {
- result->quality = (float)atof(cp);
+ result->quality = atoq(cp);
}
else if (parm[0] == 'l' && !strcmp(&parm[1], "evel")) {
- result->level = (float)atof(cp);
+ result->level = (float)atoi(cp);
}
else if (!strcmp(parm, "charset")) {
result->charset = cp;