    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019package org.apache.wiki.forms;
    020
    021import org.apache.logging.log4j.LogManager;
    022import org.apache.logging.log4j.Logger;
    023import org.apache.wiki.api.core.Context;
    024import org.apache.wiki.api.core.ContextEnum;
    025import org.apache.wiki.api.exceptions.PluginException;
    026import org.apache.wiki.api.plugin.Plugin;
    027import org.apache.wiki.http.filter.CsrfProtectionFilter;
    028import org.apache.wiki.preferences.Preferences;
    029import org.apache.wiki.util.TextUtil;
    030
    031import java.text.MessageFormat;
    032import java.util.Map;
    033import java.util.ResourceBundle;
    034
    035/**
    036 *  Opens a WikiForm.
    037 *
    038 * Builds the HTML code for opening a FORM.
    039 *
    040 * <p>Since we're only providing an opening FORM tag, we can't use
    041 * the ECS utilities.
    042 *
    043 * A Form plugin line that produces one looks like this:
    044 * <p><pre>
    045 *   [{FormOpen name='formname' handler='pluginname'
    046 *          submit='submitservlet'
    047 *          show='always'
    048 *   }]
    049 * </pre>
    050 *
    051 * <p>Mandatory parameters:
    052 * <br>The <i>name</i> field identifies this particular form to the
    053 * Form plugin across pages.
    054 * <br>The <i>handler</i> field is a WikiPlugin name; it will be
    055 * invoked with the form field values.
    056 *
    057 * <p>Optional parameters:
    058 * <p>The submitservlet is the name of a JSP/servlet capable of
    059 * handling the input from this form. It is optional; the default
    060 * value is the current page (which can handle the input by using
    061 * this Plugin.)
    062 *
    063 * <p>The <i>hide</i> parameter affects the visibility of this
    064 * form. If left out, the form is always shown. If set to
    065 * 'onsuccess', the form is not shown if it was submitted
    066 * successfully. (Note that a reload of the page would cause the
    067 * context to reset, and the form would be shown again. This may
    068 * be a useless option.)
    069 *
    070 */
    071public class FormOpen extends FormElement {
    072
    073    private static final Logger LOG = LogManager.getLogger( FormOpen.class );
    074
    075    /** Parameter name for setting the method (GET or POST).  Value is <tt>{@value}</tt>. */
    076    public static final String PARAM_METHOD = "method";
    077
    078    /**
    079     *  {@inheritDoc}
    080     */
    081    @Override
    082    public String execute( final Context ctx, final Map< String, String > params ) throws PluginException {
    083        final ResourceBundle rb = Preferences.getBundle( ctx, Plugin.CORE_PLUGINS_RESOURCEBUNDLE );
    084        final String formName = TextUtil.replaceEntities( params.get( PARAM_FORM ) );
    085        if( formName == null ) {
    086            throw new PluginException( MessageFormat.format( rb.getString( "formopen.missingparam" ), PARAM_FORM ) );
    087        }
    088        final String hide     = params.get( PARAM_HIDEFORM );
    089        final String sourcePage = ctx.getPage().getName();
    090        String submitServlet = TextUtil.replaceEntities( params.get( PARAM_SUBMITHANDLER ) );
    091        if( submitServlet == null )
    092            submitServlet = ctx.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), sourcePage );
    093
    094        String method = params.get( PARAM_METHOD );
    095        if( method == null ) {
    096            method="post";
    097        }
    098
    099        if( !( method.equalsIgnoreCase( "get" ) || method.equalsIgnoreCase( "post" ) ) ) {
    100            throw new PluginException( rb.getString( "formopen.postorgetonly" ) );
    101        }
    102
    103        FormInfo info = getFormInfo( ctx );
    104        if( info != null ) {
    105            // Previous information may be the result of submitting
    106            // this form, or of a FormSet plugin, or both. If it
    107            // exists and is for this form, fine.
    108            if( formName.equals( info.getName() ) ) {
    109                LOG.debug( "Previous FormInfo for this form was found in context." );
    110                // If the FormInfo exists, and if we're supposed to display on error only, we need to exit now.
    111                if( HIDE_SUCCESS.equals( hide ) && info.getStatus() == FormInfo.EXECUTED ) {
    112                    info.setHide( true );
    113                    return "<p>" + rb.getString( "formopen.noneedtoshow" ) + "</p>";
    114                }
    115            } else {
    116                // This would mean that a new form was started without closing an old one.  Get rid of the garbage.
    117                info = new FormInfo();
    118            }
    119        } else {
    120            // No previous FormInfo available; store now, so it'll be available for upcoming Form input elements.
    121            info = new FormInfo();
    122            storeFormInfo( ctx, info );
    123        }
    124
    125        info.setName( formName );
    126        info.setAction( submitServlet );
    127
    128        return "<div class=\"wikiform\">\n" +
    129                  "<form action=\"" + submitServlet + "\" name=\"" + formName + "\" " +
    130                        "accept-charset=\"" + ctx.getEngine().getContentEncoding() + "\" " +
    131                        "method=\"" + method + "\" enctype=\"application/x-www-form-urlencoded\">\n" +
    132                  "  <input type=\"hidden\" name=\"" + PARAM_FORMNAMEHIDDEN + "\" value=\"" + formName + "\"/>\n" +
    133                  "  <input type=\"hidden\" name=\"" + CsrfProtectionFilter.ANTICSRF_PARAM + "\" value=\"" + ctx.getWikiSession().antiCsrfToken() + "\"/>\n";
    134    }
    135
    136}