| Kea 3.0.2-git

user_file.cc
Go to the documentation of this file.
1// Copyright (C) 2013-2024 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8
9#include <cc/data.h>
10#include <user.h>
11#include <user_file.h>
12
13#include <errno.h>
14#include <iostream>
15
16 namespace user_chk {
17
18 UserFile::UserFile(const std::string& fname) : fname_(fname), file_() {
19 if (fname_.empty()) {
20 isc_throw(UserFileError, "file name cannot be blank");
21 }
22}
23
24 UserFile::~UserFile(){
25 close();
26};
27
28 void
29 UserFile::open() {
30 if (isOpen()) {
31 isc_throw(UserFileError, "file is already open");
32 }
33
34 file_.open(fname_.c_str(), std::ifstream::in);
35 int sav_error = errno;
36 if (!file_.is_open()) {
37 isc_throw(UserFileError, "cannot open file:" << fname_
38 << " reason: " << strerror(sav_error));
39 }
40}
41
42 UserPtr
43 UserFile::readNextUser() {
44 if (!isOpen()) {
45 isc_throw (UserFileError, "cannot read, file is not open");
46 }
47
48 if (file_.good()) {
49 char buf[USER_ENTRY_MAX_LEN];
50
51 // Get the next line.
52 file_.getline(buf, sizeof(buf));
53
54 // We got something, try to make a user out of it.
55 if (file_.gcount() > 0) {
56 return(makeUser(buf));
57 }
58 }
59
60 // Returns an empty user on EOF.
61 return (UserPtr());
62}
63
64 UserPtr
65 UserFile::makeUser(const std::string& user_string) {
66 // This method leverages the existing JSON parsing provided by isc::data
67 // library. Should this prove to be a performance issue, it may be that
68 // lighter weight solution would be appropriate.
69
70 // Turn the string of JSON text into an Element set.
71 isc::data::ElementPtr elements;
72 try {
73 elements = isc::data::Element::fromJSON(user_string);
74 } catch (const isc::data::JSONError& ex) {
75 isc_throw(UserFileError,
76 "UserFile entry is malformed JSON: " << ex.what());
77 }
78
79 // Get a map of the Elements, keyed by element name.
80 isc::data::ConstElementPtr element;
81 PropertyMap properties;
82 std::string id_type_str;
83 std::string id_str;
84
85 // Iterate over the elements, saving of "type" and "id" to their
86 // respective locals. Anything else is assumed to be an option so
87 // add it to the local property map.
88 for (auto const& element_pair : elements->mapValue()) {
89 // Get the element's label.
90 std::string label = element_pair.first;
91
92 // Currently everything must be a string.
93 if (element_pair.second->getType() != isc::data::Element::string) {
94 isc_throw (UserFileError, "UserFile entry: " << user_string
95 << "has non-string value for : " << label);
96 }
97
98 std::string value = element_pair.second->stringValue();
99
100 if (label == "type") {
101 id_type_str = value;
102 } else if (label == "id") {
103 id_str = value;
104 } else {
105 // JSON parsing reduces any duplicates to the last value parsed,
106 // so we will never see duplicates here.
107 properties[label]=value;
108 }
109 }
110
111 // First we attempt to translate the id type.
112 UserId::UserIdType id_type;
113 try {
114 id_type = UserId::lookupType(id_type_str);
115 } catch (const std::exception& ex) {
116 isc_throw (UserFileError, "UserFile entry has invalid type: "
117 << user_string << " " << ex.what());
118 }
119
120 // Id type is valid, so attempt to make the user based on that and
121 // the value we have for "id".
122 UserPtr user;
123 try {
124 user.reset(new User(id_type, id_str));
125 } catch (const std::exception& ex) {
126 isc_throw (UserFileError, "UserFile cannot create user form entry: "
127 << user_string << " " << ex.what());
128 }
129
130 // We have a new User, so add in the properties and return it.
131 user->setProperties(properties);
132 return (user);
133}
134
135 bool
136 UserFile::isOpen() const {
137 return (file_.is_open());
138}
139
140 void
141 UserFile::close() {
142 try {
143 if (file_.is_open()) {
144 file_.close();
145 }
146 } catch (const std::exception& ex) {
147 // Highly unlikely to occur but let's at least spit out an error.
148 // Beyond that we swallow it for tidiness.
149 std::cout << "UserFile unexpected error closing the file: "
150 << fname_ << " : " << ex.what() << std::endl;
151 }
152}
153
154} // namespace user_chk
isc::Exception::what
virtual const char * what() const
Returns a C-style character string of the cause of the exception.
Definition exceptions/exceptions.cc:32
isc::data::Element::fromJSON
static ElementPtr fromJSON(const std::string &in, bool preproc=false)
These functions will parse the given string (JSON) representation of a compound element.
Definition data.cc:798
isc::data::Element::string
@ string
Definition data.h:144
isc::data::JSONError
A standard Data module exception that is thrown if a parse error is encountered when constructing an ...
Definition data.h:49
user_chk::UserFileError
Thrown a UserFile encounters an error.
Definition user_file.h:22
user_chk::UserFile::USER_ENTRY_MAX_LEN
static const size_t USER_ENTRY_MAX_LEN
Maximum length of a single user entry.
Definition user_file.h:63
user_chk::UserFile::readNextUser
virtual UserPtr readNextUser()
Fetches the next user from the file.
Definition user_file.cc:43
user_chk::UserFile::close
virtual void close()
Closes the underlying file.
Definition user_file.cc:141
user_chk::UserFile::UserFile
UserFile(const std::string &fname)
Constructor.
Definition user_file.cc:18
user_chk::UserFile::makeUser
UserPtr makeUser(const std::string &user_string)
Creates a new User instance from JSON text.
Definition user_file.cc:65
user_chk::UserFile::isOpen
virtual bool isOpen() const
Returns true if the file is open.
Definition user_file.cc:136
user_chk::UserFile::~UserFile
virtual ~UserFile()
Destructor. / The destructor does call the close method.
Definition user_file.cc:24
user_chk::UserFile::open
virtual void open()
Opens the input file for reading.
Definition user_file.cc:29
user_chk::UserId::lookupType
static UserIdType lookupType(const std::string &type_str)
Returns the id type for a given text label.
Definition user.cc:136
user_chk::UserId::UserIdType
UserIdType
Defines the supported types of user ids.
Definition user.h:32
user_chk::User
Represents a unique DHCP user This class is used to represent a specific DHCP user who is identified ...
Definition user.h:150
data.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
isc::data::ConstElementPtr
boost::shared_ptr< const Element > ConstElementPtr
Definition data.h:29
isc::data::ElementPtr
boost::shared_ptr< Element > ElementPtr
Definition data.h:28
user_chk
Defines the logger used by the user check hooks library.
Definition user.cc:19
user_chk::PropertyMap
std::map< std::string, std::string > PropertyMap
Defines a map of string values keyed by string labels.
Definition user.h:145
user_chk::UserPtr
boost::shared_ptr< User > UserPtr
Defines a smart pointer to a User.
Definition user.h:241
user.h
This file defines classes: UserId and User.
user_file.h
Defines the class, UserFile, which implements the UserDataSource interface for text files.