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.commons.io.res.type.s3; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.UnsupportedEncodingException; 024import java.net.HttpURLConnection; 025import java.net.MalformedURLException; 026import java.net.URL; 027import java.security.InvalidKeyException; 028import java.security.NoSuchAlgorithmException; 029import java.util.ArrayList; 030import java.util.HashMap; 031import java.util.Iterator; 032import java.util.List; 033import java.util.Map; 034import java.util.TimeZone; 035 036import javax.crypto.Mac; 037import javax.crypto.spec.SecretKeySpec; 038 039import lucee.commons.io.CharsetUtil; 040import lucee.commons.lang.ExceptionUtil; 041import lucee.commons.lang.Md5; 042import lucee.commons.lang.StringUtil; 043import lucee.commons.net.URLEncoder; 044import lucee.commons.net.http.Entity; 045import lucee.commons.net.http.HTTPResponse; 046import lucee.commons.net.http.Header; 047import lucee.commons.net.http.httpclient3.HTTPEngine3Impl; 048import lucee.loader.util.Util; 049import lucee.runtime.config.Constants; 050import lucee.runtime.engine.ThreadLocalPageContext; 051import lucee.runtime.exp.PageException; 052import lucee.runtime.op.Caster; 053import lucee.runtime.type.dt.DateTime; 054 055import org.apache.commons.collections.map.ReferenceMap; 056import org.xml.sax.SAXException; 057 058public final class S3 implements S3Constants { 059 060 private static final String DEFAULT_URL="s3.amazonaws.com"; 061 062 private String secretAccessKey; 063 private String accessKeyId; 064 private TimeZone timezone; 065 private String host; 066 067 068 private static final Map<String,S3Info> infos=new ReferenceMap(); 069 private static final Map<String,AccessControlPolicy> acps=new ReferenceMap(); 070 071 public static final int MAX_REDIRECT = 15; 072 073 public String toString(){ 074 return "secretAccessKey:"+secretAccessKey+";accessKeyId:"+accessKeyId+";host:"+host+";timezone:"+ 075 (timezone==null?"":timezone.getID()); 076 } 077 078 public String hash() { 079 try { 080 return Md5.getDigestAsString(toString()); 081 } catch (IOException e) { 082 return null; 083 } 084 } 085 086 public S3(String secretAccessKey, String accessKeyId,TimeZone tz) { 087 host=DEFAULT_URL; 088 this.secretAccessKey = secretAccessKey; 089 this.accessKeyId = accessKeyId; 090 this.timezone = tz; 091 //testFinal(); 092 } 093 094 095 096 public S3() { 097 098 //testFinal(); 099 } 100 101 /** 102 * @return the secretAccessKey 103 * @throws S3Exception 104 */ 105 String getSecretAccessKeyValidate() throws S3Exception { 106 if(StringUtil.isEmpty(secretAccessKey)) 107 throw new S3Exception("secretAccessKey is not defined, define in "+Constants.APP_CFC+" (s3.awsSecretKey) or as part of the path."); 108 return secretAccessKey; 109 } 110 111 /** 112 * @return the accessKeyId 113 * @throws S3Exception 114 */ 115 String getAccessKeyIdValidate() throws S3Exception { 116 if(StringUtil.isEmpty(accessKeyId)) 117 throw new S3Exception("accessKeyId is not defined, define in "+Constants.APP_CFC+" (this.s3.accessKeyId) or as part of the path."); 118 return accessKeyId; 119 } 120 121 String getSecretAccessKey() { 122 return secretAccessKey; 123 } 124 125 /** 126 * @return the accessKeyId 127 * @throws S3Exception 128 */ 129 String getAccessKeyId() { 130 return accessKeyId; 131 } 132 133 /** 134 * @return the tz 135 */ 136 TimeZone getTimeZone() { 137 if(timezone==null)timezone=ThreadLocalPageContext.getTimeZone(); 138 return timezone; 139 } 140 141 private static byte[] HMAC_SHA1(String key, String message,String charset) throws UnsupportedEncodingException, NoSuchAlgorithmException, InvalidKeyException { 142 143 SecretKeySpec sks = new SecretKeySpec(key.getBytes(charset),"HmacSHA1"); 144 Mac mac = Mac.getInstance(sks.getAlgorithm()); 145 mac.init(sks); 146 mac.update(message.getBytes(charset)); 147 return mac.doFinal(); 148 149 } 150 151 private static String createSignature(String str, String secretAccessKey,String charset) throws InvalidKeyException, NoSuchAlgorithmException, IOException { 152 //str=StringUtil.replace(str, "\\n", String.valueOf((char)10), false); 153 byte[] digest = HMAC_SHA1(secretAccessKey,str,charset); 154 try { 155 return Caster.toB64(digest); 156 } catch (Throwable t) { 157 ExceptionUtil.rethrowIfNecessary(t); 158 throw new IOException(t.getMessage()); 159 } 160 } 161 162 public InputStream listBucketsRaw() throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 163 String dateTimeString = Util.toHTTPTimeString(); 164 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/", getSecretAccessKeyValidate(), "iso-8859-1"); 165 166 HTTPResponse rsp = HTTPEngine3Impl.get(new URL("http://"+host), null, null, -1,MAX_REDIRECT, null, "Lucee", null, 167 new Header[]{ 168 header("Date",dateTimeString), 169 header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature) 170 } 171 ); 172 return rsp.getContentAsStream(); 173 174 } 175 176 177 public HTTPResponse head(String bucketName, String objectName) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 178 bucketName=checkBucket(bucketName); 179 boolean hasObj=!StringUtil.isEmpty(objectName); 180 if(hasObj)objectName=checkObjectName(objectName); 181 182 String dateTimeString = Util.toHTTPTimeString(); 183 String signature = createSignature("HEAD\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:""), getSecretAccessKeyValidate(), "iso-8859-1"); 184 185 186 List<Header> headers=new ArrayList<Header>(); 187 headers.add(header("Date",dateTimeString)); 188 headers.add(header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 189 headers.add(header("Host",bucketName+"."+host)); 190 191 String strUrl="http://"+bucketName+"."+host+"/"; 192 //if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 193 if(hasObj) { 194 strUrl+=objectName; 195 } 196 HTTPResponse method = HTTPEngine3Impl.head(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, "Lucee", null,headers.toArray(new Header[headers.size()])); 197 return method; 198 199 } 200 201 202 203 204 public InputStream aclRaw(String bucketName, String objectName) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 205 bucketName=checkBucket(bucketName); 206 boolean hasObj=!StringUtil.isEmpty(objectName); 207 if(hasObj)objectName=checkObjectName(objectName); 208 209 String dateTimeString = Util.toHTTPTimeString(); 210 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:"")+"?acl", getSecretAccessKeyValidate(), "iso-8859-1"); 211 212 213 List<Header> headers=new ArrayList<Header>(); 214 headers.add(header("Date",dateTimeString)); 215 headers.add(header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 216 headers.add(header("Host",bucketName+"."+host)); 217 218 String strUrl="http://"+bucketName+"."+host+"/"; 219 //if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 220 if(hasObj) { 221 strUrl+=objectName; 222 } 223 strUrl+="?acl"; 224 225 HTTPResponse method = HTTPEngine3Impl.get(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, "Lucee", null,headers.toArray(new Header[headers.size()])); 226 return method.getContentAsStream(); 227 228 } 229 230 public AccessControlPolicy getAccessControlPolicy(String bucketName, String objectName) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 231 InputStream raw = aclRaw(bucketName,objectName); 232 //print.o(IOUtil.toString(raw, null)); 233 ACLFactory factory=new ACLFactory(raw, this); 234 return factory.getAccessControlPolicy(); 235 } 236 237 238 239 240 public void setAccessControlPolicy(String bucketName, String objectName,AccessControlPolicy acp) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 241 bucketName=checkBucket(bucketName); 242 boolean hasObj=!StringUtil.isEmpty(objectName); 243 if(hasObj)objectName=checkObjectName(objectName); 244 245 246 Entity re = HTTPEngine3Impl.getByteArrayEntity(acp.toXMLString().getBytes(CharsetUtil.ISO88591),"text/html"); 247 248 249 String dateTimeString = Util.toHTTPTimeString(); 250 251 252 String cs = "PUT\n\n"+re.contentType()+"\n"+dateTimeString+"\n/"+bucketName+"/"+(hasObj?objectName:"")+"?acl"; 253 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 254 Header[] headers = new Header[]{ 255 header("Content-Type",re.contentType()), 256 header("Content-Length",Long.toString(re.contentLength())), 257 header("Date",dateTimeString), 258 header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 259 }; 260 261 String strUrl="http://"+bucketName+"."+host+"/"; 262 if(hasObj) { 263 strUrl+=objectName; 264 } 265 strUrl+="?acl"; 266 267 268 269 HTTPResponse method = HTTPEngine3Impl.put(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, 270 "Lucee", null,headers,re); 271 if(method.getStatusCode()!=200){ 272 new ErrorFactory(method.getContentAsStream()); 273 } 274 275 276 } 277 278 public InputStream listContentsRaw(String bucketName,String prefix,String marker,int maxKeys) throws MalformedURLException, IOException, InvalidKeyException, NoSuchAlgorithmException { 279 bucketName=checkBucket(bucketName); 280 String dateTimeString = Util.toHTTPTimeString(); 281 String signature = createSignature("GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/", getSecretAccessKeyValidate(), "iso-8859-1"); 282 283 284 List<Header> headers=new ArrayList<Header>(); 285 headers.add(header("Date",dateTimeString)); 286 headers.add(header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature)); 287 headers.add(header("Host",bucketName+"."+host)); 288 289 String strUrl="http://"+bucketName+"."+host+"/"; 290 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"; 291 292 293 char amp='?'; 294 if(!Util.isEmpty(prefix)){ 295 strUrl+=amp+"prefix="+encodeEL(prefix); 296 amp='&'; 297 } 298 if(!Util.isEmpty(marker)) { 299 strUrl+=amp+"marker="+encodeEL(marker); 300 amp='&'; 301 } 302 if(maxKeys!=-1) { 303 strUrl+=amp+"max-keys="+maxKeys; 304 amp='&'; 305 } 306 307 HTTPResponse method = HTTPEngine3Impl.get(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, "Lucee", null,headers.toArray(new Header[headers.size()])); 308 return method.getContentAsStream(); 309 } 310 311 312 public Content[] listContents(String bucketName,String prefix) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 313 String marker=null,last=null; 314 ContentFactory factory; 315 Content[] contents; 316 List<Content[]> list = new ArrayList<Content[]>(); 317 int size=0; 318 while(true) { 319 factory = new ContentFactory(listContentsRaw(bucketName, prefix, marker, -1),this); 320 contents = factory.getContents(); 321 list.add(contents); 322 size+=contents.length; 323 if(factory.isTruncated() && contents.length>0) { 324 last=marker; 325 marker=contents[contents.length-1].getKey(); 326 if(marker.equals(last))break; 327 } 328 else break; 329 } 330 331 if(list.size()==1) return list.get(0); 332 if(list.size()==0) return new Content[0]; 333 334 Content[] rtn=new Content[size]; 335 Iterator<Content[]> it = list.iterator(); 336 int index=0; 337 while(it.hasNext()) { 338 contents=it.next(); 339 for(int i=0;i<contents.length;i++) { 340 rtn[index++]=contents[i]; 341 } 342 } 343 344 return rtn; 345 } 346 347 public Content[] listContents(String bucketName,String prefix,String marker,int maxKeys) throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 348 InputStream raw = listContentsRaw(bucketName, prefix, marker, maxKeys); 349 //print.o(IOUtil.toString(raw, null)); 350 ContentFactory factory = new ContentFactory(raw,this); 351 return factory.getContents(); 352 } 353 354 public Bucket[] listBuckets() throws InvalidKeyException, MalformedURLException, NoSuchAlgorithmException, IOException, SAXException { 355 InputStream raw = listBucketsRaw(); 356 //print.o(IOUtil.toString(raw, null)); 357 BucketFactory factory = new BucketFactory(raw,this); 358 return factory.getBuckets(); 359 } 360 361 public void putBuckets(String bucketName,int acl, int storage) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 362 String strXML = ""; 363 if(storage==STORAGE_EU) { 364 strXML="<CreateBucketConfiguration><LocationConstraint>EU</LocationConstraint></CreateBucketConfiguration>"; 365 } 366 367 byte[] barr = strXML.getBytes(CharsetUtil.ISO88591); 368 put(bucketName, null, acl,HTTPEngine3Impl.getByteArrayEntity(barr,"text/html")); 369 } 370 371 /*public void putObject(String bucketName,String objectName,int acl,Resource res) throws IOException, InvalidKeyException, NoSuchAlgorithmException, PageException, SAXException, EncoderException { 372 String contentType = IOUtil.getMimeType(res, "application"); 373 InputStream is = null; 374 try { 375 is = res.getInputStream(); 376 put(bucketName, objectName, acl, is, contentType); 377 } 378 finally { 379 IOUtil.closeEL(is); 380 } 381 }*/ 382 /* 383 public void put(String bucketName,String objectName,int acl, InputStream is,long length, String contentType) throws IOException, InvalidKeyException, NoSuchAlgorithmException, PageException, SAXException, EncoderException { 384 put(bucketName, objectName, acl, HTTPUtil.toRequestEntity(is),length, contentType); 385 }*/ 386 387 public void put(String bucketName,String objectName,int acl, Entity re) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 388 bucketName=checkBucket(bucketName); 389 objectName=checkObjectName(objectName); 390 391 String dateTimeString = Util.toHTTPTimeString(); 392 // Create a canonical string to send based on operation requested 393 String cs = "PUT\n\n"+re.contentType()+"\n"+dateTimeString+"\nx-amz-acl:"+toStringACL(acl)+"\n/"+bucketName+"/"+objectName; 394 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 395 Header[] headers = new Header[]{ 396 header("Content-Type",re.contentType()), 397 header("Content-Length",Long.toString(re.contentLength())), 398 header("Date",dateTimeString), 399 header("x-amz-acl",toStringACL(acl)), 400 header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 401 }; 402 403 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 404 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 405 406 407 408 HTTPResponse method = HTTPEngine3Impl.put(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, 409 "Lucee", null,headers,re); 410 if(method.getStatusCode()!=200){ 411 new ErrorFactory(method.getContentAsStream()); 412 } 413 414 415 } 416 417 public HttpURLConnection preput(String bucketName,String objectName,int acl, String contentType) throws IOException, InvalidKeyException, NoSuchAlgorithmException { 418 bucketName=checkBucket(bucketName); 419 objectName=checkObjectName(objectName); 420 421 String dateTimeString = Util.toHTTPTimeString(); 422 // Create a canonical string to send based on operation requested 423 String cs = "PUT\n\n"+contentType+"\n"+dateTimeString+"\nx-amz-acl:"+toStringACL(acl)+"\n/"+bucketName+"/"+objectName; 424 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 425 426 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 427 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 428 429 URL url = new URL(strUrl); 430 431 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); 432 conn.setRequestMethod("PUT"); 433 434 conn.setFixedLengthStreamingMode(227422142); 435 conn.setDoOutput(true); 436 conn.setUseCaches(false); 437 conn.setRequestProperty("CONTENT-TYPE", contentType); 438 conn.setRequestProperty("USER-AGENT", "S3 Resource"); 439 //conn.setRequestProperty("Transfer-Encoding", "chunked" ); 440 conn.setRequestProperty("Date", dateTimeString); 441 conn.setRequestProperty("x-amz-acl", toStringACL(acl)); 442 conn.setRequestProperty("Authorization", "AWS "+getAccessKeyIdValidate()+":"+signature); 443 return conn; 444 } 445 446 public String getObjectLink(String bucketName,String objectName,int secondsValid) throws InvalidKeyException, NoSuchAlgorithmException, IOException { 447 bucketName=checkBucket(bucketName); 448 objectName=checkObjectName(objectName); 449 450 long epoch = (System.currentTimeMillis()/1000)+(secondsValid); 451 String cs = "GET\n\n\n"+epoch+"\n/"+bucketName+"/"+objectName; 452 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 453 454 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 455 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 456 457 458 return strUrl+"?AWSAccessKeyId="+getAccessKeyIdValidate()+"&Expires="+epoch+"&Signature="+signature; 459 } 460 461 public InputStream getInputStream(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 462 return getData(bucketName, objectName).getContentAsStream(); 463 } 464 465 public Map<String, String> getMetadata(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 466 HTTPResponse method = getData(bucketName, objectName); 467 Header[] headers = method.getAllHeaders(); 468 Map<String,String> rtn=new HashMap<String, String>(); 469 String name; 470 if(headers!=null)for(int i=0;i<headers.length;i++){ 471 name=headers[i].getName(); 472 if(name.startsWith("x-amz-meta-")) 473 rtn.put(name.substring(11), headers[i].getValue()); 474 } 475 return rtn; 476 } 477 478 private HTTPResponse getData(String bucketName,String objectName) throws InvalidKeyException, NoSuchAlgorithmException, IOException, SAXException { 479 bucketName=checkBucket(bucketName); 480 objectName=checkObjectName(objectName); 481 482 String dateTimeString = Util.toHTTPTimeString(); 483 //long epoch = (System.currentTimeMillis()/1000)+6000; 484 String cs = "GET\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+objectName; 485 486 487 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 488 489 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 490 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 491 URL url = new URL(strUrl); 492 493 494 HTTPResponse method = HTTPEngine3Impl.get(url, null, null, -1,MAX_REDIRECT, null, "Lucee", null, 495 new Header[]{ 496 header("Date",dateTimeString), 497 header("Host",bucketName+"."+host), 498 header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature) 499 } 500 ); 501 if(method.getStatusCode()!=200) 502 new ErrorFactory(method.getContentAsStream()); 503 return method; 504 } 505 506 public void delete(String bucketName, String objectName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, SAXException { 507 bucketName=checkBucket(bucketName); 508 objectName = checkObjectName(objectName); 509 510 String dateTimeString = Util.toHTTPTimeString(); 511 // Create a canonical string to send based on operation requested 512 String cs ="DELETE\n\n\n"+dateTimeString+"\n/"+bucketName+"/"+objectName; 513 //print.out(cs); 514 String signature = createSignature(cs, getSecretAccessKeyValidate(), "iso-8859-1"); 515 516 Header[] headers =new Header[]{ 517 header("Date",dateTimeString), 518 header("Authorization","AWS "+getAccessKeyIdValidate()+":"+signature), 519 }; 520 521 String strUrl="http://"+bucketName+"."+host+"/"+objectName; 522 if(Util.hasUpperCase(bucketName))strUrl="http://"+host+"/"+bucketName+"/"+objectName; 523 524 525 526 HTTPResponse rsp = HTTPEngine3Impl.delete(new URL(strUrl), null, null, -1,MAX_REDIRECT, null, "Lucee", null,headers); 527 528 if(rsp.getStatusCode()!=200) 529 new ErrorFactory(rsp.getContentAsStream()); 530 } 531 532 533 534 535 536 537 // -------------------------------- 538 public static String toStringACL(int acl) throws S3Exception { 539 switch(acl) { 540 case ACL_AUTH_READ:return "authenticated-read"; 541 case ACL_PUBLIC_READ:return "public-read"; 542 case ACL_PRIVATE:return "private"; 543 case ACL_PUBLIC_READ_WRITE:return "public-read-write"; 544 } 545 throw new S3Exception("invalid acl definition"); 546 } 547 548 public static String toStringStorage(int storage) throws S3Exception { 549 String s = toStringStorage(storage, null); 550 if(s==null) 551 throw new S3Exception("invalid storage definition"); 552 return s; 553 } 554 public static String toStringStorage(int storage, String defaultValue) { 555 switch(storage) { 556 case STORAGE_EU:return "eu"; 557 case STORAGE_US:return "us"; 558 case STORAGE_US_WEST:return "us-west"; 559 } 560 return defaultValue; 561 } 562 563 public static int toIntACL(String acl) throws S3Exception { 564 acl=acl.toLowerCase().trim(); 565 if("public-read".equals(acl)) return ACL_PUBLIC_READ; 566 if("private".equals(acl)) return ACL_PRIVATE; 567 if("public-read-write".equals(acl)) return ACL_PUBLIC_READ_WRITE; 568 if("authenticated-read".equals(acl)) return ACL_AUTH_READ; 569 570 if("public_read".equals(acl)) return ACL_PUBLIC_READ; 571 if("public_read_write".equals(acl)) return ACL_PUBLIC_READ_WRITE; 572 if("authenticated_read".equals(acl)) return ACL_AUTH_READ; 573 574 if("publicread".equals(acl)) return ACL_PUBLIC_READ; 575 if("publicreadwrite".equals(acl)) return ACL_PUBLIC_READ_WRITE; 576 if("authenticatedread".equals(acl)) return ACL_AUTH_READ; 577 578 throw new S3Exception("invalid acl value, valid values are [public-read, private, public-read-write, authenticated-read]"); 579 } 580 581 public static int toIntStorage(String storage) throws S3Exception { 582 int s=toIntStorage(storage,-1); 583 if(s==-1) 584 throw new S3Exception("invalid storage value, valid values are [eu,us,us-west]"); 585 return s; 586 } 587 public static int toIntStorage(String storage, int defaultValue) { 588 storage=storage.toLowerCase().trim(); 589 if("us".equals(storage)) return STORAGE_US; 590 if("usa".equals(storage)) return STORAGE_US; 591 if("eu".equals(storage)) return STORAGE_EU; 592 593 if("u.s.".equals(storage)) return STORAGE_US; 594 if("u.s.a.".equals(storage)) return STORAGE_US; 595 if("europe.".equals(storage)) return STORAGE_EU; 596 if("euro.".equals(storage)) return STORAGE_EU; 597 if("e.u.".equals(storage)) return STORAGE_EU; 598 if("united states of america".equals(storage)) return STORAGE_US; 599 600 if("us-west".equals(storage)) return STORAGE_US_WEST; 601 if("usa-west".equals(storage)) return STORAGE_US_WEST; 602 603 604 return defaultValue; 605 } 606 607 608 private String checkObjectName(String objectName) throws UnsupportedEncodingException { 609 if(Util.isEmpty(objectName)) return ""; 610 if(objectName.startsWith("/"))objectName=objectName.substring(1); 611 return encode(objectName); 612 } 613 614 private String checkBucket(String name) { 615 /*if(!Decision.isVariableName(name)) 616 throw new S3Exception("invalid bucket name definition ["+name+"], name should only contain letters, digits, dashes and underscores"); 617 618 if(name.length()<3 || name.length()>255) 619 throw new S3Exception("invalid bucket name definition ["+name+"], the length of a bucket name must be between 3 and 255"); 620 */ 621 622 return encodeEL(name); 623 } 624 625 private String encodeEL(String name) { 626 try { 627 return encode(name); 628 629 } catch (UnsupportedEncodingException e) { 630 return name; 631 } 632 } 633 private String encode(String name) throws UnsupportedEncodingException { 634 return URLEncoder.encode(name,"UTF-8"); 635 } 636 637 /** 638 * @param secretAccessKey the secretAccessKey to set 639 */ 640 public void setSecretAccessKey(String secretAccessKey) { 641 this.secretAccessKey = secretAccessKey; 642 } 643 644 /** 645 * @param accessKeyId the accessKeyId to set 646 */ 647 public void setAccessKeyId(String accessKeyId) { 648 this.accessKeyId = accessKeyId; 649 } 650 651 /** 652 * @param url the url to set 653 */ 654 public void setHost(String host) { 655 this.host=host; 656 } 657 658 public String getHost() { 659 return host; 660 } 661 662 public S3Info getInfo(String path) { 663 return infos.get(toKey(path)); 664 } 665 666 public void setInfo(String path,S3Info info) { 667 infos.put(toKey(path),info); 668 } 669 670 public AccessControlPolicy getACP(String path) { 671 return acps.get(toKey(path)); 672 } 673 674 public void setACP(String path,AccessControlPolicy acp) { 675 acps.put(toKey(path),acp); 676 } 677 678 public void releaseCache(String path) { 679 Object k = toKey(path); 680 infos.remove(k); 681 acps.remove(k); 682 } 683 684 private String toKey(String path) { 685 return toString()+":"+path.toLowerCase(); 686 } 687 688 private Header header(String name, String value) { 689 return HTTPEngine3Impl.header(name,value); 690 } 691 692 public static DateTime toDate(String strDate, TimeZone tz) throws PageException { 693 if(strDate.endsWith("Z")) 694 strDate=strDate.substring(0,strDate.length()-1); 695 return Caster.toDate(strDate, tz); 696 } 697} 698 699 700 701 702