Welcome Guest, Not a member yet? Register   Sign In
SERVER HTTP_RANGE being stripped by codeigniter, works in a straight PHP file.
#1

[eluser]deejuk[/eluser]
This has been bugging me for weeks, I have been debugging issues thinking it was encoding types and coding issues. Turns out its something to do with codeigniter.

This code works fine in a straight PHP file (on every device), when I put it in codeigniter it won't work on iphone but it will on other devices. Codeigniter must be doing something strange like not sending HTTP_RANGE but I cant figure it out. PLEASE HELP!!!!!

controllers/mycontroller.php

Code:
$filepath = "new.mp4";
        if (is_file($filepath)) {

                header("Content-type: $content_type");
                if (isset($_SERVER['HTTP_RANGE']))  { // do it for any device that supports byte-ranges not only iPhone

                        $fp = @fopen($filepath, 'rb');

                    $size   = filesize($filepath); // File size
                    $length = $size;           // Content length
                    $start  = 0;               // Start byte
                    $end    = $size - 1;       // End byte
                    header("Accept-Ranges: 0-$length");
                    if (isset($_SERVER['HTTP_RANGE'])) {

                            $c_start = $start;
                            $c_end   = $end;
                            // Extract the range string
                            list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2);
                            // Make sure the client hasn't sent us a multibyte range
                            if (strpos($range, ',') !== false) {

                                    header('HTTP/1.1 416 Requested Range Not Satisfiable');
                                    header("Content-Range: bytes $start-$end/$size");
                                    // (?) Echo some info to the client?
                                    exit;
                            }
                            if ($range == '-') {

                                    // The n-number of the last bytes is requested
                                    $c_start = $size - substr($range, 1);
                            }
                            else {

                                    $range  = explode('-', $range);
                                    $c_start = $range[0];
                                    $c_end   = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $size;
                            }
                            $c_end = ($c_end > $end) ? $end : $c_end;
                            // Validate the requested range and return an error if it's not correct.
                            if ($c_start > $c_end || $c_start > $size - 1 || $c_end >= $size) {

                                    header('HTTP/1.1 416 Requested Range Not Satisfiable');
                                    header("Content-Range: bytes $start-$end/$size");
                                    // (?) Echo some info to the client?
                                    exit;
                            }
                            $start  = $c_start;
                            $end    = $c_end;
                            $length = $end - $start + 1; // Calculate new content length
                            fseek($fp, $start);
                            header('HTTP/1.1 206 Partial Content');
                    }
                    // Notify the client the byte range we'll be outputting
                    header("Content-Range: bytes $start-$end/$size");
                    header("Content-Length: $length");

                    // Start buffered download
                    $buffer = 1024 * 8;
                    while(!feof($fp) && ($p = ftell($fp)) <= $end) {

                            if ($p + $buffer > $end) {

                                    // In case we're only outputtin a chunk, make sure we don't
                                    // read past the length
                                    $buffer = $end - $p + 1;
                            }
                            set_time_limit(0); // Reset time limit for big files
                            echo fread($fp, $buffer);
                            flush(); // Free up memory. Otherwise large files will trigger PHP's memory limit.
                    }

                    fclose($fp);

                 }
                else {
//Just display the video and let the device sort it out, this option works for desktops but generally not ios
                        header("Content-Length: ".filesize($filepath));
                        header("X-Sendfile: $filepath");
                        //readfile($filepath);
                }

        }

Hope somebody can work out what I am doing wrong, thanks in advanced!
#2

[eluser]deejuk[/eluser]
it seems to be something to do with partial content failing

Code:
[23/May/2014:18:11:28 +0100] "GET /handler/test HTTP/1.1" 206 603 "-" "AppleCoreMedia/1.0.0.11D167 (iPhone Simulator; U; CPU OS 7_1 like Mac OS X; en_us)"
- - [23/May/2014:18:11:28 +0100] "GET /handler/test HTTP/1.1" 206 101483 "-" "AppleCoreMedia/1.0.0.11D167 (iPhone Simulator; U; CPU OS 7_1 like Mac OS X; en_us)"
Not much to go on I know. but these re the requests which the iphone returned a playbutton with a cross through it, only happens through codeigniter.
#3

[eluser]InsiteFX[/eluser]
Read this:

Configuring mime types with htaccess

#4

[eluser]Tim Brownlaw[/eluser]
Code:
Codeigniter must be doing something strange like not sending HTTP_RANGE

