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;
029
030import java.text.MessageFormat;
031import java.util.Map;
032import java.util.ResourceBundle;
033
034/**
035 *  Opens a WikiForm.
036 *
037 * Builds the HTML code for opening a FORM.
038 *
039 * <p>Since we're only providing an opening FORM tag, we can't use
040 * the ECS utilities.
041 *
042 * A Form plugin line that produces one looks like this:
043 * <p><pre>
044 *   [{FormOpen name='formname' handler='pluginname'
045 *          submit='submitservlet'
046 *          show='always'
047 *   }]
048 * </pre>
049 *
050 * <p>Mandatory parameters:
051 * <br>The <i>name</i> field identifies this particular form to the
052 * Form plugin across pages.
053 * <br>The <i>handler</i> field is a WikiPlugin name; it will be
054 * invoked with the form field values.
055 *
056 * <p>Optional parameters:
057 * <p>The submitservlet is the name of a JSP/servlet capable of
058 * handling the input from this form. It is optional; the default
059 * value is the current page (which can handle the input by using
060 * this Plugin.)
061 *
062 * <p>The <i>hide</i> parameter affects the visibility of this
063 * form. If left out, the form is always shown. If set to
064 * 'onsuccess', the form is not shown if it was submitted
065 * successfully. (Note that a reload of the page would cause the
066 * context to reset, and the form would be shown again. This may
067 * be a useless option.)
068 *
069 */
070public class FormOpen extends FormElement {
071
072    private static final Logger LOG = LogManager.getLogger( FormOpen.class );
073
074    /** Parameter name for setting the method (GET or POST).  Value is <tt>{@value}</tt>. */
075    public static final String PARAM_METHOD = "method";
076
077    /**
078     *  {@inheritDoc}
079     */
080    @Override
081    public String execute( final Context ctx, final Map< String, String > params ) throws PluginException {
082        final ResourceBundle rb = Preferences.getBundle( ctx, Plugin.CORE_PLUGINS_RESOURCEBUNDLE );
083        final String formName = params.get( PARAM_FORM );
084        if( formName == null ) {
085            throw new PluginException( MessageFormat.format( rb.getString( "formopen.missingparam" ), PARAM_FORM ) );
086        }
087        final String hide     = params.get( PARAM_HIDEFORM );
088        final String sourcePage = ctx.getPage().getName();
089        String submitServlet = params.get( PARAM_SUBMITHANDLER );
090        if( submitServlet == null )
091            submitServlet = ctx.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), sourcePage );
092
093        String method = params.get( PARAM_METHOD );
094        if( method == null ) {
095            method="post";
096        }
097
098        if( !( method.equalsIgnoreCase( "get" ) || method.equalsIgnoreCase( "post" ) ) ) {
099            throw new PluginException( rb.getString( "formopen.postorgetonly" ) );
100        }
101
102        FormInfo info = getFormInfo( ctx );
103        if( info != null ) {
104            // Previous information may be the result of submitting
105            // this form, or of a FormSet plugin, or both. If it
106            // exists and is for this form, fine.
107            if( formName.equals( info.getName() ) ) {
108                LOG.debug( "Previous FormInfo for this form was found in context." );
109                // If the FormInfo exists, and if we're supposed to display on error only, we need to exit now.
110                if( HIDE_SUCCESS.equals( hide ) && info.getStatus() == FormInfo.EXECUTED ) {
111                    info.setHide( true );
112                    return "<p>" + rb.getString( "formopen.noneedtoshow" ) + "</p>";
113                }
114            } else {
115                // This would mean that a new form was started without closing an old one.  Get rid of the garbage.
116                info = new FormInfo();
117            }
118        } else {
119            // No previous FormInfo available; store now, so it'll be available for upcoming Form input elements.
120            info = new FormInfo();
121            storeFormInfo( ctx, info );
122        }
123
124        info.setName( formName );
125        info.setAction( submitServlet );
126
127        return "<div class=\"wikiform\">\n" +
128                  "<form action=\"" + submitServlet + "\" name=\"" + formName + "\" " +
129                        "accept-charset=\"" + ctx.getEngine().getContentEncoding() + "\" " +
130                        "method=\"" + method + "\" enctype=\"application/x-www-form-urlencoded\">\n" +
131                  "  <input type=\"hidden\" name=\"" + PARAM_FORMNAMEHIDDEN + "\" value=\"" + formName + "\"/>\n" +
132                  "  <input type=\"hidden\" name=\"" + CsrfProtectionFilter.ANTICSRF_PARAM + "\" value=\"" + ctx.getWikiSession().antiCsrfToken() + "\"/>\n";
133    }
134
135}