Passed
Push — 1.11.x ( 31fff3...86e7ae )
by Yannick
15:37 queued 10s
created

plugin/vchamilo/vcron.php (1 issue)

1
<?php
2
/* For license terms, see /license.txt */
3
exit;
4
/**
5
 * This file is a cron microclock script.
6
 * It will be used as replacement of setting individual
7
 * cron lines for all virtual instances.
8
 *
9
 * Setup this vcron to run at the smallest period possible, as
10
 * it will schedule all availables vchamilos to be run as required.
11
 * Note that one activaton of this cron may not always run real crons
12
 * or may be run more than one cron.
13
 *
14
 * If used on a big system with clustering, ensure hostnames are adressed
15
 * at the load balancer entry and not on physical hosts
16
 *
17
 * @package plugin/vchamilo
18
 * @category plugins
19
 *
20
 * @author Valery fremaux ([email protected])
21
 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL
22
 */
23
define('CLI_SCRIPT', true); // for chamilo imported code
24
require_once dirname(dirname(__DIR__)).'/main/inc/global.inc.php';
25
26
global $DB;
27
$DB = new DatabaseManager();
28
29
define('ROUND_ROBIN', 0);
30
define('LOWEST_POSSIBLE_GAP', 1);
31
32
global $VCRON;
33
34
$VCRON = new stdClass();
35
$VCRON->ACTIVATION = 'cli'; // choose how individual cron are launched, 'cli' or 'web'
36
$VCRON->STRATEGY = ROUND_ROBIN; // choose vcron rotation mode
37
$VCRON->PERIOD = 15 * MINSECS; // used if LOWEST_POSSIBLE_GAP to setup the max gap
0 ignored issues
show
The constant MINSECS was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
38
$VCRON->TIMEOUT = 300; // time out for CURL call to effective cron
39
// $VCRON->TRACE = $_configuration['root_sys'].'plugin/vchamilo/log/vcrontrace.log';   // Trace file where to collect cron outputs
40
$VCRON->TRACE = '/data/log/chamilo/vcrontrace.log'; // Trace file where to collect cron outputs
41
$VCRON->TRACE_ENABLE = true; // enables tracing
42
43
if (!is_dir($_configuration['root_sys'].'plugin/vchamilo/log')) {
44
    $mode = api_get_permissions_for_new_directories();
45
    mkdir($_configuration['root_sys'].'plugin/vchamilo/log', $mode, true);
46
}
47
48
/**
49
 * fire a cron URL using CURL.
50
 */
51
function fire_vhost_cron($vhost)
52
{
53
    global $VCRON;
54
55
    if ($VCRON->TRACE_ENABLE) {
56
        $CRONTRACE = fopen($VCRON->TRACE, 'a');
57
    }
58
    $ch = curl_init($vhost->root_web.'/main/cron/run.php');
59
60
    $http_proxy_host = api_get_setting('vchamilo_httpproxyhost', 'vchamilo');
61
    $http_proxy_port = api_get_setting('vchamilo_httpproxyport', 'vchamilo');
62
    $http_proxy_bypass = api_get_setting('vchamilo_httpproxybypass', 'vchamilo');
63
    $http_proxy_user = api_get_setting('vchamilo_httpproxyuser', 'vchamilo');
64
    $http_proxy_password = api_get_setting('vchamilo_httpproxypassword', 'vchamilo');
65
66
    curl_setopt($ch, CURLOPT_TIMEOUT, $VCRON->TIMEOUT);
67
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
68
    curl_setopt($ch, CURLOPT_POST, true);
69
    curl_setopt($ch, CURLOPT_USERAGENT, 'Chamilo');
70
    curl_setopt($ch, CURLOPT_POSTFIELDS, '');
71
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: text/xml charset=UTF-8"]);
72
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
73
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
74
75
    // Check for proxy.
76
    if (!empty($http_proxy_host) && !is_proxybypass($uri)) {
77
        curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, false);
78
79
        if (empty($http_proxy_port)) {
80
            echo "Using proxy $http_proxy_host\n";
81
            curl_setopt($ch, CURLOPT_PROXY, $http_proxy_host);
82
        } else {
83
            echo "Using proxy $http_proxy_host:$http_proxy_port\n";
84
            curl_setopt($ch, CURLOPT_PROXY, $http_proxy_host.':'.$http_proxy_port);
85
        }
86
87
        if (!empty($http_proxy_user) and !empty($http_proxy_password)) {
88
            curl_setopt($ch, CURLOPT_PROXYUSERPWD, $http_proxy_user.':'.$http_proxy_password);
89
            if (defined('CURLOPT_PROXYAUTH')) {
90
                // any proxy authentication if PHP 5.1
91
                curl_setopt($ch, CURLOPT_PROXYAUTH, CURLAUTH_BASIC | CURLAUTH_NTLM);
92
            }
93
        }
94
    }
