Non-dynamic custom HTTP headers - php

According to this Mozilla article on Ogg media, media works more seamlessly in the browser with an X-Content-Duration header, giving the length in seconds of the piece.
Assuming that I have that length stored somewhere (certainly in a database, perhaps also in the filename itself (video-file-name.XXX.ogv, where XXX is the time in seconds)), is there any way to form this extra header using only Apache .htaccess settings? I ask because loading the file into a PHP script seems clumsy, especially when PHP will by default add other headers which disable caching, and won't respond properly to range (partial content) requests. Yes, a lot of code could be written in PHP to support ETags and range requests, but it seems like overkill to do all that just to add one header, when Apache has all that functionality built in.

This is the domain of mod_cern_meta. It allows statically assigning extra HTTP headers to files.
You could use a cron job, and generate a *.meta file for every video.

I don't have examples, but you should be able to use mod_header to specify HTTP Response headers at the .htaccess level.
Of course, the question of where should I add the header really depends on how you are accessing it. If you are just hitting a static resource for download, adding it via Apache makes sense. However, you mention a DB. If you decide to store those files in a database, then you have some API providing the file, in which case that API implementation should append the header and not offload to apache.
Also, if the dynamic data you are wanting ever requires processing to determine (its not in the filename or etc) then you're already using some code engine to achieve it, just let that add the header.

This is the kind of thing you do with a mod_perl extension, to intercept these requests and add additional headers before allowing Apache to continue handling it.
One purely PHP approach which might work is to have the requests route through PHP using mod_rewrite, add the additional header, but then let Apache handle the rest by using the virtual function.
Alternatively, you could use your database of durations to contruct a static .htaccess file which uses mod_header to insert the correct duration header for each requested file.

Related

Is it possible to return a HTTP request to apache after php processing?

What I want to do is the following:
A User initates a HTTP GET request for a static file (for example an image or an mp3 file for HTML5 audio)
A PHP script intercepts these requests (for example via mod_rewrite) and checks the cookie for valid authentification
If successful, the file is delivered to the User, or the User gets a 401
Now, it would be perfect and most simple if the PHP script could "pass through" a successful request and return control to Apache, so that Apache can deliver the file as if it was the original request. Since we have also caching and the need to deliver audio files (including chunked requests) this would free the php script from manually creating the response headers etc.
Is this possible at all?
And if not, what would be the easiest, simplest solution to achieve this, so that caching and (chunked) requests for audio files still works as intended?
I think what you want is X-Sendfile.
Indeed, you can use mod_rewrite to let PHP deal with whatever-mime files, and then return an error or the wanted file via the X-Sendfile header (note that you’ll have to activate the eponymous module within apache).
Didn’t test it though. It seems to be a pretty important issue. OwnCloud, for example, still use PHP to serve files...

Count downloads without `echo file_get_contents($file)`?

I am now having download links on my server that directly points to files. I have a set of quite complicated rewrite rules but they don't affect what I am asking for.
What I want to do is to count the number of downloads. I know I could write a PHP script to echo the content and with a rewrite rule so that the PHP script will process all downloads.
However, there are a few points that I am worried about:
There is a chance that some dangerous paths (e.g. /etc/passwd, ../../index.php) will not be blocked due to carelessness or unnoticed bugs
Need to handle HTTP 404 Not Found response (and others) in the script which I prefer letting Apache handle them (I have an error handler script that rely on server redirect variables)
HTTP headers (like content type or modified time) may not be correctly set
Using a PHP script doesn't usually allow HTTP 304 Unmodified response so that browser caching will be useless, and re-download can consume extra bandwidth Actually I can check for that, but would require some more coding and debugging.
PHP script uses more processing power than directly loading the file directly by Apache
So, I would like to find some other ways to perform statistics. Can I, for example, make Apache trigger a script when certain files (in certain directories) are being requested and downloaded?
This may not be quite what you're looking for, but in the spirit of using the right tool for the job you could easily use Google Analytics (or probably any other analytics package) to track this. Take a look at https://support.google.com/analytics/bin/answer.py?hl=en-GB&answer=1136922.
Edit:
It would require the ability to modify the vhost setup for your site, but you could create a separate apache log file for your downloads. Let's say you've got a downloads folder to store the files that are available for download, you could add something like this to your vhost:
SetEnvIf Request_URI "^/downloads/.+$" download
LogFormat "%U" download-log
CustomLog download-tracking.log download-log env=download
Now, any time something is requested from the /downloads/ folder, it will be logged in the download-tracking.log file.
A few things to know:
You can have as many SentEnvIf lines as you need. As long as they all set the download environment variable, the request will be logged to the CustomLog
The LogFormat I've shown will log only the URI requested, but you can easily customize that to log much more than just the URI, see http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#logformat for more details.
If you're providing PDF files, be aware that some browsers/plugins will make a separate request for each page of the PDF so you would need to account for that when you read the logs.
The primary benefit of this method is that it does not require any coding, just a simple config change and you're ready to go. The downside, of course, is that you'd have to do some kind of log processing. It just depends what is most important to you.
Another option would be to use a PHP script and the readfile function. This makes it much easier to log requests to a database, but it does come with the other issues you mentioned earlier.
There are ways to pipe Apache logs to MySQL, but from what I've seen it can be tricky. Depending on what you're doing, it may be worth the effort... but then again it might not.
You can parse the Apache log files.
Apaches mod_lua probably is the most general, flexible and effective approach to hooking own code into the request processing inside apache. Usually you chose that language for the task that offers the most direct approach. And lua is much better in teracting with c/c++ than anything else.
However there certainly are other strategies, so be creative. Two things come to my mind immediately:
some creative use of PAM if you are under some sort of unix like system: configure some kind of dummy authentication requirement and setup PAM for processing. Inside the PAM configuration you can do whatever you like. The avantage: you get requests and can filter yourself what to count and what not. You have to make sure the PAM response does not create a valid session though, so that you really get a tick for each request done by a client, not only the first one.
there are other apache modules that allow to do request processing. Have a look at the forensic module or the external filter module. Both allow to hook external logic into request processing. You will need cli based php configured for that.

