001 package railo.runtime.type.scope; 002 003 import java.io.BufferedReader; 004 import java.io.File; 005 import java.io.InputStream; 006 import java.io.UnsupportedEncodingException; 007 import java.util.ArrayList; 008 import java.util.Iterator; 009 import java.util.Map; 010 011 import javax.servlet.ServletInputStream; 012 import javax.servlet.http.HttpServletRequest; 013 014 import org.apache.commons.fileupload.FileItemFactory; 015 import org.apache.commons.fileupload.FileItemIterator; 016 import org.apache.commons.fileupload.FileItemStream; 017 import org.apache.commons.fileupload.disk.DiskFileItem; 018 import org.apache.commons.fileupload.disk.DiskFileItemFactory; 019 import org.apache.commons.fileupload.servlet.ServletFileUpload; 020 import org.apache.commons.fileupload.servlet.ServletRequestContext; 021 022 import railo.commons.collections.HashTable; 023 import railo.commons.io.IOUtil; 024 import railo.commons.io.res.Resource; 025 import railo.commons.lang.ByteNameValuePair; 026 import railo.commons.lang.StringUtil; 027 import railo.commons.net.URLItem; 028 import railo.runtime.PageContext; 029 import railo.runtime.config.ConfigImpl; 030 import railo.runtime.exp.PageException; 031 import railo.runtime.net.http.ServletInputStreamDummy; 032 import railo.runtime.op.Caster; 033 import railo.runtime.type.Array; 034 import railo.runtime.type.KeyImpl; 035 import railo.runtime.type.List; 036 import railo.runtime.type.util.ArrayUtil; 037 import railo.runtime.util.ApplicationContext; 038 039 040 /** 041 * Form Scope 042 */ 043 public final class FormImpl extends ScopeSupport implements Form,ScriptProtected,FormUpload { 044 045 046 private byte EQL=61; 047 private byte NL=10; 048 private byte AMP=38; 049 050 051 private HashTable fileItems=new HashTable(); 052 private Exception initException=null; 053 054 private String encoding=null; 055 private int scriptProtected=ScriptProtected.UNDEFINED; 056 private static final URLItem[] empty=new URLItem[0]; 057 //private static final ResourceFilter FILTER = new ExtensionResourceFilter(".upload",false); 058 private URLItem[] raw=empty; 059 private static int count=1; 060 061 private static final int HEADER_TEXT_PLAIN=0; 062 private static final int HEADER_MULTIPART_FORM_DATA=1; 063 private static final int HEADER_APP_URL_ENC=2; 064 private int headerType=-1; 065 066 /** 067 * standart class Constructor 068 */ 069 public FormImpl() { 070 super(true,"form",SCOPE_FORM); 071 } 072 073 /** 074 * @see railo.runtime.type.scope.Form#getEncoding() 075 */ 076 public String getEncoding() { 077 return encoding; 078 } 079 080 /** 081 * @see railo.runtime.type.scope.Form#setEncoding(java.lang.String) 082 */ 083 public void setEncoding(String encoding) throws UnsupportedEncodingException { 084 encoding=encoding.trim().toUpperCase(); 085 if(encoding.equals(this.encoding)) return; 086 this.encoding = encoding; 087 if(!isInitalized()) return; 088 fillDecoded(raw,encoding,isScriptProtected()); 089 setFieldNames(); 090 } 091 092 /** 093 * @see railo.runtime.type.scope.ScopeSupport#initialize(railo.runtime.PageContext) 094 */ 095 public void initialize(PageContext pc) { 096 if(encoding==null)encoding=pc.getConfig().getWebCharset(); 097 098 if(scriptProtected==ScriptProtected.UNDEFINED) { 099 scriptProtected=((pc.getApplicationContext().getScriptProtect()&ApplicationContext.SCRIPT_PROTECT_FORM)>0)? 100 ScriptProtected.YES:ScriptProtected.NO; 101 } 102 super.initialize(pc); 103 104 String contentType=pc. getHttpServletRequest().getContentType(); 105 106 if(contentType==null) return; 107 contentType=StringUtil.toLowerCase(contentType); 108 if(contentType.startsWith("multipart/form-data")) { 109 headerType=HEADER_MULTIPART_FORM_DATA; 110 initializeMultiPart(pc,isScriptProtected()); 111 } 112 else if(contentType.startsWith("text/plain")) { 113 headerType=HEADER_TEXT_PLAIN; 114 initializeUrlEncodedOrTextPlain(pc,'\n',isScriptProtected()); 115 } 116 else { 117 headerType=HEADER_APP_URL_ENC; 118 initializeUrlEncodedOrTextPlain(pc,'&',isScriptProtected()); 119 } 120 setFieldNames(); 121 } 122 123 void setFieldNames() { 124 if(size()>0) { 125 setEL(KeyImpl.FIELD_NAMES,List.arrayToList(keysAsString(), ",")); 126 } 127 } 128 129 130 private void initializeMultiPart(PageContext pc, boolean scriptProteced) { 131 // get temp directory 132 Resource tempDir = ((ConfigImpl)pc.getConfig()).getTempDirectory(); 133 Resource tempFile; 134 135 // Create a new file upload handler 136 final String encoding=getEncoding(); 137 FileItemFactory factory = tempDir instanceof File? 138 new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD,(File)tempDir): 139 new DiskFileItemFactory(); 140 141 ServletFileUpload upload = new ServletFileUpload(factory); 142 upload.setHeaderEncoding(encoding); 143 //ServletRequestContext c = new ServletRequestContext(pc.getHttpServletRequest()); 144 145 146 HttpServletRequest req = pc.getHttpServletRequest(); 147 ServletRequestContext context = new ServletRequestContext(req) { 148 public String getCharacterEncoding() { 149 return encoding; 150 } 151 }; 152 153 // Parse the request 154 try { 155 FileItemIterator iter = upload.getItemIterator(context); 156 //byte[] value; 157 InputStream is; 158 ArrayList list=new ArrayList(); 159 while (iter.hasNext()) { 160 FileItemStream item = iter.next(); 161 162 is=IOUtil.toBufferedInputStream(item.openStream()); 163 if (item.getContentType()==null || StringUtil.isEmpty(item.getName())) { 164 list.add(new URLItem(item.getFieldName(),new String(IOUtil.toBytes(is),encoding),false)); 165 } 166 else { 167 tempFile=tempDir.getRealResource(getFileName()); 168 fileItems.put(item.getFieldName().toLowerCase(), 169 new Item(tempFile,item.getContentType(),item.getName(),item.getFieldName())); 170 String value=tempFile.toString(); 171 IOUtil.copy(is, tempFile,true); 172 173 list.add(new URLItem(item.getFieldName(),value,false)); 174 } 175 } 176 177 raw=(URLItem[]) list.toArray(new URLItem[list.size()]); 178 fillDecoded(raw,encoding,scriptProteced); 179 } 180 catch (Exception e) { 181 182 //throw new PageRuntimeException(Caster.toPageException(e)); 183 fillDecodedEL(new URLItem[0],encoding,scriptProteced); 184 initException=e; 185 } 186 } 187 188 private static String getFileName() { 189 return "tmp-"+(count++)+".upload"; 190 } 191 192 /*private void initializeMultiPart(PageContext pc, boolean scriptProteced) { 193 194 File tempDir=FileWrapper.toFile(pc.getConfig().getTempDirectory()); 195 196 // Create a factory for disk-based file items 197 DiskFileItemFactory factory = new DiskFileItemFactory(-1,tempDir); 198 199 // Create a new file upload handler 200 ServletFileUpload upload = new ServletFileUpload(factory); 201 202 upload.setHeaderEncoding(getEncoding()); 203 204 //FileUpload fileUpload=new FileUpload(new DiskFileItemFactory(0,tempDir)); 205 java.util.List list; 206 try { 207 list = upload.parseRequest(pc.getHttpServletRequest()); 208 raw=new ByteNameValuePair[list.size()]; 209 210 for(int i=0;i<raw.length;i++) { 211 DiskFileItem val=(DiskFileItem) list.get(i); 212 if(val.isFormField()) { 213 raw[i]=new ByteNameValuePair(getBytes(val.getFieldName()),val.get(),false); 214 } 215 else { 216 print.out("-------------------------------"); 217 print.out("fieldname:"+val.getFieldName()); 218 print.out("name:"+val.getName()); 219 print.out("formfield:"+val.isFormField()); 220 print.out("memory:"+val.isInMemory()); 221 print.out("exist:"+val.getStoreLocation().getCanonicalFile().exists()); 222 223 fileItems.put(val.getFieldName().toLowerCase(),val); 224 225 raw[i]=new ByteNameValuePair(getBytes(val.getFieldName()),val.getStoreLocation().getCanonicalFile().toString().getBytes(),false); 226 //raw.put(val.getFieldName(),val.getStoreLocation().getCanonicalFile().toString()); 227 } 228 } 229 fillDecoded(raw,encoding,scriptProteced); 230 } 231 catch (Exception e) { 232 233 //throw new PageRuntimeException(Caster.toPageException(e)); 234 fillDecodedEL(new ByteNameValuePair[0],encoding,scriptProteced); 235 initException=e; 236 } 237 }*/ 238 239 private void initializeUrlEncodedOrTextPlain(PageContext pc, char delimeter, boolean scriptProteced) { 240 BufferedReader reader=null; 241 try { 242 reader = pc.getHttpServletRequest().getReader(); 243 raw=setFrom___(IOUtil.toString(reader,false),delimeter); 244 fillDecoded(raw,encoding,scriptProteced); 245 } 246 catch (Exception e) { 247 248 fillDecodedEL(new URLItem[0],encoding,scriptProteced); 249 initException=e; 250 } 251 finally { 252 IOUtil.closeEL(reader); 253 } 254 } 255 256 /** 257 * @see railo.runtime.type.Scope#release() 258 */ 259 public void release() { 260 super.release(); 261 encoding=null; 262 scriptProtected=ScriptProtected.UNDEFINED; 263 raw=empty; 264 265 if(!fileItems.isEmpty()) { 266 Iterator it = fileItems.entrySet().iterator(); 267 Item item; 268 while(it.hasNext()) { 269 item=(Item) ((Map.Entry) it.next()).getValue(); 270 item.getResource().delete(); 271 } 272 fileItems.clear(); 273 } 274 initException=null; 275 276 } 277 278 public FormImpl.Item[] getFileItems() { 279 if(fileItems==null || fileItems.isEmpty()) return new FormImpl.Item[0]; 280 281 Iterator it = fileItems.entrySet().iterator(); 282 Map.Entry entry; 283 FormImpl.Item[] rtn=new FormImpl.Item[fileItems.size()]; 284 int index=0; 285 while(it.hasNext()){ 286 entry=(Entry) it.next(); 287 rtn[index++]=(Item) entry.getValue(); 288 } 289 return rtn; 290 } 291 292 293 /** 294 * @see railo.runtime.type.scope.Form#getFileUpload(java.lang.String) 295 */ 296 public DiskFileItem getFileUpload(String key) { 297 return null; 298 } 299 public Item getUploadResource(String key) { 300 key=key.trim(); 301 String lcKey = StringUtil.toLowerCase(key); 302 303 // x 304 Item item = (Item) fileItems.get(lcKey); 305 if(item!=null)return item; 306 307 // form.x 308 if(lcKey.startsWith("form.")) { 309 lcKey=lcKey.substring(5).trim(); 310 item = (Item) fileItems.get(lcKey); 311 if(item!=null)return item; 312 } 313 314 // form . x 315 try { 316 Array array = List.listToArray(lcKey, '.'); 317 if(array.size()>1 && array.getE(1).toString().trim().equals("form")) { 318 array.removeE(1); 319 lcKey=List.arrayToList(array, ".").trim(); 320 item = (Item) fileItems.get(lcKey); 321 if(item!=null)return item; 322 } 323 } 324 catch (PageException e) {} 325 326 // /file.tmp 327 Iterator it = fileItems.entrySet().iterator(); 328 //print.out("------------------"); 329 while(it.hasNext()) { 330 item=(Item) ((Map.Entry)it.next()).getValue(); 331 //print.out(item.getResource().getAbsolutePath()+" - "+key); 332 //try { 333 //if(item.getStoreLocation().getCanonicalFile().toString().equalsIgnoreCase(key))return item; 334 if(item.getResource().getAbsolutePath().equalsIgnoreCase(key))return item; 335 //} 336 //catch (IOException e) {} 337 } 338 339 return null; 340 } 341 342 /** 343 * @see railo.runtime.type.scope.Form#getInitException() 344 */ 345 public PageException getInitException() { 346 if(initException!=null) 347 return Caster.toPageException(initException); 348 return null; 349 } 350 351 /** 352 * 353 * @see railo.runtime.type.scope.URL#setScriptProtecting(boolean) 354 */ 355 public void setScriptProtecting(boolean scriptProtected) { 356 int _scriptProtected = scriptProtected?ScriptProtected.YES:ScriptProtected.NO; 357 if(isInitalized() && _scriptProtected!=this.scriptProtected) { 358 fillDecodedEL(raw,encoding,scriptProtected); 359 setFieldNames(); 360 } 361 this.scriptProtected=_scriptProtected; 362 /*if(isScriptProtected()) return; 363 if(scriptProtected) { 364 if(isInitalized()) { 365 fillDecodedEL(raw,encoding,scriptProtected); 366 } 367 this.scriptProtected=ScriptProtected.YES; 368 } 369 else this.scriptProtected=ScriptProtected.NO;*/ 370 } 371 372 /** 373 * 374 * @see railo.runtime.type.scope.URL#isScriptProtected() 375 */ 376 public boolean isScriptProtected() { 377 return scriptProtected==ScriptProtected.YES ; 378 } 379 380 /** 381 * @return the raw 382 */ 383 public URLItem[] getRaw() { 384 return raw; 385 } 386 387 public void addRaw(URLItem[] raw) { 388 URLItem[] nr=new URLItem[this.raw.length+raw.length]; 389 for(int i=0;i<this.raw.length;i++) { 390 nr[i]=this.raw[i]; 391 } 392 for(int i=0;i<raw.length;i++) { 393 nr[this.raw.length+i]=raw[i]; 394 } 395 this.raw=nr; 396 397 if(!isInitalized()) return; 398 fillDecodedEL(this.raw,encoding,isScriptProtected()); 399 setFieldNames(); 400 } 401 402 public class Item { 403 Resource resource; 404 String contentType; 405 String name; 406 private String fieldName; 407 408 public Item(Resource resource, String contentType,String name, String fieldName) { 409 this.fieldName = fieldName; 410 this.name = name; 411 this.resource = resource; 412 this.contentType = contentType; 413 } 414 /** 415 * @return the resource 416 */ 417 public Resource getResource() { 418 return resource; 419 } 420 /** 421 * @return the contentType 422 */ 423 public String getContentType() { 424 return contentType; 425 } 426 /** 427 * @return the name 428 */ 429 public String getName() { 430 return name; 431 } 432 /** 433 * @return the fieldName 434 */ 435 public String getFieldName() { 436 return fieldName; 437 } 438 } 439 440 /** 441 * @return return content as a http header input stream 442 */ 443 public ServletInputStream getInputStream() { 444 if(headerType==HEADER_APP_URL_ENC) { 445 return new ServletInputStreamDummy(toBarr(raw,AMP)); 446 } 447 else if(headerType==HEADER_TEXT_PLAIN) { 448 return new ServletInputStreamDummy(toBarr(raw,NL)); 449 } 450 /*else if(headerType==HEADER_MULTIPART_FORM_DATA) { 451 return new FormImplInputStream(this); 452 // TODO 453 }*/ 454 return new ServletInputStreamDummy(new byte[]{}); 455 } 456 457 private byte[] toBarr(URLItem[] items, byte del) { 458 459 ByteNameValuePair[] raw=new ByteNameValuePair[items.length]; 460 for(int i=0;i<raw.length;i++) { 461 try { 462 raw[i]=new ByteNameValuePair(items[i].getName().getBytes("iso-8859-1"),items[i].getValue().getBytes("iso-8859-1"),items[i].isUrlEncoded()); 463 } catch (UnsupportedEncodingException e) {} 464 } 465 466 int size=0; 467 if(!ArrayUtil.isEmpty(raw)){ 468 for(int i=0;i<raw.length;i++) { 469 size+=raw[i].getName().length; 470 size+=raw[i].getValue().length; 471 size+=2; 472 } 473 size--; 474 } 475 byte[] barr = new byte[size],bname,bvalue; 476 int count=0; 477 478 for(int i=0;i<raw.length;i++) { 479 bname=raw[i].getName(); 480 bvalue=raw[i].getValue(); 481 // name 482 for(int y=0;y<bname.length;y++) { 483 barr[count++]=bname[y]; 484 } 485 barr[count++]=EQL; 486 // value 487 for(int y=0;y<bvalue.length;y++) { 488 barr[count++]=bvalue[y]; 489 } 490 if(i+1<raw.length)barr[count++]=del; 491 } 492 return barr; 493 } 494 495 }