dever vor 4 Jahren
Ursprung
Commit
56081c3214
96 geänderte Dateien mit 10673 neuen und 5 gelöschten Zeilen
  1. 2 2
      database/upload.php
  2. 17 0
      database/yun.php
  3. 2 2
      lib/Store/Core.php
  4. 4 1
      lib/Store/Handle.php
  5. 211 0
      lib/Store/Oss.php
  6. 263 0
      sdk/OSS/Core/MimeTypes.php
  7. 54 0
      sdk/OSS/Core/OssException.php
  8. 529 0
      sdk/OSS/Core/OssUtil.php
  9. 25 0
      sdk/OSS/Http/LICENSE
  10. 897 0
      sdk/OSS/Http/RequestCore.php
  11. 8 0
      sdk/OSS/Http/RequestCore_Exception.php
  12. 56 0
      sdk/OSS/Http/ResponseCore.php
  13. 181 0
      sdk/OSS/Model/BucketInfo.php
  14. 39 0
      sdk/OSS/Model/BucketListInfo.php
  15. 85 0
      sdk/OSS/Model/BucketStat.php
  16. 99 0
      sdk/OSS/Model/CnameConfig.php
  17. 113 0
      sdk/OSS/Model/CorsConfig.php
  18. 150 0
      sdk/OSS/Model/CorsRule.php
  19. 65 0
      sdk/OSS/Model/DeleteMarkerInfo.php
  20. 41 0
      sdk/OSS/Model/DeleteObjectInfo.php
  21. 63 0
      sdk/OSS/Model/DeletedObjectInfo.php
  22. 64 0
      sdk/OSS/Model/ExtendWormConfig.php
  23. 37 0
      sdk/OSS/Model/GetLiveChannelHistory.php
  24. 68 0
      sdk/OSS/Model/GetLiveChannelInfo.php
  25. 107 0
      sdk/OSS/Model/GetLiveChannelStatus.php
  26. 64 0
      sdk/OSS/Model/InitiateWormConfig.php
  27. 88 0
      sdk/OSS/Model/LifecycleAction.php
  28. 107 0
      sdk/OSS/Model/LifecycleConfig.php
  29. 126 0
      sdk/OSS/Model/LifecycleRule.php
  30. 134 0
      sdk/OSS/Model/ListMultipartUploadInfo.php
  31. 97 0
      sdk/OSS/Model/ListPartsInfo.php
  32. 121 0
      sdk/OSS/Model/LiveChannelConfig.php
  33. 59 0
      sdk/OSS/Model/LiveChannelHistory.php
  34. 107 0
      sdk/OSS/Model/LiveChannelInfo.php
  35. 107 0
      sdk/OSS/Model/LiveChannelListInfo.php
  36. 86 0
      sdk/OSS/Model/LoggingConfig.php
  37. 93 0
      sdk/OSS/Model/ObjectInfo.php
  38. 126 0
      sdk/OSS/Model/ObjectListInfo.php
  39. 114 0
      sdk/OSS/Model/ObjectVersionInfo.php
  40. 162 0
      sdk/OSS/Model/ObjectVersionListInfo.php
  41. 63 0
      sdk/OSS/Model/PartInfo.php
  42. 36 0
      sdk/OSS/Model/PrefixInfo.php
  43. 93 0
      sdk/OSS/Model/RefererConfig.php
  44. 68 0
      sdk/OSS/Model/RequestPaymentConfig.php
  45. 77 0
      sdk/OSS/Model/RestoreConfig.php
  46. 91 0
      sdk/OSS/Model/ServerSideEncryptionConfig.php
  47. 76 0
      sdk/OSS/Model/StorageCapacityConfig.php
  48. 41 0
      sdk/OSS/Model/Tag.php
  49. 89 0
      sdk/OSS/Model/TaggingConfig.php
  50. 55 0
      sdk/OSS/Model/UploadInfo.php
  51. 67 0
      sdk/OSS/Model/VersioningConfig.php
  52. 76 0
      sdk/OSS/Model/WebsiteConfig.php
  53. 90 0
      sdk/OSS/Model/WormConfig.php
  54. 27 0
      sdk/OSS/Model/XmlConfig.php
  55. 3529 0
      sdk/OSS/OssClient.php
  56. 31 0
      sdk/OSS/Result/AclResult.php
  57. 27 0
      sdk/OSS/Result/AppendResult.php
  58. 19 0
      sdk/OSS/Result/BodyResult.php
  59. 21 0
      sdk/OSS/Result/CallbackResult.php
  60. 30 0
      sdk/OSS/Result/CopyObjectResult.php
  61. 39 0
      sdk/OSS/Result/DeleteObjectVersionsResult.php
  62. 27 0
      sdk/OSS/Result/DeleteObjectsResult.php
  63. 34 0
      sdk/OSS/Result/ExistResult.php
  64. 26 0
      sdk/OSS/Result/GetBucketEncryptionResult.php
  65. 37 0
      sdk/OSS/Result/GetBucketInfoResult.php
  66. 26 0
      sdk/OSS/Result/GetBucketRequestPaymentResult.php
  67. 26 0
      sdk/OSS/Result/GetBucketStatResult.php
  68. 26 0
      sdk/OSS/Result/GetBucketTagsResult.php
  69. 26 0
      sdk/OSS/Result/GetBucketVersioningResult.php
  70. 26 0
      sdk/OSS/Result/GetBucketWormResult.php
  71. 19 0
      sdk/OSS/Result/GetCnameResult.php
  72. 34 0
      sdk/OSS/Result/GetCorsResult.php
  73. 41 0
      sdk/OSS/Result/GetLifecycleResult.php
  74. 19 0
      sdk/OSS/Result/GetLiveChannelHistoryResult.php
  75. 19 0
      sdk/OSS/Result/GetLiveChannelInfoResult.php
  76. 19 0
      sdk/OSS/Result/GetLiveChannelStatusResult.php
  77. 30 0
      sdk/OSS/Result/GetLocationResult.php
  78. 41 0
      sdk/OSS/Result/GetLoggingResult.php
  79. 41 0
      sdk/OSS/Result/GetRefererResult.php
  80. 34 0
      sdk/OSS/Result/GetStorageCapacityResult.php
  81. 40 0
      sdk/OSS/Result/GetWebsiteResult.php
  82. 23 0
      sdk/OSS/Result/HeaderResult.php
  83. 27 0
      sdk/OSS/Result/InitiateBucketWormResult.php
  84. 29 0
      sdk/OSS/Result/InitiateMultipartUploadResult.php
  85. 32 0
      sdk/OSS/Result/ListBucketsResult.php
  86. 16 0
      sdk/OSS/Result/ListLiveChannelResult.php
  87. 55 0
      sdk/OSS/Result/ListMultipartUploadResult.php
  88. 96 0
      sdk/OSS/Result/ListObjectVersionsResult.php
  89. 71 0
      sdk/OSS/Result/ListObjectsResult.php
  90. 42 0
      sdk/OSS/Result/ListPartsResult.php
  91. 16 0
      sdk/OSS/Result/PutLiveChannelResult.php
  92. 20 0
      sdk/OSS/Result/PutSetDeleteResult.php
  93. 175 0
      sdk/OSS/Result/Result.php
  94. 24 0
      sdk/OSS/Result/SymlinkResult.php
  95. 28 0
      sdk/OSS/Result/UploadPartResult.php
  96. 12 0
      sdk/oss.php

+ 2 - 2
database/upload.php