95
96
    $timestamp_send = time();
97
    $rawresponse = curl_exec($ch);
98
    $timestamp_receive = time();
99
100
    if ($rawresponse === false) {
101
        $error = curl_errno($ch).':'.curl_error($ch);
102
        if ($VCRON->TRACE_ENABLE) {
103
            if ($CRONTRACE) {
104
                fputs($CRONTRACE, "VCron start on $vhost->root_web : ".api_time_to_hms($timestamp_send)."\n");
105
                fputs($CRONTRACE, "VCron Error : $error \n");
106
                fputs($CRONTRACE, "VCron stop on $vhost->root_web : $timestamp_receive\n#################\n\n");
107
                fclose($CRONTRACE);
108
            }
109
        }
110
        echo "VCron started on $vhost->root_web : ".api_time_to_hms($timestamp_send)."\n";
111
        echo "VCron Error : $error \n";
112
        echo "VCron stop on $vhost->root_web : ".api_time_to_hms($timestamp_receive)."\n#################\n\n";
113
114
        return false;
115
    }
116
117
    if ($VCRON->TRACE_ENABLE) {
118
        if ($CRONTRACE) {
119
            fputs($CRONTRACE, "VCron start on $vhost->vhostname : ".api_time_to_hms($timestamp_send)."\n");
120
            fputs($CRONTRACE, $rawresponse."\n");
121
            fputs($CRONTRACE, "VCron stop on $vhost->vhostname : ".api_time_to_hms($timestamp_receive)."\n#################\n\n");
122
            fclose($CRONTRACE);
123
        }
124
    }
125
    echo "VCron start on $vhost->root_web : ".api_time_to_hms($timestamp_send)."\n";
126
    echo $rawresponse."\n";
127
    echo "VCron stop on $vhost->root_web : ".api_time_to_hms($timestamp_receive)."\n#################\n\n";
128
    $vhost->lastcrongap = time() - $vhost->lastcron;
129
    $vhost->lastcron = $timestamp_send;
130
    $vhost->croncount++;
131
132
    $vhostid = $vhost->id;
133
    unset($vhost->id);
134
135
    Database::update('vchamilo', (array) $vhost, ['id = ?' => $vhostid]);
136
}
137
138
/**
139
 * fire a cron URL using cli exec.
140
 */
141
function exec_vhost_cron($vhost)
142
{
143
    global $VCRON, $DB, $_configuration;
144
145
    if ($VCRON->TRACE_ENABLE) {
146
        $CRONTRACE = fopen($VCRON->TRACE, 'a');
147
    }
148
149
    $cmd = 'php "'.$_configuration['root_sys'].'/plugin/vchamilo/cli/cron.php" --host='.$vhost->root_web;
150
151
    $timestamp_send = time();
152
    exec($cmd, $rawresponse);
153
    $timestamp_receive = time();
154
155
    if ($VCRON->TRACE_ENABLE) {
156
        if ($CRONTRACE) {
157
            fputs($CRONTRACE, "VCron start on $vhost->root_web : $timestamp_send\n");
158
            fputs($CRONTRACE, $rawresponse."\n");
159
            fputs($CRONTRACE, "VCron stop on $vhost->root_web : $timestamp_receive\n#################\n\n");
160
            fclose($CRONTRACE);
161
        }
162
    }
163
164
    echo "VCron start on $vhost->root_web : $timestamp_send\n";
165
    echo implode("\n", $rawresponse)."\n";
166
    echo "VCron stop on $vhost->root_web : $timestamp_receive\n#################\n\n";
167
168
    $vhost->lastcrongap = time() - $vhost->lastcron;
169
    $vhost->lastcron = $timestamp_send;
170
    $vhost->croncount++;
171
172
    $DB->update_record('vchamilo', $vhost, 'id');
173
}
174
175
/**
176
 * check if $url matches anything in proxybypass list.
177
 *
178
 * any errors just result in the proxy being used (least bad)
179
 *
180
 * @global object
181
 *
182
 * @param string $url url to check
183
 *
184
 * @return bool true if we should bypass the proxy
185
 */
