internal GetObjectsListResponse(HttpStatusCode statusCode, string responseContent)
            : base(statusCode, responseContent)
        {
            if (string.IsNullOrEmpty(responseContent) ||
                !HttpStatusCode.OK.Equals(statusCode))
            {
                return;
            }
            using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(responseContent)))
            {
                this.BucketResult = (ListBucketResult) new XmlSerializer(typeof(ListBucketResult)).Deserialize(stream);
            }
            XDocument root  = XDocument.Parse(responseContent);
            var       items = from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Contents")
                              select new Item
            {
                Key          = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Key").Value,
                LastModified = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}LastModified").Value,
                ETag         = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}ETag").Value,
                Size         = ulong.Parse(c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Size").Value, CultureInfo.CurrentCulture),
                IsDir        = false
            };
            var prefixes = from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}CommonPrefixes")
                           select new Item
            {
                Key   = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Prefix").Value,
                IsDir = true
            };

            items             = items.Concat(prefixes);
            this.ObjectsTuple = Tuple.Create(this.BucketResult, items.ToList());
        }
Exemplo n.º 2
0
        public void Test()
        {
            string xml = @"<ListBucketResult xmlns=""http://s3.amazonaws.com/doc/2006-03-01/"">
                <Name>cmcdn</Name>
                <Prefix>1</Prefix>
                <Marker></Marker>
                <MaxKeys>100</MaxKeys>
                <IsTruncated>true</IsTruncated>
                <Contents>
                    <Key>100000/800x600.jpeg</Key>
                    <LastModified>2009-06-20T09:54:05.000Z</LastModified>
                    <ETag>&quot;c55fad5b272947050bed993ec22c6d0d&quot;</ETag>
                    <Size>116879</Size>
                    <Owner>
                        <ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID>
                        <DisplayName>jason17095</DisplayName>
                    </Owner>
                    <StorageClass>STANDARD</StorageClass>
                </Contents>
                <Contents><Key>100001/800x600.jpeg</Key><LastModified>2009-06-20T09:54:01.000Z</LastModified><ETag>&quot;4ef58e19a01ea04d4f9da27c6f6638d7&quot;</ETag><Size>116882</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100002/800x600.jpeg</Key><LastModified>2009-06-20T09:54:03.000Z</LastModified><ETag>&quot;684a80aa91730cb5405f7e80ce5964c4&quot;</ETag><Size>135978</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100003/800x600.jpeg</Key><LastModified>2009-06-20T09:54:03.000Z</LastModified><ETag>&quot;02e0d9459b336939d502dfc48735ec27&quot;</ETag><Size>118443</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100004/800x600.jpeg</Key><LastModified>2009-06-20T09:54:05.000Z</LastModified><ETag>&quot;1a770a89862a9c562e0d50cfaabeb3cf&quot;</ETag><Size>78121</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100005/751x454.jpeg</Key><LastModified>2009-01-31T01:56:16.000Z</LastModified><ETag>&quot;2de8dd5eb865d07f0290661c0810fef8&quot;</ETag><Size>66425</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100005/76x45.jpeg</Key><LastModified>2009-01-31T01:56:15.000Z</LastModified><ETag>&quot;b332051971d6d0c886cc82386201acc8&quot;</ETag><Size>2767</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100005/85x66-c.jpeg</Key><LastModified>2009-02-06T19:22:13.000Z</LastModified><ETag>&quot;aca7d00231df12c237e167e757030420&quot;</ETag><Size>3827</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>10001/240x140-c.jpeg</Key><LastModified>2009-06-07T21:12:43.000Z</LastModified><ETag>&quot;95971a91f300c7dfcfc2aa10eea6e0fb&quot;</ETag><Size>15264</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>10001/800x500.jpeg</Key><LastModified>2010-01-06T07:06:36.000Z</LastModified><ETag>&quot;705bf0b85d18f5103aef04d38c55aec4&quot;</ETag><Size>127995</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100010/240x140-c.jpeg</Key><LastModified>2009-01-27T10:05:46.000Z</LastModified><ETag>&quot;24cfccef22ba3f522d80da0e5ff316c7&quot;</ETag><Size>9223</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100010/76x50.jpeg</Key><LastModified>2009-02-28T00:54:22.000Z</LastModified><ETag>&quot;dde230c9a84cc675daf8f7ffd7c275b6&quot;</ETag><Size>2276</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100010/800x533.jpeg</Key><LastModified>2009-02-28T00:54:21.000Z</LastModified><ETag>&quot;328cba3f2b86aba12a9bc82c373f77f5&quot;</ETag><Size>87509</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100011/76x50.jpeg</Key><LastModified>2009-02-28T00:54:22.000Z</LastModified><ETag>&quot;eaeb79622b7e119d9e68c8d625b13039&quot;</ETag><Size>2510</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100011/800x533.jpeg</Key><LastModified>2009-02-28T00:54:25.000Z</LastModified><ETag>&quot;f0916e5b73842b971858ac9caae99e13&quot;</ETag><Size>95977</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100012/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;a4e3b4e047ffcc7620ef0c42ab8653b8&quot;</ETag><Size>2553</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100012/800x533.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;1e1bc2f521703d77c755b1243edc6b34&quot;</ETag><Size>91198</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100013/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;2f8e25a2d84c53bcbaae41e3a7dfb5f9&quot;</ETag><Size>2492</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100013/800x533.jpeg</Key><LastModified>2009-02-28T00:54:25.000Z</LastModified><ETag>&quot;051c429013472a26e2fd53d4652e4729&quot;</ETag><Size>83263</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100014/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;d28169de8e5ab2fee04953441237082c&quot;</ETag><Size>2461</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100014/800x533.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;dc50d4962026a406df27f00b5a2380ac&quot;</ETag><Size>75645</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100015/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;3b1d83db75f9a9e922d46238889e689f&quot;</ETag><Size>2427</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100015/800x533.jpeg</Key><LastModified>2009-02-28T00:54:24.000Z</LastModified><ETag>&quot;673395aa2384ab6aaf73c06640cb529d&quot;</ETag><Size>74532</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100017/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;e1712adc4d2c65be6630a4469929c186&quot;</ETag><Size>2490</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100017/800x533.jpeg</Key><LastModified>2009-02-28T00:54:24.000Z</LastModified><ETag>&quot;16ea459e7ec536df7a8d9f99f97807f1&quot;</ETag><Size>85499</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100018/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;7d07a81ad9f228c529936f37c4a5516e&quot;</ETag><Size>2459</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100018/800x533.jpeg</Key><LastModified>2009-02-28T00:54:25.000Z</LastModified><ETag>&quot;a6736b9c704c969849317b5017a58f26&quot;</ETag><Size>80252</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100019/76x50.jpeg</Key><LastModified>2009-02-28T00:54:23.000Z</LastModified><ETag>&quot;ac878f96e63148727205f380eeafa295&quot;</ETag><Size>2561</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100019/800x533.jpeg</Key><LastModified>2009-02-28T00:54:27.000Z</LastModified><ETag>&quot;b827d4034ad09e7a7937777e375fb623&quot;</ETag><Size>76946</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100020/76x50.jpeg</Key><LastModified>2009-02-28T00:54:39.000Z</LastModified><ETag>&quot;a79bff93ce728f3b69dd688641a2c146&quot;</ETag><Size>2353</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100020/800x533.jpeg</Key><LastModified>2009-02-28T00:54:27.000Z</LastModified><ETag>&quot;a99b3c3677de66374f5ced105b302785&quot;</ETag><Size>73828</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100021/76x50.jpeg</Key><LastModified>2009-02-28T00:54:40.000Z</LastModified><ETag>&quot;343e1f3754bc843eda87994fabc7dcda&quot;</ETag><Size>2498</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100021/800x533.jpeg</Key><LastModified>2009-02-28T00:54:28.000Z</LastModified><ETag>&quot;e7880067cf3dcc866e89290d438d0a36&quot;</ETag><Size>73382</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100022/76x50.jpeg</Key><LastModified>2009-02-28T00:54:40.000Z</LastModified><ETag>&quot;de99cc0099552e733beb5b52bc57fb45&quot;</ETag><Size>2238</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100022/800x533.jpeg</Key><LastModified>2009-02-28T00:54:29.000Z</LastModified><ETag>&quot;445e02490c560a46ce5f6b5302597027&quot;</ETag><Size>63673</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100023/76x50.jpeg</Key><LastModified>2009-02-28T00:54:40.000Z</LastModified><ETag>&quot;56bcfb29ef325109e2307e0ab2680dba&quot;</ETag><Size>3035</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100023/800x533.jpeg</Key><LastModified>2009-02-28T00:54:29.000Z</LastModified><ETag>&quot;f1a566c9279edda735ddf348ba7eefed&quot;</ETag><Size>98221</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100024/76x50.jpeg</Key><LastModified>2009-02-28T00:54:41.000Z</LastModified><ETag>&quot;91065780c3427da413691d0ef824f282&quot;</ETag><Size>2644</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100024/800x533.jpeg</Key><LastModified>2009-02-28T00:54:30.000Z</LastModified><ETag>&quot;625ddecda88a8d58106e855e95a8b8ed&quot;</ETag><Size>93177</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100025/76x50.jpeg</Key><LastModified>2009-02-28T00:54:41.000Z</LastModified><ETag>&quot;6706a4632023afffe54d38e5166de7d5&quot;</ETag><Size>2259</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100025/800x533.jpeg</Key><LastModified>2009-02-28T00:54:31.000Z</LastModified><ETag>&quot;72b366054ccaf53951667002054ec3e3&quot;</ETag><Size>72609</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100026/76x50.jpeg</Key><LastModified>2009-02-28T00:54:41.000Z</LastModified><ETag>&quot;d8357e4a81050e9df810ca88fc6c552f&quot;</ETag><Size>2334</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100026/800x533.jpeg</Key><LastModified>2009-02-28T00:54:31.000Z</LastModified><ETag>&quot;1abc6d54a4b6aa50eb593678d055acf8&quot;</ETag><Size>79443</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100027/76x50.jpeg</Key><LastModified>2009-02-28T00:54:41.000Z</LastModified><ETag>&quot;06aa89fdf4862f3185b1ad9586e19c1b&quot;</ETag><Size>2312</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100027/800x533.jpeg</Key><LastModified>2009-02-28T00:54:31.000Z</LastModified><ETag>&quot;f31e927a00e45239e9dc2dfe4ddd5041&quot;</ETag><Size>78452</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100028/76x50.jpeg</Key><LastModified>2009-02-28T00:54:41.000Z</LastModified><ETag>&quot;f606cc5da137f0f7bd07d9c64e75daba&quot;</ETag><Size>2309</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100028/800x533.jpeg</Key><LastModified>2009-02-28T00:54:32.000Z</LastModified><ETag>&quot;f4eac353a67c82dd63a5f0a011e3357d&quot;</ETag><Size>85090</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100029/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;35b8b239daf9f23647d5b92dd8df308a&quot;</ETag><Size>2412</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100029/800x533.jpeg</Key><LastModified>2009-02-28T00:54:34.000Z</LastModified><ETag>&quot;cc7e61fe17aca5e4dd3ba50328561e1c&quot;</ETag><Size>82376</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100030/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;4e209441b31e574f843a5ed33bfc38f7&quot;</ETag><Size>2578</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100030/800x533.jpeg</Key><LastModified>2009-02-28T00:54:34.000Z</LastModified><ETag>&quot;5b8248bb4e384ba4bee327c5b123c3fc&quot;</ETag><Size>85491</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100031/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;dc394bed0ccfe643d68c5b3f978a8f67&quot;</ETag><Size>2480</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100031/800x533.jpeg</Key><LastModified>2009-02-28T00:54:34.000Z</LastModified><ETag>&quot;ad37a9d4aeb36191a2ef6bb5e2094819&quot;</ETag><Size>77359</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100032/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;a7a182a0c7f03c0cd13cf6231e8a856d&quot;</ETag><Size>2289</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100032/800x533.jpeg</Key><LastModified>2009-02-28T00:54:35.000Z</LastModified><ETag>&quot;0bf6957496054cc3fb6cf61bc2cfaef3&quot;</ETag><Size>89525</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100033/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;a1fa1002203c41605b7c5eff2f6eacd0&quot;</ETag><Size>2449</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100033/800x533.jpeg</Key><LastModified>2009-02-28T00:54:35.000Z</LastModified><ETag>&quot;49991bf643254bda6ab226c863135917&quot;</ETag><Size>91792</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100034/76x50.jpeg</Key><LastModified>2009-02-28T00:56:03.000Z</LastModified><ETag>&quot;0985c6ce1916fc01c62c7e9921ed63f7&quot;</ETag><Size>1956</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100034/800x533.jpeg</Key><LastModified>2009-02-28T00:54:36.000Z</LastModified><ETag>&quot;3680993ea2873f698d83c3bbb390e536&quot;</ETag><Size>70690</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100035/76x50.jpeg</Key><LastModified>2009-02-28T00:56:04.000Z</LastModified><ETag>&quot;80d4326b5d6bfd356f5c413f54ad00f2&quot;</ETag><Size>1808</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100035/800x533.jpeg</Key><LastModified>2009-02-28T00:54:37.000Z</LastModified><ETag>&quot;9afc1f01f77010426e71c194b1db43a9&quot;</ETag><Size>68424</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100036/76x50.jpeg</Key><LastModified>2009-02-28T00:56:04.000Z</LastModified><ETag>&quot;d3d82e531099eba9e925953a60d1db6c&quot;</ETag><Size>1859</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100036/800x533.jpeg</Key><LastModified>2009-02-28T00:54:37.000Z</LastModified><ETag>&quot;a6d49d5ed78bcc08809cc30d018fc02a&quot;</ETag><Size>73678</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100037/76x50.jpeg</Key><LastModified>2009-02-28T00:56:04.000Z</LastModified><ETag>&quot;0bf20e267d951bad2033f3aaa2819ac8&quot;</ETag><Size>2002</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100037/800x533.jpeg</Key><LastModified>2009-02-28T00:54:39.000Z</LastModified><ETag>&quot;46d9be8508d5cc20c03dfefd6ded2e3f&quot;</ETag><Size>78422</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100038/76x48.jpeg</Key><LastModified>2009-02-03T04:01:24.000Z</LastModified><ETag>&quot;360258290abeb6f428107c03f3d7b4a9&quot;</ETag><Size>2160</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100038/800x506.jpeg</Key><LastModified>2009-02-03T04:01:25.000Z</LastModified><ETag>&quot;216a8cecf70c313fb163f4a1a93687db&quot;</ETag><Size>131847</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100039/700x522.jpeg</Key><LastModified>2009-02-03T04:01:25.000Z</LastModified><ETag>&quot;f1aca43d86d82b9c32ffaf92af5352e8&quot;</ETag><Size>128155</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100039/76x56.jpeg</Key><LastModified>2009-02-03T04:01:25.000Z</LastModified><ETag>&quot;b7d1b23ff29629accf8e564bf992f8d5&quot;</ETag><Size>2608</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>10004/800x600.jpeg</Key><LastModified>2010-03-27T02:55:25.000Z</LastModified><ETag>&quot;c427c400e9b3d8a4c011fd14578dde77&quot;</ETag><Size>218644</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100041/240x140-c.jpeg</Key><LastModified>2009-05-12T19:59:34.000Z</LastModified><ETag>&quot;4d092726dbfd38666bb6c6567348a121&quot;</ETag><Size>13763</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100047/375x140-c.jpeg</Key><LastModified>2009-04-08T19:12:13.000Z</LastModified><ETag>&quot;d860a6fa0369a8dad5cc063a360c2e93&quot;</ETag><Size>19824</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100053/375x140-c.jpeg</Key><LastModified>2009-04-08T19:12:13.000Z</LastModified><ETag>&quot;724164795e7ea772610e1b419e2dcb25&quot;</ETag><Size>19328</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100063/440x660.jpeg</Key><LastModified>2009-02-13T01:05:54.000Z</LastModified><ETag>&quot;be25d1f5bc9b810c168db633ce1cb975&quot;</ETag><Size>63712</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100064/515x660.jpeg</Key><LastModified>2009-02-13T01:05:56.000Z</LastModified><ETag>&quot;e49e6f07ea1ad3e50eb4544b6ec84d4c&quot;</ETag><Size>87658</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100065/523x660.jpeg</Key><LastModified>2009-02-13T01:05:56.000Z</LastModified><ETag>&quot;44dda2676acd554840c4ed41ed904d7e&quot;</ETag><Size>68546</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100066/800x576.jpeg</Key><LastModified>2009-02-13T01:05:56.000Z</LastModified><ETag>&quot;ec7643230b8d23b8a855673b2c3a9bec&quot;</ETag><Size>131592</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100067/515x660.jpeg</Key><LastModified>2009-02-13T01:05:56.000Z</LastModified><ETag>&quot;c608a2c0accdeb252d81c0a797a262dd&quot;</ETag><Size>97100</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100068/510x660.jpeg</Key><LastModified>2009-02-15T05:21:45.000Z</LastModified><ETag>&quot;4dd606f970296b293e72127fd0b6cf07&quot;</ETag><Size>85451</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100070/240x140-c.jpeg</Key><LastModified>2009-02-13T01:05:31.000Z</LastModified><ETag>&quot;a2cb5cdd46669c1d65642a26135237b1&quot;</ETag><Size>16039</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100070/720x466.jpeg</Key><LastModified>2009-02-13T01:05:54.000Z</LastModified><ETag>&quot;bf64556c652e7f1c8995872b8f8335fa&quot;</ETag><Size>104092</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100071/510x660.jpeg</Key><LastModified>2009-02-13T01:05:57.000Z</LastModified><ETag>&quot;71de6e4d96878cac54f49b17fb14a25e&quot;</ETag><Size>54454</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100072/192x100-c.jpeg</Key><LastModified>2010-04-01T14:06:41.000Z</LastModified><ETag>&quot;a0a8f22520697d9457b9ba6c2c4cb70c&quot;</ETag><Size>2956</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100072/240x140-c.jpeg</Key><LastModified>2010-04-01T14:06:14.000Z</LastModified><ETag>&quot;f490b9f88fb7161275dca323b6573c17&quot;</ETag><Size>4524</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100072/315x420.jpeg</Key><LastModified>2010-04-01T14:06:42.000Z</LastModified><ETag>&quot;48c4ba4cd0ce6e624b5a2259b88ce9b7&quot;</ETag><Size>15878</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100072/495x660.jpeg</Key><LastModified>2010-04-01T14:07:06.000Z</LastModified><ETag>&quot;12708e9813a7e3839ab95ee1ada8fcd2&quot;</ETag><Size>41436</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100072/85x66-c.jpeg</Key><LastModified>2010-04-01T14:06:41.000Z</LastModified><ETag>&quot;2cd741115a349d673844a79ac27253c2&quot;</ETag><Size>1674</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100074/800x600.jpeg</Key><LastModified>2010-04-01T14:07:05.000Z</LastModified><ETag>&quot;a5e8989d45cbaab0f2b67f8a5a8265f4&quot;</ETag><Size>78982</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100074/85x66-c.jpeg</Key><LastModified>2010-04-01T14:06:41.000Z</LastModified><ETag>&quot;16f7985e4474260a853036e802b35889&quot;</ETag><Size>3190</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100075/800x600.jpeg</Key><LastModified>2010-04-01T14:07:05.000Z</LastModified><ETag>&quot;d0d61505b21e990d18e7d5ca4072139b&quot;</ETag><Size>75121</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100075/85x66-c.jpeg</Key><LastModified>2010-04-01T14:06:41.000Z</LastModified><ETag>&quot;4b6f66f6454af74921c318450a602358&quot;</ETag><Size>3239</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100076/800x600.jpeg</Key><LastModified>2010-04-01T14:07:05.000Z</LastModified><ETag>&quot;eff3fbc8ec1e1813e8d19a9c921335a2&quot;</ETag><Size>67024</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100076/85x66-c.jpeg</Key><LastModified>2010-04-01T14:06:42.000Z</LastModified><ETag>&quot;a4e4a80cdf71f166606332f9b29de343&quot;</ETag><Size>3000</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100077/240x140-c.jpeg</Key><LastModified>2009-06-12T19:03:33.000Z</LastModified><ETag>&quot;376c3f87fef7f2f208629f42abc841de&quot;</ETag><Size>11721</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100080/240x140-c.jpeg</Key><LastModified>2009-06-12T19:03:33.000Z</LastModified><ETag>&quot;a4601bbf4e0ba471db75b6daffd7ed81&quot;</ETag><Size>15132</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100093/240x140-c.jpeg</Key><LastModified>2009-06-12T20:56:33.000Z</LastModified><ETag>&quot;76b4fd520855e9290401b191f0de3889&quot;</ETag><Size>16637</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100094/260x37.jpeg</Key><LastModified>2009-02-08T01:10:51.000Z</LastModified><ETag>&quot;56fc637744037fd48e2858a932d5fea7&quot;</ETag><Size>5406</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100094/760x110-c.jpeg</Key><LastModified>2009-01-26T10:48:37.000Z</LastModified><ETag>&quot;695432ff1b5e525587e401bd63ce015a&quot;</ETag><Size>22911</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100110/97x102.jpeg</Key><LastModified>2010-03-17T14:09:27.000Z</LastModified><ETag>&quot;27d3ea0bc36ac0d2f8592490c6214902&quot;</ETag><Size>4452</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents><Contents><Key>100111/97x102.jpeg</Key><LastModified>2009-12-21T05:52:18.000Z</LastModified><ETag>&quot;9cdae36adc5ef808dc68f4e9df4a47bc&quot;</ETag><Size>4167</Size><Owner><ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID><DisplayName>jason17095</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListBucketResult>";

            var result = ListBucketResult.ParseXml(xml);

            Assert.Equal("cmcdn", result.Name);
            Assert.Equal("1", result.Prefix);
            Assert.Equal("", result.Marker);
            Assert.Equal(100, result.MaxKeys);

            Assert.Equal(100, result.Items.Length);
            Assert.Equal("100000/800x600.jpeg", result.Items[0].Key);

            // Assert.Equal("STANDARD", result.Items[0].StorageClass);
            Assert.Equal(DateTime.Parse("2009-06-20T09:54:05.000Z", null, DateTimeStyles.AdjustToUniversal), result.Items[0].LastModified);
        }
