103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.server;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.Enumeration;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.List;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.util.StringTokenizer;
2403928aee4356845252ac6b662d5c72c29903813eJake Slack
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.LazyList;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
2803928aee4356845252ac6b662d5c72c29903813eJake Slack
2903928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
3003928aee4356845252ac6b662d5c72c29903813eJake Slack/** Byte range inclusive of end points.
3103928aee4356845252ac6b662d5c72c29903813eJake Slack * <PRE>
3203928aee4356845252ac6b662d5c72c29903813eJake Slack *
3303928aee4356845252ac6b662d5c72c29903813eJake Slack *   parses the following types of byte ranges:
3403928aee4356845252ac6b662d5c72c29903813eJake Slack *
3503928aee4356845252ac6b662d5c72c29903813eJake Slack *       bytes=100-499
3603928aee4356845252ac6b662d5c72c29903813eJake Slack *       bytes=-300
3703928aee4356845252ac6b662d5c72c29903813eJake Slack *       bytes=100-
3803928aee4356845252ac6b662d5c72c29903813eJake Slack *       bytes=1-2,2-3,6-,-2
3903928aee4356845252ac6b662d5c72c29903813eJake Slack *
4003928aee4356845252ac6b662d5c72c29903813eJake Slack *   given an entity length, converts range to string
4103928aee4356845252ac6b662d5c72c29903813eJake Slack *
4203928aee4356845252ac6b662d5c72c29903813eJake Slack *       bytes 100-499/500
4303928aee4356845252ac6b662d5c72c29903813eJake Slack *
4403928aee4356845252ac6b662d5c72c29903813eJake Slack * </PRE>
4503928aee4356845252ac6b662d5c72c29903813eJake Slack *
4603928aee4356845252ac6b662d5c72c29903813eJake Slack * Based on RFC2616 3.12, 14.16, 14.35.1, 14.35.2
4703928aee4356845252ac6b662d5c72c29903813eJake Slack * @version $version$
4803928aee4356845252ac6b662d5c72c29903813eJake Slack *
4903928aee4356845252ac6b662d5c72c29903813eJake Slack */
5003928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class InclusiveByteRange
5103928aee4356845252ac6b662d5c72c29903813eJake Slack{
5203928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(InclusiveByteRange.class);
5303928aee4356845252ac6b662d5c72c29903813eJake Slack
5403928aee4356845252ac6b662d5c72c29903813eJake Slack    long first = 0;
5503928aee4356845252ac6b662d5c72c29903813eJake Slack    long last  = 0;
5603928aee4356845252ac6b662d5c72c29903813eJake Slack
5703928aee4356845252ac6b662d5c72c29903813eJake Slack    public InclusiveByteRange(long first, long last)
5803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
5903928aee4356845252ac6b662d5c72c29903813eJake Slack        this.first = first;
6003928aee4356845252ac6b662d5c72c29903813eJake Slack        this.last = last;
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getFirst()
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
6503928aee4356845252ac6b662d5c72c29903813eJake Slack        return first;
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
6703928aee4356845252ac6b662d5c72c29903813eJake Slack
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getLast()
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7003928aee4356845252ac6b662d5c72c29903813eJake Slack        return last;
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7203928aee4356845252ac6b662d5c72c29903813eJake Slack
7303928aee4356845252ac6b662d5c72c29903813eJake Slack
7403928aee4356845252ac6b662d5c72c29903813eJake Slack
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
7703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param headers Enumeration of Range header fields.
7803928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param size Size of the resource.
7903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return LazyList of satisfiable ranges
8003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    public static List satisfiableRanges(Enumeration headers, long size)
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8303928aee4356845252ac6b662d5c72c29903813eJake Slack        Object satRanges=null;
8403928aee4356845252ac6b662d5c72c29903813eJake Slack
8503928aee4356845252ac6b662d5c72c29903813eJake Slack        // walk through all Range headers
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    headers:
8703928aee4356845252ac6b662d5c72c29903813eJake Slack        while (headers.hasMoreElements())
8803928aee4356845252ac6b662d5c72c29903813eJake Slack        {
8903928aee4356845252ac6b662d5c72c29903813eJake Slack            String header = (String) headers.nextElement();
9003928aee4356845252ac6b662d5c72c29903813eJake Slack            StringTokenizer tok = new StringTokenizer(header,"=,",false);
9103928aee4356845252ac6b662d5c72c29903813eJake Slack            String t=null;
9203928aee4356845252ac6b662d5c72c29903813eJake Slack            try
9303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
9403928aee4356845252ac6b662d5c72c29903813eJake Slack                // read all byte ranges for this header
9503928aee4356845252ac6b662d5c72c29903813eJake Slack                while (tok.hasMoreTokens())
9603928aee4356845252ac6b662d5c72c29903813eJake Slack                {
9703928aee4356845252ac6b662d5c72c29903813eJake Slack                    try
9803928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
9903928aee4356845252ac6b662d5c72c29903813eJake Slack                        t = tok.nextToken().trim();
10003928aee4356845252ac6b662d5c72c29903813eJake Slack
10103928aee4356845252ac6b662d5c72c29903813eJake Slack                        long first = -1;
10203928aee4356845252ac6b662d5c72c29903813eJake Slack                        long last = -1;
10303928aee4356845252ac6b662d5c72c29903813eJake Slack                        int d = t.indexOf('-');
10403928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (d < 0 || t.indexOf("-",d + 1) >= 0)
10503928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
10603928aee4356845252ac6b662d5c72c29903813eJake Slack                            if ("bytes".equals(t))
10703928aee4356845252ac6b662d5c72c29903813eJake Slack                                continue;
10803928aee4356845252ac6b662d5c72c29903813eJake Slack                            LOG.warn("Bad range format: {}",t);
10903928aee4356845252ac6b662d5c72c29903813eJake Slack                            continue headers;
11003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
11103928aee4356845252ac6b662d5c72c29903813eJake Slack                        else if (d == 0)
11203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
11303928aee4356845252ac6b662d5c72c29903813eJake Slack                            if (d + 1 < t.length())
11403928aee4356845252ac6b662d5c72c29903813eJake Slack                                last = Long.parseLong(t.substring(d + 1).trim());
11503928aee4356845252ac6b662d5c72c29903813eJake Slack                            else
11603928aee4356845252ac6b662d5c72c29903813eJake Slack                            {
11703928aee4356845252ac6b662d5c72c29903813eJake Slack                                LOG.warn("Bad range format: {}",t);
11803928aee4356845252ac6b662d5c72c29903813eJake Slack                                continue;
11903928aee4356845252ac6b662d5c72c29903813eJake Slack                            }
12003928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
12103928aee4356845252ac6b662d5c72c29903813eJake Slack                        else if (d + 1 < t.length())
12203928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
12303928aee4356845252ac6b662d5c72c29903813eJake Slack                            first = Long.parseLong(t.substring(0,d).trim());
12403928aee4356845252ac6b662d5c72c29903813eJake Slack                            last = Long.parseLong(t.substring(d + 1).trim());
12503928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
12603928aee4356845252ac6b662d5c72c29903813eJake Slack                        else
12703928aee4356845252ac6b662d5c72c29903813eJake Slack                            first = Long.parseLong(t.substring(0,d).trim());
12803928aee4356845252ac6b662d5c72c29903813eJake Slack
12903928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (first == -1 && last == -1)
13003928aee4356845252ac6b662d5c72c29903813eJake Slack                            continue headers;
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (first != -1 && last != -1 && (first > last))
13303928aee4356845252ac6b662d5c72c29903813eJake Slack                            continue headers;
13403928aee4356845252ac6b662d5c72c29903813eJake Slack
13503928aee4356845252ac6b662d5c72c29903813eJake Slack                        if (first < size)
13603928aee4356845252ac6b662d5c72c29903813eJake Slack                        {
13703928aee4356845252ac6b662d5c72c29903813eJake Slack                            InclusiveByteRange range = new InclusiveByteRange(first,last);
13803928aee4356845252ac6b662d5c72c29903813eJake Slack                            satRanges = LazyList.add(satRanges,range);
13903928aee4356845252ac6b662d5c72c29903813eJake Slack                        }
14003928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
14103928aee4356845252ac6b662d5c72c29903813eJake Slack                    catch (NumberFormatException e)
14203928aee4356845252ac6b662d5c72c29903813eJake Slack                    {
14303928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.warn("Bad range format: {}",t);
14403928aee4356845252ac6b662d5c72c29903813eJake Slack                        LOG.ignore(e);
14503928aee4356845252ac6b662d5c72c29903813eJake Slack                        continue;
14603928aee4356845252ac6b662d5c72c29903813eJake Slack                    }
14703928aee4356845252ac6b662d5c72c29903813eJake Slack                }
14803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
14903928aee4356845252ac6b662d5c72c29903813eJake Slack            catch(Exception e)
15003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
15103928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("Bad range format: {}",t);
15203928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.ignore(e);
15303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
15403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        return LazyList.getList(satRanges,true);
15603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
15703928aee4356845252ac6b662d5c72c29903813eJake Slack
15803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15903928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getFirst(long size)
16003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
16103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (first<0)
16203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
16303928aee4356845252ac6b662d5c72c29903813eJake Slack            long tf=size-last;
16403928aee4356845252ac6b662d5c72c29903813eJake Slack            if (tf<0)
16503928aee4356845252ac6b662d5c72c29903813eJake Slack                tf=0;
16603928aee4356845252ac6b662d5c72c29903813eJake Slack            return tf;
16703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
16803928aee4356845252ac6b662d5c72c29903813eJake Slack        return first;
16903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17003928aee4356845252ac6b662d5c72c29903813eJake Slack
17103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getLast(long size)
17303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (first<0)
17503928aee4356845252ac6b662d5c72c29903813eJake Slack            return size-1;
17603928aee4356845252ac6b662d5c72c29903813eJake Slack
17703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (last<0 ||last>=size)
17803928aee4356845252ac6b662d5c72c29903813eJake Slack            return size-1;
17903928aee4356845252ac6b662d5c72c29903813eJake Slack        return last;
18003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18103928aee4356845252ac6b662d5c72c29903813eJake Slack
18203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    public long getSize(long size)
18403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18503928aee4356845252ac6b662d5c72c29903813eJake Slack        return getLast(size)-getFirst(size)+1;
18603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18703928aee4356845252ac6b662d5c72c29903813eJake Slack
18803928aee4356845252ac6b662d5c72c29903813eJake Slack
18903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19003928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toHeaderRangeString(long size)
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19203928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder sb = new StringBuilder(40);
19303928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append("bytes ");
19403928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(getFirst(size));
19503928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append('-');
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(getLast(size));
19703928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append("/");
19803928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(size);
19903928aee4356845252ac6b662d5c72c29903813eJake Slack        return sb.toString();
20003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
20103928aee4356845252ac6b662d5c72c29903813eJake Slack
20203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20303928aee4356845252ac6b662d5c72c29903813eJake Slack    public static String to416HeaderRangeString(long size)
20403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder sb = new StringBuilder(40);
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append("bytes */");
20703928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(size);
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        return sb.toString();
20903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21003928aee4356845252ac6b662d5c72c29903813eJake Slack
21103928aee4356845252ac6b662d5c72c29903813eJake Slack
21203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21303928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
21403928aee4356845252ac6b662d5c72c29903813eJake Slack    public String toString()
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
21603928aee4356845252ac6b662d5c72c29903813eJake Slack        StringBuilder sb = new StringBuilder(60);
21703928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(Long.toString(first));
21803928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(":");
21903928aee4356845252ac6b662d5c72c29903813eJake Slack        sb.append(Long.toString(last));
22003928aee4356845252ac6b662d5c72c29903813eJake Slack        return sb.toString();
22103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
22203928aee4356845252ac6b662d5c72c29903813eJake Slack
22303928aee4356845252ac6b662d5c72c29903813eJake Slack
22403928aee4356845252ac6b662d5c72c29903813eJake Slack}
22503928aee4356845252ac6b662d5c72c29903813eJake Slack
22603928aee4356845252ac6b662d5c72c29903813eJake Slack
22703928aee4356845252ac6b662d5c72c29903813eJake Slack
228