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     */
019    package org.apache.wiki.plugin;
020    
021    import java.util.Map;
022    
023    import org.apache.wiki.WikiContext;
024    import org.apache.wiki.WikiEngine;
025    import org.apache.wiki.api.exceptions.PluginException;
026    import org.apache.wiki.api.exceptions.ProviderException;
027    import org.apache.wiki.api.plugin.WikiPlugin;
028    import org.apache.wiki.attachment.Attachment;
029    import org.apache.wiki.attachment.AttachmentManager;
030    import 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    
056    public 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            StringBuffer result = new StringBuffer();
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    }