1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "account_command.h"
16 #include <fstream>
17 #include <getopt.h>
18 #include <sys/stat.h>
19 #include "account_log_wrapper.h"
20 #include "singleton.h"
21 #include "string_ex.h"
22 
23 using namespace OHOS::AAFwk;
24 
25 namespace OHOS {
26 namespace AccountSA {
27 namespace {
28 const std::string SHORT_OPTIONS = "hn:t:i:s:l:c:ea";
29 const struct option LONG_OPTIONS[] = {
30     {"help", no_argument, nullptr, 'h'},
31     {"name", required_argument, nullptr, 'n'},
32     {"type", required_argument, nullptr, 't'},
33     {"id", required_argument, nullptr, 'i'},
34     {"shortName", optional_argument, nullptr, 's'},
35     {"disallowedlist", optional_argument, nullptr, 'l'},
36     {"constraint", required_argument, nullptr, 'c'},
37     {"enable", no_argument, nullptr, 'e'},
38     {"all", no_argument, nullptr, 'a'},
39     {nullptr, no_argument, nullptr, no_argument}
40 };
41 
42 static const std::string DEACTIVATE_COMMAND = "deactivate";
43 static const std::string DELETE_COMMAND = "delete";
44 static const std::string SWITCH_COMMAND = "switch";
45 static const std::string DUMP_COMMAND = "dump";
46 static const std::string SET_COMMAND = "set";
47 static const std::string CREATE_COMMAND = "create";
48 static constexpr int MIN_ARGUMENT_NUMBER = 2;
49 static constexpr int MAX_ARGUMENT_NUMBER = 4096;
50 }  // namespace
51 
AccountCommand(int argc,char * argv[])52 AccountCommand::AccountCommand(int argc, char *argv[])
53 {
54     ACCOUNT_LOGD("enter");
55     opterr = 0;
56     argc_ = argc;
57     argv_ = argv;
58     name_ = TOOL_NAME;
59 
60     if (argc < MIN_ARGUMENT_NUMBER || argc > MAX_ARGUMENT_NUMBER) {
61         cmd_ = "help";
62         return;
63     }
64     cmd_ = argv[1];
65     for (int i = MIN_ARGUMENT_NUMBER; i < argc; i++) {
66         argList_.push_back(argv[i]);
67     }
68     for (int i = 0; i < argc_; i++) {
69         ACCOUNT_LOGD("argv_[%{public}d]: %{public}s", i, argv_[i]);
70     }
71 }
72 
CreateCommandMap()73 void AccountCommand::CreateCommandMap()
74 {
75     commandMap_ = {
76         {"help", [this] { return this->RunAsHelpCommand(); }},
77         {"create", [this] { return this->RunAsCreateCommand(); }},
78         {"delete", [this] { return this->RunAsDeleteCommand(); }},
79         {"dump", [this] { return this->RunAsDumpCommand(); }},
80         {"set", [this] { return this->RunAsSetCommand(); }},
81         {"switch", [this] { return this->RunAsSwitchCommand(); }},
82         {"deactivate", [this] { return this->RunAsDeactivateCommand(); }},
83     };
84 }
85 
GetCommandErrorMsg() const86 std::string AccountCommand::GetCommandErrorMsg() const
87 {
88     std::string commandErrorMsg =
89         name_ + ": '" + cmd_ + "' is not a valid " + name_ + " command. See '" + name_ + " help'.\n";
90 
91     return commandErrorMsg;
92 }
93 
GetUnknownOptionMsg(std::string & unknownOption) const94 std::string AccountCommand::GetUnknownOptionMsg(std::string& unknownOption) const
95 {
96     std::string result = "";
97 
98     if (optind < 0 || optind > argc_) {
99         return result;
100     }
101 
102     result.append("fail: unknown option");
103     result.append(".\n");
104 
105     return result;
106 }
107 
OnCommand()108 void AccountCommand::OnCommand()
109 {
110     auto respond = commandMap_[cmd_];
111     if (respond == nullptr) {
112         resultReceiver_.append(GetCommandErrorMsg());
113         respond = commandMap_["help"];
114     }
115 
116     respond();
117 }
118 
ExecCommand()119 std::string AccountCommand::ExecCommand()
120 {
121     CreateCommandMap();
122     OnCommand();
123     return resultReceiver_;
124 }
125 
RunAsHelpCommand(void)126 ErrCode AccountCommand::RunAsHelpCommand(void)
127 {
128     ACCOUNT_LOGD("enter");
129     resultReceiver_.append(HELP_MSG);
130     return ERR_OK;
131 }
132 
ParseCreateCommandOpt(std::string & name,std::string & shortName,OsAccountType & osAccountType,std::vector<std::string> & disallowedList)133 ErrCode AccountCommand::ParseCreateCommandOpt(std::string &name,
134     std::string &shortName, OsAccountType &osAccountType, std::vector<std::string> &disallowedList)
135 {
136     int counter = 0;
137     ErrCode result = ERR_OK;
138     while (true) {
139         counter++;
140 
141         int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
142         ACCOUNT_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
143 
144         if (option == -1) {
145             if (counter == 1) {
146                 result = RunCommandError(CREATE_COMMAND);
147             }
148             break;
149         }
150 
151         if (option == '?') {
152             result = RunAsCreateCommandMissingOptionArgument();
153             break;
154         }
155 
156         result = RunAsCreateCommandExistentOptionArgument(option, name, shortName, osAccountType, disallowedList);
157     }
158     return result;
159 }
160 
RunAsCreateCommand(void)161 ErrCode AccountCommand::RunAsCreateCommand(void)
162 {
163     ACCOUNT_LOGD("enter");
164     ErrCode result = ERR_OK;
165     std::string name = "";
166     std::string shortName = "";
167     OsAccountType osAccountType = END;
168     CreateOsAccountOptions options;
169     result = ParseCreateCommandOpt(name, shortName, osAccountType, options.disallowedHapList);
170     if (result == ERR_OK) {
171         if (name.size() == 0 || osAccountType == END) {
172             ACCOUNT_LOGD("'acm create' without enough options");
173 
174             if (name.size() == 0) {
175                 resultReceiver_.append(HELP_MSG_NO_NAME_OPTION + "\n");
176             }
177 
178             if (osAccountType == END) {
179                 resultReceiver_.append(HELP_MSG_NO_TYPE_OPTION + "\n");
180             }
181 
182             result = ERR_INVALID_VALUE;
183         }
184     }
185 
186     if (result != ERR_OK && result != ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED) {
187         resultReceiver_.append(HELP_MSG_CREATE);
188     } else {
189         /* create */
190 
191         // make os account info
192         OsAccountInfo osAccountInfo;
193         if (shortName.empty()) {
194             shortName = name;
195         }
196         // create an os account
197         result = OsAccount::GetInstance().CreateOsAccount(name, shortName, osAccountType, osAccountInfo, options);
198         switch (result) {
199             case ERR_OK:
200                 resultReceiver_ = STRING_CREATE_OS_ACCOUNT_OK + "\n";
201                 break;
202             case ERR_OSACCOUNT_SERVICE_MANAGER_NOT_ENABLE_MULTI_ERROR:
203                 resultReceiver_ = "create failed, reason: multiple-os-account feature not enabled\n";
204                 break;
205             default:
206                 resultReceiver_ = STRING_CREATE_OS_ACCOUNT_NG + "\n";
207         }
208     }
209 
210     ACCOUNT_LOGD("result = %{public}d, name = %{public}s, type = %{public}d", result, name.c_str(), osAccountType);
211     return result;
212 }
213 
RunAsDeleteCommand(void)214 ErrCode AccountCommand::RunAsDeleteCommand(void)
215 {
216     ErrCode result = ERR_OK;
217     int id = -1;
218 
219     ParseCommandOpt(DELETE_COMMAND, result, id);
220 
221     if (result != ERR_OK) {
222         resultReceiver_.append(HELP_MSG_DELETE);
223     } else {
224         /* delete */
225 
226         // delete an os account
227         result = OsAccount::GetInstance().RemoveOsAccount(id);
228         if (result == ERR_OK) {
229             resultReceiver_ = STRING_DELETE_OS_ACCOUNT_OK + "\n";
230         } else {
231             resultReceiver_ = STRING_DELETE_OS_ACCOUNT_NG + "\n";
232         }
233     }
234 
235     ACCOUNT_LOGD("result = %{public}d, id = %{public}d", result, id);
236     return result;
237 }
238 
RunAsDumpCommand(void)239 ErrCode AccountCommand::RunAsDumpCommand(void)
240 {
241     ErrCode result = ERR_OK;
242     int id = -1;
243 
244     ParseCommandOpt(DUMP_COMMAND, result, id);
245 
246     if (result != ERR_OK) {
247         resultReceiver_.append(HELP_MSG_DUMP);
248     } else {
249         /* dump */
250 
251         // dump state
252         std::vector<std::string> state;
253         result = OsAccount::GetInstance().DumpState(id, state);
254         if (result == ERR_OK) {
255             for (auto info : state) {
256                 resultReceiver_ += info + "\n";
257             }
258         } else {
259             resultReceiver_ = STRING_DUMP_OS_ACCOUNT_NG + "\n";
260         }
261     }
262 
263     ACCOUNT_LOGD("result = %{public}d, id = %{public}d", result, id);
264     return result;
265 }
266 
RunCommand(int & counter,ErrCode & result,bool & enable,int & id,std::vector<std::string> & constraints)267 void AccountCommand::RunCommand(
268     int &counter, ErrCode &result, bool &enable, int &id, std::vector<std::string> &constraints)
269 {
270     while (true) {
271         counter++;
272 
273         int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
274         ACCOUNT_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
275 
276         if (option == -1) {
277             if (counter == 1) {
278                 result = RunCommandError(SET_COMMAND);
279             }
280             break;
281         }
282 
283         if (option == '?') {
284             result = RunAsSetCommandMissingOptionArgument();
285             break;
286         }
287 
288         result = RunAsSetCommandExistentOptionArgument(option, id, constraints, enable);
289     }
290 }
291 
RunAsSetCommand(void)292 ErrCode AccountCommand::RunAsSetCommand(void)
293 {
294     ErrCode result = ERR_OK;
295     int counter = 0;
296     int id = -1;
297     std::vector<std::string> constraints;
298     bool enable = false;
299 
300     RunCommand(counter, result, enable, id, constraints);
301 
302     if (result == ERR_OK) {
303         if (id == -1 || constraints.size() == 0) {
304             ACCOUNT_LOGD("'acm set' without enough options");
305 
306             if (id == -1) {
307                 resultReceiver_.append(HELP_MSG_NO_ID_OPTION + "\n");
308             }
309 
310             if (constraints.size() == 0) {
311                 resultReceiver_.append(HELP_MSG_NO_CONSTRAINTS_OPTION + "\n");
312             }
313 
314             result = ERR_INVALID_VALUE;
315         }
316     }
317 
318     if (result != ERR_OK) {
319         resultReceiver_.append(HELP_MSG_SET);
320     } else {
321         /* set */
322 
323         // set os account constraints
324         result = OsAccount::GetInstance().SetOsAccountConstraints(id, constraints, enable);
325         if (result == ERR_OK) {
326             resultReceiver_ = STRING_SET_OS_ACCOUNT_CONSTRAINTS_OK + "\n";
327         } else {
328             resultReceiver_ = STRING_SET_OS_ACCOUNT_CONSTRAINTS_NG + "\n";
329         }
330     }
331 
332     ACCOUNT_LOGD("result = %{public}d, id = %{public}d, enable = %{public}d", result, id, enable);
333     for (auto constraint : constraints) {
334         ACCOUNT_LOGD("constraint = %{public}s", constraint.c_str());
335     }
336 
337     return result;
338 }
339 
ParseCommandOpt(const std::string & command,ErrCode & result,int & id)340 void AccountCommand::ParseCommandOpt(const std::string &command, ErrCode &result, int &id)
341 {
342     int counter = 0;
343     while (true) {
344         counter++;
345 
346         int option = getopt_long(argc_, argv_, SHORT_OPTIONS.c_str(), LONG_OPTIONS, nullptr);
347         ACCOUNT_LOGD("option: %{public}d, optopt: %{public}d, optind: %{public}d", option, optopt, optind);
348 
349         if (option == -1) {
350             if (counter == 1) {
351                 result = RunCommandError(command);
352             }
353             break;
354         }
355 
356         if (option == '?') {
357             result = RunAsCommonCommandMissingOptionArgument(command);
358             break;
359         }
360 
361         result = RunAsCommonCommandExistentOptionArgument(option, id);
362     }
363 }
364 
RunAsSwitchCommand(void)365 ErrCode AccountCommand::RunAsSwitchCommand(void)
366 {
367     ErrCode result = ERR_OK;
368     int id = -1;
369     ParseCommandOpt(SWITCH_COMMAND, result, id);
370 
371     if (result != ERR_OK) {
372         resultReceiver_.append(HELP_MSG_SWITCH);
373     } else {
374         /* switch */
375 
376         // switch an os account
377         result = OsAccount::GetInstance().ActivateOsAccount(id);
378         if (result == ERR_OK) {
379             resultReceiver_ = STRING_SWITCH_OS_ACCOUNT_OK + "\n";
380         } else {
381             resultReceiver_ = STRING_SWITCH_OS_ACCOUNT_NG + "\n";
382         }
383     }
384 
385     ACCOUNT_LOGD("result = %{public}d, id = %{public}d", result, id);
386     return result;
387 }
388 
RunAsDeactivateCommand(void)389 ErrCode AccountCommand::RunAsDeactivateCommand(void)
390 {
391     ErrCode result = ERR_OK;
392     int id = -1;
393 
394     ParseCommandOpt(DEACTIVATE_COMMAND, result, id);
395 
396     if (result != ERR_OK) {
397         resultReceiver_.append(HELP_MSG_DEACTIVATE);
398     } else if (id != -1) {
399         /* deactivate */
400 
401         // deactivate an os account
402         result = OsAccount::GetInstance().DeactivateOsAccount(id);
403         if (result == ERR_OK) {
404             resultReceiver_ = STRING_DEACTIVATE_OS_ACCOUNT_OK + "\n";
405         } else {
406             resultReceiver_ = STRING_DEACTIVATE_OS_ACCOUNT_NG + "\n";
407         }
408     } else {
409         result = OsAccount::GetInstance().DeactivateAllOsAccounts();
410         if (result == ERR_OK) {
411             resultReceiver_ = STRING_DEACTIVATE_ALL_OS_ACCOUNTS_OK + "\n";
412         } else {
413             resultReceiver_ = STRING_DEACTIVATE_ALL_OS_ACCOUNTS_NG + "\n";
414         }
415     }
416 
417     ACCOUNT_LOGD("result = %{public}d, id = %{public}d", result, id);
418 
419     return result;
420 }
421 
RunAsCreateCommandMissingOptionArgument(void)422 ErrCode AccountCommand::RunAsCreateCommandMissingOptionArgument(void)
423 {
424     ErrCode result = ERR_OK;
425 
426     switch (optopt) {
427         case 'n': {
428             // 'acm create -n <name>' with no argument: acm create -n
429             // 'acm create --name <name>' with no argument: acm create --name
430             ACCOUNT_LOGD("'acm create -n' with no argument.");
431 
432             resultReceiver_.append(HELP_MSG_OPTION_REQUIRES_AN_ARGUMENT + "\n");
433             result = ERR_INVALID_VALUE;
434             break;
435         }
436         case 't': {
437             // 'acm create -t <type>' with no argument: acm create -t
438             // 'acm create --type <type>' with no argument: acm create --type
439             ACCOUNT_LOGD("'acm create -t' with no argument.");
440 
441             resultReceiver_.append(HELP_MSG_OPTION_REQUIRES_AN_ARGUMENT + "\n");
442 
443             result = ERR_INVALID_VALUE;
444             break;
445         }
446         default: {
447             // 'acm create' with an unknown option: acm create -x
448             // 'acm create' with an unknown option: acm create -xxx
449             std::string unknownOption = "";
450             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
451 
452             ACCOUNT_LOGD("'acm create' with an unknown option.");
453 
454             resultReceiver_.append(unknownOptionMsg);
455             result = ERR_INVALID_VALUE;
456             break;
457         }
458     }
459 
460     ACCOUNT_LOGD("end, result = %{public}d", result);
461     return result;
462 }
463 
RunAsCreateCommandExistentOptionArgument(const int & option,std::string & name,std::string & shortName,OsAccountType & type,std::vector<std::string> & disallowedList)464 ErrCode AccountCommand::RunAsCreateCommandExistentOptionArgument(const int &option, std::string &name,
465     std::string &shortName, OsAccountType &type, std::vector<std::string> &disallowedList)
466 {
467     ErrCode result = ERR_OK;
468 
469     switch (option) {
470         case 'h': {
471             // 'acm create -h'
472             // 'acm create --help'
473             result = ERR_INVALID_VALUE;
474             break;
475         }
476         case 'n': {
477             // 'acm create -n <name>'
478             // 'acm create --name <name>'
479             name = optarg;
480             break;
481         }
482         case 't': {
483             // 'acm create -t <type>'
484             // 'acm create --type <type>'
485             result = AnalyzeTypeArgument(type);
486             break;
487         }
488         case 's': {
489             // 'acm create -s <shortName>'
490             // 'acm create --shortName <shortName>'
491             shortName = optarg;
492             break;
493         }
494         case 'l': {
495             // 'acm create -l <disallowedlist>'
496             // 'acm create --disallowedlist <disallowedlist>'
497             result = AnalyzeDisallowedListArgument(disallowedList);
498             break;
499         }
500         default: {
501             break;
502         }
503     }
504 
505     ACCOUNT_LOGD("end, result = %{public}d", result);
506     return result;
507 }
508 
RunAsCommonCommandMissingOptionArgument(const std::string & command)509 ErrCode AccountCommand::RunAsCommonCommandMissingOptionArgument(const std::string &command)
510 {
511     ErrCode result = ERR_OK;
512 
513     switch (optopt) {
514         case 'i': {
515             // 'acm command -i <id>' with no argument: acm command -i
516             // 'acm command --id <id>' with no argument: acm command --id
517             ACCOUNT_LOGD("'acm %{public}s -i' with no argument.", command.c_str());
518 
519             resultReceiver_.append(HELP_MSG_OPTION_REQUIRES_AN_ARGUMENT + "\n");
520             result = ERR_INVALID_VALUE;
521             break;
522         }
523         default: {
524             // 'acm delete' with an unknown option: acm delete -x
525             // 'acm delete' with an unknown option: acm delete -xxx
526             std::string unknownOption = "";
527             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
528 
529             ACCOUNT_LOGD("'acm %{public}s' with an unknown option.",  command.c_str());
530 
531             resultReceiver_.append(unknownOptionMsg);
532             result = ERR_INVALID_VALUE;
533             break;
534         }
535     }
536     ACCOUNT_LOGD("end, result = %{public}d", result);
537     return result;
538 }
539 
RunCommandError(const std::string & command)540 ErrCode AccountCommand::RunCommandError(const std::string &command)
541 {
542     ErrCode result = ERR_OK;
543 
544     if (optind < 0 || optind >= argc_) {
545         ACCOUNT_LOGD("optind %{public}d invalid", optind);
546         return ERR_INVALID_VALUE;
547     }
548 
549     // When scanning the first argument
550     if (strcmp(argv_[optind], cmd_.c_str()) == 0) {
551         // 'acm command' with no option: acm command
552         // 'acm command' with a wrong argument: acm command xxx
553         ACCOUNT_LOGD("'acm %{public}s' with no option.", command.c_str());
554 
555         resultReceiver_.append(HELP_MSG_NO_OPTION + "\n");
556         result = ERR_INVALID_VALUE;
557     }
558 
559     ACCOUNT_LOGD("end, result = %{public}d", result);
560 
561     return result;
562 }
563 
RunAsSetCommandMissingOptionArgument(void)564 ErrCode AccountCommand::RunAsSetCommandMissingOptionArgument(void)
565 {
566     ErrCode result = ERR_OK;
567 
568     switch (optopt) {
569         case 'i': {
570             // 'acm set -i <id>' with no argument: acm set -i
571             // 'acm set --id <id>' with no argument: acm set --id
572             ACCOUNT_LOGD("'acm set -i' with no argument.");
573 
574             resultReceiver_.append(HELP_MSG_OPTION_REQUIRES_AN_ARGUMENT + "\n");
575             result = ERR_INVALID_VALUE;
576             break;
577         }
578         case 'c': {
579             // 'acm set -c <constraints>' with no argument: acm set -c
580             // 'acm set --constraint <constraints>' with no argument: acm set --constraint
581             ACCOUNT_LOGD("'acm set -c' with no argument.");
582 
583             resultReceiver_.append(HELP_MSG_OPTION_REQUIRES_AN_ARGUMENT + "\n");
584             result = ERR_INVALID_VALUE;
585             break;
586         }
587         default: {
588             // 'acm set' with an unknown option: acm set -x
589             // 'acm set' with an unknown option: acm set -xxx
590             std::string unknownOption = "";
591             std::string unknownOptionMsg = GetUnknownOptionMsg(unknownOption);
592 
593             ACCOUNT_LOGD("'set dump' with an unknown option.");
594 
595             resultReceiver_.append(unknownOptionMsg);
596             result = ERR_INVALID_VALUE;
597             break;
598         }
599     }
600     ACCOUNT_LOGD("end, result = %{public}d", result);
601     return result;
602 }
603 
RunAsSetCommandExistentOptionArgument(const int & option,int & id,std::vector<std::string> & constraints,bool & enable)604 ErrCode AccountCommand::RunAsSetCommandExistentOptionArgument(
605     const int &option, int &id, std::vector<std::string> &constraints, bool &enable)
606 {
607     ErrCode result = ERR_OK;
608 
609     switch (option) {
610         case 'h': {
611             // 'acm set -h'
612             // 'acm set --help'
613             result = ERR_INVALID_VALUE;
614             break;
615         }
616         case 'i': {
617             // 'acm set -i <id>'
618             // 'acm set --id <id>'
619             result = AnalyzeLocalIdArgument(id);
620             break;
621         }
622         case 'c': {
623             // 'acm set -c <constraints>'
624             // 'acm set --constraint <constraints>'
625             result = AnalyzeConstraintArgument(constraints);
626             break;
627         }
628         case 'e': {
629             // 'acm set -e'
630             // 'acm set --enable'
631             enable = true;
632             break;
633         }
634         default: {
635             break;
636         }
637     }
638 
639     ACCOUNT_LOGD("end, result = %{public}d, id = %{public}d", result, id);
640     return result;
641 }
642 
RunAsCommonCommandExistentOptionArgument(const int & option,int & id)643 ErrCode AccountCommand::RunAsCommonCommandExistentOptionArgument(const int &option, int &id)
644 {
645     ErrCode result = ERR_OK;
646 
647     switch (option) {
648         case 'h': {
649             // 'acm command -h'
650             // 'acm command --help'
651             // command includes stop, switch, deactivate, dump, delete
652             result = ERR_INVALID_VALUE;
653             break;
654         }
655         case 'i': {
656             // 'acm command -i <id>'
657             // 'acm command --id <id>
658             // command includes stop, switch, deactivate, dump, delete
659             result = AnalyzeLocalIdArgument(id);
660             break;
661         }
662         default: {
663             break;
664         }
665     }
666     ACCOUNT_LOGD("end, result = %{public}d, id = %{public}d", result, id);
667     return result;
668 }
669 
AnalyzeTypeArgument(OsAccountType & type)670 ErrCode AccountCommand::AnalyzeTypeArgument(OsAccountType &type)
671 {
672     ErrCode result = ERR_OK;
673     std::string typeByUser = optarg;
674 
675     if (typeByUser == "admin") {
676         type = OsAccountType::ADMIN;
677     } else if (typeByUser == "normal") {
678         type = OsAccountType::NORMAL;
679     } else if (typeByUser == "guest") {
680         type = OsAccountType::GUEST;
681     } else if (typeByUser == "private") {
682         type = OsAccountType::PRIVATE;
683     } else {
684         resultReceiver_.append(HELP_MSG_INVALID_TYPE_ARGUMENT + "\n");
685         result = ERR_INVALID_VALUE;
686     }
687 
688     return result;
689 }
690 
IsExistFile(const std::string & path)691 static bool IsExistFile(const std::string &path)
692 {
693     if (path.empty()) {
694         return false;
695     }
696 
697     struct stat buf = {};
698     if (stat(path.c_str(), &buf) != 0) {
699         return false;
700     }
701 
702     return S_ISREG(buf.st_mode);
703 }
704 
GetDisallowedListByPath(const std::string & path,std::vector<std::string> & disallowedList)705 static ErrCode GetDisallowedListByPath(const std::string &path, std::vector<std::string> &disallowedList)
706 {
707     if (!IsExistFile(path)) {
708         ACCOUNT_LOGE("cannot find file, path = %{public}s", path.c_str());
709         return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED;
710     }
711     std::ifstream readFile;
712     readFile.open(path.c_str(), std::ios::in);
713     if (!readFile.is_open()) {
714         ACCOUNT_LOGE("cannot open file, path = %{public}s", path.c_str());
715         return ERR_ACCOUNT_COMMON_FILE_OPEN_FAILED;
716     }
717     std::string str;
718     while (getline(readFile, str)) {
719         ACCOUNT_LOGI("read file, str = %{public}s", str.c_str());
720         disallowedList.emplace_back(str);
721     }
722     readFile.close();
723     return ERR_OK;
724 }
725 
AnalyzeDisallowedListArgument(std::vector<std::string> & disallowedList)726 ErrCode AccountCommand::AnalyzeDisallowedListArgument(std::vector<std::string> &disallowedList)
727 {
728     std::string listPath = optarg;
729     return GetDisallowedListByPath(listPath, disallowedList);
730 }
731 
AnalyzeLocalIdArgument(int & id)732 ErrCode AccountCommand::AnalyzeLocalIdArgument(int &id)
733 {
734     std::string idByUser = optarg;
735     if (!StrToInt(idByUser, id)) {
736         resultReceiver_.append(HELP_MSG_INVALID_ID_ARGUMENT + "\n");
737         return ERR_INVALID_VALUE;
738     }
739 
740     return ERR_OK;
741 }
742 
AnalyzeConstraintArgument(std::vector<std::string> & constraints)743 ErrCode AccountCommand::AnalyzeConstraintArgument(std::vector<std::string> &constraints)
744 {
745     std::string constraintsByUser = optarg;
746     ACCOUNT_LOGD("constraintsByUser = %{public}s", constraintsByUser.c_str());
747 
748     constraints.clear();
749     std::string constraint = "";
750     std::string delimiter = ",";
751     size_t last = 0;
752     size_t next = 0;
753 
754     while ((next = constraintsByUser.find(delimiter, last)) != std::string::npos) {
755         constraint = constraintsByUser.substr(last, next - last);
756         ACCOUNT_LOGD("constraint = %{public}s", constraint.c_str());
757 
758         constraints.emplace_back(constraint);
759         last = next + 1;
760     }
761     constraint = constraintsByUser.substr(last);
762     ACCOUNT_LOGD("constraint = %{public}s", constraint.c_str());
763     constraints.emplace_back(constraint);
764 
765     return ERR_OK;
766 }
767 }  // namespace AccountSA
768 }  // namespace OHOS