1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server;
20
21 import java.util.Enumeration;
22 import java.util.List;
23 import java.util.StringTokenizer;
24
25 import org.eclipse.jetty.util.LazyList;
26 import org.eclipse.jetty.util.log.Log;
27 import org.eclipse.jetty.util.log.Logger;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class InclusiveByteRange
54 {
55 private static final Logger LOG = Log.getLogger(InclusiveByteRange.class);
56
57 long first = 0;
58 long last = 0;
59
60 public InclusiveByteRange(long first, long last)
61 {
62 this.first = first;
63 this.last = last;
64 }
65
66 public long getFirst()
67 {
68 return first;
69 }
70
71 public long getLast()
72 {
73 return last;
74 }
75
76
77
78
79
80
81
82
83
84 public static List<InclusiveByteRange> satisfiableRanges(Enumeration<String> headers, long size)
85 {
86 Object satRanges=null;
87
88
89 headers:
90 while (headers.hasMoreElements())
91 {
92 String header = headers.nextElement();
93 StringTokenizer tok = new StringTokenizer(header,"=,",false);
94 String t=null;
95 try
96 {
97
98 while (tok.hasMoreTokens())
99 {
100 try
101 {
102 t = tok.nextToken().trim();
103
104 long first = -1;
105 long last = -1;
106 int d = t.indexOf('-');
107 if (d < 0 || t.indexOf("-",d + 1) >= 0)
108 {
109 if ("bytes".equals(t))
110 continue;
111 LOG.warn("Bad range format: {}",t);
112 continue headers;
113 }
114 else if (d == 0)
115 {
116 if (d + 1 < t.length())
117 last = Long.parseLong(t.substring(d + 1).trim());
118 else
119 {
120 LOG.warn("Bad range format: {}",t);
121 continue;
122 }
123 }
124 else if (d + 1 < t.length())
125 {
126 first = Long.parseLong(t.substring(0,d).trim());
127 last = Long.parseLong(t.substring(d + 1).trim());
128 }
129 else
130 first = Long.parseLong(t.substring(0,d).trim());
131
132 if (first == -1 && last == -1)
133 continue headers;
134
135 if (first != -1 && last != -1 && (first > last))
136 continue headers;
137
138 if (first < size)
139 {
140 InclusiveByteRange range = new InclusiveByteRange(first,last);
141 satRanges = LazyList.add(satRanges,range);
142 }
143 }
144 catch (NumberFormatException e)
145 {
146 LOG.warn("Bad range format: {}",t);
147 LOG.ignore(e);
148 continue;
149 }
150 }
151 }
152 catch(Exception e)
153 {
154 LOG.warn("Bad range format: {}",t);
155 LOG.ignore(e);
156 }
157 }
158 return LazyList.getList(satRanges,true);
159 }
160
161
162 public long getFirst(long size)
163 {
164 if (first<0)
165 {
166 long tf=size-last;
167 if (tf<0)
168 tf=0;
169 return tf;
170 }
171 return first;
172 }
173
174
175 public long getLast(long size)
176 {
177 if (first<0)
178 return size-1;
179
180 if (last<0 ||last>=size)
181 return size-1;
182 return last;
183 }
184
185
186 public long getSize(long size)
187 {
188 return getLast(size)-getFirst(size)+1;
189 }
190
191
192
193 public String toHeaderRangeString(long size)
194 {
195 StringBuilder sb = new StringBuilder(40);
196 sb.append("bytes ");
197 sb.append(getFirst(size));
198 sb.append('-');
199 sb.append(getLast(size));
200 sb.append("/");
201 sb.append(size);
202 return sb.toString();
203 }
204
205
206 public static String to416HeaderRangeString(long size)
207 {
208 StringBuilder sb = new StringBuilder(40);
209 sb.append("bytes */");
210 sb.append(size);
211 return sb.toString();
212 }
213
214
215
216 @Override
217 public String toString()
218 {
219 StringBuilder sb = new StringBuilder(60);
220 sb.append(Long.toString(first));
221 sb.append(":");
222 sb.append(Long.toString(last));
223 return sb.toString();
224 }
225
226
227 }
228
229
230