Page 1 of 3

Setting Content_Type

Posted: Sat Aug 13, 2016 8:22 pm
by shortmort37
I've cobbled together some modification code described here, that permits phpBB to play mp4's without bbcode, and using the native capabilities of HTML5. Perhaps if I can further educate myself, I'll take a stab at writing an extension. But for now...

I continue to struggle with the presentation of mp4's natively under iOS. I've since determined (using Firebox's Inspector tool) that the Content_Type delivered by my code for mp4's is "application/octet-stream" - if I cobble together a simple web page for the same .mp4 video I uploaded to phpBB, Apache recognizes the extension and sets the Content_Type to "video/mp4". The latter presents just fine on my iPad and iPhone.

It seems most desktop browsers can detect the mime-type by examining the first few bytes of the data stream, and can present the video for display. However, this is non-standard; and in any event, doesn't work for iOS.

I don't know much about the Symfony framework, but it would seem that I want to set the Content_Type to "video/mp4" when I reference attachments that have been uploaded with this mimetype (and is indicated as such in the database). Can anyone point me to where I should be looking, or better yet, advise as to where I should set the header record for Content_Type?

Thanks
Dan

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 3:15 pm
by shortmort37
*bump*

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 4:31 pm
by shortmort37
Hmm... This snippet from Symfony's Response.php looks like it has a clue. It suggests that it is the client that tells the server, what the content type of the requested object should be ...

Code: Select all

            // Content-type based on the Request
            if (!$headers->has('Content-Type')) {
                $format = $request->getRequestFormat();
                if (null !== $format && $mimeType = $request->getMimeType($format)) {
                    $headers->set('Content-Type', $mimeType);
                }
            }

            // Fix Content-Type
            $charset = $this->charset ?: 'UTF-8';
            if (!$headers->has('Content-Type')) {
                $headers->set('Content-Type', 'text/html; charset='.$charset);
            } elseif (0 === stripos($headers->get('Content-Type'), 'text/') && false === stripos($headers->get('Content-Type'), 'charset')) {
                // add the charset
                $headers->set('Content-Type', $headers->get('Content-Type').'; charset='.$charset);
            }
Here's the snippet from my web page, that works for all browsers, even iOS. It requests a file with an mp4 filename extension:

Code: Select all

  	<video controls name="media" width="320" height="285">
            <source src="./3_5458180c7eddb48b876e9fe3e05fd825.mp4" type="video/mp4">
        </video>
...and here's the snippet that doesn't:

Code: Select all

 <!-- This works on Windows Chrome and Firefox, but not on iPod Safari -->
	<video controls name="media"width="320" height="285">
            <source src="http://www.59plymouth.net/59test/download/file.php?id=7461" type="video/mp4">
        </video>
It would appear that at the time the request is formed, the client browser does not determine from the "<source src...file.php?id=7461..." what the mimetype is of the object being requested, and hence does not specify the Content_Type.

So I'm guessing, the challenge would be server-side, to update $headers with a Content_Type record derived from the database, before the Response is composed. Now, how do I do that...

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 5:24 pm
by kasimi
How to modify response headers: viewtopic.php?p=14465356#p14465356

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 5:32 pm
by shortmort37
OMG, this is awesome!! Thank you so very much - will study, and report back with either success or more questions.

Thanks again!
Dan

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 6:19 pm
by shortmort37
OK, I see. But instead of 'Content-type' => 'application/xml', I will want to set the content type to 'audio/mp3', 'video/mp4', or whatever the appropriate mime type is for the object that is being requested. At the time core.page_header_after fires, is there a data structure containing the associated mime type, loaded from the database for the object being requested?

Thanks
Dan

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 6:50 pm
by kasimi
Sorry, I misunderstood your question. You're not making a request to a phpBB page and thus the core.page_header_after event isn't triggered.

Have a look at the function send_file_to_browser() in /includes/functions_download.php which sets the content type header for attachment downloads:

Code: Select all

// Correct the mime type - we force application/octetstream for all files, except images
// Please do not change this, it is a security precaution
if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0)
{
    $attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream';
}

// (a few lines later)

header('Content-Type: ' . $attachment['mimetype']); 
There's no event in that function so you'll have to request one to be added, or modify core code.

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 7:00 pm
by shortmort37
kasimi wrote:You're not making a request to a phpBB page and thus the core.page_header_after event isn't triggered.
I'm not? Here's a page that presents an mp4 for playback. I can request the mp4 object and play it on my Windows desktop, even though the Content-Type is "application/octet-stream" - because all my desktop browsers (IE11, Chrome, Firefox) examine the stream and recognize it as an mp4. But not iOS browsers (Safari, Chrome).

So, wouldn't that event fire when the mp4 on the page is requested?

Meanwhile, I'll take a look at functions_download.php.

Thanks
Dan

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 7:11 pm
by kasimi
shortmort37 wrote:So, wouldn't that event fire when the mp4 on the page is requested?
It wouldn't, as you're expecting the video file to be sent to the client when requesting /download/file.php?id=7461 and not HTML content. In file.php there's no call to page_header(), which would set up common template variables and trigger the core.page_header_after event, among other things.

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 7:14 pm
by shortmort37
Got it. You have been very helpful! I will experiment with functions_download.php and see where that takes me.

