Mercurial > Pritunl-Fake-API
comparison www/index.php @ 0:b51518614818 default tip
New Files
author | Pluto <meokcin@gmail.com> |
---|---|
date | Tue, 03 Sep 2024 15:57:25 +0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b51518614818 |
---|---|
1 <?php | |
2 // Author: simonmicro 2023 | |
3 | |
4 // Config | |
5 $minVersionNumber = 1003235044068; | |
6 $minVersionName = '1.32.3504.68'; | |
7 $minVersionIgnored = false; // use this to ignore the min version check - used for the public endpoint to avoid breaking too many clients at once | |
8 $licenseCosts = 42; // insert here any price you want - "0" is a special value, which also breaks the UI ;) | |
9 | |
10 header('Access-Control-Allow-Origin: *'); //Allow access from everywhere... | |
11 $code = 200; // Assuming everything is fine for now | |
12 | |
13 // Check if a ".ignoreMinVersion" file exists | |
14 if(!$minVersionIgnored && file_exists('.ignoreMinVersion')) { | |
15 $minVersionIgnored = true; // If so, we ignore the min version check | |
16 } | |
17 | |
18 // Parse body (if possible) | |
19 $body = json_decode(file_get_contents('php://input')); | |
20 $clientVersion = isset($body->version) ? $body->version : null; | |
21 | |
22 // Fake API | |
23 $result = null; | |
24 if (version_compare(PHP_VERSION, '8.0.0', '<')) { | |
25 $result = array('error_msg' => 'This API only supports PHP 8 or higher.'); | |
26 $code = 500; | |
27 } else if(isset($_GET['path'])) { | |
28 $path = trim($_GET['path'], ' /'); | |
29 $pathParts = explode('/', $path); | |
30 if(count($pathParts) > 0 && $pathParts[0] == 'healthz') { | |
31 $result = 'OK'; | |
32 } else if(count($pathParts) > 0 && $pathParts[0] == 'notification') { | |
33 // Any notification/[version] will be answered here | |
34 $msg = 'Fake API endpoint for v' . $minVersionName . ' active and reachable (contacted at ' . date('r') . ').'; | |
35 if(intval($pathParts[1]) < $minVersionNumber) { | |
36 $msg .= ' Please update your Pritunl instance to a newer version as this endpoint may not compatible anymore.'; | |
37 } | |
38 $result = array( | |
39 'message' => $msg, | |
40 'vpn' => false, // idk | |
41 'www' => false // idk | |
42 ); | |
43 } else if(count($pathParts) > 0 && $pathParts[0] == 'auth') { | |
44 $result = array('error_msg' => 'Sorry, but SSO is currently not supported.'); | |
45 $code = 401; // Let Pritunl fail, without 500 codes (it will show 405) | |
46 } else if(count($pathParts) > 0 && $pathParts[0] == 'ykwyhd') { | |
47 // The "you-know-what-you-have-done" endpoint -> used as dummy url target | |
48 $result = array('detail' => 'You know what you have done.'); | |
49 } else if(!$minVersionIgnored && $clientVersion != null && $clientVersion < $minVersionNumber) { | |
50 // Check if the instance is too old for us (for now following operators) | |
51 $result = array('error_msg' => 'This API supports v' . $minVersionName . ' (' . $minVersionNumber . ') or higher.'); | |
52 $code = 473; | |
53 } else if(count($pathParts) > 0 && $pathParts[0] == 'subscription') { | |
54 // The following only works with the body containing the desired license | |
55 if(isset($body->license)) { | |
56 $license = null; | |
57 $user = md5(base64_encode($body->license)); | |
58 $url_key = substr($user, 0, 8); | |
59 $input = strtolower($body->license); | |
60 | |
61 // The stylesheet determines what is shown on the dashboard (and by the plan). | |
62 $stylesheet = ''; | |
63 if(str_contains($input, 'premium')) { | |
64 $license = 'premium'; | |
65 $stylesheet = file_get_contents('premium.css'); | |
66 // No need to install the user license "id" into CSS class, as that file only contains custom patches | |
67 } else if(str_contains($input, 'enterprise')) { | |
68 $license = 'enterprise'; | |
69 $stylesheet = file_get_contents('enterprise.css'); | |
70 $stylesheet = preg_replace('/(\.enterprise)([\.\ ])/', '$1-'.$url_key.'$2', $stylesheet); // Install user license "id" into CSS class | |
71 } else if(str_contains($input, 'ultimate')) { | |
72 $license = 'enterprise_plus'; | |
73 $stylesheet = file_get_contents('enterprise_plus.css'); | |
74 $stylesheet = preg_replace('/(\.enterprise-plus)([\.\ ])/', '$1-'.$url_key.'$2', $stylesheet); // Install user license "id" into CSS class | |
75 } | |
76 $stylesheet .= "\n/* custom.css */\n"; | |
77 $stylesheet .= str_replace('BACKGROUND_IMAGE_URI', "https://" . $_SERVER['HTTP_HOST'] . "/logo.png", file_get_contents('custom.css')); | |
78 $stylesheet .= "\n/* Generated for $license license */"; | |
79 | |
80 $state = null; | |
81 if($license) { // The following only makes sense if you selected any license | |
82 if(str_starts_with($input, 'bad')) { | |
83 $state = 'Bad'; | |
84 } else if(str_starts_with($input, 'canceled')) { | |
85 $state = 'canceled'; | |
86 } else if(str_starts_with($input, 'active')) { | |
87 $state = 'Active'; | |
88 } | |
89 } | |
90 | |
91 if($state == 'Active') { | |
92 $result = array( | |
93 'active' => true, // if the sub is not active, the css won't use the LICENSE-subscription_id pattern | |
94 'status' => $state, | |
95 'plan' => $license, | |
96 'url_key' => $user, | |
97 'quantity' => 42, | |
98 'amount' => $licenseCosts, | |
99 'credit' => 42, | |
100 'period_end' => false, | |
101 'trial_end' => false, | |
102 'cancel_at_period_end' => false, | |
103 'premium_buy_url' => 'https://' . $_SERVER['HTTP_HOST'] . '/ykwyhd/', | |
104 'enterprise_buy_url' => 'https://' . $_SERVER['HTTP_HOST'] . '/ykwyhd/', | |
105 'portal_url' => 'https://' . $_SERVER['HTTP_HOST'] . '/ykwyhd/', | |
106 'styles' => array( | |
107 'etag' => null, // the resource is NOT encrypted | |
108 'last_modified' => time(), | |
109 'data' => $stylesheet | |
110 ) | |
111 ); | |
112 } else if($state == 'Canceled') { | |
113 $result = array( | |
114 'active' => false, // Here we can savely disable any style | |
115 'status' => $state, | |
116 'plan' => $license, | |
117 'quantity' => 42, | |
118 'amount' => 42, | |
119 'period_end' => false, | |
120 'trial_end' => false, | |
121 'cancel_at_period_end' => false, | |
122 'styles' => array( | |
123 'etag' => null, | |
124 'last_modified' => null, | |
125 'data' => null | |
126 ) | |
127 ); | |
128 } else if($state == 'Bad' || $state == null) { | |
129 $code = 470; // -> bad license | |
130 // Do not mention "canceled" in "error_msg", as it is somewhat useless (same as bad)... | |
131 $result = array( | |
132 'error' => 'license_invalid', | |
133 'error_msg' => $state == null ? 'Unknown command. Use ["bad" | "active"] ["premium" | "enterprise" | "ultimate"].' : 'As you wish.', | |
134 'active' => false, | |
135 'status' => null, | |
136 'plan' => null, | |
137 'quantity' => null, | |
138 'amount' => null, | |
139 'period_end' => null, | |
140 'trial_end' => null, | |
141 'cancel_at_period_end' => null, | |
142 'styles' => array( | |
143 'etag' => null, | |
144 'last_modified' => null, | |
145 'data' => null | |
146 ) | |
147 ); | |
148 } | |
149 } else { | |
150 $result = array('error_msg' => 'Missing license in body.'); | |
151 $code = 401; | |
152 } | |
153 } else if(count($pathParts) > 0 && $pathParts[0] == 'checkout') { | |
154 $result = array( | |
155 'zipCode' => false, | |
156 'allowRememberMe' => false, | |
157 'image' => 'https://' . $_SERVER['HTTP_HOST'] . '/logo.png', | |
158 'key' => null, // Insert here a key to unlock the stripe store (is a string). And buy the subscription... | |
159 'plans' => array( | |
160 'premium' => array( | |
161 'amount' => $licenseCosts | |
162 ), | |
163 'enterprise' => array( | |
164 'amount' => $licenseCosts | |
165 ), | |
166 'enterprise_plus' => array( | |
167 'amount' => $licenseCosts | |
168 ) | |
169 ) | |
170 ); | |
171 } | |
172 } | |
173 | |
174 header('Content-Type: application/json'); | |
175 http_response_code($code); | |
176 echo json_encode($result); | |
177 | |
178 // Should we log any request? Used for the development and debugging of this API | |
179 if(false) { | |
180 // Log request | |
181 file_put_contents('access.log', "\n" . date('r') . ":\n" . json_encode(array('head' => getallheaders(), 'body' => file_get_contents('php://input'), 'get' => $_GET, 'post' => $_POST, 'answer_code' => $code, 'answer' => $result)) . "\n", FILE_APPEND); | |
182 | |
183 // GET operator to clear log file | |
184 if(isset($_GET['clear'])) | |
185 file_put_contents('access.log', ''); | |
186 } | |
187 ?> |