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