Thank you, very much.
Dan

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 8:35 pm
by shortmort37
In the modification I refer to at the beginning of this thread, I added ATTACHMENT_CATEGORY_HTML5 to constants.php as part of the change to enable native html5 browser capability to play audio/video. It looks like I ought to be able to add that category to functions_download.php, and thus not force an overwrite of the mimetype in the header response. But, I'm wondering what the vulnerability is that is referenced here in functions_download.php:

Code: Select all

// Correct the mime type - we force application/octetstream for all files, except images
// Please do not change this, it is a security precaution

Re: Setting Content_Type

Posted: Sun Aug 14, 2016 9:03 pm
by RMcGirr83
shortmort37 wrote:

Code: Select all

// Correct the mime type - we force application/octetstream for all files, except images
// Please do not change this, it is a security precaution
Because one could also alter to include HTTP headers from un-realiable sources (even inject into the page something that was not requested). You should be able to set your own headers from within your event if I understand symphony enough which may not be the case.

http://symfony.com/doc/current/introduc ... ntals.html

Re: Setting Content_Type

Posted: Mon Aug 22, 2016 1:57 am
by shortmort37
OK, I'm back. I've installed Fiddler 4 on my desktop, and I'm capturing headers using it as a proxy for my iPad.

After removing the constraint on mimetype in functions_download.php, I am now delivering Content-Type: video/mp4. However, It's still not presenting the video for play.

Here's the URL, and here are the headers in the response for the video:

Code: Select all

HTTP/1.1 200 OK
Date: Mon, 22 Aug 2016 01:07:08 GMT
Server: Apache
X-Powered-By: PHP/5.6.24
Cache-Control: public
Content-Disposition: attachment; filename=4.mp4
Last-Modified: Sat, 13 Aug 2016 18:49:44 GMT
Content-Length: 3079192
Keep-Alive: timeout=3, max=97
Connection: Keep-Alive
Content-Type: video/mp4
On an iPad, this is what I see.
IMG_0064.PNG
Here's a simple webpage with the same video, and here are the (multiple, partial) headers in the response:

Code: Select all

HTTP/1.1 206 Partial Content
Date: Mon, 22 Aug 2016 01:13:40 GMT
Server: Apache
Last-Modified: Sat, 13 Aug 2016 18:44:57 GMT
Accept-Ranges: bytes
Content-Length: 2
Content-Range: bytes 0-1/3079192
Keep-Alive: timeout=3, max=99
Connection: Keep-Alive
Content-Type: video/mp4

HTTP/1.1 206 Partial Content
Date: Mon, 22 Aug 2016 01:13:40 GMT
Server: Apache
Last-Modified: Sat, 13 Aug 2016 18:44:57 GMT
Accept-Ranges: bytes
Content-Length: 3079192
Content-Range: bytes 0-3079191/3079192
Keep-Alive: timeout=3, max=98
Connection: Keep-Alive
Content-Type: video/mp4

HTTP/1.1 206 Partial Content
Date: Mon, 22 Aug 2016 01:13:41 GMT
Server: Apache
Last-Modified: Sat, 13 Aug 2016 18:44:57 GMT
Accept-Ranges: bytes
Content-Length: 23576
Content-Range: bytes 3055616-3079191/3079192
Keep-Alive: timeout=3, max=100
Connection: Keep-Alive
Content-Type: video/mp4

HTTP/1.1 206 Partial Content
Date: Mon, 22 Aug 2016 01:13:41 GMT
Server: Apache
Last-Modified: Sat, 13 Aug 2016 18:44:57 GMT
Accept-Ranges: bytes
Content-Length: 7192
Content-Range: bytes 3072000-3079191/3079192
Keep-Alive: timeout=3, max=99
Connection: Keep-Alive
Content-Type: video/mp4

HTTP/1.1 206 Partial Content
Date: Mon, 22 Aug 2016 01:13:41 GMT
Server: Apache
Last-Modified: Sat, 13 Aug 2016 18:44:57 GMT
Accept-Ranges: bytes
Content-Length: 1904
Content-Range: bytes 3070096-3071999/3079192
Keep-Alive: timeout=3, max=98
Connection: Keep-Alive
Content-Type: video/mp4
And here's what I see on an iPad:

IMG_0063.PNG
The start button is enabled, and the video plays.

Where do I go from here?

Re: Setting Content_Type

Posted: Mon Aug 22, 2016 2:40 am
by 3Di
Both URLs display well on my win7/firefox. (Updated to the latest).

It could be some wrong setting on you Ipad's brower/OS.

Are you writing an extension and got a link to where to lurk at your extension' code as the whole one?

Re: Setting Content_Type

Posted: Mon Aug 22, 2016 3:26 am
by shortmort37
If you read the beginning of this thread, you will see that the problem is exclusively with iOS.

Windows browsers interpret the content from the first few bytes of the stream, even when the Content-Type is not specific about the mime type. Not so with iOS.

I fixed that - but the problem persists. Only with phpBB, though. The example in my simple web page plays fine.

I need help, diagnosing the difference between my two examples under iOS - one of which works, and one of which doesn't. Observations about browsers on Windows doesn't help me.