1 /*
2  * Copyright 2009-2017 Alibaba Cloud All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <alibabacloud/oss/model/SetBucketCorsRequest.h>
18 #include "utils/Utils.h"
19 #include "ModelError.h"
20 #include <sstream>
21 #include <set>
22 #include <alibabacloud/oss/Const.h>
23 
24 using namespace AlibabaCloud::OSS;
25 
SetBucketCorsRequest(const std::string & bucket)26 SetBucketCorsRequest::SetBucketCorsRequest(const std::string &bucket) :
27     OssBucketRequest(bucket)
28 {
29 }
30 
addCORSRule(const CORSRule & rule)31 void SetBucketCorsRequest::addCORSRule(const CORSRule &rule)
32 {
33     ruleList_.push_back(rule);
34 }
35 
setCORSRules(const CORSRuleList & rules)36 void SetBucketCorsRequest::setCORSRules(const CORSRuleList &rules)
37 {
38     ruleList_ = rules;
39 }
40 
payload() const41 std::string SetBucketCorsRequest::payload() const
42 {
43     std::stringstream ss;
44     ss << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl;
45     ss << "<CORSConfiguration>" << std::endl;
46     for (const auto &rule : ruleList_)
47     {
48         ss << "  <CORSRule>" << std::endl;
49         for (const auto &origin : rule.AllowedOrigins())
50             ss << "    <AllowedOrigin>" << origin << "</AllowedOrigin>" << std::endl;
51 
52         for (const auto &method : rule.AllowedMethods())
53             ss << "    <AllowedMethod>" << method << "</AllowedMethod>" << std::endl;
54 
55         for (const auto &header : rule.AllowedHeaders())
56             ss << "    <AllowedHeader>" << header << "</AllowedHeader>" << std::endl;
57 
58         for (const auto &header : rule.ExposeHeaders())
59             ss << "    <ExposeHeader>" << header << "</ExposeHeader>" << std::endl;
60 
61         if (rule.MaxAgeSeconds() > 0)
62             ss << "    <MaxAgeSeconds>" << std::to_string(rule.MaxAgeSeconds()) << "</MaxAgeSeconds>" << std::endl;
63         ss << "  </CORSRule>" << std::endl;
64     }
65     ss << "</CORSConfiguration>" << std::endl;
66     return ss.str();
67 }
68 
specialParameters() const69 ParameterCollection SetBucketCorsRequest::specialParameters() const
70 {
71     ParameterCollection parameters;
72     parameters["cors"] = "";
73     return parameters;
74 }
75 
CountOfAsterisk(const CORSAllowedList & items)76 static int CountOfAsterisk(const CORSAllowedList &items)
77 {
78     int count = 0;
79     for (auto const&item : items) {
80         count += item.compare("*") ? 0 : 1;
81     }
82     return count;
83 }
84 
InAllowedMethods(const CORSAllowedList & items)85 static bool InAllowedMethods(const CORSAllowedList &items)
86 {
87     static std::set<std::string> allowedMethods =
88     {
89         "GET" , "PUT" , "DELETE", "POST", "HEAD"
90     };
91 
92     //if (items.empty())
93     //    return false;
94 
95     for (auto const&item : items) {
96         if (allowedMethods.find(Trim(item.c_str())) == allowedMethods.end()) {
97             return false;
98         }
99     }
100     return true;
101 }
102 
validate() const103 int SetBucketCorsRequest::validate() const
104 {
105     int ret = OssBucketRequest::validate();
106     if (ret) return ret;
107 
108     if (ruleList_.size() > BucketCorsRuleLimit)
109         return ARG_ERROR_CORS_RULE_LIMIT;
110 
111     for (auto const &rule : ruleList_) {
112 
113         if (rule.AllowedOrigins().empty())
114             return ARG_ERROR_CORS_ALLOWEDORIGINS_EMPTY;
115 
116         if (CountOfAsterisk(rule.AllowedOrigins()) > 1)
117             return ARG_ERROR_CORS_ALLOWEDORIGINS_ASTERISK_COUNT;
118 
119         if (rule.AllowedMethods().empty())
120             return ARG_ERROR_CORS_ALLOWEDMETHODS_EMPTY;
121 
122         if (!InAllowedMethods(rule.AllowedMethods()))
123             return ARG_ERROR_CORS_ALLOWEDMETHODS_VALUE;
124 
125         if (CountOfAsterisk(rule.AllowedHeaders()) > 1)
126             return ARG_ERROR_CORS_ALLOWEDHEADERS_ASTERISK_COUNT;
127 
128         if (CountOfAsterisk(rule.ExposeHeaders()) > 0)
129             return ARG_ERROR_CORS_EXPOSEHEADERS_ASTERISK_COUNT;
130 
131         if ((rule.MaxAgeSeconds() != CORSRule::UNSET_AGE_SEC) &&
132             (rule.MaxAgeSeconds() < 0 || rule.MaxAgeSeconds() > 999999999)) {
133             return ARG_ERROR_CORS_MAXAGESECONDS_RANGE;
134         }
135     }
136 
137     return 0;
138 }
139 
140