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
021import java.io.IOException;
022
023import javax.servlet.http.HttpServletResponse;
024
025import lucee.commons.lang.StringUtil;
026import lucee.commons.net.HTTPUtil;
027import lucee.runtime.exp.Abort;
028import lucee.runtime.exp.ApplicationException;
029import lucee.runtime.exp.NativeException;
030import lucee.runtime.exp.PageException;
031import lucee.runtime.ext.tag.TagImpl;
032import lucee.runtime.listener.ApplicationContext;
033import lucee.runtime.net.http.ReqRspUtil;
034import lucee.runtime.op.Caster;
035
036
037public final class Location extends TagImpl {
038
039        /** Yes or No. clientManagement must be enabled. Yes appends client variable 
040        **              information to the URL you specify in the url. */
041        private boolean addtoken=true;
042
043        /** The URL of the HTML file or CFML page to open. */
044        private String url="";
045        
046        private int statuscode=302;
047        
048
049        @Override
050        public void release()   {
051                super.release();
052                addtoken=true;
053                url="";
054                statuscode=302;
055        }
056
057        /**
058         * @param statuscode the statuscode to set
059         * @throws ApplicationException 
060         */
061        public void setStatuscode(double statuscode) throws ApplicationException {
062                int sc=(int) statuscode;
063                if(sc<300 || sc>307) 
064                        throw new ApplicationException("invalid value for attribute statuscode ["+Caster.toString(statuscode)+"]",
065                                        "attribute must have one of the folloing values [300|301|302|303|304|305|307]");
066                        
067                this.statuscode = sc;
068        }
069
070
071        /** set the value addtoken
072        *  Yes or No. clientManagement must be enabled. Yes appends client variable 
073        *               information to the URL you specify in the url.
074        * @param addtoken value to set
075        **/
076        public void setAddtoken(boolean addtoken)       {
077                this.addtoken=addtoken;
078        }
079
080        /** set the value url
081        *  The URL of the HTML file or CFML page to open.
082        * @param url value to set
083         * @throws ApplicationException
084        **/
085        public void setUrl(String url) throws ApplicationException      {
086                this.url=url.trim();
087                if(this.url.length()==0) throw new ApplicationException("invalid url [empty string] for attribute url");
088                if(StringUtil.hasLineFeed(url)) throw new ApplicationException("invalid url ["+url+"] for attribute url, carriage-return or line-feed inside the url are not allowed");
089        }
090
091
092        @Override
093        public int doStartTag() throws PageException    {
094                try {
095                        pageContext.getOut().clear();
096                } catch (IOException e) {
097                        throw Caster.toPageException(e);
098                }
099                HttpServletResponse rsp = pageContext. getHttpServletResponse();
100                
101                url=HTTPUtil.encode(url);
102                
103                // add token
104                if(addtoken && needId()) {
105                        String[] arr=url.split("\\?");
106                        
107                        // only string_name
108                        if(arr.length==1) {
109                                url+="?"+pageContext.getURLToken();
110                        }
111                        // script_name and query_string
112                        else if(arr.length>1) {
113                                url=arr[0]+"?"+pageContext.getURLToken();
114                                for(int i=1;i<arr.length;i++)url+="&"+arr[i]; 
115                        }
116                        url=ReqRspUtil.encodeRedirectURLEL(rsp,url);    
117                }
118                
119                rsp.setHeader("Connection", "close"); // IE unter IIS6, Win2K3 und Resin
120                rsp.setStatus(statuscode);
121                rsp.setHeader("location", url);
122                
123                
124                try {
125                        pageContext.forceWrite("<html>\n<head>\n\t<title>Document Moved</title>\n");
126                        //pageContext.forceWrite("\t<script>window.location='"+JSStringFormat.invoke(url)+"';</script>\n");
127                        pageContext.forceWrite("</head>\n<body>\n\t<h1>Object Moved</h1>\n\t             <a HREF=\""+url+"\">here</a>\n");
128                        pageContext.forceWrite("</body>\n</html>");
129                } catch (IOException e) {
130                        throw new NativeException(e);
131                }
132        if(pageContext.getConfig().debug())pageContext.getDebugger().setOutput(false);
133                throw new Abort(Abort.SCOPE_REQUEST);
134        }
135        
136        
137
138
139        private boolean needId() {
140                ApplicationContext ac = pageContext.getApplicationContext();
141                return ac.isSetClientManagement() || ac.isSetSessionManagement();
142        }
143
144        @Override
145        public int doEndTag()   {
146                return EVAL_PAGE;
147        }
148}