Mobile browser detection with .htaccess fails with Opera Mini - .htaccess

I'm having trouble figuring this one out. I'm trying to direct mobile traffic to the mobile version of a website via HTACCESS User-Agent sniffing, like so:
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|ipad|iphone|ipod|iemobile|mini|mobi|palmos|webos|googlebot\-mobile) [NC]
RewriteCond %{HTTP_HOST} ^mobile\.mywebsite\.com$
RewriteRule ^([aA0-zZ9\-\/]*)/([^/]*)$ /index.php?page=$1&q=$2&q2=$3&setview=mobile [L,QSA]
The string mini|mobi is where the Opera Mini browser should be detected. However, this does NOT happen. I've also changed that string to opera m and other variations. Still no luck.
This rewrite condition appears to work with other mobile browsers, but not Opera, and I don't understand why. Even the second condition, which checks for an explicit pointer to the mobile. subdomain also fails to deliver the mobile content.
I'm not an HTACCESS guru, so my first guess is that my syntax is wrong. But why does this work on other mobile browsers and not Opera Mini?
Thanks for looking!
UPDATE: 2012-06-08
I actually resorted to a different method by using PHP to check headers. For some reason my HTACCESS file did not detect certain header information. Even though karlcow's answer would validate, I was having trouble getting the iPhone and third-party Android browsers to validate. It wasn't until a page was passed to the PHP interpreter that I was able to read the information. I guess I just don't understand how that works.
Anyway, I borrowed code from an Internet search that I placed into a library function:
function get_device_view() {
$view='desktop';
if(preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|android)/i', strtolower($_SERVER['HTTP_USER_AGENT'])))
$view='mobile';
if((strpos(strtolower($_SERVER['HTTP_ACCEPT']),'application/vnd.wap.xhtml+xml')>0) || ((isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE']))))
$view='mobile';
$mobile_ua=strtolower(substr($_SERVER['HTTP_USER_AGENT'],0,4));
$mobile_agents=array(
'w3c ','acs-','alav','alca','amoi','audi','avan','benq','bird','blac',
'blaz','brew','cell','cldc','cmd-','dang','doco','eric','hipt','inno',
'ipaq','java','jigs','kddi','keji','leno','lg-c','lg-d','lg-g','lge-',
'maui','maxo','midp','mits','mmef','mobi','mot-','moto','mwbp','nec-',
'newt','noki','oper','palm','pana','pant','phil','play','port','prox',
'qwap','sage','sams','sany','sch-','sec-','send','seri','sgh-','shar',
'sie-','siem','smal','smar','sony','sph-','symb','t-mo','teli','tim-',
'tosh','tsm-','upg1','upsi','vk-v','voda','wap-','wapa','wapi','wapp',
'wapr','webc','winw','winw','xda ','xda-');
if(in_array($mobile_ua,$mobile_agents))
$view='mobile';
if (strpos(strtolower($_SERVER['ALL_HTTP']),'OperaMini')>0)
$view='mobile';
if(strpos(strtolower($_SERVER['HTTP_USER_AGENT']),'windows')>0)
$view='desktop';
return $view;
}
This function is called as part of a strapper process for the website so that before anything is output, the $view is returned so that appropriate pages and stylesheets are loaded.
Additionally, I modified my HTACCESS file to contain the following:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{HTTP_COOKIE} !((^|;\s*)DD_VIEW=([^;]+))
RewriteCond %{HTTP_HOST} mobile\.buffalosbigdeal\.com
RewriteRule ^([aA0-zZ9\-\/]*)/*([^/]*)$ /index.php?page=$1&q=$2&q2=$3&setview=mobile [L,QSA]
As you can see I'm only redirecting explicit calls for the mobile. subdomain, and those not containing a cookie which retains the $view set during the strapper process.
My original intent was to perform browser detection exclusively using HTACCESS; because of simplicity and under premise of mod_rewrite's power. But in my frustration, and to meet the deadline, I compromised by settling for a more chunky method that may require more maintenance in the future.
Lesson learned: Build responsive websites based on browser capabilities (ie: resolution, touch, and DOM level), and do not rely heavily on user-agent strings. Have we yet a solution like this?
Thanks for looking.

Note that the pattern of Opera Mini string is
Opera/9.80 (J2ME/MIDP; Opera Mini/$CLIENT_VERSION/$SERVER_VERSION; U; $LANGUAGE) Presto/$PRESTO_VERSION
Mini is with an uppercase M. Hmm but you put NC which is for nocase, so that's not it.
Just to be sure could you try
RewriteCond %{HTTP_USER_AGENT} (android|blackberry|ipad|iphone|ipod|iemobile|mobi|palmos|webos|googlebot\-mobile) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Opera\ Mini

Should it be
if (strpos(strtolower($_SERVER['HTTP_USER_AGENT']),'operamini')>0)
or should it be
if (strpos(strtolower($_SERVER['ALL_HTTP']),'operamini')>0)
I get a debug error using ALL_HTTP, but the error goes away when I use HTTP_USER_AGENT
Here is the debug error, as follows:
Debug Notice: Undefined index: ALL_HTTP in header.php on line 29

Related

Why htaccess not working for mobile browser?

I have website (mzadkm.com) try to RewriteRule short url to app.php page .
So if user browse "mzadkm.com/app" will show "mzadkm.com/app.php" page
RewriteRule ^/app /app.php [L,R=301]
It's work on Computer , but on mobile browser give me 404 page
Any ideas
That probably is what you are looking for:
RewriteRule ^/?app /app.php [L]
The documentation clearly says, that the pattern in a RewriteRule get's applied to the relative path of the request if the rule is implemented inside a distributed configuration file. That means you actually want to match the path app and not /app here. Which is why your rule did not get applied. The ^/?app is a variant to accept both path notations, relative and absolut, which means the same rule can get implemented in the central configuration or likewise in a distributed configuration file (".htaccess").
I took the liberty to also remove the external redirection you showed ("R=301") since that most likely is not what you want, according to the phrasing of your question. Instead you want an internal rewrite .
You need to take care however that you do not implement a rewriting loop. Which would result in failing requests and an "internal server error" (http status 500).
One approach would be that:
RewriteEngine on
RewriteRule ^/?app$ /app.php [L]
Here another one:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?app /app.php [L]
Why things looked fine on your computer, but not on a mobile browser is unclear. Since the same rules get applied and the requests look the same there has to be another reason for that. I suspect you looked at a cached result of a previous attempt somewhere. Remember to always use a fresh anonymous browser window when testing. And to check the response you receive back inside your browsers network console.

Restrict single page to user agent?

How to restrict/block users with Firefox and Chrome user-agent who tring to accessing to this page:
http://example.com/test/mypage.php
http://example.com/test/mypage2.php
Or block entire pages in folder "test" from accessing only for Firefox and Chrome user-agent .
All another users-agents can be access to this pages regulary.
I want to do with .htaccess.
Is this possible and how to do that? Thanks
You can use the server variable %{HTTP_USER_AGENT}:
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} ^.*(Firefox|Chrome).*$ [NC]
RewriteRule ^test - [F]
N.B. Note that User Agent strings are notoriously unreliable indicators of the actual user agent. If, for example, an Opera browser is broadcasting a User Agent string containing the word Chrome, then that Opera browser will also be blocked by the RewriteCond above.

Server responds with a 403 error after browser update

I have a site that plays music. The user can listen to a song only by navigating to a specific site on the server that retrieves the music file and presents it to the user through the audio html tag. In order to prevent the users from accessing directly the song's address I implemented a year ago the following htaccess script:
Header set Access-Control-Allow-Origin "http://myexamplesite.000webhostapp.com/"
ErrorDocument 403 /error404.php
ErrorDocument 404 /error404.php
Options -Indexes
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://(myexamplesite\.)?000webhostapp [NC]
RewriteCond %{HTTP_REFERER} !^http://(myexamplesite\.)?000webhostapp.*$ [NC]
RewriteRule \.(mp3|png|jpg)$ - [F]
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www.)?(myexamplesite.000webhostapp.com)(/)?.*$ [NC]
RewriteRule .*.(.zip|.rar|.exe|.mp3|.pdf|.swf|.psd)$ http://myexamplesite.000webhostapp.com/error404.php [R,NC]
This script has been working flawlessly until a week ago, when chrome and mozilla updated and since then I see the error below on the chrome developer tools.
The browser cannot load any media such as images, documents and music files as described in the script above.
When I remove the script the problem is resolved but by doing so lets the users access and hotlink my resources with great ease.
The most confusing part is that mobile browsers have not any problem while desktop ones show errors. For example the updated chrome and firefox mobile browsers can access the site normally with all those resources without the issues dealt on desktop browsers.
I have tested if the problem appears in various computers and it still appears.
I believe that the problem shows up in newly updated browsers because the problem does not show up on elder versions of mozilla firefox desktop browser (version 47).
What causes this problem? How can I deal with it? I need a solution that does not override the main purpose of the htaccess script; to not allow direct access and hotlinking to sensitive media (images, pdf documents and mp3 files).

Can't get my Zend Framework 2 project working on hosting server

Currently I am developing a webshop in PHP. For this I use the Zend Framework 2.
All of my routes exist of a locale i.e. "nl_NL" or "en_EN", followed by a controller and an action www.mydomain.com/nl_NL/profile/login. Look here for an example of a route used in my project. This one belongs to the Profile Module: http://pastebin.com/jmim47w8.
If the visitor has no account, and no Cookie is set, the locale variable will first be set to the variable retrieved from the following function:
locale_accept_from_http($_SERVER['HTTP_ACCEPT_LANGUAGE'])
If a cookie is set that value will be used.
On the other hand, if a user does have an account and is logged in, the variable used will be retrieved from the user's profile.
My entire script does work on a localhost. However, on the server it doesn't.
When loading the page nothing gets shown. I have checked the error logs and couldn't find anything. However, when i place /nl_NL/ or any other locale that meets the requirements of the "locale route" regex in the url manually, it does work.
My first thought was that the url_rewrite apache module was not installed or activated, but since other websites use this module as well, and they are on the same server this doesn't seem logical. Of course I did try to check wether it was enabled by running some scripts, but to no avail. Since our server is setup to not allow shell scripts to be ran, or to check wether apache modules are enabled using phpinfo() it's quite hard to make sure.
I have tried to verify that my .htaccess file is correct, but I'm pretty much a noob at .htaccess. This is my .htaccess:
RewriteEngine On
# The following rule tells Apache that if the requested filename
# exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
To see what my IndexController looks like look here: http://pastebin.com/AEgm3Jmk.
All in all, I would really like to know how to get a Zend FW 2 project to work on a hosting server while still using url rewrite or any other way that makes it possible to use locale variables.
If there is something missing from this post that is needed to help me further, I will be happy to post it.
I have solved the problem, everything is working fine right now.
I found the problem to be in my local.php config file. The problem was
an error within this file, so it was actually a write error ( corrupt file ).
#Alex thanks for the help though, appreciate it.

url rewriting slows down proxy a lot

i have a proxy script which writes very ugly long URL. the proxy script automaticaly rewrites all href links with long ugly URL,
mysite.com/proxy.php?url=somesite.com
mysite.com/proxy.php?url=somesite.com/somedir
mysite.com/proxy.php?url=somesite.com/somedir/somepage.php
to fix this i have done 2 things
edit the proxy script so that all
href links are rewritten as
mysite.com/somesite.com
added a rewrite rule in .htaccess so that short
URLs now rewrite...
mysite.com/somesite.com
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ proxy.php?url=$1 [L,QSA]
the problem is that, whenever i click a link on a proxy loaded page, it seems to take a lot longer than before i did all this cosmetic work. is something wrong with my rewrite rule ?
The test you've written does two file tests (if 'not-file' and 'not-dir') and if they are true, it will execute your RewriteRule. This test is done for every request. Even if the result would've otherwise only required a HTTP 304 (not modified) response or when the actual files are currently held in memory by Apache.
It's possible that this slows down your site significantly if it contains many (server/client cached) images or other resources. To prevent this, try to filter without the need to access your file system. Filter as much as possible by using a regular expression. The easiest way to do this is by changing the URI path part to something unique, for instance example.com/u=somesite.com or even example.com/p/somesite.com (p for proxy)).
Your tests will be much faster if all you need to do is a regular expression pattern match as opposed to two file-existence tests (example for example.com/p/somesite/etc/....):
RewriteCond %{REQUEST_URI} ^/p/
RewriteRule ....
Update: expanded a bit and added small example
PS: even if you do not want to change your current brief URI scheme, you can use this pattern temporarily to test whether it changes performance for the better.

Resources