Exemplo n.º 3
0
        private Tuple <ListBucketResult, List <Item> > GetObjectList(string bucket, string prefix, bool recursive, string marker)
        {
            var queries = new List <string>();

            if (!recursive)
            {
                queries.Add("delimiter=%2F");
            }
            if (prefix != null)
            {
                queries.Add("prefix=" + Uri.EscapeDataString(prefix));
            }
            if (marker != null)
            {
                queries.Add("marker=" + Uri.EscapeDataString(marker));
            }
            queries.Add("max-keys=1000");
            string query = string.Join("&", queries);

            string path = bucket;

            if (query.Length > 0)
            {
                path += "?" + query;
            }
            var request  = new RestRequest(path, Method.GET);
            var response = client.Execute(request);

            if (response.StatusCode == HttpStatusCode.OK)
            {
                var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content);
                var stream       = new MemoryStream(contentBytes);
                ListBucketResult listBucketResult = (ListBucketResult)(new XmlSerializer(typeof(ListBucketResult)).Deserialize(stream));

                XDocument root = XDocument.Parse(response.Content);

                var items = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Contents")
                             select new Item()
                {
                    Key = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Key").Value,
                    LastModified = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}LastModified").Value,
                    ETag = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}ETag").Value,
                    Size = UInt64.Parse(c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Size").Value),
                    IsDir = false
                });

                var prefixes = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}CommonPrefixes")
                                select new Item()
                {
                    Key = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Prefix").Value,
                    IsDir = true
                });

                items = items.Concat(prefixes);

                return(new Tuple <ListBucketResult, List <Item> >(listBucketResult, items.ToList()));
            }
            throw ParseError(response);
        }
