forked from elastic/elastic-otel-php
-
Notifications
You must be signed in to change notification settings - Fork 0
/
phpdetection.cpp
115 lines (92 loc) · 3.79 KB
/
phpdetection.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
* 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;
}
}