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.plugin;
020
021import java.util.Map;
022
023import org.apache.wiki.WikiContext;
024import org.apache.wiki.WikiEngine;
025import org.apache.wiki.api.exceptions.PluginException;
026import org.apache.wiki.api.exceptions.ProviderException;
027import org.apache.wiki.api.plugin.WikiPlugin;
028import org.apache.wiki.attachment.Attachment;
029import org.apache.wiki.attachment.AttachmentManager;
030import org.apache.wiki.util.TextUtil;
031
032/**
033 *  Provides an image plugin for better control than is possible with a simple image inclusion.
034 *  <br> Most parameters are equivalents of the html image attributes.
035 *
036 *  <p>Parameters : </p>
037 *  <ul>
038 *  <li><b>src</b> - the source (a URL) of the image (required parameter)</li>
039 *  <li><b>align</b> - the alignment of the image</li>
040 *  <li><b>height</b> - the height of the image</li>
041 *  <li><b>width</b> - the width of the image</li>
042 *  <li><b>alt</b> - alternate text</li>
043 *  <li><b>caption</b> - the caption for the image</li>
044 *  <li><b>link</b> - the hyperlink for the image</li>
045 *  <li><b>target</b> - the target (frame) to be used for opening the image</li>
046 *  <li><b>style</b> - the style attribute of the image</li>
047 *  <li><b>class</b> - the associated class for the image</li>
048 *  <li><b>border</b> - the border for the image</li>
049 *  </ul>
050 *  
051 *  @since 2.1.4.
052 */
053// FIXME: It is not yet possible to do wiki internal links.  In order to
054//        do this cleanly, a TranslatorReader revamp is needed.
055
056public class Image
057    implements WikiPlugin
058{
059    /** The parameter name for setting the src.  Value is <tt>{@value}</tt>. */
060    public static final String PARAM_SRC      = "src";
061    /** The parameter name for setting the align.  Value is <tt>{@value}</tt>. */
062    public static final String PARAM_ALIGN    = "align";
063    /** The parameter name for setting the height.  Value is <tt>{@value}</tt>. */
064    public static final String PARAM_HEIGHT   = "height";
065    /** The parameter name for setting the width.  Value is <tt>{@value}</tt>. */
066    public static final String PARAM_WIDTH    = "width";
067    /** The parameter name for setting the alt.  Value is <tt>{@value}</tt>. */
068    public static final String PARAM_ALT      = "alt";
069    /** The parameter name for setting the caption.  Value is <tt>{@value}</tt>. */
070    public static final String PARAM_CAPTION  = "caption";
071    /** The parameter name for setting the link.  Value is <tt>{@value}</tt>. */
072    public static final String PARAM_LINK     = "link";
073    /** The parameter name for setting the target.  Value is <tt>{@value}</tt>. */
074    public static final String PARAM_TARGET   = "target";
075    /** The parameter name for setting the style.  Value is <tt>{@value}</tt>. */
076    public static final String PARAM_STYLE    = "style";
077    /** The parameter name for setting the class.  Value is <tt>{@value}</tt>. */
078    public static final String PARAM_CLASS    = "class";
079    //    public static final String PARAM_MAP      = "map";
080    /** The parameter name for setting the border.  Value is <tt>{@value}</tt>. */
081    public static final String PARAM_BORDER   = "border";
082
083    /**
084     *  This method is used to clean away things like quotation marks which
085     *  a malicious user could use to stop processing and insert javascript.
086     */
087    private static String getCleanParameter( Map<String, String> params, String paramId )
088    {
089        return TextUtil.replaceEntities( params.get( paramId ) );
090    }
091
092    /**
093     *  {@inheritDoc}
094     */
095    public String execute( WikiContext context, Map<String, String> params )
096        throws PluginException
097    {
098        WikiEngine engine = context.getEngine();
099        String src     = getCleanParameter( params, PARAM_SRC );
100        String align   = getCleanParameter( params, PARAM_ALIGN );
101        String ht      = getCleanParameter( params, PARAM_HEIGHT );
102        String wt      = getCleanParameter( params, PARAM_WIDTH );
103        String alt     = getCleanParameter( params, PARAM_ALT );
104        String caption = getCleanParameter( params, PARAM_CAPTION );
105        String link    = getCleanParameter( params, PARAM_LINK );
106        String target  = getCleanParameter( params, PARAM_TARGET );
107        String style   = getCleanParameter( params, PARAM_STYLE );
108        String cssclass= getCleanParameter( params, PARAM_CLASS );
109        // String map     = getCleanParameter( params, PARAM_MAP );
110        String border  = getCleanParameter( params, PARAM_BORDER );
111
112        if( src == null )
113        {
114            throw new PluginException("Parameter 'src' is required for Image plugin");
115        }
116
117        if( cssclass == null ) cssclass = "imageplugin";
118
119        if( target != null && !validTargetValue(target) )
120        {
121            target = null; // not a valid value so ignore
122        }
123
124        try
125        {
126            AttachmentManager mgr = engine.getAttachmentManager();
127            Attachment        att = mgr.getAttachmentInfo( context, src );
128
129            if( att != null )
130            {
131                src = context.getURL( WikiContext.ATTACH, att.getName() );
132            }
133        }
134        catch( ProviderException e )
135        {
136            throw new PluginException( "Attachment info failed: "+e.getMessage() );
137        }
138
139        StringBuilder result = new StringBuilder();
140
141        result.append( "<table border=\"0\" class=\""+cssclass+"\"" );
142        //if( align != null ) result.append(" align=\""+align+"\"");
143        //if( style != null ) result.append(" style=\""+style+"\"");
144        
145        //
146        //  Do some magic to make sure centering also work on FireFox
147        //
148        if( style != null ) 
149        {
150            result.append(" style=\""+style);
151
152            // Make sure that we add a ";" to the end of the style string
153            if( result.charAt( result.length()-1 ) != ';' ) result.append(";");
154                
155            if( align != null && align.equals("center") ) 
156            {
157                result.append(" margin-left: auto; margin-right: auto;");
158            }
159                
160            result.append("\"");
161        }
162        else
163        {
164            if( align != null && align.equals("center") ) result.append(" style=\"margin-left: auto; margin-right: auto;\"");
165        }
166        
167        if( align != null && !(align.equals("center")) ) result.append(" align=\""+align+"\"");
168        
169        result.append( ">\n" );
170
171        if( caption != null ) 
172        {
173            result.append("<caption align=bottom>"+TextUtil.replaceEntities(caption)+"</caption>\n");
174        }
175
176
177        result.append( "<tr><td>" );
178       
179        if( link != null ) 
180        {
181            result.append("<a href=\""+link+"\"");
182            if( target != null )
183            {
184                result.append(" target=\""+target+"\"");
185            }
186            result.append(">");
187        }
188
189        result.append( "<img src=\""+src+"\"" );
190       
191        if( ht != null )     result.append(" height=\""+ht+"\"");
192        if( wt != null )     result.append(" width=\""+wt+"\"");
193        if( alt != null )    result.append(" alt=\""+alt+"\"");
194        if( border != null ) result.append(" border=\""+border+"\"");
195        // if( map != null )    result.append(" map=\""+map+"\"");
196
197        result.append(" />");
198        if( link != null )  result.append("</a>");
199        result.append("</td></tr>\n");
200
201        result.append("</table>\n");
202
203        return result.toString();
204    }
205
206    private boolean validTargetValue( String s )
207    {
208        if( s.equals("_blank")
209                || s.equals("_self")
210                || s.equals("_parent")
211                || s.equals("_top") )
212        {
213            return true;
214        } 
215        else if( s.length() > 0 ) // check [a-zA-z]
216        {
217            char c = s.charAt(0);
218            return Character.isLowerCase(c) || Character.isUpperCase(c);
219        }
220        return false;
221    }
222
223}