%% ``Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB. %% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings %% AB. All Rights Reserved.'' %% %% $Id: mod_browser.erl,v 1.1 2008/12/17 09:53:35 mikpe Exp $ %% %% ---------------------------------------------------------------------- %% %% Browsers sends a string to the webbserver %% to identify themsevles. They are a bit nasty %% since the only thing that the specification really %% is strict about is that they shall be short %% tree axamples: %% %% Netscape Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u) %% IE5 Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11) %% Lynx Lynx/2.8.3rel.1 libwww-FM/2.142 %% %% ---------------------------------------------------------------------- -module(mod_browser). %% Remember that the order of the mozilla browsers are %% important since some browsers include others to behave %% as they were something else -define(MOZILLA_BROWSERS,[{opera,"opera"},{msie,"msie"}]). %% If your operatingsystem is not recognized add it to this list. -define(OPERATIVE_SYSTEMS,[{win3x,["win16","windows 3","windows 16-bit"]}, {win95,["win95","windows 95"]}, {win98,["win98", "windows 98"]}, {winnt,["winnt", "windows nt"]}, {win2k,["nt 5"]}, {sunos4,["sunos 4"]}, {sunos5,["sunos 5"]}, {sun,["sunos"]}, {aix,["aix"]}, {linux,["linux"]}, {sco,["sco","unix_sv"]}, {freebsd,["freebsd"]}, {bsd,["bsd"]}]). -define(LYNX,lynx). -define(MOZILLA,mozilla). -define(EMACS,emacs). -define(STAROFFICE,soffice). -define(MOSAIC,mosaic). -define(NETSCAPE,netscape). -define(UNKOWN,unknown). -include("httpd.hrl"). -export([do/1, test/0, getBrowser/1]). do(Info) -> case httpd_util:key1search(Info#mod.data,status) of {Status_code,PhraseArgs,Reason} -> {proceed,Info#mod.data}; undefined -> {proceed,[{'user-agent',getBrowser1(Info)}|Info#mod.data]} end. getBrowser1(Info) -> PHead=Info#mod.parsed_header, case httpd_util:key1search(PHead,"User-Agent") of undefined-> undefined; AgentString -> getBrowser(AgentString) end. getBrowser(AgentString) -> LAgentString = httpd_util:to_lower(AgentString), case regexp:first_match(LAgentString,"^[^ ]*") of {match,Start,Length} -> Browser=lists:sublist(LAgentString,Start,Length), case browserType(Browser) of {mozilla,Vsn} -> {getMozilla(LAgentString, ?MOZILLA_BROWSERS,{?NETSCAPE,Vsn}), operativeSystem(LAgentString)}; AnyBrowser -> {AnyBrowser,operativeSystem(LAgentString)} end; nomatch -> browserType(LAgentString) end. browserType([$l,$y,$n,$x|Version]) -> {?LYNX,browserVersion(Version)}; browserType([$m,$o,$z,$i,$l,$l,$a|Version]) -> {?MOZILLA,browserVersion(Version)}; browserType([$e,$m,$a,$c,$s|Version]) -> {?EMACS,browserVersion(Version)}; browserType([$e,$t,$a,$r,$o,$f,$f,$i,$c,$e|Version]) -> {?STAROFFICE,browserVersion(Version)}; browserType([$m,$o,$s,$a,$i,$c|Version]) -> {?MOSAIC,browserVersion(Version)}; browserType(Unknown)-> unknown. browserVersion([$/|VsnString]) -> case catch list_to_float(VsnString) of Number when float(Number) -> Number; Whatever -> case string:span(VsnString,"1234567890.") of 0 -> unknown; VLength -> Vsn = string:substr(VsnString,1,VLength), case string:tokens(Vsn,".") of [Number] -> list_to_float(Number++".0"); [Major,Minor|_MinorMinor] -> list_to_float(Major++"."++Minor) end end end; browserVersion(VsnString) -> browserVersion([$/|VsnString]). operativeSystem(OpString) -> operativeSystem(OpString, ?OPERATIVE_SYSTEMS). operativeSystem(OpString,[]) -> unknown; operativeSystem(OpString,[{RetVal,RegExps}|Rest]) -> case controlOperativeSystem(OpString,RegExps) of true-> RetVal; _ -> operativeSystem(OpString,Rest) end. controlOperativeSystem(OpString,[]) -> false; controlOperativeSystem(OpString,[Regexp|Regexps]) -> case regexp:match(OpString,Regexp) of {match,_,_}-> true; nomatch-> controlOperativeSystem(OpString,Regexps) end. %% OK this is ugly but thats the only way since %% all browsers dont conform to the name/vsn standard %% First we check if it is one of the browsers that %% not are the default mozillaborwser against the regexp %% for the different browsers. if no match it a mozilla %% browser i.e opera netscape or internet explorer getMozilla(AgentString,[],Default) -> Default; getMozilla(AgentString,[{Agent,AgentRegExp}|Rest],Default) -> case regexp:match(AgentString,AgentRegExp) of {match,_,_} -> {Agent,getVersion(AgentString,AgentRegExp)}; nomatch -> getMozilla(AgentString,Rest,Default) end. getVersion(AgentString,AgentRegExp) -> case regexp:match(AgentString,AgentRegExp++"[0-9\.\ ]*") of {match,Start,Length} when length(AgentRegExp) < Length -> %% Ok we got the number split it out RealStart=Start+length(AgentRegExp), RealLength=Length-length(AgentRegExp), VsnString=string:substr(AgentString,RealStart,RealLength), case string:strip(VsnString,both,$\ ) of [] -> unknown; Vsn -> case string:tokens(Vsn,".") of [Number]-> list_to_float(Number++".0"); [Major,Minor|_MinorMinor]-> list_to_float(Major++"."++Minor) end end; nomatch -> unknown end. test()-> io:format("~n--------------------------------------------------------~n"), Res1=getBrowser("Mozilla/4.75 [en] (X11; U; SunOS 5.8 sun4u)"), io:format("~p",[Res1]), io:format("~n--------------------------------------------------------~n"), io:format("~n--------------------------------------------------------~n"), Res2=getBrowser("Mozilla/4.0 (compatible; MSIE 5.0; SP1B; SunOS 5.8 sun4u; X11)"), io:format("~p",[Res2]), io:format("~n--------------------------------------------------------~n"), io:format("~n--------------------------------------------------------~n"), Res3=getBrowser("Lynx/2.8.3rel.1 libwww-FM/2.142"), io:format("~p",[Res3]), io:format("~n--------------------------------------------------------~n").