Issues (236)

src/receiver/webhook.php (4 issues)

1
<?php
2
3
namespace BPT\receiver;
4
5
use BPT\BPT;
6
use BPT\constants\loggerTypes;
7
use BPT\exception\bptException;
8
use BPT\lock;
9
use BPT\logger;
10
use BPT\settings;
11
use CURLFile;
12
use JetBrains\PhpStorm\NoReturn;
13
14
/**
15
 * webhook class , for manage and handling webhook setter and getter
16
 */
17
class webhook extends receiver {
18
    /**
19
     * @internal Only for BPT self usage , Don't use it in your source!
20
     */
21
    public static function init () {
22
        if (settings::$multi) {
23
            multi::init();
24
        }
25
        else {
26
            if (!lock::exist('BPT-HOOK')) {
27
                self::processSetWebhook();
28
            }
29
30
            receiver::telegramVerify();
31
            self::checkSecret();
32
            logger::write('Update received , lets process it ;)');
33
            receiver::processUpdate();
34
        }
35
    }
36
37
    private static function deleteOldLocks() {
38
        lock::deleteIfExist(['BPT-MULTI-EXEC', 'BPT-MULTI-CURL', 'getUpdate', 'getUpdateHook']);
39
    }
40
41
    protected static function setWebhook(string $url,string $secret = '') {
42
        $res = BPT::setWebhook($url, settings::$certificate, max_connections: settings::$max_connection, allowed_updates: settings::$allowed_updates, drop_pending_updates: settings::$skip_old_updates, secret_token: $secret);
0 ignored issues
show
The call to BPT\BPT::setWebhook() has too many arguments starting with $url. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

42
        /** @scrutinizer ignore-call */ 
43
        $res = BPT::setWebhook($url, settings::$certificate, max_connections: settings::$max_connection, allowed_updates: settings::$allowed_updates, drop_pending_updates: settings::$skip_old_updates, secret_token: $secret);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
Bug Best Practice introduced by
The method BPT\BPT::setWebhook() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

42
        /** @scrutinizer ignore-call */ 
43
        $res = BPT::setWebhook($url, settings::$certificate, max_connections: settings::$max_connection, allowed_updates: settings::$allowed_updates, drop_pending_updates: settings::$skip_old_updates, secret_token: $secret);
Loading history...
43
        if (!BPT::$status) {
44
            logger::write("There is some problem happened , telegram response : \n".json_encode($res),loggerTypes::ERROR);
45
            BPT::exit(print_r($res,true));
0 ignored issues
show
It seems like print_r($res, true) can also be of type true; however, parameter $message of BPT\BPT::exit() does only seem to accept null|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

45
            BPT::exit(/** @scrutinizer ignore-type */ print_r($res,true));
Loading history...
46
        }
47
        logger::write('Webhook was set successfully',loggerTypes::INFO);
48
    }
49
50
    protected static function checkURL() {
51
        if (!(isset($_SERVER['SERVER_NAME']) && isset($_SERVER['REQUEST_URI']))) {
52
            logger::write('For using webhook receiver , you should open this file in your webserver(by domain)',loggerTypes::ERROR);
53
            throw new bptException('WEBHOOK_NEED_URL');
54
        }
55
    }
56
57
    protected static function setURL(): string {
58
        if (isset($_GET['token'])) {
59
            logger::write('You can not specify token in url',loggerTypes::ERROR);
60
            BPT::exit('You can not specify token in url');
61
        }
62
        return (isset(settings::$certificate) ? 'http://' : 'https://') . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
63
    }
64
65
    protected static function setCertificate() {
66
        if (isset(settings::$certificate) && is_string(settings::$certificate)) {
67
            settings::$certificate = file_exists(realpath(settings::$certificate)) ? new CURLFile(settings::$certificate) : null;
68
        }
69
    }
70
71
    #[NoReturn]
72
    private static function processSetWebhook() {
73
        self::deleteOldLocks();
74
        self::checkURL();
75
        self::setCertificate();
76
        $url = self::setURL();
77
        $secret = !empty(settings::$secret) ? settings::$secret : str_replace(':','---',settings::$token);
78
        self::setWebhook($url,$secret);
79
        lock::save('BPT-HOOK', md5($secret));
80
        BPT::exit('Done');
81
    }
82
83
    private static function checkSecret() {
84
        $secret_hash = lock::read('BPT-HOOK');
85
        if ($secret_hash !== md5(self::getSecret())) {
0 ignored issues
show
It seems like self::getSecret() can also be of type false; however, parameter $string of md5() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

85
        if ($secret_hash !== md5(/** @scrutinizer ignore-type */ self::getSecret())) {
Loading history...
86
            if (isset($_SERVER['HTTP_USER_AGENT']) && $_SERVER['HTTP_USER_AGENT'] == 'TelegramBot (like TwitterBot)') {
87
                logger::write('Your file address is shared on telegram, If you didnt do it then be careful(also it counts callback urls)', loggerTypes::WARNING);
88
                BPT::exit();
89
            }
90
            if (settings::$telegram_verify) {
91
                logger::write('This is not webhook set by BPT, webhook will reset',loggerTypes::WARNING);
92
                self::processSetWebhook();
93
            }
94
        }
95
    }
96
97
    /**
98
     * @internal Only for BPT self usage , Don't use it in your source!
99
     */
100
    public static function getSecret() {
101
        return $_SERVER['HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'] ?? false;
102
    }
103
104
    /**
105
     * Fast end webserver process and run codes in background
106
     *
107
     * It will help you with telegram if you call it in less than 30 second of start time
108
     *
109
     * @param int $timeout set time out if you know how much your code will take , default is 1 day
110
     *
111
     * @return bool
112
     */
113
    public static function fastClose (int $timeout = 86400): bool {
114
        if (settings::$multi || !lock::exist('BPT-HOOK') || settings::$receiver !== \BPT\constants\receiver::WEBHOOK) {
115
            return false;
116
        }
117
        http_response_code(200);
118
        ini_set('max_execution_time', $timeout);
119
        set_time_limit($timeout);
120
        ignore_user_abort(true);
121
        if (function_exists('fastcgi_finish_request')) {
122
            return fastcgi_finish_request();
123
        }
124
        if (function_exists('litespeed_finish_request')) {
125
            return litespeed_finish_request();
126
        }
127
        return false;
128
    }
129
}