From e5007c210428a593aae09e259d31883dd2435402 Mon Sep 17 00:00:00 2001
From: Peter Rotich <peter@osticket.com>
Date: Mon, 11 Feb 2013 17:48:26 -0500
Subject: [PATCH] Move http url config to http.php Implement remote cron as api
 task (more to come)

---
 api/cron.php                  | 10 ++++---
 api/http.php                  | 11 +++++---
 api/urls.conf.php             | 11 --------
 include/api.cron.php          | 43 ++++++++++++++++++++++++++++++
 include/class.api.php         |  6 ++++-
 setup/cli/cleanup-codebase.sh |  1 +
 setup/scripts/rcron.php       | 50 +++++++++++++++++++++++++++++++++++
 7 files changed, 113 insertions(+), 19 deletions(-)
 delete mode 100644 api/urls.conf.php
 create mode 100644 include/api.cron.php
 create mode 100755 setup/scripts/rcron.php

diff --git a/api/cron.php b/api/cron.php
index a8874e3b7..2e605713e 100644
--- a/api/cron.php
+++ b/api/cron.php
@@ -2,7 +2,7 @@
 /*********************************************************************
     cron.php
 
-    File to handle cron job calls (local and remote).
+    File to handle LOCAL cron job calls.
 
     Peter Rotich <peter@osticket.com>
     Copyright (c)  2006-2012 osTicket
@@ -13,9 +13,11 @@
 
     vim: expandtab sw=4 ts=4 sts=4:
 **********************************************************************/
+if (substr(php_sapi_name(), 0, 3) != 'cli')
+    die('cron.php only supports local cron jobs - use http -> api/task/cron');
+
 @chdir(realpath(dirname(__FILE__)).'/'); //Change dir.
 require('api.inc.php');
-require_once(INCLUDE_DIR.'class.cron.php');
-Cron::run();
-$ost->logDebug('Cron Job','External cron job executed ['.$_SERVER['REMOTE_ADDR'].']');
+require_once(INCLUDE_DIR.'api.cron.php');
+LocalCronApiController::call();
 ?>
diff --git a/api/http.php b/api/http.php
index 3d0c99ad3..fce841e7e 100644
--- a/api/http.php
+++ b/api/http.php
@@ -17,9 +17,14 @@ require 'api.inc.php';
 
 # Include the main api urls
 require_once INCLUDE_DIR."class.dispatcher.php";
-$dispatcher = Dispatcher::include_urls("urls.conf.php");
 
-# Call the respective function
-$dispatcher->resolve($_SERVER['PATH_INFO']);
+$dispatcher = patterns('',
+        url_post("^/tickets\.(?P<format>xml|json|email)$", array('api.tickets.php:TicketApiController','create')),
+        url('^/task/', patterns('',
+                url_get("^cron$", array('api.cron.php:CronApiController', 'execute'))
+         ))
+        );
 
+# Call the respective function
+print $dispatcher->resolve($_SERVER['PATH_INFO']);
 ?>