Exemplo n.º 4
0
        /// <summary>
        /// Gets the list of objects in the bucket filtered by prefix
        /// </summary>
        /// <param name="bucketName">Bucket to list objects from</param>
        /// <param name="prefix">Filters all objects not beginning with a given prefix</param>
        /// <param name="recursive">Set to false to emulate a directory</param>
        /// <param name="marker">marks location in the iterator sequence</param>
        /// <returns>Task with a tuple populated with objects</returns>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>

        private async Task <Tuple <ListBucketResult, List <Item> > > GetObjectListAsync(string bucketName, string prefix, bool recursive, string marker, CancellationToken cancellationToken = default(CancellationToken))
        {
            var queries = new List <string>();

            if (!recursive)
            {
                queries.Add("delimiter=%2F");
            }
            if (prefix != null)
            {
                queries.Add("prefix=" + Uri.EscapeDataString(prefix));
            }
            if (marker != null)
            {
                queries.Add("marker=" + Uri.EscapeDataString(marker));
            }
            queries.Add("max-keys=1000");
            string query = string.Join("&", queries);

            var request = await this.CreateRequest(Method.GET,
                                                   bucketName,
                                                   resourcePath : "?" + query)
                          .ConfigureAwait(false);

            var response = await this.ExecuteTaskAsync(this.NoErrorHandlers, request, cancellationToken).ConfigureAwait(false);

            var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content);
            ListBucketResult listBucketResult = null;

            using (var stream = new MemoryStream(contentBytes))
            {
                listBucketResult = (ListBucketResult)(new XmlSerializer(typeof(ListBucketResult)).Deserialize(stream));
            }

            XDocument root = XDocument.Parse(response.Content);

            var items = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Contents")
                         select new Item()
            {
                Key = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Key").Value,
                LastModified = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}LastModified").Value,
                ETag = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}ETag").Value,
                Size = UInt64.Parse(c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Size").Value, CultureInfo.CurrentCulture),
                IsDir = false
            });

            var prefixes = (from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}CommonPrefixes")
                            select new Item()
            {
                Key = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Prefix").Value,
                IsDir = true
            });

            items = items.Concat(prefixes);

            return(new Tuple <ListBucketResult, List <Item> >(listBucketResult, items.ToList()));
        }
Exemplo n.º 5
0
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
        static async Task <ListBucketResult> BucketRead(S3Context ctx)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
        {
            Console.WriteLine("BucketRead: " + ctx.Request.Bucket);

            List <ObjectMetadata> contents = new List <ObjectMetadata>()
            {
                _ObjectMetadata
            };

            ListBucketResult result = new ListBucketResult("default", contents, 1, 1);

            return(result);
        }
Exemplo n.º 6
0
        public void Test2()
        {
            var text = @"<?xml version=""1.0"" encoding=""UTF-8""?>
<ListBucketResult xmlns=""http://s3.amazonaws.com/doc/2006-03-01/"">
	<Name>cmcdn</Name>
	<Prefix>1</Prefix>
	<Marker></Marker>
	<MaxKeys>100</MaxKeys>
	<IsTruncated>true</IsTruncated>
    <NextContinuationToken>1ueGcxLPRx1Tr/XYExHnhbYLgveDs2J/wm36Hy4vbOwM=</NextContinuationToken>
	<Contents>
		<Key>100000/800x600.jpeg</Key>
		<LastModified>2009-06-20T09:54:05.000Z</LastModified>
		<ETag>&quot;c55fad5b272947050bed993ec22c6d0d&quot;</ETag>
		<Size>116879</Size>
		<Owner>
			<ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID>
			<DisplayName>jason17095</DisplayName>
		</Owner>
		<StorageClass>STANDARD</StorageClass>
	</Contents>
	<Contents>
		<Key>100001/800x600.jpeg</Key>
		<LastModified>2009-06-20T09:54:01.000Z</LastModified>
		<ETag>&quot;4ef58e19a01ea04d4f9da27c6f6638d7&quot;</ETag>
		<Size>116882</Size>
		<Owner>
			<ID>9c18bda0312b59b259789b4acf29a06efdb6193a4ef51fcafa739f5cda4f3bf0</ID>
			<DisplayName>jason17095</DisplayName>
		</Owner>
		<StorageClass>STANDARD</StorageClass>
	</Contents>
</ListBucketResult>";

            var result = ListBucketResult.ParseXml(text);

            Assert.Equal("cmcdn", result.Name);
            Assert.Equal("1", result.Prefix);

            Assert.Equal(116879, result.Items[0].Size);
            Assert.Equal(116882, result.Items[1].Size);
            Assert.Equal(true, result.IsTruncated);

            Assert.Equal("STANDARD", result.Items[1].StorageClass);

            Assert.Equal("100000/800x600.jpeg", result.Items[0].Key);
            Assert.Equal("100001/800x600.jpeg", result.Items[1].Key);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Gets the list of objects in the bucket filtered by prefix
        /// </summary>
        /// <param name="bucketName">Bucket to list objects from</param>
        /// <param name="prefix">Filters all objects starting with a given prefix</param>
        /// <param name="delimiter">Delimit the output upto this character</param>
        /// <param name="marker">marks location in the iterator sequence</param>
        /// <returns>Task with a tuple populated with objects</returns>
        /// <param name="cancellationToken">Optional cancellation token to cancel the operation</param>
        private async Task <Tuple <ListBucketResult, List <Item> > > GetObjectListAsync(string bucketName, string prefix, string delimiter, string marker, CancellationToken cancellationToken = default(CancellationToken))
        {
            var queryMap = new Dictionary <string, string>();

            // null values are treated as empty strings.
            if (delimiter == null)
            {
                delimiter = string.Empty;
            }

            if (prefix == null)
            {
                prefix = string.Empty;
            }

            if (marker == null)
            {
                marker = string.Empty;
            }

            var request = await this.CreateRequest(Method.GET,
                                                   bucketName)
                          .ConfigureAwait(false);

            request.AddQueryParameter("delimiter", Uri.EscapeDataString(delimiter));
            request.AddQueryParameter("prefix", Uri.EscapeDataString(prefix));
            request.AddQueryParameter("max-keys", "1000");
            request.AddQueryParameter("marker", Uri.EscapeDataString(marker));
            request.AddQueryParameter("encoding-type", "url");

            var response = await this.ExecuteTaskAsync(this.NoErrorHandlers, request, cancellationToken).ConfigureAwait(false);

            var contentBytes = System.Text.Encoding.UTF8.GetBytes(response.Content);
            ListBucketResult listBucketResult = null;

            using (var stream = new MemoryStream(contentBytes))
            {
                listBucketResult = (ListBucketResult) new XmlSerializer(typeof(ListBucketResult)).Deserialize(stream);
            }

            XDocument root = XDocument.Parse(response.Content);

            var items = from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}Contents")
                        select new Item
            {
                Key          = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Key").Value,
                LastModified = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}LastModified").Value,
                ETag         = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}ETag").Value,
                Size         = ulong.Parse(c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Size").Value, CultureInfo.CurrentCulture),
                IsDir        = false
            };

            var prefixes = from c in root.Root.Descendants("{http://s3.amazonaws.com/doc/2006-03-01/}CommonPrefixes")
                           select new Item
            {
                Key   = c.Element("{http://s3.amazonaws.com/doc/2006-03-01/}Prefix").Value,
                IsDir = true
            };

            items = items.Concat(prefixes);

            return(Tuple.Create(listBucketResult, items.ToList()));
        }
        public void MarshalResponse(IConfig config, ListObjectsResponse response, IDictionary <string, string> headers, Stream responseStream)
        {
            XmlSerializer s = new XmlSerializer(typeof(ListBucketResult));

            using (XmlTextReader r = new XmlTextReader(responseStream))
            {
                r.Namespaces = false;

                ListBucketResult bucketResult = (ListBucketResult)s.Deserialize(r);

                if (bucketResult.EncodingType != null)
                {
                    response.EncodingType = ValueHelper.ParseEnum <EncodingType>(bucketResult.EncodingType);
                }

                response.Delimiter             = config.AutoUrlDecodeResponses && response.EncodingType == EncodingType.Url ? WebUtility.UrlDecode(bucketResult.Delimiter) : bucketResult.Delimiter;
                response.Prefix                = config.AutoUrlDecodeResponses && response.EncodingType == EncodingType.Url ? WebUtility.UrlDecode(bucketResult.Prefix) : bucketResult.Prefix;
                response.StartAfter            = config.AutoUrlDecodeResponses && response.EncodingType == EncodingType.Url ? WebUtility.UrlDecode(bucketResult.StartAfter) : bucketResult.StartAfter;
                response.NextContinuationToken = bucketResult.NextContinuationToken;
                response.MaxKeys               = bucketResult.MaxKeys;
                response.IsTruncated           = bucketResult.IsTruncated;
                response.KeyCount              = bucketResult.KeyCount;
                response.BucketName            = bucketResult.Name;
                response.ContinuationToken     = bucketResult.ContinuationToken;
                response.RequestCharged        = headers.ContainsKey(AmzHeaders.XAmzRequestCharged);

                if (bucketResult.CommonPrefixes != null)
                {
                    response.CommonPrefixes = new List <string>(bucketResult.CommonPrefixes.Count);

                    foreach (CommonPrefix prefix in bucketResult.CommonPrefixes)
                    {
                        response.CommonPrefixes.Add(prefix.Prefix);
                    }
                }
                else
                {
                    response.CommonPrefixes = Array.Empty <string>();
                }

                if (bucketResult.Contents != null)
                {
                    response.Objects = new List <S3Object>(bucketResult.KeyCount);

                    foreach (Content content in bucketResult.Contents)
                    {
                        S3Object obj = new S3Object();
                        obj.ObjectKey = config.AutoUrlDecodeResponses && response.EncodingType == EncodingType.Url ? WebUtility.UrlDecode(content.Key) : content.Key;
                        obj.ETag      = content.ETag;

                        if (content.StorageClass != null)
                        {
                            obj.StorageClass = ValueHelper.ParseEnum <StorageClass>(content.StorageClass);
                        }

                        obj.LastModifiedOn = content.LastModified;
                        obj.Size           = content.Size;

                        if (content.Owner != null)
                        {
                            obj.Owner = new S3Identity {
                                Name = content.Owner.DisplayName, Id = content.Owner.Id
                            }
                        }
                        ;

                        response.Objects.Add(obj);
                    }
                }
                else
                {
                    response.Objects = Array.Empty <S3Object>();
                }
            }
        }
