1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 #ifndef SQUID_HTTPHEADERRANGE_H
10 #define SQUID_HTTPHEADERRANGE_H
11 
12 #include "mem/forward.h"
13 #include "Range.h"
14 #include "SquidString.h"
15 
16 #include <vector>
17 
18 class HttpReply;
19 class Packable;
20 
21 // TODO: Refactor to disambiguate and provide message-specific APIs.
22 /// either byte-range-spec (in a request Range header)
23 /// or suffix-byte-range-spec (in a request Range header)
24 /// or byte-range part of byte-range-resp (in a response Content-Range header)
25 /// or "*" part of unsatisfied-range (in a response Content-Range header)
26 class HttpHdrRangeSpec
27 {
28     MEMPROXY_CLASS(HttpHdrRangeSpec);
29 
30 public:
31     typedef Range<int64_t, uint64_t> HttpRange;
32     static int64_t const UnknownPosition;
33 
34     HttpHdrRangeSpec();
35     static HttpHdrRangeSpec *Create(const char *field, int fieldLen);
36 
37     bool parseInit(const char *field, int flen);
38     int canonize(int64_t clen);
39     void outputInfo( char const *note) const;
40     void packInto(Packable * p) const;
41     bool mergeWith(const HttpHdrRangeSpec * donor);
42     int64_t offset;
43     int64_t length;
44 };
45 
46 /**
47  * There may be more than one byte range specified in the request.
48  * This object holds all range specs in order of their appearence
49  * in the request because we SHOULD preserve that order.
50  */
51 class HttpHdrRange
52 {
53     MEMPROXY_CLASS(HttpHdrRange);
54 
55 public:
56     static size_t ParsedCount;
57     /* Http Range Header Field */
58     static HttpHdrRange *ParseCreate(const String * range_spec);
59 
60     HttpHdrRange();
61     HttpHdrRange(HttpHdrRange const &);
62     ~HttpHdrRange();
63     HttpHdrRange &operator= (HttpHdrRange const &);
64 
65     typedef std::vector<HttpHdrRangeSpec *>::iterator iterator;
66     typedef std::vector<HttpHdrRangeSpec *>::const_iterator const_iterator;
67     iterator begin();
68     const_iterator begin () const;
69     iterator end();
70     const_iterator end() const;
71 
72     /* adjust specs after the length is known */
73     int canonize(int64_t);
74     int canonize(HttpReply *rep);
75     /* returns true if ranges are valid; inits HttpHdrRange */
76     bool parseInit(const String * range_spec);
77     void packInto(Packable * p) const;
78     /* other */
79     bool isComplex() const;
80     bool willBeComplex() const;
81     int64_t firstOffset() const;
82     int64_t lowestOffset(int64_t) const;
83     bool offsetLimitExceeded(const int64_t limit) const;
84     std::vector<HttpHdrRangeSpec *> specs;
85 
86 private:
87     void getCanonizedSpecs (std::vector<HttpHdrRangeSpec *> &copy);
88     void merge (std::vector<HttpHdrRangeSpec *> &basis);
89     int64_t clen;
90 };
91 
92 /**
93  * Data for iterating thru range specs
94  */
95 class HttpHdrRangeIter
96 {
97 
98 public:
99     HttpHdrRange::iterator pos;
100     HttpHdrRange::iterator end;
101     const HttpHdrRangeSpec *currentSpec() const;
102     void updateSpec();
103     int64_t debt() const;
104     void debt(int64_t);
105     int64_t debt_size = 0;  /* bytes left to send from the current spec */
106     String boundary;        /* boundary for multipart responses */
107     bool valid = false;
108 };
109 
110 #endif /* SQUID_HTTPHEADERRANGE_H */
111 
112