diff --git a/api/urls.conf.php b/api/urls.conf.php
deleted file mode 100644
index 99edefedc..000000000
--- a/api/urls.conf.php
+++ /dev/null
@@ -1,11 +0,0 @@
-<?php
-
-# What about patterns("api.tickets.php:TicketApiController", ...) since if the
-# class is given as the prefix, it isn't defined in more than one file. This
-# would allow for speficying imports only if an item is defined in a
-# different class (with the array("class", "method") syntax)
-return patterns('api.tickets.php:TicketApiController',
-    url_post("^/tickets\.(?P<format>xml|json|email)$", 'create')
-);
-
-?>
diff --git a/include/api.cron.php b/include/api.cron.php
new file mode 100644
index 000000000..912fff410
--- /dev/null
+++ b/include/api.cron.php
@@ -0,0 +1,43 @@
+<?php
+
+include_once INCLUDE_DIR.'class.cron.php';
+
+class CronApiController extends ApiController {
+
+    function execute() {
+
+        if(!($key=$this->requireApiKey()) || !$key->canExecuteCronJob())
+            return $this->exerr(401, 'API key not authorized');
+
+        $this->run();
+    }
+
+    /* private */
+    function run() {
+        global $ost;
+
+        Cron::run();
+       
+        $ost->logDebug('Cron Job','Cron job executed ['.$_SERVER['REMOTE_ADDR'].']');
+        $this->response(200,'Completed');
+    }
+}
+
+class LocalCronApiController extends CronApiController {
+
+    function response($code, $resp) {
+
+        if($code == 200) //Success - exit silently.
+            exit(0);
+        
+        //On error echo the response (error)
+        echo $resp;
+        exit(1);
+    }
+        
+    function call() {
+        $cron = new LocalCronApiController();
+        $cron->run();
+    }
+}
+?>
diff --git a/include/class.api.php b/include/class.api.php
index 67f47b635..48e968df5 100644
--- a/include/class.api.php
+++ b/include/class.api.php
@@ -71,6 +71,10 @@ class API {
         return ($this->ht['can_create_tickets']);
     }
 
+    function canExecuteCronjob() {
+        return true;
+    }
+
     function update($vars, &$errors) {
 
         if(!API::save($this->getId(), $vars, $errors))
@@ -166,7 +170,7 @@ class ApiController {
         # header
 
         if(!($key=$this->getApiKey()))
-            return $this->exerr(401, 'API key required');
+            return $this->exerr(401, 'Valid API key required');
         elseif (!$key->isActive() || $key->getIPAddr()!=$_SERVER['REMOTE_ADDR'])
             return $this->exerr(401, 'API key not found/active or source IP not authorized');
 
diff --git a/setup/cli/cleanup-codebase.sh b/setup/cli/cleanup-codebase.sh
index eefa0f8e8..40586b18c 100644
--- a/setup/cli/cleanup-codebase.sh
+++ b/setup/cli/cleanup-codebase.sh
@@ -39,6 +39,7 @@ images/ticket_status_title.jpg
 include/settings.php
 
 # Removed in 1.7.0
+api/urls.conf.php
 images/bg.gif
 images/fibres.png
 images/home.gif
diff --git a/setup/scripts/rcron.php b/setup/scripts/rcron.php
new file mode 100755
index 000000000..fb1d4b1cc
--- /dev/null
+++ b/setup/scripts/rcron.php
@@ -0,0 +1,50 @@
+#!/usr/bin/php -q
+<?php
+/*********************************************************************
+    rcron.php
+
+    PHP script used for remote cron calls.
+
+    Peter Rotich <peter@osticket.com>
+    Copyright (c)  2006-2013 osTicket
+    http://www.osticket.com
+
+    Released under the GNU General Public License WITHOUT ANY WARRANTY.
+    See LICENSE.TXT for details.
+
+    vim: expandtab sw=4 ts=4 sts=4:
+**********************************************************************/
+
+# Configuration: Enter the url and key. That is it.
+#  url => URL to api/task/cron e.g http://yourdomain.com/support/api/task/cron
+#  key => API's Key (see admin panel on how to generate a key)
+#
+
+$config = array(
+        'url'=>'http://yourdomain.com/support/api/task/cron',
+        'key'=>'API KEY HERE'
+        );
+
+#pre-checks
+function_exists('curl_version') or die('CURL support required');
+
+#set timeout
+set_time_limit(30);
+
+#curl post
+$ch = curl_init();        
+curl_setopt($ch, CURLOPT_URL, $config['url']);        
+curl_setopt($ch, CURLOPT_USERAGENT, 'osTicket API Client v1.7');
+curl_setopt($ch, CURLOPT_HEADER, TRUE);
+curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Expect:', 'X-API-Key: '.$config['key']));
+curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
+curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
+$result=curl_exec($ch);        
+curl_close($ch);
+
+if(preg_match('/HTTP\/.* ([0-9]+) .*/', $result, $status) && $status[1] == 200)
+    exit(0);
+
+echo $result;
+exit(1);
+?>
-- 
GitLab