forcing browser to cache images in php website

I've a php based website and would like browser to cache the images for 30 days .. i am using a shared hosting solution where I do not have access to apache config to enable mod-headers or other modules and so can not use htaccess mechanisms for this.
my site is a regular php app, and has both html contents and images. I would like browser to cache images only. I've seen php's "header" function, but couldn't find a way to force only image cache .. How do i go about it ?
Thanks
As far as I know, if you can't get access to Apache to set the headers, your only other option is to serve images from a PHP script so you can use the PHP Header methods to set the headers.
In this case, you'd need to write a PHP image handler, and replace all your image tags with calls to this handler (e.g. http://mysite.com/imagehandler.php?image=logo.png). You would then have you imagehandler.php script retrieve the image from the file system, set the mime type and cache control headers, and stream the image back to the client.
You could write your own, or if you google, you will find image handler PHP scripts. Either way, make sure you focus on security - don't allow the client to retrieve arbitrary files from your web server, because that would be a fairly major security hole....

How to create virtual directories in PHP?

I want to create an application in PHP implementing virtual directory feature.
Example: http://mydomain.com/user001 will display the contents of the url http://mydomain.com/index.php?user=user001. How can I do that?
Note:
I am using Apache server.
The traditional way to do it is mod_rewrite.
Please read this friendly article regarding rewrite.
Next, try to find a simple way in PHP to parse this variable $_SERVER['REQUEST_URI'].
After doing that, you have the name of the directory and you can get its data from the DB.
Intercept the HTTP request using the 'REQUEST_URI' element of $_SERVER. This returns (I believe) only the requested page, not the entire URI/URL - more info here. Once you've grabbed the page request, substitute the address of the actual file that's needed. For example, the user-friendly www.somewebsite.com/page01 becomes a request for the more clunky-sounding www.somewebsite.com?page01.php. This method won't create a virtual directory, as such, but should work okay. I have used a similar method on my own IT website, where each page is loaded via index.php, allowing that file to keep a log of visitors in real time (the site has Webalizer, which runs a day or so in arrears).
Rewriting the filename might work, although it's not to my personal taste. Using PHP to effect a URI/URL-swap would likely carry the benefit of reduced server demand, due to requiring less disk read/write time than filename rewrites.
I hope that helps.

How can I protect my site from being leeched?

I am using the header function of PHP
to send the file to the browser with some small code. Its work well
and I have it so that if any one requests it with a referer other than my site
it redirects to a page first.
Unfortunately it's not working with the internet download manager.
What I want to know is how the rabidshare and 4shared sites do this.
You could use sessions to make sure the download is being requested by a valid user.
Not all browsers / softwares that can see web pages will send a Referer to your server. Some sites will make a browser "fingerprint", usually hashed, which might be Referer, User-Agent and a couple of other headers strung together to make a uniquie identifier for that user and thus restrict access as you describe.
Of course, I may have completely missed the point of your post!
A typical design pattern is using a front controller to have a single entry point for all requests. By having a front controller, you can control exactly what the client sees.
You can configure this in Apache so that all requests go through a single file (it's been a while since I've done this because I now concentrate on Java). I think you would need to look at pathinfo documentation for Apache.
This might require a significant change in the rest of your application code. But, the code will be more secure and maintainable in the long run.
I've served images and other binary files through this pattern. This allowed me to easily verify users were authenticated before actually sending them the file. Obfuscation is not security, so if you rely on obfuscating your URL, an attacker may be delayed in getting in, but it is just a matter of time.
Walter
The problem probably is that sending file through php script (with headers you mentioned) doesn't support starting file download at certain position. Download managers use this feature to download file using several simultaneous threads (assuming server gives one thread at certain speed).
For small project I would recommend making a copy of file with unique filename just for download time and redirecting user to this copied file. This way he gets full server download features and it also doesn't load processor as php does. Disadvantages - more disk space required and need to cleanup download directory.

Categories