TEST_F(PlistTests, test_parse_plist_content) { // Isolate plist parsing errors to the plist parser, instead of file reader. std::string content; readFile(kTestDataPath + "test.plist", content); pt::ptree tree; auto s = parsePlistContent(content, tree); EXPECT_TRUE(s.ok()); EXPECT_EQ(s.toString(), "OK"); // Check the specifics of the PLIST. EXPECT_EQ(tree.get<bool>("Disabled"), true); EXPECT_THROW(tree.get<bool>("foobar"), pt::ptree_bad_path); EXPECT_EQ(tree.get<std::string>("Label"), "com.apple.FileSyncAgent.sshd"); std::vector<std::string> program_arguments = { "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd-keygen-wrapper", "-i", "-f", "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd_config", }; pt::ptree program_arguments_tree = tree.get_child("ProgramArguments"); std::vector<std::string> program_arguments_parsed; for (const auto& argument : program_arguments_tree) { program_arguments_parsed.push_back(argument.second.get<std::string>("")); } EXPECT_EQ(program_arguments_parsed, program_arguments); }
TEST_F(PlistBenchmark, bench_parse_plist_content) { // using LOG(ERROR) as a quick hack so that gtest displays the log line even // when the test passes LOG(ERROR) << "Starting: " << getAsciiTime(); LOG(ERROR) << "Performing " << FLAGS_iterations << " iterations"; int time = getUnixTime(); for (int i = 0; i < FLAGS_iterations; ++i) { std::string content = getPlistContent(); pt::ptree tree; auto s = parsePlistContent(content, tree); EXPECT_TRUE(s.ok()); EXPECT_EQ(s.toString(), "OK"); EXPECT_EQ(tree.get<bool>("Disabled"), true); EXPECT_THROW(tree.get<bool>("foobar"), pt::ptree_bad_path); EXPECT_EQ(tree.get<std::string>("Label"), "com.apple.FileSyncAgent.sshd"); std::vector<std::string> program_arguments = { "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd-keygen-wrapper", "-i", "-f", "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd_config", }; pt::ptree program_arguments_tree = tree.get_child("ProgramArguments"); std::vector<std::string> program_arguments_parsed; for (const auto& argument : program_arguments_tree) { program_arguments_parsed.push_back(argument.second.get<std::string>("")); } EXPECT_EQ(program_arguments_parsed, program_arguments); } LOG(ERROR) << "Ending: " << getAsciiTime(); LOG(ERROR) << "Benchmark executed in " << (getUnixTime() - time) << " seconds"; }
pt::ptree getALFTree() { std::string content; readFile(kTestDataPath + "test_alf.plist", content); pt::ptree tree; parsePlistContent(content, tree); return tree; }
static void PLIST_parse_content(benchmark::State& state) { // Buffer the plist content into memory. std::string content; readFile(kTestDataPath + "test.plist", content); while (state.KeepRunning()) { pt::ptree tree; auto status = parsePlistContent(content, tree); } }
void genQuicklookRow(sqlite3_stmt* stmt, Row& r) { for (int i = 0; i < sqlite3_column_count(stmt); i++) { auto column_name = std::string(sqlite3_column_name(stmt, i)); auto column_type = sqlite3_column_type(stmt, i); if (column_type == SQLITE_TEXT) { auto value = sqlite3_column_text(stmt, i); if (value != nullptr) { r[column_name] = std::string((const char*)value); } } else if (column_type == SQLITE_INTEGER) { // Handle INTEGER columns explicitly to handle the date-value offset. auto value = sqlite3_column_int(stmt, i); if (column_name == "last_hit_date") { value += kReferenceDateOffset; } r[column_name] = INTEGER(value); } else if (column_type == SQLITE_BLOB) { // Handle BLOB values explicitly to avoid the default char* termination // for binary-plist data. auto getField = [](const pt::ptree& tree, const std::string& field) { if (field == "mtime" && tree.count(field) > 0) { // Apply a special case for embedded date-value fields. return INTEGER(tree.get<size_t>(field) + kReferenceDateOffset); } return (tree.count(field) > 0) ? tree.get<std::string>(field) : ""; }; if (column_name == "version") { pt::ptree tree; auto version = std::string((const char*)sqlite3_column_blob(stmt, i), sqlite3_column_bytes(stmt, i)); if (parsePlistContent(version, tree)) { r["mtime"] = getField(tree, "date"); r["size"] = getField(tree, "size"); r["label"] = getField(tree, "gen"); } } } } // Transform the folder/file_name into an aggregate path. r["path"] = std::move(r["folder"]) + "/" + std::move(r["file_name"]); r.erase("folder"); r.erase("file_name"); // Transform the encoded fs_id. auto details = osquery::split(r["fs_id"], "=."); if (details.size() == 4) { r["volume_id"] = details[2]; r["inode"] = details[3]; } }
inline void genSafariExtension(const std::string& path, QueryData& results) { Row r; r["path"] = path; // Loop through (Plist key -> table column name) in kSafariExtensionKeys. struct archive* ext = archive_read_new(); if (ext == nullptr) { return; } // Use open_file, instead of the preferred open_filename for OS X 10.9. archive_read_support_format_xar(ext); if (archive_read_open_file(ext, path.c_str(), 10240) != ARCHIVE_OK) { archive_read_finish(ext); return; } struct archive_entry* entry = nullptr; while (archive_read_next_header(ext, &entry) == ARCHIVE_OK) { auto item_path = archive_entry_pathname(entry); // Documentation for libarchive mentions these APIs may return NULL. if (item_path == nullptr) { archive_read_data_skip(ext); continue; } // Assume there is no non-root Info. if (std::string(item_path).find("Info.plist") == std::string::npos) { archive_read_data_skip(ext); continue; } // Read the decompressed Info.plist content. auto content = std::string(archive_entry_size(entry), '\0'); archive_read_data_into_buffer(ext, &content[0], content.size()); // If the Plist can be parsed, extract important keys into columns. pt::ptree tree; if (parsePlistContent(content, tree).ok()) { for (const auto& it : kSafariExtensionKeys) { r[it.second] = tree.get(it.first, ""); } } break; } archive_read_close(ext); archive_read_finish(ext); results.push_back(std::move(r)); }
TEST_F(PlistTests, test_parse_plist_content) { std::string content = getPlistContent(); pt::ptree tree; auto s = parsePlistContent(content, tree); EXPECT_TRUE(s.ok()); EXPECT_EQ(s.toString(), "OK"); EXPECT_EQ(tree.get<bool>("Disabled"), true); EXPECT_THROW(tree.get<bool>("foobar"), pt::ptree_bad_path); EXPECT_EQ(tree.get<std::string>("Label"), "com.apple.FileSyncAgent.sshd"); std::vector<std::string> program_arguments = { "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd-keygen-wrapper", "-i", "-f", "/System/Library/CoreServices/FileSyncAgent.app/Contents/Resources/" "FileSyncAgent_sshd_config", }; pt::ptree program_arguments_tree = tree.get_child("ProgramArguments"); std::vector<std::string> program_arguments_parsed; for (const auto& argument : program_arguments_tree) { program_arguments_parsed.push_back(argument.second.get<std::string>("")); } EXPECT_EQ(program_arguments_parsed, program_arguments); }