user_file.cc 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <cc/data.h>
  15. #include <user.h>
  16. #include <user_file.h>
  17. #include <boost/foreach.hpp>
  18. #include <errno.h>
  19. #include <iostream>
  20. namespace user_chk {
  21. UserFile::UserFile(const std::string& fname) : fname_(fname), file_() {
  22. if (fname_.empty()) {
  23. isc_throw(UserFileError, "file name cannot be blank");
  24. }
  25. }
  26. UserFile::~UserFile(){
  27. close();
  28. };
  29. void
  30. UserFile::open() {
  31. if (isOpen()) {
  32. isc_throw (UserFileError, "file is already open");
  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. UserPtr
  42. UserFile::readNextUser() {
  43. if (!isOpen()) {
  44. isc_throw (UserFileError, "cannot read, file is not open");
  45. }
  46. if (file_.good()) {
  47. char buf[USER_ENTRY_MAX_LEN];
  48. // Get the next line.
  49. file_.getline(buf, sizeof(buf));
  50. // We got something, try to make a user out of it.
  51. if (file_.gcount() > 0) {
  52. return(makeUser(buf));
  53. }
  54. }
  55. // Returns an empty user on EOF.
  56. return (UserPtr());
  57. }
  58. UserPtr
  59. UserFile::makeUser(const std::string& user_string) {
  60. // This method leverages the existing JSON parsing provided by isc::data
  61. // library. Should this prove to be a performance issue, it may be that
  62. // lighter weight solution would be appropriate.
  63. // Turn the string of JSON text into an Element set.
  64. isc::data::ElementPtr elements;
  65. try {
  66. elements = isc::data::Element::fromJSON(user_string);
  67. } catch (isc::data::JSONError& ex) {
  68. isc_throw(UserFileError,
  69. "UserFile entry is malformed JSON: " << ex.what());
  70. }
  71. // Get a map of the Elements, keyed by element name.
  72. isc::data::ConstElementPtr element;
  73. PropertyMap properties;
  74. std::string id_type_str;
  75. std::string id_str;
  76. // Iterate over the elements, saving of "type" and "id" to their
  77. // respective locals. Anything else is assumed to be an option so
  78. // add it to the local property map.
  79. std::pair<std::string, isc::data::ConstElementPtr> element_pair;
  80. BOOST_FOREACH (element_pair, elements->mapValue()) {
  81. // Get the element's label.
  82. std::string label = element_pair.first;
  83. // Currently everything must be a string.
  84. if (element_pair.second->getType() != isc::data::Element::string) {
  85. isc_throw (UserFileError, "UserFile entry: " << user_string
  86. << "has non-string value for : " << label);
  87. }
  88. std::string value = element_pair.second->stringValue();
  89. if (label == "type") {
  90. id_type_str = value;
  91. } else if (label == "id") {
  92. id_str = value;
  93. } else {
  94. // JSON parsing reduces any duplicates to the last value parsed,
  95. // so we will never see duplicates here.
  96. properties[label]=value;
  97. }
  98. }
  99. // First we attempt to translate the id type.
  100. UserId::UserIdType id_type;
  101. try {
  102. id_type = UserId::lookupType(id_type_str);
  103. } catch (const std::exception& ex) {
  104. isc_throw (UserFileError, "UserFile entry has invalid type: "
  105. << user_string << " " << ex.what());
  106. }
  107. // Id type is valid, so attempt to make the user based on that and
  108. // the value we have for "id".
  109. UserPtr user;
  110. try {
  111. user.reset(new User(id_type, id_str));
  112. } catch (const std::exception& ex) {
  113. isc_throw (UserFileError, "UserFile cannot create user form entry: "
  114. << user_string << " " << ex.what());
  115. }
  116. // We have a new User, so add in the properties and return it.
  117. user->setProperties(properties);
  118. return (user);
  119. }
  120. bool
  121. UserFile::isOpen() const {
  122. return (file_.is_open());
  123. }
  124. void
  125. UserFile::close() {
  126. try {
  127. if (file_.is_open()) {
  128. file_.close();
  129. }
  130. } catch (const std::exception& ex) {
  131. // Highly unlikely to occur but let's at least spit out an error.
  132. // Beyond that we swallow it for tidiness.
  133. std::cout << "UserFile unexpected error closing the file: "
  134. << fname_ << " : " << ex.what() << std::endl;
  135. }
  136. }
  137. } // namespace user_chk