001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.servlet;
016    
017    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
018    import com.liferay.portal.kernel.servlet.BrowserSniffer;
019    import com.liferay.portal.kernel.servlet.HttpHeaders;
020    import com.liferay.portal.kernel.util.CharPool;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.util.WebKeys;
026    
027    import javax.servlet.http.HttpServletRequest;
028    
029    /**
030     * See http://www.zytrax.com/tech/web/browser_ids.htm for examples.
031     *
032     * @author Eduardo Lundgren
033     * @author Nate Cavanaugh
034     */
035    @DoPrivileged
036    public class BrowserSnifferImpl implements BrowserSniffer {
037    
038            @Override
039            public boolean acceptsGzip(HttpServletRequest request) {
040                    String acceptEncoding = request.getHeader(HttpHeaders.ACCEPT_ENCODING);
041    
042                    if ((acceptEncoding != null) && acceptEncoding.contains("gzip")) {
043                            return true;
044                    }
045                    else {
046                            return false;
047                    }
048            }
049    
050            @Override
051            public String getBrowserId(HttpServletRequest request) {
052                    if (isIe(request)) {
053                            return BROWSER_ID_IE;
054                    }
055                    else if (isFirefox(request)) {
056                            return BROWSER_ID_FIREFOX;
057                    }
058                    else {
059                            return BROWSER_ID_OTHER;
060                    }
061            }
062    
063            @Override
064            public float getMajorVersion(HttpServletRequest request) {
065                    return GetterUtil.getFloat(getVersion(request));
066            }
067    
068            @Override
069            public String getRevision(HttpServletRequest request) {
070                    String revision = (String)request.getAttribute(
071                            WebKeys.BROWSER_SNIFFER_REVISION);
072    
073                    if (revision != null) {
074                            return revision;
075                    }
076    
077                    revision = parseVersion(
078                            getUserAgent(request), revisionLeadings, revisionSeparators);
079    
080                    request.setAttribute(WebKeys.BROWSER_SNIFFER_REVISION, revision);
081    
082                    return revision;
083            }
084    
085            @Override
086            public String getVersion(HttpServletRequest request) {
087                    String version = (String)request.getAttribute(
088                            WebKeys.BROWSER_SNIFFER_VERSION);
089    
090                    if (version != null) {
091                            return version;
092                    }
093    
094                    String userAgent = getUserAgent(request);
095    
096                    version = parseVersion(userAgent, versionLeadings, versionSeparators);
097    
098                    if (version.isEmpty()) {
099                            version = parseVersion(
100                                    userAgent, revisionLeadings, revisionSeparators);
101                    }
102    
103                    request.setAttribute(WebKeys.BROWSER_SNIFFER_VERSION, version);
104    
105                    return version;
106            }
107    
108            @Override
109            public boolean isAir(HttpServletRequest request) {
110                    String userAgent = getUserAgent(request);
111    
112                    if (userAgent.contains("adobeair")) {
113                            return true;
114                    }
115    
116                    return false;
117            }
118    
119            @Override
120            public boolean isAndroid(HttpServletRequest request) {
121                    String userAgent = getUserAgent(request);
122    
123                    if (userAgent.contains("android")) {
124                            return true;
125                    }
126    
127                    return false;
128            }
129    
130            @Override
131            public boolean isChrome(HttpServletRequest request) {
132                    String userAgent = getUserAgent(request);
133    
134                    if (userAgent.contains("chrome")) {
135                            return true;
136                    }
137    
138                    return false;
139            }
140    
141            @Override
142            public boolean isFirefox(HttpServletRequest request) {
143                    if (!isMozilla(request)) {
144                            return false;
145                    }
146    
147                    String userAgent = getUserAgent(request);
148    
149                    for (String firefoxAlias : _FIREFOX_ALIASES) {
150                            if (userAgent.contains(firefoxAlias)) {
151                                    return true;
152                            }
153                    }
154    
155                    return false;
156            }
157    
158            @Override
159            public boolean isGecko(HttpServletRequest request) {
160                    String userAgent = getUserAgent(request);
161    
162                    if (userAgent.contains("gecko")) {
163                            return true;
164                    }
165    
166                    return false;
167            }
168    
169            @Override
170            public boolean isIe(HttpServletRequest request) {
171                    return isIe(getUserAgent(request));
172            }
173    
174            @Override
175            public boolean isIeOnWin32(HttpServletRequest request) {
176                    String userAgent = getUserAgent(request);
177    
178                    if (isIe(userAgent) &&
179                            !(userAgent.contains("wow64") || userAgent.contains("win64"))) {
180    
181                            return true;
182                    }
183    
184                    return false;
185            }
186    
187            @Override
188            public boolean isIeOnWin64(HttpServletRequest request) {
189                    String userAgent = getUserAgent(request);
190    
191                    if (isIe(userAgent) &&
192                            (userAgent.contains("wow64") || userAgent.contains("win64"))) {
193    
194                            return true;
195                    }
196    
197                    return false;
198            }
199    
200            @Override
201            public boolean isIphone(HttpServletRequest request) {
202                    String userAgent = getUserAgent(request);
203    
204                    if (userAgent.contains("iphone")) {
205                            return true;
206                    }
207    
208                    return false;
209            }
210    
211            @Override
212            public boolean isLinux(HttpServletRequest request) {
213                    String userAgent = getUserAgent(request);
214    
215                    if (userAgent.contains("linux")) {
216                            return true;
217                    }
218    
219                    return false;
220            }
221    
222            @Override
223            public boolean isMac(HttpServletRequest request) {
224                    String userAgent = getUserAgent(request);
225    
226                    if (userAgent.contains("mac")) {
227                            return true;
228                    }
229    
230                    return false;
231            }
232    
233            @Override
234            public boolean isMobile(HttpServletRequest request) {
235                    String userAgent = getUserAgent(request);
236    
237                    if (userAgent.contains("mobile") ||
238                            (isAndroid(request) && userAgent.contains("nexus"))) {
239    
240                            return true;
241                    }
242    
243                    return false;
244            }
245    
246            @Override
247            public boolean isMozilla(HttpServletRequest request) {
248                    String userAgent = getUserAgent(request);
249    
250                    if (userAgent.contains("mozilla") &&
251                            !(userAgent.contains("compatible") ||
252                              userAgent.contains("webkit"))) {
253    
254                            return true;
255                    }
256    
257                    return false;
258            }
259    
260            @Override
261            public boolean isOpera(HttpServletRequest request) {
262                    String userAgent = getUserAgent(request);
263    
264                    if (userAgent.contains("opera")) {
265                            return true;
266                    }
267    
268                    return false;
269            }
270    
271            @Override
272            public boolean isRtf(HttpServletRequest request) {
273                    if (isAndroid(request)) {
274                            return true;
275                    }
276    
277                    if (isChrome(request)) {
278                            return true;
279                    }
280    
281                    float majorVersion = getMajorVersion(request);
282    
283                    if (isIe(request) && (majorVersion >= 5.5)) {
284                            return true;
285                    }
286    
287                    if (isMozilla(request) && (majorVersion >= 1.3)) {
288                            return true;
289                    }
290    
291                    if (isOpera(request)) {
292                            if (isMobile(request) && (majorVersion >= 10.0)) {
293                                    return true;
294                            }
295                            else if (!isMobile(request)) {
296                                    return true;
297                            }
298                    }
299    
300                    if (isSafari(request)) {
301                            if (isMobile(request) && (majorVersion >= 5.0)) {
302                                    return true;
303                            }
304                            else if (!isMobile(request) && (majorVersion >= 3.0)) {
305                                    return true;
306                            }
307                    }
308    
309                    return false;
310            }
311    
312            @Override
313            public boolean isSafari(HttpServletRequest request) {
314                    String userAgent = getUserAgent(request);
315    
316                    if (isWebKit(request) && userAgent.contains("safari")) {
317                            return true;
318                    }
319    
320                    return false;
321            }
322    
323            @Override
324            public boolean isSun(HttpServletRequest request) {
325                    String userAgent = getUserAgent(request);
326    
327                    if (userAgent.contains("sunos")) {
328                            return true;
329                    }
330    
331                    return false;
332            }
333    
334            @Override
335            public boolean isWebKit(HttpServletRequest request) {
336                    String userAgent = getUserAgent(request);
337    
338                    for (String webKitAlias : _WEBKIT_ALIASES) {
339                            if (userAgent.contains(webKitAlias)) {
340                                    return true;
341                            }
342                    }
343    
344                    return false;
345            }
346    
347            @Override
348            public boolean isWindows(HttpServletRequest request) {
349                    String userAgent = getUserAgent(request);
350    
351                    for (String windowsAlias : _WINDOWS_ALIASES) {
352                            if (userAgent.contains(windowsAlias)) {
353                                    return true;
354                            }
355                    }
356    
357                    return false;
358            }
359    
360            protected static String parseVersion(
361                    String userAgent, String[] leadings, char[] separators) {
362    
363                    leading:
364                    for (String leading : leadings) {
365                            int index = 0;
366    
367                            version:
368                            while (true) {
369                                    index = userAgent.indexOf(leading, index);
370    
371                                    if ((index < 0) ||
372                                            (((index += leading.length()) + 2) > userAgent.length())) {
373    
374                                            continue leading;
375                                    }
376    
377                                    char c1 = userAgent.charAt(index);
378                                    char c2 = userAgent.charAt(++index);
379    
380                                    if (((c2 >= '0') && (c2 <= '9')) || (c2 == '.')) {
381                                            for (char separator : separators) {
382                                                    if (c1 == separator) {
383                                                            break version;
384                                                    }
385                                            }
386                                    }
387                            }
388    
389                            // Major
390    
391                            int majorStart = index;
392                            int majorEnd = index + 1;
393    
394                            for (int i = majorStart; i < userAgent.length(); i++) {
395                                    char c = userAgent.charAt(i);
396    
397                                    if ((c < '0') || (c > '9')) {
398                                            majorEnd = i;
399    
400                                            break;
401                                    }
402                            }
403    
404                            String major = userAgent.substring(majorStart, majorEnd);
405    
406                            if (userAgent.charAt(majorEnd) != '.') {
407                                    return major;
408                            }
409    
410                            // Minor
411    
412                            int minorStart = majorEnd + 1;
413                            int minorEnd = userAgent.length();
414    
415                            for (int i = minorStart; i < userAgent.length(); i++) {
416                                    char c = userAgent.charAt(i);
417    
418                                    if ((c < '0') || (c > '9')) {
419                                            minorEnd = i;
420    
421                                            break;
422                                    }
423                            }
424    
425                            String minor = userAgent.substring(minorStart, minorEnd);
426    
427                            return major.concat(StringPool.PERIOD).concat(minor);
428                    }
429    
430                    return StringPool.BLANK;
431            }
432    
433            protected String getAccept(HttpServletRequest request) {
434                    String accept = StringPool.BLANK;
435    
436                    if (request == null) {
437                            return accept;
438                    }
439    
440                    accept = String.valueOf(request.getAttribute(HttpHeaders.ACCEPT));
441    
442                    if (Validator.isNotNull(accept)) {
443                            return accept;
444                    }
445    
446                    accept = request.getHeader(HttpHeaders.ACCEPT);
447    
448                    if (accept != null) {
449                            accept = StringUtil.toLowerCase(accept);
450                    }
451                    else {
452                            accept = StringPool.BLANK;
453                    }
454    
455                    request.setAttribute(HttpHeaders.ACCEPT, accept);
456    
457                    return accept;
458            }
459    
460            protected String getUserAgent(HttpServletRequest request) {
461                    String userAgent = StringPool.BLANK;
462    
463                    if (request == null) {
464                            return userAgent;
465                    }
466    
467                    userAgent = String.valueOf(
468                            request.getAttribute(HttpHeaders.USER_AGENT));
469    
470                    if (Validator.isNotNull(userAgent)) {
471                            return userAgent;
472                    }
473    
474                    userAgent = request.getHeader(HttpHeaders.USER_AGENT);
475    
476                    if (userAgent != null) {
477                            userAgent = StringUtil.toLowerCase(userAgent);
478                    }
479                    else {
480                            userAgent = StringPool.BLANK;
481                    }
482    
483                    request.setAttribute(HttpHeaders.USER_AGENT, userAgent);
484    
485                    return userAgent;
486            }
487    
488            protected boolean isIe(String userAgent) {
489                    if ((userAgent.contains("msie") || userAgent.contains("trident")) &&
490                            !userAgent.contains("opera")) {
491    
492                            return true;
493                    }
494    
495                    return false;
496            }
497    
498            protected static String[] revisionLeadings = {"rv", "it", "ra", "ie"};
499            protected static char[] revisionSeparators =
500                    {CharPool.BACK_SLASH, CharPool.COLON, CharPool.SLASH, CharPool.SPACE};
501            protected static String[] versionLeadings =
502                    {"version", "firefox", "minefield", "chrome"};
503            protected static char[] versionSeparators =
504                    {CharPool.BACK_SLASH, CharPool.SLASH};
505    
506            private static final String[] _FIREFOX_ALIASES = {
507                    "firefox", "minefield", "granparadiso", "bonecho", "firebird",
508                    "phoenix", "camino"
509            };
510    
511            private static final String[] _WEBKIT_ALIASES = {"khtml", "applewebkit"};
512    
513            private static final String[] _WINDOWS_ALIASES = {
514                    "windows", "win32", "16bit"
515            };
516    
517    }