HttpHdrContRange.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:6k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: HttpHdrContRange.c,v 1.10 1998/12/05 00:54:09 wessels Exp $
  3.  *
  4.  * DEBUG: section 68    HTTP Content-Range Header
  5.  * AUTHOR: Alex Rousskov
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. #include "squid.h"
  35. /*
  36.  *    Currently only byte ranges are supported
  37.  *
  38.  *    Content-Range = "Content-Range" ":" content-range-spec
  39.  *    content-range-spec      = byte-content-range-spec
  40.  *    byte-content-range-spec = bytes-unit SP
  41.  *                              ( byte-range-resp-spec | "*") "/"
  42.  *                              ( entity-length | "*" )
  43.  *    byte-range-resp-spec = first-byte-pos "-" last-byte-pos
  44.  *    entity-length        = 1*DIGIT
  45.  */
  46. /* local constants */
  47. #define range_spec_unknown ((size_t)-1)
  48. /* local routines */
  49. #define known_spec(s) ((s) != range_spec_unknown)
  50. #define size_min(a,b) ((a) <= (b) ? (a) : (b))
  51. #define size_diff(a,b) ((a) >= (b) ? ((a)-(b)) : 0)
  52. /* globals */
  53. /* parses range-resp-spec and inits spec, returns true on success */
  54. static int
  55. httpHdrRangeRespSpecParseInit(HttpHdrRangeSpec * spec, const char *field, int flen)
  56. {
  57.     const char *p;
  58.     assert(spec);
  59.     spec->offset = spec->length = range_spec_unknown;
  60.     if (flen < 2)
  61. return 0;
  62.     /* is spec given ? */
  63.     if (*field == '*')
  64. return 1;
  65.     /* check format, must be %d-%d */
  66.     if (!((p = strchr(field, '-')) && (p - field < flen))) {
  67. debug(68, 2) ("invalid (no '-') resp-range-spec near: '%s'n", field);
  68. return 0;
  69.     }
  70.     /* parse offset */
  71.     if (!httpHeaderParseSize(field, &spec->offset))
  72. return 0;
  73.     p++;
  74.     /* do we have last-pos ? */
  75.     if (p - field < flen) {
  76. size_t last_pos;
  77. if (!httpHeaderParseSize(p, &last_pos))
  78.     return 0;
  79. spec->length = size_diff(last_pos + 1, spec->offset);
  80.     }
  81.     /* we managed to parse, check if the result makes sence */
  82.     if (known_spec(spec->length) && !spec->length) {
  83. debug(68, 2) ("invalid range (%d += %d) in resp-range-spec near: '%s'n",
  84.     spec->offset, spec->length, field);
  85. return 0;
  86.     }
  87.     return 1;
  88. }
  89. static void
  90. httpHdrRangeRespSpecPackInto(const HttpHdrRangeSpec * spec, Packer * p)
  91. {
  92.     if (!known_spec(spec->offset) || !known_spec(spec->length))
  93. packerPrintf(p, "*");
  94.     else
  95. packerPrintf(p, "bytes %d-%d",
  96.     spec->offset, spec->offset + spec->length - 1);
  97. }
  98. /*
  99.  * Content Range
  100.  */
  101. HttpHdrContRange *
  102. httpHdrContRangeCreate()
  103. {
  104.     HttpHdrContRange *r = memAllocate(MEM_HTTP_HDR_CONTENT_RANGE);
  105.     r->spec.offset = r->spec.length = range_spec_unknown;
  106.     r->elength = range_spec_unknown;
  107.     return r;
  108. }
  109. HttpHdrContRange *
  110. httpHdrContRangeParseCreate(const char *str)
  111. {
  112.     HttpHdrContRange *r = httpHdrContRangeCreate();
  113.     if (!httpHdrContRangeParseInit(r, str)) {
  114. httpHdrContRangeDestroy(r);
  115. r = NULL;
  116.     }
  117.     return r;
  118. }
  119. /* returns true if ranges are valid; inits HttpHdrContRange */
  120. int
  121. httpHdrContRangeParseInit(HttpHdrContRange * range, const char *str)
  122. {
  123.     const char *p;
  124.     assert(range && str);
  125.     debug(68, 8) ("parsing content-range field: '%s'n", str);
  126.     /* check range type */
  127.     if (strncasecmp(str, "bytes ", 6))
  128. return 0;
  129.     str += 6;
  130.     /* split */
  131.     if (!(p = strchr(str, '/')))
  132. return 0;
  133.     if (*str == '*')
  134. range->spec.offset = range->spec.length = range_spec_unknown;
  135.     else if (!httpHdrRangeRespSpecParseInit(&range->spec, str, p - str))
  136. return 0;
  137.     p++;
  138.     if (*p == '*')
  139. range->elength = range_spec_unknown;
  140.     else if (!httpHeaderParseSize(p, &range->elength))
  141. return 0;
  142.     debug(68, 8) ("parsed content-range field: %d-%d / %dn",
  143. range->spec.offset, range->spec.offset + range->spec.length - 1,
  144. range->elength);
  145.     return 1;
  146. }
  147. void
  148. httpHdrContRangeDestroy(HttpHdrContRange * range)
  149. {
  150.     assert(range);
  151.     memFree(range, MEM_HTTP_HDR_CONTENT_RANGE);
  152. }
  153. HttpHdrContRange *
  154. httpHdrContRangeDup(const HttpHdrContRange * range)
  155. {
  156.     HttpHdrContRange *dup;
  157.     assert(range);
  158.     dup = httpHdrContRangeCreate();
  159.     *dup = *range;
  160.     return dup;
  161. }
  162. void
  163. httpHdrContRangePackInto(const HttpHdrContRange * range, Packer * p)
  164. {
  165.     assert(range && p);
  166.     httpHdrRangeRespSpecPackInto(&range->spec, p);
  167.     if (!known_spec(range->elength))
  168. packerPrintf(p, "/*");
  169.     else
  170. packerPrintf(p, "/%d", range->elength);
  171. }
  172. void
  173. httpHdrContRangeSet(HttpHdrContRange * cr, HttpHdrRangeSpec spec, size_t ent_len)
  174. {
  175.     assert(cr && ent_len >= 0);
  176.     cr->spec = spec;
  177.     cr->elength = ent_len;
  178. }