blob: 8d2d2e0df6cdfd115d115fb1802a44c37503fc38 [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
Yves Gerey665174f2018-06-19 15:03:05 +020021OptionsFile::OptionsFile(const std::string& path) : path_(path) {}
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000022
kwiberg@webrtc.org67186fe2015-03-09 22:21:53 +000023OptionsFile::~OptionsFile() = default;
24
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000025bool OptionsFile::Load() {
26 options_.clear();
27 // Open file.
28 FileStream stream;
29 int err;
30 if (!stream.Open(path_, "r", &err)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010031 RTC_LOG_F(LS_WARNING) << "Could not open file, err=" << err;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000032 // We do not consider this an error because we expect there to be no file
33 // until the user saves a setting.
34 return true;
35 }
36 // Read in all its data.
37 std::string line;
38 StreamResult res;
39 for (;;) {
40 res = stream.ReadLine(&line);
41 if (res != SR_SUCCESS) {
42 break;
43 }
44 size_t equals_pos = line.find('=');
45 if (equals_pos == std::string::npos) {
46 // We do not consider this an error. Instead we ignore the line and
47 // keep going.
Mirko Bonadei675513b2017-11-09 11:09:25 +010048 RTC_LOG_F(LS_WARNING) << "Ignoring malformed line in " << path_;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000049 continue;
50 }
51 std::string key(line, 0, equals_pos);
52 std::string value(line, equals_pos + 1, line.length() - (equals_pos + 1));
53 options_[key] = value;
54 }
55 if (res != SR_EOS) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010056 RTC_LOG_F(LS_ERROR) << "Error when reading from file";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000057 return false;
58 } else {
59 return true;
60 }
61}
62
63bool OptionsFile::Save() {
64 // Open file.
65 FileStream stream;
66 int err;
67 if (!stream.Open(path_, "w", &err)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010068 RTC_LOG_F(LS_ERROR) << "Could not open file, err=" << err;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000069 return false;
70 }
71 // Write out all the data.
72 StreamResult res = SR_SUCCESS;
73 size_t written;
74 int error;
75 for (OptionsMap::const_iterator i = options_.begin(); i != options_.end();
76 ++i) {
Yves Gerey665174f2018-06-19 15:03:05 +020077 res =
78 stream.WriteAll(i->first.c_str(), i->first.length(), &written, &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000079 if (res != SR_SUCCESS) {
80 break;
81 }
82 res = stream.WriteAll("=", 1, &written, &error);
83 if (res != SR_SUCCESS) {
84 break;
85 }
86 res = stream.WriteAll(i->second.c_str(), i->second.length(), &written,
Yves Gerey665174f2018-06-19 15:03:05 +020087 &error);
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000088 if (res != SR_SUCCESS) {
89 break;
90 }
91 res = stream.WriteAll("\n", 1, &written, &error);
92 if (res != SR_SUCCESS) {
93 break;
94 }
95 }
96 if (res != SR_SUCCESS) {
Mirko Bonadei675513b2017-11-09 11:09:25 +010097 RTC_LOG_F(LS_ERROR) << "Unable to write to file";
henrike@webrtc.orgf0488722014-05-13 18:00:26 +000098 return false;
99 } else {
100 return true;
101 }
102}
103
Yves Gerey665174f2018-06-19 15:03:05 +0200104bool OptionsFile::IsLegalName(const std::string& name) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000105 for (size_t pos = 0; pos < name.length(); ++pos) {
106 if (name[pos] == '\n' || name[pos] == '\\' || name[pos] == '=') {
107 // Illegal character.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100108 RTC_LOG(LS_WARNING) << "Ignoring operation for illegal option " << name;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000109 return false;
110 }
111 }
112 return true;
113}
114
Yves Gerey665174f2018-06-19 15:03:05 +0200115bool OptionsFile::IsLegalValue(const std::string& value) {
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000116 for (size_t pos = 0; pos < value.length(); ++pos) {
117 if (value[pos] == '\n' || value[pos] == '\\') {
118 // Illegal character.
Mirko Bonadei675513b2017-11-09 11:09:25 +0100119 RTC_LOG(LS_WARNING) << "Ignoring operation for illegal value " << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000120 return false;
121 }
122 }
123 return true;
124}
125
126bool OptionsFile::GetStringValue(const std::string& option,
Yves Gerey665174f2018-06-19 15:03:05 +0200127 std::string* out_val) const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100128 RTC_LOG(LS_VERBOSE) << "OptionsFile::GetStringValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000129 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
Yves Gerey665174f2018-06-19 15:03:05 +0200140bool OptionsFile::GetIntValue(const std::string& option, int* out_val) const {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100141 RTC_LOG(LS_VERBOSE) << "OptionsFile::GetIntValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000142 if (!IsLegalName(option)) {
143 return false;
144 }
145 OptionsMap::const_iterator i = options_.find(option);
146 if (i == options_.end()) {
147 return false;
148 }
149 return FromString(i->second, out_val);
150}
151
152bool OptionsFile::SetStringValue(const std::string& option,
153 const std::string& value) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100154 RTC_LOG(LS_VERBOSE) << "OptionsFile::SetStringValue " << option << ":"
155 << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000156 if (!IsLegalName(option) || !IsLegalValue(value)) {
157 return false;
158 }
159 options_[option] = value;
160 return true;
161}
162
Yves Gerey665174f2018-06-19 15:03:05 +0200163bool OptionsFile::SetIntValue(const std::string& option, int value) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100164 RTC_LOG(LS_VERBOSE) << "OptionsFile::SetIntValue " << option << ":" << value;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000165 if (!IsLegalName(option)) {
166 return false;
167 }
168 return ToString(value, &options_[option]);
169}
170
171bool OptionsFile::RemoveValue(const std::string& option) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100172 RTC_LOG(LS_VERBOSE) << "OptionsFile::RemoveValue " << option;
henrike@webrtc.orgf0488722014-05-13 18:00:26 +0000173 if (!IsLegalName(option)) {
174 return false;
175 }
176 options_.erase(option);
177 return true;
178}
179
180} // namespace rtc