001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.tag;
020
021
022import java.io.IOException;
023
024import javax.servlet.jsp.tagext.Tag;
025
026import lucee.commons.io.IOUtil;
027import lucee.commons.io.SystemUtil;
028import lucee.commons.io.res.Resource;
029import lucee.commons.io.res.util.ResourceUtil;
030import lucee.commons.lang.StringUtil;
031import lucee.runtime.exp.ApplicationException;
032import lucee.runtime.exp.ExpressionException;
033import lucee.runtime.exp.PageException;
034import lucee.runtime.ext.tag.TagImpl;
035import lucee.runtime.op.Caster;
036import lucee.runtime.type.util.ListUtil;
037
038import org.apache.commons.mail.EmailAttachment;
039/**
040* Can either attach a file or add a header to a message. It is nested within a cfmail tag. You can 
041*   use more than one cfmailparam tag within a cfmail tag.
042*
043*
044*
045**/
046public final class MailParam extends TagImpl {
047
048        /** Indicates the value of the header. */
049        private String value="";
050
051        /** Attaches the specified file to the message. This attribute is mutually exclusive with the 
052        **              name attribute. */
053        private String file;
054
055        /** Specifies the name of the header. Header names are case insensitive. This attribute is mutually 
056        **              exclusive with the file attribute. */
057        private String name;
058        
059        private String type="";
060    private String disposition=null;
061    private String contentID=null;
062    private Boolean remove=false;
063    private byte[] content=null;
064
065        @Override
066        public void release()   {
067                super.release();
068                value="";
069                file=null;
070                name=null;
071                type="";
072        disposition=null;
073        contentID=null;
074        remove=null;
075        content=null;
076        }
077        
078        /**
079         * @param remove the remove to set
080         */
081        public void setRemove(boolean remove) {
082                this.remove = Caster.toBoolean(remove);
083        }
084
085
086        /**
087         * @param content the content to set
088         * @throws ExpressionException 
089         */
090        public void setContent(Object content) throws PageException {
091                if(content instanceof String)this.content = ((String)content).getBytes();
092                else this.content = Caster.toBinary(content);
093        }
094
095        /**
096         * @param type
097         */
098        public void setType(String type)        {
099                type=type.toLowerCase().trim();
100                
101                if(type.equals("text"))type="text/plain";
102                else if(type.equals("plain"))type="text/plain";
103                else if(type.equals("html"))type="text/html";
104                
105                this.type=type;
106        }
107
108        /** set the value value
109        *  Indicates the value of the header.
110        * @param value value to set
111        **/
112        public void setValue(String value)      {
113                this.value=value;
114        }
115
116        /** set the value file
117        *  Attaches the specified file to the message. This attribute is mutually exclusive with the 
118        *               name attribute.
119        * @param strFile value to set
120         * @throws PageException 
121        **/
122        public void setFile(String strFile) throws PageException        {
123                this.file=strFile;
124        }
125
126        /** set the value name
127        *  Specifies the name of the header. Header names are case insensitive. This attribute is mutually 
128        *               exclusive with the file attribute.
129        * @param name value to set
130        **/
131        public void setName(String name)        {
132                this.name=name;
133        }
134
135    /**
136     * @param disposition The disposition to set.
137     * @throws ApplicationException 
138     */
139    public void setDisposition(String disposition) throws ApplicationException {
140        disposition=disposition.trim().toLowerCase();
141        if(disposition.equals("attachment")) this.disposition=EmailAttachment.ATTACHMENT;
142        else if(disposition.equals("inline"))this.disposition=EmailAttachment.INLINE;
143        else 
144        throw new ApplicationException("disposition must have one of the following values (attachment,inline)");
145        
146    }
147    /**
148     * @param contentID The contentID to set.
149     */
150    public void setContentid(String contentID) {
151        this.contentID = contentID;
152    }
153
154
155        @Override
156        public int doStartTag() throws PageException    {
157                
158                if(content!=null){
159                        required("mailparam", "file", file);
160                        String filename = ListUtil.last(file, "/\\",true);
161                        Resource res = SystemUtil.getTempDirectory().getRealResource(filename);
162                        if(res.exists())ResourceUtil.removeEL(res, true);
163                        try {
164                                IOUtil.write(res, content);
165                        } catch (IOException e) {
166                                throw Caster.toPageException(e);
167                        } 
168                        this.file=ResourceUtil.getCanonicalPathEL(res);
169                        remove=true;
170                }
171                else if(!StringUtil.isEmpty(this.file)) {
172                        Resource res=ResourceUtil.toResourceNotExisting(pageContext,this.file);
173                if(res!=null) {
174                    if(res.exists())pageContext.getConfig().getSecurityManager().checkFileLocation(res);
175                    this.file=ResourceUtil.getCanonicalPathEL(res);
176                } 
177                }
178                
179                
180                
181                
182                // check attributes
183                boolean hasFile=!StringUtil.isEmpty(file);
184                boolean hasName=!StringUtil.isEmpty(name);
185                // both attributes
186                if(hasName && hasFile) {
187                        throw new ApplicationException("Wrong Context for tag MailParam, you cannot use attribute file and name together");
188                }
189                // no attributes
190                if(!hasName && !hasFile) {
191                        throw new ApplicationException("Wrong Context for tag MailParam, you must use attribute file or attribute name for this tag");
192                }
193                
194                // get Mail Tag
195                Tag parent=getParent();
196                while(parent!=null && !(parent instanceof Mail)) {
197                        parent=parent.getParent();
198                }
199                
200                if(parent instanceof Mail) {
201                        Mail mail = (Mail)parent;
202                        mail.setParam(type,file,name,value,disposition,contentID,remove);
203                }
204                else {
205                        throw new ApplicationException("Wrong Context, tag MailParam must be inside a Mail tag");       
206                }
207                return SKIP_BODY;
208        }
209
210        @Override
211        public int doEndTag()   {
212                return EVAL_PAGE;
213        }
214
215}