Exemplo n.º 9
0
        private async Task RequestHandler(HttpContext ctx)
        {
            if (ctx == null)
            {
                throw new ArgumentNullException(nameof(ctx));
            }
            DateTime  startTime = DateTime.Now;
            S3Context s3ctx     = null;

            try
            {
                s3ctx = new S3Context(ctx, _BaseDomains, null, (Logging.S3Requests ? Logger : null));
                s3ctx.Response.Headers.Add("x-amz-request-id", s3ctx.Request.RequestId);
                s3ctx.Response.Headers.Add("x-amz-id-2", s3ctx.Request.RequestId);
            }
            catch (Exception e)
            {
                if (Logging.Exceptions)
                {
                    Logger?.Invoke(_Header + "Exception:" + Environment.NewLine + Common.SerializeJson(e, true));
                }

                return;
            }

            bool                    success           = false;
            bool                    exists            = false;
            S3Object                s3obj             = null;
            ObjectMetadata          md                = null;
            AccessControlPolicy     acp               = null;
            LegalHold               legalHold         = null;
            Retention               retention         = null;
            Tagging                 tagging           = null;
            ListAllMyBucketsResult  buckets           = null;
            ListBucketResult        listBucketResult  = null;
            ListVersionsResult      listVersionResult = null;
            LocationConstraint      location          = null;
            BucketLoggingStatus     bucketLogging     = null;
            VersioningConfiguration versionConfig     = null;
            WebsiteConfiguration    wc                = null;
            DeleteMultiple          delMultiple       = null;
            DeleteResult            delResult         = null;

            try
            {
                if (Logging.HttpRequests)
                {
                    Logger?.Invoke(_Header + "HTTP request: " + Environment.NewLine + s3ctx.Http.ToJson(true));
                }

                if (Logging.S3Requests)
                {
                    Logger?.Invoke(_Header + "S3 request: " + Environment.NewLine + s3ctx.Request.ToJson(true));
                }

                if (PreRequestHandler != null)
                {
                    success = await PreRequestHandler(s3ctx).ConfigureAwait(false);

                    if (success)
                    {
                        await s3ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                }

                switch (s3ctx.Request.RequestType)
                {
                    #region Service

                case S3RequestType.ListBuckets:
                    if (Service.ListBuckets != null)
                    {
                        buckets = await Service.ListBuckets(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(buckets)).ConfigureAwait(false);

                        return;
                    }
                    break;

                    #endregion

                    #region Bucket

                case S3RequestType.BucketDelete:
                    if (Bucket.Delete != null)
                    {
                        await Bucket.Delete(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 204;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketDeleteTags:
                    if (Bucket.DeleteTagging != null)
                    {
                        await Bucket.DeleteTagging(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 204;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketDeleteWebsite:
                    if (Bucket.DeleteWebsite != null)
                    {
                        await Bucket.DeleteWebsite(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 204;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketExists:
                    if (Bucket.Exists != null)
                    {
                        exists = await Bucket.Exists(s3ctx).ConfigureAwait(false);

                        if (exists)
                        {
                            ctx.Response.StatusCode  = 200;
                            ctx.Response.ContentType = "text/plain";
                            await ctx.Response.Send().ConfigureAwait(false);
                        }
                        else
                        {
                            ctx.Response.StatusCode  = 404;
                            ctx.Response.ContentType = "text/plain";
                            await ctx.Response.Send().ConfigureAwait(false);
                        }
                        return;
                    }
                    break;

                case S3RequestType.BucketRead:
                    if (Bucket.Read != null)
                    {
                        listBucketResult = await Bucket.Read(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(listBucketResult)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadAcl:
                    if (Bucket.ReadAcl != null)
                    {
                        acp = await Bucket.ReadAcl(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(acp)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadLocation:
                    if (Bucket.ReadLocation != null)
                    {
                        location = await Bucket.ReadLocation(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(location)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadLogging:
                    if (Bucket.ReadLogging != null)
                    {
                        bucketLogging = await Bucket.ReadLogging(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(bucketLogging)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadTags:
                    if (Bucket.ReadTagging != null)
                    {
                        tagging = await Bucket.ReadTagging(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(tagging)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadVersioning:
                    if (Bucket.ReadVersioning != null)
                    {
                        versionConfig = await Bucket.ReadVersioning(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(versionConfig)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadVersions:
                    if (Bucket.ReadVersions != null)
                    {
                        listVersionResult = await Bucket.ReadVersions(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(listVersionResult)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketReadWebsite:
                    if (Bucket.ReadWebsite != null)
                    {
                        wc = await Bucket.ReadWebsite(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(wc)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWrite:
                    if (Bucket.Write != null)
                    {
                        await Bucket.Write(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWriteAcl:
                    if (Bucket.WriteAcl != null)
                    {
                        try
                        {
                            acp = Common.DeserializeXml <AccessControlPolicy>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Bucket.WriteAcl(s3ctx, acp).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWriteLogging:
                    if (Bucket.WriteLogging != null)
                    {
                        try
                        {
                            bucketLogging = Common.DeserializeXml <BucketLoggingStatus>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Bucket.WriteLogging(s3ctx, bucketLogging).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWriteTags:
                    if (Bucket.WriteTagging != null)
                    {
                        try
                        {
                            tagging = Common.DeserializeXml <Tagging>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Bucket.WriteTagging(s3ctx, tagging).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWriteVersioning:
                    if (Bucket.WriteVersioning != null)
                    {
                        try
                        {
                            versionConfig = Common.DeserializeXml <VersioningConfiguration>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Bucket.WriteVersioning(s3ctx, versionConfig).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.BucketWriteWebsite:
                    if (Bucket.WriteWebsite != null)
                    {
                        try
                        {
                            wc = Common.DeserializeXml <WebsiteConfiguration>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Bucket.WriteWebsite(s3ctx, wc).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                    #endregion

                    #region Object

                case S3RequestType.ObjectDelete:
                    if (Object.Delete != null)
                    {
                        await Object.Delete(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 204;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectDeleteMultiple:
                    if (Object.DeleteMultiple != null)
                    {
                        try
                        {
                            delMultiple = Common.DeserializeXml <DeleteMultiple>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        delResult = await Object.DeleteMultiple(s3ctx, delMultiple).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(delResult)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectDeleteTags:
                    if (Object.DeleteTagging != null)
                    {
                        await Object.DeleteTagging(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 204;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectExists:
                    if (Object.Exists != null)
                    {
                        md = await Object.Exists(s3ctx).ConfigureAwait(false);

                        if (md != null)
                        {
                            if (!String.IsNullOrEmpty(md.ETag))
                            {
                                ctx.Response.Headers.Add("ETag", md.ETag);
                            }
                            ctx.Response.Headers.Add("Last-Modified", md.LastModified.ToString());
                            ctx.Response.Headers.Add("x-amz-storage-class", md.StorageClass);
                            ctx.Response.StatusCode    = 200;
                            ctx.Response.ContentLength = md.Size;
                            ctx.Response.ContentType   = md.ContentType;
                            await ctx.Response.Send(md.Size).ConfigureAwait(false);
                        }
                        else
                        {
                            ctx.Response.StatusCode = 404;
                            await ctx.Response.Send().ConfigureAwait(false);
                        }
                        return;
                    }
                    break;

                case S3RequestType.ObjectRead:
                    if (Object.Read != null)
                    {
                        s3obj = await Object.Read(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode    = 200;
                        ctx.Response.ContentType   = s3obj.ContentType;
                        ctx.Response.ContentLength = s3obj.Size;
                        await ctx.Response.Send(s3obj.Size, s3obj.Data).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectReadAcl:
                    if (Object.ReadAcl != null)
                    {
                        acp = await Object.ReadAcl(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(acp)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectReadLegalHold:
                    if (Object.ReadLegalHold != null)
                    {
                        legalHold = await Object.ReadLegalHold(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(legalHold)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectReadRange:
                    if (Object.ReadRange != null)
                    {
                        s3obj = await Object.ReadRange(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode    = 200;
                        ctx.Response.ContentType   = s3obj.ContentType;
                        ctx.Response.ContentLength = s3obj.Size;
                        await ctx.Response.Send(s3obj.Size, s3obj.Data).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectReadRetention:
                    if (Object.ReadRetention != null)
                    {
                        retention = await Object.ReadRetention(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(retention)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectReadTags:
                    if (Object.ReadTagging != null)
                    {
                        tagging = await Object.ReadTagging(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "application/xml";
                        await ctx.Response.Send(Common.SerializeXml(tagging)).ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectWrite:
                    if (Object.Write != null)
                    {
                        await Object.Write(s3ctx).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectWriteAcl:
                    if (Object.WriteAcl != null)
                    {
                        try
                        {
                            acp = Common.DeserializeXml <AccessControlPolicy>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Object.WriteAcl(s3ctx, acp).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectWriteLegalHold:
                    if (Object.WriteLegalHold != null)
                    {
                        try
                        {
                            legalHold = Common.DeserializeXml <LegalHold>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Object.WriteLegalHold(s3ctx, legalHold).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectWriteRetention:
                    if (Object.WriteRetention != null)
                    {
                        try
                        {
                            retention = Common.DeserializeXml <Retention>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Object.WriteRetention(s3ctx, retention).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                case S3RequestType.ObjectWriteTags:
                    if (Object.WriteTagging != null)
                    {
                        try
                        {
                            tagging = Common.DeserializeXml <Tagging>(s3ctx.Request.DataAsString);
                        }
                        catch (InvalidOperationException ioe)
                        {
                            ioe.Data.Add("Context", s3ctx);
                            ioe.Data.Add("RequestBody", s3ctx.Request.DataAsString);
                            Logger?.Invoke(_Header + "XML exception: " + Environment.NewLine + Common.SerializeJson(ioe, true));
                            await s3ctx.Response.Send(S3Objects.ErrorCode.MalformedXML).ConfigureAwait(false);

                            return;
                        }

                        await Object.WriteTagging(s3ctx, tagging).ConfigureAwait(false);

                        ctx.Response.StatusCode  = 200;
                        ctx.Response.ContentType = "text/plain";
                        await ctx.Response.Send().ConfigureAwait(false);

                        return;
                    }
                    break;

                    #endregion
                }

                if (DefaultRequestHandler != null)
                {
                    await DefaultRequestHandler(s3ctx).ConfigureAwait(false);

                    return;
                }

                await s3ctx.Response.Send(S3Objects.ErrorCode.InvalidRequest).ConfigureAwait(false);

                return;
            }
            catch (S3Exception s3e)
            {
                if (Logging.Exceptions)
                {
                    Logger?.Invoke(_Header + "S3 exception:" + Environment.NewLine + Common.SerializeJson(s3e, true));
                }

                await s3ctx.Response.Send(s3e.Error).ConfigureAwait(false);

                return;
            }
            catch (Exception e)
            {
                if (Logging.Exceptions)
                {
                    Logger?.Invoke(_Header + "exception:" + Environment.NewLine + Common.SerializeJson(e, true));
                }

                await s3ctx.Response.Send(S3Objects.ErrorCode.InternalError).ConfigureAwait(false);

                return;
            }
            finally
            {
                if (Logging.HttpRequests)
                {
                    Logger?.Invoke(
                        _Header +
                        "[" +
                        ctx.Request.Source.IpAddress + ":" +
                        ctx.Request.Source.Port +
                        "] " +
                        ctx.Request.Method.ToString() + " " +
                        ctx.Request.Url.RawWithoutQuery + " " +
                        s3ctx.Response.StatusCode +
                        " [" + Common.TotalMsFrom(startTime) + "ms]");
                }

                if (PostRequestHandler != null)
                {
                    await PostRequestHandler(s3ctx).ConfigureAwait(false);
                }
            }
        }
Exemplo n.º 10
0
        public void MarshalResponse(GetBucketRequest request, GetBucketResponse response, IDictionary <string, string> headers, Stream responseStream)
        {
            XmlSerializer s = new XmlSerializer(typeof(ListBucketResult));

            using (XmlTextReader r = new XmlTextReader(responseStream))
            {
                r.Namespaces = false;

                ListBucketResult bucketResult = (ListBucketResult)s.Deserialize(r);
                response.MaxKeys           = bucketResult.MaxKeys;
                response.IsTruncated       = bucketResult.IsTruncated;
                response.KeyCount          = bucketResult.KeyCount;
                response.Name              = bucketResult.Name;
                response.Prefix            = bucketResult.Prefix;
                response.ContinuationToken = bucketResult.ContinuationToken;

                if (bucketResult.CommonPrefixes != null)
                {
                    response.CommonPrefixes = new List <string>(bucketResult.CommonPrefixes.Count);

                    foreach (CommonPrefix prefix in bucketResult.CommonPrefixes)
                    {
                        response.CommonPrefixes.Add(prefix.Prefix);
                    }
                }
                else
                {
                    response.CommonPrefixes = Array.Empty <string>();
                }

                if (bucketResult.EncodingType != null)
                {
                    response.EncodingType = ValueHelper.ParseEnum <EncodingType>(bucketResult.EncodingType);
                }

                response.NextContinuationToken = bucketResult.NextContinuationToken;
                response.StartAfter            = bucketResult.StartAfter;

                if (bucketResult.Contents != null)
                {
                    response.Objects = new List <S3Object>(bucketResult.KeyCount);

                    foreach (Content content in bucketResult.Contents)
                    {
                        S3Object obj = new S3Object();
                        obj.Name = content.Key;
                        obj.ETag = content.ETag;

                        if (content.StorageClass != null)
                        {
                            obj.StorageClass = ValueHelper.ParseEnum <StorageClass>(content.StorageClass);
                        }

                        obj.LastModified = content.LastModified;
                        obj.Size         = content.Size;

                        if (content.Owner != null)
                        {
                            obj.Owner = new S3ObjectIdentity {
                                Name = content.Owner.DisplayName, Id = content.Owner.Id
                            }
                        }
                        ;

                        response.Objects.Add(obj);
                    }
                }
                else
                {
                    response.Objects = Array.Empty <S3Object>();
                }
            }
        }