blob: c3b6a6ab93da7ed4df473a478204fc38c50e5961 [file] [log] [blame]
henrike@webrtc.orgf0488722014-05-13 18:00:26 +00001/*
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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "rtc_base/optionsfile.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000012
13#include <ctype.h>
14
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020015#include "rtc_base/logging.h"
16#include "rtc_base/stream.h"
17#include "rtc_base/stringencode.h"
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000018
19namespace rtc {
20
21OptionsFile::OptionsFile(const std::string &path) : path_(path) {
22}
23
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000024OptionsFile::~OptionsFile() = default;
25
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000026bool OptionsFile::Load() {
27 options_.clear();
28 // Open file.
29 FileStream stream;
30 int err;
31 if (!stream.Open(path_, "r", &err)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010032 RTC_LOG_F(LS_WARNING) << "Could not open file, err=" << err;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000033 // 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.
Mirko Bonadei675513b2017-11-09 11:09:25 +010049 RTC_LOG_F(LS_WARNING) << "Ignoring malformed line in " << path_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000050 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) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010057 RTC_LOG_F(LS_ERROR) << "Error when reading from file";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000058 return false;
59 } else {
60 return true;
61 }
62}
63
64bool OptionsFile::Save() {
65 // Open file.
66 FileStream stream;
67 int err;
68 if (!stream.Open(path_, "w", &err)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010069 RTC_LOG_F(LS_ERROR) << "Could not open file, err=" << err;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000070 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) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010098 RTC_LOG_F(LS_ERROR) << "Unable to write to file";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000099 return false;
100 } else {
101 return true;
102 }
103}
104
105bool 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.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100109 RTC_LOG(LS_WARNING) << "Ignoring operation for illegal option " << name;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000110 return false;
111 }
112 }
113 return true;
114}
115
116bool 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.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100120 RTC_LOG(LS_WARNING) << "Ignoring operation for illegal value " << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000121 return false;
122 }
123 }
124 return true;
125}
126
127bool OptionsFile::GetStringValue(const std::string& option,
128 std::string *out_val) const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100129 RTC_LOG(LS_VERBOSE) << "OptionsFile::GetStringValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000130 if (!IsLegalName(option)) {
131 return false;
132 }
133 OptionsMap::const_iterator i = options_.find(option);
134 if (i == options_.end()) {
135 return false;
136 }
137 *out_val = i->second;
138 return true;
139}
140
141bool OptionsFile::GetIntValue(const std::string& option,
142 int *out_val) const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100143 RTC_LOG(LS_VERBOSE) << "OptionsFile::GetIntValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000144 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
154bool OptionsFile::SetStringValue(const std::string& option,
155 const std::string& value) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100156 RTC_LOG(LS_VERBOSE) << "OptionsFile::SetStringValue " << option << ":"
157 << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000158 if (!IsLegalName(option) || !IsLegalValue(value)) {
159 return false;
160 }
161 options_[option] = value;
162 return true;
163}
164
165bool OptionsFile::SetIntValue(const std::string& option,
166 int value) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100167 RTC_LOG(LS_VERBOSE) << "OptionsFile::SetIntValue " << option << ":" << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000168 if (!IsLegalName(option)) {
169 return false;
170 }
171 return ToString(value, &options_[option]);
172}
173
174bool OptionsFile::RemoveValue(const std::string& option) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100175 RTC_LOG(LS_VERBOSE) << "OptionsFile::RemoveValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000176 if (!IsLegalName(option)) {
177 return false;
178 }
179 options_.erase(option);
180 return true;
181}
182
183} // namespace rtc