prod/native/loader/code/phpdetection.cpp (73 lines of code) (raw):

/* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright * ownership. Elasticsearch B.V. licenses this file to you under * the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "phpdetection.h" #include <dlfcn.h> namespace elasticapm::loader { std::string_view getMajorMinorVersion(std::string_view version) { auto lastDot = version.find_last_of('.'); if (lastDot == std::string_view::npos) { return version; } return version.substr(0, lastDot); } std::string_view getZendVersionString() { using get_zend_version_t = char *(*)(void); get_zend_version_t get_zend_version = reinterpret_cast<get_zend_version_t>(dlsym(RTLD_DEFAULT, "get_zend_version")); if (!get_zend_version) { return {}; } const char *zendVersion = get_zend_version(); if (!zendVersion) { return {}; } return zendVersion; } std::string_view getZendVersion(std::string_view zendVersion) { using namespace std::string_view_literals; static constexpr std::string_view prefix = "Zend Engine v"sv; if (!zendVersion.starts_with(prefix)) { return {}; } std::string_view version = zendVersion.substr(prefix.length(), zendVersion.find_first_of(',') - prefix.length()); return version; } std::string_view getMajorMinorZendVersion() { auto zendVersion = getZendVersion(getZendVersionString()); if (zendVersion.empty()) { return {}; } return getMajorMinorVersion(zendVersion); } bool isThreadSafe() { void *coreGlobals = dlsym(RTLD_DEFAULT, "core_globals"); return !coreGlobals; } std::tuple<std::string_view, int, int, bool> getZendModuleApiVersion(std::string_view zendVersion) { using namespace std::string_view_literals; constexpr size_t knownVersionsCount = 17; // zendEngineVersion, phpVersion, zendModuleApiVersion, isVersionSupported constexpr std::array<std::tuple<std::string_view, int, int, bool>, knownVersionsCount> knownPhpVersions{{ {"4.4"sv, 84, 20240924, true}, // PHP 8.4 {"4.3"sv, 83, 20230831, true}, // PHP 8.3 {"4.2"sv, 82, 20220829, true}, // PHP 8.2 {"4.1"sv, 81, 20210902, true}, // PHP 8.1 {"4.0"sv, 80, 20200930, false}, // PHP 8.0 {"3.4"sv, 74, 20190902, false}, // PHP 7.4 {"3.3"sv, 73, 20180731, false}, // PHP 7.3 {"3.2"sv, 72, 20170718, false}, // PHP 7.2 {"3.1"sv, 71, 20160303, false}, // PHP 7.1 {"3.0"sv, 70, 20151012, false}, // PHP 7.0 {"2.6"sv, 56, 20131226, false}, // PHP 5.6 {"2.5"sv, 55, 20121212, false}, // PHP 5.5 {"2.4"sv, 54, 20100525, false}, // PHP 5.4 {"2.3"sv, 53, 20090626, false}, // PHP 5.3 {"2.2"sv, 52, 20060613, false}, // PHP 5.2 {"2.1"sv, 51, 20050922, false}, // PHP 5.1 {"2.0"sv, 50, 20041030, false} // PHP 5.0 }}; auto foundPhpVersion = std::find_if(std::begin(knownPhpVersions), std::end(knownPhpVersions), [zendVersion](std::tuple<std::string_view, int, int, bool> const &entry) { return std::get<0>(entry) == zendVersion; }); if (foundPhpVersion == std::end(knownPhpVersions)) { return {zendVersion, 0, 0, false}; } return *foundPhpVersion; } }