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