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
OptionsFile(const std::string & path)21 OptionsFile::OptionsFile(const std::string &path) : path_(path) {
22 }
23
24 OptionsFile::~OptionsFile() = default;
25
Load()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
Save()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
IsLegalName(const std::string & name)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
IsLegalValue(const std::string & value)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
GetStringValue(const std::string & option,std::string * out_val) const127 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
GetIntValue(const std::string & option,int * out_val) const142 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
SetStringValue(const std::string & option,const std::string & value)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
SetIntValue(const std::string & option,int value)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
RemoveValue(const std::string & option)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