@@ -93,8 +93,8 @@ return array
 		'size'		=> array
 		(
 			'type' 		=> 'int-11',
-			'name' 		=> '限制大小(字节)',
-			'default' 	=> '0',
+			'name' 		=> '限制大小(单位:M)',
+			'default' 	=> '2',
 			'desc' 		=> '请输入大小',
 			'match' 	=> 'option',
 			'update'	=> 'text',

+ 17 - 0
database/yun.php

@@ -3,6 +3,11 @@
  * 上传表
  */
 
+$type = array
+(
+    1 => '阿里云',
+    2 => '七牛云',
+);
 return array
 (
     # 表名
@@ -36,6 +41,18 @@ return array
             'list'      => true,
         ),
 
+        'type'     => array
+        (
+            'type'      => 'int-1',
+            'name'      => '存储类别',
+            'default'   => '2',
+            'desc'      => '存储类别',
+            'match'     => 'is_numeric',
+            'option'    => $type,
+            'update'    => 'radio',
+            'list'        => true,
+        ),
+
         'host'      => array
         (
             'type'      => 'varchar-800',

+ 2 - 2
lib/Store/Core.php

@@ -159,14 +159,14 @@ class Core
 		}
 
 		# 默认30M
-		$size = $this->config['size'] > 0 ? 1024*$this->config['size'] : 30*1024*1024;
+		$size = $this->config['size'] > 0 ? 1024*1024*$this->config['size'] : 30*1024*1024;
 
 		if (isset($this->data['file']['size'])) {
 			$this->size = $this->data['file']['size'];
 		
 			if (($size < $this->data['file']['size']) && $size > 0) {
 				$this->output['status'] = -1;
-				$this->output['message'] = '文件不能超过'.$size.'k';
+				$this->output['message'] = '文件不能超过'.(($size/1024)/1024).'MB';
 			} elseif ($this->config['width'] > 0 && $this->config['width'] < $this->limit[0]) {
 				$this->output['status'] = -1;
 				$this->output['message'] = '图片宽度不能超过' . $this->config['width'] . 'px';

+ 4 - 1
lib/Store/Handle.php

@@ -19,8 +19,11 @@ class Handle
 
         $yun = $config['yun'];
         if ($this->save_type >= 2) {
-            if ($yun == 1) {
+            $yun = Dever::db('upload/yun')->one($yun);
+            if ($yun['type'] == 2) {
                 $yun = 'Upload\Lib\Store\Qiniu';
+            } elseif ($yun['type'] == 1) {
+                $yun = 'Upload\Lib\Store\Oss';
             }
             
             $this->yun = new $yun($data);

+ 211 - 0
lib/Store/Oss.php

@@ -0,0 +1,211 @@
+<?php
+namespace Upload\Lib\Store;
+
+use Dever;
+Dever::apply('sdk/oss', 'upload');
+use OSS\OssClient;
+use OSS\Core\OssException;
+class Oss extends Core implements Config
+{
+    public $yun = true;
+    /**
+     * 创建文件和目录
+     * 
+     * @return mixed
+     */
+    public function save()
+    {
+        $config = Dever::db('upload/yun')->one($this->config['yun']);
+        $accessKey = $config['appkey'];
+        $secretKey = $config['appsecret'];
+        $endpoint = "http://oss-cn-beijing.aliyuncs.com";
+        $bucket = $this->config['bucket'];
+        $this->host = $config['host'];
+        $ossClient = new OssClient($accessKey, $secretKey, $endpoint);
+
+        $this->getName();
+
+        $file = $this->file;
+        if ($this->config['cover'] == 3) {
+            $this->name($this->output['file'] . '_' . microtime() . '_' . rand(0,1000))->file();
+            $file = $this->file;
+        }
+
+        $options = array();
+
+        if ($this->base64) {
+            $ret = $ossClient->putObject($bucket, $file, $this->data['file']['tmp_name'], $options);
+        } else {
+            $ret = $ossClient->uploadFile($bucket, $file, $this->data['file']['tmp_name']);
+        }
+
+        if (isset($ret['info']['url'])) {
+
+            $this->file = $ret['info']['url'];
+            $file = Dever::load('upload/file-name', array('where_name' => $this->name, 'where_upload' => $this->data['key'], 'rand' => time()));
+            
+            if (!$this->limit) {
+                $data = Dever::curl($this->output['url'] . '?x-oss-process=image/info');
+                if ($data) {
+                    $data = json_decode($data, true);
+                    if (isset($data['ImageWidth']['value'])) {
+                        $this->limit = array($data['ImageWidth']['value'], $data['ImageHeight']['value']);
+                        $this->size = $data['FileSize']['value'];
+                        $this->ext = '.' . $data['Format']['value'];
+                    }
+                }
+            }
+            
+            if (isset($file) && $file) {
+                $this->update($file['id']);
+                
+            } else {
+                $this->insert();
+            }
+
+            return $this->output['url'];
+        }
+    }
+
+    public function file()
+    {
+        if ($this->base64) {
+            $data = pathinfo($this->data['pic']);
+            $data['dirname'] = str_replace($this->host, '', $data['dirname']);
+            $this->file = $data['dirname'] . '/' . $data['basename'] . $this->name . $this->ext;
+        } else {
+            $this->file = $this->path . $this->name . $this->ext;
+        }
+
+        $this->output['file'] = $this->file;
+        $this->output['url'] = $this->host . $this->file;
+        return $this->output['file'];
+    }
+    
+    /**
+     * water
+     * 
+     * @return mixed
+     */
+    public function handle_w($id)
+    {
+        $config = Dever::load('upload/pic_water-one', $id);
+        if ($config) {
+            $this->name .= '_w' . $id;
+            
+            $water = array('water'=> $config['water'], 'position'=> ($config['water_position'] ? $config['water_position'] : 1));
+            
+            $this->img()->mark($this->output['file'], $water, true, $this->file());
+        }
+    }
+
+    /**
+     * compress
+     * 
+     * @return mixed
+     */
+    public function handle_p($num, $source = false, $dest = false)
+    {
+        if (!$source) {
+            $source = $this->output['file'];
+        }
+
+        if (!$dest) {
+            if (strpos($this->name, '_p') !== false) {
+                $temp = explode('_p', $this->name);
+                $this->name = $temp[0];
+            }
+
+            $file = $this->output['file'];
+            $url = $this->output['url'];
+
+            $this->name .= '_p' . $num;
+            $dest = $this->file();
+
+            $this->output['file'] = $file;
+            $this->output['url'] = $url;
+        }
+
+        $this->img()->setType('im');
+        $this->img()->compress($source, $num, $dest);
+    }
+    
+    /**
+     * webp
+     * 
+     * @return mixed
+     */
+    public function handle_wp($num, $source = false, $dest = false)
+    {
+        if (!$source) {
+            $source = $this->output['file'];
+        }
+
+
+        if (!$dest) {
+            if (strpos($this->name, '_wp') !== false) {
+                $temp = explode('_wp', $this->name);
+                $this->name = $temp[0];
+            }
+
+            $file = $this->output['file'];
+            $url = $this->output['url'];
+
+            $this->ext = '.webp';
+            $this->name .= '_wp' . $num;
+            $dest = $this->file();
+
+            $this->output['file'] = $file;
+            $this->output['url'] = $url;
+        }
+
+        $this->img()->setType('im');
+        $this->img()->webp($source, $num, $dest);
+    }
+
+    /**
+     * thumb
+     * 
+     * @return mixed
+     */
+    public function handle_t($id, $source = false, $dest = false, $path = '')
+    {
+        $config = Dever::load('upload/pic_thumb-one', $id);
+        if ($config) {
+
+            if (!$source) {
+                $source = $this->output['file'];
+            }
+
+            //?imageView2/2/w/360/h/270/format/png/q/75|imageslim
+            //?x-oss-process=image/resize,q_50
+           // $dest = $source . '?imageView2/2/w/'.$config['width'].'/h/'.$config['height'];
+            $dest = $source . '?x-oss-process=image/resize,m_lfit,w_'.$config['width'].',h_' . $config['height'];
+
+            if (isset($config['compress']) && $config['compress'] > 0) {
+                $dest .= ',q_' . $config['compress'];
+            }
+        }
+        return $dest;
+    }
+    
+    /**
+     * crop
+     * 
+     * @return mixed
+     */
+    public function handle_c($id, $source = false, $dest = false)
+    {
+        $config = Dever::load('upload/pic_crop-one', $id);
+        
+        if ($config) {
+
+            if (!$source) {
+                $source = $this->output['file'];
+            }
+
+            $dest = $source . '?x-oss-process=image/resize,fill,w_'.$config['width'].',h_' . $config['height'];
+        }
+        return $dest;
+    }
+}

+ 263 - 0
sdk/OSS/Core/MimeTypes.php

@@ -0,0 +1,263 @@
+<?php
+
+namespace OSS\Core;
+
+/**
+ * Class MimeTypes
+ *
+ * The map of a file's extention name to its corresponding Content-Type value in the file upload request.
+ * If the file extention name is not predefined in this class, getMimetype() returns null.
+ *
+ * @package OSS\Core
+ */
+class MimeTypes
+{
+    /**
+     * Get the content-type value of http header from the file's extension name.
+     *
+     * @param string $name Default file extension name.
+     * @return string content-type
+     */
+    public static function getMimetype($name)
+    {
+        $parts = explode('.', $name);
+        if (count($parts) > 1) {
+            $ext = strtolower(end($parts));
+            if (isset(self::$mime_types[$ext])) {
+                return self::$mime_types[$ext];
+            }
+        }
+
+        return null;
+    }
+
+    private static $mime_types = array(
+        'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+        'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
+        'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
+        'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
+        'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
+        'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
+        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+        'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
+        'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
+        'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
+        'apk' => 'application/vnd.android.package-archive',
+        'hqx' => 'application/mac-binhex40',
+        'cpt' => 'application/mac-compactpro',
+        'doc' => 'application/msword',
+        'ogg' => 'audio/ogg',
+        'pdf' => 'application/pdf',
+        'rtf' => 'text/rtf',
+        'mif' => 'application/vnd.mif',
+        'xls' => 'application/vnd.ms-excel',
+        'ppt' => 'application/vnd.ms-powerpoint',
+        'odc' => 'application/vnd.oasis.opendocument.chart',
+        'odb' => 'application/vnd.oasis.opendocument.database',
+        'odf' => 'application/vnd.oasis.opendocument.formula',
+        'odg' => 'application/vnd.oasis.opendocument.graphics',
+        'otg' => 'application/vnd.oasis.opendocument.graphics-template',
+        'odi' => 'application/vnd.oasis.opendocument.image',
+        'odp' => 'application/vnd.oasis.opendocument.presentation',
+        'otp' => 'application/vnd.oasis.opendocument.presentation-template',
+        'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
+        'ots' => 'application/vnd.oasis.opendocument.spreadsheet-template',
+        'odt' => 'application/vnd.oasis.opendocument.text',
+        'odm' => 'application/vnd.oasis.opendocument.text-master',
+        'ott' => 'application/vnd.oasis.opendocument.text-template',
+        'oth' => 'application/vnd.oasis.opendocument.text-web',
+        'sxw' => 'application/vnd.sun.xml.writer',
+        'stw' => 'application/vnd.sun.xml.writer.template',
+        'sxc' => 'application/vnd.sun.xml.calc',
+        'stc' => 'application/vnd.sun.xml.calc.template',
+        'sxd' => 'application/vnd.sun.xml.draw',
+        'std' => 'application/vnd.sun.xml.draw.template',
+        'sxi' => 'application/vnd.sun.xml.impress',
+        'sti' => 'application/vnd.sun.xml.impress.template',
+        'sxg' => 'application/vnd.sun.xml.writer.global',
+        'sxm' => 'application/vnd.sun.xml.math',
+        'sis' => 'application/vnd.symbian.install',
+        'wbxml' => 'application/vnd.wap.wbxml',
+        'wmlc' => 'application/vnd.wap.wmlc',
+        'wmlsc' => 'application/vnd.wap.wmlscriptc',
+        'bcpio' => 'application/x-bcpio',
+        'torrent' => 'application/x-bittorrent',
+        'bz2' => 'application/x-bzip2',
+        'vcd' => 'application/x-cdlink',
+        'pgn' => 'application/x-chess-pgn',
+        'cpio' => 'application/x-cpio',
+        'csh' => 'application/x-csh',
+        'dvi' => 'application/x-dvi',
+        'spl' => 'application/x-futuresplash',
+        'gtar' => 'application/x-gtar',
+        'hdf' => 'application/x-hdf',
+        'jar' => 'application/java-archive',
+        'jnlp' => 'application/x-java-jnlp-file',
+        'js' => 'application/javascript',
+        'json' => 'application/json',
+        'ksp' => 'application/x-kspread',
+        'chrt' => 'application/x-kchart',
+        'kil' => 'application/x-killustrator',
+        'latex' => 'application/x-latex',
+        'rpm' => 'application/x-rpm',
+        'sh' => 'application/x-sh',
+        'shar' => 'application/x-shar',
+        'swf' => 'application/x-shockwave-flash',
+        'sit' => 'application/x-stuffit',
+        'sv4cpio' => 'application/x-sv4cpio',
+        'sv4crc' => 'application/x-sv4crc',
+        'tar' => 'application/x-tar',
+        'tcl' => 'application/x-tcl',
+        'tex' => 'application/x-tex',
+        'man' => 'application/x-troff-man',
+        'me' => 'application/x-troff-me',
+        'ms' => 'application/x-troff-ms',
+        'ustar' => 'application/x-ustar',
+        'src' => 'application/x-wais-source',
+        'zip' => 'application/zip',
+        'm3u' => 'audio/x-mpegurl',
+        'ra' => 'audio/x-pn-realaudio',
+        'wav' => 'audio/x-wav',
+        'wma' => 'audio/x-ms-wma',
+        'wax' => 'audio/x-ms-wax',
+        'pdb' => 'chemical/x-pdb',
+        'xyz' => 'chemical/x-xyz',
+        'bmp' => 'image/bmp',
+        'gif' => 'image/gif',
+        'ief' => 'image/ief',
+        'png' => 'image/png',
+        'wbmp' => 'image/vnd.wap.wbmp',
+        'ras' => 'image/x-cmu-raster',
+        'pnm' => 'image/x-portable-anymap',
+        'pbm' => 'image/x-portable-bitmap',
+        'pgm' => 'image/x-portable-graymap',
+        'ppm' => 'image/x-portable-pixmap',
+        'rgb' => 'image/x-rgb',
+        'xbm' => 'image/x-xbitmap',
+        'xpm' => 'image/x-xpixmap',
+        'xwd' => 'image/x-xwindowdump',
+        'css' => 'text/css',
+        'rtx' => 'text/richtext',
+        'tsv' => 'text/tab-separated-values',
+        'jad' => 'text/vnd.sun.j2me.app-descriptor',
+        'wml' => 'text/vnd.wap.wml',
+        'wmls' => 'text/vnd.wap.wmlscript',
+        'etx' => 'text/x-setext',
+        'mxu' => 'video/vnd.mpegurl',
+        'flv' => 'video/x-flv',
+        'wm' => 'video/x-ms-wm',
+        'wmv' => 'video/x-ms-wmv',
+        'wmx' => 'video/x-ms-wmx',
+        'wvx' => 'video/x-ms-wvx',
+        'avi' => 'video/x-msvideo',
+        'movie' => 'video/x-sgi-movie',
+        'ice' => 'x-conference/x-cooltalk',
+        '3gp' => 'video/3gpp',
+        'ai' => 'application/postscript',
+        'aif' => 'audio/x-aiff',
+        'aifc' => 'audio/x-aiff',
+        'aiff' => 'audio/x-aiff',
+        'asc' => 'text/plain',
+        'atom' => 'application/atom+xml',
+        'au' => 'audio/basic',
+        'bin' => 'application/octet-stream',
+        'cdf' => 'application/x-netcdf',
+        'cgm' => 'image/cgm',
+        'class' => 'application/octet-stream',
+        'dcr' => 'application/x-director',
+        'dif' => 'video/x-dv',
+        'dir' => 'application/x-director',
+        'djv' => 'image/vnd.djvu',
+        'djvu' => 'image/vnd.djvu',
+        'dll' => 'application/octet-stream',
+        'dmg' => 'application/octet-stream',
+        'dms' => 'application/octet-stream',
+        'dtd' => 'application/xml-dtd',
+        'dv' => 'video/x-dv',
+        'dxr' => 'application/x-director',
+        'eps' => 'application/postscript',
+        'exe' => 'application/octet-stream',
+        'ez' => 'application/andrew-inset',
+        'gram' => 'application/srgs',
+        'grxml' => 'application/srgs+xml',
+        'gz' => 'application/x-gzip',
+        'htm' => 'text/html',
+        'html' => 'text/html',
+        'ico' => 'image/x-icon',
+        'ics' => 'text/calendar',
+        'ifb' => 'text/calendar',
+        'iges' => 'model/iges',
+        'igs' => 'model/iges',
+        'jp2' => 'image/jp2',
+        'jpe' => 'image/jpeg',
+        'jpeg' => 'image/jpeg',
+        'jpg' => 'image/jpeg',
+        'kar' => 'audio/midi',
+        'lha' => 'application/octet-stream',
+        'lzh' => 'application/octet-stream',
+        'm4a' => 'audio/mp4a-latm',
+        'm4p' => 'audio/mp4a-latm',
+        'm4u' => 'video/vnd.mpegurl',
+        'm4v' => 'video/x-m4v',
+        'mac' => 'image/x-macpaint',
+        'mathml' => 'application/mathml+xml',
+        'mesh' => 'model/mesh',
+        'mid' => 'audio/midi',
+        'midi' => 'audio/midi',
+        'mov' => 'video/quicktime',
+        'mp2' => 'audio/mpeg',
+        'mp3' => 'audio/mpeg',
+        'mp4' => 'video/mp4',
+        'mpe' => 'video/mpeg',
+        'mpeg' => 'video/mpeg',
+        'mpg' => 'video/mpeg',
+        'mpga' => 'audio/mpeg',
+        'msh' => 'model/mesh',
+        'nc' => 'application/x-netcdf',
+        'oda' => 'application/oda',
+        'ogv' => 'video/ogv',
+        'pct' => 'image/pict',
+        'pic' => 'image/pict',
+        'pict' => 'image/pict',
+        'pnt' => 'image/x-macpaint',
+        'pntg' => 'image/x-macpaint',
+        'ps' => 'application/postscript',
+        'qt' => 'video/quicktime',
+        'qti' => 'image/x-quicktime',
+        'qtif' => 'image/x-quicktime',
+        'ram' => 'audio/x-pn-realaudio',
+        'rdf' => 'application/rdf+xml',
+        'rm' => 'application/vnd.rn-realmedia',
+        'roff' => 'application/x-troff',
+        'sgm' => 'text/sgml',
+        'sgml' => 'text/sgml',
+        'silo' => 'model/mesh',
+        'skd' => 'application/x-koan',
+        'skm' => 'application/x-koan',
+        'skp' => 'application/x-koan',
+        'skt' => 'application/x-koan',
+        'smi' => 'application/smil',
+        'smil' => 'application/smil',
+        'snd' => 'audio/basic',
+        'so' => 'application/octet-stream',
+        'svg' => 'image/svg+xml',
+        't' => 'application/x-troff',
+        'texi' => 'application/x-texinfo',
+        'texinfo' => 'application/x-texinfo',
+        'tif' => 'image/tiff',
+        'tiff' => 'image/tiff',
+        'tr' => 'application/x-troff',
+        'txt' => 'text/plain',
+        'vrml' => 'model/vrml',
+        'vxml' => 'application/voicexml+xml',
+        'webm' => 'video/webm',
+        'webp' => 'image/webp',
+        'wrl' => 'model/vrml',
+        'xht' => 'application/xhtml+xml',
+        'xhtml' => 'application/xhtml+xml',
+        'xml' => 'application/xml',
+        'xsl' => 'application/xml',
+        'xslt' => 'application/xslt+xml',
+        'xul' => 'application/vnd.mozilla.xul+xml',
+    );
+}

+ 54 - 0
sdk/OSS/Core/OssException.php

@@ -0,0 +1,54 @@
+<?php
+
+namespace OSS\Core;
+
+/**
+ * Class OssException
+ *
+ * This is the class that OSSClient is expected to thrown, which the caller needs to handle properly.
+ * It has the OSS specific errors which is useful for troubleshooting.
+ *
+ * @package OSS\Core
+ */
+class OssException extends \Exception
+{
+    private $details = array();
+
+    function __construct($details)
+    {
+        if (is_array($details)) {
+            $message = $details['code'] . ': ' . $details['message']
+                     . ' RequestId: ' . $details['request-id'];
+            parent::__construct($message);
+            $this->details = $details;
+        } else {
+            $message = $details;
+            parent::__construct($message);
+        }
+    }
+
+    public function getHTTPStatus()
+    {
+        return isset($this->details['status']) ? $this->details['status'] : '';
+    }
+
+    public function getRequestId()
+    {
+        return isset($this->details['request-id']) ? $this->details['request-id'] : '';
+    }
+
+    public function getErrorCode()
+    {
+        return isset($this->details['code']) ? $this->details['code'] : '';
+    }
+
+    public function getErrorMessage()
+    {
+        return isset($this->details['message']) ? $this->details['message'] : '';
+    }
+
+    public function getDetails()
+    {
+        return isset($this->details['body']) ? $this->details['body'] : '';
+    }
+}

+ 529 - 0
sdk/OSS/Core/OssUtil.php

@@ -0,0 +1,529 @@
+<?php
+
+namespace OSS\Core;
+
+/**
+ * Class OssUtil
+ *
+ * Oss Util class for OssClient. The caller could use it for formating the result from OssClient.
+ *
+ * @package OSS
+ */
+class OssUtil
+{
+    const OSS_CONTENT = 'content';
+    const OSS_LENGTH = 'length';
+    const OSS_HEADERS = 'headers';
+    const OSS_MAX_OBJECT_GROUP_VALUE = 1000;
+    const OSS_MAX_PART_SIZE = 5368709120; // 5GB
+    const OSS_MID_PART_SIZE = 10485760; // 10MB
+    const OSS_MIN_PART_SIZE = 102400; // 100KB
+
+    /**
+     * Generate query params
+     *
+     * @param array $options: a key-value pair array.
+     * @return string: the key-value list in the format such as key1=value1&key2=value2
+     */
+    public static function toQueryString($options = array())
+    {
+        $temp = array();
+        uksort($options, 'strnatcasecmp');
+        foreach ($options as $key => $value) {
+            if (is_string($key) && !is_array($value)) {
+                $temp[] = rawurlencode($key) . '=' . rawurlencode($value);
+            }
+        }
+        return implode('&', $temp);
+    }
+
+    /**
+     * Html encoding '<', '>', '&', '\', '"' in subject parameter. 
+     *
+     * @param string $subject
+     * @return string
+     */
+    public static function sReplace($subject)
+    {
+        $search = array('<', '>', '&', '\'', '"');
+        $replace = array('&lt;', '&gt;', '&amp;', '&apos;', '&quot;');
+        return str_replace($search, $replace, $subject);
+    }
+
+    /**
+     * Check whether the string includes any chinese character
+     *
+     * @param $str
+     * @return int
+     */
+    public static function chkChinese($str)
+    {
+        return preg_match('/[\x80-\xff]./', $str);
+    }
+
+    /**
+     * Checks if the string is encoded by GB2312.
+     *
+     * @param string $str
+     * @return boolean false UTF-8 encoding  TRUE GB2312 encoding
+     */
+    public static function isGb2312($str)
+    {
+        for ($i = 0; $i < strlen($str); $i++) {
+            $v = ord($str[$i]);
+            if ($v > 127) {
+                if (($v >= 228) && ($v <= 233)) {
+                    if (($i + 2) >= (strlen($str) - 1)) return true;  // not enough characters
+                    $v1 = ord($str[$i + 1]);
+                    $v2 = ord($str[$i + 2]);
+                    if (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191))
+                        return false;
+                    else
+                        return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Checks if the string is encoded by GBK
+     *
+     * @param string $str
+     * @param boolean $gbk
+     * @return boolean
+     */
+    public static function checkChar($str, $gbk = true)
+    {
+        for ($i = 0; $i < strlen($str); $i++) {
+            $v = ord($str[$i]);
+            if ($v > 127) {
+                if (($v >= 228) && ($v <= 233)) {
+                    if (($i + 2) >= (strlen($str) - 1)) return $gbk ? true : FALSE;  // not enough characters
+                    $v1 = ord($str[$i + 1]);
+                    $v2 = ord($str[$i + 2]);
+                    if ($gbk) {
+                        return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? FALSE : TRUE;//GBK
+                    } else {
+                        return (($v1 >= 128) && ($v1 <= 191) && ($v2 >= 128) && ($v2 <= 191)) ? TRUE : FALSE;
+                    }
+                }
+            }
+        }
+        return $gbk ? TRUE : FALSE;
+    }
+
+    /**
+     * Checks if the bucket name is valid
+     * bucket naming rules
+     * 1. Can only include lowercase letters, numbers, or dashes
+     * 2. Must start and end with lowercase letters or numbers
+     * 3. Must be within a length from 3 to 63 bytes.
+     *
+     * @param string $bucket Bucket name
+     * @return boolean
+     */
+    public static function validateBucket($bucket)
+    {
+        $pattern = '/^[a-z0-9][a-z0-9-]{2,62}$/';
+        if (!preg_match($pattern, $bucket)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks if object name is valid
+     * object naming rules:
+     * 1. Must be within a length from 1 to 1023 bytes
+     * 2. Cannot start with '/' or '\\'.
+     * 3. Must be encoded in UTF-8.
+     *
+     * @param string $object Object名称
+     * @return boolean
+     */
+    public static function validateObject($object)
+    {
+        $pattern = '/^.{1,1023}$/';
+        if (!preg_match($pattern, $object) ||
+            self::startsWith($object, '/') || self::startsWith($object, '\\')
+        ) {
+            return false;
+        }
+        return true;
+    }
+
+
+    /**
+     * Checks if $str starts with $findMe
+     *
+     * @param string $str
+     * @param string $findMe
+     * @return bool
+     */
+    public static function startsWith($str, $findMe)
+    {
+        if (strpos($str, $findMe) === 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    /**
+     * Generate the xml message of createBucketXmlBody.
+     *
+     * @param string $storageClass
+     * @return string
+     */
+    public static function createBucketXmlBody($storageClass)
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><CreateBucketConfiguration></CreateBucketConfiguration>');
+        $xml->addChild('StorageClass',  $storageClass);
+        return $xml->asXML();
+    }
+
+    /**
+     * validate $options
+     *
+     * @param array $options
+     * @throws OssException
+     * @return boolean
+     */
+    public static function validateOptions($options)
+    {
+        //$options
+        if ($options != NULL && !is_array($options)) {
+            throw new OssException ($options . ':' . 'option must be array');
+        }
+    }
+
+    /**
+     * check whether the Content is valid.
+     *
+     * @param $content string
+     * @throws OssException
+     */
+    public static function validateContent($content)
+    {
+        if (empty($content)) {
+            throw new OssException("http body content is invalid");
+        }
+    }
+
+    /**
+     * Check if BUCKET/OBJECT/OBJECT GROUP is empty.
+     *
+     * @param  string $name
+     * @param  string $errMsg
+     * @throws OssException
+     * @return void
+     */
+    public static function throwOssExceptionWithMessageIfEmpty($name, $errMsg)
+    {
+        if (empty($name)) {
+            if (is_string($name) && $name == '0')
+                return;
+            throw new OssException($errMsg);
+        }
+    }
+
+    /**
+     * This is a method for test only. DO NOT USE.
+     *
+     * @param $filename
+     * @param $size
+     */
+    public static function generateFile($filename, $size)
+    {
+        if (file_exists($filename) && $size == filesize($filename)) {
+            echo $filename . " already exists, no need to create again. ";
+            return;
+        }
+        $part_size = 1 * 1024 * 1024;
+        $fp = fopen($filename, "w");
+        $characters = <<<BBB
+0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+BBB;
+
+        $charactersLength = strlen($characters);
+        if ($fp) {
+            while ($size > 0) {
+                if ($size < $part_size) {
+                    $write_size = $size;
+                } else {
+                    $write_size = $part_size;
+                }
+                $size -= $write_size;
+                $a = $characters[rand(0, $charactersLength - 1)];
+                $content = str_repeat($a, $write_size);
+                $flag = fwrite($fp, $content);
+                if (!$flag) {
+                    echo "write to " . $filename . " failed. <br>";
+                    break;
+                }
+            }
+        } else {
+            echo "open " . $filename . " failed. <br>";
+        }
+        fclose($fp);
+    }
+
+    /**
+     * Get MD5 of the file.
+     *
+     * @param $filename
+     * @param $from_pos
+     * @param $to_pos
+     * @return string
+     */
+    public static function getMd5SumForFile($filename, $from_pos, $to_pos)
+    {
+        $content_md5 = "";
+        if (($to_pos - $from_pos) > self::OSS_MAX_PART_SIZE) {
+            return $content_md5;
+        }
+        $filesize = filesize($filename);
+        if ($from_pos >= $filesize || $to_pos >= $filesize || $from_pos < 0 || $to_pos < 0) {
+            return $content_md5;
+        }
+
+        $total_length = $to_pos - $from_pos + 1;
+        $buffer = 8192;
+        $left_length = $total_length;
+        if (!file_exists($filename)) {
+            return $content_md5;
+        }
+
+        if (false === $fh = fopen($filename, 'rb')) {
+            return $content_md5;
+        }
+
+        fseek($fh, $from_pos);
+        $data = '';
+        while (!feof($fh)) {
+            if ($left_length >= $buffer) {
+                $read_length = $buffer;
+            } else {
+                $read_length = $left_length;
+            }
+            if ($read_length <= 0) {
+                break;
+            } else {
+                $data .= fread($fh, $read_length);
+                $left_length = $left_length - $read_length;
+            }
+        }
+        fclose($fh);
+        $content_md5 = base64_encode(md5($data, true));
+        return $content_md5;
+    }
+
+    /**
+     * Check if the OS is Windows. The default encoding in Windows is GBK.
+     *
+     * @return bool
+     */
+    public static function isWin()
+    {
+        return strtoupper(substr(PHP_OS, 0, 3)) == "WIN";
+    }
+
+    /**
+     * Encodes the file path from GBK to UTF-8.
+     * The default encoding in Windows is GBK. 
+     * And if the file path is in Chinese, the file would not be found without the transcoding to UTF-8.
+     *
+     * @param $file_path
+     * @return string
+     */
+    public static function encodePath($file_path)
+    {
+        if (self::chkChinese($file_path) && self::isWin()) {
+            $file_path = iconv('utf-8', 'gbk', $file_path);
+        }
+        return $file_path;
+    }
+
+    /**
+     * Check if the endpoint is in the IPv4 format, such as xxx.xxx.xxx.xxx:port or xxx.xxx.xxx.xxx.
+     *
+     * @param string $endpoint The endpoint to check.
+     * @return boolean
+     */
+    public static function isIPFormat($endpoint)
+    {
+        $ip_array = explode(":", $endpoint);
+        $hostname = $ip_array[0];
+        $ret = filter_var($hostname, FILTER_VALIDATE_IP);
+        if (!$ret) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * Get the host:port from endpoint.
+     *
+     * @param string $endpoint the endpoint.
+     * @return boolean
+     */
+    public static function getHostPortFromEndpoint($endpoint)
+    {
+        $str = $endpoint;
+        $pos = strpos($str, "://");
+        if ($pos !== false) {
+            $str = substr($str, $pos+3);
+        }
+    
+        $pos = strpos($str, '#');
+        if ($pos !== false) {
+            $str = substr($str, 0, $pos);
+        }
+    
+        $pos = strpos($str, '?');
+        if ($pos !== false) {
+            $str = substr($str, 0, $pos);
+        }
+    
+        $pos = strpos($str, '/');
+        if ($pos !== false) {
+            $str = substr($str, 0, $pos);
+        }
+    
+        $pos = strpos($str, '@');
+        if ($pos !== false) {
+            $str = substr($str, $pos+1);
+        }
+       
+        if (!preg_match('/^[\w.-]+(:[0-9]+)?$/', $str)) {
+            throw new OssException("endpoint is invalid:" . $endpoint);
+        }
+
+        return $str;
+    }
+
+    /**
+     * Generate the xml message of DeleteMultiObjects.
+     *
+     * @param string[] $objects
+     * @param bool $quiet
+     * @return string
+     */
+    public static function createDeleteObjectsXmlBody($objects, $quiet)
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><Delete></Delete>');
+        $xml->addChild('Quiet', $quiet);
+        foreach ($objects as $object) {
+            $sub_object = $xml->addChild('Object');
+            $object = OssUtil::sReplace($object);
+            $sub_object->addChild('Key', $object);
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     * Generate the xml message of DeleteMultiObjects.
+     *
+     * @param DeleteObjectInfo[] $objects
+     * @param bool $quiet
+     * @return string
+     */
+    public static function createDeleteObjectVersionsXmlBody($objects, $quiet)
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><Delete></Delete>');
+        $xml->addChild('Quiet', $quiet);
+        foreach ($objects as $object) {
+            $sub_object = $xml->addChild('Object');
+            $key = OssUtil::sReplace($object->getKey());
+            $sub_object->addChild('Key', $key);
+            if (!empty($object->getVersionId())) {
+                $sub_object->addChild('VersionId', $object->getVersionId());
+            }
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     * Generate the xml message of CompleteMultipartUpload.
+     *
+     * @param array[] $listParts
+     * @return string
+     */
+    public static function createCompleteMultipartUploadXmlBody($listParts)
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CompleteMultipartUpload></CompleteMultipartUpload>');
+        foreach ($listParts as $node) {
+            $part = $xml->addChild('Part');
+            $part->addChild('PartNumber', $node['PartNumber']);
+            $part->addChild('ETag', $node['ETag']);
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     * Read the directory, return a associative array in which the MD5 is the named key and the <path,filanme> is the value.
+     *
+     * @param string $dir
+     * @param string $exclude
+     * @param bool $recursive
+     * @return string[]
+     */
+    public static function readDir($dir, $exclude = ".|..|.svn|.git", $recursive = false)
+    {
+        $file_list_array = array();
+        $base_path = $dir;
+        $exclude_array = explode("|", $exclude);
+        $exclude_array = array_unique(array_merge($exclude_array, array('.', '..')));
+
+        if ($recursive) {
+            foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir)) as $new_file) {
+                if ($new_file->isDir()) continue;
+                $object = str_replace($base_path, '', $new_file);
+                if (!in_array(strtolower($object), $exclude_array)) {
+                    $object = ltrim($object, '/');
+                    if (is_file($new_file)) {
+                        $key = md5($new_file . $object, false);
+                        $file_list_array[$key] = array('path' => $new_file, 'file' => $object,);
+                    }
+                }
+            }
+        } else if ($handle = opendir($dir)) {
+            while (false !== ($file = readdir($handle))) {
+                if (!in_array(strtolower($file), $exclude_array)) {
+                    $new_file = $dir . '/' . $file;
+                    $object = $file;
+                    $object = ltrim($object, '/');
+                    if (is_file($new_file)) {
+                        $key = md5($new_file . $object, false);
+                        $file_list_array[$key] = array('path' => $new_file, 'file' => $object,);
+                    }
+                }
+            }
+            closedir($handle);
+        }
+        return $file_list_array;
+    }
+
+    /**
+     * Decode key based on the encoding type
+     *
+     * @param string $key
+     * @param string $encoding
+     * @return string
+     */
+    public static function decodeKey($key, $encoding)
+    {
+        if ($encoding == "") {
+            return $key;
+        }
+
+        if ($encoding == "url") {
+            return rawurldecode($key);
+        } else {
+            throw new OssException("Unrecognized encoding type: " . $encoding);
+        }
+    }
+}

+ 25 - 0
sdk/OSS/Http/LICENSE

@@ -0,0 +1,25 @@
+Copyright (c) 2006-2010 Ryan Parman, Foleeo Inc., and contributors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are
+permitted provided that the following conditions are met:
+
+	* Redistributions of source code must retain the above copyright notice, this list of
+	  conditions and the following disclaimer.
+
+	* Redistributions in binary form must reproduce the above copyright notice, this list
+	  of conditions and the following disclaimer in the documentation and/or other materials
+	  provided with the distribution.
+
+	* Neither the name of Ryan Parman, Foleeo Inc. nor the names of its contributors may be used to
+	  endorse or promote products derived from this software without specific prior written
+	  permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
+AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.

+ 897 - 0
sdk/OSS/Http/RequestCore.php

@@ -0,0 +1,897 @@
+<?php
+namespace OSS\Http;
+
+
+/**
+ * Handle all HTTP requests using cURL and manages the responses.
+ *
+ * @version 2011.06.07
+ * @copyright 2006-2011 Ryan Parman
+ * @copyright 2006-2010 Foleeo Inc.
+ * @copyright 2010-2011 Amazon.com, Inc. or its affiliates.
+ * @copyright 2008-2011 Contributors
+ * @license http://opensource.org/licenses/bsd-license.php Simplified BSD License
+ */
+class RequestCore
+{
+    /**
+     * The URL being requested.
+     */
+    public $request_url;
+
+    /**
+     * The headers being sent in the request.
+     */
+    public $request_headers;
+   
+    /**
+     * The raw response callback headers
+     */
+    public $response_raw_headers;
+
+    /**
+     * Response body when error occurs
+     */
+    public $response_error_body;
+
+    /**
+     *The hander of write file
+     */
+    public $write_file_handle; 
+
+    /**
+     * The body being sent in the request.
+     */
+    public $request_body;
+
+    /**
+     * The response returned by the request.
+     */
+    public $response;
+
+    /**
+     * The headers returned by the request.
+     */
+    public $response_headers;
+
+    /**
+     * The body returned by the request.
+     */
+    public $response_body;
+
+    /**
+     * The HTTP status code returned by the request.
+     */
+    public $response_code;
+
+    /**
+     * Additional response data.
+     */
+    public $response_info;
+
+    /**
+     * The method by which the request is being made.
+     */
+    public $method;
+
+    /**
+     * Store the proxy settings to use for the request.
+     */
+    public $proxy = null;
+
+    /**
+     * The username to use for the request.
+     */
+    public $username = null;
+
+    /**
+     * The password to use for the request.
+     */
+    public $password = null;
+
+    /**
+     * Custom CURLOPT settings.
+     */
+    public $curlopts = null;
+
+    /**
+     * The state of debug mode.
+     */
+    public $debug_mode = false;
+
+    /**
+     * The default class to use for HTTP Requests (defaults to <RequestCore>).
+     */
+    public $request_class = 'OSS\Http\RequestCore';
+
+    /**
+     * The default class to use for HTTP Responses (defaults to <ResponseCore>).
+     */
+    public $response_class = 'OSS\Http\ResponseCore';
+
+    /**
+     * Default useragent string to use.
+     */
+    public $useragent = 'RequestCore/1.4.3';
+
+    /**
+     * File to read from while streaming up.
+     */
+    public $read_file = null;
+
+    /**
+     * The resource to read from while streaming up.
+     */
+    public $read_stream = null;
+
+    /**
+     * The size of the stream to read from.
+     */
+    public $read_stream_size = null;
+
+    /**
+     * The length already read from the stream.
+     */
+    public $read_stream_read = 0;
+
+    /**
+     * File to write to while streaming down.
+     */
+    public $write_file = null;
+
+    /**
+     * The resource to write to while streaming down.
+     */
+    public $write_stream = null;
+
+    /**
+     * Stores the intended starting seek position.
+     */
+    public $seek_position = null;
+
+    /**
+     * The location of the cacert.pem file to use.
+     */
+    public $cacert_location = false;
+
+    /**
+     * The state of SSL certificate verification.
+     */
+    public $ssl_verification = true;
+
+    /**
+     * The user-defined callback function to call when a stream is read from.
+     */
+    public $registered_streaming_read_callback = null;
+
+    /**
+     * The user-defined callback function to call when a stream is written to.
+     */
+    public $registered_streaming_write_callback = null;
+
+    /**
+     * The request timeout time, which is 5,184,000 seconds,that is, 6 days by default
+     *
+     * @var int
+     */
+    public $timeout = 5184000;
+
+    /**
+     * The connection timeout time, which is 10 seconds by default
+     *
+     * @var int
+     */
+    public $connect_timeout = 10;
+
+    /*%******************************************************************************************%*/
+    // CONSTANTS
+
+    /**
+     * GET HTTP Method
+     */
+    const HTTP_GET = 'GET';
+
+    /**
+     * POST HTTP Method
+     */
+    const HTTP_POST = 'POST';
+
+    /**
+     * PUT HTTP Method
+     */
+    const HTTP_PUT = 'PUT';
+
+    /**
+     * DELETE HTTP Method
+     */
+    const HTTP_DELETE = 'DELETE';
+
+    /**
+     * HEAD HTTP Method
+     */
+    const HTTP_HEAD = 'HEAD';
+
+
+    /*%******************************************************************************************%*/
+    // CONSTRUCTOR/DESTRUCTOR
+
+    /**
+     * Construct a new instance of this class.
+     *
+     * @param string $url (Optional) The URL to request or service endpoint to query.
+     * @param string $proxy (Optional) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+     * @param array $helpers (Optional) An associative array of classnames to use for request, and response functionality. Gets passed in automatically by the calling class.
+     * @return $this A reference to the current instance.
+     */
+    public function __construct($url = null, $proxy = null, $helpers = null)
+    {
+        // Set some default values.
+        $this->request_url = $url;
+        $this->method = self::HTTP_GET;
+        $this->request_headers = array();
+        $this->request_body = '';
+
+        // Set a new Request class if one was set.
+        if (isset($helpers['request']) && !empty($helpers['request'])) {
+            $this->request_class = $helpers['request'];
+        }
+
+        // Set a new Request class if one was set.
+        if (isset($helpers['response']) && !empty($helpers['response'])) {
+            $this->response_class = $helpers['response'];
+        }
+
+        if ($proxy) {
+            $this->set_proxy($proxy);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Destruct the instance. Closes opened file handles.
+     *
+     * @return $this A reference to the current instance.
+     */
+    public function __destruct()
+    {
+        if (isset($this->read_file) && isset($this->read_stream)) {
+            fclose($this->read_stream);
+        }
+
+        if (isset($this->write_file) && isset($this->write_stream)) {
+            fclose($this->write_stream);
+        }
+
+        return $this;
+    }
+
+
+    /*%******************************************************************************************%*/
+    // REQUEST METHODS
+
+    /**
+     * Set the credentials to use for authentication.
+     *
+     * @param string $user (Required) The username to authenticate with.
+     * @param string $pass (Required) The password to authenticate with.
+     * @return $this A reference to the current instance.
+     */
+    public function set_credentials($user, $pass)
+    {
+        $this->username = $user;
+        $this->password = $pass;
+        return $this;
+    }
+
+    /**
+     * Add a custom HTTP header to the cURL request.
+     *
+     * @param string $key (Required) The custom HTTP header to set.
+     * @param mixed $value (Required) The value to assign to the custom HTTP header.
+     * @return $this A reference to the current instance.
+     */
+    public function add_header($key, $value)
+    {
+        $this->request_headers[$key] = $value;
+        return $this;
+    }
+
+    /**
+     * Remove an HTTP header from the cURL request.
+     *
+     * @param string $key (Required) The custom HTTP header to set.
+     * @return $this A reference to the current instance.
+     */
+    public function remove_header($key)
+    {
+        if (isset($this->request_headers[$key])) {
+            unset($this->request_headers[$key]);
+        }
+        return $this;
+    }
+
+    /**
+     * Set the method type for the request.
+     *
+     * @param string $method (Required) One of the following constants: <HTTP_GET>, <HTTP_POST>, <HTTP_PUT>, <HTTP_HEAD>, <HTTP_DELETE>.
+     * @return $this A reference to the current instance.
+     */
+    public function set_method($method)
+    {
+        $this->method = strtoupper($method);
+        return $this;
+    }
+
+    /**
+     * Set a custom useragent string for the class.
+     *
+     * @param string $ua (Required) The useragent string to use.
+     * @return $this A reference to the current instance.
+     */
+    public function set_useragent($ua)
+    {
+        $this->useragent = $ua;
+        return $this;
+    }
+
+    /**
+     * Set the body to send in the request.
+     *
+     * @param string $body (Required) The textual content to send along in the body of the request.
+     * @return $this A reference to the current instance.
+     */
+    public function set_body($body)
+    {
+        $this->request_body = $body;
+        return $this;
+    }
+
+    /**
+     * Set the URL to make the request to.
+     *
+     * @param string $url (Required) The URL to make the request to.
+     * @return $this A reference to the current instance.
+     */
+    public function set_request_url($url)
+    {
+        $this->request_url = $url;
+        return $this;
+    }
+
+    /**
+     * Set additional CURLOPT settings. These will merge with the default settings, and override if
+     * there is a duplicate.
+     *
+     * @param array $curlopts (Optional) A set of key-value pairs that set `CURLOPT` options. These will merge with the existing CURLOPTs, and ones passed here will override the defaults. Keys should be the `CURLOPT_*` constants, not strings.
+     * @return $this A reference to the current instance.
+     */
+    public function set_curlopts($curlopts)
+    {
+        $this->curlopts = $curlopts;
+        return $this;
+    }
+
+    /**
+     * Set the length in bytes to read from the stream while streaming up.
+     *
+     * @param integer $size (Required) The length in bytes to read from the stream.
+     * @return $this A reference to the current instance.
+     */
+    public function set_read_stream_size($size)
+    {
+        $this->read_stream_size = $size;
+
+        return $this;
+    }
+
+    /**
+     * Set the resource to read from while streaming up. Reads the stream from its current position until
+     * EOF or `$size` bytes have been read. If `$size` is not given it will be determined by <php:fstat()> and
+     * <php:ftell()>.
+     *
+     * @param resource $resource (Required) The readable resource to read from.
+     * @param integer $size (Optional) The size of the stream to read.
+     * @return $this A reference to the current instance.
+     */
+    public function set_read_stream($resource, $size = null)
+    {
+        if (!isset($size) || $size < 0) {
+            $stats = fstat($resource);
+
+            if ($stats && $stats['size'] >= 0) {
+                $position = ftell($resource);
+
+                if ($position !== false && $position >= 0) {
+                    $size = $stats['size'] - $position;
+                }
+            }
+        }
+
+        $this->read_stream = $resource;
+
+        return $this->set_read_stream_size($size);
+    }
+
+    /**
+     * Set the file to read from while streaming up.
+     *
+     * @param string $location (Required) The readable location to read from.
+     * @return $this A reference to the current instance.
+     */
+    public function set_read_file($location)
+    {
+        $this->read_file = $location;
+        $read_file_handle = fopen($location, 'r');
+
+        return $this->set_read_stream($read_file_handle);
+    }
+
+    /**
+     * Set the resource to write to while streaming down.
+     *
+     * @param resource $resource (Required) The writeable resource to write to.
+     * @return $this A reference to the current instance.
+     */
+    public function set_write_stream($resource)
+    {
+        $this->write_stream = $resource;
+
+        return $this;
+    }
+
+    /**
+     * Set the file to write to while streaming down.
+     *
+     * @param string $location (Required) The writeable location to write to.
+     * @return $this A reference to the current instance.
+     */
+    public function set_write_file($location)
+    {
+        $this->write_file = $location;
+    }
+
+    /**
+     * Set the proxy to use for making requests.
+     *
+     * @param string $proxy (Required) The faux-url to use for proxy settings. Takes the following format: `proxy://user:pass@hostname:port`
+     * @return $this A reference to the current instance.
+     */
+    public function set_proxy($proxy)
+    {
+        $proxy = parse_url($proxy);
+        $proxy['user'] = isset($proxy['user']) ? $proxy['user'] : null;
+        $proxy['pass'] = isset($proxy['pass']) ? $proxy['pass'] : null;
+        $proxy['port'] = isset($proxy['port']) ? $proxy['port'] : null;
+        $this->proxy = $proxy;
+        return $this;
+    }
+
+    /**
+     * Set the intended starting seek position.
+     *
+     * @param integer $position (Required) The byte-position of the stream to begin reading from.
+     * @return $this A reference to the current instance.
+     */
+    public function set_seek_position($position)
+    {
+        $this->seek_position = isset($position) ? (integer)$position : null;
+
+        return $this;
+    }
+
+    /**
+     * A callback function that is invoked by cURL for streaming up.
+     *
+     * @param resource $curl_handle (Required) The cURL handle for the request.
+     * @param resource $header_content (Required) The header callback result.
+     * @return headers from a stream.
+     */
+   public function streaming_header_callback($curl_handle, $header_content)
+   {
+        $code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
+
+        if (isset($this->write_file) && intval($code) / 100 == 2 && !isset($this->write_file_handle))
+        {
+            $this->write_file_handle = fopen($this->write_file, 'w');
+            $this->set_write_stream($this->write_file_handle);
+        }
+
+        $this->response_raw_headers .= $header_content;
+        return strlen($header_content); 
+    }
+        
+
+    /**
+     * Register a callback function to execute whenever a data stream is read from using
+     * <CFRequest::streaming_read_callback()>.
+     *
+     * The user-defined callback function should accept three arguments:
+     *
+     * <ul>
+     *    <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+     *    <li><code>$file_handle</code> - <code>resource</code> - Required - The file handle resource that represents the file on the local file system.</li>
+     *    <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+     * </ul>
+     *
+     * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+     *    <li>The name of a global function to execute, passed as a string.</li>
+     *    <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+     *    <li>An anonymous function (PHP 5.3+).</li></ul>
+     * @return $this A reference to the current instance.
+     */
+    public function register_streaming_read_callback($callback)
+    {
+        $this->registered_streaming_read_callback = $callback;
+
+        return $this;
+    }
+
+    /**
+     * Register a callback function to execute whenever a data stream is written to using
+     * <CFRequest::streaming_write_callback()>.
+     *
+     * The user-defined callback function should accept two arguments:
+     *
+     * <ul>
+     *    <li><code>$curl_handle</code> - <code>resource</code> - Required - The cURL handle resource that represents the in-progress transfer.</li>
+     *    <li><code>$length</code> - <code>integer</code> - Required - The length in kilobytes of the data chunk that was transferred.</li>
+     * </ul>
+     *
+     * @param string|array|function $callback (Required) The callback function is called by <php:call_user_func()>, so you can pass the following values: <ul>
+     *    <li>The name of a global function to execute, passed as a string.</li>
+     *    <li>A method to execute, passed as <code>array('ClassName', 'MethodName')</code>.</li>
+     *    <li>An anonymous function (PHP 5.3+).</li></ul>
+     * @return $this A reference to the current instance.
+     */
+    public function register_streaming_write_callback($callback)
+    {
+        $this->registered_streaming_write_callback = $callback;
+
+        return $this;
+    }
+
+
+    /*%******************************************************************************************%*/
+    // PREPARE, SEND, AND PROCESS REQUEST
+
+    /**
+     * A callback function that is invoked by cURL for streaming up.
+     *
+     * @param resource $curl_handle (Required) The cURL handle for the request.
+     * @param resource $file_handle (Required) The open file handle resource.
+     * @param integer $length (Required) The maximum number of bytes to read.
+     * @return binary Binary data from a stream.
+     */
+    public function streaming_read_callback($curl_handle, $file_handle, $length)
+    {
+        // Once we've sent as much as we're supposed to send...
+        if ($this->read_stream_read >= $this->read_stream_size) {
+            // Send EOF
+            return '';
+        }
+
+        // If we're at the beginning of an upload and need to seek...
+        if ($this->read_stream_read == 0 && isset($this->seek_position) && $this->seek_position !== ftell($this->read_stream)) {
+            if (fseek($this->read_stream, $this->seek_position) !== 0) {
+                throw new RequestCore_Exception('The stream does not support seeking and is either not at the requested position or the position is unknown.');
+            }
+        }
+
+        $read = fread($this->read_stream, min($this->read_stream_size - $this->read_stream_read, $length)); // Remaining upload data or cURL's requested chunk size
+        $this->read_stream_read += strlen($read);
+
+        $out = $read === false ? '' : $read;
+
+        // Execute callback function
+        if ($this->registered_streaming_read_callback) {
+            call_user_func($this->registered_streaming_read_callback, $curl_handle, $file_handle, $out);
+        }
+
+        return $out;
+    }
+
+    /**
+     * A callback function that is invoked by cURL for streaming down.
+     *
+     * @param resource $curl_handle (Required) The cURL handle for the request.
+     * @param binary $data (Required) The data to write.
+     * @return integer The number of bytes written.
+     */
+    public function streaming_write_callback($curl_handle, $data)
+    {
+        $code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
+        
+        if (intval($code) / 100 != 2)
+        {
+            $this->response_error_body .= $data;
+            return strlen($data);
+        }
+
+        $length = strlen($data);
+        $written_total = 0;
+        $written_last = 0;
+        
+        while ($written_total < $length) {
+            $written_last = fwrite($this->write_stream, substr($data, $written_total));
+
+            if ($written_last === false) {
+                return $written_total;
+            }
+
+            $written_total += $written_last;
+        }
+
+        // Execute callback function
+        if ($this->registered_streaming_write_callback) {
+            call_user_func($this->registered_streaming_write_callback, $curl_handle, $written_total);
+        }
+
+        return $written_total;
+    }
+
+    /**
+     * Prepare and adds the details of the cURL request. This can be passed along to a <php:curl_multi_exec()>
+     * function.
+     *
+     * @return resource The handle for the cURL object.
+     *
+     */
+    public function prep_request()
+    {
+        $curl_handle = curl_init();
+
+        // Set default options.
+        curl_setopt($curl_handle, CURLOPT_URL, $this->request_url);
+        curl_setopt($curl_handle, CURLOPT_FILETIME, true);
+        curl_setopt($curl_handle, CURLOPT_FRESH_CONNECT, false);
+//		curl_setopt($curl_handle, CURLOPT_CLOSEPOLICY, CURLCLOSEPOLICY_LEAST_RECENTLY_USED);
+        curl_setopt($curl_handle, CURLOPT_MAXREDIRS, 5);
+        curl_setopt($curl_handle, CURLOPT_HEADER, true);
+        curl_setopt($curl_handle, CURLOPT_RETURNTRANSFER, true);
+        curl_setopt($curl_handle, CURLOPT_TIMEOUT, $this->timeout);
+        curl_setopt($curl_handle, CURLOPT_CONNECTTIMEOUT, $this->connect_timeout);
+        curl_setopt($curl_handle, CURLOPT_NOSIGNAL, true);
+        curl_setopt($curl_handle, CURLOPT_REFERER, $this->request_url);
+        curl_setopt($curl_handle, CURLOPT_USERAGENT, $this->useragent);
+        curl_setopt($curl_handle, CURLOPT_HEADERFUNCTION, array($this, 'streaming_header_callback'));
+        curl_setopt($curl_handle, CURLOPT_READFUNCTION, array($this, 'streaming_read_callback'));
+
+        // Verification of the SSL cert
+        if ($this->ssl_verification) {
+            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, true);
+            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, 2);
+        } else {
+            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYPEER, false);
+            curl_setopt($curl_handle, CURLOPT_SSL_VERIFYHOST, false);
+        }
+
+        // chmod the file as 0755
+        if ($this->cacert_location === true) {
+            curl_setopt($curl_handle, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
+        } elseif (is_string($this->cacert_location)) {
+            curl_setopt($curl_handle, CURLOPT_CAINFO, $this->cacert_location);
+        }
+
+        // Debug mode
+        if ($this->debug_mode) {
+            curl_setopt($curl_handle, CURLOPT_VERBOSE, true);
+        }
+
+        // Handle open_basedir & safe mode
+        if (!ini_get('safe_mode') && !ini_get('open_basedir')) {
+            curl_setopt($curl_handle, CURLOPT_FOLLOWLOCATION, true);
+        }
+
+        // Enable a proxy connection if requested.
+        if ($this->proxy) {
+            $host = $this->proxy['host'];
+            $host .= ($this->proxy['port']) ? ':' . $this->proxy['port'] : '';
+            curl_setopt($curl_handle, CURLOPT_PROXY, $host);
+
+            if (isset($this->proxy['user']) && isset($this->proxy['pass'])) {
+                curl_setopt($curl_handle, CURLOPT_PROXYUSERPWD, $this->proxy['user'] . ':' . $this->proxy['pass']);
+            }
+        }
+
+        // Set credentials for HTTP Basic/Digest Authentication.
+        if ($this->username && $this->password) {
+            curl_setopt($curl_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
+            curl_setopt($curl_handle, CURLOPT_USERPWD, $this->username . ':' . $this->password);
+        }
+
+        // Handle the encoding if we can.
+        if (extension_loaded('zlib')) {
+            curl_setopt($curl_handle, CURLOPT_ENCODING, '');
+        }
+
+        // Process custom headers
+        if (isset($this->request_headers) && count($this->request_headers)) {
+            $temp_headers = array();
+
+            foreach ($this->request_headers as $k => $v) {
+                $temp_headers[] = $k . ': ' . $v;
+            }
+
+            // fix "Expect: 100-continue"
+            $temp_headers[] = 'Expect:';
+            curl_setopt($curl_handle, CURLOPT_HTTPHEADER, $temp_headers);
+        }
+
+        switch ($this->method) {
+            case self::HTTP_PUT:
+                //unset($this->read_stream);
+                curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'PUT');
+                if (isset($this->read_stream)) {
+                    if (!isset($this->read_stream_size) || $this->read_stream_size < 0) {
+                        throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
+                    }
+                    curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
+                    curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
+                } else {
+                    curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+                }
+                break;
+
+            case self::HTTP_POST:
+                curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, 'POST');
+                if (isset($this->read_stream)) {
+                    if (!isset($this->read_stream_size) || $this->read_stream_size < 0) {
+                        throw new RequestCore_Exception('The stream size for the streaming upload cannot be determined.');
+                    }
+                    curl_setopt($curl_handle, CURLOPT_INFILESIZE, $this->read_stream_size);
+                    curl_setopt($curl_handle, CURLOPT_UPLOAD, true);
+                } else {
+                    curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+                }
+                break;
+
+            case self::HTTP_HEAD:
+                curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, self::HTTP_HEAD);
+                curl_setopt($curl_handle, CURLOPT_NOBODY, 1);
+                break;
+
+            default: // Assumed GET
+                curl_setopt($curl_handle, CURLOPT_CUSTOMREQUEST, $this->method);
+                if (isset($this->write_stream) || isset($this->write_file)) {
+                    curl_setopt($curl_handle, CURLOPT_WRITEFUNCTION, array($this, 'streaming_write_callback'));
+                    curl_setopt($curl_handle, CURLOPT_HEADER, false);
+                } else {
+                    curl_setopt($curl_handle, CURLOPT_POSTFIELDS, $this->request_body);
+                }
+                break;
+        }
+
+        // Merge in the CURLOPTs
+        if (isset($this->curlopts) && sizeof($this->curlopts) > 0) {
+            foreach ($this->curlopts as $k => $v) {
+                curl_setopt($curl_handle, $k, $v);
+            }
+        }
+
+        return $curl_handle;
+    }
+
+    /**
+     * Take the post-processed cURL data and break it down into useful header/body/info chunks. Uses the
+     * data stored in the `curl_handle` and `response` properties unless replacement data is passed in via
+     * parameters.
+     *
+     * @param resource $curl_handle (Optional) The reference to the already executed cURL request.
+     * @param string $response (Optional) The actual response content itself that needs to be parsed.
+     * @return ResponseCore A <ResponseCore> object containing a parsed HTTP response.
+     */
+    public function process_response($curl_handle = null, $response = null)
+    {
+        // Accept a custom one if it's passed.
+        if ($curl_handle && $response) {
+            $this->response = $response;
+        }
+
+        // As long as this came back as a valid resource...
+        if (is_resource($curl_handle)) {
+            // Determine what's what.
+            $header_size = curl_getinfo($curl_handle, CURLINFO_HEADER_SIZE);
+            $this->response_headers = substr($this->response, 0, $header_size);
+            $this->response_body = substr($this->response, $header_size);
+            $this->response_code = curl_getinfo($curl_handle, CURLINFO_HTTP_CODE);
+            $this->response_info = curl_getinfo($curl_handle);
+            
+            if (intval($this->response_code) / 100 != 2 && isset($this->write_file))
+            {
+                $this->response_headers = $this->response_raw_headers;
+                $this->response_body = $this->response_error_body;
+            }
+
+            // Parse out the headers
+            $this->response_headers = explode("\r\n\r\n", trim($this->response_headers));
+            $this->response_headers = array_pop($this->response_headers);
+            $this->response_headers = explode("\r\n", $this->response_headers);
+            array_shift($this->response_headers);
+
+            // Loop through and split up the headers.
+            $header_assoc = array();
+            foreach ($this->response_headers as $header) {
+                $kv = explode(': ', $header);
+                $header_assoc[strtolower($kv[0])] = isset($kv[1]) ? $kv[1] : '';
+            }
+
+            // Reset the headers to the appropriate property.
+            $this->response_headers = $header_assoc;
+            $this->response_headers['info'] = $this->response_info;
+            $this->response_headers['info']['method'] = $this->method;
+            
+            if ($curl_handle && $response) {
+                return new ResponseCore($this->response_headers, $this->response_body, $this->response_code);
+            }
+        }
+
+        // Return false
+        return false;
+    }
+
+    /**
+     * Send the request, calling necessary utility functions to update built-in properties.
+     *
+     * @param boolean $parse (Optional) Whether to parse the response with ResponseCore or not.
+     * @return string The resulting unparsed data from the request.
+     */
+    public function send_request($parse = false)
+    {
+        set_time_limit(0);
+
+        $curl_handle = $this->prep_request();
+        $this->response = curl_exec($curl_handle);
+
+        if ($this->response === false) {
+            throw new RequestCore_Exception('cURL resource: ' . (string)$curl_handle . '; cURL error: ' . curl_error($curl_handle) . ' (' . curl_errno($curl_handle) . ')');
+        }
+
+        $parsed_response = $this->process_response($curl_handle, $this->response);
+
+        curl_close($curl_handle);
+
+        if ($parse) {
+            return $parsed_response;
+        }
+
+        return $this->response;
+    }
+
+    /*%******************************************************************************************%*/
+    // RESPONSE METHODS
+
+    /**
+     * Get the HTTP response headers from the request.
+     *
+     * @param string $header (Optional) A specific header value to return. Defaults to all headers.
+     * @return string|array All or selected header values.
+     */
+    public function get_response_header($header = null)
+    {
+        if ($header) {
+            return $this->response_headers[strtolower($header)];
+        }
+        return $this->response_headers;
+    }
+
+    /**
+     * Get the HTTP response body from the request.
+     *
+     * @return string The response body.
+     */
+    public function get_response_body()
+    {
+        return $this->response_body;
+    }
+
+    /**
+     * Get the HTTP response code from the request.
+     *
+     * @return string The HTTP response code.
+     */
+    public function get_response_code()
+    {
+        return $this->response_code;
+    }
+}

+ 8 - 0
sdk/OSS/Http/RequestCore_Exception.php

@@ -0,0 +1,8 @@
+<?php
+
+namespace OSS\Http;
+
+class RequestCore_Exception extends \Exception
+{
+
+}

+ 56 - 0
sdk/OSS/Http/ResponseCore.php

@@ -0,0 +1,56 @@
+<?php
+
+namespace OSS\Http;
+
+/**
+ * Container for all response-related methods.
+ */
+class ResponseCore
+{
+    /**
+     * Store the HTTP header information.
+     */
+    public $header;
+
+    /**
+     * Store the SimpleXML response.
+     */
+    public $body;
+
+    /**
+     * Store the HTTP response code.
+     */
+    public $status;
+
+    /**
+     * Construct a new instance of this class.
+     *
+     * @param array $header (Required) Associative array of HTTP headers (typically returned by <RequestCore::get_response_header()>).
+     * @param string $body (Required) XML-formatted response from OSS.
+     * @param integer $status (Optional) HTTP response status code from the request.
+     * @return Mixed Contains an <php:array> `header` property (HTTP headers as an associative array), a <php:SimpleXMLElement> or <php:string> `body` property, and an <php:integer> `status` code.
+     */
+    public function __construct($header, $body, $status = null)
+    {
+        $this->header = $header;
+        $this->body = $body;
+        $this->status = $status;
+
+        return $this;
+    }
+
+    /**
+     * Did we receive the status code we expected?
+     *
+     * @param integer|array $codes (Optional) The status code(s) to expect. Pass an <php:integer> for a single acceptable value, or an <php:array> of integers for multiple acceptable values.
+     * @return boolean Whether we received the expected status code or not.
+     */
+    public function isOK($codes = array(200, 201, 204, 206))
+    {
+        if (is_array($codes)) {
+            return in_array($this->status, $codes);
+        }
+
+        return $this->status === $codes;
+    }
+}

+ 181 - 0
sdk/OSS/Model/BucketInfo.php

@@ -0,0 +1,181 @@
+<?php
+
+namespace OSS\Model;
+
+
+/**
+ * Bucket information class. This is the type of element in BucketListInfo's
+ *
+ * Class BucketInfo
+ * @package OSS\Model
+ */
+class BucketInfo
+{
+     /**
+     * BucketInfo constructor.
+     *
+     * @param string $location
+     * @param string $name
+     * @param string $createDate
+     */
+    public function __construct($location = '', $name = '', $createDate = '')
+    {
+        $this->location = $location;
+        $this->createDate = $createDate;
+        $this->name = $name;
+    }
+    
+    /**
+     * Get bucket location
+     *
+     * @return string
+     */
+    public function getLocation()
+    {
+        return $this->location;
+    }
+
+    /**
+     * Get bucket name
+     *
+     * @return string
+     */
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    /**
+     * Get bucket creation time.
+     *
+     * @return string
+     */
+    public function getCreateDate()
+    {
+        return $this->createDate;
+    }
+
+    /**
+     * Get bucket storage class.
+     *
+     * @return string
+     */
+    public function getStorageClass()
+    {
+        return $this->storageClass;
+    }
+
+     /**
+     * Get bucket extranet endpoint.
+     *
+     * @return string
+     */
+    public function getExtranetEndpoint()
+    {
+        return $this->extranetEndpoint;
+    }
+
+     /**
+     * Get bucket intranet endpoint.
+     *
+     * @return string
+     */
+    public function getIntranetEndpoint()
+    {
+        return $this->intranetEndpoint;
+    }
+
+    /**
+     * Get bucket intranet endpoint.
+     *
+     * @return string
+     */
+    public function getRegion()
+    {
+        return $this->region;
+    }
+    
+
+    /**
+     * Parse bucket information from node.
+     *
+     * @param xml $xml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXmlNode($xml)
+    {
+        if (isset($xml->Location)) {
+            $this->location = strval($xml->Location);
+        }
+        if (isset($xml->Name)) {
+            $this->name = strval($xml->Name);
+        }
+        if (isset($xml->CreationDate)) {
+            $this->createDate = strval($xml->CreationDate);
+        }
+        if (isset($xml->StorageClass)) {
+            $this->storageClass = strval($xml->StorageClass);
+        }
+        if (isset($xml->ExtranetEndpoint)) {
+            $this->extranetEndpoint = strval($xml->ExtranetEndpoint);
+        }
+        if (isset($xml->IntranetEndpoint)) {
+            $this->intranetEndpoint = strval($xml->IntranetEndpoint);
+        }
+        if (isset($xml->IntranetEndpoint)) {
+            $this->intranetEndpoint = strval($xml->IntranetEndpoint);
+        }
+        if (isset($xml->Region)) {
+            $this->region = strval($xml->Region);
+        }
+    }
+    
+    /**
+     * bucket region
+     *
+     * @var string
+     */
+    private $location;
+    /**
+     * bucket name
+     *
+     * @var string
+     */
+    private $name;
+
+    /**
+     * bucket creation time
+     *
+     * @var string
+     */
+    private $createDate;
+
+     /**
+     * bucket storage class
+     *
+     * @var string
+     */
+    private $storageClass;
+
+    /**
+     * bucket extranet endpoint
+     *
+     * @var string
+     */
+    private $extranetEndpoint;
+
+    /**
+     * bucket intranet endpoint
+     *
+     * @var string
+     */
+    private $intranetEndpoint;
+
+    /**
+     * bucket region
+     *
+     * @var string
+     */
+    private $region;
+}

+ 39 - 0
sdk/OSS/Model/BucketListInfo.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class BucketListInfo
+ *
+ * It's the type of return value of ListBuckets.
+ *
+ * @package OSS\Model
+ */
+class BucketListInfo
+{
+    /**
+     * BucketListInfo constructor.
+     * @param array $bucketList
+     */
+    public function __construct(array $bucketList)
+    {
+        $this->bucketList = $bucketList;
+    }
+
+    /**
+     * Get the BucketInfo list
+     *
+     * @return BucketInfo[]
+     */
+    public function getBucketList()
+    {
+        return $this->bucketList;
+    }
+
+    /**
+     * BucketInfo list
+     *
+     * @var array
+     */
+    private $bucketList = array();
+}

+ 85 - 0
sdk/OSS/Model/BucketStat.php

@@ -0,0 +1,85 @@
+<?php
+
+namespace OSS\Model;
+
+
+/**
+ * Bucket stat class.
+ *
+ * Class BucketStat
+ * @package OSS\Model
+ */
+class BucketStat
+{
+    /**
+     * Get storage
+     *
+     * @return int
+     */
+    public function getStorage()
+    {
+        return $this->storage;
+    }
+
+    /**
+     * Get object count
+     *
+     * @return int
+     */
+    public function getObjectCount()
+    {
+        return $this->objectCount;
+    }
+
+    /**
+     * Get multipart upload count.
+     *
+     * @return int
+     */
+    public function getMultipartUploadCount()
+    {
+        return $this->multipartUploadCount;
+    }
+
+    /**
+     * Parse stat from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (isset($xml->Storage) ) {
+            $this->storage = intval($xml->Storage);
+        }
+        if (isset($xml->ObjectCount) ) {
+            $this->objectCount = intval($xml->ObjectCount);
+        }
+        if (isset($xml->MultipartUploadCount) ) {
+            $this->multipartUploadCount = intval($xml->MultipartUploadCount);
+        }
+    }
+    
+    /**
+     * current storage
+     *
+     * @var int
+     */
+    private $storage;
+    /**
+     * object count
+     *
+     * @var int
+     */
+    private $objectCount;
+
+    /**
+     * multipart upload count
+     *
+     * @var int
+     */
+    private $multipartUploadCount;
+
+}

+ 99 - 0
sdk/OSS/Model/CnameConfig.php

@@ -0,0 +1,99 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class CnameConfig
+ * @package OSS\Model
+ *
+ * TODO: fix link
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
+ */
+class CnameConfig implements XmlConfig
+{
+    public function __construct()
+    {
+        $this->cnameList = array();
+    }
+
+    /**
+     * @return array
+     * @example
+     *  array(2) {
+     *    [0]=>
+     *    array(3) {
+     *      ["Domain"]=>
+     *      string(11) "www.foo.com"
+     *      ["Status"]=>
+     *      string(7) "enabled"
+     *      ["LastModified"]=>
+     *      string(8) "20150101"
+     *    }
+     *    [1]=>
+     *    array(3) {
+     *      ["Domain"]=>
+     *      string(7) "bar.com"
+     *      ["Status"]=>
+     *      string(8) "disabled"
+     *      ["LastModified"]=>
+     *      string(8) "20160101"
+     *    }
+     *  }
+     */
+    public function getCnames()
+    {
+        return $this->cnameList;
+    }
+
+
+    public function addCname($cname)
+    {
+        if (count($this->cnameList) >= self::OSS_MAX_RULES) {
+            throw new OssException(
+                "num of cname in the config exceeds self::OSS_MAX_RULES: " . strval(self::OSS_MAX_RULES));
+        }
+        $this->cnameList[] = array('Domain' => $cname);
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->Cname)) return;
+        foreach ($xml->Cname as $entry) {
+            $cname = array();
+            foreach ($entry as $key => $value) {
+                $cname[strval($key)] = strval($value);
+            }
+            $this->cnameList[] = $cname;
+        }
+    }
+
+    public function serializeToXml()
+    {
+        $strXml = <<<EOF
+<?xml version="1.0" encoding="utf-8"?>
+<BucketCnameConfiguration>
+</BucketCnameConfiguration>
+EOF;
+        $xml = new \SimpleXMLElement($strXml);
+        foreach ($this->cnameList as $cname) {
+            $node = $xml->addChild('Cname');
+            foreach ($cname as $key => $value) {
+                $node->addChild($key, $value);
+            }
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    const OSS_MAX_RULES = 10;
+
+    private $cnameList = array();
+}

+ 113 - 0
sdk/OSS/Model/CorsConfig.php

@@ -0,0 +1,113 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class CorsConfig
+ * @package OSS\Model
+ *
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
+ */
+class CorsConfig implements XmlConfig
+{
+    /**
+     * CorsConfig constructor.
+     */
+    public function __construct()
+    {
+        $this->rules = array();
+    }
+
+    /**
+     * Get CorsRule list
+     *
+     * @return CorsRule[]
+     */
+    public function getRules()
+    {
+        return $this->rules;
+    }
+
+
+    /**
+     * Add a new CorsRule
+     *
+     * @param CorsRule $rule
+     * @throws OssException
+     */
+    public function addRule($rule)
+    {
+        if (count($this->rules) >= self::OSS_MAX_RULES) {
+            throw new OssException("num of rules in the config exceeds self::OSS_MAX_RULES: " . strval(self::OSS_MAX_RULES));
+        }
+        $this->rules[] = $rule;
+    }
+
+    /**
+     * Parse CorsConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->CORSRule)) return;
+        foreach ($xml->CORSRule as $rule) {
+            $corsRule = new CorsRule();
+            foreach ($rule as $key => $value) {
+                if ($key === self::OSS_CORS_ALLOWED_HEADER) {
+                    $corsRule->addAllowedHeader(strval($value));
+                } elseif ($key === self::OSS_CORS_ALLOWED_METHOD) {
+                    $corsRule->addAllowedMethod(strval($value));
+                } elseif ($key === self::OSS_CORS_ALLOWED_ORIGIN) {
+                    $corsRule->addAllowedOrigin(strval($value));
+                } elseif ($key === self::OSS_CORS_EXPOSE_HEADER) {
+                    $corsRule->addExposeHeader(strval($value));
+                } elseif ($key === self::OSS_CORS_MAX_AGE_SECONDS) {
+                    $corsRule->setMaxAgeSeconds(strval($value));
+                }
+            }
+            $this->addRule($corsRule);
+        }
+        return;
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><CORSConfiguration></CORSConfiguration>');
+        foreach ($this->rules as $rule) {
+            $xmlRule = $xml->addChild('CORSRule');
+            $rule->appendToXml($xmlRule);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    const OSS_CORS_ALLOWED_ORIGIN = 'AllowedOrigin';
+    const OSS_CORS_ALLOWED_METHOD = 'AllowedMethod';
+    const OSS_CORS_ALLOWED_HEADER = 'AllowedHeader';
+    const OSS_CORS_EXPOSE_HEADER = 'ExposeHeader';
+    const OSS_CORS_MAX_AGE_SECONDS = 'MaxAgeSeconds';
+    const OSS_MAX_RULES = 10;
+
+    /**
+     * CorsRule list
+     *
+     * @var CorsRule[]
+     */
+    private $rules = array();
+}

+ 150 - 0
sdk/OSS/Model/CorsRule.php

@@ -0,0 +1,150 @@
+<?php
+
+namespace OSS\Model;
+
+use OSS\Core\OssException;
+
+
+/**
+ * Class CorsRule
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/PutBucketcors.html
+ */
+class CorsRule
+{
+    /**
+     * Add an allowedOrigin rule
+     *
+     * @param string $allowedOrigin
+     */
+    public function addAllowedOrigin($allowedOrigin)
+    {
+        if (!empty($allowedOrigin)) {
+            $this->allowedOrigins[] = $allowedOrigin;
+        }
+    }
+
+    /**
+     * Add an allowedMethod rule
+     *
+     * @param string $allowedMethod
+     */
+    public function addAllowedMethod($allowedMethod)
+    {
+        if (!empty($allowedMethod)) {
+            $this->allowedMethods[] = $allowedMethod;
+        }
+    }
+
+    /**
+     * Add an allowedHeader rule
+     *
+     * @param string $allowedHeader
+     */
+    public function addAllowedHeader($allowedHeader)
+    {
+        if (!empty($allowedHeader)) {
+            $this->allowedHeaders[] = $allowedHeader;
+        }
+    }
+
+    /**
+     * Add an exposeHeader rule
+     *
+     * @param string $exposeHeader
+     */
+    public function addExposeHeader($exposeHeader)
+    {
+        if (!empty($exposeHeader)) {
+            $this->exposeHeaders[] = $exposeHeader;
+        }
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxAgeSeconds()
+    {
+        return $this->maxAgeSeconds;
+    }
+
+    /**
+     * @param int $maxAgeSeconds
+     */
+    public function setMaxAgeSeconds($maxAgeSeconds)
+    {
+        $this->maxAgeSeconds = $maxAgeSeconds;
+    }
+
+    /**
+     * Get the AllowedHeaders list
+     *
+     * @return string[]
+     */
+    public function getAllowedHeaders()
+    {
+        return $this->allowedHeaders;
+    }
+
+    /**
+     * Get the AllowedOrigins list
+     *
+     * @return string[]
+     */
+    public function getAllowedOrigins()
+    {
+        return $this->allowedOrigins;
+    }
+
+    /**
+     * Get the AllowedMethods list
+     *
+     * @return string[]
+     */
+    public function getAllowedMethods()
+    {
+        return $this->allowedMethods;
+    }
+
+    /**
+     * Get the ExposeHeaders list
+     *
+     * @return string[]
+     */
+    public function getExposeHeaders()
+    {
+        return $this->exposeHeaders;
+    }
+
+    /**
+     * Serialize all the rules into the xml represented by parameter $xmlRule
+     *
+     * @param \SimpleXMLElement $xmlRule
+     * @throws OssException
+     */
+    public function appendToXml(&$xmlRule)
+    {
+        if (!isset($this->maxAgeSeconds)) {
+            throw new OssException("maxAgeSeconds is not set in the Rule");
+        }
+        foreach ($this->allowedOrigins as $allowedOrigin) {
+            $xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_ORIGIN, $allowedOrigin);
+        }
+        foreach ($this->allowedMethods as $allowedMethod) {
+            $xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_METHOD, $allowedMethod);
+        }
+        foreach ($this->allowedHeaders as $allowedHeader) {
+            $xmlRule->addChild(CorsConfig::OSS_CORS_ALLOWED_HEADER, $allowedHeader);
+        }
+        foreach ($this->exposeHeaders as $exposeHeader) {
+            $xmlRule->addChild(CorsConfig::OSS_CORS_EXPOSE_HEADER, $exposeHeader);
+        }
+        $xmlRule->addChild(CorsConfig::OSS_CORS_MAX_AGE_SECONDS, strval($this->maxAgeSeconds));
+    }
+
+    private $allowedHeaders = array();
+    private $allowedOrigins = array();
+    private $allowedMethods = array();
+    private $exposeHeaders = array();
+    private $maxAgeSeconds = null;
+}

+ 65 - 0
sdk/OSS/Model/DeleteMarkerInfo.php

@@ -0,0 +1,65 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ *
+ * Class DeleteMarkerInfo
+ *
+ * @package OSS\Model
+ */
+class DeleteMarkerInfo
+{
+    /**
+     * DeleteMarkerInfo constructor.
+     *
+     * @param string $key
+     * @param string $versionId
+     * @param string $lastModified
+     * @param string $isLatest
+     */
+    public function __construct($key, $versionId, $lastModified, $isLatest)
+    {
+        $this->key = $key;
+        $this->versionId = $versionId;
+        $this->lastModified = $lastModified;
+        $this->isLatest = $isLatest;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getVersionId()
+    {
+        return $this->versionId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getLastModified()
+    {
+        return $this->lastModified;
+    }
+
+    /**
+     * @return string
+     */
+    public function getIsLatest()
+    {
+        return $this->isLatest;
+    }
+
+    private $key = "";
+    private $versionId = "";
+    private $lastModified = "";
+    private $isLatest = "";
+}

+ 41 - 0
sdk/OSS/Model/DeleteObjectInfo.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class DeleteObjectInfo
+ * @package OSS\Model
+ */
+class DeleteObjectInfo
+{
+    /**
+     * DeleteObjectInfo constructor.
+     *
+     * @param string $key
+     * @param string $versionId
+     */
+    public function __construct($key, $versionId = '')
+    {
+        $this->key = $key;
+        $this->versionId = $versionId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getVersionId()
+    {
+        return $this->versionId;
+    }
+    
+    private $key = "";
+    private $versionId = "";
+}

+ 63 - 0
sdk/OSS/Model/DeletedObjectInfo.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class DeletedObjectInfo
+ * @package OSS\Model
+ */
+class DeletedObjectInfo
+{
+    /**
+     * DeletedObjectInfo constructor.
+     *
+     * @param string $key
+     * @param string $versionId
+     * @param string $deleteMarker
+     * @param string $deleteMarkerVersionId
+     */
+    public function __construct($key, $versionId, $deleteMarker, $deleteMarkerVersionId)
+    {
+        $this->key = $key;
+        $this->versionId = $versionId;
+        $this->deleteMarker = $deleteMarker;
+        $this->deleteMarkerVersionId = $deleteMarkerVersionId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getVersionId()
+    {
+        return $this->versionId;
+    }
+    
+    /**
+     * @return string
+     */
+    public function getDeleteMarker()
+    {
+        return $this->deleteMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDeleteMarkerVersionId()
+    {
+        return $this->deleteMarkerVersionId;
+    }
+
+    private $key = "";
+    private $versionId = "";
+    private $deleteMarker = "";
+    private $deleteMarkerVersionId = "";
+}

+ 64 - 0
sdk/OSS/Model/ExtendWormConfig.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class ExtendWormConfig
+ * @package OSS\Model
+ *
+ */
+class ExtendWormConfig implements XmlConfig
+{
+    /**
+     * ExtendWormConfig constructor.
+     * @param null $day
+     */
+    public function __construct($day = null)
+    {
+        $this->day = $day;
+    }
+
+    /**
+     * Parse ExtendWormConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        throw new OssException("Not implemented.");
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><ExtendWormConfiguration></ExtendWormConfiguration>');
+        if (isset($this->day)) {
+            $xml->addChild('RetentionPeriodInDays', $this->day);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return int
+     */
+    public function getDay()
+    {
+        return $this->day;
+    }
+
+    private $day = 0;
+}

+ 37 - 0
sdk/OSS/Model/GetLiveChannelHistory.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace OSS\Model;
+
+use OSS\Core\OssException;
+
+/**
+ * Class GetLiveChannelHistory
+ * @package OSS\Model
+ */
+class GetLiveChannelHistory implements XmlConfig
+{
+     public function getLiveRecordList()
+    {
+        return $this->liveRecordList;
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+
+        if (isset($xml->LiveRecord)) {
+            foreach ($xml->LiveRecord as $record) {
+            $liveRecord = new LiveChannelHistory();
+            $liveRecord->parseFromXmlNode($record);
+            $this->liveRecordList[] = $liveRecord;
+           }
+        }
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $liveRecordList = array();
+}

+ 68 - 0
sdk/OSS/Model/GetLiveChannelInfo.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace OSS\Model;
+/**
+ * Class GetLiveChannelInfo
+ * @package OSS\Model
+ */
+class GetLiveChannelInfo implements XmlConfig
+{
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getType()
+    {
+        return $this->type;
+    }
+  
+    public function getFragDuration()
+    {
+        return $this->fragDuration;
+    }
+   
+    public function getFragCount()
+    {
+        return $this->fragCount;
+    }
+   
+    public function getPlayListName()
+    {
+        return $this->playlistName;
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+
+        $this->description = strval($xml->Description);
+        $this->status = strval($xml->Status);
+
+        if (isset($xml->Target)) {
+            foreach ($xml->Target as $target) {
+            $this->type = strval($target->Type);
+            $this->fragDuration = strval($target->FragDuration);
+            $this->fragCount = strval($target->FragCount);
+            $this->playlistName = strval($target->PlaylistName);
+           }
+        }
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $description;
+    private $status;
+    private $type;
+    private $fragDuration;
+    private $fragCount;
+    private $playlistName;
+}

+ 107 - 0
sdk/OSS/Model/GetLiveChannelStatus.php

@@ -0,0 +1,107 @@
+<?php
+
+namespace OSS\Model;
+/**
+ * Class GetLiveChannelStatus
+ * @package OSS\Model
+ */
+class GetLiveChannelStatus implements XmlConfig
+{
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getConnectedTime()
+    {
+        return $this->connectedTime;
+    }
+
+    public function getRemoteAddr()
+    {
+        return $this->remoteAddr;
+    }
+
+    public function getVideoWidth()
+    {
+        return $this->videoWidth;
+    }
+    public function getVideoHeight()
+    {
+        return $this->videoHeight;
+    }
+    public function getVideoFrameRate()
+    {
+        return $this->videoFrameRate;
+    }
+    public function getVideoBandwidth()
+    {
+        return $this->videoBandwidth;
+    }
+    public function getVideoCodec()
+    {
+        return $this->videoCodec;
+    }
+
+    public function getAudioBandwidth()
+    {
+        return $this->audioBandwidth;
+    }
+    public function getAudioSampleRate()
+    {
+        return $this->audioSampleRate;
+    }
+    public function getAudioCodec()
+    {
+        return $this->audioCodec;
+    }
+
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        $this->status = strval($xml->Status);
+        $this->connectedTime = strval($xml->ConnectedTime);
+        $this->remoteAddr = strval($xml->RemoteAddr);
+
+        if (isset($xml->Video)) {
+            foreach ($xml->Video as $video) {
+            $this->videoWidth = intval($video->Width);
+            $this->videoHeight = intval($video->Height);
+            $this->videoFrameRate = intval($video->FrameRate);
+            $this->videoBandwidth = intval($video->Bandwidth);
+            $this->videoCodec = strval($video->Codec);
+           }
+        }
+        
+        if (isset($xml->Video)) {
+            foreach ($xml->Audio as $audio) {
+            $this->audioBandwidth = intval($audio->Bandwidth);
+            $this->audioSampleRate = intval($audio->SampleRate);
+            $this->audioCodec = strval($audio->Codec);
+           }
+        }
+
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $status;
+    private $connectedTime;
+    private $remoteAddr;
+
+    private $videoWidth;
+    private $videoHeight;
+    private $videoFrameRate;
+    private $videoBandwidth;
+    private $videoCodec;
+
+    private $audioBandwidth;
+    private $audioSampleRate;
+    private $audioCodec;
+    
+
+}

+ 64 - 0
sdk/OSS/Model/InitiateWormConfig.php

@@ -0,0 +1,64 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class InitiateWormConfig
+ * @package OSS\Model
+ *
+ */
+class InitiateWormConfig implements XmlConfig
+{
+    /**
+     * InitiateWormConfig constructor.
+     * @param null $day
+     */
+    public function __construct($day = null)
+    {
+        $this->day = $day;
+    }
+
+    /**
+     * Parse InitiateWormConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        throw new OssException("Not implemented.");
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><InitiateWormConfiguration></InitiateWormConfiguration>');
+        if (isset($this->day)) {
+            $xml->addChild('RetentionPeriodInDays', $this->day);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return int
+     */
+    public function getDay()
+    {
+        return $this->day;
+    }
+
+    private $day = 0;
+}

+ 88 - 0
sdk/OSS/Model/LifecycleAction.php

@@ -0,0 +1,88 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class LifecycleAction
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketLifecycle.html
+ */
+class LifecycleAction
+{
+    /**
+     * LifecycleAction constructor.
+     * @param string $action
+     * @param string $timeSpec
+     * @param string $timeValue
+     */
+    public function __construct($action, $timeSpec, $timeValue)
+    {
+        $this->action = $action;
+        $this->timeSpec = $timeSpec;
+        $this->timeValue = $timeValue;
+    }
+
+    /**
+     * @return LifecycleAction
+     */
+    public function getAction()
+    {
+        return $this->action;
+    }
+
+    /**
+     * @param string $action
+     */
+    public function setAction($action)
+    {
+        $this->action = $action;
+    }
+
+    /**
+     * @return string
+     */
+    public function getTimeSpec()
+    {
+        return $this->timeSpec;
+    }
+
+    /**
+     * @param string $timeSpec
+     */
+    public function setTimeSpec($timeSpec)
+    {
+        $this->timeSpec = $timeSpec;
+    }
+
+    /**
+     * @return string
+     */
+    public function getTimeValue()
+    {
+        return $this->timeValue;
+    }
+
+    /**
+     * @param string $timeValue
+     */
+    public function setTimeValue($timeValue)
+    {
+        $this->timeValue = $timeValue;
+    }
+
+    /**
+     * Use appendToXml to insert actions into xml.
+     *
+     * @param \SimpleXMLElement $xmlRule
+     */
+    public function appendToXml(&$xmlRule)
+    {
+        $xmlAction = $xmlRule->addChild($this->action);
+        $xmlAction->addChild($this->timeSpec, $this->timeValue);
+    }
+
+    private $action;
+    private $timeSpec;
+    private $timeValue;
+
+}

+ 107 - 0
sdk/OSS/Model/LifecycleConfig.php

@@ -0,0 +1,107 @@
+<?php
+
+namespace OSS\Model;
+
+use OSS\Core\OssException;
+
+
+/**
+ * Class BucketLifecycleConfig
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketLifecycle.html
+ */
+class LifecycleConfig implements XmlConfig
+{
+    /**
+     * Parse the xml into this object.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $this->rules = array();
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->Rule)) return;
+        $this->rules = array();
+        foreach ($xml->Rule as $rule) {
+            $id = strval($rule->ID);
+            $prefix = strval($rule->Prefix);
+            $status = strval($rule->Status);
+            $actions = array();
+            foreach ($rule as $key => $value) {
+                if ($key === 'ID' || $key === 'Prefix' || $key === 'Status') continue;
+                $action = $key;
+                $timeSpec = null;
+                $timeValue = null;
+                foreach ($value as $timeSpecKey => $timeValueValue) {
+                    $timeSpec = $timeSpecKey;
+                    $timeValue = strval($timeValueValue);
+                }
+                $actions[] = new LifecycleAction($action, $timeSpec, $timeValue);
+            }
+            $this->rules[] = new LifecycleRule($id, $prefix, $status, $actions);
+        }
+        return;
+    }
+
+
+    /**
+     * Serialize the object to xml
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><LifecycleConfiguration></LifecycleConfiguration>');
+        foreach ($this->rules as $rule) {
+            $xmlRule = $xml->addChild('Rule');
+            $rule->appendToXml($xmlRule);
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     *
+     * Add a LifecycleRule
+     *
+     * @param LifecycleRule $lifecycleRule
+     * @throws OssException
+     */
+    public function addRule($lifecycleRule)
+    {
+        if (!isset($lifecycleRule)) {
+            throw new OssException("lifecycleRule is null");
+        }
+        $this->rules[] = $lifecycleRule;
+    }
+
+    /**
+     *  Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * Get all lifecycle rules.
+     *
+     * @return LifecycleRule[]
+     */
+    public function getRules()
+    {
+        return $this->rules;
+    }
+
+    /**
+     * @var LifecycleRule[]
+     */
+    private $rules;
+}
+
+

+ 126 - 0
sdk/OSS/Model/LifecycleRule.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace OSS\Model;
+
+
+/**
+ * Class LifecycleRule
+ * @package OSS\Model
+ *
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketLifecycle.html
+ */
+class LifecycleRule
+{
+    /**
+     * Get Id
+     *
+     * @return string
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * @param string $id Rule Id
+     */
+    public function setId($id)
+    {
+        $this->id = $id;
+    }
+
+    /**
+     * Get a file prefix
+     *
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * Set a file prefix
+     *
+     * @param string $prefix The file prefix
+     */
+    public function setPrefix($prefix)
+    {
+        $this->prefix = $prefix;
+    }
+
+    /**
+     * Get Lifecycle status
+     *
+     * @return string
+     */
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    /**
+     * Set Lifecycle status
+     *
+     * @param string $status
+     */
+    public function setStatus($status)
+    {
+        $this->status = $status;
+    }
+
+    /**
+     *
+     * @return LifecycleAction[]
+     */
+    public function getActions()
+    {
+        return $this->actions;
+    }
+
+    /**
+     * @param LifecycleAction[] $actions
+     */
+    public function setActions($actions)
+    {
+        $this->actions = $actions;
+    }
+
+
+    /**
+     * LifecycleRule constructor.
+     *
+     * @param string $id rule Id
+     * @param string $prefix File prefix
+     * @param string $status Rule status, which has the following valid values: [self::LIFECYCLE_STATUS_ENABLED, self::LIFECYCLE_STATUS_DISABLED]
+     * @param LifecycleAction[] $actions
+     */
+    public function __construct($id, $prefix, $status, $actions)
+    {
+        $this->id = $id;
+        $this->prefix = $prefix;
+        $this->status = $status;
+        $this->actions = $actions;
+    }
+
+    /**
+     * @param \SimpleXMLElement $xmlRule
+     */
+    public function appendToXml(&$xmlRule)
+    {
+        $xmlRule->addChild('ID', $this->id);
+        $xmlRule->addChild('Prefix', $this->prefix);
+        $xmlRule->addChild('Status', $this->status);
+        foreach ($this->actions as $action) {
+            $action->appendToXml($xmlRule);
+        }
+    }
+
+    private $id;
+    private $prefix;
+    private $status;
+    private $actions = array();
+
+    const LIFECYCLE_STATUS_ENABLED = 'Enabled';
+    const LIFECYCLE_STATUS_DISABLED = 'Disabled';
+}

+ 134 - 0
sdk/OSS/Model/ListMultipartUploadInfo.php

@@ -0,0 +1,134 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class ListMultipartUploadInfo
+ * @package OSS\Model
+ *
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/multipart-upload/ListMultipartUploads.html
+ */
+class ListMultipartUploadInfo
+{
+    /**
+     * ListMultipartUploadInfo constructor.
+     *
+     * @param string $bucket
+     * @param string $keyMarker
+     * @param string $uploadIdMarker
+     * @param string $nextKeyMarker
+     * @param string $nextUploadIdMarker
+     * @param string $delimiter
+     * @param string $prefix
+     * @param int $maxUploads
+     * @param string $isTruncated
+     * @param array $uploads
+     */
+    public function __construct($bucket, $keyMarker, $uploadIdMarker, $nextKeyMarker, $nextUploadIdMarker, $delimiter, $prefix, $maxUploads, $isTruncated, array $uploads)
+    {
+        $this->bucket = $bucket;
+        $this->keyMarker = $keyMarker;
+        $this->uploadIdMarker = $uploadIdMarker;
+        $this->nextKeyMarker = $nextKeyMarker;
+        $this->nextUploadIdMarker = $nextUploadIdMarker;
+        $this->delimiter = $delimiter;
+        $this->prefix = $prefix;
+        $this->maxUploads = $maxUploads;
+        $this->isTruncated = $isTruncated;
+        $this->uploads = $uploads;
+    }
+
+    /**
+     * 得到bucket名称
+     *
+     * @return string
+     */
+    public function getBucket()
+    {
+        return $this->bucket;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKeyMarker()
+    {
+        return $this->keyMarker;
+    }
+
+    /**
+     *
+     * @return string
+     */
+    public function getUploadIdMarker()
+    {
+        return $this->uploadIdMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextKeyMarker()
+    {
+        return $this->nextKeyMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextUploadIdMarker()
+    {
+        return $this->nextUploadIdMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDelimiter()
+    {
+        return $this->delimiter;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxUploads()
+    {
+        return $this->maxUploads;
+    }
+
+    /**
+     * @return string
+     */
+    public function getIsTruncated()
+    {
+        return $this->isTruncated;
+    }
+
+    /**
+     * @return UploadInfo[]
+     */
+    public function getUploads()
+    {
+        return $this->uploads;
+    }
+
+    private $bucket = "";
+    private $keyMarker = "";
+    private $uploadIdMarker = "";
+    private $nextKeyMarker = "";
+    private $nextUploadIdMarker = "";
+    private $delimiter = "";
+    private $prefix = "";
+    private $maxUploads = 0;
+    private $isTruncated = "false";
+    private $uploads = array();
+}

+ 97 - 0
sdk/OSS/Model/ListPartsInfo.php

@@ -0,0 +1,97 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class ListPartsInfo
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/multipart-upload/ListParts.html
+ */
+class ListPartsInfo
+{
+
+    /**
+     * ListPartsInfo constructor.
+     * @param string $bucket
+     * @param string $key
+     * @param string $uploadId
+     * @param int $nextPartNumberMarker
+     * @param int $maxParts
+     * @param string $isTruncated
+     * @param array $listPart
+     */
+    public function __construct($bucket, $key, $uploadId, $nextPartNumberMarker, $maxParts, $isTruncated, array $listPart)
+    {
+        $this->bucket = $bucket;
+        $this->key = $key;
+        $this->uploadId = $uploadId;
+        $this->nextPartNumberMarker = $nextPartNumberMarker;
+        $this->maxParts = $maxParts;
+        $this->isTruncated = $isTruncated;
+        $this->listPart = $listPart;
+    }
+
+    /**
+     * @return string
+     */
+    public function getBucket()
+    {
+        return $this->bucket;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getUploadId()
+    {
+        return $this->uploadId;
+    }
+
+    /**
+     * @return int
+     */
+    public function getNextPartNumberMarker()
+    {
+        return $this->nextPartNumberMarker;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxParts()
+    {
+        return $this->maxParts;
+    }
+
+    /**
+     * @return string
+     */
+    public function getIsTruncated()
+    {
+        return $this->isTruncated;
+    }
+
+    /**
+     * @return array
+     */
+    public function getListPart()
+    {
+        return $this->listPart;
+    }
+
+    private $bucket = "";
+    private $key = "";
+    private $uploadId = "";
+    private $nextPartNumberMarker = 0;
+    private $maxParts = 0;
+    private $isTruncated = "";
+    private $listPart = array();
+}

+ 121 - 0
sdk/OSS/Model/LiveChannelConfig.php

@@ -0,0 +1,121 @@
+<?php
+
+namespace OSS\Model;
+
+
+/**
+ * Class LiveChannelConfig
+ * @package OSS\Model
+ */
+class LiveChannelConfig implements XmlConfig
+{
+    public function __construct($option = array())
+    {
+        if (isset($option['description'])) {
+            $this->description = $option['description'];
+        }
+        if (isset($option['status'])) {
+            $this->status = $option['status'];
+        }
+        if (isset($option['type'])) {
+            $this->type = $option['type'];
+        }
+        if (isset($option['fragDuration'])) {
+            $this->fragDuration = $option['fragDuration'];
+        }
+        if (isset($option['fragCount'])) {
+            $this->fragCount = $option['fragCount'];
+        }
+        if (isset($option['playListName'])) {
+            $this->playListName = $option['playListName'];
+        }
+    }
+
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    public function getFragDuration()
+    {
+        return $this->fragDuration;
+    }
+
+    public function getFragCount()
+    {
+        return $this->fragCount;
+    }
+
+    public function getPlayListName()
+    {
+        return $this->playListName;
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        $this->description = strval($xml->Description);
+        $this->status = strval($xml->Status);
+        $target = $xml->Target;
+        $this->type = strval($target->Type);
+        $this->fragDuration = intval($target->FragDuration);
+        $this->fragCount = intval($target->FragCount);
+        $this->playListName = strval($target->PlayListName);
+    }
+
+    public function serializeToXml()
+    {
+        $strXml = <<<EOF
+<?xml version="1.0" encoding="utf-8"?>
+<LiveChannelConfiguration>
+</LiveChannelConfiguration>
+EOF;
+        $xml = new \SimpleXMLElement($strXml);
+        if (isset($this->description)) {
+            $xml->addChild('Description', $this->description);
+        }
+
+        if (isset($this->status)) {
+            $xml->addChild('Status', $this->status);
+        }
+
+        $node = $xml->addChild('Target');
+        $node->addChild('Type', $this->type);
+
+        if (isset($this->fragDuration)) {
+            $node->addChild('FragDuration', $this->fragDuration);
+        }
+
+        if (isset($this->fragCount)) {
+            $node->addChild('FragCount', $this->fragCount);
+        }
+
+        if (isset($this->playListName)) {
+            $node->addChild('PlayListName', $this->playListName);
+        }
+
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+    
+    private $description;
+    private $status = "enabled";
+    private $type;
+    private $fragDuration = 5;
+    private $fragCount = 3;
+    private $playListName = "playlist.m3u8";
+}

+ 59 - 0
sdk/OSS/Model/LiveChannelHistory.php

@@ -0,0 +1,59 @@
+<?php
+
+namespace OSS\Model;
+/**
+ * Class LiveChannelHistory
+ * @package OSS\Model
+ *
+ */
+class LiveChannelHistory implements XmlConfig
+{
+    public function __construct()
+    {
+    }
+
+    public function getStartTime()
+    {
+        return $this->startTime;
+    }
+
+    public function getEndTime()
+    {
+        return $this->endTime;
+    }
+
+    public function getRemoteAddr()
+    {
+        return $this->remoteAddr;
+    }
+
+    public function parseFromXmlNode($xml)
+    {
+        if (isset($xml->StartTime)) {
+            $this->startTime = strval($xml->StartTime);
+        }
+
+        if (isset($xml->EndTime)) {
+            $this->endTime = strval($xml->EndTime);
+        }
+
+        if (isset($xml->RemoteAddr)) {
+            $this->remoteAddr = strval($xml->RemoteAddr);
+        }
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        $this->parseFromXmlNode($xml);
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $startTime;
+    private $endTime;
+    private $remoteAddr;
+}

+ 107 - 0
sdk/OSS/Model/LiveChannelInfo.php

@@ -0,0 +1,107 @@
+<?php
+
+namespace OSS\Model;
+/**
+ * Class LiveChannelInfo
+ * @package OSS\Model
+ *
+ */
+class LiveChannelInfo implements XmlConfig
+{
+    public function __construct($name = null, $description = null)
+    {
+        $this->name = $name;
+        $this->description = $description;
+        $this->publishUrls = array();
+        $this->playUrls = array();
+    }
+
+    public function getName()
+    {
+        return $this->name;
+    }
+
+    public function setName($name)
+    {
+        $this->name = $name;
+    }
+
+    public function getPublishUrls()
+    {
+        return $this->publishUrls;
+    }
+
+    public function getPlayUrls()
+    {
+        return $this->playUrls;
+    }
+
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    public function getLastModified()
+    {
+        return $this->lastModified;
+    }
+
+    public function getDescription()
+    {
+        return $this->description;
+    }
+
+    public function setDescription($description)
+    {
+        $this->description = $description;
+    }
+
+    public function parseFromXmlNode($xml)
+    {
+        if (isset($xml->Name)) {
+            $this->name = strval($xml->Name);
+        }
+
+        if (isset($xml->Description)) {
+            $this->description = strval($xml->Description);
+        }
+
+        if (isset($xml->Status)) {
+            $this->status = strval($xml->Status);
+        }
+
+        if (isset($xml->LastModified)) {
+            $this->lastModified = strval($xml->LastModified);
+        }
+
+        if (isset($xml->PublishUrls)) {
+            foreach ($xml->PublishUrls as $url) {
+                $this->publishUrls[] = strval($url->Url);
+            }
+        }
+
+        if (isset($xml->PlayUrls)) {
+            foreach ($xml->PlayUrls as $url) {
+                $this->playUrls[] = strval($url->Url);
+            }
+        }
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        $this->parseFromXmlNode($xml);
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $name;
+    private $description;
+    private $publishUrls;
+    private $playUrls;
+    private $status;
+    private $lastModified;
+}

+ 107 - 0
sdk/OSS/Model/LiveChannelListInfo.php

@@ -0,0 +1,107 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class LiveChannelListInfo
+ *
+ * The data returned by ListBucketLiveChannels
+ *
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/GetBucket.html
+ */
+class LiveChannelListInfo implements XmlConfig
+{
+    /**
+     * @return string
+     */
+    public function getBucketName()
+    {
+        return $this->bucket;
+    }
+
+    public function setBucketName($name)
+    {
+        $this->bucket = $name;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * @return string
+     */
+    public function getMarker()
+    {
+        return $this->marker;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxKeys()
+    {
+        return $this->maxKeys;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getIsTruncated()
+    {
+        return $this->isTruncated;
+    }
+
+    /**
+     * @return LiveChannelInfo[]
+     */
+    public function getChannelList()
+    {
+        return $this->channelList;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextMarker()
+    {
+        return $this->nextMarker;
+    }
+
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+
+        $this->prefix = strval($xml->Prefix);
+        $this->marker = strval($xml->Marker);
+        $this->maxKeys = intval($xml->MaxKeys);
+        $this->isTruncated = (strval($xml->IsTruncated) == 'true');
+        $this->nextMarker = strval($xml->NextMarker);
+
+        if (isset($xml->LiveChannel)) {
+            foreach ($xml->LiveChannel as $chan) {
+                $channel = new LiveChannelInfo();
+                $channel->parseFromXmlNode($chan);
+                $this->channelList[] = $channel;
+            }
+        }
+    }
+
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+    
+    private $bucket = '';
+    private $prefix = '';
+    private $marker = '';
+    private $nextMarker = '';
+    private $maxKeys = 100;
+    private $isTruncated = 'false';
+    private $channelList = array();
+}

+ 86 - 0
sdk/OSS/Model/LoggingConfig.php

@@ -0,0 +1,86 @@
+<?php
+
+namespace OSS\Model;
+
+
+/**
+ * Class LoggingConfig
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketLogging.html
+ */
+class LoggingConfig implements XmlConfig
+{
+    /**
+     * LoggingConfig constructor.
+     * @param null $targetBucket
+     * @param null $targetPrefix
+     */
+    public function __construct($targetBucket = null, $targetPrefix = null)
+    {
+        $this->targetBucket = $targetBucket;
+        $this->targetPrefix = $targetPrefix;
+    }
+
+    /**
+     * @param $strXml
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->LoggingEnabled)) return;
+        foreach ($xml->LoggingEnabled as $status) {
+            foreach ($status as $key => $value) {
+                if ($key === 'TargetBucket') {
+                    $this->targetBucket = strval($value);
+                } elseif ($key === 'TargetPrefix') {
+                    $this->targetPrefix = strval($value);
+                }
+            }
+            break;
+        }
+    }
+
+    /**
+     *  Serialize to xml string
+     *
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><BucketLoggingStatus></BucketLoggingStatus>');
+        if (isset($this->targetBucket) && isset($this->targetPrefix)) {
+            $loggingEnabled = $xml->addChild('LoggingEnabled');
+            $loggingEnabled->addChild('TargetBucket', $this->targetBucket);
+            $loggingEnabled->addChild('TargetPrefix', $this->targetPrefix);
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     * @return string
+     */
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return string
+     */
+    public function getTargetBucket()
+    {
+        return $this->targetBucket;
+    }
+
+    /**
+     * @return string
+     */
+    public function getTargetPrefix()
+    {
+        return $this->targetPrefix;
+    }
+
+    private $targetBucket = "";
+    private $targetPrefix = "";
+
+}

+ 93 - 0
sdk/OSS/Model/ObjectInfo.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ *
+ * Class ObjectInfo
+ *
+ * The element type of ObjectListInfo, which is the return value type of listObjects
+ *
+ * The return value of listObjects includes two arrays
+ * One is the returned ObjectListInfo, which is similar to a file list in a file system.
+ * The other is the returned prefix list, which is similar to a folder list in a file system.
+ *
+ * @package OSS\Model
+ */
+class ObjectInfo
+{
+    /**
+     * ObjectInfo constructor.
+     *
+     * @param string $key
+     * @param string $lastModified
+     * @param string $eTag
+     * @param string $type
+     * @param int $size
+     * @param string $storageClass
+     */
+    public function __construct($key, $lastModified, $eTag, $type, $size, $storageClass)
+    {
+        $this->key = $key;
+        $this->lastModified = $lastModified;
+        $this->eTag = $eTag;
+        $this->type = $type;
+        $this->size = $size;
+        $this->storageClass = $storageClass;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getLastModified()
+    {
+        return $this->lastModified;
+    }
+
+    /**
+     * @return string
+     */
+    public function getETag()
+    {
+        return $this->eTag;
+    }
+
+    /**
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * @return string
+     */
+    public function getStorageClass()
+    {
+        return $this->storageClass;
+    }
+
+    private $key = "";
+    private $lastModified = "";
+    private $eTag = "";
+    private $type = "";
+    private $size = 0;
+    private $storageClass = "";
+}

+ 126 - 0
sdk/OSS/Model/ObjectListInfo.php

@@ -0,0 +1,126 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class ObjectListInfo
+ *
+ * The class of return value of ListObjects
+ *
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/GetBucket.html
+ */
+class ObjectListInfo
+{
+    /**
+     * ObjectListInfo constructor.
+     *
+     * @param string $bucketName
+     * @param string $prefix
+     * @param string $marker
+     * @param string $nextMarker
+     * @param string $maxKeys
+     * @param string $delimiter
+     * @param null $isTruncated
+     * @param array $objectList
+     * @param array $prefixList
+     */
+    public function __construct($bucketName, $prefix, $marker, $nextMarker, $maxKeys, $delimiter, $isTruncated, array $objectList, array $prefixList)
+    {
+        $this->bucketName = $bucketName;
+        $this->prefix = $prefix;
+        $this->marker = $marker;
+        $this->nextMarker = $nextMarker;
+        $this->maxKeys = $maxKeys;
+        $this->delimiter = $delimiter;
+        $this->isTruncated = $isTruncated;
+        $this->objectList = $objectList;
+        $this->prefixList = $prefixList;
+    }
+
+    /**
+     * @return string
+     */
+    public function getBucketName()
+    {
+        return $this->bucketName;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * @return string
+     */
+    public function getMarker()
+    {
+        return $this->marker;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxKeys()
+    {
+        return $this->maxKeys;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDelimiter()
+    {
+        return $this->delimiter;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getIsTruncated()
+    {
+        return $this->isTruncated;
+    }
+
+    /**
+     * Get the ObjectInfo list.
+     *
+     * @return ObjectInfo[]
+     */
+    public function getObjectList()
+    {
+        return $this->objectList;
+    }
+
+    /**
+     * Get the PrefixInfo list
+     *
+     * @return PrefixInfo[]
+     */
+    public function getPrefixList()
+    {
+        return $this->prefixList;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextMarker()
+    {
+        return $this->nextMarker;
+    }
+
+    private $bucketName = "";
+    private $prefix = "";
+    private $marker = "";
+    private $nextMarker = "";
+    private $maxKeys = 0;
+    private $delimiter = "";
+    private $isTruncated = null;
+    private $objectList = array();
+    private $prefixList = array();
+}

+ 114 - 0
sdk/OSS/Model/ObjectVersionInfo.php

@@ -0,0 +1,114 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ *
+ * Class ObjectVersionInfo
+ *
+ * The element type of ObjectVersionListInfo, which is the return value type of listObjectVersions
+ *
+ * The return value of listObjectVersions includes three arrays
+ * One is the returned ObjectVersionListInfo, which is similar to a file list in a file system.
+ * The other is the returned prefix list, which is similar to a folder list in a file system.
+ *
+ * @package OSS\Model
+ */
+class ObjectVersionInfo
+{
+    /**
+     * ObjectVersionInfo constructor.
+     *
+     * @param string $key
+     * @param string $lastModified
+     * @param string $eTag
+     * @param string $type
+     * @param int $size
+     * @param string $storageClass
+     * @param string $isLatest
+     */
+    public function __construct($key, $versionId, $lastModified, $eTag, $type, $size, $storageClass, $isLatest)
+    {
+        $this->key = $key;
+        $this->versionId = $versionId;
+        $this->lastModified = $lastModified;
+        $this->eTag = $eTag;
+        $this->type = $type;
+        $this->size = $size;
+        $this->storageClass = $storageClass;
+        $this->isLatest = $isLatest;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getVersionId()
+    {
+        return $this->versionId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getLastModified()
+    {
+        return $this->lastModified;
+    }
+
+    /**
+     * @return string
+     */
+    public function getETag()
+    {
+        return $this->eTag;
+    }
+
+    /**
+     * @return string
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
+    /**
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    /**
+     * @return string
+     */
+    public function getStorageClass()
+    {
+        return $this->storageClass;
+    }
+
+    /**
+     * @return string
+     */
+    public function getIsLatest()
+    {
+        return $this->isLatest;
+    }
+
+    private $key = "";
+    private $versionId = "";
+    private $lastModified = "";
+    private $eTag = "";
+    private $type = "";
+    private $size = 0;
+    private $storageClass = "";
+    private $isLatest = "";
+}

+ 162 - 0
sdk/OSS/Model/ObjectVersionListInfo.php

@@ -0,0 +1,162 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class ObjectVersionListInfo
+ *
+ * The class of return value of ListObjectVersions
+ *
+ * @package OSS\Model
+ */
+class ObjectVersionListInfo
+{
+    /**
+     * ObjectVersionListInfo constructor.
+     *
+     * @param string $bucketName
+     * @param string $prefix
+     * @param string $keyMarker
+     * @param string $nextKeyMarker
+     * @param string $versionIdMarker
+     * @param string $nextVersionIdMarker
+     * @param string $maxKeys
+     * @param string $delimiter
+     * @param null $isTruncated
+     * @param array $objectversionList
+     * @param array $deleteMarkerList
+     * @param array $prefixList
+     */
+    public function __construct($bucketName, $prefix, $keyMarker, $nextKeyMarker, $versionIdMarker, $nextVersionIdMarker
+        , $maxKeys, $delimiter, $isTruncated
+        , array $objectversionList, array $deleteMarkerList, array $prefixList)
+    {
+        $this->bucketName = $bucketName;
+        $this->prefix = $prefix;
+        $this->keyMarker = $keyMarker;
+        $this->nextKeyMarker = $nextKeyMarker;
+        $this->versionIdMarker = $versionIdMarker;
+        $this->nextVersionIdMarker = $nextVersionIdMarker;
+        $this->maxKeys = $maxKeys;
+        $this->delimiter = $delimiter;
+        $this->isTruncated = $isTruncated;
+        $this->objectVersionList = $objectversionList;
+        $this->deleteMarkerList = $deleteMarkerList;
+        $this->prefixList = $prefixList;
+    }
+
+    /**
+     * @return string
+     */
+    public function getBucketName()
+    {
+        return $this->bucketName;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKeyMarker()
+    {
+        return $this->keyMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextKeyMarker()
+    {
+        return $this->nextKeyMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getVersionIdMarker()
+    {
+        return $this->versionIdMarker;
+    }
+
+    /**
+     * @return string
+     */
+    public function getNextVersionIdMarker()
+    {
+        return $this->nextVersionIdMarker;
+    }
+
+    /**
+     * @return int
+     */
+    public function getMaxKeys()
+    {
+        return $this->maxKeys;
+    }
+
+    /**
+     * @return string
+     */
+    public function getDelimiter()
+    {
+        return $this->delimiter;
+    }
+
+    /**
+     * @return mixed
+     */
+    public function getIsTruncated()
+    {
+        return $this->isTruncated;
+    }
+
+    /**
+     * Get the ObjectVersionInfo list.
+     *
+     * @return ObjectVersionInfo[]
+     */
+    public function getObjectVersionList()
+    {
+        return $this->objectVersionList;
+    }
+
+    /**
+     * Get the DeleteMarkerInfo list.
+     *
+     * @return DeleteMarkerInfo[]
+     */
+    public function getDeleteMarkerList()
+    {
+        return $this->deleteMarkerList;
+    }
+
+    /**
+     * Get the PrefixInfo list
+     *
+     * @return PrefixInfo[]
+     */
+    public function getPrefixList()
+    {
+        return $this->prefixList;
+    }
+
+    private $bucketName = "";
+    private $prefix = "";
+    private $keyMarker = "";
+    private $nextKeyMarker = "";
+    private $versionIdmarker = "";
+    private $nextVersionIdMarker = "";
+    private $maxKeys = 0;
+    private $delimiter = "";
+    private $isTruncated = null;
+    private $objectVersionList = array();
+    private $deleteMarkerList = array();
+    private $prefixList = array();
+}

+ 63 - 0
sdk/OSS/Model/PartInfo.php

@@ -0,0 +1,63 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class PartInfo
+ * @package OSS\Model
+ */
+class PartInfo
+{
+    /**
+     * PartInfo constructor.
+     *
+     * @param int $partNumber
+     * @param string $lastModified
+     * @param string $eTag
+     * @param int $size
+     */
+    public function __construct($partNumber, $lastModified, $eTag, $size)
+    {
+        $this->partNumber = $partNumber;
+        $this->lastModified = $lastModified;
+        $this->eTag = $eTag;
+        $this->size = $size;
+    }
+
+    /**
+     * @return int
+     */
+    public function getPartNumber()
+    {
+        return $this->partNumber;
+    }
+
+    /**
+     * @return string
+     */
+    public function getLastModified()
+    {
+        return $this->lastModified;
+    }
+
+    /**
+     * @return string
+     */
+    public function getETag()
+    {
+        return $this->eTag;
+    }
+
+    /**
+     * @return int
+     */
+    public function getSize()
+    {
+        return $this->size;
+    }
+
+    private $partNumber = 0;
+    private $lastModified = "";
+    private $eTag = "";
+    private $size = 0;
+}

+ 36 - 0
sdk/OSS/Model/PrefixInfo.php

@@ -0,0 +1,36 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class PrefixInfo
+ *
+ * ListObjects return Prefix list of classes
+ * The returned data contains two arrays
+ * One is to get the list of objects【Can be understood as the corresponding file system file list】
+ * One is to get Prefix list【Can be understood as the corresponding file system directory list】
+ *
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/GetBucket.html
+ */
+class PrefixInfo
+{
+    /**
+     * PrefixInfo constructor.
+     * @param string $prefix
+     */
+    public function __construct($prefix)
+    {
+        $this->prefix = $prefix;
+    }
+
+    /**
+     * @return string
+     */
+    public function getPrefix()
+    {
+        return $this->prefix;
+    }
+
+    private $prefix;
+}

+ 93 - 0
sdk/OSS/Model/RefererConfig.php

@@ -0,0 +1,93 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class RefererConfig
+ *
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketReferer.html
+ */
+class RefererConfig implements XmlConfig
+{
+    /**
+     * @param string $strXml
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->AllowEmptyReferer)) return;
+        if (!isset($xml->RefererList)) return;
+        $this->allowEmptyReferer =
+            (strval($xml->AllowEmptyReferer) === 'TRUE' || strval($xml->AllowEmptyReferer) === 'true') ? true : false;
+
+        foreach ($xml->RefererList->Referer as $key => $refer) {
+            $this->refererList[] = strval($refer);
+        }
+    }
+
+
+    /**
+     * serialize the RefererConfig object into xml string
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><RefererConfiguration></RefererConfiguration>');
+        if ($this->allowEmptyReferer) {
+            $xml->addChild('AllowEmptyReferer', 'true');
+        } else {
+            $xml->addChild('AllowEmptyReferer', 'false');
+        }
+        $refererList = $xml->addChild('RefererList');
+        foreach ($this->refererList as $referer) {
+            $refererList->addChild('Referer', $referer);
+        }
+        return $xml->asXML();
+    }
+
+    /**
+     * @return string
+     */
+    function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @param boolean $allowEmptyReferer
+     */
+    public function setAllowEmptyReferer($allowEmptyReferer)
+    {
+        $this->allowEmptyReferer = $allowEmptyReferer;
+    }
+
+    /**
+     * @param string $referer
+     */
+    public function addReferer($referer)
+    {
+        $this->refererList[] = $referer;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isAllowEmptyReferer()
+    {
+        return $this->allowEmptyReferer;
+    }
+
+    /**
+     * @return array
+     */
+    public function getRefererList()
+    {
+        return $this->refererList;
+    }
+
+    private $allowEmptyReferer = true;
+    private $refererList = array();
+}

+ 68 - 0
sdk/OSS/Model/RequestPaymentConfig.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class RequestPaymentConfig
+ * @package OSS\Model
+ *
+ * @link https://help.aliyun.com/document_detail/117914.htm
+ */
+class RequestPaymentConfig implements XmlConfig
+{
+    /**
+     * RequestPaymentConfig constructor.
+     * @param null $payer
+     */
+    public function __construct($payer = null)
+    {
+        $this->payer = $payer;
+    }
+
+    /**
+     * Parse ServerSideEncryptionConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (isset($xml->Payer)) {
+            $this->payer = strval($xml->Payer);
+        }
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><RequestPaymentConfiguration></RequestPaymentConfiguration>');
+        if (isset($this->payer)) {
+            $xml->addChild('Payer', $this->payer);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return string
+     */
+    public function getPayer()
+    {
+        return $this->payer;
+    }
+
+    private $payer = "";
+}

+ 77 - 0
sdk/OSS/Model/RestoreConfig.php

@@ -0,0 +1,77 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class RestoreConfig
+ * @package OSS\Model
+ *
+ */
+class RestoreConfig implements XmlConfig
+{
+    /**
+     * RestoreConfig constructor.
+     * @param int $day
+     * @param null $tier
+     */
+    public function __construct($day, $tier = null)
+    {
+        $this->day = $day;
+        $this->tier = $tier;
+    }
+
+    /**
+     * Parse RestoreConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        throw new OssException("Not implemented.");
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><RestoreRequest></RestoreRequest>');
+        $xml->addChild('Days', strval($this->day));
+        if (isset($this->tier)) {
+            $xml_param = $xml->addChild('JobParameters');
+            $xml_param->addChild('Tier', $this->tier);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return int
+     */
+    public function getDay()
+    {
+        return $this->day;
+    }
+
+    /**
+     * @return string
+     */
+    public function getTier()
+    {
+        return $this->tier;
+    }
+
+    private $day = 1;
+    private $tier = 'Standard';
+}

+ 91 - 0
sdk/OSS/Model/ServerSideEncryptionConfig.php

@@ -0,0 +1,91 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class ServerSideEncryptionConfig
+ * @package OSS\Model
+ *
+ * @link https://help.aliyun.com/document_detail/117914.htm
+ */
+class ServerSideEncryptionConfig implements XmlConfig
+{
+    /**
+     * ServerSideEncryptionConfig constructor.
+     * @param null $sseAlgorithm
+     * @param null $kmsMasterKeyID
+     */
+    public function __construct($sseAlgorithm = null, $kmsMasterKeyID = null)
+    {
+        $this->sseAlgorithm = $sseAlgorithm;
+        $this->kmsMasterKeyID = $kmsMasterKeyID;
+    }
+
+    /**
+     * Parse ServerSideEncryptionConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->ApplyServerSideEncryptionByDefault)) return;
+        foreach ($xml->ApplyServerSideEncryptionByDefault as $default) {
+            foreach ($default as $key => $value) {
+                if ($key === 'SSEAlgorithm') {
+                    $this->sseAlgorithm = strval($value);
+                } elseif ($key === 'KMSMasterKeyID') {
+                    $this->kmsMasterKeyID = strval($value);
+                }
+            }
+            break;
+        }
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><ServerSideEncryptionRule></ServerSideEncryptionRule>');
+        $default = $xml->addChild('ApplyServerSideEncryptionByDefault');
+        if (isset($this->sseAlgorithm)) {
+            $default->addChild('SSEAlgorithm', $this->sseAlgorithm);
+        }
+        if (isset($this->kmsMasterKeyID)) {
+            $default->addChild('KMSMasterKeyID', $this->kmsMasterKeyID);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return string
+     */
+    public function getSSEAlgorithm()
+    {
+        return $this->sseAlgorithm;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKMSMasterKeyID()
+    {
+        return $this->kmsMasterKeyID;
+    }
+
+    private $sseAlgorithm = "";
+    private $kmsMasterKeyID = "";
+}

+ 76 - 0
sdk/OSS/Model/StorageCapacityConfig.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace OSS\Model;
+
+use OSS\Core\OssException;
+
+/**
+ * Class StorageCapacityConfig
+ *
+ * @package OSS\Model
+ * @link http://docs.alibaba-inc.com/pages/viewpage.action?pageId=271614763
+ */
+class StorageCapacityConfig implements XmlConfig
+{
+    /**
+     * StorageCapacityConfig constructor.
+     *
+     * @param int $storageCapacity            
+     */
+    public function __construct($storageCapacity)
+    {
+        $this->storageCapacity = $storageCapacity;
+    }
+
+    /**
+     * Not implemented
+     */
+    public function parseFromXml($strXml)
+    {
+        throw new OssException("Not implemented.");
+    }
+
+    /**
+     * Serialize StorageCapacityConfig into xml
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><BucketUserQos></BucketUserQos>');
+        $xml->addChild('StorageCapacity', strval($this->storageCapacity));
+        return $xml->asXML();
+    }
+
+    /**
+     * To string
+     *
+     * @return string
+     */
+    function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * Set storage capacity
+     *
+     * @param int $storageCapacity            
+     */
+    public function setStorageCapacity($storageCapacity)
+    {
+        $this->storageCapacity = $storageCapacity;
+    }
+
+    /**
+     * Get storage capacity
+     * 
+     * @return int
+     */
+    public function getStorageCapacity()
+    {
+        return $this->storageCapacity;
+    }
+
+    private $storageCapacity = 0;
+}

+ 41 - 0
sdk/OSS/Model/Tag.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class Tag
+ * @package OSS\Model
+ */
+class Tag
+{
+    /**
+     * Tag constructor.
+     *
+     * @param string $key
+     * @param string $value
+     */
+    public function __construct($key, $value)
+    {
+        $this->key = $key;
+        $this->value = $value;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getValue()
+    {
+        return $this->value;
+    }
+
+    private $key = "";
+    private $value = "";
+}

+ 89 - 0
sdk/OSS/Model/TaggingConfig.php

@@ -0,0 +1,89 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class TaggingConfig
+ * @package OSS\Model
+ *
+ */
+class TaggingConfig implements XmlConfig
+{
+    /**
+     * TaggingConfig constructor.
+     */
+    public function __construct()
+    {
+        $this->tags = array();
+    }
+
+    /**
+     * Get Tag list
+     *
+     * @return Tag[]
+     */
+    public function getTags()
+    {
+        return $this->tags;
+    }
+
+
+    /**
+     * Add a new Tag
+     *
+     * @param Tag $tag
+     * @throws OssException
+     */
+    public function addTag($tag)
+    {
+        $this->tags[] = $tag;
+    }
+
+    /**
+     * Parse TaggingConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (!isset($xml->TagSet) || !isset($xml->TagSet->Tag)) return;
+        foreach ($xml->TagSet->Tag as $tag) {
+            $this->addTag(new Tag($tag->Key, $tag->Value));
+        }
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><Tagging></Tagging>');
+        $xmlTagSet = $xml->addChild('TagSet');
+        foreach ($this->tags as $tag) {
+            $xmlTag = $xmlTagSet->addChild('Tag');
+            $xmlTag->addChild('Key', strval($tag->getKey()));
+            $xmlTag->addChild('Value', strval($tag->getValue()));
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * Tag list
+     *
+     * @var Tag[]
+     */
+    private $tags = array();
+}

+ 55 - 0
sdk/OSS/Model/UploadInfo.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Class UploadInfo
+ *
+ * The return value of ListMultipartUpload
+ *
+ * @package OSS\Model
+ */
+class UploadInfo
+{
+    /**
+     * UploadInfo constructor.
+     *
+     * @param string $key
+     * @param string $uploadId
+     * @param string $initiated
+     */
+    public function __construct($key, $uploadId, $initiated)
+    {
+        $this->key = $key;
+        $this->uploadId = $uploadId;
+        $this->initiated = $initiated;
+    }
+
+    /**
+     * @return string
+     */
+    public function getKey()
+    {
+        return $this->key;
+    }
+
+    /**
+     * @return string
+     */
+    public function getUploadId()
+    {
+        return $this->uploadId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getInitiated()
+    {
+        return $this->initiated;
+    }
+
+    private $key = "";
+    private $uploadId = "";
+    private $initiated = "";
+}

+ 67 - 0
sdk/OSS/Model/VersioningConfig.php

@@ -0,0 +1,67 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class VersioningConfig
+ * @package OSS\Model
+ *
+ */
+class VersioningConfig implements XmlConfig
+{
+    /**
+     * VersioningConfig constructor.
+     * @param null $status
+     */
+    public function __construct($status = null)
+    {
+        $this->status = $status;
+    }
+
+    /**
+     * Parse VersioningConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (isset($xml->Status)) {
+            $this->status = strval($xml->Status);
+        }
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><VersioningConfiguration></VersioningConfiguration>');
+        if (isset($this->status)) {
+            $xml->addChild('Status', $this->status);
+        }
+        return $xml->asXML();
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return string
+     */
+    public function getStatus()
+    {
+        return $this->status;
+    }
+
+    private $status = "";
+}

+ 76 - 0
sdk/OSS/Model/WebsiteConfig.php

@@ -0,0 +1,76 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+
+/**
+ * Class WebsiteConfig
+ * @package OSS\Model
+ * @link http://help.aliyun.com/document_detail/oss/api-reference/bucket/PutBucketWebsite.html
+ */
+class WebsiteConfig implements XmlConfig
+{
+    /**
+     * WebsiteConfig constructor.
+     * @param  string $indexDocument
+     * @param  string $errorDocument
+     */
+    public function __construct($indexDocument = "", $errorDocument = "")
+    {
+        $this->indexDocument = $indexDocument;
+        $this->errorDocument = $errorDocument;
+    }
+
+    /**
+     * @param string $strXml
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (isset($xml->IndexDocument) && isset($xml->IndexDocument->Suffix)) {
+            $this->indexDocument = strval($xml->IndexDocument->Suffix);
+        }
+        if (isset($xml->ErrorDocument) && isset($xml->ErrorDocument->Key)) {
+            $this->errorDocument = strval($xml->ErrorDocument->Key);
+        }
+    }
+
+    /**
+     * Serialize the WebsiteConfig object into xml string.
+     *
+     * @return string
+     * @throws OssException
+     */
+    public function serializeToXml()
+    {
+        $xml = new \SimpleXMLElement('<?xml version="1.0" encoding="utf-8"?><WebsiteConfiguration></WebsiteConfiguration>');
+        $index_document_part = $xml->addChild('IndexDocument');
+        $error_document_part = $xml->addChild('ErrorDocument');
+        $index_document_part->addChild('Suffix', $this->indexDocument);
+        $error_document_part->addChild('Key', $this->errorDocument);
+        return $xml->asXML();
+    }
+
+    /**
+     * @return string
+     */
+    public function getIndexDocument()
+    {
+        return $this->indexDocument;
+    }
+
+    /**
+     * @return string
+     */
+    public function getErrorDocument()
+    {
+        return $this->errorDocument;
+    }
+
+    private $indexDocument = "";
+    private $errorDocument = "";
+}

+ 90 - 0
sdk/OSS/Model/WormConfig.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace OSS\Model;
+
+
+use OSS\Core\OssException;
+
+/**
+ * Class WormConfig
+ * @package OSS\Model
+ *
+ */
+class WormConfig implements XmlConfig
+{
+    /**
+     * Parse WormConfig from the xml.
+     *
+     * @param string $strXml
+     * @throws OssException
+     * @return null
+     */
+    public function parseFromXml($strXml)
+    {
+        $xml = simplexml_load_string($strXml);
+        if (isset($xml->WormId)) {
+            $this->wormId = strval($xml->WormId);
+        }
+        if (isset($xml->State)) {
+            $this->state = strval($xml->State);
+        }
+        if (isset($xml->RetentionPeriodInDays)) {
+            $this->day = intval($xml->RetentionPeriodInDays);
+        }
+        if (isset($xml->CreationDate)) {
+            $this->creationDate = strval($xml->CreationDate);
+        }
+    }
+
+    /**
+     * Serialize the object into xml string.
+     *
+     * @return string
+     */
+    public function serializeToXml()
+    {
+        throw new OssException("Not implemented.");
+    }
+
+    public function __toString()
+    {
+        return $this->serializeToXml();
+    }
+
+    /**
+     * @return string
+     */
+    public function getWormId()
+    {
+        return $this->wormId;
+    }
+
+    /**
+     * @return string
+     */
+    public function getState()
+    {
+        return $this->state;
+    }
+
+    /**
+     * @return int
+     */
+    public function getDay()
+    {
+        return $this->day;
+    }
+
+    /**
+     * @return string
+     */
+    public function getCreationDate()
+    {
+        return $this->creationDate;
+    }
+
+    private $wormId = '';
+    private $state = '';
+    private $creationDate = '';
+    private $day = 0;
+}

+ 27 - 0
sdk/OSS/Model/XmlConfig.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace OSS\Model;
+
+/**
+ * Interface XmlConfig
+ * @package OSS\Model
+ */
+interface XmlConfig
+{
+
+    /**
+     * Interface method: Parse the object from the xml.
+     *
+     * @param string $strXml
+     * @return null
+     */
+    public function parseFromXml($strXml);
+
+    /**
+     * Interface method: Serialize the object into xml.
+     *
+     * @return string
+     */
+    public function serializeToXml();
+
+}

+ 3529 - 0
sdk/OSS/OssClient.php

@@ -0,0 +1,3529 @@
+<?php
+namespace OSS;
+
+use OSS\Core\MimeTypes;
+use OSS\Core\OssException;
+use OSS\Http\RequestCore;
+use OSS\Http\RequestCore_Exception;
+use OSS\Http\ResponseCore;
+use OSS\Model\CorsConfig;
+use OSS\Model\CnameConfig;
+use OSS\Model\LoggingConfig;
+use OSS\Model\LiveChannelConfig;
+use OSS\Model\LiveChannelInfo;
+use OSS\Model\LiveChannelListInfo;
+use OSS\Model\StorageCapacityConfig;
+use OSS\Result\AclResult;
+use OSS\Result\BodyResult;
+use OSS\Result\GetCorsResult;
+use OSS\Result\GetLifecycleResult;
+use OSS\Result\GetLocationResult;
+use OSS\Result\GetLoggingResult;
+use OSS\Result\GetRefererResult;
+use OSS\Result\GetStorageCapacityResult;
+use OSS\Result\GetWebsiteResult;
+use OSS\Result\GetCnameResult;
+use OSS\Result\HeaderResult;
+use OSS\Result\InitiateMultipartUploadResult;
+use OSS\Result\ListBucketsResult;
+use OSS\Result\ListMultipartUploadResult;
+use OSS\Model\ListMultipartUploadInfo;
+use OSS\Result\ListObjectsResult;
+use OSS\Result\ListPartsResult;
+use OSS\Result\PutSetDeleteResult;
+use OSS\Result\DeleteObjectsResult;
+use OSS\Result\CopyObjectResult;
+use OSS\Result\CallbackResult;
+use OSS\Result\ExistResult;
+use OSS\Result\PutLiveChannelResult;
+use OSS\Result\GetLiveChannelHistoryResult;
+use OSS\Result\GetLiveChannelInfoResult;
+use OSS\Result\GetLiveChannelStatusResult;
+use OSS\Result\ListLiveChannelResult;
+use OSS\Result\AppendResult;
+use OSS\Model\ObjectListInfo;
+use OSS\Result\SymlinkResult;
+use OSS\Result\UploadPartResult;
+use OSS\Model\BucketListInfo;
+use OSS\Model\LifecycleConfig;
+use OSS\Model\RefererConfig;
+use OSS\Model\WebsiteConfig;
+use OSS\Core\OssUtil;
+use OSS\Model\ListPartsInfo;
+use OSS\Result\GetBucketInfoResult;
+use OSS\Model\BucketStat;
+use OSS\Result\GetBucketStatResult;
+use OSS\Model\ServerSideEncryptionConfig;
+use OSS\Result\GetBucketEncryptionResult;
+use OSS\Model\RequestPaymentConfig;
+use OSS\Result\GetBucketRequestPaymentResult;
+use OSS\Model\Tag;
+use OSS\Model\TaggingConfig;
+use OSS\Result\GetBucketTagsResult;
+use OSS\Model\VersioningConfig;
+use OSS\Result\GetBucketVersioningResult;
+use OSS\Model\InitiateWormConfig;
+use OSS\Result\InitiateBucketWormResult;
+use OSS\Model\ExtendWormConfig;
+use OSS\Result\GetBucketWormResult;
+use OSS\Model\RestoreConfig;
+use OSS\Model\ObjectVersionListInfo;
+use OSS\Result\ListObjectVersionsResult;
+use OSS\Model\DeleteObjectInfo;
+use OSS\Model\DeletedObjectInfo;
+use OSS\Result\DeleteObjectVersionsResult;
+
+/**
+ * Class OssClient
+ *
+ * Object Storage Service(OSS)'s client class, which wraps all OSS APIs user could call to talk to OSS.
+ * Users could do operations on bucket, object, including MultipartUpload or setting ACL via an OSSClient instance.
+ * For more details, please check out the OSS API document:https://www.alibabacloud.com/help/doc-detail/31947.htm
+ */
+class OssClient
+{
+    /**
+     * Constructor
+     *
+     * There're a few different ways to create an OssClient object:
+     * 1. Most common one from access Id, access Key and the endpoint: $ossClient = new OssClient($id, $key, $endpoint)
+     * 2. If the endpoint is the CName (such as www.testoss.com, make sure it's CName binded in the OSS console), 
+     *    uses $ossClient = new OssClient($id, $key, $endpoint, true)
+     * 3. If using Alicloud's security token service (STS), then the AccessKeyId, AccessKeySecret and STS token are all got from STS.
+     * Use this: $ossClient = new OssClient($id, $key, $endpoint, false, $token)
+     * 4. If the endpoint is in IP format, you could use this: $ossClient = new OssClient($id, $key, “1.2.3.4:8900”)
+     *
+     * @param string $accessKeyId The AccessKeyId from OSS or STS
+     * @param string $accessKeySecret The AccessKeySecret from OSS or STS
+     * @param string $endpoint The domain name of the datacenter,For example: oss-cn-hangzhou.aliyuncs.com
+     * @param boolean $isCName If this is the CName and binded in the bucket.
+     * @param string $securityToken from STS.
+     * @param string $requestProxy
+     * @throws OssException
+     */
+    public function __construct($accessKeyId, $accessKeySecret, $endpoint, $isCName = false, $securityToken = NULL, $requestProxy = NULL)
+    {
+        $accessKeyId = trim($accessKeyId);
+        $accessKeySecret = trim($accessKeySecret);
+        $endpoint = trim(trim($endpoint), "/");
+
+        if (empty($accessKeyId)) {
+            throw new OssException("access key id is empty");
+        }
+        if (empty($accessKeySecret)) {
+            throw new OssException("access key secret is empty");
+        }
+        if (empty($endpoint)) {
+            throw new OssException("endpoint is empty");
+        }
+        $this->hostname = $this->checkEndpoint($endpoint, $isCName);
+        $this->accessKeyId = $accessKeyId;
+        $this->accessKeySecret = $accessKeySecret;
+        $this->securityToken = $securityToken;
+        $this->requestProxy = $requestProxy;
+        self::checkEnv();
+    }
+
+    /**
+     * Lists the Bucket [GetService]. Not applicable if the endpoint is CName (because CName must be binded to a specific bucket).
+     *
+     * @param array $options
+     * @throws OssException
+     * @return BucketListInfo
+     */
+    public function listBuckets($options = NULL)
+    {
+        if ($this->hostType === self::OSS_HOST_TYPE_CNAME) {
+            throw new OssException("operation is not permitted with CName host");
+        }
+        $this->precheckOptions($options);
+        $options[self::OSS_BUCKET] = '';
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $response = $this->auth($options);
+        $result = new ListBucketsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Creates bucket,The ACL of the bucket created by default is OssClient::OSS_ACL_TYPE_PRIVATE
+     *
+     * @param string $bucket
+     * @param string $acl
+     * @param array $options
+     * @param string $storageType
+     * @return null
+     */
+    public function createBucket($bucket, $acl = self::OSS_ACL_TYPE_PRIVATE, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
+        if (isset($options[self::OSS_STORAGE])) {
+            $this->precheckStorage($options[self::OSS_STORAGE]);
+            $options[self::OSS_CONTENT] = OssUtil::createBucketXmlBody($options[self::OSS_STORAGE]);
+            unset($options[self::OSS_STORAGE]);
+        }
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes bucket
+     * The deletion will not succeed if the bucket is not empty (either has objects or parts)
+     * To delete a bucket, all its objects and parts must be deleted first.
+     *
+     * @param string $bucket
+     * @param array $options
+     * @return null
+     */
+    public function deleteBucket($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Checks if a bucket exists
+     *
+     * @param string $bucket
+     * @return bool
+     * @throws OssException
+     */
+    public function doesBucketExist($bucket)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'acl';
+        $response = $this->auth($options);
+        $result = new ExistResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the data center location information for the bucket
+     *
+     * @param string $bucket
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getBucketLocation($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'location';
+        $response = $this->auth($options);
+        $result = new GetLocationResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the Meta information for the Bucket
+     *
+     * @param string $bucket
+     * @param array $options  Refer to the SDK documentation
+     * @return array
+     */
+    public function getBucketMeta($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
+        $options[self::OSS_OBJECT] = '/';
+        $response = $this->auth($options);
+        $result = new HeaderResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the bucket ACL
+     *
+     * @param string $bucket
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getBucketAcl($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'acl';
+        $response = $this->auth($options);
+        $result = new AclResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bucket ACL
+     *
+     * @param string $bucket bucket name
+     * @param string $acl access permissions, valid values are ['private', 'public-read', 'public-read-write']
+     * @param array $options by default is empty
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketAcl($bucket, $acl, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_HEADERS] = array(self::OSS_ACL => $acl);
+        $options[self::OSS_SUB_RESOURCE] = 'acl';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets object ACL
+     *
+     * @param string $bucket
+     * @param string $object
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getObjectAcl($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options, true);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = 'acl';
+        $response = $this->auth($options);
+        $result = new AclResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the object ACL
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $acl access permissions, valid values are ['default', 'private', 'public-read', 'public-read-write']
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putObjectAcl($bucket, $object, $acl, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options, true);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_ACL => $acl);
+        $options[self::OSS_SUB_RESOURCE] = 'acl';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the bucket logging config
+     *
+     * @param string $bucket bucket name
+     * @param array $options by default is empty
+     * @throws OssException
+     * @return LoggingConfig
+     */
+    public function getBucketLogging($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'logging';
+        $response = $this->auth($options);
+        $result = new GetLoggingResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bycket logging config. Only owner can call this API.
+     *
+     * @param string $bucket bucket name
+     * @param string $targetBucket The logging file's bucket
+     * @param string $targetPrefix The logging file's prefix
+     * @param array $options By default is empty.
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketLogging($bucket, $targetBucket, $targetPrefix, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $this->precheckBucket($targetBucket, 'targetbucket is not allowed empty');
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'logging';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+
+        $loggingConfig = new LoggingConfig($targetBucket, $targetPrefix);
+        $options[self::OSS_CONTENT] = $loggingConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket logging config
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketLogging($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'logging';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the website config in bucket---that is could make the bucket as a static website once the CName is binded.
+     *
+     * @param string $bucket bucket name
+     * @param WebsiteConfig $websiteConfig
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketWebsite($bucket, $websiteConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'website';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $websiteConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the website config in the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return WebsiteConfig
+     */
+    public function getBucketWebsite($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'website';
+        $response = $this->auth($options);
+        $result = new GetWebsiteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the website config in the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketWebsite($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'website';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the cross-origin-resource-sharing (CORS) rule. It would overwrite the originl one.
+     *
+     * @param string $bucket bucket name
+     * @param CorsConfig $corsConfig CORS config. Check out the details from OSS API document
+     * @param array $options array
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketCors($bucket, $corsConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cors';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $corsConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the bucket CORS config
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return CorsConfig
+     */
+    public function getBucketCors($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cors';
+        $response = $this->auth($options);
+        $result = new GetCorsResult($response, __FUNCTION__);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket's CORS config and disable the CORS on the bucket.
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketCors($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cors';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Bind a CName for the bucket
+     *
+     * @param string $bucket bucket name
+     * @param string $cname
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function addBucketCname($bucket, $cname, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cname';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $cnameConfig = new CnameConfig();
+        $cnameConfig->addCname($cname);
+        $options[self::OSS_CONTENT] = $cnameConfig->serializeToXml();
+        $options[self::OSS_COMP] = 'add';
+
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the binded CName list of the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return CnameConfig
+     */
+    public function getBucketCname($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cname';
+        $response = $this->auth($options);
+        $result = new GetCnameResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Remove a CName binding from the bucket
+     *
+     * @param string $bucket bucket name
+     * @param CnameConfig $cnameConfig
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketCname($bucket, $cname, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'cname';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $cnameConfig = new CnameConfig();
+        $cnameConfig->addCname($cname);
+        $options[self::OSS_CONTENT] = $cnameConfig->serializeToXml();
+        $options[self::OSS_COMP] = 'delete';
+
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Creates a Live Channel under a bucket
+     *
+     * @param string $bucket bucket name
+     * @param string channelName  $channelName
+     * @param LiveChannelConfig $channelConfig
+     * @param array $options
+     * @throws OssException
+     * @return LiveChannelInfo
+     */
+    public function putBucketLiveChannel($bucket, $channelName, $channelConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $channelConfig->serializeToXml();
+
+        $response = $this->auth($options);
+        $result = new PutLiveChannelResult($response);
+        $info = $result->getData();
+        $info->setName($channelName);
+        $info->setDescription($channelConfig->getDescription());
+        
+        return $info;
+    }
+
+    /**
+     * Sets the LiveChannel status
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param string channelStatus $channelStatus enabled or disabled
+     * @param array $options
+     * @throws OssException
+     * @return null 
+     */
+    public function putLiveChannelStatus($bucket, $channelName, $channelStatus, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+        $options[self::OSS_LIVE_CHANNEL_STATUS] = $channelStatus;
+
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the LiveChannel information by the channel name
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param array $options
+     * @throws OssException
+     * @return GetLiveChannelInfo
+     */
+    public function getLiveChannelInfo($bucket, $channelName, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+
+        $response = $this->auth($options);
+        $result = new GetLiveChannelInfoResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the status of LiveChannel
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param array $options
+     * @throws OssException
+     * @return GetLiveChannelStatus
+     */
+    public function getLiveChannelStatus($bucket, $channelName, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+        $options[self::OSS_COMP] = 'stat';
+      
+        $response = $this->auth($options);
+        $result = new GetLiveChannelStatusResult($response);
+        return $result->getData();
+    }
+
+     /**
+     * Gets the LiveChannel pushing streaming record
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param array $options
+     * @throws OssException
+     * @return GetLiveChannelHistory
+     */
+    public function getLiveChannelHistory($bucket, $channelName, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+        $options[self::OSS_COMP] = 'history';
+
+        $response = $this->auth($options);
+        $result = new GetLiveChannelHistoryResult($response);
+        return $result->getData();
+    }
+  
+    /**
+     *Gets the live channel list under a bucket.
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return LiveChannelListInfo
+     */
+    public function listBucketLiveChannels($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+        $options[self::OSS_QUERY_STRING] = array(
+            'prefix' => isset($options['prefix']) ? $options['prefix'] : '',
+            'marker' => isset($options['marker']) ? $options['marker'] : '',
+            'max-keys' => isset($options['max-keys']) ? $options['max-keys'] : '',
+        );
+        $response = $this->auth($options);
+        $result = new ListLiveChannelResult($response);
+        $list = $result->getData();
+        $list->setBucketName($bucket);
+
+        return $list;
+    }
+
+    /**
+     * Creates a play list file for the LiveChannel
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName 
+     * @param string $playlistName The playlist name, must end with ".m3u8".
+     * @param array $setTime  startTime and EndTime in unix time. No more than 1 day.
+     * @throws OssException
+     * @return null
+     */
+    public function postVodPlaylist($bucket, $channelName, $playlistName, $setTime)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = $channelName . '/' . $playlistName;
+        $options[self::OSS_SUB_RESOURCE] = 'vod';
+        $options[self::OSS_LIVE_CHANNEL_END_TIME] = $setTime['EndTime'];
+        $options[self::OSS_LIVE_CHANNEL_START_TIME] = $setTime['StartTime'];
+       
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the Bucket LiveChannel
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketLiveChannel($bucket, $channelName, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = $channelName;
+        $options[self::OSS_SUB_RESOURCE] = 'live';
+
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Generates the signed pushing streaming url
+     *
+     * @param string $bucket bucket name
+     * @param string channelName $channelName
+     * @param int timeout timeout value in seconds
+     * @param array $options
+     * @throws OssException
+     * @return The signed pushing streaming url
+     */
+    public function signRtmpUrl($bucket, $channelName, $timeout = 60, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $channelName, $options, false);
+        $expires = time() + $timeout;
+        $proto = 'rtmp://';
+        $hostname = $this->generateHostname($bucket);
+        $cano_params = '';
+        $query_items = array();
+        $params = isset($options['params']) ? $options['params'] : array();
+        uksort($params, 'strnatcasecmp');
+        foreach ($params as $key => $value) {
+            $cano_params = $cano_params . $key . ':' . $value . "\n";
+            $query_items[] = rawurlencode($key) . '=' . rawurlencode($value);
+        }
+        $resource = '/' . $bucket . '/' . $channelName;
+
+        $string_to_sign = $expires . "\n" . $cano_params . $resource;
+        $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true));
+
+        $query_items[] = 'OSSAccessKeyId=' . rawurlencode($this->accessKeyId);
+        $query_items[] = 'Expires=' . rawurlencode($expires);
+        $query_items[] = 'Signature=' . rawurlencode($signature);
+
+        return $proto . $hostname . '/live/' . $channelName . '?' . implode('&', $query_items);
+    }
+
+    /**
+     * Generates the signed pushing streaming url
+     *
+     * @param string $bucket bucket name
+     * @param string $channelName channel name
+     * @param int $expiration expiration time of the Url, unix epoch, since 1970.1.1 00.00.00 UTC
+     * @param array $options
+     * @throws OssException
+     * @return The signed pushing streaming url
+     */
+    public function generatePresignedRtmpUrl($bucket, $channelName, $expiration, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $channelName, $options, false);
+        $proto = 'rtmp://';
+        $hostname = $this->generateHostname($bucket);
+        $cano_params = '';
+        $query_items = array();
+        $params = isset($options['params']) ? $options['params'] : array();
+        uksort($params, 'strnatcasecmp');
+        foreach ($params as $key => $value) {
+            $cano_params = $cano_params . $key . ':' . $value . "\n";
+            $query_items[] = rawurlencode($key) . '=' . rawurlencode($value);
+        }
+        $resource = '/' . $bucket . '/' . $channelName;
+
+        $string_to_sign = $expiration . "\n" . $cano_params . $resource;
+        $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $this->accessKeySecret, true));
+
+        $query_items[] = 'OSSAccessKeyId=' . rawurlencode($this->accessKeyId);
+        $query_items[] = 'Expires=' . rawurlencode($expiration);
+        $query_items[] = 'Signature=' . rawurlencode($signature);
+
+        return $proto . $hostname . '/live/' . $channelName . '?' . implode('&', $query_items);
+    }
+
+    /**
+     * Precheck the CORS request. Before sending a CORS request, a preflight request (OPTIONS) is sent with the specific origin.
+     * HTTP METHOD and headers information are sent to OSS as well for evaluating if the CORS request is allowed. 
+     * 
+     * Note: OSS could enable the CORS on the bucket by calling putBucketCors. Once CORS is enabled, the OSS could evaluate accordingto the preflight request.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $origin the origin of the request
+     * @param string $request_method The actual HTTP method which will be used in CORS request
+     * @param string $request_headers The actual HTTP headers which will be used in CORS request
+     * @param array $options
+     * @return array
+     * @throws OssException
+     * @link http://help.aliyun.com/document_detail/oss/api-reference/cors/OptionObject.html
+     */
+    public function optionsObject($bucket, $object, $origin, $request_method, $request_headers, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_OPTIONS;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_HEADERS] = array(
+            self::OSS_OPTIONS_ORIGIN => $origin,
+            self::OSS_OPTIONS_REQUEST_HEADERS => $request_headers,
+            self::OSS_OPTIONS_REQUEST_METHOD => $request_method
+        );
+        $response = $this->auth($options);
+        $result = new HeaderResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bucket's lifecycle config
+     *
+     * @param string $bucket bucket name
+     * @param LifecycleConfig $lifecycleConfig LifecycleConfig instance
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketLifecycle($bucket, $lifecycleConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $lifecycleConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets bucket's lifecycle config
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return LifecycleConfig
+     */
+    public function getBucketLifecycle($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+        $response = $this->auth($options);
+        $result = new GetLifecycleResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket's lifecycle config
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketLifecycle($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'lifecycle';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets a bucket's referer, which has a whitelist of referrer and specifies if empty referer is allowed.
+     * Checks out API document for more details about "Bucket Referer" 
+     *
+     * @param string $bucket bucket name
+     * @param RefererConfig $refererConfig
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function putBucketReferer($bucket, $refererConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'referer';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $refererConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the bucket's Referer
+     * Checks out API document for more details about "Bucket Referer" 
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return RefererConfig
+     */
+    public function getBucketReferer($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'referer';
+        $response = $this->auth($options);
+        $result = new GetRefererResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Set the size of the bucket,the unit is GB
+     * When the capacity of the bucket is bigger than the set, it's forbidden to continue writing
+     *
+     * @param string $bucket bucket name
+     * @param int $storageCapacity
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function putBucketStorageCapacity($bucket, $storageCapacity, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'qos';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $storageCapacityConfig = new StorageCapacityConfig($storageCapacity);
+        $options[self::OSS_CONTENT] = $storageCapacityConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the capacity of the bucket, the unit is GB
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return int
+     */
+    public function getBucketStorageCapacity($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'qos';
+        $response = $this->auth($options);
+        $result = new GetStorageCapacityResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the information of the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return BucketInfo
+     */
+    public function getBucketInfo($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'bucketInfo';
+        $response = $this->auth($options);
+        $result = new GetBucketInfoResult($response);
+        return $result->getData();
+    }
+
+     /**
+     * Get the stat of the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return BucketStat
+     */
+    public function getBucketStat($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'stat';
+        $response = $this->auth($options);
+        $result = new GetBucketStatResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bucket's policy
+     *
+     * @param string $bucket bucket name
+     * @param string $policy policy json format content
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketPolicy($bucket, $policy, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'policy';
+        $options[self::OSS_CONTENT_TYPE] = 'application/json';
+        $options[self::OSS_CONTENT] = $policy;
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets bucket's policy
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return string policy json content
+     */
+    public function getBucketPolicy($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'policy';
+        $response = $this->auth($options);
+        $result = new BodyResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket's policy
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketPolicy($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'policy';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bucket's encryption
+     *
+     * @param string $bucket bucket name
+     * @param ServerSideEncryptionConfig $sseConfig
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketEncryption($bucket, $sseConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'encryption';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $sseConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets bucket's encryption
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return ServerSideEncryptionConfig
+     */
+    public function getBucketEncryption($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'encryption';
+        $response = $this->auth($options);
+        $result = new GetBucketEncryptionResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket's encryption
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketEncryption($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'encryption';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Set the request playment of the bucket, Can be BucketOwner and Requester
+     *
+     * @param string $bucket bucket name
+     * @param string $payer
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function putBucketRequestPayment($bucket, $payer, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'requestPayment';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $config = new RequestPaymentConfig($payer);
+        $options[self::OSS_CONTENT] = $config->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the request playment of the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getBucketRequestPayment($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'requestPayment';
+        $response = $this->auth($options);
+        $result = new GetBucketRequestPaymentResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the bucket's tags
+     *
+     * @param string $bucket bucket name
+     * @param TaggingConfig $taggingConfig
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function putBucketTags($bucket, $taggingConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $taggingConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets bucket's tags
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return TaggingConfig
+     */
+    public function getBucketTags($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        $response = $this->auth($options);
+        $result = new GetBucketTagsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the bucket's tags
+     * If want to delete specified tags for a bucket, please set the $tags
+     *
+     * @param string $bucket bucket name
+     * @param tag[] $tags (optional)
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function deleteBucketTags($bucket, $tags = NULL, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        if (empty($tags)) {
+            $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        } else {
+            $value = '';
+            foreach ($tags as $tag ) {
+                $value .= $tag->getKey().',';
+            }
+            $value = rtrim($value, ',');
+            $options[self::OSS_TAGGING] = $value;
+        }
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Set the versioning of the bucket, Can be BucketOwner and Requester
+     *
+     * @param string $bucket bucket name
+     * @param string $status
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function putBucketVersioning($bucket, $status, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'versioning';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $config = new VersioningConfig($status);
+        $options[self::OSS_CONTENT] = $config->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get the versioning of the bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getBucketVersioning($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'versioning';
+        $response = $this->auth($options);
+        $result = new GetBucketVersioningResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Initialize a bucket's worm
+     *
+     * @param string $bucket bucket name
+     * @param int $day
+     * @param array $options
+     * @throws OssException
+     * @return string returns uploadid
+     */
+    public function initiateBucketWorm($bucket, $day, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'worm';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $config = new InitiateWormConfig($day);
+        $options[self::OSS_CONTENT] = $config->serializeToXml();
+        $response = $this->auth($options);
+        $result = new InitiateBucketWormResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Aborts the bucket's worm
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return null
+     */
+    public function abortBucketWorm($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'worm';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+     /**
+     * Complete a bucket's worm
+     *
+     * @param string $bucket bucket name
+     * @param string $wormId
+     * @param array $options
+     * @throws OssException
+     * @return string returns uploadid
+     */
+    public function completeBucketWorm($bucket, $wormId, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_WORM_ID] = $wormId;
+        $options[self::OSS_CONTENT] = '';
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Extend a bucket's worm
+     *
+     * @param string $bucket bucket name
+     * @param string $wormId
+     * @param int $day
+     * @param array $options
+     * @throws OssException
+     * @return string returns uploadid
+     */
+    public function extendBucketWorm($bucket, $wormId, $day, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_WORM_ID] = $wormId;
+        $options[self::OSS_SUB_RESOURCE] = 'wormExtend';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $config = new ExtendWormConfig($day);
+        $options[self::OSS_CONTENT] = $config->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Get a bucket's worm
+     *
+     * @param string $bucket bucket name
+     * @param array $options
+     * @throws OssException
+     * @return string
+     */
+    public function getBucketWorm($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'worm';
+        $response = $this->auth($options);
+        $result = new GetBucketWormResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Lists the bucket's object list (in ObjectListInfo)
+     *
+     * @param string $bucket
+     * @param array $options are defined below:
+     * $options = array(
+     *      'max-keys'  => specifies max object count to return. By default is 100 and max value could be 1000.
+     *      'prefix'    => specifies the key prefix the returned objects must have. Note that the returned keys still contain the prefix.
+     *      'delimiter' => The delimiter of object name for grouping object. When it's specified, listObjects will differeniate the object and folder. And it will return subfolder's objects.
+     *      'marker'    => The key of returned object must be greater than the 'marker'.
+     *)
+     * Prefix and marker are for filtering and paging. Their length must be less than 256 bytes
+     * @throws OssException
+     * @return ObjectListInfo
+     */
+    public function listObjects($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array();
+        $options[self::OSS_QUERY_STRING] = array_merge(
+            $query,
+            array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL,
+                  self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/',
+                  self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '',
+                  self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE,
+                  self::OSS_MARKER => isset($options[self::OSS_MARKER]) ? $options[self::OSS_MARKER] : '')
+        );
+
+        $response = $this->auth($options);
+        $result = new ListObjectsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Lists the bucket's object with version information (in ObjectListInfo)
+     *
+     * @param string $bucket
+     * @param array $options are defined below:
+     * $options = array(
+     *      'max-keys'   => specifies max object count to return. By default is 100 and max value could be 1000.
+     *      'prefix'     => specifies the key prefix the returned objects must have. Note that the returned keys still contain the prefix.
+     *      'delimiter'  => The delimiter of object name for grouping object. When it's specified, listObjectVersions will differeniate the object and folder. And it will return subfolder's objects.
+     *      'key-marker' => The key of returned object must be greater than the 'key-marker'.
+     *      'version-id-marker' => The version id of returned object must be greater than the 'version-id-marker'.
+     *)
+     * Prefix and marker are for filtering and paging. Their length must be less than 256 bytes
+     * @throws OssException
+     * @return ObjectListInfo
+     */
+    public function listObjectVersions($bucket, $options = NULL)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'versions';
+        $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array();
+        $options[self::OSS_QUERY_STRING] = array_merge(
+            $query,
+            array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL,
+                  self::OSS_DELIMITER => isset($options[self::OSS_DELIMITER]) ? $options[self::OSS_DELIMITER] : '/',
+                  self::OSS_PREFIX => isset($options[self::OSS_PREFIX]) ? $options[self::OSS_PREFIX] : '',
+                  self::OSS_MAX_KEYS => isset($options[self::OSS_MAX_KEYS]) ? $options[self::OSS_MAX_KEYS] : self::OSS_MAX_KEYS_VALUE,
+                  self::OSS_KEY_MARKER => isset($options[self::OSS_KEY_MARKER]) ? $options[self::OSS_KEY_MARKER] : '',
+                  self::OSS_VERSION_ID_MARKER => isset($options[self::OSS_VERSION_ID_MARKER]) ? $options[self::OSS_VERSION_ID_MARKER] : '')
+        );
+
+        $response = $this->auth($options);
+        $result = new ListObjectVersionsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Creates a virtual 'folder' in OSS. The name should not end with '/' because the method will append the name with a '/' anyway.
+     *
+     * Internal use only.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param array $options
+     * @return null
+     */
+    public function createObjectDir($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $object . '/';
+        $options[self::OSS_CONTENT_LENGTH] = array(self::OSS_CONTENT_LENGTH => 0);
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Uploads the $content object to OSS.
+     *
+     * @param string $bucket bucket name
+     * @param string $object objcet name
+     * @param string $content The content object
+     * @param array $options
+     * @return null
+     */
+    public function putObject($bucket, $object, $content, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+
+        $options[self::OSS_CONTENT] = $content;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $object;
+
+        if (!isset($options[self::OSS_LENGTH])) {
+            $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
+        } else {
+            $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+        }
+
+        $is_check_md5 = $this->isCheckMD5($options);
+        if ($is_check_md5) {
+        	$content_md5 = base64_encode(md5($content, true));
+        	$options[self::OSS_CONTENT_MD5] = $content_md5;
+        }
+        
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
+        }
+        $response = $this->auth($options);
+        
+        if (isset($options[self::OSS_CALLBACK]) && !empty($options[self::OSS_CALLBACK])) {
+            $result = new CallbackResult($response);
+        } else {
+            $result = new PutSetDeleteResult($response);
+        }
+            
+        return $result->getData();
+    }
+
+
+    /**
+     * creates symlink
+     * @param string $bucket bucket name
+     * @param string $symlink symlink name
+     * @param string $targetObject targetObject name
+     * @param array $options
+     * @return null
+     */
+    public function putSymlink($bucket, $symlink ,$targetObject, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $symlink, $options);
+
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $symlink;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_SYMLINK;
+        $options[self::OSS_HEADERS][self::OSS_SYMLINK_TARGET] = rawurlencode($targetObject);
+
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * gets symlink
+     * @param string $bucket bucket name
+     * @param string $symlink symlink name
+     * @param array $options
+     * @return null
+     */
+    public function getSymlink($bucket, $symlink, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $symlink, $options);
+
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = $symlink;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_SYMLINK;
+
+        $response = $this->auth($options);
+        $result = new SymlinkResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Uploads a local file
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $file local file path
+     * @param array $options
+     * @return null
+     * @throws OssException
+     */
+    public function uploadFile($bucket, $object, $file, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid");
+        $file = OssUtil::encodePath($file);
+        if (!file_exists($file)) {
+            throw new OssException($file . " file does not exist");
+        }
+        $options[self::OSS_FILE_UPLOAD] = $file;
+        $file_size = filesize($options[self::OSS_FILE_UPLOAD]);
+        $is_check_md5 = $this->isCheckMD5($options);
+        if ($is_check_md5) {
+            $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true));
+            $options[self::OSS_CONTENT_MD5] = $content_md5;
+        }
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $file);
+        }
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_CONTENT_LENGTH] = $file_size;
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Uploads object from file handle
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param resource $handle file handle
+     * @param array $options
+     * @return null
+     * @throws OssException
+     */
+    public function uploadStream($bucket, $object, $handle, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        if (!is_resource($handle)) {
+            throw new OssException("The handle must be an opened stream");
+        }
+        $options[self::OSS_FILE_UPLOAD] = $handle;
+        if ($this->isCheckMD5($options)) {
+            rewind($handle);
+            $ctx = hash_init('md5');
+            hash_update_stream($ctx, $handle);
+            $content_md5 = base64_encode(hash_final($ctx, true));
+            rewind($handle);
+            $options[self::OSS_CONTENT_MD5] = $content_md5;
+        }
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
+        }
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        if (!isset($options[self::OSS_CONTENT_LENGTH])) {
+            $options[self::OSS_CONTENT_LENGTH] = fstat($handle)[self::OSS_SIZE];
+        }
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Append the object with the content at the specified position.
+     * The specified position is typically the lengh of the current file.
+     * @param string $bucket bucket name
+     * @param string $object objcet name
+     * @param string $content content to append
+     * @param array $options
+     * @return int next append position
+     * @throws OssException
+     */
+    public function appendObject($bucket, $object, $content, $position, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+
+        $options[self::OSS_CONTENT] = $content;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = 'append';
+        $options[self::OSS_POSITION] = strval($position);
+
+        if (!isset($options[self::OSS_LENGTH])) {
+            $options[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
+        } else {
+            $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+        }
+        
+        $is_check_md5 = $this->isCheckMD5($options);
+        if ($is_check_md5) {
+        	$content_md5 = base64_encode(md5($content, true));
+        	$options[self::OSS_CONTENT_MD5] = $content_md5;
+        }
+
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
+        }
+        $response = $this->auth($options);
+        $result = new AppendResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Append the object with a local file
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $file The local file path to append with
+     * @param array $options
+     * @return int next append position
+     * @throws OssException
+     */
+    public function appendFile($bucket, $object, $file, $position, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+
+        OssUtil::throwOssExceptionWithMessageIfEmpty($file, "file path is invalid");
+        $file = OssUtil::encodePath($file);
+        if (!file_exists($file)) {
+            throw new OssException($file . " file does not exist");
+        }
+        $options[self::OSS_FILE_UPLOAD] = $file;
+        $file_size = filesize($options[self::OSS_FILE_UPLOAD]);
+        $is_check_md5 = $this->isCheckMD5($options);
+        if ($is_check_md5) {
+            $content_md5 = base64_encode(md5_file($options[self::OSS_FILE_UPLOAD], true));
+            $options[self::OSS_CONTENT_MD5] = $content_md5;
+        }
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $file);
+        }
+
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_CONTENT_LENGTH] = $file_size;
+        $options[self::OSS_SUB_RESOURCE] = 'append';
+        $options[self::OSS_POSITION] = strval($position);
+
+        $response = $this->auth($options);
+        $result = new AppendResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Copy from an existing OSS object to another OSS object. If the target object exists already, it will be overwritten.
+     *
+     * @param string $fromBucket Source bucket name
+     * @param string $fromObject Source object name
+     * @param string $toBucket Target bucket name
+     * @param string $toObject Target object name
+     * @param array $options
+     * @return null
+     * @throws OssException
+     */
+    public function copyObject($fromBucket, $fromObject, $toBucket, $toObject, $options = NULL)
+    {
+        $this->precheckCommon($fromBucket, $fromObject, $options);
+        $this->precheckCommon($toBucket, $toObject, $options);
+        $options[self::OSS_BUCKET] = $toBucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $toObject;
+        $param = '/' . $fromBucket . '/' . rawurlencode($fromObject);
+        if (isset($options[self::OSS_VERSION_ID])) {
+            $param = $param . '?versionId='.$options[self::OSS_VERSION_ID];
+            unset($options[self::OSS_VERSION_ID]);
+        }
+        if (isset($options[self::OSS_HEADERS])) {
+            $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = $param;
+        } else {
+            $options[self::OSS_HEADERS] = array(self::OSS_OBJECT_COPY_SOURCE => $param);
+        }
+        $response = $this->auth($options);
+        $result = new CopyObjectResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets Object metadata
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $options Checks out the SDK document for the detail
+     * @return array
+     */
+    public function getObjectMeta($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
+        $options[self::OSS_OBJECT] = $object;
+        $response = $this->auth($options);
+        $result = new HeaderResult($response);
+        return $result->getData();
+    }
+
+     /**
+     * Gets the simplified metadata of a object. 
+     * Simplified metadata includes ETag, Size, LastModified.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $options Checks out the SDK document for the detail
+     * @return array
+     */
+    public function getSimplifiedObjectMeta($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = 'objectMeta';
+        $response = $this->auth($options);
+        $result = new HeaderResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes a object
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param array $options
+     * @return null
+     */
+    public function deleteObject($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_OBJECT] = $object;
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes multiple objects in a bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $objects object list
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function deleteObjects($bucket, $objects, $options = null)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        if (!is_array($objects) || !$objects) {
+            throw new OssException('objects must be array');
+        }
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'delete';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $quiet = 'false';
+        if (isset($options['quiet'])) {
+            if (is_bool($options['quiet'])) { //Boolean
+                $quiet = $options['quiet'] ? 'true' : 'false';
+            } elseif (is_string($options['quiet'])) { // string
+                $quiet = ($options['quiet'] === 'true') ? 'true' : 'false';
+            }
+        }
+        $xmlBody = OssUtil::createDeleteObjectsXmlBody($objects, $quiet);
+        $options[self::OSS_CONTENT] = $xmlBody;
+        $response = $this->auth($options);
+        $result = new DeleteObjectsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes multiple objects with version id in a bucket
+     *
+     * @param string $bucket bucket name
+     * @param array $objects DeleteObjectInfo list
+     * @param array $options
+     * @return ResponseCore
+     * @throws null
+     */
+    public function deleteObjectVersions($bucket, $objects, $options = null)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        if (!is_array($objects) || !$objects) {
+            throw new OssException('objects must be array');
+        }
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'delete';
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $quiet = 'false';
+        if (isset($options['quiet'])) {
+            if (is_bool($options['quiet'])) { //Boolean
+                $quiet = $options['quiet'] ? 'true' : 'false';
+            } elseif (is_string($options['quiet'])) { // string
+                $quiet = ($options['quiet'] === 'true') ? 'true' : 'false';
+            }
+        }
+        $xmlBody = OssUtil::createDeleteObjectVersionsXmlBody($objects, $quiet);
+        $options[self::OSS_CONTENT] = $xmlBody;
+        $response = $this->auth($options);
+        $result = new DeleteObjectVersionsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets Object content
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param array $options It must contain ALIOSS::OSS_FILE_DOWNLOAD. And ALIOSS::OSS_RANGE is optional and empty means to download the whole file.
+     * @return string
+     */
+    public function getObject($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_OBJECT] = $object;
+        if (isset($options[self::OSS_LAST_MODIFIED])) {
+            $options[self::OSS_HEADERS][self::OSS_IF_MODIFIED_SINCE] = $options[self::OSS_LAST_MODIFIED];
+            unset($options[self::OSS_LAST_MODIFIED]);
+        }
+        if (isset($options[self::OSS_ETAG])) {
+            $options[self::OSS_HEADERS][self::OSS_IF_NONE_MATCH] = $options[self::OSS_ETAG];
+            unset($options[self::OSS_ETAG]);
+        }
+        if (isset($options[self::OSS_RANGE])) {
+            $range = $options[self::OSS_RANGE];
+            $options[self::OSS_HEADERS][self::OSS_RANGE] = "bytes=$range";
+            unset($options[self::OSS_RANGE]);
+        }
+        $response = $this->auth($options);
+        $result = new BodyResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Checks if the object exists
+     * It's implemented by getObjectMeta().
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param array $options
+     * @return bool True:object exists; False:object does not exist
+     */
+    public function doesObjectExist($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_HEAD;
+        $options[self::OSS_OBJECT] = $object;
+        $response = $this->auth($options);
+        $result = new ExistResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Object reading for Archive type
+     * Use Restore to enable the server to perform the thawing task
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @return null
+     * @throws OssException
+     */
+    public function restoreObject($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_RESTORE;
+        if (isset($options[self::OSS_RESTORE_CONFIG])) {
+            $config = $options[self::OSS_RESTORE_CONFIG];
+            $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+            $options[self::OSS_CONTENT] = $config->serializeToXml();
+        }
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Sets the object tagging
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param TaggingConfig $taggingConfig
+     * @throws OssException
+     * @return null
+     */
+    public function putObjectTagging($bucket, $object, $taggingConfig, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options, true);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        $options[self::OSS_CONTENT] = $taggingConfig->serializeToXml();
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the object tagging
+     *
+     * @param string $bucket
+     * @param string $object
+     * @throws OssException
+     * @return TaggingConfig
+     */
+    public function getObjectTagging($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options, true);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        $response = $this->auth($options);
+        $result = new GetBucketTagsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Deletes the object tagging
+     *
+     * @param string $bucket
+     * @param string $object
+     * @throws OssException
+     * @return TaggingConfig
+     */
+    public function deleteObjectTagging($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options, true);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = self::OSS_TAGGING;
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Processes the object
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $process process script
+     * @return string process result, json format
+     */
+    public function processObject($bucket, $object, $process, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = 'x-oss-process';
+        $options[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
+        $options[self::OSS_CONTENT] = 'x-oss-process='.$process;
+        $response = $this->auth($options);
+        $result = new BodyResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the part size according to the preferred part size.
+     * If the specified part size is too small or too big, it will return a min part or max part size instead.
+     * Otherwise returns the specified part size.
+     * @param int $partSize
+     * @return int
+     */
+    private function computePartSize($partSize)
+    {
+        $partSize = (integer)$partSize;
+        if ($partSize <= self::OSS_MIN_PART_SIZE) {
+            $partSize = self::OSS_MIN_PART_SIZE;
+        } elseif ($partSize > self::OSS_MAX_PART_SIZE) {
+            $partSize = self::OSS_MAX_PART_SIZE;
+        }
+        return $partSize;
+    }
+
+    /**
+     * Computes the parts count, size and start position according to the file size and the part size.
+     * It must be only called by upload_Part().
+     *
+     * @param integer $file_size File size
+     * @param integer $partSize part大小,part size. Default is 5MB
+     * @return array An array contains key-value pairs--the key is `seekTo`and value is `length`.
+     */
+    public function generateMultiuploadParts($file_size, $partSize = 5242880)
+    {
+        $i = 0;
+        $size_count = $file_size;
+        $values = array();
+        $partSize = $this->computePartSize($partSize);
+        while ($size_count > 0) {
+            $size_count -= $partSize;
+            $values[] = array(
+                self::OSS_SEEK_TO => ($partSize * $i),
+                self::OSS_LENGTH => (($size_count > 0) ? $partSize : ($size_count + $partSize)),
+            );
+            $i++;
+        }
+        return $values;
+    }
+
+    /**
+     * Initialize a multi-part upload
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param array $options Key-Value array
+     * @throws OssException
+     * @return string returns uploadid
+     */
+    public function initiateMultipartUpload($bucket, $object, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_SUB_RESOURCE] = 'uploads';
+        $options[self::OSS_CONTENT] = '';
+
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object);
+        }
+        if (!isset($options[self::OSS_HEADERS])) {
+            $options[self::OSS_HEADERS] = array();
+        }
+        $response = $this->auth($options);
+        $result = new InitiateMultipartUploadResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Upload a part in a multiparts upload.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $uploadId
+     * @param array $options Key-Value array
+     * @return string eTag
+     * @throws OssException
+     */
+    public function uploadPart($bucket, $object, $uploadId, $options = null)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $this->precheckParam($options, self::OSS_FILE_UPLOAD, __FUNCTION__);
+        $this->precheckParam($options, self::OSS_PART_NUM, __FUNCTION__);
+
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_UPLOAD_ID] = $uploadId;
+
+        if (isset($options[self::OSS_LENGTH])) {
+            $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+        }
+        $response = $this->auth($options);
+        $result = new UploadPartResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Gets the uploaded parts.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $uploadId uploadId
+     * @param array $options Key-Value array
+     * @return ListPartsInfo
+     * @throws OssException
+     */
+    public function listParts($bucket, $object, $uploadId, $options = null)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_UPLOAD_ID] = $uploadId;
+        $options[self::OSS_QUERY_STRING] = array();
+        foreach (array('max-parts', 'part-number-marker') as $param) {
+            if (isset($options[$param])) {
+                $options[self::OSS_QUERY_STRING][$param] = $options[$param];
+                unset($options[$param]);
+            }
+        }
+        $response = $this->auth($options);
+        $result = new ListPartsResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Abort a multiparts upload
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $uploadId uploadId
+     * @param array $options Key-Value name
+     * @return null
+     * @throws OssException
+     */
+    public function abortMultipartUpload($bucket, $object, $uploadId, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_DELETE;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_UPLOAD_ID] = $uploadId;
+        $response = $this->auth($options);
+        $result = new PutSetDeleteResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Completes a multiparts upload, after all parts are uploaded.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $uploadId uploadId
+     * @param array $listParts array( array("PartNumber"=> int, "ETag"=>string))
+     * @param array $options Key-Value array
+     * @throws OssException
+     * @return null
+     */
+    public function completeMultipartUpload($bucket, $object, $uploadId, $listParts, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_POST;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_UPLOAD_ID] = $uploadId;
+        $options[self::OSS_CONTENT_TYPE] = 'application/xml';
+        if (!is_array($listParts)) {
+            throw new OssException("listParts must be array type");
+        }
+        $options[self::OSS_CONTENT] = OssUtil::createCompleteMultipartUploadXmlBody($listParts);
+        $response = $this->auth($options);
+        if (isset($options[self::OSS_CALLBACK]) && !empty($options[self::OSS_CALLBACK])) {
+            $result = new CallbackResult($response);
+        } else {
+            $result = new PutSetDeleteResult($response);
+        }
+        return $result->getData();
+    }
+
+    /**
+     * Lists all ongoing multipart upload events, which means all initialized but not completed or aborted multipart uploads.
+     *
+     * @param string $bucket bucket
+     * @param array $options key-value array--expected keys are 'delimiter', 'key-marker', 'max-uploads', 'prefix', 'upload-id-marker'
+     * @throws OssException
+     * @return ListMultipartUploadInfo
+     */
+    public function listMultipartUploads($bucket, $options = null)
+    {
+        $this->precheckCommon($bucket, NULL, $options, false);
+        $options[self::OSS_METHOD] = self::OSS_HTTP_GET;
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = '/';
+        $options[self::OSS_SUB_RESOURCE] = 'uploads';
+
+        foreach (array('delimiter', 'key-marker', 'max-uploads', 'prefix', 'upload-id-marker') as $param) {
+            if (isset($options[$param])) {
+                $options[self::OSS_QUERY_STRING][$param] = $options[$param];
+                unset($options[$param]);
+            }
+        }
+        $query = isset($options[self::OSS_QUERY_STRING]) ? $options[self::OSS_QUERY_STRING] : array();
+        $options[self::OSS_QUERY_STRING] = array_merge(
+            $query,
+            array(self::OSS_ENCODING_TYPE => self::OSS_ENCODING_TYPE_URL)
+        );
+
+        $response = $this->auth($options);
+        $result = new ListMultipartUploadResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * Copy an existing file as a part
+     *
+     * @param string $fromBucket source bucket name
+     * @param string $fromObject source object name
+     * @param string $toBucket target bucket name
+     * @param string $toObject target object name
+     * @param int $partNumber Part number
+     * @param string $uploadId Upload Id
+     * @param array $options Key-Value array---it should have 'start' or 'end' key to specify the range of the source object to copy. If it's not specifed, the whole object is copied.
+     * @return null
+     * @throws OssException
+     */
+    public function uploadPartCopy($fromBucket, $fromObject, $toBucket, $toObject, $partNumber, $uploadId, $options = NULL)
+    {
+        $this->precheckCommon($fromBucket, $fromObject, $options);
+        $this->precheckCommon($toBucket, $toObject, $options);
+
+        //If $options['isFullCopy'] is not set, copy from the beginning
+        $start_range = "0";
+        if (isset($options['start'])) {
+            $start_range = $options['start'];
+        }
+        $end_range = "";
+        if (isset($options['end'])) {
+            $end_range = $options['end'];
+        }
+        $options[self::OSS_METHOD] = self::OSS_HTTP_PUT;
+        $options[self::OSS_BUCKET] = $toBucket;
+        $options[self::OSS_OBJECT] = $toObject;
+        $options[self::OSS_PART_NUM] = $partNumber;
+        $options[self::OSS_UPLOAD_ID] = $uploadId;
+
+        if (!isset($options[self::OSS_HEADERS])) {
+            $options[self::OSS_HEADERS] = array();
+        }
+
+        $param = '/' . $fromBucket . '/' . rawurlencode($fromObject);
+        if (isset($options[self::OSS_VERSION_ID])) {
+            $param = $param . '?versionId='.$options[self::OSS_VERSION_ID];
+            unset($options[self::OSS_VERSION_ID]);
+        }
+
+        $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE] = $param;
+        $options[self::OSS_HEADERS][self::OSS_OBJECT_COPY_SOURCE_RANGE] = "bytes=" . $start_range . "-" . $end_range;
+        $response = $this->auth($options);
+        $result = new UploadPartResult($response);
+        return $result->getData();
+    }
+
+    /**
+     * A higher level API for uploading a file with multipart upload. It consists of initialization, parts upload and completion.
+     *
+     * @param string $bucket bucket name
+     * @param string $object object name
+     * @param string $file The local file to upload
+     * @param array $options Key-Value array
+     * @return null
+     * @throws OssException
+     */
+    public function multiuploadFile($bucket, $object, $file, $options = null)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        if (isset($options[self::OSS_LENGTH])) {
+            $options[self::OSS_CONTENT_LENGTH] = $options[self::OSS_LENGTH];
+            unset($options[self::OSS_LENGTH]);
+        }
+        if (empty($file)) {
+            throw new OssException("parameter invalid, file is empty");
+        }
+        $uploadFile = OssUtil::encodePath($file);
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = $this->getMimeType($object, $uploadFile);
+        }
+
+        $upload_position = isset($options[self::OSS_SEEK_TO]) ? (integer)$options[self::OSS_SEEK_TO] : 0;
+
+        if (isset($options[self::OSS_CONTENT_LENGTH])) {
+            $upload_file_size = (integer)$options[self::OSS_CONTENT_LENGTH];
+        } else {
+            $upload_file_size = filesize($uploadFile);
+            if ($upload_file_size !== false) {
+                $upload_file_size -= $upload_position;  
+            }
+        }
+
+        if ($upload_position === false || !isset($upload_file_size) || $upload_file_size === false || $upload_file_size < 0) {
+            throw new OssException('The size of `fileUpload` cannot be determined in ' . __FUNCTION__ . '().');
+        }
+        // Computes the part size and assign it to options.
+        if (isset($options[self::OSS_PART_SIZE])) {
+            $options[self::OSS_PART_SIZE] = $this->computePartSize($options[self::OSS_PART_SIZE]);
+        } else {
+            $options[self::OSS_PART_SIZE] = self::OSS_MID_PART_SIZE;
+        }
+
+        $is_check_md5 = $this->isCheckMD5($options);
+        // if the file size is less than part size, use simple file upload.
+        if ($upload_file_size < $options[self::OSS_PART_SIZE] && !isset($options[self::OSS_UPLOAD_ID])) {
+            return $this->uploadFile($bucket, $object, $uploadFile, $options);
+        }
+
+        // Using multipart upload, initialize if no OSS_UPLOAD_ID is specified in options.
+        if (isset($options[self::OSS_UPLOAD_ID])) {
+            $uploadId = $options[self::OSS_UPLOAD_ID];
+        } else {
+            // initialize
+            $uploadId = $this->initiateMultipartUpload($bucket, $object, $options);
+        }
+
+        // generates the parts information and upload them one by one
+        $pieces = $this->generateMultiuploadParts($upload_file_size, (integer)$options[self::OSS_PART_SIZE]);
+        $response_upload_part = array();
+        foreach ($pieces as $i => $piece) {
+            $from_pos = $upload_position + (integer)$piece[self::OSS_SEEK_TO];
+            $to_pos = (integer)$piece[self::OSS_LENGTH] + $from_pos - 1;
+            $up_options = array(
+                self::OSS_FILE_UPLOAD => $uploadFile,
+                self::OSS_PART_NUM => ($i + 1),
+                self::OSS_SEEK_TO => $from_pos,
+                self::OSS_LENGTH => $to_pos - $from_pos + 1,
+                self::OSS_CHECK_MD5 => $is_check_md5,
+            );
+            if ($is_check_md5) {
+                $content_md5 = OssUtil::getMd5SumForFile($uploadFile, $from_pos, $to_pos);
+                $up_options[self::OSS_CONTENT_MD5] = $content_md5;
+            }
+            $response_upload_part[] = $this->uploadPart($bucket, $object, $uploadId, $up_options);
+        }
+
+        $uploadParts = array();
+        foreach ($response_upload_part as $i => $etag) {
+            $uploadParts[] = array(
+                'PartNumber' => ($i + 1),
+                'ETag' => $etag,
+            );
+        }
+
+        //build complete options
+        $cmp_options = null;
+        if (isset($options[self::OSS_HEADERS]) && isset($options[self::OSS_HEADERS][self::OSS_REQUEST_PAYER])) {
+            $cmp_options = array(
+                OssClient::OSS_HEADERS => array(
+                    OssClient::OSS_REQUEST_PAYER => $options[self::OSS_HEADERS][self::OSS_REQUEST_PAYER],
+            ));
+        }
+        return $this->completeMultipartUpload($bucket, $object, $uploadId, $uploadParts, $cmp_options);
+    }
+
+    /**
+     * Uploads the local directory to the specified bucket into specified folder (prefix)
+     *
+     * @param string $bucket bucket name
+     * @param string $prefix The object key prefix. Typically it's folder name. The name should not end with '/' as the API appends it automatically.
+     * @param string $localDirectory The local directory to upload
+     * @param string $exclude To excluded directories
+     * @param bool $recursive Recursive flag. True: Recursively upload all datas under the local directory; False: only upload first layer's files.
+     * @param bool $checkMd5
+     * @return array Returns two list: array("succeededList" => array("object"), "failedList" => array("object"=>"errorMessage"))
+     * @throws OssException
+     */
+    public function uploadDir($bucket, $prefix, $localDirectory, $exclude = '.|..|.svn|.git', $recursive = false, $checkMd5 = true)
+    {
+        $retArray = array("succeededList" => array(), "failedList" => array());
+        if (empty($bucket)) throw new OssException("parameter error, bucket is empty");
+        if (!is_string($prefix)) throw new OssException("parameter error, prefix is not string");
+        if (empty($localDirectory)) throw new OssException("parameter error, localDirectory is empty");
+        $directory = $localDirectory;
+        $directory = OssUtil::encodePath($directory);
+        //If it's not the local directory, throw OSSException.
+        if (!is_dir($directory)) {
+            throw new OssException('parameter error: ' . $directory . ' is not a directory, please check it');
+        }
+        //read directory
+        $file_list_array = OssUtil::readDir($directory, $exclude, $recursive);
+        if (!$file_list_array) {
+            throw new OssException($directory . ' is empty...');
+        }
+        foreach ($file_list_array as $k => $item) {
+            if (is_dir($item['path'])) {
+                continue;
+            }
+            $options = array(
+                self::OSS_PART_SIZE => self::OSS_MIN_PART_SIZE,
+                self::OSS_CHECK_MD5 => $checkMd5,
+            );
+            $realObject = (!empty($prefix) ? $prefix . '/' : '') . $item['file'];
+
+            try {
+                $this->multiuploadFile($bucket, $realObject, $item['path'], $options);
+                $retArray["succeededList"][] = $realObject;
+            } catch (OssException $e) {
+                $retArray["failedList"][$realObject] = $e->getMessage();
+            }
+        }
+        return $retArray;
+    }
+
+    /**
+     * Sign URL with specified expiration time in seconds (timeout) and HTTP method.
+     * The signed URL could be used to access the object directly.
+     *
+     * @param string $bucket
+     * @param string $object
+     * @param int $timeout expiration time in seconds.
+     * @param string $method
+     * @param array $options Key-Value array
+     * @return string
+     * @throws OssException
+     */
+    public function signUrl($bucket, $object, $timeout = 60, $method = self::OSS_HTTP_GET, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        //method
+        if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) {
+            throw new OssException("method is invalid");
+        }
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_METHOD] = $method;
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = '';
+        }
+        $timeout = time() + $timeout;
+        $options[self::OSS_PREAUTH] = $timeout;
+        $options[self::OSS_DATE] = $timeout;
+        $this->setSignStsInUrl(true);
+        return $this->auth($options);
+    }
+
+    /**
+     * Sign URL with specified expiration time in seconds and HTTP method.
+     * The signed URL could be used to access the object directly.
+     *
+     * @param string $bucket
+     * @param string $object
+     * @param int $expiration expiration time of the Url, unix epoch, since 1970.1.1 00.00.00 UTC
+     * @param string $method
+     * @param array $options Key-Value array
+     * @return string
+     * @throws OssException
+     */
+    public function generatePresignedUrl($bucket, $object, $expiration, $method = self::OSS_HTTP_GET, $options = NULL)
+    {
+        $this->precheckCommon($bucket, $object, $options);
+        //method
+        if (self::OSS_HTTP_GET !== $method && self::OSS_HTTP_PUT !== $method) {
+            throw new OssException("method is invalid");
+        }
+        $options[self::OSS_BUCKET] = $bucket;
+        $options[self::OSS_OBJECT] = $object;
+        $options[self::OSS_METHOD] = $method;
+        if (!isset($options[self::OSS_CONTENT_TYPE])) {
+            $options[self::OSS_CONTENT_TYPE] = '';
+        }
+        $options[self::OSS_PREAUTH] = $expiration;
+        $options[self::OSS_DATE] = $expiration;
+        $this->setSignStsInUrl(true);
+        return $this->auth($options);
+    }
+
+    /**
+     * validates options. Create a empty array if it's NULL.
+     *
+     * @param array $options
+     * @throws OssException
+     */
+    private function precheckOptions(&$options)
+    {
+        OssUtil::validateOptions($options);
+        if (!$options) {
+            $options = array();
+        }
+    }
+
+    /**
+     * Validates bucket parameter
+     *
+     * @param string $bucket
+     * @param string $errMsg
+     * @throws OssException
+     */
+    private function precheckBucket($bucket, $errMsg = 'bucket is not allowed empty')
+    {
+        OssUtil::throwOssExceptionWithMessageIfEmpty($bucket, $errMsg);
+    }
+
+    /**
+     * validates object parameter
+     *
+     * @param string $object
+     * @throws OssException
+     */
+    private function precheckObject($object)
+    {
+        OssUtil::throwOssExceptionWithMessageIfEmpty($object, "object name is empty");
+    }
+
+    /**
+     * 校验option restore
+     *
+     * @param string $restore
+     * @throws OssException
+     */
+    private function precheckStorage($storage)
+    {
+        if (is_string($storage)) {
+            switch ($storage) {
+                case self::OSS_STORAGE_ARCHIVE:
+                    return;
+                case self::OSS_STORAGE_IA:
+                    return;
+                case self::OSS_STORAGE_STANDARD:
+                    return;
+                case self::OSS_STORAGE_COLDARCHIVE:
+                    return;
+                default:
+                    break;
+            }
+        }
+        throw new OssException('storage name is invalid');
+    }
+
+    /**
+     * Validates bucket,options parameters and optionally validate object parameter.
+     *
+     * @param string $bucket
+     * @param string $object
+     * @param array $options
+     * @param bool $isCheckObject
+     */
+    private function precheckCommon($bucket, $object, &$options, $isCheckObject = true)
+    {
+        if ($isCheckObject) {
+            $this->precheckObject($object);
+        }
+        $this->precheckOptions($options);
+        $this->precheckBucket($bucket);
+    }
+
+    /**
+     * checks parameters
+     *
+     * @param array $options
+     * @param string $param
+     * @param string $funcName
+     * @throws OssException
+     */
+    private function precheckParam($options, $param, $funcName)
+    {
+        if (!isset($options[$param])) {
+            throw new OssException('The `' . $param . '` options is required in ' . $funcName . '().');
+        }
+    }
+
+    /**
+     * Checks md5
+     *
+     * @param array $options
+     * @return bool|null
+     */
+    private function isCheckMD5($options)
+    {
+        return $this->getValue($options, self::OSS_CHECK_MD5, false, true, true);
+    }
+
+    /**
+     * Gets value of the specified key from the options 
+     *
+     * @param array $options
+     * @param string $key
+     * @param string $default
+     * @param bool $isCheckEmpty
+     * @param bool $isCheckBool
+     * @return bool|null
+     */
+    private function getValue($options, $key, $default = NULL, $isCheckEmpty = false, $isCheckBool = false)
+    {
+        $value = $default;
+        if (isset($options[$key])) {
+            if ($isCheckEmpty) {
+                if (!empty($options[$key])) {
+                    $value = $options[$key];
+                }
+            } else {
+                $value = $options[$key];
+            }
+            unset($options[$key]);
+        }
+        if ($isCheckBool) {
+            if ($value !== true && $value !== false) {
+                $value = false;
+            }
+        }
+        return $value;
+    }
+
+    /**
+     * Gets mimetype
+     *
+     * @param string $object
+     * @return string
+     */
+    private function getMimeType($object, $file = null)
+    {
+        if (!is_null($file)) {
+            $type = MimeTypes::getMimetype($file);
+            if (!is_null($type)) {
+                return $type;
+            }
+        }
+
+        $type = MimeTypes::getMimetype($object);
+        if (!is_null($type)) {
+            return $type;
+        }
+
+        return self::DEFAULT_CONTENT_TYPE;
+    }
+
+    /**
+     * Validates and executes the request according to OSS API protocol.
+     *
+     * @param array $options
+     * @return ResponseCore
+     * @throws OssException
+     * @throws RequestCore_Exception
+     */
+    private function auth($options)
+    {
+        OssUtil::validateOptions($options);
+        //Validates bucket, not required for list_bucket
+        $this->authPrecheckBucket($options);
+        //Validates object
+        $this->authPrecheckObject($options);
+        //object name encoding must be UTF-8
+        $this->authPrecheckObjectEncoding($options);
+        //Validates ACL
+        $this->authPrecheckAcl($options);
+        // Should https or http be used?
+        $scheme = $this->useSSL ? 'https://' : 'http://';
+        // gets the host name. If the host name is public domain or private domain, form a third level domain by prefixing the bucket name on the domain name.
+        $hostname = $this->generateHostname($options[self::OSS_BUCKET]);
+        $string_to_sign = '';
+        $headers = $this->generateHeaders($options, $hostname);
+        $signable_query_string_params = $this->generateSignableQueryStringParam($options);
+        $signable_query_string = OssUtil::toQueryString($signable_query_string_params);
+        $resource_uri = $this->generateResourceUri($options);
+        //Generates the URL (add query parameters)
+        $conjunction = '?';
+        $non_signable_resource = '';
+        if (isset($options[self::OSS_SUB_RESOURCE])) {
+            $conjunction = '&';
+        }
+        if ($signable_query_string !== '') {
+            $signable_query_string = $conjunction . $signable_query_string;
+            $conjunction = '&';
+        }
+        $query_string = $this->generateQueryString($options);
+        if ($query_string !== '') {
+            $non_signable_resource .= $conjunction . $query_string;
+            $conjunction = '&';
+        }
+        $this->requestUrl = $scheme . $hostname . $resource_uri . $signable_query_string . $non_signable_resource;
+
+        //Creates the request
+        $request = new RequestCore($this->requestUrl, $this->requestProxy);
+        $request->set_useragent($this->generateUserAgent());
+        // Streaming uploads
+        if (isset($options[self::OSS_FILE_UPLOAD])) {
+            if (is_resource($options[self::OSS_FILE_UPLOAD])) {
+                $length = null;
+
+                if (isset($options[self::OSS_CONTENT_LENGTH])) {
+                    $length = $options[self::OSS_CONTENT_LENGTH];
+                } elseif (isset($options[self::OSS_SEEK_TO])) {
+                    $stats = fstat($options[self::OSS_FILE_UPLOAD]);
+                    if ($stats && $stats[self::OSS_SIZE] >= 0) {
+                        $length = $stats[self::OSS_SIZE] - (integer)$options[self::OSS_SEEK_TO];
+                    }
+                }
+                $request->set_read_stream($options[self::OSS_FILE_UPLOAD], $length);
+            } else {
+                $request->set_read_file($options[self::OSS_FILE_UPLOAD]);
+                $length = $request->read_stream_size;
+                if (isset($options[self::OSS_CONTENT_LENGTH])) {
+                    $length = $options[self::OSS_CONTENT_LENGTH];
+                } elseif (isset($options[self::OSS_SEEK_TO]) && isset($length)) {
+                    $length -= (integer)$options[self::OSS_SEEK_TO];
+                }
+                $request->set_read_stream_size($length);
+            }
+        }
+        if (isset($options[self::OSS_SEEK_TO])) {
+            $request->set_seek_position((integer)$options[self::OSS_SEEK_TO]);
+        }
+        if (isset($options[self::OSS_FILE_DOWNLOAD])) {
+            if (is_resource($options[self::OSS_FILE_DOWNLOAD])) {
+                $request->set_write_stream($options[self::OSS_FILE_DOWNLOAD]);
+            } else {
+                $request->set_write_file($options[self::OSS_FILE_DOWNLOAD]);
+            }
+        }
+
+        if (isset($options[self::OSS_METHOD])) {
+            $request->set_method($options[self::OSS_METHOD]);
+            $string_to_sign .= $options[self::OSS_METHOD] . "\n";
+        }
+
+        if (isset($options[self::OSS_CONTENT])) {
+            $request->set_body($options[self::OSS_CONTENT]);
+            if ($headers[self::OSS_CONTENT_TYPE] === 'application/x-www-form-urlencoded') {
+                $headers[self::OSS_CONTENT_TYPE] = 'application/octet-stream';
+            }
+
+            $headers[self::OSS_CONTENT_LENGTH] = strlen($options[self::OSS_CONTENT]);
+            $headers[self::OSS_CONTENT_MD5] = base64_encode(md5($options[self::OSS_CONTENT], true));
+        }
+
+        if (isset($options[self::OSS_CALLBACK])) {
+            $headers[self::OSS_CALLBACK] = base64_encode($options[self::OSS_CALLBACK]);
+        }
+        if (isset($options[self::OSS_CALLBACK_VAR])) {
+            $headers[self::OSS_CALLBACK_VAR] = base64_encode($options[self::OSS_CALLBACK_VAR]);
+        }
+
+        if (!isset($headers[self::OSS_ACCEPT_ENCODING])) {
+            $headers[self::OSS_ACCEPT_ENCODING] = '';
+        }
+
+        uksort($headers, 'strnatcasecmp');
+
+        foreach ($headers as $header_key => $header_value) {
+            $header_value = str_replace(array("\r", "\n"), '', $header_value);
+            if ($header_value !== '' || $header_key === self::OSS_ACCEPT_ENCODING) {
+                $request->add_header($header_key, $header_value);
+            }
+
+            if (
+                strtolower($header_key) === 'content-md5' ||
+                strtolower($header_key) === 'content-type' ||
+                strtolower($header_key) === 'date' ||
+                (isset($options['self::OSS_PREAUTH']) && (integer)$options['self::OSS_PREAUTH'] > 0)
+            ) {
+                $string_to_sign .= $header_value . "\n";
+            } elseif (substr(strtolower($header_key), 0, 6) === self::OSS_DEFAULT_PREFIX) {
+                $string_to_sign .= strtolower($header_key) . ':' . $header_value . "\n";
+            }
+        }
+        // Generates the signable_resource
+        $signable_resource = $this->generateSignableResource($options);
+        $signable_resource = rawurldecode($signable_resource) . urldecode($signable_query_string);
+        $string_to_sign_ordered = $string_to_sign;
+        $string_to_sign .= $signable_resource;
+
+        // Sort the strings to be signed.
+        $string_to_sign_ordered .= $this->stringToSignSorted($signable_resource);
+
+
+        $signature = base64_encode(hash_hmac('sha1', $string_to_sign_ordered, $this->accessKeySecret, true));
+        $request->add_header('Authorization', 'OSS ' . $this->accessKeyId . ':' . $signature);
+
+        if (isset($options[self::OSS_PREAUTH]) && (integer)$options[self::OSS_PREAUTH] > 0) {
+            $signed_url = $this->requestUrl . $conjunction . self::OSS_URL_ACCESS_KEY_ID . '=' . rawurlencode($this->accessKeyId) . '&' . self::OSS_URL_EXPIRES . '=' . $options[self::OSS_PREAUTH] . '&' . self::OSS_URL_SIGNATURE . '=' . rawurlencode($signature);
+            return $signed_url;
+        } elseif (isset($options[self::OSS_PREAUTH])) {
+            return $this->requestUrl;
+        }
+
+        if ($this->timeout !== 0) {
+            $request->timeout = $this->timeout;
+        }
+        if ($this->connectTimeout !== 0) {
+            $request->connect_timeout = $this->connectTimeout;
+        }
+
+        try {
+            $request->send_request();
+        } catch (RequestCore_Exception $e) {
+            throw(new OssException('RequestCoreException: ' . $e->getMessage()));
+        }
+        $response_header = $request->get_response_header();
+        $response_header['oss-request-url'] = $this->requestUrl;
+        $response_header['oss-redirects'] = $this->redirects;
+        $response_header['oss-stringtosign'] = $string_to_sign;
+        $response_header['oss-requestheaders'] = $request->request_headers;
+
+        $data = new ResponseCore($response_header, $request->get_response_body(), $request->get_response_code());
+        //retry if OSS Internal Error
+        if ((integer)$request->get_response_code() === 500) {
+            if ($this->redirects <= $this->maxRetries) {
+                //Sets the sleep time betwen each retry.
+                $delay = (integer)(pow(4, $this->redirects) * 100000);
+                usleep($delay);
+                $this->redirects++;
+                $data = $this->auth($options);
+            }
+        }
+        
+        $this->redirects = 0;
+        return $data;
+    }
+
+    /**
+     * Sets the max retry count
+     *
+     * @param int $maxRetries
+     * @return void
+     */
+    public function setMaxTries($maxRetries = 3)
+    {
+        $this->maxRetries = $maxRetries;
+    }
+
+    /**
+     * Gets the max retry count
+     *
+     * @return int
+     */
+    public function getMaxRetries()
+    {
+        return $this->maxRetries;
+    }
+
+    /**
+     * Enaable/disable STS in the URL. This is to determine the $sts value passed from constructor take effect or not.
+     *
+     * @param boolean $enable
+     */
+    public function setSignStsInUrl($enable)
+    {
+        $this->enableStsInUrl = $enable;
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isUseSSL()
+    {
+        return $this->useSSL;
+    }
+
+    /**
+     * @param boolean $useSSL
+     */
+    public function setUseSSL($useSSL)
+    {
+        $this->useSSL = $useSSL;
+    }
+
+    /**
+     * Validates bucket name--throw OssException if it's invalid
+     *
+     * @param $options
+     * @throws OssException
+     */
+    private function authPrecheckBucket($options)
+    {
+        if (!(('/' == $options[self::OSS_OBJECT]) && ('' == $options[self::OSS_BUCKET]) && ('GET' == $options[self::OSS_METHOD])) && !OssUtil::validateBucket($options[self::OSS_BUCKET])) {
+            throw new OssException('"' . $options[self::OSS_BUCKET] . '"' . 'bucket name is invalid');
+        }
+    }
+
+    /**
+     *
+     * Validates the object name--throw OssException if it's invalid.
+     *
+     * @param $options
+     * @throws OssException
+     */
+    private function authPrecheckObject($options)
+    {
+        if (isset($options[self::OSS_OBJECT]) && $options[self::OSS_OBJECT] === '/') {
+            return;
+        }
+
+        if (isset($options[self::OSS_OBJECT]) && !OssUtil::validateObject($options[self::OSS_OBJECT])) {
+            throw new OssException('"' . $options[self::OSS_OBJECT] . '"' . ' object name is invalid');
+        }
+    }
+
+    /**
+     * Checks the object's encoding. Convert it to UTF8 if it's in GBK or GB2312
+     *
+     * @param mixed $options parameter
+     */
+    private function authPrecheckObjectEncoding(&$options)
+    {
+        $tmp_object = $options[self::OSS_OBJECT];
+        try {
+            if (OssUtil::isGb2312($options[self::OSS_OBJECT])) {
+                $options[self::OSS_OBJECT] = iconv('GB2312', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
+            } elseif (OssUtil::checkChar($options[self::OSS_OBJECT], true)) {
+                $options[self::OSS_OBJECT] = iconv('GBK', "UTF-8//IGNORE", $options[self::OSS_OBJECT]);
+            }
+        } catch (\Exception $e) {
+            try {
+                $tmp_object = iconv(mb_detect_encoding($tmp_object), "UTF-8", $tmp_object);
+            } catch (\Exception $e) {
+            }
+        }
+        $options[self::OSS_OBJECT] = $tmp_object;
+    }
+
+    /**
+     * Checks if the ACL is one of the 3 predefined one. Throw OSSException if not.
+     *
+     * @param $options
+     * @throws OssException
+     */
+    private function authPrecheckAcl($options)
+    {
+        if (isset($options[self::OSS_HEADERS][self::OSS_ACL]) && !empty($options[self::OSS_HEADERS][self::OSS_ACL])) {
+            if (!in_array(strtolower($options[self::OSS_HEADERS][self::OSS_ACL]), self::$OSS_ACL_TYPES)) {
+                throw new OssException($options[self::OSS_HEADERS][self::OSS_ACL] . ':' . 'acl is invalid(private,public-read,public-read-write)');
+            }
+        }
+    }
+
+    /**
+     * Gets the host name for the current request.
+     * It could be either a third level domain (prefixed by bucket name) or second level domain if it's CName or IP
+     *
+     * @param $bucket
+     * @return string The host name without the protocol scheem (e.g. https://)
+     */
+    private function generateHostname($bucket)
+    {
+        if ($this->hostType === self::OSS_HOST_TYPE_IP) {
+            $hostname = $this->hostname;
+        } elseif ($this->hostType === self::OSS_HOST_TYPE_CNAME) {
+            $hostname = $this->hostname;
+        } else {
+            // Private domain or public domain
+            $hostname = ($bucket == '') ? $this->hostname : ($bucket . '.') . $this->hostname;
+        }
+        return $hostname;
+    }
+
+    /**
+     * Gets the resource Uri in the current request
+     *
+     * @param $options
+     * @return string return the resource uri.
+     */
+    private function generateResourceUri($options)
+    {
+        $resource_uri = "";
+
+        // resource_uri + bucket
+        if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) {
+            if ($this->hostType === self::OSS_HOST_TYPE_IP) {
+                $resource_uri = '/' . $options[self::OSS_BUCKET];
+            }
+        }
+
+        // resource_uri + object
+        if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
+            $resource_uri .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
+        }
+
+        // resource_uri + sub_resource
+        $conjunction = '?';
+        if (isset($options[self::OSS_SUB_RESOURCE])) {
+            $resource_uri .= $conjunction . $options[self::OSS_SUB_RESOURCE];
+        }
+        return $resource_uri;
+    }
+
+    /**
+     * Generates the signalbe query string parameters in array type
+     *
+     * @param array $options
+     * @return array
+     */
+    private function generateSignableQueryStringParam($options)
+    {
+        $signableQueryStringParams = array();
+        $signableList = array(
+            self::OSS_PART_NUM,
+            'response-content-type',
+            'response-content-language',
+            'response-cache-control',
+            'response-content-encoding',
+            'response-expires',
+            'response-content-disposition',
+            self::OSS_UPLOAD_ID,
+            self::OSS_COMP,
+            self::OSS_LIVE_CHANNEL_STATUS,
+            self::OSS_LIVE_CHANNEL_START_TIME,
+            self::OSS_LIVE_CHANNEL_END_TIME,
+            self::OSS_PROCESS,
+            self::OSS_POSITION,
+            self::OSS_SYMLINK,
+            self::OSS_RESTORE,
+            self::OSS_TAGGING,
+            self::OSS_WORM_ID,
+            self::OSS_TRAFFIC_LIMIT,
+            self::OSS_VERSION_ID,
+        );
+
+        foreach ($signableList as $item) {
+            if (isset($options[$item])) {
+                $signableQueryStringParams[$item] = $options[$item];
+            }
+        }
+
+        if ($this->enableStsInUrl && (!is_null($this->securityToken))) {
+            $signableQueryStringParams["security-token"] = $this->securityToken;
+        }
+
+        return $signableQueryStringParams;
+    }
+
+    /**
+     *  Generates the resource uri for signing
+     *
+     * @param mixed $options
+     * @return string
+     */
+    private function generateSignableResource($options)
+    {
+        $signableResource = "";
+        $signableResource .= '/';
+        if (isset($options[self::OSS_BUCKET]) && '' !== $options[self::OSS_BUCKET]) {
+            $signableResource .= $options[self::OSS_BUCKET];
+            // if there's no object in options, adding a '/' if the host type is not IP.\
+            if ($options[self::OSS_OBJECT] == '/') {
+                if ($this->hostType !== self::OSS_HOST_TYPE_IP) {
+                    $signableResource .= "/";
+                }
+            }
+        }
+        //signable_resource + object
+        if (isset($options[self::OSS_OBJECT]) && '/' !== $options[self::OSS_OBJECT]) {
+            $signableResource .= '/' . str_replace(array('%2F', '%25'), array('/', '%'), rawurlencode($options[self::OSS_OBJECT]));
+        }
+        if (isset($options[self::OSS_SUB_RESOURCE])) {
+            $signableResource .= '?' . $options[self::OSS_SUB_RESOURCE];
+        }
+        return $signableResource;
+    }
+
+    /**
+     * generates query string
+     *
+     * @param mixed $options
+     * @return string
+     */
+    private function generateQueryString($options)
+    {
+        //query parameters
+        $queryStringParams = array();
+        if (isset($options[self::OSS_QUERY_STRING])) {
+            $queryStringParams = array_merge($queryStringParams, $options[self::OSS_QUERY_STRING]);
+        }
+        return OssUtil::toQueryString($queryStringParams);
+    }
+
+    private function stringToSignSorted($string_to_sign)
+    {
+        $queryStringSorted = '';
+        $explodeResult = explode('?', $string_to_sign);
+        $index = count($explodeResult);
+        if ($index === 1)
+            return $string_to_sign;
+
+        $queryStringParams = explode('&', $explodeResult[$index - 1]);
+        sort($queryStringParams);
+
+        foreach($queryStringParams as $params)
+        {
+             $queryStringSorted .= $params . '&';    
+        }
+
+        $queryStringSorted = substr($queryStringSorted, 0, -1);
+
+        return $explodeResult[0] . '?' . $queryStringSorted;
+    }
+
+    /**
+     * Initialize headers
+     *
+     * @param mixed $options
+     * @param string $hostname hostname
+     * @return array
+     */
+    private function generateHeaders($options, $hostname)
+    {
+        $headers = array(
+            self::OSS_CONTENT_MD5 => '',
+            self::OSS_CONTENT_TYPE => isset($options[self::OSS_CONTENT_TYPE]) ? $options[self::OSS_CONTENT_TYPE] : self::DEFAULT_CONTENT_TYPE,
+            self::OSS_DATE => isset($options[self::OSS_DATE]) ? $options[self::OSS_DATE] : gmdate('D, d M Y H:i:s \G\M\T'),
+            self::OSS_HOST => $hostname,
+        );
+        if (isset($options[self::OSS_CONTENT_MD5])) {
+            $headers[self::OSS_CONTENT_MD5] = $options[self::OSS_CONTENT_MD5];
+        }
+
+        //Add stsSecurityToken
+        if ((!is_null($this->securityToken)) && (!$this->enableStsInUrl)) {
+            $headers[self::OSS_SECURITY_TOKEN] = $this->securityToken;
+        }
+        //Merge HTTP headers
+        if (isset($options[self::OSS_HEADERS])) {
+            $headers = array_merge($headers, $options[self::OSS_HEADERS]);
+        }
+        return $headers;
+    }
+
+    /**
+     * Generates UserAgent
+     *
+     * @return string
+     */
+    private function generateUserAgent()
+    {
+        return self::OSS_NAME . "/" . self::OSS_VERSION . " (" . php_uname('s') . "/" . php_uname('r') . "/" . php_uname('m') . ";" . PHP_VERSION . ")";
+    }
+
+    /**
+     * Checks endpoint type and returns the endpoint without the protocol schema.
+     * Figures out the domain's type (ip, cname or private/public domain).
+     *
+     * @param string $endpoint
+     * @param boolean $isCName
+     * @return string The domain name without the protocol schema.
+     */
+    private function checkEndpoint($endpoint, $isCName)
+    {
+        $ret_endpoint = null;
+        if (strpos($endpoint, 'http://') === 0) {
+            $ret_endpoint = substr($endpoint, strlen('http://'));
+        } elseif (strpos($endpoint, 'https://') === 0) {
+            $ret_endpoint = substr($endpoint, strlen('https://'));
+            $this->useSSL = true;
+        } else {
+            $ret_endpoint = $endpoint;
+        }
+
+        $ret_endpoint = OssUtil::getHostPortFromEndpoint($ret_endpoint);
+
+        if ($isCName) {
+            $this->hostType = self::OSS_HOST_TYPE_CNAME;
+        } elseif (OssUtil::isIPFormat($ret_endpoint)) {
+            $this->hostType = self::OSS_HOST_TYPE_IP;
+        } else {
+            $this->hostType = self::OSS_HOST_TYPE_NORMAL;
+        }
+        return $ret_endpoint;
+    }
+
+    /**
+     * Check if all dependent extensions are installed correctly.
+     * For now only "curl" is needed.
+     * @throws OssException
+     */
+    public static function checkEnv()
+    {
+        if (function_exists('get_loaded_extensions')) {
+            //Test curl extension
+            $enabled_extension = array("curl");
+            $extensions = get_loaded_extensions();
+            if ($extensions) {
+                foreach ($enabled_extension as $item) {
+                    if (!in_array($item, $extensions)) {
+                        throw new OssException("Extension {" . $item . "} is not installed or not enabled, please check your php env.");
+                    }
+                }
+            } else {
+                throw new OssException("function get_loaded_extensions not found.");
+            }
+        } else {
+            throw new OssException('Function get_loaded_extensions has been disabled, please check php config.');
+        }
+    }
+
+    /**
+     * Sets the http's timeout (in seconds)
+     *
+     * @param int $timeout
+     */
+    public function setTimeout($timeout)
+    {
+        $this->timeout = $timeout;
+    }
+
+    /**
+     * Sets the http's connection timeout (in seconds)
+     *
+     * @param int $connectTimeout
+     */
+    public function setConnectTimeout($connectTimeout)
+    {
+        $this->connectTimeout = $connectTimeout;
+    }
+
+    // Constants for Life cycle
+    const OSS_LIFECYCLE_EXPIRATION = "Expiration";
+    const OSS_LIFECYCLE_TIMING_DAYS = "Days";
+    const OSS_LIFECYCLE_TIMING_DATE = "Date";
+    //OSS Internal constants
+    const OSS_BUCKET = 'bucket';
+    const OSS_OBJECT = 'object';
+    const OSS_HEADERS = OssUtil::OSS_HEADERS;
+    const OSS_METHOD = 'method';
+    const OSS_QUERY = 'query';
+    const OSS_BASENAME = 'basename';
+    const OSS_MAX_KEYS = 'max-keys';
+    const OSS_UPLOAD_ID = 'uploadId';
+    const OSS_PART_NUM = 'partNumber';
+    const OSS_COMP = 'comp';
+    const OSS_LIVE_CHANNEL_STATUS = 'status';
+    const OSS_LIVE_CHANNEL_START_TIME = 'startTime';
+    const OSS_LIVE_CHANNEL_END_TIME = 'endTime';
+    const OSS_POSITION = 'position';
+    const OSS_MAX_KEYS_VALUE = 100;
+    const OSS_MAX_OBJECT_GROUP_VALUE = OssUtil::OSS_MAX_OBJECT_GROUP_VALUE;
+    const OSS_MAX_PART_SIZE = OssUtil::OSS_MAX_PART_SIZE;
+    const OSS_MID_PART_SIZE = OssUtil::OSS_MID_PART_SIZE;
+    const OSS_MIN_PART_SIZE = OssUtil::OSS_MIN_PART_SIZE;
+    const OSS_FILE_SLICE_SIZE = 8192;
+    const OSS_PREFIX = 'prefix';
+    const OSS_DELIMITER = 'delimiter';
+    const OSS_MARKER = 'marker';
+    const OSS_ACCEPT_ENCODING = 'Accept-Encoding';
+    const OSS_CONTENT_MD5 = 'Content-Md5';
+    const OSS_SELF_CONTENT_MD5 = 'x-oss-meta-md5';
+    const OSS_CONTENT_TYPE = 'Content-Type';
+    const OSS_CONTENT_LENGTH = 'Content-Length';
+    const OSS_IF_MODIFIED_SINCE = 'If-Modified-Since';
+    const OSS_IF_UNMODIFIED_SINCE = 'If-Unmodified-Since';
+    const OSS_IF_MATCH = 'If-Match';
+    const OSS_IF_NONE_MATCH = 'If-None-Match';
+    const OSS_CACHE_CONTROL = 'Cache-Control';
+    const OSS_EXPIRES = 'Expires';
+    const OSS_PREAUTH = 'preauth';
+    const OSS_CONTENT_COING = 'Content-Coding';
+    const OSS_CONTENT_DISPOSTION = 'Content-Disposition';
+    const OSS_RANGE = 'range';
+    const OSS_ETAG = 'etag';
+    const OSS_LAST_MODIFIED = 'lastmodified';
+    const OS_CONTENT_RANGE = 'Content-Range';
+    const OSS_CONTENT = OssUtil::OSS_CONTENT;
+    const OSS_BODY = 'body';
+    const OSS_LENGTH = OssUtil::OSS_LENGTH;
+    const OSS_HOST = 'Host';
+    const OSS_DATE = 'Date';
+    const OSS_AUTHORIZATION = 'Authorization';
+    const OSS_FILE_DOWNLOAD = 'fileDownload';
+    const OSS_FILE_UPLOAD = 'fileUpload';
+    const OSS_PART_SIZE = 'partSize';
+    const OSS_SEEK_TO = 'seekTo';
+    const OSS_SIZE = 'size';
+    const OSS_QUERY_STRING = 'query_string';
+    const OSS_SUB_RESOURCE = 'sub_resource';
+    const OSS_DEFAULT_PREFIX = 'x-oss-';
+    const OSS_CHECK_MD5 = 'checkmd5';
+    const DEFAULT_CONTENT_TYPE = 'application/octet-stream';
+    const OSS_SYMLINK_TARGET = 'x-oss-symlink-target';
+    const OSS_SYMLINK = 'symlink';
+    const OSS_HTTP_CODE = 'http_code';
+    const OSS_REQUEST_ID = 'x-oss-request-id';
+    const OSS_INFO = 'info';
+    const OSS_STORAGE = 'storage';
+    const OSS_RESTORE = 'restore';
+    const OSS_STORAGE_STANDARD = 'Standard';
+    const OSS_STORAGE_IA = 'IA';
+    const OSS_STORAGE_ARCHIVE = 'Archive';
+    const OSS_STORAGE_COLDARCHIVE = 'ColdArchive';
+    const OSS_TAGGING = 'tagging';
+    const OSS_WORM_ID = 'wormId';
+    const OSS_RESTORE_CONFIG = 'restore-config';
+    const OSS_KEY_MARKER = 'key-marker';
+    const OSS_VERSION_ID_MARKER = 'version-id-marker';
+    const OSS_VERSION_ID = 'versionId';
+    const OSS_HEADER_VERSION_ID = 'x-oss-version-id';
+
+    //private URLs
+    const OSS_URL_ACCESS_KEY_ID = 'OSSAccessKeyId';
+    const OSS_URL_EXPIRES = 'Expires';
+    const OSS_URL_SIGNATURE = 'Signature';
+    //HTTP METHOD
+    const OSS_HTTP_GET = 'GET';
+    const OSS_HTTP_PUT = 'PUT';
+    const OSS_HTTP_HEAD = 'HEAD';
+    const OSS_HTTP_POST = 'POST';
+    const OSS_HTTP_DELETE = 'DELETE';
+    const OSS_HTTP_OPTIONS = 'OPTIONS';
+    //Others
+    const OSS_ACL = 'x-oss-acl';
+    const OSS_OBJECT_ACL = 'x-oss-object-acl';
+    const OSS_OBJECT_GROUP = 'x-oss-file-group';
+    const OSS_MULTI_PART = 'uploads';
+    const OSS_MULTI_DELETE = 'delete';
+    const OSS_OBJECT_COPY_SOURCE = 'x-oss-copy-source';
+    const OSS_OBJECT_COPY_SOURCE_RANGE = "x-oss-copy-source-range";
+    const OSS_PROCESS = "x-oss-process";
+    const OSS_CALLBACK = "x-oss-callback";
+    const OSS_CALLBACK_VAR = "x-oss-callback-var";
+    const OSS_REQUEST_PAYER = "x-oss-request-payer";
+    const OSS_TRAFFIC_LIMIT = "x-oss-traffic-limit";
+    //Constants for STS SecurityToken
+    const OSS_SECURITY_TOKEN = "x-oss-security-token";
+    const OSS_ACL_TYPE_PRIVATE = 'private';
+    const OSS_ACL_TYPE_PUBLIC_READ = 'public-read';
+    const OSS_ACL_TYPE_PUBLIC_READ_WRITE = 'public-read-write';
+    const OSS_ENCODING_TYPE = "encoding-type";
+    const OSS_ENCODING_TYPE_URL = "url";
+
+    // Domain Types
+    const OSS_HOST_TYPE_NORMAL = "normal";//http://bucket.oss-cn-hangzhou.aliyuncs.com/object
+    const OSS_HOST_TYPE_IP = "ip";  //http://1.1.1.1/bucket/object
+    const OSS_HOST_TYPE_SPECIAL = 'special'; //http://bucket.guizhou.gov/object
+    const OSS_HOST_TYPE_CNAME = "cname";  //http://mydomain.com/object
+    //OSS ACL array
+    static $OSS_ACL_TYPES = array(
+        self::OSS_ACL_TYPE_PRIVATE,
+        self::OSS_ACL_TYPE_PUBLIC_READ,
+        self::OSS_ACL_TYPE_PUBLIC_READ_WRITE
+    );
+    // OssClient version information
+    const OSS_NAME = "aliyun-sdk-php";
+    const OSS_VERSION = "2.4.1";
+    const OSS_BUILD = "20200929";
+    const OSS_AUTHOR = "";
+    const OSS_OPTIONS_ORIGIN = 'Origin';
+    const OSS_OPTIONS_REQUEST_METHOD = 'Access-Control-Request-Method';
+    const OSS_OPTIONS_REQUEST_HEADERS = 'Access-Control-Request-Headers';
+
+    //use ssl flag
+    private $useSSL = false;
+    private $maxRetries = 3;
+    private $redirects = 0;
+
+    // user's domain type. It could be one of the four: OSS_HOST_TYPE_NORMAL, OSS_HOST_TYPE_IP, OSS_HOST_TYPE_SPECIAL, OSS_HOST_TYPE_CNAME
+    private $hostType = self::OSS_HOST_TYPE_NORMAL;
+    private $requestUrl;
+    private $requestProxy = null;
+    private $accessKeyId;
+    private $accessKeySecret;
+    private $hostname;
+    private $securityToken;
+    private $enableStsInUrl = false;
+    private $timeout = 0;
+    private $connectTimeout = 0;
+}

+ 31 - 0
sdk/OSS/Result/AclResult.php

@@ -0,0 +1,31 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * The type of the return value of getBucketAcl, it wraps the data parsed from xml.
+ *
+ * @package OSS\Result
+ */
+class AclResult extends Result
+{
+    /**
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        if (empty($content)) {
+            throw new OssException("body is null");
+        }
+        $xml = simplexml_load_string($content);
+        if (isset($xml->AccessControlList->Grant)) {
+            return strval($xml->AccessControlList->Grant);
+        } else {
+            throw new OssException("xml format exception");
+        }
+    }
+}

+ 27 - 0
sdk/OSS/Result/AppendResult.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * Class AppendResult
+ * @package OSS\Result
+ */
+class AppendResult extends Result
+{
+    /**
+     * Get the value of next-append-position from append's response headers
+     *
+     * @return int
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $header = $this->rawResponse->header;
+        if (isset($header["x-oss-next-append-position"])) {
+            return intval($header["x-oss-next-append-position"]);
+        }
+        throw new OssException("cannot get next-append-position");
+    }
+}

+ 19 - 0
sdk/OSS/Result/BodyResult.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class BodyResult
+ * @package OSS\Result
+ */
+class BodyResult extends Result
+{
+    /**
+     * @return string
+     */
+    protected function parseDataFromResponse()
+    {
+        return empty($this->rawResponse->body) ? "" : $this->rawResponse->body;
+    }
+}

+ 21 - 0
sdk/OSS/Result/CallbackResult.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class CallbackResult
+ * @package OSS\Result
+ */
+class CallbackResult extends PutSetDeleteResult
+{
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 && (int)(intval($status)) !== 203) {
+            return true;
+        }
+        return false;
+    }
+
+}

+ 30 - 0
sdk/OSS/Result/CopyObjectResult.php

@@ -0,0 +1,30 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class CopyObjectResult
+ * @package OSS\Result
+ */
+class CopyObjectResult extends Result
+{
+    /**
+     * @return array()
+     */
+    protected function parseDataFromResponse()
+    {
+        $body = $this->rawResponse->body;
+        $xml = simplexml_load_string($body); 
+        $result = array();
+        
+        if (isset($xml->LastModified)) {
+            $result[] = $xml->LastModified;
+        }
+        if (isset($xml->ETag)) {
+            $result[] = $xml->ETag;
+        }
+
+        return array_merge($result, $this->rawResponse->header);
+    }
+}

+ 39 - 0
sdk/OSS/Result/DeleteObjectVersionsResult.php

@@ -0,0 +1,39 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssUtil;
+use OSS\Model\DeletedObjectInfo;
+
+/**
+ * Class DeleteObjectVersionsResult
+ * @package OSS\Result
+ */
+class DeleteObjectVersionsResult extends Result
+{
+    /**
+     * @return DeletedObjectInfo[]
+     */
+    protected function parseDataFromResponse()
+    {
+        $xml = simplexml_load_string($this->rawResponse->body); 
+        $encodingType = isset($xml->EncodingType) ? strval($xml->EncodingType) : "";
+        return $this->parseDeletedList($xml, $encodingType);
+    }
+
+    private function parseDeletedList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->Deleted)) {
+            foreach ($xml->Deleted as $content) {
+                $key = isset($content->Key) ? strval($content->Key) : "";
+                $key = OssUtil::decodeKey($key, $encodingType);
+                $versionId = isset($content->VersionId) ? strval($content->VersionId) : "";
+                $deleteMarker = isset($content->DeleteMarker) ? strval($content->DeleteMarker) : "";
+                $deleteMarkerVersionId = isset($content->DeleteMarkerVersionId) ? strval($content->DeleteMarkerVersionId) : "";
+                $retList[] = new DeletedObjectInfo($key, $versionId, $deleteMarker, $deleteMarkerVersionId);
+            }
+        }
+        return $retList;
+    }
+}

+ 27 - 0
sdk/OSS/Result/DeleteObjectsResult.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class DeleteObjectsResult
+ * @package OSS\Result
+ */
+class DeleteObjectsResult extends Result
+{
+    /**
+     * @return array()
+     */
+    protected function parseDataFromResponse()
+    {
+        $body = $this->rawResponse->body;
+        $xml = simplexml_load_string($body); 
+        $objects = array();
+
+        if (isset($xml->Deleted)) {
+            foreach($xml->Deleted as $deleteKey)
+                $objects[] = $deleteKey->Key;
+        }
+        return $objects;
+    }
+}

+ 34 - 0
sdk/OSS/Result/ExistResult.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace OSS\Result;
+
+/**
+ * Class ExistResult checks if bucket or object exists, according to the http status in response headers.
+ * @package OSS\Result
+ */
+class ExistResult extends Result
+{
+    /**
+     * @return bool
+     */
+    protected function parseDataFromResponse()
+    {
+        return intval($this->rawResponse->status) === 200 ? true : false;
+    }
+
+    /**
+     * Check if the response status is OK according to the http status code.
+     * [200-299]: OK; [404]: Not found. It means the object or bucket is not found--it's a valid response too.
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+
+}

+ 26 - 0
sdk/OSS/Result/GetBucketEncryptionResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\ServerSideEncryptionConfig;
+
+/**
+ * Class GetBucketEncryptionResult
+ * @package OSS\Result
+ */
+class GetBucketEncryptionResult extends Result
+{
+    /**
+     *  Parse the ServerSideEncryptionConfig object from the response
+     *
+     * @return ServerSideEncryptionConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new ServerSideEncryptionConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+}

+ 37 - 0
sdk/OSS/Result/GetBucketInfoResult.php

@@ -0,0 +1,37 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+use OSS\Model\BucketInfo;
+
+/**
+ * Class GetBucketResult interface returns the result class, encapsulated
+ * The returned xml data is parsed
+ *
+ * @package OSS\Result
+ */
+class GetBucketInfoResult extends Result
+{
+    /**
+     * Parse data from response
+     * 
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        if (empty($content)) {
+            throw new OssException("body is null");
+        }
+        $xml = simplexml_load_string($content);
+        if (isset($xml->Bucket)) {
+            $info = new BucketInfo();
+            $info->parseFromXmlNode($xml->Bucket);
+            return $info;
+        } else {
+            throw new OssException("xml format exception");
+        }
+    }
+}

+ 26 - 0
sdk/OSS/Result/GetBucketRequestPaymentResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\RequestPaymentConfig;
+
+/**
+ * Class GetBucketRequestPaymentResult
+ * @package OSS\Result
+ */
+class GetBucketRequestPaymentResult extends Result
+{
+    /**
+     *  Parse the RequestPaymentConfig object from the response
+     *
+     * @return RequestPaymentConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new RequestPaymentConfig();
+        $config->parseFromXml($content);
+        return $config->getPayer();
+    }
+}

+ 26 - 0
sdk/OSS/Result/GetBucketStatResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\BucketStat;
+
+/**
+ * Class GetRefererResult
+ * @package OSS\Result
+ */
+class GetBucketStatResult extends Result
+{
+    /**
+     * Parse bucket stat data
+     *
+     * @return BucketStat
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $stat = new BucketStat();
+        $stat->parseFromXml($content);
+        return $stat;
+    }
+}

+ 26 - 0
sdk/OSS/Result/GetBucketTagsResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\TaggingConfig;
+
+/**
+ * Class GetBucketTagsResult
+ * @package OSS\Result
+ */
+class GetBucketTagsResult extends Result
+{
+    /**
+     *  Parse the TaggingConfig object from the response
+     *
+     * @return TaggingConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new TaggingConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+}

+ 26 - 0
sdk/OSS/Result/GetBucketVersioningResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\VersioningConfig;
+
+/**
+ * Class GetBucketVersioningResult
+ * @package OSS\Result
+ */
+class GetBucketVersioningResult extends Result
+{
+    /**
+     *  Parse the VersioningConfig object from the response
+     *
+     * @return VersioningConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new VersioningConfig();
+        $config->parseFromXml($content);
+        return $config->getStatus();
+    }
+}

+ 26 - 0
sdk/OSS/Result/GetBucketWormResult.php

@@ -0,0 +1,26 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\WormConfig;
+
+/**
+ * Class GetBucketWormResult
+ * @package OSS\Result
+ */
+class GetBucketWormResult extends Result
+{
+    /**
+     * Parse bucket stat data
+     *
+     * @return WormConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new WormConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+}

+ 19 - 0
sdk/OSS/Result/GetCnameResult.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\CnameConfig;
+
+class GetCnameResult extends Result
+{
+    /**
+     * @return CnameConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new CnameConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+}

+ 34 - 0
sdk/OSS/Result/GetCorsResult.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\CorsConfig;
+
+class GetCorsResult extends Result
+{
+    /**
+     * @return CorsConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new CorsConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+
+    /**
+     * Check if the response is OK, according to the http status. [200-299]:OK, the Cors config could be got; [404]: not found--no Cors config.
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+
+}

+ 41 - 0
sdk/OSS/Result/GetLifecycleResult.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\LifecycleConfig;
+
+/**
+ * Class GetLifecycleResult
+ * @package OSS\Result
+ */
+class GetLifecycleResult extends Result
+{
+    /**
+     *  Parse the LifecycleConfig object from the response
+     *
+     * @return LifecycleConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new LifecycleConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+
+    /**
+     * Check if the response is OK according to the http status.
+     * [200-299]: OK, and the LifecycleConfig could be got; [404] The Life cycle config is not found.
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+}

+ 19 - 0
sdk/OSS/Result/GetLiveChannelHistoryResult.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\GetLiveChannelHistory;
+
+class GetLiveChannelHistoryResult extends Result
+{
+    /**
+     * @return
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $channelList = new GetLiveChannelHistory();
+        $channelList->parseFromXml($content);
+        return $channelList;
+    }
+}

+ 19 - 0
sdk/OSS/Result/GetLiveChannelInfoResult.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\GetLiveChannelInfo;
+
+class GetLiveChannelInfoResult extends Result
+{
+    /**
+     * @return
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $channelList = new GetLiveChannelInfo();
+        $channelList->parseFromXml($content);
+        return $channelList;
+    }
+}

+ 19 - 0
sdk/OSS/Result/GetLiveChannelStatusResult.php

@@ -0,0 +1,19 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\GetLiveChannelStatus;
+
+class GetLiveChannelStatusResult extends Result
+{
+    /**
+     * @return
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $channelList = new GetLiveChannelStatus();
+        $channelList->parseFromXml($content);
+        return $channelList;
+    }
+}

+ 30 - 0
sdk/OSS/Result/GetLocationResult.php

@@ -0,0 +1,30 @@
+<?php
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * Class GetLocationResult getBucketLocation interface returns the result class, encapsulated
+ * The returned xml data is parsed
+ *
+ * @package OSS\Result
+ */
+class GetLocationResult extends Result
+{
+
+    /**
+     * Parse data from response
+     * 
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        if (empty($content)) {
+            throw new OssException("body is null");
+        }
+        $xml = simplexml_load_string($content);
+        return $xml;
+    }
+}

+ 41 - 0
sdk/OSS/Result/GetLoggingResult.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\LoggingConfig;
+
+
+/**
+ * Class GetLoggingResult
+ * @package OSS\Result
+ */
+class GetLoggingResult extends Result
+{
+    /**
+     * Parse LoggingConfig data
+     *
+     * @return LoggingConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new LoggingConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+
+    /**
+     * Judged according to the return HTTP status code, [200-299] that is OK, get the bucket configuration interface,
+     * 404 is also considered a valid response
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+}

+ 41 - 0
sdk/OSS/Result/GetRefererResult.php

@@ -0,0 +1,41 @@
+<?php
+
+namespace OSS\Result;
+
+
+use OSS\Model\RefererConfig;
+
+/**
+ * Class GetRefererResult
+ * @package OSS\Result
+ */
+class GetRefererResult extends Result
+{
+    /**
+     * Parse RefererConfig data
+     *
+     * @return RefererConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new RefererConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+
+    /**
+     * Judged according to the return HTTP status code, [200-299] that is OK, get the bucket configuration interface,
+     * 404 is also considered a valid response
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+}

+ 34 - 0
sdk/OSS/Result/GetStorageCapacityResult.php

@@ -0,0 +1,34 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * Class AclResult  GetBucketAcl interface returns the result class, encapsulated
+ * The returned xml data is parsed
+ *
+ * @package OSS\Result
+ */
+class GetStorageCapacityResult extends Result
+{
+    /**
+     * Parse data from response
+     * 
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        if (empty($content)) {
+            throw new OssException("body is null");
+        }
+        $xml = simplexml_load_string($content);
+        if (isset($xml->StorageCapacity)) {
+            return intval($xml->StorageCapacity);
+        } else {
+            throw new OssException("xml format exception");
+        }
+    }
+}

+ 40 - 0
sdk/OSS/Result/GetWebsiteResult.php

@@ -0,0 +1,40 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\WebsiteConfig;
+
+/**
+ * Class GetWebsiteResult
+ * @package OSS\Result
+ */
+class GetWebsiteResult extends Result
+{
+    /**
+     * Parse WebsiteConfig data
+     *
+     * @return WebsiteConfig
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $config = new WebsiteConfig();
+        $config->parseFromXml($content);
+        return $config;
+    }
+
+    /**
+     * Judged according to the return HTTP status code, [200-299] that is OK, get the bucket configuration interface,
+     * 404 is also considered a valid response
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2 || (int)(intval($status)) === 404) {
+            return true;
+        }
+        return false;
+    }
+}

+ 23 - 0
sdk/OSS/Result/HeaderResult.php

@@ -0,0 +1,23 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class HeaderResult
+ * @package OSS\Result
+ * @link https://docs.aliyun.com/?spm=5176.383663.13.7.HgUIqL#/pub/oss/api-reference/object&GetObjectMeta
+ */
+class HeaderResult extends Result
+{
+    /**
+     * The returned ResponseCore header is used as the return data
+     *
+     * @return array
+     */
+    protected function parseDataFromResponse()
+    {
+        return empty($this->rawResponse->header) ? array() : $this->rawResponse->header;
+    }
+
+}

+ 27 - 0
sdk/OSS/Result/InitiateBucketWormResult.php

@@ -0,0 +1,27 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * Class InitiateBucketWormResult
+ * @package OSS\Result
+ */
+class InitiateBucketWormResult extends Result
+{
+    /**
+     * Get the value of worm-id from response headers
+     *
+     * @return int
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $header = $this->rawResponse->header;
+        if (isset($header["x-oss-worm-id"])) {
+            return strval($header["x-oss-worm-id"]);
+        }
+        throw new OssException("cannot get worm-id");
+    }
+}

+ 29 - 0
sdk/OSS/Result/InitiateMultipartUploadResult.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+
+/**
+ * Class initiateMultipartUploadResult
+ * @package OSS\Result
+ */
+class InitiateMultipartUploadResult extends Result
+{
+    /**
+     * Get uploadId in result and return
+     *
+     * @throws OssException
+     * @return string
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $xml = simplexml_load_string($content);
+        if (isset($xml->UploadId)) {
+            return strval($xml->UploadId);
+        }
+        throw new OssException("cannot get UploadId");
+    }
+}

+ 32 - 0
sdk/OSS/Result/ListBucketsResult.php

@@ -0,0 +1,32 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\BucketInfo;
+use OSS\Model\BucketListInfo;
+
+/**
+ * Class ListBucketsResult
+ *
+ * @package OSS\Result
+ */
+class ListBucketsResult extends Result
+{
+    /**
+     * @return BucketListInfo
+     */
+    protected function parseDataFromResponse()
+    {
+        $bucketList = array();
+        $content = $this->rawResponse->body;
+        $xml = new \SimpleXMLElement($content);
+        if (isset($xml->Buckets) && isset($xml->Buckets->Bucket)) {
+            foreach ($xml->Buckets->Bucket as $bucket) {
+                $bucketInfo = new BucketInfo();
+                $bucketInfo->parseFromXmlNode($bucket);
+                $bucketList[] = $bucketInfo;
+            }
+        }
+        return new BucketListInfo($bucketList);
+    }
+}

+ 16 - 0
sdk/OSS/Result/ListLiveChannelResult.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\LiveChannelListInfo;
+
+class ListLiveChannelResult extends Result
+{
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $channelList = new LiveChannelListInfo();
+        $channelList->parseFromXml($content);
+        return $channelList;
+    }
+}

+ 55 - 0
sdk/OSS/Result/ListMultipartUploadResult.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssUtil;
+use OSS\Model\ListMultipartUploadInfo;
+use OSS\Model\UploadInfo;
+
+
+/**
+ * Class ListMultipartUploadResult
+ * @package OSS\Result
+ */
+class ListMultipartUploadResult extends Result
+{
+    /**
+     * Parse the return data from the ListMultipartUpload interface
+     *
+     * @return ListMultipartUploadInfo
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $xml = simplexml_load_string($content);
+
+        $encodingType = isset($xml->EncodingType) ? strval($xml->EncodingType) : "";
+        $bucket = isset($xml->Bucket) ? strval($xml->Bucket) : "";
+        $keyMarker = isset($xml->KeyMarker) ? strval($xml->KeyMarker) : "";
+        $keyMarker = OssUtil::decodeKey($keyMarker, $encodingType);
+        $uploadIdMarker = isset($xml->UploadIdMarker) ? strval($xml->UploadIdMarker) : "";
+        $nextKeyMarker = isset($xml->NextKeyMarker) ? strval($xml->NextKeyMarker) : "";
+        $nextKeyMarker = OssUtil::decodeKey($nextKeyMarker, $encodingType);
+        $nextUploadIdMarker = isset($xml->NextUploadIdMarker) ? strval($xml->NextUploadIdMarker) : "";
+        $delimiter = isset($xml->Delimiter) ? strval($xml->Delimiter) : "";
+        $delimiter = OssUtil::decodeKey($delimiter, $encodingType);
+        $prefix = isset($xml->Prefix) ? strval($xml->Prefix) : "";
+        $prefix = OssUtil::decodeKey($prefix, $encodingType);
+        $maxUploads = isset($xml->MaxUploads) ? intval($xml->MaxUploads) : 0;
+        $isTruncated = isset($xml->IsTruncated) ? strval($xml->IsTruncated) : "";
+        $listUpload = array();
+
+        if (isset($xml->Upload)) {
+            foreach ($xml->Upload as $upload) {
+                $key = isset($upload->Key) ? strval($upload->Key) : "";
+                $key = OssUtil::decodeKey($key, $encodingType);
+                $uploadId = isset($upload->UploadId) ? strval($upload->UploadId) : "";
+                $initiated = isset($upload->Initiated) ? strval($upload->Initiated) : "";
+                $listUpload[] = new UploadInfo($key, $uploadId, $initiated);
+            }
+        }
+        return new ListMultipartUploadInfo($bucket, $keyMarker, $uploadIdMarker,
+            $nextKeyMarker, $nextUploadIdMarker,
+            $delimiter, $prefix, $maxUploads, $isTruncated, $listUpload);
+    }
+}

+ 96 - 0
sdk/OSS/Result/ListObjectVersionsResult.php

@@ -0,0 +1,96 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssUtil;
+use OSS\Model\ObjectVersionInfo;
+use OSS\Model\ObjectVersionListInfo;
+use OSS\Model\DeleteMarkerInfo;
+use OSS\Model\PrefixInfo;
+
+/**
+ * Class ListObjectVersionsResult
+ * @package OSS\Result
+ */
+class ListObjectVersionsResult extends Result
+{
+    /**
+     * Parse the xml data returned by the ListObjectVersions interface
+     *
+     * return ObjectVersionListInfo
+     */
+    protected function parseDataFromResponse()
+    {
+        $xml = simplexml_load_string($this->rawResponse->body); 
+        $encodingType = isset($xml->EncodingType) ? strval($xml->EncodingType) : "";
+        $objectVersionList = $this->parseObjecVersionList($xml, $encodingType);
+        $deleteMarkerList = $this->parseDeleteMarkerList($xml, $encodingType);
+        $prefixList = $this->parsePrefixList($xml, $encodingType);
+        $bucketName = isset($xml->Name) ? strval($xml->Name) : "";
+        $prefix = isset($xml->Prefix) ? strval($xml->Prefix) : "";
+        $prefix = OssUtil::decodeKey($prefix, $encodingType);
+        $keyMarker = isset($xml->KeyMarker) ? strval($xml->KeyMarker) : "";
+        $keyMarker = OssUtil::decodeKey($keyMarker, $encodingType);
+        $nextKeyMarker = isset($xml->NextKeyMarker) ? strval($xml->NextKeyMarker) : "";
+        $nextKeyMarker = OssUtil::decodeKey($nextKeyMarker, $encodingType);
+        $versionIdMarker = isset($xml->VersionIdMarker) ? strval($xml->VersionIdMarker) : "";
+        $nextVersionIdMarker = isset($xml->NextVersionIdMarker) ? strval($xml->NextVersionIdMarker) : "";
+        $maxKeys = isset($xml->MaxKeys) ? intval($xml->MaxKeys) : 0;
+        $delimiter = isset($xml->Delimiter) ? strval($xml->Delimiter) : "";
+        $delimiter = OssUtil::decodeKey($delimiter, $encodingType);
+        $isTruncated = isset($xml->IsTruncated) ? strval($xml->IsTruncated) : "";
+
+        return new ObjectVersionListInfo($bucketName, $prefix, $keyMarker, $nextKeyMarker, 
+            $versionIdMarker, $nextVersionIdMarker,$maxKeys, $delimiter, $isTruncated,
+            $objectVersionList, $deleteMarkerList, $prefixList);
+    }
+
+    private function parseObjecVersionList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->Version)) {
+            foreach ($xml->Version as $content) {
+                $key = isset($content->Key) ? strval($content->Key) : "";
+                $key = OssUtil::decodeKey($key, $encodingType);
+                $versionId = isset($content->VersionId) ? strval($content->VersionId) : "";
+                $lastModified = isset($content->LastModified) ? strval($content->LastModified) : "";
+                $eTag = isset($content->ETag) ? strval($content->ETag) : "";
+                $type = isset($content->Type) ? strval($content->Type) : "";
+                $size = isset($content->Size) ? intval($content->Size) : 0;
+                $storageClass = isset($content->StorageClass) ? strval($content->StorageClass) : "";
+                $isLatest = isset($content->IsLatest) ? strval($content->IsLatest) : "";
+                $retList[] = new ObjectVersionInfo($key, $versionId, $lastModified, $eTag, $type, $size, $storageClass, $isLatest);
+            }
+        }
+        return $retList;
+    }
+
+    private function parseDeleteMarkerList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->DeleteMarker)) {
+            foreach ($xml->DeleteMarker as $content) {
+                $key = isset($content->Key) ? strval($content->Key) : "";
+                $key = OssUtil::decodeKey($key, $encodingType);
+                $versionId = isset($content->VersionId) ? strval($content->VersionId) : "";
+                $lastModified = isset($content->LastModified) ? strval($content->LastModified) : "";
+                $isLatest = isset($content->IsLatest) ? strval($content->IsLatest) : "";
+                $retList[] = new DeleteMarkerInfo($key, $versionId, $lastModified, $isLatest);
+            }
+        }
+        return $retList;
+    }
+
+    private function parsePrefixList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->CommonPrefixes)) {
+            foreach ($xml->CommonPrefixes as $commonPrefix) {
+                $prefix = isset($commonPrefix->Prefix) ? strval($commonPrefix->Prefix) : "";
+                $prefix = OssUtil::decodeKey($prefix, $encodingType);
+                $retList[] = new PrefixInfo($prefix);
+            }
+        }
+        return $retList;
+    }
+}

+ 71 - 0
sdk/OSS/Result/ListObjectsResult.php

@@ -0,0 +1,71 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssUtil;
+use OSS\Model\ObjectInfo;
+use OSS\Model\ObjectListInfo;
+use OSS\Model\PrefixInfo;
+
+/**
+ * Class ListObjectsResult
+ * @package OSS\Result
+ */
+class ListObjectsResult extends Result
+{
+    /**
+     * Parse the xml data returned by the ListObjects interface
+     *
+     * return ObjectListInfo
+     */
+    protected function parseDataFromResponse()
+    {
+        $xml = new \SimpleXMLElement($this->rawResponse->body);
+        $encodingType = isset($xml->EncodingType) ? strval($xml->EncodingType) : "";
+        $objectList = $this->parseObjectList($xml, $encodingType);
+        $prefixList = $this->parsePrefixList($xml, $encodingType);
+        $bucketName = isset($xml->Name) ? strval($xml->Name) : "";
+        $prefix = isset($xml->Prefix) ? strval($xml->Prefix) : "";
+        $prefix = OssUtil::decodeKey($prefix, $encodingType);
+        $marker = isset($xml->Marker) ? strval($xml->Marker) : "";
+        $marker = OssUtil::decodeKey($marker, $encodingType);
+        $maxKeys = isset($xml->MaxKeys) ? intval($xml->MaxKeys) : 0;
+        $delimiter = isset($xml->Delimiter) ? strval($xml->Delimiter) : "";
+        $delimiter = OssUtil::decodeKey($delimiter, $encodingType);
+        $isTruncated = isset($xml->IsTruncated) ? strval($xml->IsTruncated) : "";
+        $nextMarker = isset($xml->NextMarker) ? strval($xml->NextMarker) : "";
+        $nextMarker = OssUtil::decodeKey($nextMarker, $encodingType);
+        return new ObjectListInfo($bucketName, $prefix, $marker, $nextMarker, $maxKeys, $delimiter, $isTruncated, $objectList, $prefixList);
+    }
+
+    private function parseObjectList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->Contents)) {
+            foreach ($xml->Contents as $content) {
+                $key = isset($content->Key) ? strval($content->Key) : "";
+                $key = OssUtil::decodeKey($key, $encodingType);
+                $lastModified = isset($content->LastModified) ? strval($content->LastModified) : "";
+                $eTag = isset($content->ETag) ? strval($content->ETag) : "";
+                $type = isset($content->Type) ? strval($content->Type) : "";
+                $size = isset($content->Size) ? intval($content->Size) : 0;
+                $storageClass = isset($content->StorageClass) ? strval($content->StorageClass) : "";
+                $retList[] = new ObjectInfo($key, $lastModified, $eTag, $type, $size, $storageClass);
+            }
+        }
+        return $retList;
+    }
+
+    private function parsePrefixList($xml, $encodingType)
+    {
+        $retList = array();
+        if (isset($xml->CommonPrefixes)) {
+            foreach ($xml->CommonPrefixes as $commonPrefix) {
+                $prefix = isset($commonPrefix->Prefix) ? strval($commonPrefix->Prefix) : "";
+                $prefix = OssUtil::decodeKey($prefix, $encodingType);
+                $retList[] = new PrefixInfo($prefix);
+            }
+        }
+        return $retList;
+    }
+}

+ 42 - 0
sdk/OSS/Result/ListPartsResult.php

@@ -0,0 +1,42 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\ListPartsInfo;
+use OSS\Model\PartInfo;
+
+
+/**
+ * Class ListPartsResult
+ * @package OSS\Result
+ */
+class ListPartsResult extends Result
+{
+    /**
+     * Parse the xml data returned by the ListParts interface
+     *
+     * @return ListPartsInfo
+     */
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $xml = simplexml_load_string($content);
+        $bucket = isset($xml->Bucket) ? strval($xml->Bucket) : "";
+        $key = isset($xml->Key) ? strval($xml->Key) : "";
+        $uploadId = isset($xml->UploadId) ? strval($xml->UploadId) : "";
+        $nextPartNumberMarker = isset($xml->NextPartNumberMarker) ? intval($xml->NextPartNumberMarker) : "";
+        $maxParts = isset($xml->MaxParts) ? intval($xml->MaxParts) : "";
+        $isTruncated = isset($xml->IsTruncated) ? strval($xml->IsTruncated) : "";
+        $partList = array();
+        if (isset($xml->Part)) {
+            foreach ($xml->Part as $part) {
+                $partNumber = isset($part->PartNumber) ? intval($part->PartNumber) : "";
+                $lastModified = isset($part->LastModified) ? strval($part->LastModified) : "";
+                $eTag = isset($part->ETag) ? strval($part->ETag) : "";
+                $size = isset($part->Size) ? intval($part->Size) : "";
+                $partList[] = new PartInfo($partNumber, $lastModified, $eTag, $size);
+            }
+        }
+        return new ListPartsInfo($bucket, $key, $uploadId, $nextPartNumberMarker, $maxParts, $isTruncated, $partList);
+    }
+}

+ 16 - 0
sdk/OSS/Result/PutLiveChannelResult.php

@@ -0,0 +1,16 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Model\LiveChannelInfo;
+
+class PutLiveChannelResult extends Result
+{
+    protected function parseDataFromResponse()
+    {
+        $content = $this->rawResponse->body;
+        $channel = new LiveChannelInfo();
+        $channel->parseFromXml($content);
+        return $channel;
+    }
+}

+ 20 - 0
sdk/OSS/Result/PutSetDeleteResult.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace OSS\Result;
+
+
+/**
+ * Class PutSetDeleteResult
+ * @package OSS\Result
+ */
+class PutSetDeleteResult extends Result
+{
+    /**
+     * @return array()
+     */
+    protected function parseDataFromResponse()
+    {
+        $body = array('body' => $this->rawResponse->body);
+        return array_merge($this->rawResponse->header, $body);
+    }
+}

+ 175 - 0
sdk/OSS/Result/Result.php

@@ -0,0 +1,175 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+use OSS\Http\ResponseCore;
+
+
+/**
+ * Class Result, The result class of The operation of the base class, different requests in dealing with the return of data have different logic,
+ * The specific parsing logic postponed to subclass implementation
+ *
+ * @package OSS\Model
+ */
+abstract class Result
+{
+    /**
+     * Result constructor.
+     * @param $response ResponseCore
+     * @throws OssException
+     */
+    public function __construct($response)
+    {
+        if ($response === null) {
+            throw new OssException("raw response is null");
+        }
+        $this->rawResponse = $response;
+        $this->parseResponse();
+    }
+
+    /**
+     * Get requestId
+     *
+     * @return string
+     */
+    public function getRequestId()
+    {
+        if (isset($this->rawResponse) &&
+            isset($this->rawResponse->header) &&
+            isset($this->rawResponse->header['x-oss-request-id'])
+        ) {
+            return $this->rawResponse->header['x-oss-request-id'];
+        } else {
+            return '';
+        }
+    }
+
+    /**
+     * Get the returned data, different request returns the data format is different
+     *
+     * $return mixed
+     */
+    public function getData()
+    {
+        return $this->parsedData;
+    }
+
+    /**
+     * Subclass implementation, different requests return data has different analytical logic, implemented by subclasses
+     *
+     * @return mixed
+     */
+    abstract protected function parseDataFromResponse();
+
+    /**
+     * Whether the operation is successful
+     *
+     * @return mixed
+     */
+    public function isOK()
+    {
+        return $this->isOk;
+    }
+
+    /**
+     * @throws OssException
+     */
+    public function parseResponse()
+    {
+        $this->isOk = $this->isResponseOk();
+        if ($this->isOk) {
+            $this->parsedData = $this->parseDataFromResponse();
+        } else {
+            $httpStatus = strval($this->rawResponse->status);
+            $requestId = strval($this->getRequestId());
+            $code = $this->retrieveErrorCode($this->rawResponse->body);
+            $message = $this->retrieveErrorMessage($this->rawResponse->body);
+            $body = $this->rawResponse->body;
+
+            $details = array(
+                'status' => $httpStatus,
+                'request-id' => $requestId,
+                'code' => $code,
+                'message' => $message,
+                'body' => $body
+            );
+            throw new OssException($details);
+        }
+    }
+
+    /**
+     * Try to get the error message from body
+     *
+     * @param $body
+     * @return string
+     */
+    private function retrieveErrorMessage($body)
+    {
+        if (empty($body) || false === strpos($body, '<?xml')) {
+            return '';
+        }
+        $xml = simplexml_load_string($body);
+        if (isset($xml->Message)) {
+            return strval($xml->Message);
+        }
+        return '';
+    }
+
+    /**
+     * Try to get the error Code from body
+     *
+     * @param $body
+     * @return string
+     */
+    private function retrieveErrorCode($body)
+    {
+        if (empty($body) || false === strpos($body, '<?xml')) {
+            return '';
+        }
+        $xml = simplexml_load_string($body);
+        if (isset($xml->Code)) {
+            return strval($xml->Code);
+        }
+        return '';
+    }
+
+    /**
+     * Judging from the return http status code, [200-299] that is OK
+     *
+     * @return bool
+     */
+    protected function isResponseOk()
+    {
+        $status = $this->rawResponse->status;
+        if ((int)(intval($status) / 100) == 2) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return the original return data
+     *
+     * @return ResponseCore
+     */
+    public function getRawResponse()
+    {
+        return $this->rawResponse;
+    }
+
+    /**
+     * Indicate whether the request is successful
+     */
+    protected $isOk = false;
+    /**
+     * Data parsed by subclasses
+     */
+    protected $parsedData = null;
+    /**
+     * Store the original Response returned by the auth function
+     *
+     * @var ResponseCore
+     */
+    protected $rawResponse;
+}

+ 24 - 0
sdk/OSS/Result/SymlinkResult.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+use OSS\OssClient;
+
+/**
+ *
+ * @package OSS\Result
+ */
+class SymlinkResult extends Result
+{
+    /**
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $this->rawResponse->header[OssClient::OSS_SYMLINK_TARGET] = rawurldecode($this->rawResponse->header[OssClient::OSS_SYMLINK_TARGET]);
+        return $this->rawResponse->header;
+    }
+}
+

+ 28 - 0
sdk/OSS/Result/UploadPartResult.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace OSS\Result;
+
+use OSS\Core\OssException;
+
+/**
+ * Class UploadPartResult
+ * @package OSS\Result
+ */
+class UploadPartResult extends Result
+{
+    /**
+     * 结果中part的ETag
+     *
+     * @return string
+     * @throws OssException
+     */
+    protected function parseDataFromResponse()
+    {
+        $header = $this->rawResponse->header;
+        if (isset($header["etag"])) {
+            return $header["etag"];
+        }
+        throw new OssException("cannot get ETag");
+
+    }
+}

+ 12 - 0
sdk/oss.php

@@ -0,0 +1,12 @@
+<?php
+
+
+function classLoader($class)
+{
+    $path = str_replace('\\', DIRECTORY_SEPARATOR, $class);
+    $file = __DIR__ . DIRECTORY_SEPARATOR . $path . '.php';
+    if (file_exists($file)) {
+        require_once $file;
+    }
+}
+spl_autoload_register('classLoader');