This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point'); |
||
3 | /********************************************************************************* |
||
4 | * SugarCRM Community Edition is a customer relationship management program developed by |
||
5 | * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc. |
||
6 | |||
7 | * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd. |
||
8 | * Copyright (C) 2011 - 2014 Salesagility Ltd. |
||
9 | * |
||
10 | * This program is free software; you can redistribute it and/or modify it under |
||
11 | * the terms of the GNU Affero General Public License version 3 as published by the |
||
12 | * Free Software Foundation with the addition of the following permission added |
||
13 | * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK |
||
14 | * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY |
||
15 | * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. |
||
16 | * |
||
17 | * This program is distributed in the hope that it will be useful, but WITHOUT |
||
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
||
19 | * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
||
20 | * details. |
||
21 | * |
||
22 | * You should have received a copy of the GNU Affero General Public License along with |
||
23 | * this program; if not, see http://www.gnu.org/licenses or write to the Free |
||
24 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
||
25 | * 02110-1301 USA. |
||
26 | * |
||
27 | * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road, |
||
28 | * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected]. |
||
29 | * |
||
30 | * The interactive user interfaces in modified source and object code versions |
||
31 | * of this program must display Appropriate Legal Notices, as required under |
||
32 | * Section 5 of the GNU Affero General Public License version 3. |
||
33 | * |
||
34 | * In accordance with Section 7(b) of the GNU Affero General Public License version 3, |
||
35 | * these Appropriate Legal Notices must retain the display of the "Powered by |
||
36 | * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not |
||
37 | * reasonably feasible for technical reasons, the Appropriate Legal Notices must |
||
38 | * display the words "Powered by SugarCRM" and "Supercharged by SuiteCRM". |
||
39 | ********************************************************************************/ |
||
40 | |||
41 | |||
42 | /** |
||
43 | * Job queue job |
||
44 | * @api |
||
45 | */ |
||
46 | class SchedulersJob extends Basic |
||
47 | { |
||
48 | const JOB_STATUS_QUEUED = 'queued'; |
||
49 | const JOB_STATUS_RUNNING = 'running'; |
||
50 | const JOB_STATUS_DONE = 'done'; |
||
51 | |||
52 | const JOB_PENDING = 'queued'; |
||
53 | const JOB_PARTIAL = 'partial'; |
||
54 | const JOB_SUCCESS = 'success'; |
||
55 | const JOB_FAILURE = 'failure'; |
||
56 | |||
57 | // schema attributes |
||
58 | public $id; |
||
59 | public $name; |
||
60 | public $deleted; |
||
61 | public $date_entered; |
||
62 | public $date_modified; |
||
63 | public $scheduler_id; |
||
64 | public $execute_time; // when to execute |
||
65 | public $status; |
||
66 | public $resolution; |
||
67 | public $message; |
||
68 | public $target; // URL or function name |
||
69 | public $data; // Data set |
||
70 | public $requeue; // Requeue on failure? |
||
71 | public $retry_count; |
||
72 | public $failure_count; |
||
73 | public $job_delay=0; // Frequency to run it |
||
74 | public $assigned_user_id; // User under which the task is running |
||
75 | public $client; // Client ID that owns this job |
||
76 | public $execute_time_db; |
||
77 | public $percent_complete; // how much of the job is done |
||
78 | |||
79 | // standard SugarBean child attrs |
||
80 | var $table_name = "job_queue"; |
||
81 | var $object_name = "SchedulersJob"; |
||
82 | var $module_dir = "SchedulersJobs"; |
||
83 | var $new_schema = true; |
||
84 | var $process_save_dates = true; |
||
85 | // related fields |
||
86 | var $job_name; // the Scheduler's 'name' field |
||
87 | var $job; // the Scheduler's 'job' field |
||
88 | // object specific attributes |
||
89 | public $user; // User object |
||
90 | var $scheduler; // Scheduler parent |
||
91 | public $min_interval = 30; // minimal interval for job reruns |
||
92 | protected $job_done = true; |
||
93 | protected $old_user; |
||
94 | |||
95 | /** |
||
96 | * Job constructor. |
||
97 | */ |
||
98 | 35 | function __construct() |
|
99 | { |
||
100 | 35 | parent::__construct(); |
|
101 | 35 | if(!empty($GLOBALS['sugar_config']['jobs']['min_retry_interval'])) { |
|
102 | 35 | $this->min_interval = $GLOBALS['sugar_config']['jobs']['min_retry_interval']; |
|
103 | } |
||
104 | 35 | } |
|
105 | |||
106 | /** |
||
107 | * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead |
||
108 | */ |
||
109 | function SchedulersJob(){ |
||
110 | $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code'; |
||
111 | if(isset($GLOBALS['log'])) { |
||
112 | $GLOBALS['log']->deprecated($deprecatedMessage); |
||
113 | } |
||
114 | else { |
||
115 | trigger_error($deprecatedMessage, E_USER_DEPRECATED); |
||
116 | } |
||
117 | self::__construct(); |
||
118 | } |
||
119 | |||
120 | 3 | public function check_date_relationships_load() |
|
121 | { |
||
122 | // Hack to work around the mess with dates being auto-converted to user format on retrieve |
||
123 | 3 | $this->execute_time_db = $this->db->fromConvert($this->execute_time, 'datetime'); |
|
124 | 3 | parent::check_date_relationships_load(); |
|
125 | 3 | } |
|
126 | /** |
||
127 | * handleDateFormat |
||
128 | * |
||
129 | * This function handles returning a datetime value. It allows a user instance to be passed in, but will default to the |
||
130 | * user member variable instance if none is found. |
||
131 | * |
||
132 | * @param string $date String value of the date to calculate, defaults to 'now' |
||
133 | * @param object $user The User instance to use in calculating the time value, if empty, it will default to user member variable |
||
134 | * @param boolean $user_format Boolean indicating whether or not to convert to user's time format, defaults to false |
||
135 | * |
||
136 | * @return string Formatted datetime value |
||
137 | */ |
||
138 | 1 | function handleDateFormat($date='now', $user=null, $user_format=false) { |
|
139 | 1 | global $timedate; |
|
140 | |||
141 | 1 | if(!isset($timedate) || empty($timedate)) |
|
142 | { |
||
143 | $timedate = new TimeDate(); |
||
144 | } |
||
145 | |||
146 | // get user for calculation |
||
147 | 1 | $user = (empty($user)) ? $this->user : $user; |
|
148 | |||
149 | 1 | if($date == 'now') |
|
150 | { |
||
151 | 1 | $dbTime = $timedate->asUser($timedate->getNow(), $user); |
|
152 | } else { |
||
153 | 1 | $dbTime = $timedate->asUser($timedate->fromString($date, $user), $user); |
|
0 ignored issues
–
show
|
|||
154 | } |
||
155 | |||
156 | // if $user_format is set to true then just return as th user's time format, otherwise, return as database format |
||
157 | 1 | return $user_format ? $dbTime : $timedate->fromUser($dbTime, $user)->asDb(); |
|
158 | } |
||
159 | |||
160 | |||
161 | /////////////////////////////////////////////////////////////////////////// |
||
162 | //// SCHEDULERSJOB HELPER FUNCTIONS |
||
163 | |||
164 | /** |
||
165 | * This function takes a passed URL and cURLs it to fake multi-threading with another httpd instance |
||
166 | * @param $job String in URI-clean format |
||
167 | * @param $timeout Int value in secs for cURL to timeout. 30 default. |
||
168 | */ |
||
169 | 2 | public function fireUrl($job, $timeout=30) |
|
170 | { |
||
171 | // TODO: figure out what error is thrown when no more apache instances can be spun off |
||
172 | // cURL inits |
||
173 | 2 | $ch = curl_init(); |
|
174 | 2 | curl_setopt($ch, CURLOPT_URL, $job); // set url |
|
175 | 2 | curl_setopt($ch, CURLOPT_FAILONERROR, true); // silent failure (code >300); |
|
176 | 2 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // do not follow location(); inits - we always use the current |
|
177 | 2 | curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); |
|
178 | 2 | curl_setopt($ch, CURLOPT_DNS_USE_GLOBAL_CACHE, false); // not thread-safe |
|
179 | 2 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // return into a variable to continue program execution |
|
180 | 2 | curl_setopt($ch, CURLOPT_TIMEOUT, $timeout); // never times out - bad idea? |
|
181 | 2 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5); // 5 secs for connect timeout |
|
182 | 2 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, true); // open brand new conn |
|
183 | 2 | curl_setopt($ch, CURLOPT_HEADER, true); // do not return header info with result |
|
184 | 2 | curl_setopt($ch, CURLOPT_NOPROGRESS, true); // do not have progress bar |
|
185 | 2 | $urlparts = parse_url($job); |
|
186 | 2 | if(empty($urlparts['port'])) { |
|
187 | 2 | if($urlparts['scheme'] == 'https'){ |
|
188 | 2 | $urlparts['port'] = 443; |
|
189 | } else { |
||
190 | 1 | $urlparts['port'] = 80; |
|
191 | } |
||
192 | } |
||
193 | 2 | curl_setopt($ch, CURLOPT_PORT, $urlparts['port']); // set port as reported by Server |
|
194 | //TODO make the below configurable |
||
195 | 2 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // most customers will not have Certificate Authority account |
|
196 | 2 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // most customers will not have Certificate Authority account |
|
197 | |||
198 | 2 | curl_setopt($ch, CURLOPT_NOSIGNAL, true); // ignore any cURL signals to PHP (for multi-threading) |
|
199 | 2 | $result = curl_exec($ch); |
|
200 | 2 | $cInfo = curl_getinfo($ch); //url,content_type,header_size,request_size,filetime,http_code |
|
201 | //ssl_verify_result,total_time,namelookup_time,connect_time |
||
202 | //pretransfer_time,size_upload,size_download,speed_download, |
||
203 | //speed_upload,download_content_length,upload_content_length |
||
204 | //starttransfer_time,redirect_time |
||
205 | 2 | if(curl_errno($ch)) { |
|
206 | 1 | $this->errors .= curl_errno($ch)."\n"; |
|
207 | } |
||
208 | 2 | curl_close($ch); |
|
209 | |||
210 | 2 | if($result !== FALSE && $cInfo['http_code'] < 400) { |
|
211 | 2 | $GLOBALS['log']->debug("----->Firing was successful: $job"); |
|
212 | 2 | $GLOBALS['log']->debug('----->WTIH RESULT: '.strip_tags($result).' AND '.strip_tags(print_r($cInfo, true))); |
|
213 | 2 | return true; |
|
214 | } else { |
||
215 | 1 | $GLOBALS['log']->fatal("Job failed: $job"); |
|
216 | 1 | return false; |
|
217 | } |
||
218 | } |
||
219 | //// END SCHEDULERSJOB HELPER FUNCTIONS |
||
220 | /////////////////////////////////////////////////////////////////////////// |
||
221 | |||
222 | |||
223 | /////////////////////////////////////////////////////////////////////////// |
||
224 | //// STANDARD SUGARBEAN OVERRIDES |
||
225 | /** |
||
226 | * This function gets DB data and preps it for ListViews |
||
227 | */ |
||
228 | 1 | function get_list_view_data() |
|
229 | { |
||
230 | 1 | global $mod_strings; |
|
231 | |||
232 | 1 | $temp_array = $this->get_list_view_array(); |
|
233 | 1 | $temp_array['JOB_NAME'] = $this->job_name; |
|
234 | 1 | $temp_array['JOB'] = $this->job; |
|
235 | |||
236 | 1 | return $temp_array; |
|
237 | } |
||
238 | |||
239 | /** method stub for future customization |
||
240 | * |
||
241 | */ |
||
242 | 1 | function fill_in_additional_list_fields() |
|
243 | { |
||
244 | 1 | $this->fill_in_additional_detail_fields(); |
|
245 | 1 | } |
|
246 | |||
247 | |||
248 | /** |
||
249 | * Mark this job as failed |
||
250 | * @param string $message |
||
251 | */ |
||
252 | 1 | public function failJob($message = null) |
|
253 | { |
||
254 | 1 | return $this->resolveJob(self::JOB_FAILURE, $message); |
|
255 | } |
||
256 | |||
257 | /** |
||
258 | * Mark this job as success |
||
259 | * @param string $message |
||
260 | */ |
||
261 | 1 | public function succeedJob($message = null) |
|
262 | { |
||
263 | 1 | return $this->resolveJob(self::JOB_SUCCESS, $message); |
|
264 | } |
||
265 | |||
266 | /** |
||
267 | * Called if job failed but will be retried |
||
268 | */ |
||
269 | public function onFailureRetry() |
||
270 | { |
||
271 | // TODO: what we do if job fails, notify somebody? |
||
272 | $this->call_custom_logic("job_failure_retry"); |
||
273 | } |
||
274 | |||
275 | /** |
||
276 | * Called if job has failed and will not be retried |
||
277 | */ |
||
278 | 4 | public function onFinalFailure() |
|
279 | { |
||
280 | // TODO: what we do if job fails, notify somebody? |
||
281 | 4 | $this->call_custom_logic("job_failure"); |
|
282 | 4 | } |
|
283 | |||
284 | /** |
||
285 | * Resolve job as success or failure |
||
286 | * @param string $resolution One of JOB_ constants that define job status |
||
287 | * @param string $message |
||
288 | * @return bool |
||
289 | */ |
||
290 | 5 | public function resolveJob($resolution, $message = null) |
|
291 | { |
||
292 | 5 | $GLOBALS['log']->info("Resolving job {$this->id} as $resolution: $message"); |
|
293 | 5 | if($resolution == self::JOB_FAILURE) { |
|
294 | 4 | $this->failure_count++; |
|
295 | 4 | if($this->requeue && $this->retry_count > 0) { |
|
296 | // retry failed job |
||
297 | $this->status = self::JOB_STATUS_QUEUED; |
||
298 | if($this->job_delay < $this->min_interval) { |
||
299 | $this->job_delay = $this->min_interval; |
||
300 | } |
||
301 | $this->execute_time = $GLOBALS['timedate']->getNow()->modify("+{$this->job_delay} seconds")->asDb(); |
||
302 | $this->retry_count--; |
||
303 | $GLOBALS['log']->info("Will retry job {$this->id} at {$this->execute_time} ($this->retry_count)"); |
||
304 | $this->onFailureRetry(); |
||
305 | } else { |
||
306 | // final failure |
||
307 | 4 | $this->status = self::JOB_STATUS_DONE; |
|
308 | 4 | $this->onFinalFailure(); |
|
309 | } |
||
310 | } else { |
||
311 | 3 | $this->status = self::JOB_STATUS_DONE; |
|
312 | } |
||
313 | 5 | $this->addMessages($message); |
|
314 | 5 | $this->resolution = $resolution; |
|
315 | 5 | $this->save(); |
|
316 | 5 | if($this->status == self::JOB_STATUS_DONE && $this->resolution == self::JOB_SUCCESS) { |
|
317 | 3 | $this->updateSchedulerSuccess(); |
|
318 | } |
||
319 | 5 | return true; |
|
320 | } |
||
321 | |||
322 | /** |
||
323 | * Update schedulers table on job success |
||
324 | */ |
||
325 | 3 | protected function updateSchedulerSuccess() |
|
326 | { |
||
327 | 3 | if(empty($this->scheduler_id)) { |
|
328 | 3 | return; |
|
329 | } |
||
330 | $this->db->query("UPDATE schedulers SET last_run={$this->db->now()} WHERE id=".$this->db->quoted($this->scheduler_id)); |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * Assemle job messages |
||
335 | * Takes messages in $this->message, errors & $message and assembles them into $this->message |
||
336 | * @param string $message |
||
337 | */ |
||
338 | 6 | protected function addMessages($message) |
|
339 | { |
||
340 | 6 | if(!empty($this->errors)) { |
|
341 | 1 | $this->message .= $this->errors; |
|
342 | 1 | $this->errors = ''; |
|
343 | } |
||
344 | 6 | if(!empty($message)) { |
|
345 | 4 | $this->message .= "$message\n"; |
|
346 | } |
||
347 | 6 | } |
|
348 | |||
349 | /** |
||
350 | * Rerun this job again |
||
351 | * @param string $message |
||
352 | * @param string $delay how long to delay (default is job's delay) |
||
353 | * @return bool |
||
354 | */ |
||
355 | 1 | public function postponeJob($message = null, $delay = null) |
|
356 | { |
||
357 | 1 | $this->status = self::JOB_STATUS_QUEUED; |
|
358 | 1 | $this->addMessages($message); |
|
359 | 1 | $this->resolution = self::JOB_PARTIAL; |
|
360 | 1 | if(empty($delay)) { |
|
361 | $delay = intval($this->job_delay); |
||
362 | } |
||
363 | 1 | $this->execute_time = $GLOBALS['timedate']->getNow()->modify("+$delay seconds")->asDb(); |
|
364 | 1 | $GLOBALS['log']->info("Postponing job {$this->id} to {$this->execute_time}: $message"); |
|
365 | |||
366 | 1 | $this->save(); |
|
367 | 1 | return true; |
|
368 | } |
||
369 | |||
370 | /** |
||
371 | * Delete a job |
||
372 | * @see SugarBean::mark_deleted($id) |
||
373 | */ |
||
374 | 7 | public function mark_deleted($id) |
|
375 | { |
||
376 | 7 | return $this->db->query("DELETE FROM {$this->table_name} WHERE id=".$this->db->quoted($id)); |
|
377 | } |
||
378 | |||
379 | /** |
||
380 | * Shutdown handler to be called if something breaks in the middle of the job |
||
381 | */ |
||
382 | 1 | public function unexpectedExit() |
|
383 | { |
||
384 | 1 | if(!$this->job_done) { |
|
385 | // Job wasn't properly finished, fail it |
||
386 | $this->resolveJob(self::JOB_FAILURE, translate('ERR_FAILED', 'SchedulersJobs')); |
||
387 | } |
||
388 | 1 | } |
|
389 | |||
390 | /** |
||
391 | * Run the job by ID |
||
392 | * @param string $id |
||
393 | * @param string $client Client that is trying to run the job |
||
394 | * @return bool|string true on success, false on job failure, error message on failure to run |
||
395 | */ |
||
396 | 2 | public static function runJobId($id, $client) |
|
397 | { |
||
398 | 2 | $job = new self(); |
|
399 | 2 | $job->retrieve($id); |
|
400 | 2 | if(empty($job->id)) { |
|
401 | 1 | $GLOBALS['log']->fatal("Job $id not found."); |
|
402 | 1 | return "Job $id not found."; |
|
403 | } |
||
404 | 2 | if($job->status != self::JOB_STATUS_RUNNING) { |
|
405 | 1 | $GLOBALS['log']->fatal("Job $id is not marked as running."); |
|
406 | 1 | return "Job $id is not marked as running."; |
|
407 | } |
||
408 | 2 | if($job->client != $client) { |
|
409 | 1 | $GLOBALS['log']->fatal("Job $id belongs to client {$job->client}, can not run as $client."); |
|
410 | 1 | return "Job $id belongs to another client, can not run as $client."; |
|
411 | } |
||
412 | 1 | $job->job_done = false; |
|
413 | 1 | register_shutdown_function(array($job, "unexpectedExit")); |
|
414 | 1 | $res = $job->runJob(); |
|
415 | 1 | $job->job_done = true; |
|
416 | 1 | return $res; |
|
417 | } |
||
418 | |||
419 | /** |
||
420 | * Error handler, assembles the error messages |
||
421 | * @param int $errno |
||
422 | * @param string $errstr |
||
423 | * @param string $errfile |
||
424 | * @param int $errline |
||
425 | */ |
||
426 | 2 | public function errorHandler($errno, $errstr, $errfile, $errline) |
|
427 | { |
||
428 | switch($errno) |
||
429 | { |
||
430 | 2 | case E_USER_WARNING: |
|
431 | 2 | case E_COMPILE_WARNING: |
|
432 | 2 | case E_CORE_WARNING: |
|
433 | 2 | case E_WARNING: |
|
434 | 2 | $type = "Warning"; |
|
435 | 2 | break; |
|
436 | 1 | case E_USER_ERROR: |
|
437 | 1 | case E_COMPILE_ERROR: |
|
438 | 1 | case E_CORE_ERROR: |
|
439 | 1 | case E_ERROR: |
|
440 | 1 | $type = "Fatal Error"; |
|
441 | 1 | break; |
|
442 | 1 | case E_PARSE: |
|
443 | 1 | $type = "Parse Error"; |
|
444 | 1 | break; |
|
445 | 1 | case E_RECOVERABLE_ERROR: |
|
446 | 1 | $type = "Recoverable Error"; |
|
447 | 1 | break; |
|
448 | default: |
||
449 | // Ignore errors we don't know about |
||
450 | return; |
||
451 | } |
||
452 | 2 | $errstr = strip_tags($errstr); |
|
453 | 2 | $this->errors .= sprintf(translate('ERR_PHP', 'SchedulersJobs'), $type, $errno, $errstr, $errfile, $errline)."\n"; |
|
454 | 2 | } |
|
455 | |||
456 | /** |
||
457 | * Change current user to given user |
||
458 | * @param User $user |
||
459 | */ |
||
460 | 1 | protected function sudo($user) |
|
461 | { |
||
462 | 1 | $GLOBALS['current_user'] = $user; |
|
463 | // Reset the session |
||
464 | 1 | if(session_id()) { |
|
465 | session_destroy(); |
||
466 | } |
||
467 | 1 | if(!headers_sent()) { |
|
468 | session_start(); |
||
469 | session_regenerate_id(); |
||
470 | } |
||
471 | 1 | $_SESSION['is_valid_session']= true; |
|
472 | 1 | $_SESSION['user_id'] = $user->id; |
|
473 | 1 | $_SESSION['type'] = 'user'; |
|
474 | 1 | $_SESSION['authenticated_user_id'] = $user->id; |
|
475 | 1 | } |
|
476 | |||
477 | /** |
||
478 | * Set environment to the user of this job |
||
479 | * @return boolean |
||
480 | */ |
||
481 | 1 | protected function setJobUser() |
|
482 | { |
||
483 | // set up the current user and drop session |
||
484 | 1 | if(!empty($this->assigned_user_id)) { |
|
485 | 1 | $this->old_user = $GLOBALS['current_user']; |
|
486 | 1 | if(empty($this->user->id) || $this->assigned_user_id != $this->user->id) { |
|
487 | 1 | $this->user = BeanFactory::getBean('Users', $this->assigned_user_id); |
|
488 | 1 | if(empty($this->user->id)) { |
|
489 | $this->resolveJob(self::JOB_FAILURE, sprintf(translate('ERR_NOSUCHUSER', 'SchedulersJobs'), $this->assigned_user_id)); |
||
490 | return false; |
||
491 | } |
||
492 | } |
||
493 | 1 | $this->sudo($this->user); |
|
494 | } else { |
||
495 | 1 | $this->resolveJob(self::JOB_FAILURE, translate('ERR_NOUSER', 'SchedulersJobs')); |
|
496 | 1 | return false; |
|
497 | } |
||
498 | 1 | return true; |
|
499 | } |
||
500 | |||
501 | /** |
||
502 | * Restore previous user environment |
||
503 | */ |
||
504 | 1 | protected function restoreJobUser() |
|
505 | { |
||
506 | 1 | if(!empty($this->old_user->id) && $this->old_user->id != $this->user->id) { |
|
507 | $this->sudo($this->old_user); |
||
508 | } |
||
509 | 1 | } |
|
510 | |||
511 | /** |
||
512 | * Run this job |
||
513 | * @return bool Was the job successful? |
||
514 | */ |
||
515 | 2 | public function runJob() |
|
516 | { |
||
517 | 2 | require_once('modules/Schedulers/_AddJobsHere.php'); |
|
518 | |||
519 | 2 | $this->errors = ""; |
|
520 | 2 | $exJob = explode('::', $this->target, 2); |
|
521 | 2 | if($exJob[0] == 'function') { |
|
522 | // set up the current user and drop session |
||
523 | 1 | if(!$this->setJobUser()) { |
|
524 | 1 | return false; |
|
525 | } |
||
526 | 1 | $func = $exJob[1]; |
|
527 | 1 | $GLOBALS['log']->debug("----->SchedulersJob calling function: $func"); |
|
528 | 1 | set_error_handler(array($this, "errorHandler"), E_ALL & ~E_NOTICE & ~E_STRICT); |
|
529 | 1 | if(!is_callable($func)) { |
|
530 | $this->resolveJob(self::JOB_FAILURE, sprintf(translate('ERR_CALL', 'SchedulersJobs'), $func)); |
||
531 | } |
||
532 | 1 | $data = array($this); |
|
533 | 1 | if(!empty($this->data)) { |
|
534 | $data[] = $this->data; |
||
535 | } |
||
536 | 1 | $res = call_user_func_array($func, $data); |
|
537 | 1 | restore_error_handler(); |
|
538 | 1 | $this->restoreJobUser(); |
|
539 | 1 | if($this->status == self::JOB_STATUS_RUNNING) { |
|
540 | // nobody updated the status yet - job function could do that |
||
541 | if($res) { |
||
542 | $this->resolveJob(self::JOB_SUCCESS); |
||
543 | return true; |
||
544 | } else { |
||
545 | $this->resolveJob(self::JOB_FAILURE); |
||
546 | return false; |
||
547 | } |
||
548 | } else { |
||
549 | 1 | return $this->resolution != self::JOB_FAILURE; |
|
550 | } |
||
551 | 2 | } elseif($exJob[0] == 'url') { |
|
552 | 1 | if(function_exists('curl_init')) { |
|
553 | 1 | $GLOBALS['log']->debug('----->SchedulersJob firing URL job: '.$exJob[1]); |
|
554 | 1 | set_error_handler(array($this, "errorHandler"), E_ALL & ~E_NOTICE & ~E_STRICT); |
|
555 | 1 | if($this->fireUrl($exJob[1])) { |
|
556 | 1 | restore_error_handler(); |
|
557 | 1 | $this->resolveJob(self::JOB_SUCCESS); |
|
558 | 1 | return true; |
|
559 | } else { |
||
560 | restore_error_handler(); |
||
561 | $this->resolveJob(self::JOB_FAILURE); |
||
562 | return false; |
||
563 | } |
||
564 | } else { |
||
565 | $this->resolveJob(self::JOB_FAILURE, translate('ERR_CURL', 'SchedulersJobs')); |
||
566 | } |
||
567 | 1 | } elseif ($exJob[0] == 'class') { |
|
568 | $tmpJob = new $exJob[1](); |
||
569 | if($tmpJob instanceof RunnableSchedulerJob) |
||
570 | { |
||
571 | // set up the current user and drop session |
||
572 | if(!$this->setJobUser()) { |
||
573 | return false; |
||
574 | } |
||
575 | $tmpJob->setJob($this); |
||
576 | $result = $tmpJob->run($this->data); |
||
577 | $this->restoreJobUser(); |
||
578 | if ($this->status == self::JOB_STATUS_RUNNING) { |
||
579 | // nobody updated the status yet - job class could do that |
||
580 | if ($result) { |
||
581 | $this->resolveJob(self::JOB_SUCCESS); |
||
582 | return true; |
||
583 | } else { |
||
584 | $this->resolveJob(self::JOB_FAILURE); |
||
585 | return false; |
||
586 | } |
||
587 | } else { |
||
588 | return $this->resolution != self::JOB_FAILURE; |
||
589 | } |
||
590 | } |
||
591 | else { |
||
592 | $this->resolveJob(self::JOB_FAILURE, sprintf(translate('ERR_JOBTYPE', 'SchedulersJobs'), strip_tags($this->target))); |
||
593 | } |
||
594 | } |
||
595 | else { |
||
596 | 1 | $this->resolveJob(self::JOB_FAILURE, sprintf(translate('ERR_JOBTYPE', 'SchedulersJobs'), strip_tags($this->target))); |
|
597 | } |
||
598 | 1 | return false; |
|
599 | } |
||
600 | |||
601 | } // end class Job |
||
602 | |||
603 | /** |
||
604 | * Runnable job queue job |
||
605 | * |
||
606 | */ |
||
607 | interface RunnableSchedulerJob |
||
0 ignored issues
–
show
|
|||
608 | { |
||
609 | /** |
||
610 | * @abstract |
||
611 | * @param SchedulersJob $job |
||
612 | */ |
||
613 | public function setJob(SchedulersJob $job); |
||
614 | |||
615 | /** |
||
616 | * @abstract |
||
617 | * |
||
618 | */ |
||
619 | public function run($data); |
||
620 | } |
||
621 |
Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code: