mirror of
https://github.com/valitydev/osquery-1.git
synced 2024-11-07 18:08:53 +00:00
daf4e95948
Fix up `stringFromCFString` bug related to non ascii strings You could see it in wifi_networks table with Chinese network name for instance. ``` osquery> select network_name from wifi_networks; [ {"network_name":""}, ] ``` Should be something like: ``` osquery> select network_name from wifi_networks; [ {"network_name":"星期天"}, ] ``` The problem was in function `stringFromCFString`. It was designed to work only with ascii strings, which is wrong. So, I fixed it.
111 lines
3.3 KiB
C++
111 lines
3.3 KiB
C++
/**
|
|
* Copyright (c) 2014-present, Facebook, Inc.
|
|
* All rights reserved.
|
|
*
|
|
* This source code is licensed under both the Apache 2.0 license (found in the
|
|
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
|
|
* in the COPYING file in the root directory of this source tree).
|
|
* You may select, at your option, one of the above-listed licenses.
|
|
*/
|
|
|
|
#include <iomanip>
|
|
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include "osquery/core/conversions.h"
|
|
|
|
namespace osquery {
|
|
|
|
std::string stringFromCFString(const CFStringRef& cf_string) {
|
|
// Access, then convert the CFString. CFStringGetCStringPtr is less-safe.
|
|
auto const wlength = CFStringGetLength(cf_string);
|
|
auto const length =
|
|
CFStringGetMaximumSizeForEncoding(wlength, kCFStringEncodingUTF8);
|
|
if (length == kCFNotFound) {
|
|
return "";
|
|
}
|
|
auto result = std::string(length + 1, '\0');
|
|
// According to documentation: "if there is an error in conversion, the buffer
|
|
// contains only partial results". And because of that we don't need to check
|
|
// up the return value.
|
|
CFStringGetCString(
|
|
cf_string, &result.front(), result.size(), kCFStringEncodingUTF8);
|
|
result.resize(result.find('\0'));
|
|
return result;
|
|
}
|
|
|
|
std::string stringFromCFData(const CFDataRef& cf_data) {
|
|
CFRange range = CFRangeMake(0, CFDataGetLength(cf_data));
|
|
|
|
char* buffer = (char*)malloc(range.length + 1);
|
|
if (buffer == nullptr) {
|
|
return "";
|
|
}
|
|
memset(buffer, 0, range.length + 1);
|
|
|
|
std::stringstream result;
|
|
CFDataGetBytes(cf_data, range, (UInt8*)buffer);
|
|
for (CFIndex i = 0; i < range.length; ++i) {
|
|
uint8_t byte = buffer[i];
|
|
if (isprint(byte)) {
|
|
result << byte;
|
|
} else if (buffer[i] == 0) {
|
|
result << ' ';
|
|
} else {
|
|
result << '%' << std::setfill('0') << std::setw(2) << std::hex
|
|
<< (int)byte;
|
|
}
|
|
}
|
|
|
|
// Cleanup allocations.
|
|
free(buffer);
|
|
return result.str();
|
|
}
|
|
|
|
std::string stringFromCFNumber(const CFDataRef& cf_number) {
|
|
return stringFromCFNumber(cf_number, CFNumberGetType((CFNumberRef)cf_number));
|
|
}
|
|
|
|
std::string stringFromCFNumber(const CFDataRef& cf_number, CFNumberType type) {
|
|
// Make sure the type is a number.
|
|
if (CFGetTypeID(cf_number) != CFNumberGetTypeID()) {
|
|
return "0";
|
|
}
|
|
|
|
// Support a signed 64, a double, and treat everything else as a signed int.
|
|
if (type == kCFNumberSInt64Type) {
|
|
long long int value;
|
|
if (CFNumberGetValue((CFNumberRef)cf_number, type, &value)) {
|
|
return boost::lexical_cast<std::string>(value);
|
|
}
|
|
} else if (type == kCFNumberDoubleType) {
|
|
double value;
|
|
if (CFNumberGetValue((CFNumberRef)cf_number, type, &value)) {
|
|
return boost::lexical_cast<std::string>(value);
|
|
}
|
|
} else {
|
|
unsigned int value;
|
|
if (CFNumberGetValue((CFNumberRef)cf_number, type, &value)) {
|
|
return boost::lexical_cast<std::string>(value);
|
|
}
|
|
}
|
|
// Cast as a string.
|
|
return "0";
|
|
}
|
|
|
|
std::string stringFromCFAbsoluteTime(const CFDataRef& cf_abstime) {
|
|
double value;
|
|
if (CFNumberGetValue((CFNumberRef)cf_abstime, kCFNumberFloat64Type, &value)) {
|
|
// Add seconds difference between CFAbsoluteTime and UNIX times.
|
|
value += kCFAbsoluteTimeIntervalSince1970;
|
|
|
|
// Check if overflowed
|
|
if (value > 0) {
|
|
return boost::lexical_cast<std::string>(std::llround(value));
|
|
}
|
|
}
|
|
|
|
return "0";
|
|
}
|
|
}
|