Diff -- /var/www/vhosts/3dshawn.com/crm.3dshawn.com/MODS/ContactForge/UAParser.pm
Diff
/var/www/vhosts/3dshawn.com/crm.3dshawn.com/MODS/ContactForge/UAParser.pm
added on local at 2026-07-01 15:02:58
Added
+0
lines
Removed
-0
lines
Context
51
unchanged
Blobs
from 1d2e031c60d3
to 1d2e031c60d3
to 1d2e031c60d3
Unified diff
Naive LCS-based line diff. Additions in emerald, deletions in rose. Both sides decompressed live from BLOB_STORE.| 1 | 1 | package MODS::ContactForge::UAParser; |
| 2 | 2 | #====================================================================== |
| 3 | 3 | # ContactForge -- minimal User-Agent string parser. No CPAN deps. |
| 4 | 4 | # Catches the top 95% of real-world UA strings into: |
| 5 | 5 | # { browser, browser_version, os, os_version, device } |
| 6 | 6 | #====================================================================== |
| 7 | 7 | use strict; |
| 8 | 8 | use warnings; |
| 9 | 9 | |
| 10 | 10 | sub new { bless {}, shift } |
| 11 | 11 | |
| 12 | 12 | sub parse { |
| 13 | 13 | my ($self, $ua) = @_; |
| 14 | 14 | $ua //= ''; |
| 15 | 15 | my $r = { browser => '', browser_version => '', os => '', os_version => '', device => 'desktop' }; |
| 16 | 16 | |
| 17 | 17 | # OS |
| 18 | 18 | if ($ua =~ /Windows NT 10/i) { $r->{os} = 'Windows'; $r->{os_version} = '10/11'; } |
| 19 | 19 | elsif ($ua =~ /Windows NT ([\d.]+)/i) { $r->{os} = 'Windows'; $r->{os_version} = $1; } |
| 20 | 20 | elsif ($ua =~ /Mac OS X ([\d_]+)/i) { $r->{os} = 'macOS'; ($r->{os_version} = $1) =~ tr/_/./; } |
| 21 | 21 | elsif ($ua =~ /iPhone OS ([\d_]+)/i) { $r->{os} = 'iOS'; ($r->{os_version} = $1) =~ tr/_/./; $r->{device} = 'mobile'; } |
| 22 | 22 | elsif ($ua =~ /iPad/i && $ua =~ /OS ([\d_]+)/) { $r->{os} = 'iOS'; ($r->{os_version} = $1) =~ tr/_/./; $r->{device} = 'tablet'; } |
| 23 | 23 | elsif ($ua =~ /Android ([\d.]+)/i) { $r->{os} = 'Android'; $r->{os_version} = $1; $r->{device} = ($ua =~ /Mobile/i) ? 'mobile' : 'tablet'; } |
| 24 | 24 | elsif ($ua =~ /CrOS/i) { $r->{os} = 'ChromeOS'; } |
| 25 | 25 | elsif ($ua =~ /Linux/i) { $r->{os} = 'Linux'; } |
| 26 | 26 | |
| 27 | 27 | # Browser (order matters: Edge before Chrome before Safari, OPR before Chrome) |
| 28 | 28 | if ($ua =~ /Edg(?:e|A|iOS)?\/([\d.]+)/i) { $r->{browser} = 'Edge'; $r->{browser_version} = $1; } |
| 29 | 29 | elsif ($ua =~ /OPR\/([\d.]+)/i) { $r->{browser} = 'Opera'; $r->{browser_version} = $1; } |
| 30 | 30 | elsif ($ua =~ /SamsungBrowser\/([\d.]+)/i) { $r->{browser} = 'Samsung'; $r->{browser_version} = $1; } |
| 31 | 31 | elsif ($ua =~ /YaBrowser\/([\d.]+)/i) { $r->{browser} = 'Yandex'; $r->{browser_version} = $1; } |
| 32 | 32 | elsif ($ua =~ /Firefox\/([\d.]+)/i) { $r->{browser} = 'Firefox'; $r->{browser_version} = $1; } |
| 33 | 33 | elsif ($ua =~ /CriOS\/([\d.]+)/i) { $r->{browser} = 'Chrome'; $r->{browser_version} = $1; } |
| 34 | 34 | elsif ($ua =~ /Chrome\/([\d.]+)/i) { $r->{browser} = 'Chrome'; $r->{browser_version} = $1; } |
| 35 | 35 | elsif ($ua =~ /Version\/([\d.]+).*Safari/i) { $r->{browser} = 'Safari'; $r->{browser_version} = $1; } |
| 36 | 36 | elsif ($ua =~ /Safari/i) { $r->{browser} = 'Safari'; } |
| 37 | 37 | elsif ($ua =~ /MSIE ([\d.]+)/i) { $r->{browser} = 'IE'; $r->{browser_version} = $1; } |
| 38 | 38 | elsif ($ua =~ /Trident.*rv:([\d.]+)/i) { $r->{browser} = 'IE'; $r->{browser_version} = $1; } |
| 39 | 39 | |
| 40 | 40 | # Device override |
| 41 | 41 | if ($ua =~ /bot|crawl|spider|google|bing|yahoo|baidu|duckduck|slurp|yandexbot|sogou|exabot|facebookexternalhit|monitor/i) { |
| 42 | 42 | $r->{device} = 'bot'; |
| 43 | 43 | } elsif ($r->{device} eq 'desktop') { |
| 44 | 44 | if ($ua =~ /iPad|Tablet/i) { $r->{device} = 'tablet'; } |
| 45 | 45 | elsif ($ua =~ /Mobi|iPhone|Android.*Mobile/i) { $r->{device} = 'mobile'; } |
| 46 | 46 | } |
| 47 | 47 | |
| 48 | 48 | return $r; |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | 1; |