· 6 years ago · Feb 04, 2020, 10:52 AM
1<?php
2
3header('Access-Control-Allow-Origin: *');
4header('Content-Type: application/javascript');
5// Query params are:
6
7//require_once dirname(__FILE__) . '/kclick_client.php';
8$client = new KClickClient('https://golden-club.top/api.php?', 'vfqmrct5gjtsgfrzvzg9chsrcgvmvspq');
9$client->sendAllParams(); // to send all params from page query
10$client->forceRedirectOffer(); // redirect to offer if an offer is chosen
11// $client->param('sub_id_5', '123'); // you can send any params
12$client->param('frm', 'script'); // you can send any params
13// $client->keyword('PASTE_KEYWORD'); // send custom keyword
14// $client->currentPageAsReferrer(); // to send current page URL as click referrer
15// $client->debug(); // to enable debug mode and show the errors
16// $client->execute(); // request to api, show the output and continue
17$client->executeAndBreak(); // to stop page execution if there is redirect or some output
18
19
20
21/**
22 * Usage:
23 * require_once 'kclick_client.php';
24 * $client = new KClickClient('http://tds.com/api.php', 'CAMPAIGN_TOKEN');
25 * $client->sendUtmLabels(); # send only utm labels
26 * $client->sendAllParams(); # send all params
27 * $client
28 * ->keyword('[KEYWORD]')
29 * ->execute(); # use executeAndBreak() to break the page execution if there is redirect or some output
30 *
31 */
32class KClickClient
33{
34 const SESSION_SUB_ID = 'sub_id';
35 const SESSION_LANDING_TOKEN = 'landing_token';
36 /** @version 3.5 **/
37 const VERSION = 3;
38 const STATE_SESSION_KEY = 'keitaro_state';
39 const STATE_SESSION_EXPIRES_KEY = 'keitaro_state_expires';
40 const DEFAULT_TTL = 1;
41 /**
42 * @var KHttpClient
43 */
44 private $_httpClient;
45 private $_debug = false;
46 private $_trackerUrl;
47 private $_params = array();
48 private $_log = array();
49 private $_excludeParams = array('api_key', 'token', 'language', 'ua', 'ip', 'referrer', 'force_redirect_offer');
50 private $_result;
51 private $_stateRestored;
52
53 const ERROR = '[KTrafficClient] Something is wrong. Enable debug mode to see the reason.';
54
55 public function __construct($trackerUrl, $token)
56 {
57 $this->trackerUrl($trackerUrl);
58 $this->campaignToken($token);
59 $this->version(self::VERSION);
60 $this->param('info', 1);
61 $this->fillParams();
62 }
63
64 public function fillParams()
65 {
66 $referrer = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
67 $this->setHttpClient(new KHttpClient());
68
69 $this->ip($this->_findIp())
70 ->ua(isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null)
71 ->language((isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2) : ''))
72 ->seReferrer($referrer)
73 ->referrer($referrer)
74 ->param('original_headers', getallheaders())
75 ->param('original_host', isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost')
76 ->param('kversion', '3.4');
77
78 if ($this->isPrefetchDetected()) {
79 $this->param('prefetch', 1);
80 }
81 }
82
83 public function currentPageAsReferrer()
84 {
85 $this->referrer($this->_getCurrentPage());
86 return $this;
87 }
88
89 public function debug($state = true)
90 {
91 $this->_debug = $state;
92 return $this;
93 }
94
95 public function seReferrer($seReferrer)
96 {
97 $this->_params['se_referrer'] = $seReferrer;
98 return $this;
99 }
100
101 public function referrer($referrer)
102 {
103 $this->_params['referrer'] = $referrer;
104 return $this;
105 }
106
107 public function setHttpClient($httpClient)
108 {
109 $this->_httpClient = $httpClient;
110 return $this;
111 }
112
113 public function trackerUrl($name)
114 {
115 $this->_trackerUrl = $name;
116 }
117
118 // @deprecated
119 public function token($token)
120 {
121 return $this->campaignToken($token);
122 }
123
124 public function campaignToken($campaignToken)
125 {
126 $this->_params['token'] = $campaignToken;
127 return $this;
128 }
129 public function version($version)
130 {
131 $this->_params['version'] = $version;
132 return $this;
133 }
134
135 public function ua($ua)
136 {
137 $this->_params['ua'] = $ua;
138 return $this;
139 }
140
141 public function language($language)
142 {
143 $this->_params['language'] = $language;
144 return $this;
145 }
146
147 public function keyword($keyword)
148 {
149 $this->_params['keyword'] = $keyword;
150 return $this;
151 }
152
153 public function forceRedirectOffer()
154 {
155 $this->_params['force_redirect_offer'] = 1;
156 }
157
158 public function ip($ip)
159 {
160 $this->_params['ip'] = $ip;
161 return $this;
162 }
163
164 public function sendUtmLabels()
165 {
166 foreach ($_GET as $name => $value) {
167 if (strstr($name, 'utm_')) {
168 $this->_params[$name] = $value;
169 }
170 }
171 }
172
173 public function setLandingToken($token)
174 {
175 $this->_startSession();
176 $_SESSION['token'] = $token;
177 }
178
179 public function getSubId()
180 {
181 $result = $this->performRequest();
182 if (empty($result->info->sub_id)) {
183 $this->log('No sub_id is defined');
184 return 'no_subid';
185 }
186 $subId = $result->info->sub_id;
187 return $subId;
188 }
189
190 public function getToken()
191 {
192 $result = $this->performRequest();
193 if (empty($result->info->sub_id)) {
194 $this->log('No landing token is defined');
195 return 'no_token';
196 }
197 $subId = $result->info->token;
198 return $subId;
199 }
200
201 public function sendAllParams()
202 {
203 foreach ($_GET as $name => $value) {
204 if (empty($this->_params[$name]) && !in_array($name, $this->_excludeParams)) {
205 $this->_params[$name] = $value;
206 }
207 }
208 }
209
210 public function restoreFromSession()
211 {
212 if ($this->isStateRestored()) {
213 return;
214 }
215 $this->_startSession();
216 if (!empty($_SESSION[self::STATE_SESSION_KEY])) {
217 if ($_SESSION[self::STATE_SESSION_EXPIRES_KEY] < time()) {
218 unset($_SESSION[self::STATE_SESSION_KEY]);
219 unset($_SESSION[self::STATE_SESSION_EXPIRES_KEY]);
220 $this->log('State expired');
221 } else {
222 $this->_result = json_decode($_SESSION[self::STATE_SESSION_KEY], false);
223 if (isset($this->_result) && isset($this->_result->headers)) {
224 $this->_result->headers = array();
225 }
226 $this->_stateRestored = true;
227 $this->log('State restored');
228 }
229 }
230 }
231
232 public function restoreFromQuery()
233 {
234 if (isset($_GET['_subid'])) {
235 $this->_stateRestored = true;
236 if (empty($this->_result)) {
237 $this->_result = new StdClass();
238 $this->_result->info = new StdClass();
239 }
240 $this->_result->info->sub_id = $_GET['_subid'];
241 $this->log('SubId loaded from query');
242 if (isset($_GET['_token'])) {
243 $this->_result->info->token = $_GET['_token'];
244 $this->log('Landing token loaded from query');
245 }
246 $this->_storeState($this->_result, self::DEFAULT_TTL);
247 $this->_stateRestored = true;
248 }
249 }
250
251 public function isStateRestored()
252 {
253 return $this->_stateRestored;
254 }
255
256 public function isPrefetchDetected()
257 {
258 $checkServerParams = array('HTTP_X_PURPOSE' => 'preview', 'HTTP_X_MOZ' => 'prefetch', 'HTTP_X_FB_HTTP_ENGINE' => 'Liger');
259 foreach ($checkServerParams as $name => $value) {
260 if (isset($_SERVER[$name]) && $_SERVER[$name] == $value) {
261 return true;
262 }
263 }
264 return false;
265 }
266
267 public function saveCookie($key, $value, $ttl)
268 {
269 if (isset($_COOKIE[$key]) && $_COOKIE[$key] == $value) {
270 return;
271 }
272 if (!headers_sent()) {
273 setcookie($key, $value, $this->_getCookiesExpireTimestamp($ttl), '/', $this->_getCookieHost());
274 }
275 $_COOKIE[$key] = $value;
276 }
277
278 public function param($name, $value)
279 {
280 if (!in_array($name, $this->_excludeParams)) {
281 $this->_params[$name] = $value;
282 }
283 return $this;
284 }
285
286 public function params($value)
287 {
288 if (!empty($value)) {
289 if (is_string($value)) {
290 parse_str($value, $result);
291 foreach ($result as $name => $value) {
292 $this->param($name, $value);
293 }
294 }
295 }
296
297 return $this;
298 }
299
300 public function reset()
301 {
302 $this->_result = null;
303 }
304
305 public function performRequest()
306 {
307 if ($this->_result) {
308 return $this->_result;
309 }
310 $request = $this->_buildRequestUrl();
311 $params = $this->getParams();
312 $options = $this->_getRequestOptions();
313 $this->log('Request: ' . $request);
314 try {
315 $result = $this->_httpClient->request($request, $params, $options);
316 $this->log('Response: ' . $result);
317 } catch (KTrafficClientError $e) {
318 if ($this->_debug) {
319 throw $e;
320 } else {
321 return self::ERROR;
322 }
323 }
324 $this->_result = json_decode($result);
325 $this->_storeState(
326 $this->_result,
327 isset($this->_result->cookies_ttl) ? $this->_result->cookies_ttl : null
328 );
329
330 if (isset($this->_result->cookies)) {
331 $this->_saveKeitaroCookies($this->_result->cookies , $this->_result->cookies_ttl);
332 }
333 return $this->_result;
334 }
335
336 public function execute($break = false, $print = true)
337 {
338 $content = $this->getContent();
339
340 if ($print) {
341 $headers = $this->sendHeaders();
342 echo $content;
343 } else {
344 return $content;
345 }
346
347 if ($break && (!empty($content) || $this->checkHeaders($headers))) {
348 exit;
349 }
350 }
351
352 public function checkHeaders($headers)
353 {
354 if (empty($headers)) {
355 return;
356 }
357 foreach ($headers as $header) {
358 if (strpos($header, 'Location:') === 0) {
359 return true;
360 }
361 if ($header == 'HTTP/1.1 404 Not Found') {
362 return true;
363 }
364 }
365 return false;
366 }
367
368 public function getContent()
369 {
370 $result = $this->performRequest();
371 $content = '';
372 if (!empty($result)) {
373 if (!empty($result->error)) {
374 $content .= $result->error;
375 }
376 if (!empty($result->body)) {
377 if (isset($result->contentType) && (strstr($result->contentType, 'image') || strstr($result->contentType, 'application/pdf'))) {
378 $content = base64_decode($result->body);
379 } else {
380 $content .= $result->body;
381 }
382 }
383 }
384
385 return $content;
386 }
387
388 public function showLog($separator = '<br />')
389 {
390 echo '<hr>' . implode($separator, $this->getLog()). '<hr>';
391 }
392
393 public function log($msg)
394 {
395 if ($this->_debug) {
396 error_log($msg);
397 }
398 $this->_log[] = $msg;
399 }
400
401 public function getLog()
402 {
403 return $this->_log;
404 }
405
406 public function executeAndBreak()
407 {
408 $this->execute(true);
409 }
410
411 public function getParams()
412 {
413 return $this->_params;
414 }
415
416 private function _storeState($result, $ttl)
417 {
418 $this->_startSession();
419 $_SESSION[self::STATE_SESSION_KEY] = json_encode($result);
420 $_SESSION[self::STATE_SESSION_EXPIRES_KEY] = time() + ($ttl * 60 * 60);
421
422 // for back-compatibility purpose
423 if (!empty($result->info)) {
424 if (!empty($result->info->sub_id)) {
425 $_SESSION[self::SESSION_SUB_ID] = $result->info->sub_id;
426 }
427 if (!empty($result->info->token)) {
428 $_SESSION[self::SESSION_LANDING_TOKEN] = $result->info->token;
429 }
430 }
431 }
432
433 private function _saveKeitaroCookies($cookies, $ttl)
434 {
435 foreach ($cookies as $key => $value) {
436 $this->saveCookie($key, $value, $ttl);
437 }
438 }
439
440 public function sendHeaders()
441 {
442 $result = $this->performRequest();
443 $headers = array();
444 $file = "";
445 $line = "";
446 if (headers_sent($file, $line)) {
447 $msg = "Body output already started";
448 if (!empty($file)) {
449 $msg .= "({$file}:{$line})";
450 }
451 $this->log($msg);
452 }
453
454
455 if (!empty($result->headers)) {
456 foreach ($result->headers as $header) {
457 $headers[] = $header;
458 if (!headers_sent()) {
459 header($header);
460 }
461 }
462 }
463
464 if (!empty($result->status)) {
465 http_response_code($result->status);
466 }
467
468 if (!empty($result->contentType)) {
469 $header = 'Content-Type: ' . $result->contentType;
470 $headers[] = $header;
471 if (!headers_sent()) {
472 header($header);
473 }
474 }
475 return $headers;
476 }
477
478 // @deprecated
479 public function updateHeaders()
480 {
481 $this->sendHeaders();
482 }
483
484 public function getOffer($params = array(), $fallback = 'no_offer')
485 {
486 $result = $this->performRequest();
487 $token = $this->getToken();
488 if (empty($token)) {
489 $this->log('Campaign hasn\'t returned offer');
490 return $fallback;
491 }
492 $params['_lp'] = 1;
493 $params['_token'] = $result->info->token;
494 return $this->_buildOfferUrl($params);
495 }
496
497 public function isBot()
498 {
499 $result = $this->performRequest();
500 if (isset($result->info)) {
501 return isset($result->info->is_bot) ? $result->info->is_bot : false;
502 }
503 }
504
505 public function isUnique($level = 'campaign')
506 {
507 $result = $this->performRequest();
508 if (isset($result->info) && $result->info->uniqueness) {
509 return isset($result->info->uniqueness->$level) ? $result->info->uniqueness->$level : false;
510 }
511 }
512
513 // @deprecated
514 public function forceChooseOffer()
515 {
516 throw new \Error('forceChooseOffer was removed in KClickClient v3.');
517 }
518
519 public function getBody()
520 {
521 $result = $this->performRequest();
522 return $result->body;
523 }
524
525 public function getHeaders()
526 {
527 $result = $this->performRequest();
528 return $result->headers;
529 }
530
531 private function _startSession()
532 {
533 if (!headers_sent()) {
534 @session_start();
535 }
536 }
537
538 private function _buildOfferUrl($params = array())
539 {
540 $request = parse_url($this->_trackerUrl);
541 $lastChar = substr($request['path'], -1);
542 if ($lastChar != '/' && $lastChar != '\\') {
543 $path = str_replace(basename($request['path']), '', $request['path']);
544 } else {
545 $path = $request['path'];
546 }
547 $path = ltrim($path, "\\\/");
548 $params = http_build_query($params);
549 return "{$request['scheme']}://{$request['host']}/{$path}?{$params}";
550 }
551
552
553 private function _getCurrentPage()
554 {
555 if ((isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443) || !empty($_SERVER['HTTPS'])) {
556 $scheme = 'https';
557 } else {
558 $scheme = 'http';
559 }
560 return $scheme . '://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
561 }
562
563 private function _buildRequestUrl()
564 {
565 $request = parse_url($this->_trackerUrl);
566 $url = "{$request['scheme']}://{$request['host']}";
567 if (isset($request['port'])) {
568 $url = ':' . $request['port'];
569 }
570 $url .= "/{$request['path']}";
571 return $url;
572 }
573
574
575 private function _findIp()
576 {
577 $ip = null;
578 $headers = array(
579 'HTTP_X_FORWARDED_FOR',
580 'HTTP_FORWARDED_FOR',
581 'HTTP_X_FORWARDED',
582 'HTTP_FORWARDED',
583 'HTTP_CLIENT_IP',
584 'HTTP_FORWARDED_FOR_IP',
585 'X_FORWARDED_FOR',
586 'FORWARDED_FOR',
587 'X_FORWARDED',
588 'FORWARDED',
589 'CLIENT_IP',
590 'FORWARDED_FOR_IP',
591 'HTTP_PROXY_CONNECTION');
592 foreach ($headers as $header) {
593 if (!empty($_SERVER[$header])) {
594 $tmp = explode(',', $_SERVER[$header]);
595 $ip = trim($tmp[0]);
596 break;
597 }
598 }
599 if (strstr($ip, ',')) {
600 $tmp = explode(',', $ip);
601 if (stristr($_SERVER['HTTP_USER_AGENT'], 'mini')) {
602 $ip = trim($tmp[count($tmp) - 2]);
603 } else {
604 $ip = trim($tmp[0]);
605 }
606 }
607
608 if (empty($ip)) {
609 $ip = $_SERVER['REMOTE_ADDR'];
610 }
611
612 return $ip;
613 }
614
615 private function _getCookiesExpireTimestamp($ttl)
616 {
617 return time() + 60 * 60 * $ttl;
618 }
619
620 private function _getCookieHost()
621 {
622 if (isset($_SERVER['HTTP_HOST']) && substr_count($_SERVER['HTTP_HOST'], '.') < 3) {
623 $host = '.' . str_replace('www.', '', $_SERVER['HTTP_HOST']);
624 } else {
625 $host = null;
626 }
627 return $host;
628 }
629
630 private function _getRequestOptions()
631 {
632 $opts = array();
633 if (isset($_SERVER["HTTP_COOKIE"])) {
634 $opts['cookies'] = preg_replace('/PHPSESSID=.*?;/si', '', $_SERVER["HTTP_COOKIE"]);
635 }
636
637 return $opts;
638 }
639}
640
641class KHttpClient
642{
643 const UA = 'KHttpClient';
644
645 public function request($url, $params, $opts = array())
646 {
647 $ch = curl_init();
648 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
649 curl_setopt($ch, CURLOPT_URL, $url);
650 curl_setopt($ch, CURLOPT_HEADER, 0);
651 curl_setopt($ch, CURLOPT_COOKIE, isset($opts['cookies']) ? $opts['cookies'] : null);
652 curl_setopt($ch, CURLOPT_NOBODY, 0);
653 curl_setopt($ch, CURLOPT_TIMEOUT, 10);
654 curl_setopt($ch, CURLOPT_USERAGENT, self::UA);
655 curl_setopt($ch, CURLOPT_POST, 1);
656 curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($params));
657 $result = curl_exec($ch);
658 if (curl_error($ch)) {
659 throw new KTrafficClientError(curl_error($ch));
660 }
661
662 if (empty($result)) {
663 throw new KTrafficClientError('Empty response');
664 }
665 return $result;
666 }
667}
668
669class KTrafficClientError extends \Exception {}
670
671
672if (!function_exists('http_response_code')) {
673 function http_response_code($code = NULL) {
674
675 if ($code !== NULL) {
676
677 switch ($code) {
678 case 100: $text = 'Continue'; break;
679 case 101: $text = 'Switching Protocols'; break;
680 case 200: $text = 'OK'; break;
681 case 201: $text = 'Created'; break;
682 case 202: $text = 'Accepted'; break;
683 case 203: $text = 'Non-Authoritative Information'; break;
684 case 204: $text = 'No Content'; break;
685 case 205: $text = 'Reset Content'; break;
686 case 206: $text = 'Partial Content'; break;
687 case 300: $text = 'Multiple Choices'; break;
688 case 301: $text = 'Moved Permanently'; break;
689 case 302: $text = 'Moved Temporarily'; break;
690 case 303: $text = 'See Other'; break;
691 case 304: $text = 'Not Modified'; break;
692 case 305: $text = 'Use Proxy'; break;
693 case 400: $text = 'Bad Request'; break;
694 case 401: $text = 'Unauthorized'; break;
695 case 402: $text = 'Payment Required'; break;
696 case 403: $text = 'Forbidden'; break;
697 case 404: $text = 'Not Found'; break;
698 case 405: $text = 'Method Not Allowed'; break;
699 case 406: $text = 'Not Acceptable'; break;
700 case 407: $text = 'Proxy Authentication Required'; break;
701 case 408: $text = 'Request Time-out'; break;
702 case 409: $text = 'Conflict'; break;
703 case 410: $text = 'Gone'; break;
704 case 411: $text = 'Length Required'; break;
705 case 412: $text = 'Precondition Failed'; break;
706 case 413: $text = 'Request Entity Too Large'; break;
707 case 414: $text = 'Request-URI Too Large'; break;
708 case 415: $text = 'Unsupported Media Type'; break;
709 case 500: $text = 'Internal Server Error'; break;
710 case 501: $text = 'Not Implemented'; break;
711 case 502: $text = 'Bad Gateway'; break;
712 case 503: $text = 'Service Unavailable'; break;
713 case 504: $text = 'Gateway Time-out'; break;
714 case 505: $text = 'HTTP Version not supported'; break;
715 default:
716 exit('Unknown http status code "' . htmlentities($code) . '"');
717 break;
718 }
719
720 $protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
721
722 header($protocol . ' ' . $code . ' ' . $text);
723
724 $GLOBALS['http_response_code'] = $code;
725
726 } else {
727
728 $code = (isset($GLOBALS['http_response_code']) ? $GLOBALS['http_response_code'] : 200);
729
730 }
731
732 return $code;
733
734 }
735}
736
737if (!function_exists('getallheaders'))
738{
739 function getallheaders()
740 {
741 $headers = array();
742 foreach ($_SERVER as $name => $value)
743 {
744 if (substr($name, 0, 5) == 'HTTP_')
745 {
746 $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
747 }
748 }
749 return $headers;
750 }
751}