PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.14.2
Independent Analytics – WordPress Analytics Plugin v2.14.2
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / iawp-click-endpoint.php
independent-analytics Last commit date
IAWP 6 months ago dist 6 months ago freemius 7 months ago img 7 months ago javascript-source 6 months ago languages 6 months ago vendor 6 months ago views 6 months ago iawp-bootstrap.php 6 months ago iawp-click-endpoint.php 1 year ago iawp.php 6 months ago readme.txt 6 months ago
iawp-click-endpoint.php
193 lines
1 <?php
2
3 // Warning. This file is a standalone PHP file whose sole purpose is to sanitize input and store
4 // that input in a CSV for later processing. WordPress is not loaded and the classes from the
5 // plugin are not available.
6
7 class Cache
8 {
9 private $attributes;
10
11 public function __construct(array $attributes)
12 {
13 $this->attributes = $attributes;
14 }
15
16 public function is_pro(): bool
17 {
18 return $this->attributes['is_pro'] === true;
19 }
20
21 public function avoid_temporary_directory(): bool
22 {
23 return $this->attributes['avoid_temporary_directory'] === true;
24 }
25
26 public function get_upload_directory(): string
27 {
28 return trim($this->attributes['upload_directory']);
29 }
30
31 public function get_custom_ip_header(): ?string
32 {
33 if (array_key_exists('custom_ip_header', $this->attributes)) {
34 return trim($this->attributes['custom_ip_header']);
35 }
36
37 return null;
38 }
39
40 public function get_visitor_token_salt(): string
41 {
42 return trim($this->attributes['visitor_token_salt']);
43 }
44 }
45
46 function get_cache(): ?Cache
47 {
48 $file = __DIR__ . "/iawp-click-config.php";
49
50 if (!is_readable($file)) {
51 return null;
52 }
53
54 $contents = file_get_contents($file);
55
56 if (false === $contents) {
57 return null;
58 }
59
60 $lines = explode("\n", $contents);
61
62 if (count($lines) !== 2) {
63 return null;
64 }
65
66 $json = trim($lines[1]);
67 $data = json_decode($json, true);
68
69 if (is_null($data)) {
70 return null;
71 }
72
73 return new Cache($data);
74
75 }
76
77 function get_ip_address(Cache $cache): ?string
78 {
79 if (defined('IAWP_TEST_IP')) {
80 return IAWP_TEST_IP;
81 }
82
83 $headers = [
84 'HTTP_X_FORWARDED_FOR',
85 'HTTP_X_FORWARDED',
86 'HTTP_FORWARDED_FOR',
87 'HTTP_FORWARDED',
88 'REMOTE_ADDR',
89 'HTTP_CF_CONNECTING_IP',
90 'HTTP_CLIENT_IP',
91 'HTTP_INCAP_CLIENT_IP',
92 'HTTP_CF_CONNECTING_IP',
93 ];
94
95 if (is_string($cache->get_custom_ip_header())) {
96 array_unshift($headers, $cache->get_custom_ip_header());
97 }
98
99 foreach ($headers as $header) {
100 if (isset($_SERVER[$header])) {
101 return explode(',', $_SERVER[$header])[0];
102 }
103 }
104
105 return null;
106 }
107
108 function get_visitor_token(Cache $cache): ?string
109 {
110 return md5($cache->get_visitor_token_salt() . get_ip_address($cache) . $_SERVER['HTTP_USER_AGENT']);
111 }
112
113 function trailing_slash(string $path): string
114 {
115 $path = rtrim($path, '/\\');
116
117 return $path . DIRECTORY_SEPARATOR;
118 }
119
120 /**
121 * Get the path to the click data file and create it if needed.
122 *
123 * @return string
124 */
125 function get_click_data_file(Cache $cache): string
126 {
127 if (!$cache->avoid_temporary_directory()) {
128 $text_file = trailing_slash(sys_get_temp_dir()) . "iawp-click-data.txt";
129
130 if (is_file($text_file) && is_readable($text_file) && is_writable($text_file)) {
131 return $text_file;
132 }
133
134 if (file_put_contents($text_file, "") !== false && file_get_contents($text_file) !== false) {
135 return $text_file;
136 }
137 }
138
139 $php_file = trailing_slash(__DIR__) . "iawp-click-data.php";
140
141 if (is_file($php_file)) {
142 return $php_file;
143 }
144
145 if (file_put_contents($php_file, "<?php exit; ?>\n") !== false) {
146 return $php_file;
147 }
148
149 // Unable to create either data file so there's nowhere to store the click data
150 exit;
151 }
152
153 $cache = get_cache();
154
155 if (is_null($cache) || is_null(get_ip_address($cache))) {
156 exit;
157 }
158
159 if (!$cache->is_pro()) {
160 exit;
161 }
162
163 $json_body = file_get_contents('php://input');
164 $body = json_decode($json_body, true);
165
166 if (is_null($body)) {
167 exit;
168 }
169
170 $click_data_file = get_click_data_file($cache);
171 $data = [
172 'href' => $body['href'],
173 'classes' => $body['classes'],
174 'ids' => $body['ids'],
175 'payload' => json_encode($body['payload']),
176 'signature' => $body['signature'],
177 'visitor_token' => get_visitor_token($cache),
178 'created_at' => time(),
179 ];
180
181 if (!is_readable($click_data_file) || !is_writable($click_data_file)) {
182 exit;
183 }
184
185 $file_resource = fopen($click_data_file, 'a');
186
187 if (false === $file_resource) {
188 exit;
189 }
190
191 fwrite($file_resource, json_encode($data) . "\n");
192 fclose($file_resource);
193