PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
[ start all new proposals below, under PATCHES PROPOSED. ]
- * mod_deflate: Fix creation of invalid Etags with mod_deflate
- (PR 39727, comment #22)
- (updated to use Roy's patch)
- Trunk version of patch:
- (http://svn.apache.org/viewvc?view=rev&revision=740149)
- http://svn.apache.org/viewvc?view=rev&revision=743595
- Backport version for 2.2.x of patch:
- http://people.apache.org/~lars/mod_deflate_etagfix.patch
- +1: lars, fielding, minfrin
-
PATCHES PROPOSED TO BACKPORT FROM TRUNK:
[ New proposals should be added at the end of the list ]
ctx->libz_end_func(&ctx->stream);
return APR_SUCCESS;
}
-/* PR 39727: we're screwing up our clients if we leave a strong ETag
- * header while transforming content. Henrik Nordstrom suggests
- * appending ";gzip".
- *
- * Pending a more thorough review of our Etag handling, let's just
- * implement his suggestion. It fixes the bug, or at least turns it
- * from a showstopper to an inefficiency. And it breaks nothing that
- * wasn't already broken.
+/* ETag must be unique among the possible representations, so a change
+ * to content-encoding requires a corresponding change to the ETag.
+ * This routine appends -transform (e.g., -gzip) to the entity-tag
+ * value inside the double-quotes if an ETag has already been set
+ * and its value already contains double-quotes. PR 39727
*/
static void deflate_check_etag(request_rec *r, const char *transform)
{
const char *etag = apr_table_get(r->headers_out, "ETag");
- if (etag && (((etag[0] != 'W') && (etag[0] !='w')) || (etag[1] != '/'))) {
- apr_table_set(r->headers_out, "ETag",
- apr_pstrcat(r->pool, etag, "-", transform, NULL));
- }
+ apr_size_t etaglen;
+
+ if ((etag && ((etaglen = strlen(etag)) > 2))) {
+ if (etag[etaglen - 1] == '"') {
+ apr_size_t transformlen = strlen(transform);
+ char *newtag = apr_palloc(r->pool, etaglen + transformlen + 2);
+ char *d = newtag;
+ char *e = d + etaglen - 1;
+ const char *s = etag;
+
+ for (; d < e; ++d, ++s) {
+ *d = *s; /* copy etag to newtag up to last quote */
+ }
+ *d++ = '-'; /* append dash to newtag */
+ s = transform;
+ e = d + transformlen;
+ for (; d < e; ++d, ++s) {
+ *d = *s; /* copy transform to newtag */
+ }
+ *d++ = '"'; /* append quote to newtag */
+ *d = '\0'; /* null terminate newtag */
+
+ apr_table_setn(r->headers_out, "ETag", newtag);
+ }
+ }
}
static apr_status_t deflate_out_filter(ap_filter_t *f,
apr_bucket_brigade *bb)