2 * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 * @file src/cyad/CommandlineParser/CyadCommandlineParser.cpp
18 * @author Aleksander Zdyb <a.zdyb@samsung.com>
20 * @brief Commandline parser for Cyad
29 #include <cyad/CommandlineParser/PolicyParsingException.h>
31 #include "CyadCommandlineParser.h"
35 namespace CyadCmdlineArgs {
36 const char HELP = 'h';
37 const char * const HELP_LONG = "help";
39 const char SET_BUCKET = 'b';
40 const char * const SET_BUCKET_LONG = "set-bucket";
42 const char DELETE_BUCKET = 'd';
43 const char * const DELETE_BUCKET_LONG = "delete-bucket";
45 const char POLICY = 'p';
46 const char * const POLICY_LONG = "policy";
48 const char METADATA = 'm';
49 const char * const METADATA_LONG = "metadata";
51 const char BUCKET = 'k';
52 const char * const BUCKET_LONG = "bucket";
54 const char SET_POLICY = 's';
55 const char * const SET_POLICY_LONG = "set-policy";
57 const char CLIENT = 'c';
58 const char * const CLIENT_LONG = "client";
60 const char USER = 'u';
61 const char * const USER_LONG = "user";
63 const char PRIVILEGE = 'r';
64 const char * const PRIVILEGE_LONG = "privilege";
66 const char BULK = 'f';
67 const char * const BULK_LONG = "bulk";
70 namespace CyadCmdlineErrors {
71 const char * const UNKNOWN_ERROR = "Unknown error";
72 const char * const NO_OPTION = "No option specified";
73 const char * const UNKNOWN_OPTION = "Unknown option";
74 const char * const UNKNOWN_OPTION_SET_BUCKET = "Unknown option in --set-bucket";
75 const char * const UNKNOWN_OPTION_DELETE_BUCKET = "Unknown option in --delete-bucket";
76 const char * const UNKNOWN_OPTION_SET_POLICY = "Unknown option in --set-policy";
77 const char * const NO_POLICY = "No --policy specified";
78 const char * const NO_BUCKET = "No bucket specified";
79 const char * const INVALID_POLICY = "Invalid --policy option";
80 const char * const OPTION_MISSING_SET_POLICY = "One or more option missing in --set-policy";
81 const char * const ARGUMENT_MISSING_SET_POLICY = "One or more argument missing in --set-policy";
84 CyadCommandlineParser::CyadCommandlineParser(int argc, char * const *argv)
85 : m_argc(argc), m_argv(argv) {}
87 CyadCommandlineParser::~CyadCommandlineParser() {}
89 std::shared_ptr<CyadCommand> CyadCommandlineParser::parseMain(void) {
90 namespace Args = CyadCmdlineArgs;
92 const struct option long_options[] = {
93 { Args::HELP_LONG, no_argument, nullptr, Args::HELP },
94 { Args::SET_BUCKET_LONG, required_argument, nullptr, Args::SET_BUCKET },
95 { Args::DELETE_BUCKET_LONG, required_argument, nullptr, Args::DELETE_BUCKET },
96 { Args::SET_POLICY_LONG, no_argument, nullptr, Args::SET_POLICY },
97 { nullptr, 0, nullptr, 0 }
100 optind = 0; // On entry to `getopt', zero means this is the first call; initialize.
102 std::stringstream optstr;
103 optstr << ":" << Args::HELP
104 << Args::SET_BUCKET << ":"
105 << Args::DELETE_BUCKET << ":"
108 while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
111 return std::make_shared<HelpCyadCommand>();
113 case Args::SET_BUCKET:
114 return parseSetBucket(optarg);
116 case Args::DELETE_BUCKET:
117 return parseDeleteBucket(optarg);
119 case Args::SET_POLICY:
120 return parseSetPolicy();
122 case '?': // Unknown option
123 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
125 case ':': // Missing argument
127 case Args::SET_BUCKET:
128 case Args::DELETE_BUCKET:
129 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_BUCKET);
131 // Shall never happen, but let's just make compiler happy.
132 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_ERROR);
135 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::UNKNOWN_OPTION);
139 return std::make_shared<ErrorCyadCommand>(CyadCmdlineErrors::NO_OPTION);
142 std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetBucket(const std::string &bucketId) {
143 namespace Args = CyadCmdlineArgs;
144 namespace Errors = CyadCmdlineErrors;
146 const struct option long_options[] = {
147 { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY },
148 { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA },
149 { nullptr, 0, nullptr, 0 }
153 std::string metadata;
156 std::stringstream optstr;
158 << Args::POLICY << ":"
159 << Args::METADATA << ":";
161 while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
170 return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_SET_BUCKET);
175 return std::make_shared<ErrorCyadCommand>(Errors::NO_POLICY);
178 auto policyType = parsePolicyType(policy);
179 return std::make_shared<SetBucketCyadCommand>(bucketId, PolicyResult(policyType, metadata));
180 } catch (const PolicyParsingException &) {
181 return std::make_shared<ErrorCyadCommand>(Errors::INVALID_POLICY);
185 std::shared_ptr<CyadCommand> CyadCommandlineParser::parseDeleteBucket(const std::string &bucketId) {
186 namespace Errors = CyadCmdlineErrors;
188 // Expect no additional options
189 const struct option long_options[] = {
190 { nullptr, 0, nullptr, 0 }
193 if (getopt_long(m_argc, m_argv, ":", long_options, nullptr) == -1) {
194 return std::make_shared<DeleteBucketCyadCommand>(bucketId);
196 return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_DELETE_BUCKET);
200 std::shared_ptr<CyadCommand> CyadCommandlineParser::parseSetPolicy(void) {
201 namespace Args = CyadCmdlineArgs;
202 namespace Errors = CyadCmdlineErrors;
204 const struct option long_options[] = {
205 { Args::CLIENT_LONG, required_argument, nullptr, Args::CLIENT },
206 { Args::USER_LONG, required_argument, nullptr, Args::USER },
207 { Args::PRIVILEGE_LONG, required_argument, nullptr, Args::PRIVILEGE },
208 { Args::BUCKET_LONG, required_argument, nullptr, Args::BUCKET },
209 { Args::POLICY_LONG, required_argument, nullptr, Args::POLICY },
210 { Args::METADATA_LONG, required_argument, nullptr, Args::METADATA },
211 { Args::BULK_LONG, required_argument, nullptr, Args::BULK },
212 { nullptr, 0, nullptr, 0 }
215 typedef std::map<char, std::string> OptionsValues;
216 OptionsValues values = { { Args::CLIENT, std::string() },
217 { Args::USER, std::string() },
218 { Args::PRIVILEGE, std::string() },
219 { Args::POLICY, std::string() } };
221 std::string metadata;
225 std::stringstream optstr;
227 << Args::CLIENT << ":"
229 << Args::PRIVILEGE << ":"
230 << Args::BUCKET << ":"
231 << Args::POLICY << ":"
232 << Args::METADATA << ":"
233 << Args::BULK << ":";
235 while ((opt = getopt_long(m_argc, m_argv, optstr.str().c_str(), long_options, nullptr)) != -1) {
239 case Args::PRIVILEGE:
241 values[opt] = optarg;
250 return std::make_shared<SetPolicyBulkCyadCommand>(optarg);
251 case ':': // Missing argument
252 return std::make_shared<ErrorCyadCommand>(Errors::ARGUMENT_MISSING_SET_POLICY);
254 return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_OPTION_SET_POLICY);
258 for (const auto &val : values) {
259 if (val.second.empty()) {
260 // TODO: Identify actual option
261 return std::make_shared<ErrorCyadCommand>(Errors::OPTION_MISSING_SET_POLICY);
266 auto policyType = parsePolicyType(values[Args::POLICY]);
267 auto policyResult = PolicyResult(policyType, metadata);
268 return std::make_shared<SetPolicyCyadCommand>(bucket, policyResult,
269 PolicyKey(values[Args::CLIENT],
271 values[Args::PRIVILEGE]));
272 } catch (const PolicyParsingException &) {
273 return std::make_shared<ErrorCyadCommand>(Errors::INVALID_POLICY);
276 return std::make_shared<ErrorCyadCommand>(Errors::UNKNOWN_ERROR);
279 PolicyType CyadCommandlineParser::parsePolicyType(const std::string &rawPolicy) {
280 if (rawPolicy == "DENY")
281 return CYNARA_ADMIN_DENY;
282 if (rawPolicy == "NONE")
283 return CYNARA_ADMIN_NONE;
284 if (rawPolicy == "BUCKET")
285 return CYNARA_ADMIN_BUCKET;
286 if (rawPolicy == "ALLOW")
287 return CYNARA_ADMIN_ALLOW;
289 // If base for std::stoi is set to 0, it detects base by itself from the format of the sequence
291 return std::stoi(rawPolicy, nullptr, 0);
292 } catch (const std::logic_error &) {
293 throw PolicyParsingException();
297 } /* namespace Cynara */