001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (https://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software GmbH & Co. KG, please see the
018 * company website: https://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: https://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.ui.login;
029
030import org.opencms.crypto.CmsEncryptionException;
031import org.opencms.db.CmsUserSettings;
032import org.opencms.file.CmsObject;
033import org.opencms.file.CmsProject;
034import org.opencms.file.CmsResource;
035import org.opencms.file.CmsResourceFilter;
036import org.opencms.i18n.CmsAcceptLanguageHeaderParser;
037import org.opencms.i18n.CmsMessageContainer;
038import org.opencms.jsp.CmsJspLoginBean;
039import org.opencms.main.CmsException;
040import org.opencms.main.CmsLog;
041import org.opencms.main.OpenCms;
042import org.opencms.security.CmsDefaultAuthorizationHandler;
043import org.opencms.security.CmsOrganizationalUnit;
044import org.opencms.security.CmsRole;
045import org.opencms.ui.apps.CmsAppHierarchyConfiguration;
046import org.opencms.ui.apps.CmsFileExplorerConfiguration;
047import org.opencms.ui.apps.CmsPageEditorConfiguration;
048import org.opencms.util.CmsRequestUtil;
049import org.opencms.util.CmsStringUtil;
050import org.opencms.workplace.CmsWorkplace;
051import org.opencms.workplace.CmsWorkplaceLoginHandler;
052import org.opencms.workplace.CmsWorkplaceManager;
053import org.opencms.workplace.CmsWorkplaceSettings;
054import org.opencms.workplace.Messages;
055
056import java.io.Serializable;
057import java.util.ArrayList;
058import java.util.Calendar;
059import java.util.GregorianCalendar;
060import java.util.Iterator;
061import java.util.List;
062import java.util.Locale;
063
064import javax.servlet.http.Cookie;
065import javax.servlet.http.HttpServletRequest;
066import javax.servlet.http.HttpServletResponse;
067
068import org.apache.commons.logging.Log;
069
070/**
071 * Utility to login users to the OpenCms workplace.<p>
072 */
073public class CmsLoginHelper extends CmsJspLoginBean {
074
075    /**
076     * Holds the current login parameters.<p>
077     */
078    public static class LoginParameters implements Serializable {
079
080        /** The serial version id. */
081        private static final long serialVersionUID = -2636377967076796207L;
082
083        /** The authorization token. */
084        private String m_authToken;
085
086        /** The locale to use for display, this will not be the workplace locale, but the browser locale. */
087        private Locale m_locale;
088
089        /** The logout flag. */
090        private boolean m_logout;
091
092        /** The value of the organizational unit parameter. */
093        private String m_oufqn;
094
095        /** The value of the PC type parameter. */
096        private String m_pcType;
097
098        /** The redirect URL after a successful login. */
099        private String m_requestedResource;
100
101        /** The value of the user name parameter. */
102        private String m_username;
103
104        /** Reset password flag. */
105        private boolean m_reset;
106
107        /** Indicates that user was automatically logged out. */
108        private boolean m_autoLogout;
109
110        /**
111         * Constructor.<p>
112         *
113         * @param username the user name
114         * @param pcType the pc type
115         * @param oufqn the ou fqn
116         * @param requestedResource the requested resource
117         * @param locale the locale
118         * @param authToken the authorization token
119         * @param logout the logout flag
120         * @param reset flag to indicate whether we are in 'reset password' mode
121         * @param autoLogout if true, show message about automatic logout
122         */
123        public LoginParameters(
124            String username,
125            String pcType,
126            String oufqn,
127            String requestedResource,
128            Locale locale,
129            String authToken,
130            boolean logout,
131            boolean reset,
132            boolean autoLogout) {
133
134            m_username = username;
135            m_pcType = pcType;
136            m_oufqn = oufqn;
137            m_requestedResource = requestedResource;
138            m_locale = locale;
139            m_authToken = authToken;
140            m_logout = logout;
141            m_reset = reset;
142            m_autoLogout = autoLogout;
143        }
144
145        /**
146         * Gets the authorization token.<p>
147         *
148         * @return the authorization token
149         */
150        public String getAuthToken() {
151
152            return m_authToken;
153        }
154
155        /**
156         * Returns the locale.<p>
157         *
158         * @return the locale
159         */
160        public Locale getLocale() {
161
162            return m_locale;
163        }
164
165        /**
166         * Returns the ou fqn.<p>
167         *
168         * @return the ou fqn
169         */
170        public String getOufqn() {
171
172            return m_oufqn;
173        }
174
175        /**
176         * Returns the pc type.<p>
177         *
178         * @return the pc type
179         */
180        public String getPcType() {
181
182            return m_pcType;
183        }
184
185        /**
186         * Returns the requested resource.<p>
187         *
188         * @return the requested resource
189         */
190        public String getRequestedResource() {
191
192            return m_requestedResource;
193        }
194
195        /**
196         * Returns the user name.<p>
197         *
198         * @return the user name
199         */
200        public String getUsername() {
201
202            return m_username;
203        }
204
205        /**
206         * True if we should show a message about the user having been automatically logged out.
207         *
208         * @return true if we should show a message about the user having been automatically logged out
209         */
210        public boolean isAutoLogout() {
211
212            return m_autoLogout;
213        }
214
215        /**
216         * Returns if a logout is requested.<p>
217         *
218         * @return the logout flag
219         */
220        public boolean isLogout() {
221
222            return m_logout;
223        }
224
225        /**
226         * Returns whether the pc type is private.<p>
227         *
228         * @return <code>true</code> if the pc type is private
229         */
230        public boolean isPrivatePc() {
231
232            return (m_pcType == null) || m_pcType.equals(PCTYPE_PRIVATE);
233        }
234
235        /**
236         * Returns true if we are in 'reset password' mode.<p>
237         *
238         * @return true in reset mode, false otherwise
239         */
240        public boolean isReset() {
241
242            return m_reset;
243        }
244    }
245
246    /** Action constant: Default action, display the dialog. */
247    public static final int ACTION_DISPLAY = 0;
248
249    /** Action constant: Login successful. */
250    public static final int ACTION_LOGIN = 1;
251
252    /** Action constant: Logout. */
253    public static final int ACTION_LOGOUT = 2;
254
255    /** The parameter name for the "getoulist" action. */
256    public static final String PARAM_ACTION_GETOULIST = "getoulist";
257
258    /** The parameter name for the "login" action. */
259    public static final String PARAM_ACTION_LOGIN = "login";
260
261    /** The parameter name for the "logout" action. */
262    public static final String PARAM_ACTION_LOGOUT = "logout";
263
264    /** Parameter name for the authorization token. */
265    public static final String PARAM_AUTHTOKEN = "at";
266
267    /** Parameter name for the auto-logout notification. */
268    public static final String PARAM_AUTOLOGOUT = "auto_logout";
269
270    /** The html id for the login form. */
271    public static final String PARAM_FORM = "ocLoginForm";
272
273    /** The parameter name for the organizational unit. */
274    public static final String PARAM_OUFQN = "ocOuFqn";
275
276    /** The parameter name for the search organizational unit. */
277    public static final String PARAM_OUSEARCH = "ocOuSearch";
278
279    /** The parameter name for the password. */
280    public static final String PARAM_PASSWORD = "ocPword";
281
282    /** The parameter name for the PC type. */
283    public static final String PARAM_PCTYPE = "ocPcType";
284
285    /** The parameter name for the organizational unit. */
286    public static final String PARAM_PREDEF_OUFQN = "ocPredefOuFqn";
287
288    /** The parameter name for the user name. */
289    public static final String PARAM_USERNAME = "ocUname";
290
291    /** Parameter used to open the 'send reset mail' view instead of the login dialog. */
292    public static final String PARAM_RESET_PASSWORD = "reset";
293
294    /** The parameter name for the workplace data. */
295    public static final String PARAM_WPDATA = "ocWpData";
296
297    /** PC type constant: private PC. */
298    public static final String PCTYPE_PRIVATE = "private";
299
300    /** PC type constant: public PC. */
301    public static final String PCTYPE_PUBLIC = "public";
302
303    /** The oufqn cookie name. */
304    private static final String COOKIE_OUFQN = "OpenCmsOuFqn";
305
306    /** The PC type cookie name. */
307    private static final String COOKIE_PCTYPE = "OpenCmsPcType";
308
309    /** The username cookie name. */
310    private static final String COOKIE_USERNAME = "OpenCmsUserName";
311
312    /** The log object for this class. */
313    private static final Log LOG = CmsLog.getLog(CmsLoginHelper.class);
314
315    /**
316     * Gets the copyright information HTML.<p>
317     *
318     * @param locale the locale for which to get the copyright info
319     *
320     * @return the copyright info HTML
321     */
322    public static String getCopyrightHtml(Locale locale) {
323
324        StringBuffer html = new StringBuffer();
325        html.append("<div style=\"text-align: center; font-size: 10px; white-space: nowrap;\">");
326        html.append("<a href=\"https://www.opencms.org\" target=\"_blank\">OpenCms</a> ");
327        html.append(Messages.get().getBundle(locale).key(Messages.GUI_LOGIN_OPENCMS_IS_FREE_SOFTWARE_0));
328        html.append("</div>\n");
329        html.append("<div style=\"text-align: center; font-size: 10px; white-space: nowrap;\">");
330        html.append(Messages.get().getBundle(locale).key(Messages.GUI_LOGIN_TRADEMARKS_0));
331        html.append("</div>\n");
332        html.append("<div style=\"text-align: center; font-size: 10px; white-space: nowrap;\">");
333        html.append("&copy; 2002 - 2026 Alkacon Software GmbH &amp; Co. KG. ");
334        html.append(Messages.get().getBundle(locale).key(Messages.GUI_LOGIN_RIGHTS_RESERVED_0));
335        html.append("</div>\n");
336        return html.toString();
337    }
338
339    /**
340     * Returns the direct edit path from the user settings, or <code>null</code> if not set.<p>
341     *
342     * @param cms the CMS context to use
343     * @param userSettings the user settings
344     * @param forceDirectEdit <code>true</code> to ignore the start view
345     *
346     * @return the direct edit path
347     */
348    public static String getDirectEditPath(CmsObject cms, CmsUserSettings userSettings, boolean forceDirectEdit) {
349
350        if (forceDirectEdit
351            || (userSettings.getStartView().equals(CmsWorkplace.VIEW_DIRECT_EDIT)
352                | userSettings.getStartView().equals(CmsPageEditorConfiguration.APP_ID))) {
353
354            try {
355                CmsObject cloneCms = OpenCms.initCmsObject(cms);
356                String startSite = CmsWorkplace.getStartSiteRoot(cloneCms, userSettings);
357                cloneCms.getRequestContext().setSiteRoot(startSite);
358                String projectName = userSettings.getStartProject();
359                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(projectName)) {
360                    cloneCms.getRequestContext().setCurrentProject(cloneCms.readProject(projectName));
361                }
362                String folder = userSettings.getStartFolder();
363                if (!cloneCms.existsResource(folder)) {
364                    folder = "/";
365                }
366                CmsResource targetRes = cloneCms.readDefaultFile(folder, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
367                if (targetRes != null) {
368                    return cloneCms.getSitePath(targetRes);
369                }
370            } catch (Exception e) {
371                LOG.debug(e.getLocalizedMessage(), e);
372            }
373        }
374        return null;
375    }
376
377    /**
378     * Returns the login parameters for the current request.<p>
379     *
380     * @param cms the cms context
381     * @param request the request
382     * @param workplaceUiRequest true if this is called from a workplace UI request
383     *
384     * @return the login parameters
385     */
386    public static LoginParameters getLoginParameters(
387        CmsObject cms,
388        HttpServletRequest request,
389        boolean workplaceUiRequest) {
390
391        String authToken = request.getParameter(PARAM_AUTHTOKEN);
392        String autoLogout = request.getParameter(PARAM_AUTOLOGOUT);
393
394        String actionLogout = CmsRequestUtil.getNotEmptyParameter(request, PARAM_ACTION_LOGOUT);
395        boolean logout = Boolean.valueOf(actionLogout).booleanValue();
396        String oufqn = request.getParameter(PARAM_OUFQN);
397        if (oufqn == null) {
398            oufqn = getPreDefOuFqn(cms, request, logout);
399        }
400        String pcType = getPcType(request);
401
402        String username = CmsRequestUtil.getNotEmptyParameter(request, PARAM_USERNAME);
403        if (username != null) {
404            // remove white spaces, can only lead to confusion on user name
405            username = username.trim();
406        }
407        // get cookies only on private PC types (or if security option is disabled)
408        if ((pcType == null) || PCTYPE_PRIVATE.equals(pcType)) {
409            // get the user name cookie
410            Cookie userNameCookie = getCookie(request, COOKIE_USERNAME);
411            if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(userNameCookie.getValue())
412                && !"null".equals(userNameCookie.getValue())) {
413                // only set the data if needed
414                if (username == null) {
415                    username = userNameCookie.getValue();
416                }
417                if (pcType == null) {
418                    // set PC type to private PC if the user cookie is found
419                    pcType = PCTYPE_PRIVATE;
420                }
421            }
422            if (oufqn == null) {
423                // get the organizational unit cookie
424                Cookie ouFqnCookie = getCookie(request, COOKIE_OUFQN);
425                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(ouFqnCookie.getValue())
426                    && !"null".equals(ouFqnCookie.getValue())) {
427                    oufqn = ouFqnCookie.getValue();
428                }
429            }
430        }
431        String requestedResource = CmsRequestUtil.getNotEmptyParameter(
432            request,
433            CmsWorkplaceManager.PARAM_LOGIN_REQUESTED_RESOURCE);
434        boolean validRequestedResource = false;
435        if (!CmsStringUtil.isEmptyOrWhitespaceOnly(requestedResource)) {
436            String encryptedRequestedResource = request.getParameter(
437                CmsDefaultAuthorizationHandler.PARAM_ENCRYPTED_REQUESTED_RESOURCE);
438            try {
439                String decryptedResource = OpenCms.getDefaultTextEncryption().decrypt(encryptedRequestedResource);
440                if (requestedResource.equals(decryptedResource)) {
441                    validRequestedResource = true;
442                }
443            } catch (CmsEncryptionException e) {
444                LOG.warn(e.getLocalizedMessage(), e);
445            }
446            if (!validRequestedResource) {
447                requestedResource = null;
448            }
449        }
450        Locale locale = getLocaleForRequest(request);
451        String resetStr = request.getParameter(PARAM_RESET_PASSWORD);
452        boolean reset = (resetStr != null);
453        return new LoginParameters(
454            username,
455            pcType,
456            oufqn,
457            requestedResource,
458            locale,
459            authToken,
460            logout,
461            reset,
462            Boolean.parseBoolean(autoLogout));
463    }
464
465    /**
466     * Gets the list of OUs which should be selectable in the login dialog.<p>
467     *
468     * @param cms the CMS context to use
469     * @param predefOu the predefined OU
470     *
471     * @return the list of organizational units for the OU selector
472     */
473    public static List<CmsOrganizationalUnit> getOrgUnitsForLoginDialog(CmsObject cms, String predefOu) {
474
475        List<CmsOrganizationalUnit> result = new ArrayList<CmsOrganizationalUnit>();
476        try {
477            if (predefOu == null) {
478                result.add(OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, ""));
479                result.addAll(OpenCms.getOrgUnitManager().getOrganizationalUnits(cms, "", true));
480                Iterator<CmsOrganizationalUnit> itOus = result.iterator();
481                while (itOus.hasNext()) {
482                    CmsOrganizationalUnit ou = itOus.next();
483                    if (ou.hasFlagHideLogin() || ou.hasFlagWebuser()) {
484                        itOus.remove();
485                    }
486                }
487            } else {
488                result.add(OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, predefOu));
489            }
490        } catch (CmsException e) {
491            LOG.error(e.getLocalizedMessage(), e);
492        }
493        return result;
494
495    }
496
497    /**
498     * Returns the start view.<p>
499     *
500     * @param cms the cms context
501     *
502     * @return the start view
503     */
504    public static String getStartView(CmsObject cms) {
505
506        CmsUserSettings settings = new CmsUserSettings(cms);
507        String targetView = getDirectEditPath(cms, settings, false);
508        if (targetView == null) {
509            if (settings.getStartView().startsWith("/")) {
510                if (CmsWorkplace.VIEW_WORKPLACE.equals(settings.getStartView())) {
511                    targetView = "#" + CmsFileExplorerConfiguration.APP_ID;
512                } else if (CmsWorkplace.VIEW_ADMIN.equals(settings.getStartView())) {
513                    targetView = "#" + CmsAppHierarchyConfiguration.APP_ID;
514                }
515            } else {
516                targetView = "#" + settings.getStartView();
517            }
518        }
519        return targetView;
520    }
521
522    /**
523     * Gets the window title for a given locale.<p>
524     *
525     * @param locale the locale
526     * @return the window title
527     */
528    public static String getTitle(Locale locale) {
529
530        return Messages.get().getBundle(locale).key(Messages.GUI_LOGIN_TITLE_0);
531    }
532
533    /**
534     * Initializes the site and project for a CMS context after login, and returns the workplace settings for the corresponding user.<p>
535     *
536     * @param cms the CMS context which should be initialized
537     * @return the workplace set
538     */
539    public static CmsWorkplaceSettings initSiteAndProject(CmsObject cms) {
540
541        CmsWorkplaceSettings workplaceSettings = CmsWorkplace.initWorkplaceSettings(cms, null, false);
542        String startSite = CmsWorkplace.getStartSiteRoot(cms, workplaceSettings);
543        // switch to the preferred site
544        workplaceSettings.setSite(startSite);
545        cms.getRequestContext().setSiteRoot(startSite);
546        // store the workplace settings
547        CmsUserSettings settings = workplaceSettings.getUserSettings();
548        // get the direct edit path
549
550        try {
551            CmsProject project = cms.readProject(settings.getStartProject());
552            if (OpenCms.getOrgUnitManager().getAllAccessibleProjects(cms, project.getOuFqn(), false).contains(
553                project)) {
554                // user has access to the project, set this as current project
555                workplaceSettings.setProject(project.getUuid());
556                cms.getRequestContext().setCurrentProject(project);
557            }
558        } catch (CmsException e) {
559            // unable to set the startup project, bad but not critical
560            LOG.warn(
561                Messages.get().getBundle().key(
562                    Messages.LOG_LOGIN_NO_STARTUP_PROJECT_2,
563                    cms.getRequestContext().getCurrentUser().getName(),
564                    settings.getStartProject()),
565                e);
566        }
567        return workplaceSettings;
568    }
569
570    /**
571     * Sets the cookie data.<p>
572     *
573     * @param pcType the pctype value
574     * @param username the username value
575     * @param oufqn the oufqn value
576     *
577     * @param request the current request
578     * @param response the current response
579     */
580    public static void setCookieData(
581        String pcType,
582        String username,
583        String oufqn,
584        HttpServletRequest request,
585        HttpServletResponse response) {
586
587        if (CmsStringUtil.isEmpty(oufqn)) {
588            oufqn = "/";
589        }
590        // set the PC type cookie only if security dialog is enabled
591        if (OpenCms.getLoginManager().isEnableSecurity() && CmsStringUtil.isNotEmpty(pcType)) {
592            Cookie pcTypeCookie = getCookie(request, COOKIE_PCTYPE);
593            pcTypeCookie.setValue(pcType);
594            setCookie(pcTypeCookie, false, request, response);
595        }
596
597        // only store user name and OU cookies on private PC types
598        if (PCTYPE_PRIVATE.equals(pcType)) {
599            // set the user name cookie
600            Cookie userNameCookie = getCookie(request, COOKIE_USERNAME);
601            userNameCookie.setValue(username);
602            setCookie(userNameCookie, false, request, response);
603
604            // set the organizational unit cookie
605            Cookie ouFqnCookie = getCookie(request, COOKIE_OUFQN);
606            ouFqnCookie.setValue(oufqn);
607            setCookie(ouFqnCookie, false, request, response);
608        } else if (OpenCms.getLoginManager().isEnableSecurity() && PCTYPE_PUBLIC.equals(pcType)) {
609            // delete user name and organizational unit cookies
610            Cookie userNameCookie = getCookie(request, COOKIE_USERNAME);
611            setCookie(userNameCookie, true, request, response);
612            Cookie ouFqnCookie = getCookie(request, COOKIE_OUFQN);
613            setCookie(ouFqnCookie, true, request, response);
614
615        }
616    }
617
618    /**
619     * Checks if the current user should be logged out automatically when opening the login dialog page.
620     *
621     * @param cms the current CMS context
622     * @return true if the user should be logged out
623     */
624    public static boolean shouldAutoLogout(CmsObject cms) {
625
626        return OpenCms.getLoginManager().isForceLogoutForUnprivilegedUsers()
627            && !OpenCms.getRoleManager().hasRole(cms, CmsRole.ELEMENT_AUTHOR);
628    }
629
630    /**
631     * Checks that the user name and password are not empty, and returns an error message if they are.<p>
632     *
633     * @param username the user name
634     * @param password the password
635     *
636     * @return the error message, or null if the user name and password are OK
637     */
638    public static CmsMessageContainer validateUserAndPasswordNotEmpty(String username, String password) {
639
640        boolean userEmpty = CmsStringUtil.isEmpty(username);
641        boolean passwordEmpty = CmsStringUtil.isEmpty(password);
642
643        // login was requested
644        if (userEmpty && passwordEmpty) {
645            return Messages.get().container(Messages.GUI_LOGIN_NO_DATA_0);
646        } else if (userEmpty) {
647            return Messages.get().container(Messages.GUI_LOGIN_NO_NAME_0);
648        } else if (passwordEmpty) {
649            return Messages.get().container(Messages.GUI_LOGIN_NO_PASSWORD_0);
650        }
651        return null;
652    }
653
654    /**
655     * Returns the cookie with the given name, if not cookie is found a new one is created.<p>
656     *
657     * @param request the current request
658     * @param name the name of the cookie
659     *
660     * @return the cookie
661     */
662    protected static Cookie getCookie(HttpServletRequest request, String name) {
663
664        Cookie[] cookies = request.getCookies();
665        for (int i = 0; (cookies != null) && (i < cookies.length); i++) {
666            if (name.equalsIgnoreCase(cookies[i].getName())) {
667                return cookies[i];
668            }
669        }
670        return new Cookie(name, "");
671    }
672
673    /**
674     * Sets the cookie in the response.<p>
675     *
676     * @param cookie the cookie to set
677     * @param delete flag to determine if the cookir should be deleted
678     * @param request the current request
679     * @param response the current response
680     */
681    protected static void setCookie(
682        Cookie cookie,
683        boolean delete,
684        HttpServletRequest request,
685        HttpServletResponse response) {
686
687        if (request.getAttribute(PARAM_PREDEF_OUFQN) != null) {
688            // prevent the use of cookies if using a direct ou login url
689            return;
690        }
691        int maxAge = 0;
692        if (!delete) {
693            // set the expiration date of the cookie to six months from today
694            GregorianCalendar cal = new GregorianCalendar();
695            cal.add(Calendar.MONTH, 6);
696            maxAge = (int)((cal.getTimeInMillis() - System.currentTimeMillis()) / 1000);
697        }
698        cookie.setMaxAge(maxAge);
699        // set the path
700        cookie.setPath(
701            CmsStringUtil.joinPaths(
702                OpenCms.getStaticExportManager().getVfsPrefix(),
703                CmsWorkplaceLoginHandler.LOGIN_HANDLER));
704        // set the cookie
705        response.addCookie(cookie);
706    }
707
708    /**
709     * Returns the locale for the given request.<p>
710     *
711     * @param req the request
712     *
713     * @return the locale
714     */
715    private static Locale getLocaleForRequest(HttpServletRequest req) {
716
717        CmsAcceptLanguageHeaderParser parser = new CmsAcceptLanguageHeaderParser(
718            req,
719            OpenCms.getWorkplaceManager().getDefaultLocale());
720        List<Locale> acceptedLocales = parser.getAcceptedLocales();
721        List<Locale> workplaceLocales = OpenCms.getWorkplaceManager().getLocales();
722        Locale locale = OpenCms.getLocaleManager().getFirstMatchingLocale(acceptedLocales, workplaceLocales);
723        if (locale == null) {
724            // no match found - use OpenCms default locale
725            locale = OpenCms.getWorkplaceManager().getDefaultLocale();
726        }
727        return locale;
728    }
729
730    /**
731     * Returns the pc type of the current request.<p>
732     *
733     * @param request the request
734     *
735     * @return the pc type
736     */
737    private static String getPcType(HttpServletRequest request) {
738
739        String pcType = null;
740        if (!OpenCms.getLoginManager().isEnableSecurity()) {
741            // if security option is disabled, just set PC type to "private" to get common login dialog
742            pcType = PCTYPE_PRIVATE;
743        } else {
744            // security option is enabled, try to get PC type from request parameter
745            pcType = CmsRequestUtil.getNotEmptyParameter(request, PARAM_PCTYPE);
746            if (pcType == null) {
747                Cookie pcTypeCookie = getCookie(request, COOKIE_PCTYPE);
748                if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(pcTypeCookie.getValue())
749                    && !"null".equals(pcTypeCookie.getValue())) {
750                    pcType = pcTypeCookie.getValue();
751                }
752            }
753
754        }
755        return pcType;
756    }
757
758    /**
759     * Returns the pre defined ou fqn.<p>
760     *
761     * @param cms the cms context
762     * @param request the request
763     * @param logout in case of a logout
764     *
765     * @return the ou fqn
766     */
767    private static String getPreDefOuFqn(CmsObject cms, HttpServletRequest request, boolean logout) {
768
769        if (logout && (request.getAttribute(PARAM_PREDEF_OUFQN) == null)) {
770            String oufqn = cms.getRequestContext().getOuFqn();
771            if (!oufqn.startsWith(CmsOrganizationalUnit.SEPARATOR)) {
772                oufqn = CmsOrganizationalUnit.SEPARATOR + oufqn;
773            }
774            request.setAttribute(CmsLoginHelper.PARAM_PREDEF_OUFQN, oufqn);
775        }
776        return (String)request.getAttribute(PARAM_PREDEF_OUFQN);
777    }
778}