UserAgentProfile

An attempt to extract the useful information from user-agent headers (like cellphones type) or browser or device OS where other information are not present. Recently, I came across something like there's a specification for user-agent headers. When I started this code, I expected the same but every header even those of the same manufacturer didn't seem to follow any particular standard hence the many 'ifs' statements in the code. Hope you find it useful...

######################################################################################
# description: UAProf profiler. An attempt to extract the useful information from
#              user-agents headers(like cellphones type, browser or device OS) where other
#              information are not present.
#
#       usage: UserAgentProfiler {Nokia6600/1.0 (4.03.24) SymbianOS/6.1 Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0}
#              The user-agents contains funny characters so put the string in "{}"
#
######################################################################################
proc UserAgentProfiler {devProfile} {
    set uAgentStr {}
    set userAgent0 [lindex [split $devProfile " "] 0]
    set userAgent1 [lindex [split $devProfile " "] 1]
    set userAgent2 [lindex [split $devProfile " "] 2]
    set userAgent3 [lindex [split $devProfile " "] 3]
    set userAgent4 [lindex [split $devProfile " "] 4]
    set userAgent5 [lindex [split $devProfile " "] 5]
    set userAgent6 [lindex [split $devProfile " "] 6]

    # since there is no consistency amongst device user-agent definition,
    # attempt to determine the correct user-agent based on the OS/browser version
    if { [string match Mozilla/* $userAgent0] } {
        set brwVersion [lindex [split $userAgent0 /] 1]
        switch -glob $brwVersion {
            5.* {
                if {$userAgent1 == {(Linux;}} {
                    # this is a gt-i9000 user agent profile
                    set userAgent $userAgent6 ; set uAgentStr $userAgent6
                } elseif {$userAgent1 == {(SAMSUNG;}} {
                    # SAMSUNG-GT-S8500 user agent profile
                    set userAgent $userAgent2 ; set uAgentStr $userAgent2
                } elseif {$userAgent1 == {(Vodafone-W1/V02c_19Jan2011_ZA;}} {
                    set userAgent {Vodafone-W1} ; set uAgentStr {Vodafone-W1}
                } elseif {$userAgent1 == {BlackBerry;}} {
                    # this is a blackberry user agent profile
                    set userAgent $userAgent3 ; set uAgentStr $userAgent3
                } elseif {$userAgent1 == {Macintosh;}} {
                    # this is an Apple iPhone (Intel Mac OS X 10_5_7 AppleWebKit/530.17)
                    set userAgent {iPhone} ; set uAgentStr $userAgent
                } elseif {$userAgent1 == {}} {
                    # this is an xxxxx user agent profile
                    set userAgent $userAgent4 ; set uAgentStr $userAgent4
                } elseif {$userAgent1 == {3gpp-gba}} {
                    # this is a 3gpp-gba user agent profile
                    set uAgentStr $userAgent1
                } else {
                    # the user-agent could not be determined by browser_version.
                    # determine the user-agent based on the operating system / firmware version
                    set osVersion [lindex [split $userAgent1 /] 1]

                    if { $osVersion == {3;}} {
                        set userAgent $userAgent3 ; set uAgentStr $userAgent3
                    } elseif { $osVersion == {9.1;}} {set userAgent {iPhone} ; set uAgentStr {iPhone}
                    } elseif { $osVersion == {9.2;}} {set userAgent $userAgent4 ; set uAgentStr $userAgent4
                    } elseif {$osVersion == {9.3;}} {
                        # NokiaE-Series user agent profile
                        if {$userAgent2 == {U;}} {
                            set userAgent $userAgent4 ; set uAgentStr $userAgent4
                        } else {
                            set userAgent $userAgent3 ; set uAgentStr $userAgent3
                        }
                    } elseif { $osVersion == {9.4;}} {
                        # Nokia5800d Series useragent profile
                        if {$userAgent2 == {U;}} {
                            set userAgent $userAgent4 ; set uAgentStr $userAgent4
                        } else {
                            set userAgent $userAgent3 ; set uAgentStr $userAgent3
                        }

                    } else { set userAgent $userAgent3 ; set uAgentStr $userAgent3 }
                }
        }
        5.0\(Linux* { set userAgent [lindex [split $userAgent0 \;] 4] }
        4.* {
            if {$userAgent1 == {(compatible;}} {
                if {$userAgent2 == {Nokia}} {
                    set userAgent $userAgent5 ; set uAgentStr $userAgent5
                } elseif { $userAgent5 == {CE;} } {
                    set uAgentStr $userAgent6
                } elseif { $userAgent5 == {CE)} } {
                    append uAgentStr $userAgent4 $userAgent5
                } elseif { $userAgent5 == {NT)} } {
                    append uAgentStr $userAgent4 $userAgent5
                } elseif { $userAgent5 == {OS)} } {
                    set uAgentStr $userAgent6
                } elseif { [string match $userAgent4 {Series80/2.0}] } {
                    set uAgentStr $userAgent5
                } elseif { $userAgent4 == {Symbian} } {
                    set uAgentStr $userAgent6
                } elseif { $userAgent3 == {4.01;} } {
                    set uAgentStr $userAgent6
                } elseif { [string match $userAgent4 {S60/3.0}] } {
                    set uAgentStr $userAgent5
                } elseif { $userAgent2 == {ELM;} } {
                    append uAgentStr $userAgent5 $userAgent6
                } elseif { $userAgent3 == {6.0;} || $userAgent3 == {7.0;} || $userAgent3 == {8.0;} } {
                        append uAgentStr $userAgent4 $userAgent5
                } else {
                        set userAgent [lindex [split $devProfile " "] 8] ; set uAgentStr $userAgent
                }
            } else {
                    set userAgent $userAgent1 ; set uAgentStr $userAgent1
            }
                }
        default { set uAgentStr {AppUAgent} }
            }

    } elseif {[string match {Setting} $userAgent0]} {
            set uAgentStr $userAgent1
    } elseif {[string match SonyEricssonW302* $userAgent0]} {
            set uAgentStr $userAgent1
    } else {
            set uAgentStr $userAgent0
    }

    # this are important lines of codes for debugging uaprofs and refining existing or add new ones.
    # the fields logged are unrecognized uaprof and can be used to define them within the code
    set debugFile "udef_uaprof.log"
    if { $uAgentStr == "" } { 
        set dbg [open $debugFile a]
    puts $dbg "[info script]::[clock format [clock seconds] -format {%d-%b-%Y %H:%M}] field0=$userAgent0 field1=$userAgent1 field2=$userAgent2 field3=$userAgent3 field4=$userAgent4 field5=$userAgent5 field6=$userAgent6"
        close $dbg
    }
    
    set retUserAgent [lindex [split $uAgentStr /] 0] 
    if { $retUserAgent == {} } { set retUserAgent {NOUAGENT} }
    unset userAgent0 userAgent1 userAgent2 userAgent3 userAgent4 userAgent5 userAgent6
    return $retUserAgent

} ;#endOf::UserAgentProfiler
% UserAgentProfiler {Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)}
WindowsNT
%
%
% UserAgentProfiler {Nokia6600/1.0 (4.03.24) SymbianOS/6.1 Series60/2.0 Profile/MIDP-2.0 Configuration/CLDC-1.0}
Nokia6600
%
%
% UserAgentProfiler {SonyEricssonK700i/R2AG SEMC-Browser/4.0.3 Profile/MIDP-2.0 Configuration/CLDC-1.1}
SonyEricssonK700i
%
% UserAgentProfiler {Mozilla/5.0 (SymbianOS/9.4; U; Series60/5.0 Nokia5230/10.0.071; Profile/MIDP-2.1 Configuration/CLDC-1.1 ) AppleWebKit/413 (KHTML, like Gecko) Safari/413}
Nokia5230
%
% UserAgentProfiler {OPWV-SDK/62 UP.Browser/6.2.2.1.208 (GUI) MMP/2.0}
OPWV-SDK
%