This source file includes following definitions.
- ValidateUTF8
- CopyStringFromDictionary
- SetSSID
- GetSSIDFromProperties
- GetNetworkIdFromProperties
- GetNameFromProperties
- GetUIDataFromValue
- GetUIDataFromProperties
- SetUIData
- CopyIdentifyingProperties
- DoIdentifyingPropertiesMatch
- IsPassphraseKey
- ShillNetworkTypeToFlag
- Default
- Wireless
- Mobile
- NonVirtual
- Ethernet
- WiFi
- Cellular
- VPN
- Wimax
- Primitive
- Equals
- MatchesType
- MatchesPattern
- ToDebugString
#include "chromeos/network/shill_property_util.h"
#include "base/i18n/icu_encoding_detection.h"
#include "base/i18n/icu_string_conversions.h"
#include "base/json/json_writer.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/values.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_ui_data.h"
#include "chromeos/network/onc/onc_utils.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
namespace shill_property_util {
namespace {
std::string ValidateUTF8(const std::string& str) {
std::string result;
for (int32 index = 0; index < static_cast<int32>(str.size()); ++index) {
uint32 code_point_out;
bool is_unicode_char = base::ReadUnicodeCharacter(
str.c_str(), str.size(), &index, &code_point_out);
const uint32 kFirstNonControlChar = 0x20;
if (is_unicode_char && (code_point_out >= kFirstNonControlChar)) {
base::WriteUnicodeCharacter(code_point_out, &result);
} else {
const uint32 kReplacementChar = 0xFFFD;
base::WriteUnicodeCharacter(kReplacementChar, &result);
}
}
return result;
}
bool CopyStringFromDictionary(const base::DictionaryValue& source,
const std::string& key,
base::DictionaryValue* dest) {
std::string string_value;
if (!source.GetStringWithoutPathExpansion(key, &string_value) ||
string_value.empty())
return false;
dest->SetStringWithoutPathExpansion(key, string_value);
return true;
}
}
void SetSSID(const std::string ssid, base::DictionaryValue* properties) {
std::string hex_ssid = base::HexEncode(ssid.c_str(), ssid.size());
properties->SetStringWithoutPathExpansion(shill::kWifiHexSsid, hex_ssid);
}
std::string GetSSIDFromProperties(const base::DictionaryValue& properties,
bool* unknown_encoding) {
if (unknown_encoding)
*unknown_encoding = false;
std::string hex_ssid;
properties.GetStringWithoutPathExpansion(shill::kWifiHexSsid, &hex_ssid);
if (hex_ssid.empty()) {
NET_LOG_ERROR("GetSSIDFromProperties", "No HexSSID set.");
return std::string();
}
std::string ssid;
std::vector<uint8> raw_ssid_bytes;
if (base::HexStringToBytes(hex_ssid, &raw_ssid_bytes)) {
ssid = std::string(raw_ssid_bytes.begin(), raw_ssid_bytes.end());
NET_LOG_DEBUG(
"GetSSIDFromProperties",
base::StringPrintf("%s, SSID: %s", hex_ssid.c_str(), ssid.c_str()));
} else {
NET_LOG_ERROR("GetSSIDFromProperties",
base::StringPrintf("Error processing: %s", hex_ssid.c_str()));
return std::string();
}
if (IsStringUTF8(ssid))
return ssid;
std::string encoding;
if (!base::DetectEncoding(ssid, &encoding)) {
properties.GetStringWithoutPathExpansion(shill::kCountryProperty,
&encoding);
}
std::string utf8_ssid;
if (!encoding.empty() &&
base::ConvertToUtf8AndNormalize(ssid, encoding, &utf8_ssid)) {
if (utf8_ssid != ssid) {
NET_LOG_DEBUG(
"GetSSIDFromProperties",
base::StringPrintf(
"Encoding=%s: %s", encoding.c_str(), utf8_ssid.c_str()));
}
return utf8_ssid;
}
if (unknown_encoding)
*unknown_encoding = true;
NET_LOG_DEBUG(
"GetSSIDFromProperties",
base::StringPrintf("Unrecognized Encoding=%s", encoding.c_str()));
return ssid;
}
std::string GetNetworkIdFromProperties(
const base::DictionaryValue& properties) {
if (properties.empty())
return "EmptyProperties";
std::string result;
if (properties.GetStringWithoutPathExpansion(shill::kGuidProperty, &result))
return result;
if (properties.GetStringWithoutPathExpansion(shill::kSSIDProperty, &result))
return result;
if (properties.GetStringWithoutPathExpansion(shill::kNameProperty, &result))
return result;
std::string type = "UnknownType";
properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
return "Unidentified " + type;
}
std::string GetNameFromProperties(const std::string& service_path,
const base::DictionaryValue& properties) {
std::string name;
properties.GetStringWithoutPathExpansion(shill::kNameProperty, &name);
std::string validated_name = ValidateUTF8(name);
if (validated_name != name) {
NET_LOG_DEBUG("GetNameFromProperties",
base::StringPrintf("Validated name %s: UTF8: %s",
service_path.c_str(),
validated_name.c_str()));
}
std::string type;
properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
if (type.empty()) {
NET_LOG_ERROR("GetNameFromProperties: No type", service_path);
return validated_name;
}
if (!NetworkTypePattern::WiFi().MatchesType(type))
return validated_name;
bool unknown_ssid_encoding = false;
std::string ssid = GetSSIDFromProperties(properties, &unknown_ssid_encoding);
if (ssid.empty())
NET_LOG_ERROR("GetNameFromProperties", "No SSID set: " + service_path);
if (ssid.empty() || (unknown_ssid_encoding && !validated_name.empty()))
return validated_name;
if (ssid != validated_name) {
NET_LOG_DEBUG("GetNameFromProperties",
base::StringPrintf("%s: SSID: %s, Name: %s",
service_path.c_str(),
ssid.c_str(),
validated_name.c_str()));
}
return ssid;
}
scoped_ptr<NetworkUIData> GetUIDataFromValue(const base::Value& ui_data_value) {
std::string ui_data_str;
if (!ui_data_value.GetAsString(&ui_data_str))
return scoped_ptr<NetworkUIData>();
if (ui_data_str.empty())
return make_scoped_ptr(new NetworkUIData());
scoped_ptr<base::DictionaryValue> ui_data_dict(
chromeos::onc::ReadDictionaryFromJson(ui_data_str));
if (!ui_data_dict)
return scoped_ptr<NetworkUIData>();
return make_scoped_ptr(new NetworkUIData(*ui_data_dict));
}
scoped_ptr<NetworkUIData> GetUIDataFromProperties(
const base::DictionaryValue& shill_dictionary) {
const base::Value* ui_data_value = NULL;
shill_dictionary.GetWithoutPathExpansion(shill::kUIDataProperty,
&ui_data_value);
if (!ui_data_value) {
VLOG(2) << "Dictionary has no UIData entry.";
return scoped_ptr<NetworkUIData>();
}
scoped_ptr<NetworkUIData> ui_data = GetUIDataFromValue(*ui_data_value);
if (!ui_data)
LOG(ERROR) << "UIData is not a valid JSON dictionary.";
return ui_data.Pass();
}
void SetUIData(const NetworkUIData& ui_data,
base::DictionaryValue* shill_dictionary) {
base::DictionaryValue ui_data_dict;
ui_data.FillDictionary(&ui_data_dict);
std::string ui_data_blob;
base::JSONWriter::Write(&ui_data_dict, &ui_data_blob);
shill_dictionary->SetStringWithoutPathExpansion(shill::kUIDataProperty,
ui_data_blob);
}
bool CopyIdentifyingProperties(const base::DictionaryValue& service_properties,
base::DictionaryValue* dest) {
bool success = true;
CopyStringFromDictionary(service_properties, shill::kGuidProperty, dest);
std::string type;
service_properties.GetStringWithoutPathExpansion(shill::kTypeProperty, &type);
success &= !type.empty();
dest->SetStringWithoutPathExpansion(shill::kTypeProperty, type);
if (type == shill::kTypeWifi) {
success &= CopyStringFromDictionary(
service_properties, shill::kSecurityProperty, dest);
success &=
CopyStringFromDictionary(service_properties, shill::kWifiHexSsid, dest);
success &= CopyStringFromDictionary(
service_properties, shill::kModeProperty, dest);
} else if (type == shill::kTypeVPN) {
success &= CopyStringFromDictionary(
service_properties, shill::kNameProperty, dest);
const base::DictionaryValue* provider_properties = NULL;
if (!service_properties.GetDictionaryWithoutPathExpansion(
shill::kProviderProperty, &provider_properties)) {
NET_LOG_ERROR("Missing VPN provider dict",
GetNetworkIdFromProperties(service_properties));
return false;
}
std::string vpn_provider_type;
provider_properties->GetStringWithoutPathExpansion(shill::kTypeProperty,
&vpn_provider_type);
success &= !vpn_provider_type.empty();
dest->SetStringWithoutPathExpansion(shill::kProviderTypeProperty,
vpn_provider_type);
std::string vpn_provider_host;
provider_properties->GetStringWithoutPathExpansion(shill::kHostProperty,
&vpn_provider_host);
success &= !vpn_provider_host.empty();
dest->SetStringWithoutPathExpansion(shill::kProviderHostProperty,
vpn_provider_host);
} else if (type == shill::kTypeEthernet || type == shill::kTypeEthernetEap) {
} else {
NOTREACHED() << "Unsupported network type " << type;
success = false;
}
if (!success) {
NET_LOG_ERROR("Missing required properties",
GetNetworkIdFromProperties(service_properties));
}
return success;
}
bool DoIdentifyingPropertiesMatch(const base::DictionaryValue& properties_a,
const base::DictionaryValue& properties_b) {
base::DictionaryValue identifying_a;
if (!CopyIdentifyingProperties(properties_a, &identifying_a))
return false;
base::DictionaryValue identifying_b;
if (!CopyIdentifyingProperties(properties_b, &identifying_b))
return false;
return identifying_a.Equals(&identifying_b);
}
bool IsPassphraseKey(const std::string& key) {
return key == shill::kEapPrivateKeyPasswordProperty ||
key == shill::kEapPasswordProperty ||
key == shill::kL2tpIpsecPasswordProperty ||
key == shill::kOpenVPNPasswordProperty ||
key == shill::kOpenVPNAuthUserPassProperty ||
key == shill::kOpenVPNTLSAuthContentsProperty ||
key == shill::kPassphraseProperty ||
key == shill::kOpenVPNOTPProperty ||
key == shill::kEapPrivateKeyProperty ||
key == shill::kEapPinProperty ||
key == shill::kApnPasswordProperty;
}
}
namespace {
const char kPatternDefault[] = "PatternDefault";
const char kPatternEthernet[] = "PatternEthernet";
const char kPatternWireless[] = "PatternWireless";
const char kPatternMobile[] = "PatternMobile";
const char kPatternNonVirtual[] = "PatternNonVirtual";
enum NetworkTypeBitFlag {
kNetworkTypeNone = 0,
kNetworkTypeEthernet = 1 << 0,
kNetworkTypeWifi = 1 << 1,
kNetworkTypeWimax = 1 << 2,
kNetworkTypeCellular = 1 << 3,
kNetworkTypeVPN = 1 << 4,
kNetworkTypeEthernetEap = 1 << 5,
kNetworkTypeBluetooth = 1 << 6
};
struct ShillToBitFlagEntry {
const char* shill_network_type;
NetworkTypeBitFlag bit_flag;
} shill_type_to_flag[] = {
{ shill::kTypeEthernet, kNetworkTypeEthernet },
{ shill::kTypeEthernetEap, kNetworkTypeEthernetEap },
{ shill::kTypeWifi, kNetworkTypeWifi },
{ shill::kTypeWimax, kNetworkTypeWimax },
{ shill::kTypeCellular, kNetworkTypeCellular },
{ shill::kTypeVPN, kNetworkTypeVPN },
{ shill::kTypeBluetooth, kNetworkTypeBluetooth }
};
NetworkTypeBitFlag ShillNetworkTypeToFlag(const std::string& shill_type) {
for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
if (shill_type_to_flag[i].shill_network_type == shill_type)
return shill_type_to_flag[i].bit_flag;
}
NET_LOG_ERROR("ShillNetworkTypeToFlag", "Unknown type: " + shill_type);
return kNetworkTypeNone;
}
}
NetworkTypePattern NetworkTypePattern::Default() {
return NetworkTypePattern(~0);
}
NetworkTypePattern NetworkTypePattern::Wireless() {
return NetworkTypePattern(kNetworkTypeWifi | kNetworkTypeWimax |
kNetworkTypeCellular);
}
NetworkTypePattern NetworkTypePattern::Mobile() {
return NetworkTypePattern(kNetworkTypeCellular | kNetworkTypeWimax);
}
NetworkTypePattern NetworkTypePattern::NonVirtual() {
return NetworkTypePattern(~kNetworkTypeVPN);
}
NetworkTypePattern NetworkTypePattern::Ethernet() {
return NetworkTypePattern(kNetworkTypeEthernet);
}
NetworkTypePattern NetworkTypePattern::WiFi() {
return NetworkTypePattern(kNetworkTypeWifi);
}
NetworkTypePattern NetworkTypePattern::Cellular() {
return NetworkTypePattern(kNetworkTypeCellular);
}
NetworkTypePattern NetworkTypePattern::VPN() {
return NetworkTypePattern(kNetworkTypeVPN);
}
NetworkTypePattern NetworkTypePattern::Wimax() {
return NetworkTypePattern(kNetworkTypeWimax);
}
NetworkTypePattern NetworkTypePattern::Primitive(
const std::string& shill_network_type) {
return NetworkTypePattern(ShillNetworkTypeToFlag(shill_network_type));
}
bool NetworkTypePattern::Equals(const NetworkTypePattern& other) const {
return pattern_ == other.pattern_;
}
bool NetworkTypePattern::MatchesType(
const std::string& shill_network_type) const {
return MatchesPattern(Primitive(shill_network_type));
}
bool NetworkTypePattern::MatchesPattern(
const NetworkTypePattern& other_pattern) const {
if (Equals(other_pattern))
return true;
return pattern_ & other_pattern.pattern_;
}
std::string NetworkTypePattern::ToDebugString() const {
if (Equals(Default()))
return kPatternDefault;
if (Equals(Ethernet()))
return kPatternEthernet;
if (Equals(Wireless()))
return kPatternWireless;
if (Equals(Mobile()))
return kPatternMobile;
if (Equals(NonVirtual()))
return kPatternNonVirtual;
std::string str;
for (size_t i = 0; i < arraysize(shill_type_to_flag); ++i) {
if (!(pattern_ & shill_type_to_flag[i].bit_flag))
continue;
if (!str.empty())
str += "|";
str += shill_type_to_flag[i].shill_network_type;
}
return str;
}
NetworkTypePattern::NetworkTypePattern(int pattern) : pattern_(pattern) {}
}