diff src/http/modules/ngx_http_range_filter.c @ 10:46833bd150cb NGINX_0_1_5

nginx 0.1.5 *) Bugfix: on Solaris and Linux there may be too many "recvmsg() returned not enough data" alerts. *) Bugfix: there were the "writev() failed (22: Invalid argument)" errors on Solaris in proxy mode without sendfile. On other platforms that do not support sendfile at all the process got caught in an endless loop. *) Bugfix: segmentation fault on Solaris in proxy mode and using sendfile. *) Bugfix: segmentation fault on Solaris. *) Bugfix: on-line upgrade did not work on Linux. *) Bugfix: the ngx_http_autoindex_module module did not escape the spaces, the quotes, and the percent signs in the directory listing. *) Change: the decrease of the copy operations. *) Feature: the userid_p3p directive.
author Igor Sysoev <http://sysoev.ru>
date Thu, 11 Nov 2004 00:00:00 +0300
parents 4b2dafa26fe2
children 74b1868dd3cd
line wrap: on
line diff
--- a/src/http/modules/ngx_http_range_filter.c
+++ b/src/http/modules/ngx_http_range_filter.c
@@ -107,11 +107,13 @@ static ngx_http_output_body_filter_pt   
 
 static ngx_int_t ngx_http_range_header_filter(ngx_http_request_t *r)
 {
-    ngx_int_t                     rc;
-    ngx_uint_t                    boundary, suffix, i;
     u_char                       *p;
     size_t                        len;
     off_t                         start, end;
+    ngx_int_t                     rc;
+    uint32_t                      boundary;
+    ngx_uint_t                    suffix, i;
+    ngx_table_elt_t              *content_range;
     ngx_http_range_t             *range;
     ngx_http_range_filter_ctx_t  *ctx;
 
@@ -141,8 +143,11 @@ static ngx_int_t ngx_http_range_header_f
         return ngx_http_next_header_filter(r);
     }
 
-    ngx_init_array(r->headers_out.ranges, r->pool, 5, sizeof(ngx_http_range_t),
-                   NGX_ERROR);
+    if (ngx_array_init(&r->headers_out.ranges, r->pool, 5,
+                                        sizeof(ngx_http_range_t)) == NGX_ERROR)
+    {
+        return NGX_ERROR;
+    }
 
     rc = 0;
     range = NULL;
@@ -180,8 +185,10 @@ static ngx_int_t ngx_http_range_header_f
             while (*p == ' ') { p++; }
 
             if (*p == ',' || *p == '\0') {
-                ngx_test_null(range, ngx_push_array(&r->headers_out.ranges),
-                              NGX_ERROR);
+                if (!(range = ngx_array_push(&r->headers_out.ranges))) {
+                    return NGX_ERROR;
+                }
+
                 range->start = start;
                 range->end = r->headers_out.content_length_n;
 
@@ -223,7 +230,10 @@ static ngx_int_t ngx_http_range_header_f
             break;
         }
 
