1 /* 2 * Copyright 2008 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/base/optionsfile.h" 12 13 #include <ctype.h> 14 15 #include "webrtc/base/logging.h" 16 #include "webrtc/base/stream.h" 17 #include "webrtc/base/stringencode.h" 18 19 namespace rtc { 20 21 OptionsFile::OptionsFile(const std::string &path) : path_(path) { 22 } 23 24 OptionsFile::~OptionsFile() = default; 25 26 bool OptionsFile::Load() { 27 options_.clear(); 28 // Open file. 29 FileStream stream; 30 int err; 31 if (!stream.Open(path_, "r", &err)) { 32 LOG_F(LS_WARNING) << "Could not open file, err=" << err; 33 // We do not consider this an error because we expect there to be no file 34 // until the user saves a setting. 35 return true; 36 } 37 // Read in all its data. 38 std::string line; 39 StreamResult res; 40 for (;;) { 41 res = stream.ReadLine(&line); 42 if (res != SR_SUCCESS) { 43 break; 44 } 45 size_t equals_pos = line.find('='); 46 if (equals_pos == std::string::npos) { 47 // We do not consider this an error. Instead we ignore the line and 48 // keep going. 49 LOG_F(LS_WARNING) << "Ignoring malformed line in " << path_; 50 continue; 51 } 52 std::string key(line, 0, equals_pos); 53 std::string value(line, equals_pos + 1, line.length() - (equals_pos + 1)); 54 options_[key] = value; 55 } 56 if (res != SR_EOS) { 57 LOG_F(LS_ERROR) << "Error when reading from file"; 58 return false; 59 } else { 60 return true; 61 } 62 } 63 64 bool OptionsFile::Save() { 65 // Open file. 66 FileStream stream; 67 int err; 68 if (!stream.Open(path_, "w", &err)) { 69 LOG_F(LS_ERROR) << "Could not open file, err=" << err; 70 return false; 71 } 72 // Write out all the data. 73 StreamResult res = SR_SUCCESS; 74 size_t written; 75 int error; 76 for (OptionsMap::const_iterator i = options_.begin(); i != options_.end(); 77 ++i) { 78 res = stream.WriteAll(i->first.c_str(), i->first.length(), &written, 79 &error); 80 if (res != SR_SUCCESS) { 81 break; 82 } 83 res = stream.WriteAll("=", 1, &written, &error); 84 if (res != SR_SUCCESS) { 85 break; 86 } 87 res = stream.WriteAll(i->second.c_str(), i->second.length(), &written, 88 &error); 89 if (res != SR_SUCCESS) { 90 break; 91 } 92 res = stream.WriteAll("\n", 1, &written, &error); 93 if (res != SR_SUCCESS) { 94 break; 95 } 96 } 97 if (res != SR_SUCCESS) { 98 LOG_F(LS_ERROR) << "Unable to write to file"; 99 return false; 100 } else { 101 return true; 102 } 103 } 104 105 bool OptionsFile::IsLegalName(const std::string &name) { 106 for (size_t pos = 0; pos < name.length(); ++pos) { 107 if (name[pos] == '\n' || name[pos] == '\\' || name[pos] == '=') { 108 // Illegal character. 109 LOG(LS_WARNING) << "Ignoring operation for illegal option " << name; 110 return false; 111 } 112 } 113 return true; 114 } 115 116 bool OptionsFile::IsLegalValue(const std::string &value) { 117 for (size_t pos = 0; pos < value.length(); ++pos) { 118 if (value[pos] == '\n' || value[pos] == '\\') { 119 // Illegal character. 120 LOG(LS_WARNING) << "Ignoring operation for illegal value " << value; 121 return false; 122 } 123 } 124 return true; 125 } 126 127 bool OptionsFile::GetStringValue(const std::string& option, 128 std::string *out_val) const { 129 LOG(LS_VERBOSE) << "OptionsFile::GetStringValue " 130 << option; 131 if (!IsLegalName(option)) { 132 return false; 133 } 134 OptionsMap::const_iterator i = options_.find(option); 135 if (i == options_.end()) { 136 return false; 137 } 138 *out_val = i->second; 139 return true; 140 } 141 142 bool OptionsFile::GetIntValue(const std::string& option, 143 int *out_val) const { 144 LOG(LS_VERBOSE) << "OptionsFile::GetIntValue " 145 << option; 146 if (!IsLegalName(option)) { 147 return false; 148 } 149 OptionsMap::const_iterator i = options_.find(option); 150 if (i == options_.end()) { 151 return false; 152 } 153 return FromString(i->second, out_val); 154 } 155 156 bool OptionsFile::SetStringValue(const std::string& option, 157 const std::string& value) { 158 LOG(LS_VERBOSE) << "OptionsFile::SetStringValue " 159 << option << ":" << value; 160 if (!IsLegalName(option) || !IsLegalValue(value)) { 161 return false; 162 } 163 options_[option] = value; 164 return true; 165 } 166 167 bool OptionsFile::SetIntValue(const std::string& option, 168 int value) { 169 LOG(LS_VERBOSE) << "OptionsFile::SetIntValue " 170 << option << ":" << value; 171 if (!IsLegalName(option)) { 172 return false; 173 } 174 return ToString(value, &options_[option]); 175 } 176 177 bool OptionsFile::RemoveValue(const std::string& option) { 178 LOG(LS_VERBOSE) << "OptionsFile::RemoveValue " << option; 179 if (!IsLegalName(option)) { 180 return false; 181 } 182 options_.erase(option); 183 return true; 184 } 185 186 } // namespace rtc 187