186
function is_proxybypass($url)
187
{
188
    $http_proxy_host = api_get_setting('vchamilo_httpproxyhost', 'vchamilo');
189
    $http_proxy_port = api_get_setting('vchamilo_httpproxyport', 'vchamilo');
190
    $http_proxy_bypass = api_get_setting('vchamilo_httpproxybypass', 'vchamilo');
191
192
    // sanity check
193
    if (empty($http_proxy_host) or empty($http_proxy_bypass)) {
194
        return false;
195
    }
196
197
    // get the host part out of the url
198
    if (!$host = parse_url($url, PHP_URL_HOST)) {
199
        return false;
200
    }
201
202
    // get the possible bypass hosts into an array
203
    $matches = explode(',', $http_proxy_bypass);
204
205
    // check for a match
206
    // (IPs need to match the left hand side and hosts the right of the url,
207
    // but we can recklessly check both as there can't be a false +ve)
208
    $bypass = false;
209
    foreach ($matches as $match) {
210
        $match = trim($match);
211
212
        // try for IP match (Left side)
213
        $lhs = substr($host, 0, strlen($match));
214
        if (strcasecmp($match, $lhs) == 0) {
215
            return true;
216
        }
217
218
        // try for host match (Right side)
219
        $rhs = substr($host, -strlen($match));
220
        if (strcasecmp($match, $rhs) == 0) {
221
            return true;
222
        }
223
    }
224
225
    // nothing matched.
226
    return false;
227
}
228
229
// Main execution sequence
230
231
if (!$vchamilos = Database::select('*', 'vchamilo', [], 'all')) {
232
    exit("Nothing to do. No Vhosts");
233
}
234
235
$allvhosts = array_values($vchamilos);
236
237
echo "<pre>";
238
echo "Chamilo VCron... start\n";
239
echo "Last croned : ".api_get_setting('vchamilo_cron_lasthost', 'vchamilo')."\n";
240
241
if ($VCRON->STRATEGY == ROUND_ROBIN) {
242
    $rr = 0;
243
    foreach ($allvhosts as $vhostassoc) {
244
        $vhost = (object) $vhostassoc;
245
        if ($rr == 1) {
246
            api_set_setting('vchamilo_cron_lasthost', $vhost->id);
247
            echo "Round Robin : ".$vhost->root_web."\n";
248
            if ($VCRON->ACTIVATION == 'cli') {
249
                exec_vhost_cron($vhost);
250
            } else {
251
                fire_vhost_cron($vhost);
252
            }
253
254
            exit('Done.');
255
        }
256
        if ($vhost->id == api_get_setting('vchamilo_cron_lasthost', 'vchamilo')) {
257
            $rr = 1; // take next one
258
        }
259
    }
260
261
    // We were at last. Loop back and take first.
262
    $firsthost = (object) $allvhosts[0];
263
    api_set_setting('vchamilo_cron_lasthost', $firsthost->id, 'vchamilo');
264
    echo "Round Robin : ".$firsthost->root_web."\n";
265
    if ($VCRON->ACTIVATION == 'cli') {
266
        exec_vhost_cron($firsthost);
267
    } else {
268
        fire_vhost_cron($firsthost);
269
    }
270
} elseif ($VCRON->STRATEGY == LOWEST_POSSIBLE_GAP) {
271
    // First make measurement of cron period.
272
    if (api_get_setting('vcrontickperiod', 'vchamilo')) {
273
        api_set_setting('vcrontime', time(), 'vchamilo');
274
275
        return;
276
    }
277
    api_set_setting('vcrontickperiod', time() - api_get_setting('vcrontime', 'vchamilo'), 'vchamilo');
278
    $hostsperturn = max(1, $VCRON->PERIOD / api_get_setting('vcrontickperiod', 'vchamilo') * count($allvhosts));
279
    $i = 0;
280
    foreach ($allvhosts as $vhostassoc) {
281
        $vhost = (object) $vhostassoc;
282
        if ((time() - $vhost->lastcron) > $VCRON->PERIOD) {
283
            if ($VCRON->ACTIVATION == 'cli') {
284
                exec_vhost_cron($vhost);
285
            } else {
286
                fire_vhost_cron($vhost);
287
            }
288
            $i++;
289
            if ($i >= $hostsperturn) {
290
                return;
291
            }
292
        }
293
    }
294
}
295