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}