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
23using namespace OHOS::AAFwk;
24
25namespace OHOS {
26namespace AccountSA {
27namespace {
28const std::string SHORT_OPTIONS = "hn:t:i:s:l:c:ea";
29const 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
42static const std::string DEACTIVATE_COMMAND = "deactivate";
43static const std::string DELETE_COMMAND = "delete";
44static const std::string SWITCH_COMMAND = "switch";
45static const std::string DUMP_COMMAND = "dump";
46static const std::string SET_COMMAND = "set";
47static const std::string CREATE_COMMAND = "create";
48static constexpr int MIN_ARGUMENT_NUMBER = 2;
49static constexpr int MAX_ARGUMENT_NUMBER = 4096;
50}  // namespace
51
52AccountCommand::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
73void 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
86std::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
94std::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
108void 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
119std::string AccountCommand::ExecCommand()
120{
121    CreateCommandMap();
122    OnCommand();
123    return resultReceiver_;
124}
125
126ErrCode AccountCommand::RunAsHelpCommand(void)
127{
128    ACCOUNT_LOGD("enter");
129    resultReceiver_.append(HELP_MSG);
130    return ERR_OK;
131}
132
133ErrCode 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
161ErrCode 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
214ErrCode 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
239ErrCode 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
267void 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
292ErrCode 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
340void 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
365ErrCode 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
389ErrCode 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
422ErrCode 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
464ErrCode 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
509ErrCode 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
540ErrCode 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
564ErrCode 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
604ErrCode 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
643ErrCode 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
670ErrCode 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
691static 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
705static 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
726ErrCode AccountCommand::AnalyzeDisallowedListArgument(std::vector<std::string> &disallowedList)
727{
728    std::string listPath = optarg;
729    return GetDisallowedListByPath(listPath, disallowedList);
730}
731
732ErrCode 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
743ErrCode 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