Well time to play spot the difference to debug what's going on.
You need to see what's being produced!

If you say it works in vanilla php and not in CI, what are the differences?

What does a var_dump($_SERVER) indicate or var_dump($_SERVER['HTTP_RANGE']) between a plain php file and within CI...

Are you so sure that your code isn't the issue????
Are your Variables you are creating with list, being created with the correct values? Echo them to see.
Are the generated headers correct?

You can also get addons for Firefox to view http headers. There are a few of those about.

Also does $_SERVER['HTTP_RANGE'] mysteriously change in that file above? You are testing for it's existence twice?

If you know what the input should be - you can create that and pass that in. You know what the output should be... so is it?

Just do all the normal... "Does this bit do what It should?" checks throughout the code and you'll quickly find where it's going wrong!


#5

[eluser]deejuk[/eluser]
Hi ,

Thanks for your replies, the biggest hurdle has been debugging. I have tested with lots of firefox add-ons (and burp_ unfortunately the http headers are not very helpful all seems to be fine. The only time a request would be made for HTTP_RANGE is for when a device like (iphone) requests parts or bytes of a file. So this makes it extremely difficult to debug as a desktop environment does not behave in this way.

I dont see how adding mime type to htaccess would change anything, I have added it to codeigniter but like I said it works fine in a vanilla PHP file.

I have disabled everything in codeigniter and cannot see one bit of difference between the two, its hard debugging because it works fine on the straight download. But the only time a HTTP_RANGE request is made is if IOS detects the header mp4, and if this is set its impossible to echo information on the page.

So I am left at playing the guessing game. Apple do not offer any useful debugging tools.

I am open to more suggestions or debug methods I am unaware of.

Thanks

#6

[eluser]deejuk[/eluser]
So it turns out, HTTP_RANGE is empty on codeigniter version, but not on the vanilla php version.

Any idea what codeigniter is doing to prevent this or how can ensures its parsed?

I have a feeling it might be something to do with the security features built in, which could be stripping the content. I did try disabling global XSS, didn’t seem to make a difference

Thanks
[quote author="Tim Brownlaw" date="1400897731"]
Code:
Codeigniter must be doing something strange like not sending HTTP_RANGE

Well time to play spot the difference to debug what's going on.
You need to see what's being produced!

If you say it works in vanilla php and not in CI, what are the differences?

What does a var_dump($_SERVER) indicate or var_dump($_SERVER['HTTP_RANGE']) between a plain php file and within CI...

Are you so sure that your code isn't the issue????
Are your Variables you are creating with list, being created with the correct values? Echo them to see.
Are the generated headers correct?

You can also get addons for Firefox to view http headers. There are a few of those about.

Also does $_SERVER['HTTP_RANGE'] mysteriously change in that file above? You are testing for it's existence twice?

If you know what the input should be - you can create that and pass that in. You know what the output should be... so is it?

Just do all the normal... "Does this bit do what It should?" checks throughout the code and you'll quickly find where it's going wrong!


[/quote]
#7

[eluser]Tim Brownlaw[/eluser]
I just did a really quick "dig" through the CI 2.1.4 Code!

There is a file /application/user_agents.php that might be worth looking at.

I've not had time to look over this and just throwing it out there as something to look at!

Just to add...

$_SERVER[‘HTTP_RANGE’] is a "Server" thing... I dont think CI touches it at all as it uses $this->input->server() to perform any filtering...

So something else is going on.


Cheers
Tim
#8

[eluser]deejuk[/eluser]
Nothing in there which helps unfortunately.

The only other thing I can think of, is if CI is outputting some header I can't see.

I did some output tests in both files, headers, requests etc.. They were both identical the only difference was the range was empty on CI.

The odd thing is, if I remove or reverse the if command on HTTP_RANGE it works on iphone in CI, so the phone is defiantly sending the right requests for bytes and CI is allowing the correct return, just not the initial request.

#9

[eluser]Tim Brownlaw[/eluser]
Well that's why I asked why you were testing for http_range in two places... One within the other...

Might just be that your change is now giving you the correct code!
#10

[eluser]deejuk[/eluser]
The thing is it does not get past the first http_range check, your right I don’t need it in twice but this isn’t the issue. I cant use the functionality without this because it changes the output based on this.

I will try seeing if it gets to the root index.php of CI, that way I can tell if its defiantly CI stripping it. other than that, I have no idea how else I can debug this.

Thanks




Theme © iAndrew 2016 - Forum software by © MyBB