-        ngx_test_null(range, ngx_push_array(&r->headers_out.ranges), NGX_ERROR);
+        if (!(range = ngx_array_push(&r->headers_out.ranges))) {
+            return NGX_ERROR;
+        }
+
         range->start = start;
 
         if (end >= r->headers_out.content_length_n) {
@@ -249,29 +259,26 @@ static ngx_int_t ngx_http_range_header_f
         r->headers_out.status = rc;
         r->headers_out.ranges.nelts = 0;
 
-        r->headers_out.content_range = ngx_list_push(&r->headers_out.headers);
-        if (r->headers_out.content_range == NULL) {
+        if (!(content_range = ngx_list_push(&r->headers_out.headers))) {
             return NGX_ERROR;
         }
 
-        r->headers_out.content_range->key.len = sizeof("Content-Range") - 1;
-        r->headers_out.content_range->key.data = (u_char *) "Content-Range";
+        r->headers_out.content_range = content_range;
+
+        content_range->key.len = sizeof("Content-Range") - 1;
+        content_range->key.data = (u_char *) "Content-Range";
 
-        r->headers_out.content_range->value.data =
-                                               ngx_palloc(r->pool, 8 + 20 + 1);
-        if (r->headers_out.content_range->value.data == NULL) {
+        content_range->value.data =
+                   ngx_palloc(r->pool, sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
+
+        if (content_range->value.data == NULL) {
             return NGX_ERROR;
         }
 
-        r->headers_out.content_range->value.len =
-                ngx_sprintf(r->headers_out.content_range->value.data,
-                            "bytes */%O", r->headers_out.content_length_n)
-                - r->headers_out.content_range->value.data;
-#if 0
-                ngx_snprintf((char *) r->headers_out.content_range->value.data,
-                             8 + 20 + 1, "bytes */" OFF_T_FMT,
-                             r->headers_out.content_length_n);
-#endif
+        content_range->value.len = ngx_sprintf(content_range->value.data,
+                                               "bytes */%O",
+                                               r->headers_out.content_length_n)
+                                   - content_range->value.data;
 
         r->headers_out.content_length_n = -1;
         if (r->headers_out.content_length) {
@@ -280,176 +287,134 @@ static ngx_int_t ngx_http_range_header_f
         }
 
         return rc;
+    }
+
+    r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
+
+    if (r->headers_out.ranges.nelts == 1) {
+
+        if (!(content_range = ngx_list_push(&r->headers_out.headers))) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.content_range = content_range;
+
+        content_range->key.len = sizeof("Content-Range") - 1;
+        content_range->key.data = (u_char *) "Content-Range";
+
+        content_range->value.data =
+               ngx_palloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
+        if (content_range->value.data == NULL) {
+            return NGX_ERROR;
+        }
+
+        /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
+
+        content_range->value.len = ngx_sprintf(content_range->value.data,
+                                               "bytes %O-%O/%O",
+                                               range->start, range->end - 1,
+                                               r->headers_out.content_length_n)
+                                   - content_range->value.data;
+
+        r->headers_out.content_length_n = range->end - range->start;
+
+        return ngx_http_next_header_filter(r);
+    }
+
+
+    /* TODO: what if no content_type ?? */
+
+    ngx_http_create_ctx(r, ctx, ngx_http_range_body_filter_module,
+                        sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
+
+
+    len = sizeof(CRLF "--0123456789" CRLF "Content-Type: ") - 1
+          + r->headers_out.content_type->value.len
+          + sizeof(CRLF "Content-Range: bytes ") - 1;
+
+    if (r->headers_out.charset.len) {
+        len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
+    }
+
+    if (!(ctx->boundary_header.data = ngx_palloc(r->pool, len))) {
+        return NGX_ERROR;
+    }
+
+    boundary = ngx_next_temp_number(0);
+
+    /*
+     * The boundary header of the range:
+     * CRLF
+     * "--0123456789" CRLF
+     * "Content-Type: image/jpeg" CRLF
+     * "Content-Range: bytes "
+     */
+
+    if (r->headers_out.charset.len) {
+        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
+                                           CRLF "--%010ud" CRLF
+                                           "Content-Type: %V; charset=%V" CRLF
+                                           "Content-Range: bytes ",
+                                           boundary,
+                                           &r->headers_out.content_type->value,
+                                           &r->headers_out.charset)
+                                   - ctx->boundary_header.data;
+
+        r->headers_out.charset.len = 0;
 
     } else {
-        r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
-
-        if (r->headers_out.ranges.nelts == 1) {
-
-            r->headers_out.content_range =
-                                        ngx_list_push(&r->headers_out.headers);
-            if (r->headers_out.content_range == NULL) {
-                return NGX_ERROR;
-            }
-
-            r->headers_out.content_range->key.len = sizeof("Content-Range") - 1;
-            r->headers_out.content_range->key.data = (u_char *) "Content-Range";
-
-            ngx_test_null(r->headers_out.content_range->value.data,
-                          ngx_palloc(r->pool, 6 + 20 + 1 + 20 + 1 + 20 + 1),
-                          NGX_ERROR);
-
-            /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
-
-            r->headers_out.content_range->value.len =
-                         ngx_sprintf(r->headers_out.content_range->value.data,
-                                     "bytes %O-%O/%O",
-                                     range->start, range->end - 1,
-                                     r->headers_out.content_length_n)
-                         - r->headers_out.content_range->value.data;
-
-#if 0
-                   ngx_snprintf((char *)
-                                r->headers_out.content_range->value.data,
-                                6 + 20 + 1 + 20 + 1 + 20 + 1,
-                                "bytes " OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT,
-                                range->start, range->end - 1,
-                                r->headers_out.content_length_n);
-#endif
+        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
+                                           CRLF "--%010ud" CRLF
+                                           "Content-Type: %V" CRLF
+                                           "Content-Range: bytes ",
+                                           boundary,
+                                           &r->headers_out.content_type->value)
+                                   - ctx->boundary_header.data;
+    }
 
-            r->headers_out.content_length_n = range->end - range->start;
-
-        } else {
-
-#if 0
-            /* TODO: what if no content_type ?? */
+    r->headers_out.content_type->value.data =
+           ngx_palloc(r->pool, sizeof("Content-Type: multipart/byteranges; "
+                                      "boundary=0123456789") - 1);
 
-            if (!(r->headers_out.content_type =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-            {
-                return NGX_ERROR;
-            }
-#endif
-
-            ngx_http_create_ctx(r, ctx, ngx_http_range_body_filter_module,
-                                sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
+    if (r->headers_out.content_type->value.data == NULL) {
+        return NGX_ERROR;
+    }
 
-            len = 4 + 10 + 2 + 14 + r->headers_out.content_type->value.len
-                                  + 2 + 21 + 1;
-
-            if (r->headers_out.charset.len) {
-                len += 10 + r->headers_out.charset.len;
-            }
-
-            ngx_test_null(ctx->boundary_header.data, ngx_palloc(r->pool, len),
-                          NGX_ERROR);
+    /* "Content-Type: multipart/byteranges; boundary=0123456789" */
 
-            boundary = ngx_next_temp_number(0);
-
-            /*
-             * The boundary header of the range:
-             * CRLF
-             * "--0123456789" CRLF
-             * "Content-Type: image/jpeg" CRLF
-             * "Content-Range: bytes "
-             */
+    r->headers_out.content_type->value.len =
+                           ngx_sprintf(r->headers_out.content_type->value.data,
+                                       "multipart/byteranges; boundary=%010ud",
+                                       boundary)
+                           - r->headers_out.content_type->value.data;
 
-            if (r->headers_out.charset.len) {
-                ctx->boundary_header.len =
-                          ngx_sprintf(ctx->boundary_header.data,
-                                      CRLF "--%010ui" CRLF
-                                      "Content-Type: %s; charset=%s" CRLF
-                                      "Content-Range: bytes ",
-                                      boundary,
-                                      r->headers_out.content_type->value.data,
-                                      r->headers_out.charset.data)
-                          - ctx->boundary_header.data;
-#if 0
-                         ngx_snprintf((char *) ctx->boundary_header.data, len,
-                                      CRLF "--%010" NGX_UINT_T_FMT CRLF
-                                      "Content-Type: %s; charset=%s" CRLF
-                                      "Content-Range: bytes ",
-                                      boundary,
-                                      r->headers_out.content_type->value.data,
-                                      r->headers_out.charset.data);
-#endif
-
-                r->headers_out.charset.len = 0;
+    /* the size of the last boundary CRLF "--0123456789--" CRLF */
+    len = sizeof(CRLF "--0123456789--" CRLF) - 1;
 
-            } else {
-                ctx->boundary_header.len =
-                          ngx_sprintf(ctx->boundary_header.data,
-                                      CRLF "--%010ui" CRLF
-                                      "Content-Type: %s" CRLF
-                                      "Content-Range: bytes ",
-                                      boundary,
-                                      r->headers_out.content_type->value.data)
-                          - ctx->boundary_header.data;
+    range = r->headers_out.ranges.elts;
+    for (i = 0; i < r->headers_out.ranges.nelts; i++) {
 
-#if 0
-                         ngx_snprintf((char *) ctx->boundary_header.data, len,
-                                      CRLF "--%010" NGX_UINT_T_FMT CRLF
-                                      "Content-Type: %s" CRLF
-                                      "Content-Range: bytes ",
-                                      boundary,
-                                      r->headers_out.content_type->value.data);
+        /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
 
-#endif
-            }
-
-            ngx_test_null(r->headers_out.content_type->value.data,
-                          ngx_palloc(r->pool, 31 + 10 + 1),
-                          NGX_ERROR);
+        range[i].content_range.data =
+                                ngx_palloc(r->pool, 3 * NGX_OFF_T_LEN + 2 + 4);
 
-            /* "Content-Type: multipart/byteranges; boundary=0123456789" */
-
-            r->headers_out.content_type->value.len =
-                       ngx_sprintf(r->headers_out.content_type->value.data,
-                                   "multipart/byteranges; boundary=%010ui",
-                                   boundary)
-                       - r->headers_out.content_type->value.data;
-#if 0
-                      ngx_snprintf((char *)
-                                   r->headers_out.content_type->value.data,
-                                   31 + 10 + 1,
-                                   "multipart/byteranges; boundary=%010"
-                                   NGX_UINT_T_FMT,
-                                   boundary);
-#endif
-
-            /* the size of the last boundary CRLF "--0123456789--" CRLF */
-            len = 4 + 10 + 4;
-
-            range = r->headers_out.ranges.elts;
-            for (i = 0; i < r->headers_out.ranges.nelts; i++) {
-                ngx_test_null(range[i].content_range.data,
-                              ngx_palloc(r->pool, 20 + 1 + 20 + 1 + 20 + 5),
-                              NGX_ERROR);
+        if (range[i].content_range.data == NULL) {
+            return NGX_ERROR;
+        }
 
-                /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
+        range[i].content_range.len = ngx_sprintf(range[i].content_range.data,
+                                               "%O-%O/%O" CRLF CRLF,
+                                               range[i].start, range[i].end - 1,
+                                               r->headers_out.content_length_n)
+                                     - range[i].content_range.data;
 
-                range[i].content_range.len =
-                                 ngx_sprintf(range[i].content_range.data,
-                                             "%O-%O/%O" CRLF CRLF,
-                                             range[i].start, range[i].end - 1,
-                                             r->headers_out.content_length_n)
-                                 - range[i].content_range.data;
-#if 0
-                  ngx_snprintf((char *) range[i].content_range.data,
-                               20 + 1 + 20 + 1 + 20 + 5,
-                               OFF_T_FMT "-" OFF_T_FMT "/" OFF_T_FMT CRLF CRLF,
-                               range[i].start, range[i].end - 1,
-                               r->headers_out.content_length_n);
-#endif
+        len += ctx->boundary_header.len + range[i].content_range.len
+                                    + (size_t) (range[i].end - range[i].start);
+    }
 
-                len += ctx->boundary_header.len + range[i].content_range.len
-                                    + (size_t) (range[i].end - range[i].start);
-            }
-
-            r->headers_out.content_length_n = len;
-            r->headers_out.content_length = NULL;
-        }
-    }
+    r->headers_out.content_length_n = len;
+    r->headers_out.content_length = NULL;
 
     return ngx_http_next_header_filter(r);
 }
@@ -496,33 +461,54 @@ static ngx_int_t ngx_http_range_body_fil
              * "Content-Range: bytes "
              */
 
-            ngx_test_null(b, ngx_calloc_buf(r->pool), NGX_ERROR);
+            if (!(b = ngx_calloc_buf(r->pool))) {
+                return NGX_ERROR;
+            }
+
             b->memory = 1;
             b->pos = ctx->boundary_header.data;
             b->last = ctx->boundary_header.data + ctx->boundary_header.len;
 
-            ngx_test_null(hcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+            if (!(hcl = ngx_alloc_chain_link(r->pool))) {
+                return NGX_ERROR;
+            }
+
             hcl->buf = b;
 
+
             /* "SSSS-EEEE/TTTT" CRLF CRLF */
 
-            ngx_test_null(b, ngx_calloc_buf(r->pool), NGX_ERROR);
+            if (!(b = ngx_calloc_buf(r->pool))) {
+                return NGX_ERROR;
+            }
+
             b->temporary = 1;
             b->pos = range[i].content_range.data;
             b->last = range[i].content_range.data + range[i].content_range.len;
 
-            ngx_test_null(rcl, ngx_alloc_chain_link(r->pool), NGX_ERROR);
+            if (!(rcl = ngx_alloc_chain_link(r->pool))) {
+                return NGX_ERROR;
+            }
+
             rcl->buf = b;
 
+
             /* the range data */
 
-            ngx_test_null(b, ngx_calloc_buf(r->pool), NGX_ERROR);
+            if (!(b = ngx_calloc_buf(r->pool))) {
+                return NGX_ERROR;
+            }
+
             b->in_file = 1;
             b->file_pos = range[i].start;
             b->file_last = range[i].end;
             b->file = in->buf->file;
 
-            ngx_alloc_link_and_set_buf(dcl, b, r->pool, NGX_ERROR);
+            if (!(dcl = ngx_alloc_chain_link(r->pool))) {
+                return NGX_ERROR;
+            }
+
+            dcl->buf = b;
 
             *ll = hcl;
             hcl->next = rcl;
@@ -532,15 +518,29 @@ static ngx_int_t ngx_http_range_body_fil
 
         /* the last boundary CRLF "--0123456789--" CRLF  */
 
-        ngx_test_null(b, ngx_calloc_buf(r->pool), NGX_ERROR);
+        if (!(b = ngx_calloc_buf(r->pool))) {
+            return NGX_ERROR;
+        }
+
         b->temporary = 1;
         b->last_buf = 1;
-        ngx_test_null(b->pos, ngx_palloc(r->pool, 4 + 10 + 4), NGX_ERROR);
+
+        b->pos = ngx_palloc(r->pool, sizeof(CRLF "--0123456789--" CRLF) - 1);
+        if (b->pos == NULL) {
+            return NGX_ERROR;
+        }
+
         b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, 4 + 10);
         *b->last++ = '-'; *b->last++ = '-';
         *b->last++ = CR; *b->last++ = LF;
 
-        ngx_alloc_link_and_set_buf(hcl, b, r->pool, NGX_ERROR);
+        if (!(hcl = ngx_alloc_chain_link(r->pool))) {
+            return NGX_ERROR;
+        }
+
+        hcl->buf = b;
+        hcl->next = NULL;
+
         *ll = hcl;
 
         return ngx_http_next_body_filter(r, out);