001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
005 *
006 * This library is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 2.1 of the License, or (at your option) any later version.
010 *
011 * This library is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * For further information about Alkacon Software GmbH & Co. KG, please see the
017 * company website: http://www.alkacon.com
018 *
019 * For further information about OpenCms, please see the
020 * project website: http://www.opencms.org
021 *
022 * You should have received a copy of the GNU Lesser General Public
023 * License along with this library; if not, write to the Free Software
024 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
025 *
026 */
027
028package org.opencms.workplace;
029
030import org.opencms.file.CmsResource;
031import org.opencms.file.CmsResourceFilter;
032import org.opencms.i18n.CmsEncoder;
033import org.opencms.i18n.CmsMessageContainer;
034import org.opencms.jsp.CmsJspActionElement;
035import org.opencms.main.CmsException;
036import org.opencms.main.CmsLog;
037import org.opencms.main.OpenCms;
038import org.opencms.security.CmsPermissionSet;
039import org.opencms.staticexport.CmsLinkManager;
040import org.opencms.ui.apps.CmsAppHierarchyConfiguration;
041import org.opencms.util.CmsRequestUtil;
042import org.opencms.util.CmsStringUtil;
043import org.opencms.workplace.editors.CmsPreEditorAction;
044import org.opencms.workplace.tools.CmsToolDialog;
045import org.opencms.workplace.tools.CmsToolManager;
046
047import java.io.IOException;
048import java.util.HashMap;
049import java.util.Map;
050
051import javax.servlet.http.HttpServletRequest;
052import javax.servlet.http.HttpServletResponse;
053import javax.servlet.jsp.JspException;
054import javax.servlet.jsp.JspWriter;
055import javax.servlet.jsp.PageContext;
056
057import org.apache.commons.logging.Log;
058
059/**
060 * Provides methods for building the dialog windows of OpenCms.<p>
061 *
062 * @since 6.0.0
063 */
064public class CmsDialog extends CmsToolDialog {
065
066    /** Value for the action: cancel. */
067    public static final int ACTION_CANCEL = 4;
068
069    /** Value for the action: close popup window. */
070    public static final int ACTION_CLOSEPOPUP = 6;
071
072    /** Value for the action: save & close popup window. */
073    public static final int ACTION_CLOSEPOPUP_SAVE = 7;
074
075    /** Value for the action: confirmed. */
076    public static final int ACTION_CONFIRMED = 1;
077
078    /** Value for the action: continue. */
079    public static final int ACTION_CONTINUE = 8;
080
081    /** Value for the action: default (show initial dialog form). */
082    public static final int ACTION_DEFAULT = 0;
083
084    /** Value for the action: locks confirmed. */
085    public static final int ACTION_LOCKS_CONFIRMED = 99;
086
087    /** Value for the action: ok. */
088    public static final int ACTION_OK = 3;
089
090    // note: action values 90 - 99 are reserved for reports
091    /** Value for the action: begin the report. */
092    public static final int ACTION_REPORT_BEGIN = 90;
093
094    /** Value for the action: end the report. */
095    public static final int ACTION_REPORT_END = 92;
096
097    /** Value for the action: update the report. */
098    public static final int ACTION_REPORT_UPDATE = 91;
099
100    /** Value for the action: button "set" clicked. */
101    public static final int ACTION_SET = 5;
102
103    /** Value for the action: wait (show please wait screen). */
104    public static final int ACTION_WAIT = 2;
105
106    /** Constant for the "Advanced" button in the build button methods. */
107    public static final int BUTTON_ADVANCED = 3;
108
109    /** Constant for the "Back" button in the build button methods. */
110    public static final int BUTTON_BACK = 9;
111
112    /** Constant for the "Cancel" button in the build button methods. */
113    public static final int BUTTON_CANCEL = 1;
114
115    /** Constant for the "Close" button in the build button methods. */
116    public static final int BUTTON_CLOSE = 2;
117
118    /** Constant for the "Continue" button in the build button methods. */
119    public static final int BUTTON_CONTINUE = 10;
120
121    /** Constant for the "Details" button in the build button methods. */
122    public static final int BUTTON_DETAILS = 5;
123
124    /** Constant for the "Discard" button in the build button methods (same function as "Cancel" button but different text on button. */
125    public static final int BUTTON_DISCARD = 8;
126
127    /** Constant for the "Edit" button in the build button methods (same function as "Ok" button but different text on button. */
128    public static final int BUTTON_EDIT = 7;
129
130    /** Constant for the "OK" button in the build button methods. */
131    public static final int BUTTON_OK = 0;
132
133    /** Constant for the "OK" button in the build button methods (without form submission). */
134    public static final int BUTTON_OK_NO_SUBMIT = 6;
135
136    /** Constant for the "Set" button in the build button methods. */
137    public static final int BUTTON_SET = 4;
138
139    /** Request parameter value for the action: back. */
140    public static final String DIALOG_BACK = "back";
141
142    /** Request parameter value for the action: cancel. */
143    public static final String DIALOG_CANCEL = "cancel";
144
145    /** Request parameter value for the action: dialog confirmed. */
146    public static final String DIALOG_CONFIRMED = "confirmed";
147
148    /** Request parameter value for the action: continue. */
149    public static final String DIALOG_CONTINUE = "continue";
150
151    /** Request parameter value for the action: initial call. */
152    public static final String DIALOG_INITIAL = "initial";
153
154    /** Request parameter value for the action: dialog locks confirmed. */
155    public static final String DIALOG_LOCKS_CONFIRMED = "locksconfirmed";
156
157    /** Request parameter value for the action: ok. */
158    public static final String DIALOG_OK = "ok";
159
160    /** Request parameter value for the action: set. */
161    public static final String DIALOG_SET = "set";
162
163    /** Request parameter value for the action: show please wait screen. */
164    public static final String DIALOG_WAIT = "wait";
165
166    /** Request parameter name for the action. */
167    public static final String PARAM_ACTION = "action";
168
169    /** Request parameter name for the action. */
170    public static final String PARAM_ACTION_VALUE_FOR_CHANGED_INDEX = "index";
171
172    /** Request parameter name for the closelink. */
173    public static final String PARAM_CLOSELINK = "closelink";
174
175    /** Request parameter name for the dialog type. */
176    public static final String PARAM_DIALOGTYPE = "dialogtype";
177
178    /** Request parameter name for the error stack. */
179    public static final String PARAM_ERRORSTACK = "errorstack";
180
181    /** Request parameter name for the file. */
182    public static final String PARAM_FILE = "file";
183
184    /** Request parameter name for the frame name. */
185    public static final String PARAM_FRAMENAME = "framename";
186
187    /** Request parameter name for the "is popup" flag. */
188    public static final String PARAM_ISPOPUP = "ispopup";
189
190    /** Request parameter name for the lock. */
191    public static final String PARAM_LOCK = "lock";
192
193    /** Request parameter name for the error message. */
194    public static final String PARAM_MESSAGE = "message";
195
196    /** Request parameter name for the originalparams. */
197    public static final String PARAM_ORIGINALPARAMS = "originalparams";
198
199    /** Request parameter name for the preactiondone. */
200    public static final String PARAM_PREACTIONDONE = "preactiondone";
201
202    /** Request parameter name for the redirect flag. */
203    public static final String PARAM_REDIRECT = "redirect";
204
205    /** Request parameter name for the resource. */
206    public static final String PARAM_RESOURCE = "resource";
207
208    /** Request parameter name for the target. */
209    public static final String PARAM_TARGET = "target";
210
211    /** Request parameter name for the thread id. */
212    public static final String PARAM_THREAD = "thread";
213
214    /** Request parameter name for indicating if another thread is following the current one. */
215    public static final String PARAM_THREAD_HASNEXT = "threadhasnext";
216
217    /** Request parameter name for the dialog title. */
218    public static final String PARAM_TITLE = "title";
219
220    /** Request parameter value for the action: begin the report. */
221    public static final String REPORT_BEGIN = "reportbegin";
222
223    /** Request parameter value for the action: end the report. */
224    public static final String REPORT_END = "reportend";
225
226    /** Request parameter value for the action: update the report. */
227    public static final String REPORT_UPDATE = "reportupdate";
228
229    /** Key name for the throwable attribute. */
230    protected static final String ATTRIBUTE_THROWABLE = "throwable";
231
232    /** The log object for this class. */
233    private static final Log LOG = CmsLog.getLog(CmsDialog.class);
234
235    /** The dialog action. */
236    private int m_action;
237
238    /**
239     * The custom mapping for online help.<p>
240     *
241     * It will be translated to a javascript variable called onlineHelpUriCustom.
242     * If it is set, the top.head javascript for the online help will use this value. <p>
243     */
244    private String m_onlineHelpUriCustom;
245
246    /** The dialog action parameter. */
247    private String m_paramAction;
248
249    /** The close link parameter. */
250    private String m_paramCloseLink;
251
252    /** The dialog type. */
253    private String m_paramDialogtype;
254
255    /** The frame name parameter. */
256    private String m_paramFrameName;
257
258    /** The is popup parameter. */
259    private String m_paramIsPopup;
260
261    /** The messages parameter. */
262    private String m_paramMessage;
263
264    /** The original parameters. */
265    private String m_paramOriginalParams;
266
267    /** The pre action done parameter. */
268    private String m_paramPreActionDone;
269
270    /** The redirect parameter. */
271    private String m_paramRedirect;
272
273    /** The resource parameter. */
274    private String m_paramResource;
275
276    /** The title parameter. */
277    private String m_paramTitle;
278
279    /**
280     * Public constructor with JSP action element.<p>
281     *
282     * @param jsp an initialized JSP action element
283     */
284    public CmsDialog(CmsJspActionElement jsp) {
285
286        super(jsp);
287    }
288
289    /**
290     * Public constructor with JSP variables.<p>
291     *
292     * @param context the JSP page context
293     * @param req the JSP request
294     * @param res the JSP response
295     */
296    public CmsDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
297
298        this(new CmsJspActionElement(context, req, res));
299    }
300
301    /**
302     * Returns an initialized CmsDialog instance that is read from the request attributes.<p>
303     *
304     * This method is used by dialog elements.
305     * The dialog elements do not initialize their own workplace class,
306     * but use the initialized instance of the "master" class.
307     * This is required to ensure that parameters of the "master" class
308     * can properly be kept on the dialog elements.<p>
309     *
310     * To prevent null pointer exceptions, an empty dialog is returned if
311     * nothing is found in the request attributes.<p>
312     *
313     * @param context the JSP page context
314     * @param req the JSP request
315     * @param res the JSP response
316     *
317     * @return an initialized CmsDialog instance that is read from the request attributes
318     */
319    public static CmsDialog initCmsDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) {
320
321        CmsDialog wp = (CmsDialog)req.getAttribute(CmsWorkplace.SESSION_WORKPLACE_CLASS);
322        if (wp == null) {
323            // ensure that we don't get null pointers if the page is directly called
324            wp = new CmsDialog(new CmsJspActionElement(context, req, res));
325            wp.fillParamValues(req);
326        }
327        return wp;
328    }
329
330    /**
331     * Used to close the current JSP dialog.<p>
332     *
333     * This method tries to include the URI stored in the workplace settings.
334     * This URI is determined by the frame name, which has to be set
335     * in the frame name parameter.<p>
336     *
337     * @throws JspException if including an element fails
338     */
339    public void actionCloseDialog() throws JspException {
340
341        // create a map with empty "resource" parameter to avoid changing the folder when returning to explorer file list
342        Map<String, String> params = new HashMap<String, String>();
343        params.put(PARAM_RESOURCE, "");
344        if (isPopup()) {
345            JspWriter out = getJsp().getJspContext().getOut();
346            try {
347                // try to close the popup
348
349                out.write("<html><head></head>\n");
350                out.write("<body onload=\"top.close();\">\n");
351                out.write("</body>\n");
352                out.write("</html>\n");
353            } catch (IOException e) {
354                // error redirecting, include explorer file list
355                getJsp().include(FILE_EXPLORER_FILELIST, null, params);
356            } finally {
357                try {
358                    out.close();
359                } catch (IOException e) {
360                    throw new JspException(e.getMessage(), e);
361                }
362            }
363        } else if (getParamCloseLink() != null) {
364            // close link parameter present
365            try {
366                if (CmsLinkManager.isWorkplaceLink(getParamCloseLink())) {
367                    // in case the close link points to the new workplace, make sure to set the new location on the top frame
368                    openWorkplaceLink(getParamCloseLink());
369                } else if (Boolean.valueOf(getParamRedirect()).booleanValue()) {
370                    // redirect parameter is true, redirect to given close link
371                    getJsp().getResponse().sendRedirect(getParamCloseLink());
372                } else {
373                    // forward JSP
374                    if (!isForwarded()) {
375                        setForwarded(true);
376                        CmsRequestUtil.forwardRequest(
377                            getParamCloseLink(),
378                            getJsp().getRequest(),
379                            getJsp().getResponse());
380                    }
381                }
382            } catch (Exception e) {
383                // forward failed
384                throw new JspException(e.getMessage(), e);
385            }
386        } else if (getParamFramename() != null) {
387            // no workplace frame mode (currently used for galleries)
388            // frame name parameter found, get URI
389            String frameUri = getSettings().getFrameUris().get(getParamFramename());
390            // resetting the action parameter
391            params.put(PARAM_ACTION, "");
392            if (frameUri != null) {
393                // URI found, include it
394                // remove context path from URI before inclusion
395                frameUri = CmsLinkManager.removeOpenCmsContext(frameUri);
396                // include the found frame URI
397                getJsp().include(frameUri, null, params);
398            } else {
399                // no URI found, include the explorer file list
400                openLaunchpad();
401            }
402        } else {
403            // no frame name parameter found, include the explorer file list
404            openLaunchpad();
405        }
406    }
407
408    /**
409     * Returns the html code to build the ajax report container.<p>
410     *
411     * @param title the title of the report box
412     *
413     * @return html code
414     */
415    public String buildAjaxResultContainer(String title) {
416
417        StringBuffer html = new StringBuffer(512);
418        html.append(dialogBlockStart(title));
419        html.append(dialogWhiteBoxStart());
420        html.append("<div id='ajaxreport' >");
421        html.append(buildAjaxWaitMessage());
422        html.append("</div>\n");
423        html.append(dialogWhiteBoxEnd());
424        html.append(dialogBlockEnd());
425        html.append("&nbsp;<br>\n");
426        return html.toString();
427    }
428
429    /**
430     * Override to display additional options in the lock dialog.<p>
431     *
432     * @return html code to display additional options
433     */
434    public String buildLockAdditionalOptions() {
435
436        return "";
437    }
438
439    /**
440     * Returns the html code to build the confirmation messages.<p>
441     *
442     * @return html code
443     */
444    public String buildLockConfirmationMessageJS() {
445
446        StringBuffer html = new StringBuffer(512);
447        html.append("<script type='text/javascript'><!--\n");
448        html.append("function setConfirmationMessage(locks, blockinglocks) {\n");
449        html.append("\tvar confMsg = document.getElementById('conf-msg');\n");
450        html.append("\tif (locks > -1) {\n");
451        html.append("\t\tif (blockinglocks > '0') {\n");
452        html.append("\t\t\tshowAjaxReportContent();\n");
453        html.append("\t\t\tdocument.getElementById('lock-body-id').className = '';\n");
454        html.append("\t\t\tdocument.getElementById('butClose').className = '';\n");
455        html.append("\t\t\tdocument.getElementById('butContinue').className = 'hide';\n");
456        html.append("\t\t\tconfMsg.innerHTML = '");
457        html.append(key(org.opencms.workplace.commons.Messages.GUI_OPERATION_BLOCKING_LOCKS_0));
458        html.append("';\n");
459        html.append("\t\t} else {\n");
460        html.append("\t\t\tsubmitAction('");
461        html.append(CmsDialog.DIALOG_OK);
462        html.append("', null, 'main');\n");
463        html.append("\t\t\tdocument.forms['main'].submit();\n");
464        html.append("\t\t}\n");
465        html.append("\t} else {\n");
466        html.append("\t\tdocument.getElementById('butClose').className = '';\n");
467        html.append("\t\tdocument.getElementById('butContinue').className = 'hide';\n");
468        html.append("\t\tconfMsg.innerHTML = '");
469        html.append(key(Messages.GUI_AJAX_REPORT_WAIT_0));
470        html.append("';\n");
471        html.append("\t}\n");
472        html.append("}\n");
473        html.append("// -->\n");
474        html.append("</script>\n");
475        return html.toString();
476    }
477
478    /**
479     * Returns the html code to build the header box.<p>
480     *
481     * @return html code
482     *
483     * @throws CmsException if something goes wrong
484     */
485    public String buildLockHeaderBox() throws CmsException {
486
487        StringBuffer html = new StringBuffer(512);
488        // include resource info
489        html.append(dialogBlockStart(null));
490        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_TITLE_0));
491        html.append(": ");
492        html.append(getJsp().property("Title", getParamResource(), ""));
493        html.append("<br>\n");
494        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_STATE_0));
495        html.append(": ");
496        html.append(getState());
497        html.append("<br>\n");
498        html.append(key(org.opencms.workplace.commons.Messages.GUI_LABEL_PERMALINK_0));
499        html.append(": ");
500        html.append(OpenCms.getLinkManager().getPermalink(getCms(), getParamResource()));
501        html.append(dialogBlockEnd());
502        return html.toString();
503    }
504
505    /**
506     * Builds the outer dialog window border.<p>
507     *
508     * @param segment the HTML segment (START / END)
509     * @param attributes optional additional attributes for the opening dialog table
510     *
511     * @return a dialog window start / end segment
512     */
513    public String dialog(int segment, String attributes) {
514
515        if (segment == HTML_START) {
516            StringBuffer html = new StringBuffer(512);
517            if (useNewStyle()) {
518                html.append(dialogTitle());
519            }
520            html.append("<table class=\"dialog\" cellpadding=\"0\" cellspacing=\"0\"");
521            if (attributes != null) {
522                html.append(" ");
523                html.append(attributes);
524            }
525            html.append("><tr><td>\n<table class=\"dialogbox\" cellpadding=\"0\" cellspacing=\"0\">\n");
526            html.append("<tr><td>\n");
527            if (useNewStyle() && getToolManager().hasToolPathForUrl(getJsp().getRequestContext().getUri())) {
528                html.append(getAdminTool().groupHtml(this));
529            }
530            return html.toString();
531        } else {
532            return "</td></tr></table>\n</td></tr></table>\n<p>&nbsp;</p>\n";
533        }
534    }
535
536    /**
537     * Builds a block with 3D border and optional subheadline in the dialog content area.<p>
538     *
539     * @param segment the HTML segment (START / END)
540     * @param headline the headline String for the block
541     * @param error if true, an error block will be created
542     *
543     * @return 3D block start / end segment
544     */
545    public String dialogBlock(int segment, String headline, boolean error) {
546
547        if (segment == HTML_START) {
548            StringBuffer result = new StringBuffer(512);
549            String errorStyle = "";
550            if (error) {
551                errorStyle = " dialogerror";
552            }
553            result.append("<!-- 3D block start -->\n");
554            result.append("<fieldset class=\"dialogblock\">\n");
555            if (CmsStringUtil.isNotEmpty(headline)) {
556                result.append("<legend>");
557                result.append("<span class=\"textbold");
558                result.append(errorStyle);
559                result.append("\" unselectable=\"on\">");
560                result.append(headline);
561                result.append("</span></legend>\n");
562            }
563            return result.toString();
564        } else {
565            return "</fieldset>\n<!-- 3D block end -->\n";
566        }
567    }
568
569    /**
570     * Builds the end HTML for a block with 3D border in the dialog content area.<p>
571     *
572     * @return 3D block start / end segment
573     */
574    public String dialogBlockEnd() {
575
576        return dialogBlock(HTML_END, null, false);
577    }
578
579    /**
580     * Builds the start HTML for a block with 3D border and optional subheadline in the dialog content area.<p>
581     *
582     * @param headline the headline String for the block
583     *
584     * @return 3D block start / end segment
585     */
586    public String dialogBlockStart(String headline) {
587
588        return dialogBlock(HTML_START, headline, false);
589    }
590
591    /**
592     * Builds the button row under the dialog content area without the buttons.<p>
593     *
594     * @param segment the HTML segment (START / END)
595     *
596     * @return the button row start / end segment
597     */
598    public String dialogButtonRow(int segment) {
599
600        if (segment == HTML_START) {
601            return "<!-- button row start -->\n<div class=\"dialogbuttons\" unselectable=\"on\">\n";
602        } else {
603            return "</div>\n<!-- button row end -->\n";
604        }
605    }
606
607    /**
608     * Builds the end of the button row under the dialog content area without the buttons.<p>
609     *
610     * @return the button row end segment
611     */
612    public String dialogButtonRowEnd() {
613
614        return dialogButtonRow(HTML_END);
615    }
616
617    /**
618     * Builds the start of the button row under the dialog content area without the buttons.<p>
619     *
620     * @return the button row start segment
621     */
622    public String dialogButtonRowStart() {
623
624        return dialogButtonRow(HTML_START);
625    }
626
627    /**
628     * Builds the html for the button row under the dialog content area, including buttons.<p>
629     *
630     * @param buttons array of constants of which buttons to include in the row
631     * @param attributes array of Strings for additional button attributes
632     *
633     * @return the html for the button row under the dialog content area, including buttons
634     */
635    public String dialogButtons(int[] buttons, String[] attributes) {
636
637        StringBuffer result = new StringBuffer(256);
638        result.append(dialogButtonRow(HTML_START));
639        for (int i = 0; i < buttons.length; i++) {
640            dialogButtonsHtml(result, buttons[i], attributes[i]);
641        }
642        result.append(dialogButtonRow(HTML_END));
643        return result.toString();
644    }
645
646    /**
647     * Builds a button row with a single "close" button.<p>
648     *
649     * @return the button row
650     */
651    public String dialogButtonsClose() {
652
653        return dialogButtons(new int[] {BUTTON_CLOSE}, new String[1]);
654    }
655
656    /**
657     * Builds a button row with a single "close" button.<p>
658     *
659     * @param closeAttribute additional attributes for the "close" button
660     *
661     * @return the button row
662     */
663    public String dialogButtonsClose(String closeAttribute) {
664
665        return dialogButtons(new int[] {BUTTON_CLOSE}, new String[] {closeAttribute});
666    }
667
668    /**
669     * Builds a button row with a "close" and a "details" button.<p>
670     *
671     * @param closeAttribute additional attributes for the "close" button
672     * @param detailsAttribute additional attributes for the "details" button
673     *
674     * @return the button row
675     */
676    public String dialogButtonsCloseDetails(String closeAttribute, String detailsAttribute) {
677
678        return dialogButtons(new int[] {BUTTON_CLOSE, BUTTON_DETAILS}, new String[] {closeAttribute, detailsAttribute});
679    }
680
681    /**
682     * Builds a button row with a single "ok" button.<p>
683     *
684     * @return the button row
685     */
686    public String dialogButtonsOk() {
687
688        return dialogButtons(new int[] {BUTTON_OK}, new String[1]);
689    }
690
691    /**
692     * Builds a button row with a single "ok" button.<p>
693     *
694     * @param okAttribute additional attributes for the "ok" button
695     *
696     * @return the button row
697     */
698    public String dialogButtonsOk(String okAttribute) {
699
700        return dialogButtons(new int[] {BUTTON_OK}, new String[] {okAttribute});
701    }
702
703    /**
704     * Builds a button row with an "ok" and a "cancel" button.<p>
705     *
706     * @return the button row
707     */
708    public String dialogButtonsOkCancel() {
709
710        return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[2]);
711    }
712
713    /**
714     * Builds a button row with an "ok" and a "cancel" button.<p>
715     *
716     * @param okAttributes additional attributes for the "ok" button
717     * @param cancelAttributes additional attributes for the "cancel" button
718     *
719     * @return the button row
720     */
721    public String dialogButtonsOkCancel(String okAttributes, String cancelAttributes) {
722
723        return dialogButtons(new int[] {BUTTON_OK, BUTTON_CANCEL}, new String[] {okAttributes, cancelAttributes});
724    }
725
726    /**
727     * Builds a button row with an "ok", a "cancel" and an "advanced" button.<p>
728     *
729     * @param okAttributes additional attributes for the "ok" button
730     * @param cancelAttributes additional attributes for the "cancel" button
731     * @param advancedAttributes additional attributes for the "advanced" button
732     *
733     * @return the button row
734     */
735    public String dialogButtonsOkCancelAdvanced(
736        String okAttributes,
737        String cancelAttributes,
738        String advancedAttributes) {
739
740        return dialogButtons(
741            new int[] {BUTTON_OK, BUTTON_CANCEL, BUTTON_ADVANCED},
742            new String[] {okAttributes, cancelAttributes, advancedAttributes});
743    }
744
745    /**
746     * Builds a button row with a "set", an "ok", and a "cancel" button.<p>
747     *
748     * @param setAttributes additional attributes for the "set" button
749     * @param okAttributes additional attributes for the "ok" button
750     * @param cancelAttributes additional attributes for the "cancel" button
751     *
752     * @return the button row
753     */
754    public String dialogButtonsSetOkCancel(String setAttributes, String okAttributes, String cancelAttributes) {
755
756        return dialogButtons(
757            new int[] {BUTTON_SET, BUTTON_OK, BUTTON_CANCEL},
758            new String[] {setAttributes, okAttributes, cancelAttributes});
759    }
760
761    /**
762     * Builds the content area of the dialog window.<p>
763     *
764     * @param segment the HTML segment (START / END)
765     * @param title the title String for the dialog window
766     *
767     * @return a content area start / end segment
768     */
769    public String dialogContent(int segment, String title) {
770
771        if (segment == HTML_START) {
772            StringBuffer result = new StringBuffer(512);
773            // null title is ok, we always want the title headline
774            result.append(dialogHead(title));
775            result.append("<div class=\"dialogcontent\" unselectable=\"on\">\n");
776            result.append("<!-- dialogcontent start -->\n");
777            return result.toString();
778        } else {
779            return "<!-- dialogcontent end -->\n</div>\n";
780        }
781    }
782
783    /**
784     * Returns the end html for the content area of the dialog window.<p>
785     *
786     * @return the end html for the content area of the dialog window
787     */
788    public String dialogContentEnd() {
789
790        return dialogContent(HTML_END, null);
791    }
792
793    /**
794     * Returns the start html for the content area of the dialog window.<p>
795     *
796     * @param title the title for the dialog
797     *
798     * @return the start html for the content area of the dialog window
799     */
800    public String dialogContentStart(String title) {
801
802        return dialogContent(HTML_START, title);
803    }
804
805    /**
806     * Returns the end html for the outer dialog window border.<p>
807     *
808     * @return the end html for the outer dialog window border
809     */
810    public String dialogEnd() {
811
812        return dialog(HTML_END, null);
813    }
814
815    /**
816     * Builds the title of the dialog window.<p>
817     *
818     * @param title the title String for the dialog window
819     *
820     * @return the HTML title String for the dialog window
821     */
822    public String dialogHead(String title) {
823
824        String escapedTitle;
825        if (title == null) {
826            escapedTitle = "";
827        } else {
828            escapedTitle = CmsEncoder.escapeHtml(title);
829        }
830
831        return "<div class=\"dialoghead\" unselectable=\"on\">" + escapedTitle + "</div>";
832    }
833
834    /**
835     * Builds an invisible horizontal spacer with the specified width.<p>
836     *
837     * @param width the width of the spacer in pixels
838     *
839     * @return an invisible horizontal spacer with the specified width
840     */
841    public String dialogHorizontalSpacer(int width) {
842
843        return "<td><span style=\"display:block; height: 1px; width: " + width + "px;\"></span></td>";
844    }
845
846    /**
847     * Builds the necessary button row.<p>
848     *
849     * @return the button row
850     */
851    public String dialogLockButtons() {
852
853        StringBuffer html = new StringBuffer(512);
854        html.append("<div id='butClose' >\n");
855        html.append(dialogButtonsClose());
856        html.append("</div>\n");
857        html.append("<div id='butContinue' class='hide' >\n");
858        html.append(
859            dialogButtons(
860                new int[] {BUTTON_CONTINUE, BUTTON_CANCEL},
861                new String[] {" onclick=\"submitAction('" + DIALOG_OK + "', form); form.submit();\"", ""}));
862        html.append("</div>\n");
863        return html.toString();
864    }
865
866    /**
867     * Builds a dialog line without break (display: block).<p>
868     *
869     * @param segment the HTML segment (START / END)
870     *
871     * @return a row start / end segment
872     */
873    public String dialogRow(int segment) {
874
875        if (segment == HTML_START) {
876            return "<div class=\"dialogrow\">";
877        } else {
878            return "</div>\n";
879        }
880    }
881
882    /**
883     * Builds the end of a dialog line without break (display: block).<p>
884     *
885     * @return the row end segment
886     */
887    public String dialogRowEnd() {
888
889        return dialogRow(HTML_END);
890    }
891
892    /**
893     * Builds the start of a dialog line without break (display: block).<p>
894     *
895     * @return the row start segment
896     */
897    public String dialogRowStart() {
898
899        return dialogRow(HTML_START);
900    }
901
902    /**
903     * Builds the standard javascript for submitting the dialog.<p>
904     *
905     * @return the standard javascript for submitting the dialog
906     */
907    @Override
908    public String dialogScriptSubmit() {
909
910        if (useNewStyle()) {
911            return super.dialogScriptSubmit();
912        }
913        StringBuffer result = new StringBuffer(512);
914        result.append("function submitAction(actionValue, theForm, formName) {\n");
915        result.append("\tif (theForm == null) {\n");
916        result.append("\t\ttheForm = document.forms[formName];\n");
917        result.append("\t}\n");
918        result.append("\ttheForm." + PARAM_FRAMENAME + ".value = window.name;\n");
919        result.append("\tif (actionValue == \"" + DIALOG_OK + "\") {\n");
920        result.append("\t\treturn true;\n");
921        result.append("\t}\n");
922        result.append("\ttheForm." + PARAM_ACTION + ".value = actionValue;\n");
923        result.append("\ttheForm.submit();\n");
924        result.append("\treturn false;\n");
925        result.append("}\n");
926
927        return result.toString();
928    }
929
930    /**
931     * Builds a horizontal separator line in the dialog content area.<p>
932     *
933     * @return a separator element
934     */
935    public String dialogSeparator() {
936
937        return "<div class=\"dialogseparator\" unselectable=\"on\"></div>";
938    }
939
940    /**
941     * Builds a space between two elements in the dialog content area.<p>
942     *
943     * @return a space element
944     */
945    public String dialogSpacer() {
946
947        return "<div class=\"dialogspacer\" unselectable=\"on\">&nbsp;</div>";
948    }
949
950    /**
951     * Returns the start html for the outer dialog window border.<p>
952     *
953     * @return the start html for the outer dialog window border
954     */
955    public String dialogStart() {
956
957        return dialog(HTML_START, null);
958    }
959
960    /**
961     * Returns the start html for the outer dialog window border.<p>
962     *
963     * @param attributes optional html attributes to insert
964     *
965     * @return the start html for the outer dialog window border
966     */
967    public String dialogStart(String attributes) {
968
969        return dialog(HTML_START, attributes);
970    }
971
972    /**
973     * Builds a subheadline in the dialog content area.<p>
974     *
975     * @param headline the desired headline string
976     *
977     * @return a subheadline element
978     */
979    public String dialogSubheadline(String headline) {
980
981        StringBuffer retValue = new StringBuffer(128);
982        retValue.append("<div class=\"dialogsubheader\" unselectable=\"on\">");
983        retValue.append(headline);
984        retValue.append("</div>\n");
985        return retValue.toString();
986    }
987
988    /**
989     * Builds the HTML code to fold and unfold a white-box.<p>
990     *
991     * @param headline the heading to display
992     * @param id the id of the toggle
993     * @param show true if the white box is open at the beginning
994     *
995     * @return HTML code to fold and unfold a white-box
996     */
997    public String dialogToggleStart(String headline, String id, boolean show) {
998
999        StringBuffer result = new StringBuffer(512);
1000        // set icon and style class to use: hide user permissions
1001        String image = "plus.png";
1002        String styleClass = "hide";
1003        if (show) {
1004            // show user permissions
1005            image = "minus.png";
1006            styleClass = "show";
1007        }
1008
1009        result.append("<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\">\n");
1010        result.append("<tr>\n");
1011        result.append(
1012            "\t<td style=\"vertical-align: bottom; padding-bottom: 2px;\"><a href=\"javascript:toggleDetail('");
1013        result.append(id);
1014        result.append("');\"><img src=\"");
1015        result.append(getSkinUri());
1016        result.append("commons/");
1017        result.append(image);
1018        result.append("\" class=\"noborder\" id=\"ic-");
1019        result.append(id);
1020        result.append("\"></a></td>\n");
1021        result.append("\t<td>");
1022        result.append(dialogSubheadline(headline));
1023        result.append("</td>\n");
1024        result.append("</tr>\n");
1025        result.append("</table>\n");
1026
1027        result.append("<div class=\"");
1028        result.append(styleClass);
1029        result.append("\" id=\"");
1030        result.append(id);
1031        result.append("\">\n");
1032        return result.toString();
1033    }
1034
1035    /**
1036     * Builds a white box in the dialog content area.<p>
1037     *
1038     * @param segment the HTML segment (START / END)
1039     *
1040     * @return the white box start / end segment
1041     */
1042    public String dialogWhiteBox(int segment) {
1043
1044        if (segment == HTML_START) {
1045            return "<!-- white box start -->\n"
1046                + "<div class=\"dialoginnerboxborder\">\n"
1047                + "<div class=\"dialoginnerbox\" unselectable=\"off\">\n";
1048        } else {
1049            return "</div>\n</div>\n<!-- white box end -->\n";
1050        }
1051    }
1052
1053    /**
1054     * Builds the end of a white box in the dialog content area.<p>
1055     *
1056     * @return the white box end segment
1057     */
1058    public String dialogWhiteBoxEnd() {
1059
1060        return dialogWhiteBox(HTML_END);
1061    }
1062
1063    /**
1064     * Builds the start of a white box in the dialog content area.<p>
1065     *
1066     * @return the white box start segment
1067     */
1068    public String dialogWhiteBoxStart() {
1069
1070        return dialogWhiteBox(HTML_START);
1071    }
1072
1073    /**
1074     * Returns the action value.<p>
1075     *
1076     * The action value is used on JSP pages to select the proper action
1077     * in a large "switch" statement.<p>
1078     *
1079     * @return the action value
1080     */
1081    public int getAction() {
1082
1083        return m_action;
1084    }
1085
1086    /**
1087     * Returns the action to be carried out after a click on the cancel button..<p>
1088     *
1089     * @return the action to be carried out after a click on the cancel button.
1090     */
1091    public String getCancelAction() {
1092
1093        return DIALOG_CANCEL;
1094    }
1095
1096    /**
1097     * Returns the http URI of the current dialog, to be used
1098     * as value for the "action" attribute of a html form.<p>
1099     *
1100     * This URI is the real one.<p>
1101     *
1102     * @return the http URI of the current dialog
1103     */
1104    public String getDialogRealUri() {
1105
1106        return getJsp().link(getJsp().getRequestContext().getUri());
1107    }
1108
1109    /**
1110     * Returns the http URI of the current dialog, to be used
1111     * as value for the "action" attribute of a html form.<p>
1112     *
1113     * This URI could not be really the real one... <p>
1114     *
1115     * @return the http URI of the current dialog
1116     */
1117    public String getDialogUri() {
1118
1119        if (!useNewStyle()) {
1120            return getDialogRealUri();
1121        } else {
1122            return CmsToolManager.linkForToolPath(getJsp(), getCurrentToolPath());
1123        }
1124    }
1125
1126    /**
1127     * Returns the custom mapping for the online help.<p>
1128     *
1129     * @return the custom mapping for the online help
1130     */
1131    public String getOnlineHelpUriCustom() {
1132
1133        if (m_onlineHelpUriCustom == null) {
1134            return null;
1135        }
1136        StringBuffer result = new StringBuffer(m_onlineHelpUriCustom.length() + 4);
1137        result.append("\"");
1138        result.append(m_onlineHelpUriCustom);
1139        result.append("\"");
1140        return result.toString();
1141    }
1142
1143    /**
1144     * Returns the value of the action parameter,
1145     * or null if this parameter was not provided.<p>
1146     *
1147     * The action parameter is very important,
1148     * it will select the dialog action to perform.
1149     * The value of the {@link #getAction()} method will be
1150     * initialized from the action parameter.<p>
1151     *
1152     * @return the value of the action parameter
1153     */
1154    public String getParamAction() {
1155
1156        return m_paramAction;
1157    }
1158
1159    /**
1160     * Returns the value of the close link parameter,
1161     * or null if this parameter was not provided.<p>
1162     *
1163     * @return the value of the close link parameter
1164     */
1165    public String getParamCloseLink() {
1166
1167        if ((m_paramCloseLink == null) || "null".equals(m_paramCloseLink)) {
1168            return null;
1169        }
1170        return m_paramCloseLink;
1171    }
1172
1173    /**
1174     * Returns the value of the dialog type parameter,
1175     * or null if this parameter was not provided.<p>
1176     *
1177     * This parameter is very important.
1178     * It must match to the localization keys,
1179     * e.g. "copy" for the copy dialog.<p>
1180     *
1181     * This parameter must be set manually by the subclass during
1182     * first initialization.<p>
1183     *
1184     * @return the value of the dialog type parameter
1185     */
1186    public String getParamDialogtype() {
1187
1188        return m_paramDialogtype;
1189    }
1190
1191    /**
1192     * Returns the value of the frame name parameter.<p>
1193     *
1194     * @return the value of the frame name parameter
1195     */
1196    public String getParamFramename() {
1197
1198        if ((m_paramFrameName != null) && !"null".equals(m_paramFrameName)) {
1199            return m_paramFrameName;
1200        } else {
1201            return null;
1202        }
1203    }
1204
1205    /**
1206     * Returns the is popup parameter.<p>
1207     *
1208     * Use this parameter to indicate that the dialog is shown in a popup window.<p>
1209     *
1210     * @return the is popup parameter
1211     */
1212    public String getParamIsPopup() {
1213
1214        return m_paramIsPopup;
1215    }
1216
1217    /**
1218     * Returns the value of the message parameter,
1219     * or null if this parameter was not provided.<p>
1220     *
1221     * The message parameter is used on dialogs to
1222     * show any text message.<p>
1223     *
1224     * @return the value of the message parameter
1225     */
1226    public String getParamMessage() {
1227
1228        return m_paramMessage;
1229    }
1230
1231    /**
1232     * Returns the value of the original parameters parameter.<p>
1233     *
1234     * This stores the request parameter values from a previous dialog, if necessary.<p>
1235     *
1236     * @return the value of the original parameters parameter
1237     */
1238    public String getParamOriginalParams() {
1239
1240        return m_paramOriginalParams;
1241    }
1242
1243    /**
1244     * Returns the value of the preaction done parameter.<p>
1245     *
1246     * @return the value of the preaction done parameter
1247     */
1248    public String getParamPreActionDone() {
1249
1250        return m_paramPreActionDone;
1251    }
1252
1253    /**
1254     * Returns the value of the redirect flag parameter.<p>
1255     *
1256     * @return the value of the redirect flag parameter
1257     */
1258    public String getParamRedirect() {
1259
1260        return m_paramRedirect;
1261    }
1262
1263    /**
1264     * Returns the value of the file parameter,
1265     * or null if this parameter was not provided.<p>
1266     *
1267     * The file parameter selects the file on which the dialog action
1268     * is to be performed.<p>
1269     *
1270     * @return the value of the file parameter
1271     */
1272    public String getParamResource() {
1273
1274        if ((m_paramResource != null) && !"null".equals(m_paramResource)) {
1275            return m_paramResource;
1276        } else {
1277            return null;
1278        }
1279    }
1280
1281    /**
1282     * Returns the value of the title parameter,
1283     * or null if this parameter was not provided.<p>
1284     *
1285     * This parameter is used to build the title
1286     * of the dialog. It is a parameter so that the title
1287     * can be passed to included elements.<p>
1288     *
1289     * @return the value of the title parameter
1290     */
1291    public String getParamTitle() {
1292
1293        return m_paramTitle;
1294    }
1295
1296    /**
1297     * Gets a formatted file state string.<p>
1298     *
1299     * @return formatted state string
1300     *
1301     * @throws CmsException if something goes wrong
1302     */
1303    public String getState() throws CmsException {
1304
1305        if (CmsStringUtil.isNotEmpty(getParamResource())) {
1306            CmsResource file = getCms().readResource(getParamResource(), CmsResourceFilter.ALL);
1307            if (getCms().isInsideCurrentProject(getParamResource())) {
1308                return key(Messages.getStateKey(file.getState()));
1309            } else {
1310                return key(Messages.GUI_EXPLORER_STATENIP_0);
1311            }
1312        }
1313        return "+++ resource parameter not found +++";
1314    }
1315
1316    /**
1317     * Checks if the current resource has lock state exclusive or inherited.<p>
1318     *
1319     * This is used to determine whether the dialog shows the option to delete all
1320     * siblings of the resource or not.
1321     *
1322     * @return true if lock state is exclusive or inherited, otherwise false
1323     */
1324    public boolean hasCorrectLockstate() {
1325
1326        org.opencms.lock.CmsLock lock = null;
1327        try {
1328            // get the lock state for the current resource
1329            lock = getCms().getLock(getParamResource());
1330        } catch (CmsException e) {
1331            // error getting lock state, log the error and return false
1332            LOG.error(e.getLocalizedMessage(getLocale()), e);
1333            return false;
1334        }
1335        // check if auto lock feature is enabled
1336        boolean autoLockFeature = lock.isNullLock() && OpenCms.getWorkplaceManager().autoLockResources();
1337        return autoLockFeature || lock.isExclusive() || lock.isInherited();
1338    }
1339
1340    /**
1341     * Checks if this resource has siblings.<p>
1342     *
1343     * @return true if this resource has siblings
1344     */
1345    public boolean hasSiblings() {
1346
1347        try {
1348            return getCms().readResource(getParamResource(), CmsResourceFilter.ALL).getSiblingCount() > 1;
1349        } catch (CmsException e) {
1350            LOG.error(e.getLocalizedMessage(getLocale()), e);
1351            return false;
1352        }
1353
1354    }
1355
1356    /**
1357     * Builds the start html of the page, including setting of DOCTYPE and
1358     * inserting a header with the content-type.<p>
1359     *
1360     * @return the start html of the page
1361     */
1362    public String htmlStart() {
1363
1364        return pageHtml(HTML_START, null);
1365    }
1366
1367    /**
1368     * Builds the start html of the page, including setting of DOCTYPE and
1369     * inserting a header with the content-type.<p>
1370     *
1371     * This overloads the default method of the parent class.<p>
1372     *
1373     * @param helpUrl the key for the online help to include on the page
1374     *
1375     * @return the start html of the page
1376     */
1377    @Override
1378    public String htmlStart(String helpUrl) {
1379
1380        return pageHtml(HTML_START, helpUrl);
1381    }
1382
1383    /**
1384     * Builds the start html of the page, including setting of DOCTYPE and
1385     * inserting a header with the content-type.<p>
1386     *
1387     * @param helpUrl the key for the online help to include on the page
1388     * @param title the title for the page
1389     *
1390     * @return the start html of the page
1391     */
1392    public String htmlStart(String helpUrl, String title) {
1393
1394        return pageHtml(HTML_START, helpUrl, title);
1395    }
1396
1397    /**
1398     * Builds the start html of the page, including setting of DOCTYPE,
1399     * inserting a header with the content-type and choosing an individual style sheet.<p>
1400     *
1401     * @param title the title for the page
1402     * @param stylesheet the style sheet to include
1403     *
1404     * @return the start html of the page
1405     */
1406    public String htmlStartStyle(String title, String stylesheet) {
1407
1408        return pageHtmlStyle(HTML_START, title, stylesheet);
1409    }
1410
1411    /**
1412     * Displays the throwable on the error page and logs the error.<p>
1413     *
1414     * @param wp the workplace class
1415     * @param t the throwable to be displayed on the error page
1416     *
1417     * @throws JspException if the include of the error page jsp fails
1418     */
1419    public void includeErrorpage(CmsWorkplace wp, Throwable t) throws JspException {
1420
1421        CmsLog.getLog(wp).error(Messages.get().getBundle().key(Messages.ERR_WORKPLACE_DIALOG_0), t);
1422        getJsp().getRequest().setAttribute(SESSION_WORKPLACE_CLASS, wp);
1423        getJsp().getRequest().setAttribute(ATTRIBUTE_THROWABLE, t);
1424        getJsp().include(FILE_DIALOG_SCREEN_ERRORPAGE);
1425    }
1426
1427    /**
1428     * Returns the "isPopup" flag.<p>
1429     *
1430     * @return the "isPopup" flag
1431     */
1432    public boolean isPopup() {
1433
1434        return Boolean.valueOf(getParamIsPopup()).booleanValue();
1435    }
1436
1437    /**
1438     * Returns if the dialog is called in direct edit mode before the editor is opened.<p>
1439     *
1440     * @return true if the dialog is called in direct edit mode before the editor is opened
1441     */
1442    public boolean isPreEditor() {
1443
1444        return CmsPreEditorAction.isPreEditorMode(this);
1445    }
1446
1447    /**
1448     * Builds the start html of the page, including setting of DOCTYPE and
1449     * inserting a header with the content-type.<p>
1450     *
1451     * This overloads the default method of the parent class.<p>
1452     *
1453     * @param segment the HTML segment (START / END)
1454     * @param helpUrl the url for the online help to include on the page
1455     *
1456     * @return the start html of the page
1457     */
1458    @Override
1459    public String pageHtml(int segment, String helpUrl) {
1460
1461        return pageHtml(segment, helpUrl, null);
1462    }
1463
1464    /**
1465     * Builds the start html of the page, including setting of DOCTYPE and
1466     * inserting a header with the content-type.<p>
1467     *
1468     * This overloads the default method of the parent class.<p>
1469     *
1470     * @param segment the HTML segment (START / END)
1471     * @param helpUrl the url for the online help to include on the page
1472     * @param title the title for the page
1473     *
1474     * @return the start html of the page
1475     */
1476    public String pageHtml(int segment, String helpUrl, String title) {
1477
1478        if (segment == HTML_START) {
1479            String stylesheet = null;
1480            if (isPopup() && !useNewStyle()) {
1481                stylesheet = "popup.css";
1482            }
1483            StringBuffer result = new StringBuffer(pageHtmlStyle(segment, title, stylesheet));
1484            if (getSettings().isViewExplorer()) {
1485                result.append("<script type=\"text/javascript\" src=\"");
1486                result.append(getSkinUri());
1487                result.append("commons/explorer.js\"></script>\n");
1488            }
1489            result.append("<script type=\"text/javascript\">\n");
1490            result.append(dialogScriptSubmit());
1491            if (helpUrl != null) {
1492                result.append("if (top.head && top.head.helpUrl) {\n");
1493                result.append("\ttop.head.helpUrl=\"");
1494                result.append(helpUrl + "\";\n");
1495                result.append("}\n\n");
1496            }
1497            // the variable that may be set as path: if non-null this will be
1498            // used as path for the online help window. This is needed because there are pages
1499            // e.g. /administration/accounts/users/new  that perform a jsp - forward while leaving the
1500            // path parameter on the old page: no correct online help possible.
1501            result.append("var onlineHelpUriCustom = ");
1502            result.append(getOnlineHelpUriCustom());
1503            result.append(";\n");
1504
1505            result.append("</script>\n");
1506            return result.toString();
1507        } else {
1508            return super.pageHtml(segment, null);
1509        }
1510    }
1511
1512    /**
1513     * Set the custom mapping for the online help. <p>
1514     *
1515     * This value will be set to a javascript variable called onlineHelpUriCustom.
1516     * If it is set, the top.head javascript for the online help will use this value. <p>
1517     *
1518     * This method should be called from <code>{@link #initWorkplaceRequestValues(CmsWorkplaceSettings, HttpServletRequest)}</code>,
1519     * <code>{@link CmsWorkplace#initWorkplaceMembers(CmsJspActionElement)}</code>
1520     * or from the jsp if the dialog class is used for several actions.
1521     * It should be used whenever the online help mapping does not work (due to jsp - forwards).<p>
1522     *
1523     * @param uri the left hand value in mapping.properties for the online help pages
1524     */
1525    public void setOnlineHelpUriCustom(String uri) {
1526
1527        m_onlineHelpUriCustom = uri;
1528    }
1529
1530    /**
1531     * Sets the value of the action parameter.<p>
1532     *
1533     * @param value the value to set
1534     */
1535    public void setParamAction(String value) {
1536
1537        m_paramAction = value;
1538    }
1539
1540    /**
1541     * Sets the value of the close link parameter.<p>
1542     *
1543     * @param value the value to set
1544     */
1545    public void setParamCloseLink(String value) {
1546
1547        // ensure decoded chars are re-encoded again properly
1548
1549        m_paramCloseLink = value;
1550    }
1551
1552    /**
1553     * Sets the value of the dialog type parameter.<p>
1554     *
1555     * @param value the value to set
1556     */
1557    public void setParamDialogtype(String value) {
1558
1559        m_paramDialogtype = value;
1560    }
1561
1562    /**
1563     * Sets the value of the frame name parameter.<p>
1564     *
1565     * @param value the value to set
1566     */
1567    public void setParamFramename(String value) {
1568
1569        m_paramFrameName = value;
1570    }
1571
1572    /**
1573     * Sets the is popup parameter.<p>
1574     *
1575     * @param value the is popup parameter value
1576     */
1577    public void setParamIsPopup(String value) {
1578
1579        m_paramIsPopup = value;
1580    }
1581
1582    /**
1583     * Sets the value of the message parameter.<p>
1584     *
1585     * @param value the value to set
1586     */
1587    public void setParamMessage(String value) {
1588
1589        m_paramMessage = value;
1590    }
1591
1592    /**
1593     * Sets the value of the original parameters parameter.<p>
1594     *
1595     * @param paramOriginalParams the value of the original parameters parameter
1596     */
1597    public void setParamOriginalParams(String paramOriginalParams) {
1598
1599        m_paramOriginalParams = paramOriginalParams;
1600    }
1601
1602    /**
1603     * Sets the value of the preaction done parameter.<p>
1604     *
1605     * @param paramPreActionDone the value of the preaction done parameter
1606     */
1607    public void setParamPreActionDone(String paramPreActionDone) {
1608
1609        m_paramPreActionDone = paramPreActionDone;
1610    }
1611
1612    /**
1613     * Sets the value of the redirect flag parameter.<p>
1614     *
1615     * @param redirect the value of the redirect flag parameter
1616     */
1617    public void setParamRedirect(String redirect) {
1618
1619        m_paramRedirect = redirect;
1620    }
1621
1622    /**
1623     * Sets the value of the file parameter.<p>
1624     *
1625     * @param value the value to set
1626     */
1627    public void setParamResource(String value) {
1628
1629        m_paramResource = value;
1630    }
1631
1632    /**
1633     * Sets the value of the title parameter.<p>
1634     *
1635     * @param value the value to set
1636     */
1637    public void setParamTitle(String value) {
1638
1639        m_paramTitle = value;
1640    }
1641
1642    /**
1643     * Appends a space char. between tag attributes.<p>
1644     *
1645     * @param attribute a tag attribute
1646     *
1647     * @return the tag attribute with a leading space char
1648     */
1649    protected String appendDelimiter(String attribute) {
1650
1651        if (CmsStringUtil.isNotEmpty(attribute)) {
1652            if (!attribute.startsWith(" ")) {
1653                // add a delimiter space between the beginning button HTML and the button tag attributes
1654                return " " + attribute;
1655            } else {
1656                return attribute;
1657            }
1658        }
1659
1660        return "";
1661    }
1662
1663    /**
1664     * Returns ajax wait message.<p>
1665     *
1666     * @return html code
1667     */
1668    protected String buildAjaxWaitMessage() {
1669
1670        StringBuffer html = new StringBuffer(512);
1671        html.append("<table border='0' style='vertical-align:middle; height: 150px;'>\n");
1672        html.append("<tr><td width='40' align='center' valign='middle'><img src='");
1673        html.append(CmsWorkplace.getSkinUri());
1674        html.append("commons/wait.gif' id='ajaxreport-img' width='32' height='32' alt=''></td>\n");
1675        html.append("<td valign='middle'><span id='ajaxreport-txt' style='color: #000099; font-weight: bold;'>\n");
1676        html.append(key(org.opencms.workplace.Messages.GUI_AJAX_REPORT_WAIT_0));
1677        html.append("</span><br></td></tr></table>\n");
1678        return html.toString();
1679    }
1680
1681    /**
1682     * Checks if the permissions of the current user on the resource to use in the dialog are sufficient.<p>
1683     *
1684     * Automatically generates a CmsMessageContainer object with an error message and stores it in the users session.<p>
1685     *
1686     * @param required the required permissions for the dialog
1687     * @param neededForFolder if true, the permissions are required for the parent folder of the resource (e.g. for editors)
1688     *
1689     * @return true if the permissions are sufficient, otherwise false
1690     */
1691    protected boolean checkResourcePermissions(CmsPermissionSet required, boolean neededForFolder) {
1692
1693        return checkResourcePermissions(
1694            required,
1695            neededForFolder,
1696            Messages.get().container(
1697                Messages.GUI_ERR_RESOURCE_PERMISSIONS_2,
1698                getParamResource(),
1699                required.getPermissionString()));
1700    }
1701
1702    /**
1703     * Checks if the permissions of the current user on the resource to use in the dialog are sufficient.<p>
1704     *
1705     * Automatically generates a CmsMessageContainer object with an error message and stores it in the users session.<p>
1706     *
1707     * @param required the required permissions for the dialog
1708     * @param neededForFolder if true, the permissions are required for the parent folder of the resource (e.g. for editors)
1709     * @param errorMessage the message container that is stored in the session in case the permissions are not sufficient
1710     *
1711     * @return true if the permissions are sufficient, otherwise false
1712     */
1713    protected boolean checkResourcePermissions(
1714        CmsPermissionSet required,
1715        boolean neededForFolder,
1716        CmsMessageContainer errorMessage) {
1717
1718        boolean hasPermissions = false;
1719        try {
1720            CmsResource res;
1721            if (neededForFolder) {
1722                // check permissions for the folder the resource is in
1723                res = getCms().readResource(CmsResource.getParentFolder(getParamResource()), CmsResourceFilter.ALL);
1724            } else {
1725                res = getCms().readResource(getParamResource(), CmsResourceFilter.ALL);
1726            }
1727            hasPermissions = getCms().hasPermissions(res, required, false, CmsResourceFilter.ALL);
1728        } catch (CmsException e) {
1729            // should usually never happen
1730            if (LOG.isInfoEnabled()) {
1731                LOG.info(e);
1732            }
1733        }
1734
1735        if (!hasPermissions) {
1736            // store the error message in the users session
1737            getSettings().setErrorMessage(errorMessage);
1738        }
1739
1740        return hasPermissions;
1741    }
1742
1743    /**
1744     * Returns the full path of the current workplace folder.<p>
1745     *
1746     * @return the full path of the current workplace folder
1747     */
1748    protected String computeCurrentFolder() {
1749
1750        String currentFolder = getSettings().getExplorerResource();
1751        if (currentFolder == null) {
1752            // set current folder to root folder
1753            try {
1754                currentFolder = getCms().getSitePath(getCms().readFolder("/", CmsResourceFilter.IGNORE_EXPIRATION));
1755            } catch (CmsException e) {
1756                // can usually be ignored
1757                if (LOG.isInfoEnabled()) {
1758                    LOG.info(e);
1759                }
1760                currentFolder = "/";
1761            }
1762        }
1763        if (!currentFolder.endsWith("/")) {
1764            // add folder separator to currentFolder
1765            currentFolder += "/";
1766        }
1767        return currentFolder;
1768    }
1769
1770    /**
1771     * Renders the HTML for a single input button of a specified type.<p>
1772     *
1773     * @param result a string buffer where the rendered HTML gets appended to
1774     * @param button a integer key to identify the button
1775     * @param attribute an optional string with possible tag attributes, or null
1776     */
1777    protected void dialogButtonsHtml(StringBuffer result, int button, String attribute) {
1778
1779        attribute = appendDelimiter(attribute);
1780
1781        switch (button) {
1782            case BUTTON_OK:
1783                result.append("<input name=\"ok\" value=\"");
1784                result.append(key(Messages.GUI_DIALOG_BUTTON_OK_0) + "\"");
1785                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1786                    result.append(" type=\"submit\"");
1787                } else {
1788                    result.append(" type=\"button\"");
1789                }
1790                result.append(" class=\"dialogbutton\"");
1791                result.append(attribute);
1792                result.append(">\n");
1793                break;
1794            case BUTTON_CANCEL:
1795                result.append("<input name=\"cancel\" type=\"button\" value=\"");
1796                result.append(key(Messages.GUI_DIALOG_BUTTON_CANCEL_0) + "\"");
1797                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1798                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1799                }
1800                result.append(" class=\"dialogbutton\"");
1801                result.append(attribute);
1802                result.append(">\n");
1803                break;
1804            case BUTTON_EDIT:
1805                result.append("<input name=\"ok\" value=\"");
1806                result.append(key(Messages.GUI_DIALOG_BUTTON_EDIT_0) + "\"");
1807                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1808                    result.append(" type=\"submit\"");
1809                } else {
1810                    result.append(" type=\"button\"");
1811                }
1812                result.append(" class=\"dialogbutton\"");
1813                result.append(attribute);
1814                result.append(">\n");
1815                break;
1816            case BUTTON_DISCARD:
1817                result.append("<input name=\"cancel\" type=\"button\" value=\"");
1818                result.append(key(Messages.GUI_DIALOG_BUTTON_DISCARD_0) + "\"");
1819                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1820                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1821                }
1822                result.append(" class=\"dialogbutton\"");
1823                result.append(attribute);
1824                result.append(">\n");
1825                break;
1826            case BUTTON_CLOSE:
1827                result.append("<input name=\"close\" type=\"button\" value=\"");
1828                result.append(key(Messages.GUI_DIALOG_BUTTON_CLOSE_0) + "\"");
1829                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1830                    result.append(" onclick=\"submitAction('" + DIALOG_CANCEL + "', form);\"");
1831                }
1832                result.append(" class=\"dialogbutton\"");
1833                result.append(attribute);
1834                result.append(">\n");
1835                break;
1836            case BUTTON_ADVANCED:
1837                result.append("<input name=\"advanced\" type=\"button\" value=\"");
1838                result.append(key(Messages.GUI_DIALOG_BUTTON_ADVANCED_0) + "\"");
1839                result.append(" class=\"dialogbutton\"");
1840                result.append(attribute);
1841                result.append(">\n");
1842                break;
1843            case BUTTON_SET:
1844                result.append("<input name=\"set\" type=\"button\" value=\"");
1845                result.append(key(Messages.GUI_DIALOG_BUTTON_SET_0) + "\"");
1846                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1847                    result.append(" onclick=\"submitAction('" + DIALOG_SET + "', form);\"");
1848                }
1849                result.append(" class=\"dialogbutton\"");
1850                result.append(attribute);
1851                result.append(">\n");
1852                break;
1853            case BUTTON_BACK:
1854                result.append("<input name=\"set\" type=\"button\" value=\"");
1855                result.append(key(Messages.GUI_DIALOG_BUTTON_BACK_0) + "\"");
1856                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1857                    result.append(" onclick=\"submitAction('" + DIALOG_BACK + "', form);\"");
1858                }
1859                result.append(" class=\"dialogbutton\"");
1860                result.append(attribute);
1861                result.append(">\n");
1862                break;
1863            case BUTTON_CONTINUE:
1864                result.append("<input name=\"set\" type=\"button\" value=\"");
1865                result.append(key(Messages.GUI_DIALOG_BUTTON_CONTINUE_0) + "\"");
1866                if (attribute.toLowerCase().indexOf("onclick") == -1) {
1867                    result.append(" onclick=\"submitAction('" + DIALOG_CONTINUE + "', form);\"");
1868                }
1869                result.append(" class=\"dialogbutton\"");
1870                result.append(attribute);
1871                result.append(">\n");
1872                break;
1873            case BUTTON_DETAILS:
1874                result.append("<input name=\"details\" type=\"button\" value=\"");
1875                result.append(key(Messages.GUI_DIALOG_BUTTON_DETAIL_0) + "\"");
1876                result.append(" class=\"dialogbutton\"");
1877                result.append(attribute);
1878                result.append(">\n");
1879                break;
1880            default:
1881                // not a valid button code, just insert a warning in the HTML
1882                result.append("<!-- invalid button code: ");
1883                result.append(button);
1884                result.append(" -->\n");
1885        }
1886    }
1887
1888    /**
1889     * Returns the link URL to get back one folder in the administration view.<p>
1890     *
1891     * @return the link URL to get back one folder in the administration view
1892     */
1893    protected String getAdministrationBackLink() {
1894
1895        return CmsWorkplace.VFS_PATH_WORKPLACE
1896            + "action/administration_content_top.html"
1897            + "?sender="
1898            + CmsResource.getParentFolder(getJsp().getRequestContext().getFolderUri());
1899    }
1900
1901    /**
1902     * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest)
1903     */
1904    @Override
1905    protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) {
1906
1907        fillParamValues(request);
1908        if (DIALOG_CANCEL.equals(getParamAction())) {
1909            setAction(ACTION_CANCEL);
1910        }
1911    }
1912
1913    /**
1914     * Opens the launch pad view.<p>
1915     *
1916     * @throws JspException in case writing to the JSP output stream fails
1917     */
1918    protected void openLaunchpad() throws JspException {
1919
1920        try {
1921            openWorkplaceLink(
1922                OpenCms.getSystemInfo().getWorkplaceContext() + "#!" + CmsAppHierarchyConfiguration.APP_ID);
1923        } catch (Exception e) {
1924            // forward failed
1925            throw new JspException(e.getMessage(), e);
1926        }
1927    }
1928
1929    /**
1930     * Opens a workplace UI link in the top frame.<p>
1931     *
1932     * @param workplaceLink the workplace link to open
1933     *
1934     * @throws IOException in case writing to the JSP output stream fails
1935     */
1936    protected void openWorkplaceLink(String workplaceLink) throws IOException {
1937
1938        // in case the close link points to the new workplace, make sure to set the new location on the top frame
1939        JspWriter out = getJsp().getJspContext().getOut();
1940        try {
1941            out.write(
1942                "<html><head><script type=\"text/javascript\">top.location.href=\""
1943                    + workplaceLink
1944                    + "\";</script></head>\n");
1945            out.write("</html>\n");
1946        } finally {
1947            out.close();
1948        }
1949    }
1950
1951    /**
1952     * Sets the action value.<p>
1953     *
1954     * @param value the action value
1955     */
1956    protected void setAction(int value) {
1957
1958        m_action = value;
1959    }
1960}