147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2008 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/optionsfile.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <ctype.h>
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stream.h"
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringencode.h"
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgOptionsFile::OptionsFile(const std::string &path) : path_(path) {
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::Load() {
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  options_.clear();
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Open file.
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FileStream stream;
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int err;
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!stream.Open(path_, "r", &err)) {
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_WARNING) << "Could not open file, err=" << err;
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // We do not consider this an error because we expect there to be no file
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // until the user saves a setting.
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Read in all its data.
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::string line;
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  StreamResult res;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (;;) {
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    res = stream.ReadLine(&line);
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res != SR_SUCCESS) {
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    size_t equals_pos = line.find('=');
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (equals_pos == std::string::npos) {
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // We do not consider this an error. Instead we ignore the line and
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // keep going.
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG_F(LS_WARNING) << "Ignoring malformed line in " << path_;
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      continue;
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::string key(line, 0, equals_pos);
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    std::string value(line, equals_pos + 1, line.length() - (equals_pos + 1));
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    options_[key] = value;
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (res != SR_EOS) {
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_ERROR) << "Error when reading from file";
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::Save() {
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Open file.
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  FileStream stream;
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int err;
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!stream.Open(path_, "w", &err)) {
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_ERROR) << "Could not open file, err=" << err;
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Write out all the data.
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  StreamResult res = SR_SUCCESS;
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  size_t written;
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error;
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (OptionsMap::const_iterator i = options_.begin(); i != options_.end();
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org       ++i) {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    res = stream.WriteAll(i->first.c_str(), i->first.length(), &written,
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        &error);
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res != SR_SUCCESS) {
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    res = stream.WriteAll("=", 1, &written, &error);
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res != SR_SUCCESS) {
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    res = stream.WriteAll(i->second.c_str(), i->second.length(), &written,
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        &error);
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res != SR_SUCCESS) {
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    res = stream.WriteAll("\n", 1, &written, &error);
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (res != SR_SUCCESS) {
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      break;
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (res != SR_SUCCESS) {
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_F(LS_ERROR) << "Unable to write to file";
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return true;
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::IsLegalName(const std::string &name) {
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t pos = 0; pos < name.length(); ++pos) {
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (name[pos] == '\n' || name[pos] == '\\' || name[pos] == '=') {
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Illegal character.
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "Ignoring operation for illegal option " << name;
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::IsLegalValue(const std::string &value) {
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  for (size_t pos = 0; pos < value.length(); ++pos) {
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (value[pos] == '\n' || value[pos] == '\\') {
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Illegal character.
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "Ignoring operation for illegal value " << value;
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::GetStringValue(const std::string& option,
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 std::string *out_val) const {
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_VERBOSE) << "OptionsFile::GetStringValue "
12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << option;
12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsLegalName(option)) {
13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  OptionsMap::const_iterator i = options_.find(option);
13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (i == options_.end()) {
13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  *out_val = i->second;
13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::GetIntValue(const std::string& option,
14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              int *out_val) const {
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_VERBOSE) << "OptionsFile::GetIntValue "
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << option;
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsLegalName(option)) {
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  OptionsMap::const_iterator i = options_.find(option);
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (i == options_.end()) {
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return FromString(i->second, out_val);
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::SetStringValue(const std::string& option,
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                                 const std::string& value) {
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_VERBOSE) << "OptionsFile::SetStringValue "
15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << option << ":" << value;
15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsLegalName(option) || !IsLegalValue(value)) {
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  options_[option] = value;
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::SetIntValue(const std::string& option,
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                              int value) {
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_VERBOSE) << "OptionsFile::SetIntValue "
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                  << option << ":" << value;
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsLegalName(option)) {
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ToString(value, &options_[option]);
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool OptionsFile::RemoveValue(const std::string& option) {
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LOG(LS_VERBOSE) << "OptionsFile::RemoveValue " << option;
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!IsLegalName(option)) {
17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  options_.erase(option);
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
185