Home | History | Annotate | Download | only in base
      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 OptionsFile::~OptionsFile() = default;
     25 
     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 
     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 
    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 
    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 
    127 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 
    142 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 
    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 
    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 
    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