osquery-1/osquery/core/darwin/conversions.cpp
2016-02-11 11:48:58 -08:00

113 lines
3.0 KiB
C++

/*
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#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.
CFIndex length = CFStringGetLength(cf_string);
char* buffer = (char*)malloc(length + 1);
if (buffer == nullptr) {
return "";
}
if (!CFStringGetCString(
cf_string, buffer, length + 1, kCFStringEncodingASCII)) {
free(buffer);
return "";
}
// Cleanup allocations.
std::string result(buffer);
free(buffer);
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, kCFNumberIntType);
}
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";
}
}