| @@ -0,0 +1,72 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| attachment.php | ||
| Attachments interface for clients. | ||
| Clients should never see the dir paths. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: attachment.php,v 1.1.2.2 2010/04/15 14:33:55 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| require('secure.inc.php'); | ||
| //TODO: alert admin on any error on this file. | ||
| if(!$thisclient || !$thisclient->isClient() || !$_GET['id'] || !$_GET['ref']) die($trl->translate("TEXT_ACCESS_DENIED")); | ||
|
|
||
| $sql='SELECT attach_id,ref_id,ticket.ticket_id,ticketID,ticket.created,dept_id,file_name,file_key,email FROM '.TICKET_ATTACHMENT_TABLE. | ||
| ' LEFT JOIN '.TICKET_TABLE.' ticket USING(ticket_id) '. | ||
| ' WHERE attach_id='.db_input($_GET['id']); | ||
| //valid ID?? | ||
| if(!($resp=db_query($sql)) || !db_num_rows($resp)) die('Invalid/unknown file'); | ||
| list($id,$refid,$tid,$extid,$date,$deptID,$filename,$key,$email)=db_fetch_row($resp); | ||
|
|
||
| //Still paranoid...:)...check the secret session based hash and email | ||
| $hash=MD5($tid*$refid.session_id()); | ||
| if(!$_GET['ref'] || strcmp($hash,$_GET['ref']) || strcasecmp($thisclient->getEmail(),$email)) die('Access denied: Kwaheri'); | ||
|
|
||
|
|
||
| //see if the file actually exits. | ||
| $month=date('my',strtotime("$date")); | ||
| $file=rtrim($cfg->getUploadDir(),'/')."/$month/$key".'_'.$filename; | ||
| if(!file_exists($file)) | ||
| $file=rtrim($cfg->getUploadDir(),'/')."/$key".'_'.$filename; | ||
|
|
||
| if(!file_exists($file)) die('Invalid Attachment'); | ||
|
|
||
| $extension =substr($filename,-3); | ||
| switch(strtolower($extension)) | ||
| { | ||
| case "pdf": $ctype="application/pdf"; break; | ||
| case "exe": $ctype="application/octet-stream"; break; | ||
| case "zip": $ctype="application/zip"; break; | ||
| case "doc": $ctype="application/msword"; break; | ||
| case "xls": $ctype="application/vnd.ms-excel"; break; | ||
| case "ppt": $ctype="application/vnd.ms-powerpoint"; break; | ||
| case "gif": $ctype="image/gif"; break; | ||
| case "png": $ctype="image/png"; break; | ||
| case "jpg": $ctype="image/jpg"; break; | ||
| default: $ctype="application/force-download"; | ||
| } | ||
| header("Pragma: public"); | ||
| header("Expires: 0"); | ||
| header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); | ||
| header("Cache-Control: public"); | ||
| header("Content-Type: $ctype"); | ||
| $user_agent = strtolower ($_SERVER["HTTP_USER_AGENT"]); | ||
| if ((is_integer(strpos($user_agent,"msie"))) && (is_integer(strpos($user_agent,"win")))) | ||
| { | ||
| header( "Content-Disposition: filename=".basename($filename).";" ); | ||
| } else { | ||
| header( "Content-Disposition: attachment; filename=".basename($filename).";" ); | ||
| } | ||
| header("Content-Transfer-Encoding: binary"); | ||
| header("Content-Length: ".filesize($file)); | ||
| readfile($file); | ||
| exit(); | ||
| ?> |
| @@ -0,0 +1,22 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| captcha.php | ||
| Simply returns captcha image. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: captcha.php,v 1.1.2.2 2010/04/15 14:34:05 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| require_once('main.inc.php'); | ||
| require(INCLUDE_DIR.'class.captcha.php'); | ||
|
|
||
| $captcha = new Captcha(5,12,ROOT_DIR.'images/captcha/'); | ||
| echo $captcha->getImage(); | ||
| ?> |
| @@ -0,0 +1,60 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| client.inc.php | ||
| File included on every client page | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: $ | ||
| **********************************************************************/ | ||
| if(!strcasecmp(basename($_SERVER['SCRIPT_NAME']),basename(__FILE__))) die('kwaheri rafiki!'); | ||
|
|
||
| if(!file_exists('main.inc.php')) die('Fatal Error.'); | ||
|
|
||
| require_once('main.inc.php'); | ||
|
|
||
| if(!defined('INCLUDE_DIR')) die('Fatal error'); | ||
|
|
||
| /*Some more include defines specific to client only */ | ||
| define('CLIENTINC_DIR',INCLUDE_DIR.'client/'); | ||
| define('OSTCLIENTINC',TRUE); | ||
|
|
||
| //Check the status of the HelpDesk. | ||
| if(!is_object($cfg) || !$cfg->getId() || $cfg->isHelpDeskOffline()) { | ||
| include('./offline.php'); | ||
| exit; | ||
| } | ||
|
|
||
| //Forced upgrade? Version mismatch. | ||
| if(defined('THIS_VERSION') && strcasecmp($cfg->getVersion(),THIS_VERSION)) { | ||
| die('System is offline for an upgrade.'); | ||
| exit; | ||
| } | ||
|
|
||
| /* include what is needed on client stuff */ | ||
| require_once(INCLUDE_DIR.'class.client.php'); | ||
| require_once(INCLUDE_DIR.'class.ticket.php'); | ||
| require_once(INCLUDE_DIR.'class.dept.php'); | ||
|
|
||
| //clear some vars | ||
| $errors=array(); | ||
| $msg=''; | ||
| $thisclient=null; | ||
| //Make sure the user is valid..before doing anything else. | ||
| if($_SESSION['_client']['userID'] && $_SESSION['_client']['key']) | ||
| $thisclient = new ClientSession($_SESSION['_client']['userID'],$_SESSION['_client']['key']); | ||
|
|
||
| //print_r($_SESSION); | ||
| //is the user logged in? | ||
| if($thisclient && $thisclient->getId() && $thisclient->isValid()){ | ||
| $thisclient->refreshSession(); | ||
| } | ||
|
|
||
| ?> |
| @@ -0,0 +1,2 @@ | ||
| ost-config.primeiro.teste.php | ||
| ost-config.php |
| @@ -0,0 +1 @@ | ||
| Deny from all |
| @@ -0,0 +1,40 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| ajax.kbase.php | ||
| AJAX interface for knowledge base related...allowed methods. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: ajax.kbase.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| if(!defined('OSTAJAXINC') || !defined('INCLUDE_DIR')) die('!'); | ||
|
|
||
| class KbaseAjaxAPI{ | ||
|
|
||
| function cannedResp($params) { | ||
|
|
||
| $sql='SELECT answer FROM '.KB_PREMADE_TABLE.' WHERE isenabled=1 AND premade_id='.db_input($params['id']); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) | ||
| list($response)=db_fetch_row($res); | ||
|
|
||
| if($response && $params['tid'] && strpos($response,'%')!==false) { | ||
| include_once(INCLUDE_DIR.'class.ticket.php'); | ||
|
|
||
| $ticket = new Ticket($params['tid']); | ||
| if($ticket && $ticket->getId()){ | ||
| $response=$ticket->replaceTemplateVars($response); | ||
| } | ||
| } | ||
|
|
||
| return $response; | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,141 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| ajax.tickets.php | ||
| AJAX interface for tickets | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: ajax.tickets.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| if(!defined('OSTAJAXINC') || !defined('INCLUDE_DIR')) die('403'); | ||
|
|
||
| include_once(INCLUDE_DIR.'class.ticket.php'); | ||
|
|
||
| class TicketsAjaxAPI{ | ||
|
|
||
| function searchbyemail($params) { | ||
|
|
||
| $input = db_input(strtolower($params['input']),false); | ||
| $len = strlen($input); | ||
| $limit = isset($params['limit']) ? (int) $params['limit']:25; | ||
| $items=array(); | ||
| $sql='SELECT DISTINCT email,name FROM '.TICKET_TABLE.' WHERE email LIKE \''.$input.'%\' ORDER BY created LIMIT '.$limit; | ||
| $resp=db_query($sql); | ||
| if($resp && db_num_rows($resp)){ | ||
| while(list($email,$name)=db_fetch_row($resp)) { | ||
| $name=(strpos($name,'@')===false)?$name:''; | ||
| $items[] ='{"id": "'.$email.'", "value": "'.$email.'", "info": "'.$name.'"}'; | ||
| } | ||
| } | ||
| $result= '{"results": ['.implode(", ", $items).']}'; | ||
| return $result; | ||
| } | ||
|
|
||
| function search($params) { | ||
|
|
||
| $input = db_input(strtolower($params['input']),false); | ||
| $len = strlen($input); | ||
| $limit = isset($params['limit']) ? (int) $params['limit']:25; | ||
| $items=array(); | ||
| $ticketid=false; | ||
| if(is_numeric($input)) { | ||
| $WHERE=' WHERE ticketID LIKE \''.$input.'%\''; | ||
| $ticketid=true; | ||
| }else{ | ||
| $WHERE=' WHERE email LIKE \''.$input.'%\''; | ||
| } | ||
| $sql='SELECT DISTINCT ticketID,email FROM '.TICKET_TABLE.' '.$WHERE.' ORDER BY created LIMIT '.$limit; | ||
| $resp=db_query($sql); | ||
| if($resp && db_num_rows($resp)){ | ||
| while(list($id,$email)=db_fetch_row($resp)) { | ||
| $info=($ticketid)?$email:$id; | ||
| $id=($ticketid)?$id:$email; | ||
| $items[] ='{"id": "'.$id.'", "value": "'.$id.'", "info": "'.$info.'"}'; | ||
| } | ||
| } | ||
| $result= '{"results": ['.implode(", ", $items).']}'; | ||
| return $result; | ||
| } | ||
|
|
||
| function acquireLock($params) { | ||
| global $cfg,$thisuser; | ||
|
|
||
| if(!$params['tid'] or !is_numeric($params['tid'])) | ||
| return 0; | ||
|
|
||
| $ticket = new Ticket($params['tid']); | ||
|
|
||
| if(!$ticket || (!$thisuser->canAccessDept($ticket->getDeptId()) && ($ticket->isAssigned() && $thisuser->getId()!=$ticket->getStaffId()))) | ||
| return '{"id":0, "retry":false}'; | ||
|
|
||
| //is the ticket already locked? | ||
| if($ticket->isLocked() && ($lock=$ticket->getLock()) && !$lock->isExpired()) { | ||
| /*Note: Ticket->acquireLock does the same logic...but we need it here since we need to know who owns the lock up front*/ | ||
|
|
||
| //Ticket is locked by someone else.?? | ||
| if($lock->getStaffId()!=$thisuser->getId()) | ||
| return '{"id":0, "retry":false}'; | ||
|
|
||
| //Ticket already locked by staff...try renewing it. | ||
| $lock->renew(); //New clock baby! | ||
|
|
||
| return '{"id":'.$lock->getId().', "time":'.$lock->getTime().'}'; | ||
| } | ||
|
|
||
| //Ticket is not locked or the lock is expired...try locking it... | ||
| if(($lock=$ticket->acquireLock())) //Set the lock. | ||
| return '{"id":'.$lock->getId().', "time":'.$lock->getTime().'}'; | ||
|
|
||
| //unable to obtain the lock..for some really weired reason! | ||
| return '{"id":0, "retry":true}'; //Client should watch for possible loop on retries. Max attempts? | ||
| } | ||
|
|
||
| function renewLock($params) { | ||
| global $thisuser; | ||
|
|
||
| if(!$params['id'] or !is_numeric($params['id'])) | ||
| return '{"id":0, "retry":true}'; | ||
|
|
||
| $lock= new TicketLock($params['id']); | ||
|
|
||
| if(!$lock->load() || !$lock->getStaffId() || $lock->isExpired()) //Said lock doesn't exist or is is expired | ||
| return TicketsAjaxAPI::acquireLock($params); //acquire the lock | ||
|
|
||
| if($lock->getStaffId()!=$thisuser->getId()) //user doesn't own the lock anymore??? sorry...try to next time. | ||
| return '{"id":0, "retry":false}'; //Give up... | ||
|
|
||
| //Renew the lock. | ||
| $lock->renew(); //Failure here is not an issue since the lock is not expired yet.. | ||
|
|
||
| return '{"id":'.$lock->getId().', "time":'.$lock->getTime().'}'; | ||
| } | ||
|
|
||
| function releaseLock($params) { | ||
| global $thisuser; | ||
|
|
||
| if($params['id'] && is_numeric($params['id'])){ //Lock Id provided! | ||
|
|
||
| $lock= new TicketLock($params['id']); | ||
| //Already gone? | ||
| if(!$lock->load() || !$lock->getStaffId() || $lock->isExpired()) //Said lock doesn't exist or is is expired | ||
| return 1; | ||
|
|
||
| //make sure the user actually owns the lock before releasing it. | ||
| return ($lock->getStaffId()==$thisuser->getId() && $lock->release())?1:0; | ||
|
|
||
| }elseif($params['tid']){ //release all the locks the user owns on the ticket. | ||
| return TicketLock::removeStaffLocks($thisuser->getId(),$params['tid'])?1:0; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,89 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.api.php | ||
| Api related functions... | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.api.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| class Api { | ||
|
|
||
|
|
||
| function add($ip,&$errors) { | ||
| global $cfg; | ||
|
|
||
| $passphrase=$cfg->getAPIPassphrase(); | ||
|
|
||
| if(!$passphrase) | ||
| $errors['err']='API passphrase missing.'; | ||
|
|
||
| if(!$ip || !Validator::is_ip($ip)) | ||
| $errors['ip']='Valid IP required'; | ||
| elseif(Api::getKey($ip)) | ||
| $errors['ip']='API key for the IP already exists'; | ||
|
|
||
| $id=0; | ||
| if(!$errors) { | ||
| $sql='INSERT INTO '.API_KEY_TABLE.' SET created=NOW(), updated=NOW(), isactive=1'. | ||
| ',ipaddr='.db_input($ip). | ||
| ',apikey='.db_input(strtoupper(md5($ip.md5($passphrase)))); //Security of the apikey is not as critical at the moment | ||
|
|
||
| if(db_query($sql)) | ||
| $id=db_insert_id(); | ||
|
|
||
| } | ||
|
|
||
| return $id; | ||
| } | ||
|
|
||
| function setPassphrase($phrase,&$errors) { | ||
| global $cfg; | ||
|
|
||
| if(!$phrase) | ||
| $errors['phrase']='Required'; | ||
| elseif(str_word_count($_POST['phrase'])<3) | ||
| $errors['phrase']='Must be at least 3 words long.'; | ||
| elseif(!strcmp($cfg->getAPIPassphrase(),$phrase)) | ||
| $errors['phrase']='Already set'; | ||
| else{ | ||
| $sql='UPDATE '.CONFIG_TABLE.' SET updated=NOW(), api_passphrase='.db_input($phrase). | ||
| ' WHERE id='.db_input($cfg->getId()); | ||
| if(db_query($sql) && db_affected_rows()){ | ||
| $cfg->reload(); | ||
| return true; | ||
| } | ||
|
|
||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
|
|
||
| function getKey($ip) { | ||
|
|
||
| $key=null; | ||
| $resp=db_query('SELECT apikey FROM '.API_KEY_TABLE.' WHERE ipaddr='.db_input($ip)); | ||
| if($resp && db_num_rows($resp)) | ||
| list($key)=db_fetch_row($resp); | ||
|
|
||
| return $key; | ||
| } | ||
|
|
||
|
|
||
| function validate($key,$ip) { | ||
|
|
||
| $resp=db_query('SELECT id FROM '.API_KEY_TABLE.' WHERE ipaddr='.db_input($ip).' AND apikey='.db_input($key)); | ||
| return ($resp && db_num_rows($resp))?true:false; | ||
|
|
||
| } | ||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,33 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.banlist.php | ||
| Banned emails handle. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.banlist.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| class Banlist { | ||
|
|
||
| function add($email,$submitter='') { | ||
| $sql='INSERT IGNORE INTO '.BANLIST_TABLE.' SET added=NOW(),email='.db_input($email).',submitter='.db_input($submitter); | ||
| return (db_query($sql) && ($id=db_insert_id()))?$id:0; | ||
| } | ||
|
|
||
| function remove($email) { | ||
| $sql='DELETE FROM '.BANLIST_TABLE.' WHERE email='.db_input($email); | ||
| return (db_query($sql) && db_affected_rows())?true:false; | ||
| } | ||
|
|
||
| function isbanned($email) { | ||
| return db_num_rows(db_query('SELECT id FROM '.BANLIST_TABLE.' WHERE email='.db_input($email)))?true:false; | ||
| } | ||
| } |
| @@ -0,0 +1,55 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.captcha.php | ||
| Very basic captcha class. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: $ | ||
| **********************************************************************/ | ||
| class Captcha { | ||
| var $hash; | ||
| var $bgimages=array('cottoncandy.png','grass.png','ripple.png','silk.png','whirlpool.png', | ||
| 'bubbles.png','crackle.png','lines.png','sand.png','snakeskin.png'); | ||
| var $font = 10; | ||
| function Captcha($len=6,$font=7,$bg=''){ | ||
|
|
||
| $this->hash = strtoupper(substr(md5(rand(0, 9999)),rand(0, 24),$len)); | ||
| $this->font = $font; | ||
|
|
||
| if($bg && !is_dir($bg)){ //bg file provided? | ||
| $this->bgimg=$bg; | ||
| }else{ //assume dir provided or defaults to local. | ||
| $this->bgimg=rtrim($bg,'/').'/'.$this->bgimages[array_rand($this->bgimages, 1)]; | ||
| } | ||
| } | ||
|
|
||
| function getImage(){ | ||
|
|
||
| if(!extension_loaded('gd') || !function_exists('gd_info')) //GD ext required. | ||
| return; | ||
|
|
||
| $_SESSION['captcha'] =''; //Clear | ||
|
|
||
| list($w,$h) = getimagesize($this->bgimg); | ||
| $x = round(($w/2)-((strlen($this->hash)*imagefontwidth($this->font))/2), 1); | ||
| $y = round(($h/2)-(imagefontheight($this->font)/2)); | ||
|
|
||
| $img= imagecreatefrompng($this->bgimg); | ||
| imagestring($img,$this->font, $x, $y,$this->hash,imagecolorallocate($img,0, 0, 0)); | ||
|
|
||
| Header ("(captcha-content-type:) image/png"); | ||
| imagepng($img); | ||
| imagedestroy($img); | ||
| $_SESSION['captcha'] = md5($this->hash); | ||
| } | ||
| } | ||
|
|
||
| ?> |
| @@ -0,0 +1,88 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.client.php | ||
| Handles everything about client | ||
| The class will undergo major changes one client's accounts are used. | ||
| At the moment we will play off the email + ticket ID authentication. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.client.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| class Client { | ||
|
|
||
|
|
||
| var $id; | ||
| var $fullname; | ||
| var $username; | ||
| var $passwd; | ||
| var $email; | ||
|
|
||
|
|
||
| var $udata; | ||
| var $ticket_id; | ||
| var $ticketID; | ||
|
|
||
| function Client($email,$id){ | ||
| $this->id =0; | ||
| return ($this->lookup($id,$email)); | ||
| } | ||
|
|
||
| function isClient(){ | ||
| return TRUE; | ||
| } | ||
|
|
||
| function lookup($id,$email=''){ | ||
| $sql='SELECT ticket_id,ticketID,name,email FROM '.TICKET_TABLE.' WHERE ticketID='.db_input($id); | ||
| if($email){ //don't validate...using whatever is entered. | ||
| $sql.=' AND email='.db_input($email); | ||
| } | ||
| $res=db_query($sql); | ||
| if(!$res || !db_num_rows($res)) | ||
| return NULL; | ||
|
|
||
| /* Faking most of the stuff for now till we start using accounts.*/ | ||
| $row=db_fetch_array($res); | ||
| $this->udata=$row; | ||
| $this->id = $row['ticketID']; //placeholder | ||
| $this->ticket_id = $row['ticket_id']; | ||
| $this->ticketID = $row['ticketID']; | ||
| $this->fullname = ucfirst($row['name']); | ||
| $this->username = $row['email']; | ||
| $this->email = $row['email']; | ||
|
|
||
| return($this->id); | ||
| } | ||
|
|
||
|
|
||
| function getId(){ | ||
| return $this->id; | ||
| } | ||
|
|
||
| function getEmail(){ | ||
| return($this->email); | ||
| } | ||
|
|
||
| function getUserName(){ | ||
| return($this->username); | ||
| } | ||
|
|
||
| function getName(){ | ||
| return($this->fullname); | ||
| } | ||
|
|
||
| function getTicketID() { | ||
| return $this->ticketID; | ||
| } | ||
| } | ||
|
|
||
| ?> |
| @@ -0,0 +1,44 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.cron.php | ||
| Nothing special...just a central location for all cron calls. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 osTicket | ||
| http://www.osticket.com | ||
| Released under the GNU General Public License WITHOUT ANY WARRANTY. | ||
| See LICENSE.TXT for details. | ||
| TODO: The plan is to make cron jobs db based. | ||
| vim: expandtab sw=4 ts=4 sts=4: | ||
| $Id: class.cron.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| //TODO: Make it DB based! | ||
| class Cron { | ||
|
|
||
| function MailFetcher() { | ||
| require_once(INCLUDE_DIR.'class.mailfetch.php'); | ||
| MailFetcher::fetchMail(); //Fetch mail..frequency is limited by email account setting. | ||
| } | ||
|
|
||
| function TicketMonitor() { | ||
| require_once(INCLUDE_DIR.'class.ticket.php'); | ||
| require_once(INCLUDE_DIR.'class.lock.php'); | ||
| Ticket::checkOverdue(); //Make stale tickets overdue | ||
| TicketLock::cleanup(); //Remove expired locks | ||
| } | ||
|
|
||
| function PurgeLogs() { | ||
| Sys::purgeLogs(); | ||
| } | ||
|
|
||
| function run(){ //called by outside cron NOT autocron | ||
| Cron::MailFetcher(); | ||
| Cron::TicketMonitor(); | ||
| cron::PurgeLogs(); | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,265 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.dept.php | ||
| Department class | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.dept.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| class Dept { | ||
| var $id; | ||
| var $name; | ||
| var $signature; | ||
|
|
||
| var $tplId; | ||
|
|
||
| var $emailId; | ||
| var $email; | ||
|
|
||
| var $autorespEmail; | ||
|
|
||
| var $managerId; | ||
| var $manager; | ||
|
|
||
| var $row; | ||
|
|
||
| function Dept($id=0){ | ||
| $this->id=0; | ||
| if($id && ($info=$this->getInfoById($id))){ | ||
| $this->row=$info; | ||
| $this->id=$info['dept_id']; | ||
| $this->tplId=$info['tpl_id']; | ||
| $this->emailId=$info['email_id']; | ||
| $this->managerId=$info['manager_id']; | ||
| $this->deptname=$info['dept_name']; | ||
| $this->signature=$info['dept_signature']; | ||
| $this->getEmail(); //Auto load email struct. | ||
| } | ||
| } | ||
|
|
||
| function getId(){ | ||
| return $this->id; | ||
| } | ||
|
|
||
| function getName(){ | ||
| return $this->deptname; | ||
| } | ||
|
|
||
|
|
||
| function getEmailId(){ | ||
| return $this->emailId; | ||
| } | ||
|
|
||
| function getEmail(){ | ||
|
|
||
| if(!$this->email && $this->emailId) | ||
| $this->email= new Email($this->emailId); | ||
|
|
||
| return $this->email; | ||
| } | ||
|
|
||
| function getTemplateId() { | ||
| return $this->tplId; | ||
| } | ||
|
|
||
| function getAutoRespEmail() { | ||
|
|
||
| if(!$this->autorespEmail && $this->row['autoresp_email_id']) | ||
| $this->autorespEmail= new Email($this->row['autoresp_email_id']); | ||
| else // Defualt to dept email if autoresp is not specified. | ||
| $this->autorespEmail= $this->getEmail(); | ||
|
|
||
| return $this->autorespEmail; | ||
| } | ||
|
|
||
| function getEmailAddress() { | ||
| return $this->email?$this->email->getAddress():null; | ||
| } | ||
|
|
||
| function getSignature() { | ||
|
|
||
| return $this->signature; | ||
| } | ||
|
|
||
| function canAppendSignature() { | ||
| return ($this->signature && $this->row['can_append_signature'])?true:false; | ||
| } | ||
|
|
||
| function getManagerId(){ | ||
| return $this->managerId; | ||
| } | ||
|
|
||
| function getManager(){ | ||
|
|
||
| if(!$this->manager && $this->managerId) | ||
| $this->manager= new Staff($this->managerId); | ||
|
|
||
| return $this->manager; | ||
| } | ||
|
|
||
| function isPublic() { | ||
| return $this->row['ispublic']?true:false; | ||
| } | ||
|
|
||
| function autoRespONNewTicket() { | ||
| return $this->row['ticket_auto_response']?true:false; | ||
| } | ||
|
|
||
| function autoRespONNewMessage() { | ||
| return $this->row['message_auto_response']?true:false; | ||
| } | ||
|
|
||
| function noreplyAutoResp(){ | ||
| return $this->row['noreply_autoresp']?true:false; | ||
| } | ||
|
|
||
| function getInfo() { | ||
| return $this->row; | ||
| } | ||
|
|
||
| function update($vars,&$errors) { | ||
| if($this->save($this->getId(),$vars,$errors)){ | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| function getInfoById($id) { | ||
| $sql='SELECT * FROM '.DEPT_TABLE.' WHERE dept_id='.db_input($id); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) | ||
| return db_fetch_array($res); | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
|
|
||
| function getIdByName($name) { | ||
| $id=0; | ||
| $sql ='SELECT dept_id FROM '.DEPT_TABLE.' WHERE dept_name='.db_input($name); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) | ||
| list($id)=db_fetch_row($res); | ||
|
|
||
| return $id; | ||
| } | ||
|
|
||
| function getIdByEmail($email) { | ||
| $id=0; | ||
| $sql ='SELECT dept_id FROM '.DEPT_TABLE.' WHERE dept_email='.db_input($email); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) | ||
| list($id)=db_fetch_row($res); | ||
|
|
||
| return $id; | ||
| } | ||
|
|
||
| function getNameById($id) { | ||
| $sql ='SELECT dept_name FROM '.DEPT_TABLE.' WHERE dept_id='.db_input($id); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) | ||
| list($name)=db_fetch_row($res); | ||
| return $name; | ||
| } | ||
|
|
||
| function getDefaultDeptName() { | ||
| global $cfg; | ||
| return Dept::getNameById($cfg->getDefaultDeptId()); | ||
| } | ||
|
|
||
|
|
||
| function create($vars,&$errors) { | ||
| return Dept::save(0,$vars,$errors); | ||
| } | ||
|
|
||
|
|
||
| function delete($id) { | ||
| global $cfg; | ||
| if($id==$cfg->getDefaultDeptId()) | ||
| return 0; | ||
|
|
||
| $sql='DELETE FROM '.DEPT_TABLE.' WHERE dept_id='.db_input($id); | ||
| if(db_query($sql) && ($num=db_affected_rows())){ | ||
| // DO SOME HOUSE CLEANING | ||
| //TODO: Do insert select internal note... | ||
| //Move tickets to default Dept. | ||
| db_query('UPDATE '.TICKET_TABLE.' SET dept_id='.db_input($cfg->getDefaultDeptId()).' WHERE dept_id='.db_input($id)); | ||
| //Move Dept members | ||
| //This should never happen..since delete should be issued only to empty Depts...but check it anyways | ||
| db_query('UPDATE '.STAFF_TABLE.' SET dept_id='.db_input($cfg->getDefaultDeptId()).' WHERE dept_id='.db_input($id)); | ||
| //make help topic using the dept default to default-dept. | ||
| db_query('UPDATE '.TOPIC_TABLE.' SET dept_id='.db_input($cfg->getDefaultDeptId()).' WHERE dept_id='.db_input($id)); | ||
| return $num; | ||
| } | ||
| return 0; | ||
|
|
||
| } | ||
|
|
||
| function save($id,$vars,&$errors) { | ||
| global $cfg; | ||
|
|
||
| if($id && $id!=$_POST['dept_id']) | ||
| $errors['err']='Missing or invalid Dept ID'; | ||
|
|
||
| if(!$_POST['email_id'] || !is_numeric($_POST['email_id'])) | ||
| $errors['email_id']='Dept email required'; | ||
|
|
||
| if(!is_numeric($_POST['tpl_id'])) | ||
| $errors['tpl_id']='Template required'; | ||
|
|
||
| if(!$_POST['dept_name']) { | ||
| $errors['dept_name']='Dept name required'; | ||
| }elseif(strlen($_POST['dept_name'])<4) { | ||
| $errors['dept_name']='Dept name must be at least 4 chars.'; | ||
| }else{ | ||
| $sql='SELECT dept_id FROM '.DEPT_TABLE.' WHERE dept_name='.db_input($_POST['dept_name']); | ||
| if($id) | ||
| $sql.=' AND dept_id!='.db_input($id); | ||
|
|
||
| if(db_num_rows(db_query($sql))) | ||
| $errors['dept_name']='Department already exist'; | ||
| } | ||
|
|
||
| if($_POST['ispublic'] && !$_POST['dept_signature']) | ||
| $errors['dept_signature']='Signature required'; | ||
|
|
||
| if(!$_POST['ispublic'] && ($_POST['dept_id']==$cfg->getDefaultDeptId())) | ||
| $errors['ispublic']='Default department can not be private'; | ||
|
|
||
| if(!$errors){ | ||
|
|
||
| $sql=' SET updated=NOW() '. | ||
| ',ispublic='.db_input($_POST['ispublic']). | ||
| ',email_id='.db_input($_POST['email_id']). | ||
| ',tpl_id='.db_input($_POST['tpl_id']). | ||
| ',autoresp_email_id='.db_input($_POST['autoresp_email_id']). | ||
| ',manager_id='.db_input($_POST['manager_id']?$_POST['manager_id']:0). | ||
| ',dept_name='.db_input(Format::striptags($_POST['dept_name'])). | ||
| ',dept_signature='.db_input(Format::striptags($_POST['dept_signature'])). | ||
| ',ticket_auto_response='.db_input($_POST['ticket_auto_response']). | ||
| ',message_auto_response='.db_input($_POST['message_auto_response']). | ||
| ',can_append_signature='.db_input(isset($_POST['can_append_signature'])?1:0); | ||
|
|
||
| if($id) { | ||
| $sql='UPDATE '.DEPT_TABLE.' '.$sql.' WHERE dept_id='.db_input($id); | ||
| if(!db_query($sql) || !db_affected_rows()) | ||
| $errors['err']='Unable to update '.Format::input($_POST['dept_name']).' Dept. Error occured'; | ||
| }else{ | ||
| $sql='INSERT INTO '.DEPT_TABLE.' '.$sql.',created=NOW()'; | ||
| if(db_query($sql) && ($deptID=db_insert_id())) | ||
| return $deptID; | ||
|
|
||
| $errors['err']='Unable to create department. Internal error'; | ||
| } | ||
| } | ||
|
|
||
| return $errors?false:true; | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,166 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.format.php | ||
| Collection of helper function used for formatting | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.format.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
|
|
||
| class Format { | ||
|
|
||
|
|
||
| function file_size($bytes) { | ||
|
|
||
| if($bytes<1024) | ||
| return $bytes.' bytes'; | ||
| if($bytes <102400) | ||
| return round(($bytes/1024),1).' kb'; | ||
|
|
||
| return round(($bytes/1024000),1).' mb'; | ||
| } | ||
|
|
||
| function file_name($filename) { | ||
|
|
||
| $search = array('/ß/','/ä/','/Ä/','/ö/','/Ö/','/ü/','/Ü/','([^[:alnum:]._])'); | ||
| $replace = array('ss','ae','Ae','oe','Oe','ue','Ue','_'); | ||
| return preg_replace($search,$replace,$filename); | ||
| } | ||
|
|
||
| function phone($phone) { | ||
|
|
||
| $stripped= preg_replace("/[^0-9]/", "", $phone); | ||
| if(strlen($stripped) == 7) | ||
| return preg_replace("/([0-9]{3})([0-9]{4})/", "$1-$2",$stripped); | ||
| elseif(strlen($stripped) == 10) | ||
| return preg_replace("/([0-9]{3})([0-9]{3})([0-9]{4})/", "($1) $2-$3",$stripped); | ||
| else | ||
| return $phone; | ||
| } | ||
|
|
||
| function truncate($string,$len,$hard=false) { | ||
|
|
||
| if(!$len || $len>strlen($string)) | ||
| return $string; | ||
|
|
||
| $string = substr($string,0,$len); | ||
|
|
||
| return $hard?$string:(substr($string,0,strrpos($string,' ')).' ...'); | ||
| } | ||
|
|
||
| function strip_slashes($var){ | ||
| return is_array($var)?array_map(array('Format','strip_slashes'),$var):stripslashes($var); | ||
| } | ||
|
|
||
| function htmlchars($var) { | ||
| return is_array($var)?array_map(array('Format','htmlchars'),$var):htmlspecialchars($var,ENT_QUOTES); | ||
| } | ||
|
|
||
|
|
||
| //Same as htmlchars above but with ability to add extra checks...etc. | ||
| function input($var) { | ||
|
|
||
| /*: Moved to main.inc.php | ||
| if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) | ||
| $var=Format::strip_slashes($var); | ||
| */ | ||
| return Format::htmlchars($var); | ||
| } | ||
|
|
||
| //Format text for display.. | ||
| function display($text) { | ||
| global $cfg; | ||
|
|
||
| $text=Format::htmlchars($text); //take care of html special chars | ||
| if($cfg && $cfg->clickableURLS() && $text) | ||
| $text=Format::clickableurls($text); | ||
|
|
||
| //Wrap long words... | ||
| $text =preg_replace_callback('/\w{75,}/',create_function('$matches','return wordwrap($matches[0],70,"\n",true);'),$text); | ||
|
|
||
| return nl2br($text); | ||
| } | ||
|
|
||
| function striptags($string) { | ||
| return strip_tags(html_entity_decode($string)); //strip all tags ...no mercy! | ||
| } | ||
|
|
||
| //make urls clickable. Mainly for display | ||
| function clickableurls($text) { | ||
|
|
||
| //Not perfect but it works - please help improve it. | ||
| $text=preg_replace('/(((f|ht){1}tp(s?):\/\/)[-a-zA-Z0-9@:%_\+.~#?&;\/\/=]+)/','<a href="\\1" target="_blank">\\1</a>', $text); | ||
| $text=preg_replace("/(^|[ \\n\\r\\t])(www\.([a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+)(\/[^\/ \\n\\r]*)*)/", | ||
| '\\1<a href="http://\\2" target="_blank">\\2</a>', $text); | ||
| $text=preg_replace("/(^|[ \\n\\r\\t])([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4})/",'\\1<a href="mailto:\\2" target="_blank">\\2</a>', $text); | ||
|
|
||
| return $text; | ||
| } | ||
|
|
||
| function stripEmptyLines ( $string) { | ||
| //return preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $string); | ||
| //return preg_replace('/\s\s+/',"\n",$string); //Too strict?? | ||
| return preg_replace("/\n{3,}/", "\n\n", $string); | ||
| } | ||
|
|
||
|
|
||
| function linebreaks($string) { | ||
| return urldecode(ereg_replace("%0D", " ", urlencode($string))); | ||
| } | ||
|
|
||
| /* elapsed time */ | ||
| function elapsedTime($sec){ | ||
|
|
||
| if(!$sec || !is_numeric($sec)) return ""; | ||
|
|
||
| $days = floor($sec / 86400); | ||
| $hrs = floor(bcmod($sec,86400)/3600); | ||
| $mins = round(bcmod(bcmod($sec,86400),3600)/60); | ||
| if($days > 0) $tstring = $days . 'd,'; | ||
| if($hrs > 0) $tstring = $tstring . $hrs . 'h,'; | ||
| $tstring =$tstring . $mins . 'm'; | ||
|
|
||
| return $tstring; | ||
| } | ||
|
|
||
| /* Dates helpers...most of this crap will change once we move to PHP 5*/ | ||
| function db_date($time) { | ||
| global $cfg; | ||
| return Format::userdate($cfg->getDateFormat(),Misc::db2gmtime($time)); | ||
| } | ||
|
|
||
| function db_datetime($time) { | ||
| global $cfg; | ||
| return Format::userdate($cfg->getDateTimeFormat(),Misc::db2gmtime($time)); | ||
| } | ||
|
|
||
| function db_daydatetime($time) { | ||
| global $cfg; | ||
| return Format::userdate($cfg->getDayDateTimeFormat(),Misc::db2gmtime($time)); | ||
| } | ||
|
|
||
| function userdate($format,$gmtime) { | ||
| return Format::date($format,$gmtime,$_SESSION['TZ_OFFSET'],$_SESSION['daylight']); | ||
| } | ||
|
|
||
| function date($format,$gmtimestamp,$offset=0,$daylight=false){ | ||
| if(!$gmtimestamp || !is_numeric($gmtimestamp)) return ""; | ||
|
|
||
| $offset+=$daylight?date('I',$gmtimestamp):0; //Daylight savings crap. | ||
| return date($format,($gmtimestamp+($offset*3600))); | ||
| } | ||
|
|
||
|
|
||
|
|
||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,78 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.group.php | ||
| Groups | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: $ | ||
| **********************************************************************/ | ||
|
|
||
| class Group { | ||
|
|
||
| function update($id,$vars,&$errors) { | ||
| if($id && Group::save($id,$vars,$errors)){ | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| function create($vars,&$errors) { | ||
| return Group::save(0,$vars,$errors); | ||
| } | ||
|
|
||
| function save($id,$vars,&$errors) { | ||
|
|
||
| if($id && !$vars['group_id']) | ||
| $errors['err']='Missing or invalid group ID'; | ||
|
|
||
| if(!$vars['group_name']) { | ||
| $errors['group_name']='Group name required'; | ||
| }elseif(strlen($vars['group_name'])<5) { | ||
| $errors['group_name']='Group name must be at least 5 chars.'; | ||
| }else { | ||
| $sql='SELECT group_id FROM '.GROUP_TABLE.' WHERE group_name='.db_input($vars['group_name']); | ||
| if($id) | ||
| $sql.=' AND group_id!='.db_input($id); | ||
|
|
||
| if(db_num_rows(db_query($sql))) | ||
| $errors['group_name']='Group name already exists'; | ||
| } | ||
|
|
||
| if(!$errors){ | ||
|
|
||
| $sql=' SET updated=NOW(), group_name='.db_input(Format::striptags($vars['group_name'])). | ||
| ', group_enabled='.db_input($vars['group_enabled']). | ||
| ', dept_access='.db_input($vars['depts']?implode(',',$vars['depts']):''). | ||
| ', can_create_tickets='.db_input($vars['can_create_tickets']). | ||
| ', can_delete_tickets='.db_input($vars['can_delete_tickets']). | ||
| ', can_edit_tickets='.db_input($vars['can_edit_tickets']). | ||
| ', can_transfer_tickets='.db_input($vars['can_transfer_tickets']). | ||
| ', can_close_tickets='.db_input($vars['can_close_tickets']). | ||
| ', can_ban_emails='.db_input($vars['can_ban_emails']). | ||
| ', can_manage_kb='.db_input($vars['can_manage_kb']); | ||
| //echo $sql; | ||
| if($id) { | ||
| $res=db_query('UPDATE '.GROUP_TABLE.' '.$sql.' WHERE group_id='.db_input($id)); | ||
| if(!$res || !db_affected_rows()) | ||
| $errors['err']='Internal error occured'; | ||
| }else{ | ||
| $res=db_query('INSERT INTO '.GROUP_TABLE.' '.$sql.',created=NOW()'); | ||
| if($res && ($gID=db_insert_id())) | ||
| return $gID; | ||
|
|
||
| $errors['err']='Unable to create the group. Internal error'; | ||
| } | ||
| } | ||
|
|
||
| return $errors?false:true; | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,52 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.http.php | ||
| Http helper. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.http.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| class Http { | ||
|
|
||
| function header_code_verbose($code) { | ||
| switch($code): | ||
| case 200: return '200 OK'; | ||
| case 204: return '204 NoContent'; | ||
| case 401: return '401 Unauthorized'; | ||
| case 403: return '403 Forbidden'; | ||
| case 405: return '405 Method Not Allowed'; | ||
| case 416: return '416 Requested Range Not Satisfiable'; | ||
| default: return '500 Internal Server Error'; | ||
| endswitch; | ||
| } | ||
|
|
||
| function response($code,$content,$contentType='text/html',$charset='UTF-8') { | ||
|
|
||
| header('HTTP/1.1 '.Http::header_code_verbose($code)); | ||
| header('Status: '.Http::header_code_verbose($code)."\r\n"); | ||
| header("Connection: Close\r\n"); | ||
| header("Content-Type: $contentType; charset=$charset\r\n"); | ||
| header('Content-Length: '.strlen($content)."\r\n\r\n"); | ||
| print $content; | ||
| exit; | ||
| } | ||
|
|
||
| function redirect($url,$delay=0,$msg='') { | ||
|
|
||
| if(strstr($_SERVER['SERVER_SOFTWARE'], 'IIS')){ | ||
| header("Refresh: $delay; URL=$url"); | ||
| }else{ | ||
| header("Location: $url"); | ||
| } | ||
| exit; | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,137 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.lock.php | ||
| Ticket lock handle. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.lock.php,v 1.1.2.1 2009/08/17 18:35:46 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| /* | ||
| * Mainly used as a helper... | ||
| */ | ||
|
|
||
| class TicketLock { | ||
| var $id; | ||
| var $staff_id; | ||
| var $created; | ||
| var $expire; | ||
| var $expiretime; | ||
|
|
||
| function TicketLock($id,$load=true){ | ||
| $this->id=$id; | ||
| if($load) $this->load(); | ||
| } | ||
|
|
||
| function load() { | ||
|
|
||
| if(!$this->id) | ||
| return false; | ||
|
|
||
| $sql='SELECT *,TIME_TO_SEC(TIMEDIFF(expire,NOW())) as timeleft FROM '.TICKET_LOCK_TABLE.' WHERE lock_id='.db_input($this->id); | ||
| if(($res=db_query($sql)) && db_num_rows($res)) { | ||
| $info=db_fetch_array($res); | ||
| $this->id=$info['lock_id']; | ||
| $this->staff_id=$info['staff_id']; | ||
| $this->created=$info['created']; | ||
| $this->expire=$info['expire']; | ||
| $this->expiretime=time()+$info['timeleft']; | ||
| return true; | ||
| } | ||
| $this->id=0; | ||
| return false; | ||
| } | ||
|
|
||
| function reload() { | ||
| return $this->load(); | ||
| } | ||
|
|
||
| //Create a ticket lock...this function assumes the caller check for access & validity of ticket & staff x-ship. | ||
| function acquire($ticketId,$staffId) { | ||
| global $cfg; | ||
|
|
||
| if(!$ticketId or !$staffId or !$cfg->getLockTime()) | ||
| return 0; | ||
|
|
||
| //Cleanup any expired locks on the ticket. | ||
| db_query('DELETE FROM '.TICKET_LOCK_TABLE.' WHERE ticket_id='.db_input($ticketId).' AND expire<NOW()'); | ||
| //TODO: cleanup any other locks owned by the user? (NOT a good idea.. could be working on 2 tickets at once??) | ||
| $sql='INSERT IGNORE INTO '.TICKET_LOCK_TABLE.' SET created=NOW() '. | ||
| ',ticket_id='.db_input($ticketId). | ||
| ',staff_id='.db_input($staffId). | ||
| ',expire=DATE_ADD(NOW(),INTERVAL '.$cfg->getLockTime().' MINUTE) '; | ||
|
|
||
| return db_query($sql)?db_insert_id():0; | ||
| } | ||
|
|
||
| //Renew existing lock. | ||
| function renew() { | ||
| global $cfg; | ||
|
|
||
| $sql='UPDATE '.TICKET_LOCK_TABLE.' SET expire=DATE_ADD(NOW(),INTERVAL '.$cfg->getLockTime().' MINUTE) '. | ||
| ' WHERE lock_id='.db_input($this->getId()); | ||
| //echo $sql; | ||
| if(db_query($sql) && db_affected_rows()) { | ||
| $this->reload(); | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| //release aka delete a lock. | ||
| function release(){ | ||
| //FORCED release - we don't give a .... | ||
| $sql='DELETE FROM '.TICKET_LOCK_TABLE.' WHERE lock_id='.db_input($this->getId()); | ||
| return (db_query($sql) && db_affected_rows())?true:false; | ||
| } | ||
|
|
||
| function getId(){ | ||
| return $this->id; | ||
| } | ||
|
|
||
| function getStaffId(){ | ||
| return $this->staff_id; | ||
| } | ||
|
|
||
| function getCreateTime() { | ||
| return $this->created; | ||
| } | ||
|
|
||
| function getExpireTime() { | ||
| return $this->expire; | ||
| } | ||
| //Get remaiming time before the lock expires | ||
| function getTime() { | ||
| return $this->isExpired()?0:($this->expiretime-time()); | ||
| } | ||
|
|
||
| //Should we be doing realtime check here? (Ans: not really....expiretime is local & based on loadtime) | ||
| function isExpired(){ | ||
| return (time()>$this->expiretime)?true:false; | ||
| } | ||
|
|
||
| //Simply remove ALL locks a user (staff) holds on a ticket(s). | ||
| function removeStaffLocks($staffId,$ticketId=0) { | ||
| $sql='DELETE FROM '.TICKET_LOCK_TABLE.' WHERE staff_id='.db_input($staffId); | ||
| if($ticketId) | ||
| $sql.=' AND ticket_id='.db_input($ticketId); | ||
|
|
||
| return db_query($sql)?true:false; | ||
| } | ||
|
|
||
| //Called via cron | ||
| function cleanup() { | ||
| //Cleanup any expired locks. | ||
| db_query('DELETE FROM '.TICKET_LOCK_TABLE.' WHERE expire<NOW()'); | ||
| @db_query('OPTIMIZE TABLE '.TICKET_LOCK_TABLE); | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,367 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.mailfetch.php | ||
| mail fetcher class. Uses IMAP ext for now. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.mailfetch.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| require_once(INCLUDE_DIR.'class.mailparse.php'); | ||
| require_once(INCLUDE_DIR.'class.ticket.php'); | ||
| require_once(INCLUDE_DIR.'class.dept.php'); | ||
|
|
||
| class MailFetcher { | ||
| var $hostname; | ||
| var $username; | ||
| var $password; | ||
|
|
||
| var $port; | ||
| var $protocol; | ||
| var $encryption; | ||
|
|
||
| var $mbox; | ||
|
|
||
| var $charset= 'UTF-8'; | ||
|
|
||
| function MailFetcher($username,$password,$hostname,$port,$protocol,$encryption='') { | ||
|
|
||
| if(!strcasecmp($protocol,'pop')) //force pop3 | ||
| $protocol='pop3'; | ||
|
|
||
| $this->hostname=$hostname; | ||
| $this->username=$username; | ||
| $this->password=$password; | ||
| $this->protocol=strtolower($protocol); | ||
| $this->port = $port; | ||
| $this->encryption = $encryption; | ||
|
|
||
| $this->serverstr=sprintf('{%s:%d/%s',$this->hostname,$this->port,strtolower($this->protocol)); | ||
| if(!strcasecmp($this->encryption,'SSL')){ | ||
| $this->serverstr.='/ssl'; | ||
| } | ||
| $this->serverstr.='/novalidate-cert}INBOX'; //add other flags here as needed. | ||
|
|
||
| //echo $this->serverstr; | ||
| //Charset to convert the mail to. | ||
| $this->charset='UTF-8'; | ||
| //Set timeouts | ||
| if(function_exists('imap_timeout')) | ||
| imap_timeout(1,20); //Open timeout. | ||
| } | ||
|
|
||
| function connect() { | ||
| return $this->open()?true:false; | ||
| } | ||
|
|
||
| function open() { | ||
|
|
||
| //echo $this->serverstr; | ||
| if($this->mbox && imap_ping($this->mbox)) | ||
| return $this->mbox; | ||
|
|
||
| $this->mbox =@imap_open($this->serverstr,$this->username,$this->password); | ||
|
|
||
| return $this->mbox; | ||
| } | ||
|
|
||
| function close() { | ||
| imap_close($this->mbox,CL_EXPUNGE); | ||
| } | ||
|
|
||
| function mailcount(){ | ||
| return count(imap_headers($this->mbox)); | ||
| } | ||
|
|
||
|
|
||
| function decode($encoding,$text) { | ||
|
|
||
| switch($encoding) { | ||
| case 1: | ||
| $text=imap_8bit($text); | ||
| break; | ||
| case 2: | ||
| $text=imap_binary($text); | ||
| break; | ||
| case 3: | ||
| $text=imap_base64($text); | ||
| break; | ||
| case 4: | ||
| $text=imap_qprint($text); | ||
| break; | ||
| case 5: | ||
| default: | ||
| $text=$text; | ||
| } | ||
| return $text; | ||
| } | ||
|
|
||
| //Convert text to desired encoding..defaults to utf8 | ||
| function mime_encode($text,$charset=null,$enc='utf-8') { //Thank in part to afterburner | ||
|
|
||
| $encodings=array('UTF-8','WINDOWS-1251', 'ISO-8859-5', 'ISO-8859-1','KOI8-R'); | ||
| if(function_exists("iconv") and $text) { | ||
| if($charset) | ||
| return iconv($charset,$enc.'//IGNORE',$text); | ||
| elseif(function_exists("mb_detect_encoding")) | ||
| return iconv(mb_detect_encoding($text,$encodings),$enc,$text); | ||
| } | ||
|
|
||
| return utf8_encode($text); | ||
| } | ||
|
|
||
| //Generic decoder - mirrors imap_utf8 | ||
| function mime_decode($text) { | ||
|
|
||
| $a = imap_mime_header_decode($text); | ||
| $str = ''; | ||
| foreach ($a as $k => $part) | ||
| $str.= $part->text; | ||
|
|
||
| return $str?$str:imap_utf8($text); | ||
| } | ||
|
|
||
| function getLastError(){ | ||
| return imap_last_error(); | ||
| } | ||
|
|
||
| function getMimeType($struct) { | ||
| $mimeType = array('TEXT', 'MULTIPART', 'MESSAGE', 'APPLICATION', 'AUDIO', 'IMAGE', 'VIDEO', 'OTHER'); | ||
| if(!$struct || !$struct->subtype) | ||
| return 'TEXT/PLAIN'; | ||
|
|
||
| return $mimeType[(int) $struct->type].'/'.$struct->subtype; | ||
| } | ||
|
|
||
| function getHeaderInfo($mid) { | ||
|
|
||
| $headerinfo=imap_headerinfo($this->mbox,$mid); | ||
| $sender=$headerinfo->from[0]; | ||
|
|
||
| //Parse what we need... | ||
| $header=array( | ||
| 'from' =>array('name' =>@$sender->personal,'email' =>strtolower($sender->mailbox).'@'.$sender->host), | ||
| 'subject'=>@$headerinfo->subject, | ||
| 'mid' =>$headerinfo->message_id); | ||
| return $header; | ||
| } | ||
|
|
||
| //search for specific mime type parts....encoding is the desired encoding. | ||
| function getPart($mid,$mimeType,$encoding=false,$struct=null,$partNumber=false){ | ||
|
|
||
| if(!$struct && $mid) | ||
| $struct=@imap_fetchstructure($this->mbox, $mid); | ||
| //Match the mime type. | ||
| if($struct && !$struct->ifdparameters && strcasecmp($mimeType,$this->getMimeType($struct))==0){ | ||
| $partNumber=$partNumber?$partNumber:1; | ||
| if(($text=imap_fetchbody($this->mbox, $mid, $partNumber))){ | ||
| if($struct->encoding==3 or $struct->encoding==4) //base64 and qp decode. | ||
| $text=$this->decode($struct->encoding,$text); | ||
| $charset=null; | ||
| if($encoding) { //Convert text to desired mime encoding... | ||
| if($struct->ifparameters){ | ||
| if(!strcasecmp($struct->parameters[0]->attribute,'CHARSET') && strcasecmp($struct->parameters[0]->value,'US-ASCII')) | ||
| $charset=trim($struct->parameters[0]->value); | ||
| } | ||
| $text=$this->mime_encode($text,$charset,$encoding); | ||
| } | ||
| return $text; | ||
| } | ||
| } | ||
| //Do recursive search | ||
| $text=''; | ||
| if($struct && $struct->parts){ | ||
| while(list($i, $substruct) = each($struct->parts)) { | ||
| if($partNumber) | ||
| $prefix = $partNumber . '.'; | ||
| if(($result=$this->getPart($mid,$mimeType,$encoding,$substruct,$prefix.($i+1)))) | ||
| $text.=$result; | ||
| } | ||
| } | ||
| return $text; | ||
| } | ||
|
|
||
| function getHeader($mid){ | ||
| return imap_fetchheader($this->mbox, $mid,FT_PREFETCHTEXT); | ||
| } | ||
|
|
||
|
|
||
| function getPriority($mid){ | ||
| return Mail_Parse::parsePriority($this->getHeader($mid)); | ||
| } | ||
|
|
||
| function getBody($mid) { | ||
|
|
||
| $body =''; | ||
| if(!($body = $this->getpart($mid,'TEXT/PLAIN',$this->charset))) { | ||
| if(($body = $this->getPart($mid,'TEXT/HTML',$this->charset))) { | ||
| //Convert tags of interest before we striptags | ||
| $body=str_replace("</DIV><DIV>", "\n", $body); | ||
| $body=str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $body); | ||
| $body=Format::striptags($body); //Strip tags?? | ||
| } | ||
| } | ||
| return $body; | ||
| } | ||
|
|
||
| function createTicket($mid,$emailid=0){ | ||
| global $cfg; | ||
|
|
||
| $mailinfo=$this->getHeaderInfo($mid); | ||
|
|
||
| //Make sure the email is NOT one of the undeleted emails. | ||
| if($mailinfo['mid'] && ($id=Ticket::getIdByMessageId(trim($mailinfo['mid']),$mailinfo['from']['email']))){ | ||
| //TODO: Move emails to a fetched folder when delete is false?? | ||
| return false; | ||
| } | ||
|
|
||
| $var['name']=$this->mime_decode($mailinfo['from']['name']); | ||
| $var['email']=$mailinfo['from']['email']; | ||
| $var['subject']=$mailinfo['subject']?$this->mime_decode($mailinfo['subject']):'[No Subject]'; | ||
| $var['message']=Format::stripEmptyLines($this->getBody($mid)); | ||
| $var['header']=$this->getHeader($mid); | ||
| $var['emailId']=$emailid?$emailid:$cfg->getDefaultEmailId(); //ok to default? | ||
| $var['name']=$var['name']?$var['name']:$var['email']; //No name? use email | ||
| $var['mid']=$mailinfo['mid']; | ||
|
|
||
| if($cfg->useEmailPriority()) | ||
| $var['pri']=$this->getPriority($mid); | ||
|
|
||
| $ticket=null; | ||
| $newticket=true; | ||
| //Check the subject line for possible ID. | ||
| if(preg_match ("[[#][0-9]{1,10}]",$var['subject'],$regs)) { | ||
| $extid=trim(preg_replace("/[^0-9]/", "", $regs[0])); | ||
| $ticket= new Ticket(Ticket::getIdByExtId($extid)); | ||
| //Allow mismatched emails?? For now NO. | ||
| if(!$ticket || strcasecmp($ticket->getEmail(),$var['email'])) | ||
| $ticket=null; | ||
| } | ||
|
|
||
| $errors=array(); | ||
| if(!$ticket) { | ||
| if(!($ticket=Ticket::create($var,$errors,'Email')) || $errors) | ||
| return null; | ||
| $msgid=$ticket->getLastMsgId(); | ||
| }else{ | ||
| $message=$var['message']; | ||
| //Strip quoted reply...TODO: figure out how mail clients do it without special tag.. | ||
| if($cfg->stripQuotedReply() && ($tag=$cfg->getReplySeparator()) && strpos($var['message'],$tag)) | ||
| list($message)=split($tag,$var['message']); | ||
| $msgid=$ticket->postMessage($message,'Email',$var['mid'],$var['header']); | ||
| } | ||
| //Save attachments if any. | ||
| if($msgid && $cfg->allowEmailAttachments()){ | ||
| if(($struct = imap_fetchstructure($this->mbox,$mid)) && $struct->parts) { | ||
| if($ticket->getLastMsgId()!=$msgid) | ||
| $ticket->setLastMsgId($msgid); | ||
| $this->saveAttachments($ticket,$mid,$struct); | ||
|
|
||
| } | ||
| } | ||
| return $ticket; | ||
| } | ||
|
|
||
| function saveAttachments($ticket,$mid,$part,$index=0) { | ||
| global $cfg; | ||
|
|
||
| if($part && $part->ifdparameters && ($filename=$part->dparameters[0]->value)){ //attachment | ||
| $index=$index?$index:1; | ||
| if($ticket && $cfg->canUploadFileType($filename) && $cfg->getMaxFileSize()>=$part->bytes) { | ||
| //extract the attachments...and do the magic. | ||
| $data=$this->decode($part->encoding, imap_fetchbody($this->mbox,$mid,$index)); | ||
| $ticket->saveAttachment($filename,$data,$ticket->getLastMsgId(),'M'); | ||
| return; | ||
| } | ||
| //TODO: Log failure?? | ||
| } | ||
|
|
||
| //Recursive attachment search! | ||
| if($part && $part->parts) { | ||
| foreach($part->parts as $k=>$struct) { | ||
| if($index) $prefix = $index.'.'; | ||
| $this->saveAttachments($ticket,$mid,$struct,$prefix.($k+1)); | ||
| } | ||
| } | ||
|
|
||
| } | ||
|
|
||
| function fetchTickets($emailid,$max=20,$deletemsgs=false){ | ||
|
|
||
| $nummsgs=imap_num_msg($this->mbox); | ||
| //echo "New Emails: $nummsgs\n"; | ||
| $msgs=$errors=0; | ||
| for($i=$nummsgs; $i>0; $i--){ //process messages in reverse. Latest first. FILO. | ||
| if($this->createTicket($i,$emailid)){ | ||
| imap_setflag_full($this->mbox, imap_uid($this->mbox,$i), "\\Seen", ST_UID); //IMAP only?? | ||
| if($deletemsgs) | ||
| imap_delete($this->mbox,$i); | ||
| $msgs++; | ||
| $errors=0; //We are only interested in consecutive errors. | ||
| }else{ | ||
| $errors++; | ||
| } | ||
| if(($max && $msgs>=$max) || $errors>20) | ||
| break; | ||
| } | ||
| @imap_expunge($this->mbox); | ||
|
|
||
| return $msgs; | ||
| } | ||
|
|
||
| function fetchMail(){ | ||
| global $cfg; | ||
|
|
||
| if(!$cfg->canFetchMail()) | ||
| return; | ||
|
|
||
| //We require imap ext to fetch emails via IMAP/POP3 | ||
| if(!function_exists('imap_open')) { | ||
| $msg='PHP must be compiled with IMAP extension enabled for IMAP/POP3 fetch to work!'; | ||
| Sys::log(LOG_WARN,'Mail Fetch Error',$msg); | ||
| return; | ||
| } | ||
|
|
||
| $MAX_ERRORS=5; //Max errors before we start delayed fetch attempts - hardcoded for now. | ||
|
|
||
| $sql=' SELECT email_id,mail_host,mail_port,mail_protocol,mail_encryption,mail_delete,mail_errors,userid,userpass FROM '.EMAIL_TABLE. | ||
| ' WHERE mail_active=1 AND (mail_errors<='.$MAX_ERRORS.' OR (TIME_TO_SEC(TIMEDIFF(NOW(),mail_lasterror))>5*60) )'. | ||
| ' AND (mail_lastfetch IS NULL OR TIME_TO_SEC(TIMEDIFF(NOW(),mail_lastfetch))>mail_fetchfreq*60) '; | ||
| //echo $sql; | ||
| if(!($accounts=db_query($sql)) || !db_num_rows($accounts)) | ||
| return; | ||
|
|
||
| //TODO: Lock the table here?? | ||
| while($row=db_fetch_array($accounts)) { | ||
| $fetcher = new MailFetcher($row['userid'],Misc::decrypt($row['userpass'],SECRET_SALT), | ||
| $row['mail_host'],$row['mail_port'],$row['mail_protocol'],$row['mail_encryption']); | ||
| if($fetcher->connect()){ | ||
| $fetcher->fetchTickets($row['email_id'],$row['mail_fetchmax'],$row['mail_delete']?true:false); | ||
| $fetcher->close(); | ||
| db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=0, mail_lastfetch=NOW() WHERE email_id='.db_input($row['email_id'])); | ||
| }else{ | ||
| $errors=$row['mail_errors']+1; | ||
| db_query('UPDATE '.EMAIL_TABLE.' SET mail_errors=mail_errors+1, mail_lasterror=NOW() WHERE email_id='.db_input($row['email_id'])); | ||
| if($errors>=$MAX_ERRORS){ | ||
| //We've reached the MAX consecutive errors...will attempt logins at delayed intervals | ||
| $msg="\nThe system is having trouble fetching emails from the following mail account: \n". | ||
| "\nUser: ".$row['userid']. | ||
| "\nHost: ".$row['mail_host']. | ||
| "\nError: ".$fetcher->getLastError(). | ||
| "\n\n ".$errors.' consecutive errors. Maximum of '.$MAX_ERRORS. ' allowed'. | ||
| "\n\n This could be connection issues related to the host. Next delayed login attempt in aprox. 10 minutes"; | ||
| Sys::alertAdmin('Mail Fetch Failure Alert',$msg,true); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ?> |
| @@ -0,0 +1,180 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.mailparse.php | ||
| Mail parsing helper class. | ||
| Mail parsing will change once we move to PHP5 | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.mailparse.php,v 1.2.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| require_once('Mail/mimeDecode.php'); | ||
| require_once('Mail/RFC822.php'); | ||
|
|
||
| class Mail_Parse { | ||
|
|
||
| var $mime_message; | ||
| var $include_bodies; | ||
| var $decode_headers; | ||
| var $decode_bodies; | ||
|
|
||
| var $struct; | ||
|
|
||
| function Mail_parse($mimeMessage,$includeBodies=true,$decodeHeaders=TRUE,$decodeBodies=TRUE){ | ||
|
|
||
| $this->mime_message=$mimeMessage; | ||
| $this->include_bodies=$includeBodies; | ||
| $this->decode_headers=$decodeHeaders; | ||
| $this->decode_bodies=$decodeBodies; | ||
| } | ||
|
|
||
| function decode() { | ||
|
|
||
| $params = array('crlf' => "\r\n", | ||
| 'input' =>$this->mime_message, | ||
| 'include_bodies'=> $this->include_bodies, | ||
| 'decode_headers'=> $this->decode_headers, | ||
| 'decode_bodies' => $this->decode_bodies); | ||
| $this->splitBodyHeader(); | ||
| $this->struct=Mail_mimeDecode::decode($params); | ||
|
|
||
| return (PEAR::isError($this->struct) || !(count($this->struct->headers)>1))?FALSE:TRUE; | ||
| } | ||
|
|
||
| function splitBodyHeader() { | ||
|
|
||
| if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s",$this->mime_message, $match)) { | ||
| $this->header=$match[1]; | ||
| } | ||
| } | ||
|
|
||
|
|
||
| function getStruct(){ | ||
| return $this->struct; | ||
| } | ||
|
|
||
| function getHeader() { | ||
| if(!$this->header) $this->splitBodyHeader(); | ||
|
|
||
| return $this->header; | ||
| } | ||
|
|
||
| function getError(){ | ||
| return PEAR::isError($this->struct)?$this->struct->getMessage():''; | ||
| } | ||
|
|
||
|
|
||
| function getFromAddressList(){ | ||
| return Mail_Parse::parseAddressList($this->struct->headers['from']); | ||
| } | ||
|
|
||
| function getToAddressList(){ | ||
| //Delivered-to incase it was a BBC mail. | ||
| return Mail_Parse::parseAddressList($this->struct->headers['to']?$this->struct->headers['to']:$this->struct->headers['delivered-to']); | ||
| } | ||
|
|
||
| function getCcAddressList(){ | ||
| return $this->struct->headers['cc']?Mail_Parse::parseAddressList($this->struct->headers['cc']):null; | ||
| } | ||
|
|
||
| function getMessageId(){ | ||
| return $this->struct->headers['message-id']; | ||
| } | ||
|
|
||
| function getSubject(){ | ||
| return $this->struct->headers['subject']; | ||
| } | ||
|
|
||
| function getBody(){ | ||
|
|
||
| $body=''; | ||
| if(!($body=$this->getPart($this->struct,'text/plain'))) { | ||
| if(($body=$this->getPart($this->struct,'text/html'))) { | ||
| //Cleanup the html. | ||
| $body=str_replace("</DIV><DIV>", "\n", $body); | ||
| $body=str_replace(array("<br>", "<br />", "<BR>", "<BR />"), "\n", $body); | ||
| $body=Format::striptags($body); | ||
| } | ||
| } | ||
| return $body; | ||
| } | ||
|
|
||
| function getPart($struct,$ctypepart) { | ||
|
|
||
| if($struct && !$struct->parts) { | ||
| $ctype = @strtolower($struct->ctype_primary.'/'.$struct->ctype_secondary); | ||
| if($ctype && strcasecmp($ctype,$ctypepart)==0) | ||
| return $struct->body; | ||
| } | ||
|
|
||
| $data=''; | ||
| if($struct && $struct->parts) { | ||
| foreach($struct->parts as $i=>$part) { | ||
| if($part && !$part->disposition && ($text=$this->getPart($part,$ctypepart))) | ||
| $data.=$text; | ||
| } | ||
| } | ||
| return $data; | ||
| } | ||
|
|
||
| function getAttachments($part=null){ | ||
|
|
||
| if($part==null) | ||
| $part=$this->getStruct(); | ||
|
|
||
| if($part && $part->disposition | ||
| && (!strcasecmp($part->disposition,'attachment') | ||
| || !strcasecmp($part->disposition,'inline') | ||
| || !strcasecmp($part->ctype_primary,'image'))){ | ||
| if(!($filename=$part->d_parameters['filename']) && $part->d_parameters['filename*']) | ||
| $filename=$part->d_parameters['filename*']; //Do we need to decode? | ||
| return array(array('filename'=>$filename,'body'=>$part->body)); | ||
| } | ||
|
|
||
| $files=array(); | ||
| if($part->parts){ | ||
| foreach($part->parts as $k=>$p){ | ||
| if($p && ($result=$this->getAttachments($p))) { | ||
| $files=array_merge($files,$result); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return $files; | ||
| } | ||
|
|
||
| function getPriority(){ | ||
| return Mail_Parse::parsePriority($this->getHeader()); | ||
| } | ||
|
|
||
| function parsePriority($header=null){ | ||
|
|
||
| $priority=0; | ||
| if($header && ($begin=strpos($header,'X-Priority:'))!==false){ | ||
| $begin+=strlen('X-Priority:'); | ||
| $xpriority=preg_replace("/[^0-9]/", "",substr($header, $begin, strpos($header,"\n",$begin) - $begin)); | ||
| if(!is_numeric($xpriority)) | ||
| $priority=0; | ||
| elseif($xpriority>4) | ||
| $priority=1; | ||
| elseif($xpriority>=3) | ||
| $priority=2; | ||
| elseif($xpriority>0) | ||
| $priority=3; | ||
| } | ||
| return $priority; | ||
| } | ||
|
|
||
| function parseAddressList($address){ | ||
| return Mail_RFC822::parseAddressList($address, null, null,false); | ||
| } | ||
| } |
| @@ -0,0 +1,145 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.misc.php | ||
| Misc collection of useful generic helper functions. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.misc.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| class Misc { | ||
|
|
||
| function randCode($len=8) { | ||
| return substr(strtoupper(base_convert(microtime(),10,16)),0,$len); | ||
| } | ||
|
|
||
| /* Helper used to generate ticket IDs */ | ||
| function randNumber($len=6,$start=false,$end=false) { | ||
|
|
||
| mt_srand ((double) microtime() * 1000000); | ||
| $start=(!$len && $start)?$start:str_pad(1,$len,"0",STR_PAD_RIGHT); | ||
| $end=(!$len && $end)?$end:str_pad(9,$len,"9",STR_PAD_RIGHT); | ||
|
|
||
| return mt_rand($start,$end); | ||
| } | ||
|
|
||
| function encrypt($text, $salt) { | ||
|
|
||
| //if mcrypt extension is not installed--simply return unencryted text and log a warning. | ||
| if(!function_exists('mcrypt_encrypt') || !function_exists('mcrypt_decrypt')) { | ||
| $msg='Cryptography extension mcrypt is not enabled or installed. IMAP/POP passwords are being stored as plain text in database.'; | ||
| Sys::log(LOG_WARN,'mcrypt missing',$msg); | ||
| return $text; | ||
| } | ||
|
|
||
| return trim(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256,$salt, $text, MCRYPT_MODE_ECB, | ||
| mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND)))); | ||
| } | ||
|
|
||
| function decrypt($text, $salt) { | ||
| if(!function_exists('mcrypt_encrypt') || !function_exists('mcrypt_decrypt')) | ||
| return $text; | ||
|
|
||
| return trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $salt, base64_decode($text), MCRYPT_MODE_ECB, | ||
| mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_ECB), MCRYPT_RAND))); | ||
| } | ||
|
|
||
| /* misc date helpers...this will go away once we move to php 5 */ | ||
| function db2gmtime($var){ | ||
| global $cfg; | ||
| if(!$var) return; | ||
|
|
||
| $dbtime=is_int($var)?$var:strtotime($var); | ||
| return $dbtime-($cfg->getMysqlTZoffset()*3600); | ||
| } | ||
|
|
||
| //Take user time or gmtime and return db (mysql) time. | ||
| function dbtime($var=null){ | ||
| global $cfg; | ||
|
|
||
| if(is_null($var) || !$var) | ||
| $time=Misc::gmtime(); //gm time. | ||
| else{ //user time to GM. | ||
| $time=is_int($var)?$var:strtotime($var); | ||
| $offset=$_SESSION['TZ_OFFSET']+($_SESSION['daylight']?date('I',$time):0); | ||
| $time=$time-($offset*3600); | ||
| } | ||
| //gm to db time | ||
| return $time+($cfg->getMysqlTZoffset()*3600); | ||
| } | ||
|
|
||
| /*Helper get GM time based on timezone offset*/ | ||
| function gmtime() { | ||
| return time()-date('Z'); | ||
| } | ||
|
|
||
| //Current page | ||
| function currentURL() { | ||
|
|
||
| $str = 'http'; | ||
| if ($_SERVER['HTTPS'] == 'on') { | ||
| $str .='s'; | ||
| } | ||
| $str .= '://'; | ||
| if (!isset($_SERVER['REQUEST_URI'])) { //IIS??? | ||
| $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],1 ); | ||
| if (isset($_SERVER['QUERY_STRING'])) { | ||
| $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING']; | ||
| } | ||
| } | ||
| if ($_SERVER['SERVER_PORT']!=80) { | ||
| $str .= $_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['REQUEST_URI']; | ||
| } else { | ||
| $str .= $_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']; | ||
| } | ||
|
|
||
| return $str; | ||
| } | ||
|
|
||
| function timeDropdown($hr=null, $min =null,$name='time') { | ||
| $hr =is_null($hr)?0:$hr; | ||
| $min =is_null($min)?0:$min; | ||
|
|
||
| //normalize; | ||
| if($hr>=24) | ||
| $hr=$hr%24; | ||
| elseif($hr<0) | ||
| $hr=0; | ||
|
|
||
| if($min>=45) | ||
| $min=45; | ||
| elseif($min>=30) | ||
| $min=30; | ||
| elseif($min>=15) | ||
| $min=15; | ||
| else | ||
| $min=0; | ||
|
|
||
| ob_start(); | ||
| echo sprintf('<select name="%s" id="%s">',$name,$name); | ||
| echo '<option value="" selected>Time</option>'; | ||
| for($i=23; $i>=0; $i--) { | ||
| for($minute=45; $minute>=0; $minute-=15) { | ||
| $sel=($hr==$i && $min==$minute)?'selected="selected"':''; | ||
| $_minute=str_pad($minute, 2, '0',STR_PAD_LEFT); | ||
| $_hour=str_pad($i, 2, '0',STR_PAD_LEFT); | ||
| echo sprintf('<option value="%s:%s" %s>%s:%s</option>',$_hour,$_minute,$sel,$_hour,$_minute); | ||
| } | ||
| } | ||
| echo '</select>'; | ||
| $output = ob_get_contents(); | ||
| ob_end_clean(); | ||
|
|
||
| return $output; | ||
| } | ||
|
|
||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,217 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.msgtpl.php | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.msgtpl.php,v 1.1.2.1 2009/08/17 18:35:47 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| class Template { | ||
|
|
||
| var $id; | ||
| var $name; | ||
|
|
||
| var $info; | ||
|
|
||
| function Template($id,$cId=0){ | ||
| $this->load($id,$cId); | ||
| } | ||
|
|
||
| function load($id,$cId=0) { | ||
|
|
||
| if(!$id) | ||
| return false; | ||
|
|
||
| $sql='SELECT * FROM '.EMAIL_TEMPLATE_TABLE.' WHERE tpl_id='.db_input($id); | ||
| if($cId && is_numeric($cId)) | ||
| $sql.=' AND cfg_id='.db_input($cId); | ||
|
|
||
| if(($res=db_query($sql)) && db_num_rows($res)) { | ||
| $info=db_fetch_array($res); | ||
| $this->id=$info['tpl_id']; | ||
| $this->cfgId=$info['cfg_id']; | ||
| $this->name=$info['name']; | ||
| $this->info=$info; | ||
| return true; | ||
| } | ||
| $this->id=0; | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| function reload() { | ||
| return $this->load($this->getId(),$this->getCfgId()); | ||
| } | ||
|
|
||
| function getId(){ | ||
| return $this->id; | ||
| } | ||
|
|
||
| function getCfgId(){ | ||
| return $this->cfgId; | ||
| } | ||
|
|
||
| function getName(){ | ||
| return $this->name; | ||
| } | ||
|
|
||
| function getInfo() { | ||
| return $this->info; | ||
| } | ||
|
|
||
| function getCreateDate() { | ||
| return $this->info['created']; | ||
| } | ||
|
|
||
| function getUpdateDate() { | ||
| return $this->info['updated']; | ||
| } | ||
|
|
||
|
|
||
| function update($var,&$errors){ | ||
|
|
||
|
|
||
| $fields=array(); | ||
| $fields['id'] = array('type'=>'int', 'required'=>1, 'error'=>'Internal Error'); | ||
| $fields['name'] = array('type'=>'string', 'required'=>1, 'error'=>'Name required'); | ||
| //Notices sent to user | ||
| $fields['ticket_autoresp_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_autoresp_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['message_autoresp_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['message_autoresp_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['ticket_notice_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_notice_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['ticket_overlimit_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_overlimit_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['ticket_reply_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_reply_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| //Alerts sent to Staff | ||
| $fields['ticket_alert_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_alert_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['message_alert_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['message_alert_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['note_alert_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['note_alert_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['assigned_alert_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['assigned_alert_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
| $fields['ticket_overdue_subj'] = array('type'=>'string', 'required'=>1, 'error'=>'Subject required'); | ||
| $fields['ticket_overdue_body'] = array('type'=>'string', 'required'=>1, 'error'=>'Template message required'); | ||
|
|
||
| $validate = new Validator($fields); | ||
| if(!$validate->validate($var)){ | ||
| $errors=array_merge($errors,$validate->errors()); | ||
| } | ||
|
|
||
| if(!$errors && $var['id'] && $var['id']!=$this->getId()) | ||
| $errors['err']='Internal error. Try again'; | ||
|
|
||
| if(!$errors['name'] && ($tid=Template::getIdByName($var['name'])) && $tid!=$this->getId()) | ||
| $errors['name']='Name already in use'; | ||
|
|
||
| if(!$errors) { | ||
|
|
||
| $sql='UPDATE '.EMAIL_TEMPLATE_TABLE.' SET updated=NOW() '. | ||
| ',name='.db_input(Format::striptags($var['name'])). | ||
| ',notes='.db_input(Format::striptags($var['notes'])). | ||
| ',ticket_autoresp_subj='.db_input(Format::striptags($var['ticket_autoresp_subj'])). | ||
| ',ticket_autoresp_body='.db_input(Format::striptags($var['ticket_autoresp_body'])). | ||
| ',message_autoresp_subj='.db_input(Format::striptags($var['message_autoresp_subj'])). | ||
| ',message_autoresp_body='.db_input(Format::striptags($var['message_autoresp_body'])). | ||
| ',ticket_notice_subj='.db_input(Format::striptags($var['ticket_notice_subj'])). | ||
| ',ticket_notice_body='.db_input(Format::striptags($var['ticket_notice_body'])). | ||
| ',ticket_alert_subj='.db_input(Format::striptags($var['ticket_alert_subj'])). | ||
| ',ticket_alert_body='.db_input(Format::striptags($var['ticket_alert_body'])). | ||
| ',message_alert_subj='.db_input(Format::striptags($var['message_alert_subj'])). | ||
| ',message_alert_body='.db_input(Format::striptags($var['message_alert_body'])). | ||
| ',note_alert_subj='.db_input(Format::striptags($var['note_alert_subj'])). | ||
| ',note_alert_body='.db_input(Format::striptags($var['note_alert_body'])). | ||
| ',assigned_alert_subj='.db_input(Format::striptags($var['assigned_alert_subj'])). | ||
| ',assigned_alert_body='.db_input(Format::striptags($var['assigned_alert_body'])). | ||
| ',ticket_overdue_subj='.db_input(Format::striptags($var['ticket_overdue_subj'])). | ||
| ',ticket_overdue_body='.db_input(Format::striptags($var['ticket_overdue_body'])). | ||
| ',ticket_overlimit_subj='.db_input(Format::striptags($var['ticket_overlimit_subj'])). | ||
| ',ticket_overlimit_body='.db_input(Format::striptags($var['ticket_overlimit_body'])). | ||
| ',ticket_reply_subj='.db_input(Format::striptags($var['ticket_reply_subj'])). | ||
| ',ticket_reply_body='.db_input(Format::striptags($var['ticket_reply_body'])). | ||
| ' WHERE tpl_id='.db_input($this->getId()); | ||
|
|
||
| if(!db_query($sql) || !db_affected_rows()) | ||
| $errors['err']='Unable to update. Internal error occured'; | ||
|
|
||
| } | ||
|
|
||
| return $errors?false:true; | ||
|
|
||
| } | ||
|
|
||
|
|
||
| function getIdByName($name) { | ||
|
|
||
| $id=0; | ||
| $sql='SELECT tpl_id FROM '.EMAIL_TEMPLATE_TABLE.' WHERE name='.db_input($name); | ||
| if(($resp=db_query($sql)) && db_num_rows($resp)) | ||
| list($id)=db_fetch_row($resp); | ||
|
|
||
| return $id; | ||
| } | ||
|
|
||
|
|
||
| function create($var,&$errors){ | ||
| global $cfg; | ||
|
|
||
| if(!$var['name']) | ||
| $errors['name']='required'; | ||
| elseif(!$errors && Template::getIdByName($var['name'])) | ||
| $errors['name']='Name already in use'; | ||
|
|
||
| if(!$var['copy_template']) | ||
| $errors['copy_template']='required'; | ||
| else if(!$errors){ | ||
| $template= new Template($var['copy_template'],$cfg->getId()); | ||
| if(!is_object($template) || !$template->getId()) | ||
| $errors['copy_template']='Unknown template'; | ||
| } | ||
|
|
||
| $id=0; | ||
| if(!$errors && ($info=$template->getInfo())) { | ||
|
|
||
| $sql='INSERT INTO '.EMAIL_TEMPLATE_TABLE.' SET updated=NOW(), created=NOW() '. | ||
| ',cfg_id='.db_input($cfg->getId()). | ||
| ',name='.db_input(Format::striptags($var['name'])). | ||
| ',notes='.db_input('New template: copy of '.$info['name']). | ||
| ',ticket_autoresp_subj='.db_input(Format::striptags($info['ticket_autoresp_subj'])). | ||
| ',ticket_autoresp_body='.db_input(Format::striptags($info['ticket_autoresp_body'])). | ||
| ',message_autoresp_subj='.db_input(Format::striptags($info['message_autoresp_subj'])). | ||
| ',message_autoresp_body='.db_input(Format::striptags($info['message_autoresp_body'])). | ||
| ',ticket_notice_subj='.db_input(Format::striptags($info['ticket_notice_subj'])). | ||
| ',ticket_notice_body='.db_input(Format::striptags($info['ticket_notice_body'])). | ||
| ',ticket_alert_subj='.db_input(Format::striptags($info['ticket_alert_subj'])). | ||
| ',ticket_alert_body='.db_input(Format::striptags($info['ticket_alert_body'])). | ||
| ',message_alert_subj='.db_input(Format::striptags($info['message_alert_subj'])). | ||
| ',message_alert_body='.db_input(Format::striptags($info['message_alert_body'])). | ||
| ',note_alert_subj='.db_input(Format::striptags($info['note_alert_subj'])). | ||
| ',note_alert_body='.db_input(Format::striptags($info['note_alert_body'])). | ||
| ',assigned_alert_subj='.db_input(Format::striptags($info['assigned_alert_subj'])). | ||
| ',assigned_alert_body='.db_input(Format::striptags($info['assigned_alert_body'])). | ||
| ',ticket_overdue_subj='.db_input(Format::striptags($info['ticket_overdue_subj'])). | ||
| ',ticket_overdue_body='.db_input(Format::striptags($info['ticket_overdue_body'])). | ||
| ',ticket_overlimit_subj='.db_input(Format::striptags($info['ticket_overlimit_subj'])). | ||
| ',ticket_overlimit_body='.db_input(Format::striptags($info['ticket_overlimit_body'])). | ||
| ',ticket_reply_subj='.db_input(Format::striptags($info['ticket_reply_subj'])). | ||
| ',ticket_reply_body='.db_input(Format::striptags($info['ticket_reply_body'])); | ||
| //echo $sql; | ||
| if(!db_query($sql) || !($id=db_insert_id())) | ||
| $errors['err']='Unable to create the template. Internal error occured'; | ||
| } | ||
| return $id; | ||
| } | ||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,103 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.nav.php | ||
| Navigation helper classes. Pointless BUT helps keep navigation clean and free from errors. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: $ | ||
| **********************************************************************/ | ||
| class StaffNav { | ||
| var $tabs=array(); | ||
| var $submenu=array(); | ||
|
|
||
| var $activetab; | ||
| var $ptype; | ||
|
|
||
| function StaffNav($pagetype='staff'){ | ||
| global $thisuser; | ||
|
|
||
| $trl = $_SESSION['trl']; | ||
|
|
||
| $this->ptype=$pagetype; | ||
| $tabs=array(); | ||
| if($thisuser->isAdmin() && strcasecmp($pagetype,'admin')==0) { | ||
| $desc = $trl->translate("LABEL_DASHBOARD"); | ||
| $title = $trl->translate("LABEL_ADMIN_DASHBOARD"); | ||
| $tabs['dashboard']=array('desc'=>$title,'href'=>'admin.php?t=dashboard','title'=>$tile); | ||
| $desc = $trl->translate("LABEL_SETTINGS"); | ||
| $title = $trl->translate("LABEL_SYSTEM_SETTINGS"); | ||
| $tabs['settings']=array('desc'=>$desc,'href'=>'admin.php?t=settings','title'=>$title); | ||
| $desc = $trl->_t('LABEL_EMAILS'); | ||
| $title = $trl->_t('LABEL_EMAILS_SETTINGS'); | ||
| $tabs['emails']=array('desc'=>$desc,'href'=>'admin.php?t=email','title'=>$title); | ||
| $desc = $trl->_t('LABEL_HELP_TOPICS'); | ||
| $title = $trl->_t('LABEL_HELP_TOPICS'); | ||
| $tabs['topics']=array('desc'=>$desc,'href'=>'admin.php?t=topics','title'=>$title); | ||
| $desc = $trl->_t('LABEL_STAFF'); | ||
| $title = $trl->_t('LABEL_STAFF_MEMBERS'); | ||
| $tabs['staff']=array('desc'=>$desc,'href'=>'admin.php?t=staff','title'=>$title); | ||
| $desc = $trl->_t('LABEL_DEPARTMENTS'); | ||
| $title = $trl->_t('LABEL_DEPARTMENTS'); | ||
| $tabs['depts']=array('desc'=>$desc,'href'=>'admin.php?t=depts','title'=>$title); | ||
| }else { | ||
| $tabs['tickets']=array('desc'=>'Tickets','href'=>'tickets.php','title'=>'Ticket Queue'); | ||
| if($thisuser && $thisuser->canManageKb()){ | ||
| $desc = $trl->translate('LABEL_KNOWLEDGE_BASE'); | ||
| $title = $trl->translate('LABEL_KNOWLEDGE_BASE_PREMATE'); | ||
| $tabs['kbase']=array('desc'=>$desc,'href'=>'kb.php','title'=>$title); | ||
| } | ||
| $desc = $trl->translate('LABEL_DIRECTORY'); | ||
| $title = $trl->translate('LABEL_DIRETORY_STAFF'); | ||
| $tabs['directory']=array('desc'=>$desc,'href'=>'directory.php','title'=>$title); | ||
| $desc = $trl->translate('LABEL_MY_ACCOUNT'); | ||
| $title = $trl->translate('LABEL_MY_ACCOUNT'); | ||
| $tabs['profile']=array('desc'=>$desc,'href'=>'profile.php','title'=>$title); | ||
| } | ||
| $this->tabs=$tabs; | ||
| } | ||
|
|
||
|
|
||
| function setTabActive($tab){ | ||
|
|
||
| if($this->tabs[$tab]){ | ||
| $this->tabs[$tab]['active']=true; | ||
| if($this->activetab && $this->activetab!=$tab && $this->tabs[$this->activetab]) | ||
| $this->tabs[$this->activetab]['active']=false; | ||
| $this->activetab=$tab; | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| function addSubMenu($item,$tab=null) { | ||
|
|
||
| $tab=$tab?$tab:$this->activetab; | ||
| $this->submenu[$tab][]=$item; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| function getActiveTab(){ | ||
| return $this->activetab; | ||
| } | ||
|
|
||
| function getTabs(){ | ||
| return $this->tabs; | ||
| } | ||
|
|
||
| function getSubMenu($tab=null){ | ||
|
|
||
| $tab=$tab?$tab:$this->activetab; | ||
| return $this->submenu[$tab]; | ||
| } | ||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,145 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.format.php | ||
| Pagenation support class | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006-2010 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: | ||
| $Id: class.pagenate.php,v 1.1.2.2 2009/11/29 22:03:28 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
|
|
||
| class PageNate { | ||
|
|
||
| var $start; | ||
| var $limit; | ||
| var $total; | ||
| var $page; | ||
| var $pages; | ||
| var $trl; | ||
|
|
||
| function PageNate($total,$page,$limit=20,$trl=null, $url='') { | ||
| $this->total = intval($total); | ||
| $this->limit = max($limit, 1 ); | ||
| $this->page = max($page, 1 ); | ||
| $this->start = max((($page-1)*$this->limit),0); | ||
| $this->pages = ceil( $this->total / $this->limit ); | ||
|
|
||
| if(isset($trl)){ | ||
| $this->trl = $trl; | ||
| }else{ | ||
| $this->trl = new Translator(); | ||
| } | ||
| if (($this->limit > $this->total) || ($this->page>ceil($this->total/$this->limit))) { | ||
| $this->start = 0; | ||
| } | ||
| if (($this->limit-1)*$this->start > $this->total) { | ||
| $this->start -= $this->start % $this->limit; | ||
| } | ||
| $this->setURL($url); | ||
| } | ||
| function setURL($url='',$vars=''){ | ||
| if($url){ | ||
| if(strpos($url,'?')===false) | ||
| $url=$url.'?'; | ||
| }else{ | ||
| $url=THISPAGE.'?'; | ||
| } | ||
| $this->url=$url.$vars; | ||
| } | ||
|
|
||
| function getStart() { | ||
| return $this->start; | ||
| } | ||
|
|
||
| function getLimit() { | ||
| return $this->limit; | ||
| } | ||
|
|
||
|
|
||
| function getNumPages(){ | ||
| return $this->pages; | ||
| } | ||
|
|
||
| function getPage() { | ||
| return ceil(($this->start+1)/$this->limit); | ||
| } | ||
|
|
||
|
|
||
| function showing() { | ||
| $html = ''; | ||
| $from= $this->start+1; | ||
| if ($this->start + $this->limit < $this->total) { | ||
| $to= $this->start + $this->limit; | ||
| } else { | ||
| $to= $this->total; | ||
| } | ||
| if(!isset($this->trl)){ | ||
| $html=" Showing "; | ||
| if ($this->total > 0) { | ||
| $html .= "$from - $to of " .$this->total; | ||
| }else{ | ||
| $html .= " 0 "; | ||
| } | ||
| }else{ | ||
| if ($this->total > 0) { | ||
| $html .= $this->trl->translate('TEXT_SHOW_FROM_TO_OF_ALL',array($from, $to, $this->total)); | ||
| }else{ | ||
| $html .= $this->trl->translate('TEXT_SHOW_ZERO'); | ||
| } | ||
| } | ||
| return $html; | ||
| } | ||
|
|
||
| function getPageLinks() { | ||
| $html = ''; | ||
| $file =$this->url; | ||
| $displayed_span = 5; | ||
| $total_pages = ceil( $this->total / $this->limit ); | ||
| $this_page = ceil( ($this->start+1) / $this->limit ); | ||
|
|
||
| $last=$this_page-1; | ||
| $next=$this_page+1; | ||
|
|
||
| $start_loop = floor($this_page-$displayed_span); | ||
| $stop_loop = ceil($this_page + $displayed_span); | ||
|
|
||
|
|
||
|
|
||
| $stopcredit =($start_loop<1)?0-$start_loop:0; | ||
| $startcredit =($stop_loop>$total_pages)?$stop_loop-$total_pages:0; | ||
|
|
||
| $start_loop =($start_loop-$startcredit>0)?$start_loop-$startcredit:1; | ||
| $stop_loop =($stop_loop+$stopcredit>$total_pages)?$total_pages:$stop_loop+$stopcredit; | ||
|
|
||
| if($start_loop>1){ | ||
| $lastspan=($start_loop-$displayed_span>0)?$start_loop-$displayed_span:1; | ||
| $html .= "\n<a href=\"$file&p=$lastspan\" ><strong>«</strong></a>"; | ||
| } | ||
|
|
||
| for ($i=$start_loop; $i <= $stop_loop; $i++) { | ||
| $page = ($i - 1) * $this->limit; | ||
| if ($i == $this_page) { | ||
| $html .= "\n<b>[$i]</b>"; | ||
| } else { | ||
| $html .= "\n<a href=\"$file&p=$i\" ><b>$i</b></a>"; | ||
| } | ||
| } | ||
| if($stop_loop<$total_pages){ | ||
| $nextspan=($stop_loop+$displayed_span>$total_pages)?$total_pages-$displayed_span:$stop_loop+$displayed_span; | ||
| $html .= "\n<a href=\"$file&p=$nextspan\" ><strong>»</strong></a>"; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| return $html; | ||
| } | ||
|
|
||
| } | ||
| ?> |
| @@ -0,0 +1,3 @@ | ||
| <?php | ||
| //No longer used. just used to clear the old file for now. Will be deleted in the upcoming versions. | ||
| ?> |
| @@ -0,0 +1,340 @@ | ||
| <?php | ||
| /********************************************************************* | ||
| class.staff.php | ||
| Everything about staff. | ||
| Peter Rotich <peter@osticket.com> | ||
| Copyright (c) 2006,2007,2008,2009 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: | ||
| $Id: class.staff.php,v 1.1.2.1 2009/08/17 18:38:50 carlos.delfino Exp $ | ||
| **********************************************************************/ | ||
| class Staff { | ||
|
|
||
| var $udata; | ||
| var $group_id; | ||
| var $dept_id; | ||
| var $passwd; | ||
| var $id; | ||
| var $fullname; | ||
| var $username; | ||
| var $email; | ||
|
|
||
| var $firstname; | ||
| var $lastname; | ||
| var $signature; | ||
|
|
||
| var $dept; | ||
|
|
||
| function Staff($var){ | ||
| $this->id =0; | ||
| return ($this->lookup($var)); | ||
| } | ||
|
|
||
| function lookup($var){ | ||
|
|
||
| $sql=sprintf("SELECT * FROM ".STAFF_TABLE." LEFT JOIN ".GROUP_TABLE." USING(group_id) WHERE %s=%s ", | ||
| is_numeric($var)?'staff_id':'username',db_input($var)); | ||
|
|
||
| $res=db_query($sql); | ||
| if(!$res || !db_num_rows($res)) | ||
| return NULL; | ||
|
|
||
| $row=db_fetch_array($res); | ||
| $this->udata=$row; | ||
| $this->id = $row['staff_id']; | ||
| $this->group_id = $row['group_id']; | ||
| $this->dept_id = $row['dept_id']; | ||
| $this->firstname = ucfirst($row['firstname']); | ||
| $this->lastname = ucfirst($row['lastname']); | ||
| $this->fullname = ucfirst($row['firstname'].' '.$row['lastname']); | ||
| $this->passwd = $row['passwd']; | ||
| $this->username = $row['username']; | ||
| $this->email = $row['email']; | ||
| $this->signature = $row['signature']; | ||
|
|
||
| return($this->id); | ||
| } | ||
|
|
||
| function reload(){ | ||
| $this->lookup($this->id); | ||
| } | ||
|
|
||
| function getInfo() { | ||
| return $this->udata; | ||
| } | ||
|
|
||
| /*compares user password*/ | ||
| function check_passwd($password){ | ||
| return (strlen($this->passwd) && strcmp($this->passwd, MD5($password))==0)?(TRUE):(FALSE); | ||
| } | ||
|
|
||
| function getTZoffset(){ | ||
| global $cfg; | ||
|
|
||
| $offset=$this->udata['timezone_offset']; | ||
| return $offset?$offset:$cfg->getTZoffset(); | ||
| } | ||
|
|
||
| function observeDaylight() { | ||
| return $this->udata['daylight_saving']?true:false; | ||
| } | ||
|
|
||
| function getRefreshRate(){ | ||
| return $this->udata['auto_refresh_rate']; | ||
| } | ||
|
|
||
| function getPageLimit() { | ||
| global $cfg; | ||
| $limit=$this->udata['max_page_size']; | ||
| return $limit?$limit:$cfg->getPageSize(); | ||
| } | ||
|
|
||
| function getData(){ | ||
| return($this->udata); | ||
| } | ||
|
|
||
| function getId(){ | ||
| return $this->id; | ||
| } | ||
|
|
||
| function getEmail(){ | ||
| return($this->email); | ||
| } | ||
|
|
||
| function getUserName(){ | ||
| return($this->username); | ||
| } | ||
|
|
||
| function getName(){ | ||
| return($this->fullname); | ||
| } | ||
|
|
||
| function getFirstName(){ | ||
| return $this->firstname; | ||
| } | ||
|
|
||
| function getLastName(){ | ||
| return $this->lastname; | ||
| } | ||
|
|
||
| function getDeptId(){ | ||
| return $this->dept_id; | ||
| } | ||
|
|
||
| function getGroupId(){ | ||
| return $this->group_id; | ||
| } | ||
|
|
||
| function getSignature(){ | ||
| return($this->signature); | ||
| } | ||
|
|
||
| function appendMySignature(){ | ||
| return $this->signature?true:false; | ||
| } | ||
|
|
||
| function forcePasswdChange(){ | ||
| return $this->udata['change_passwd']?true:false; | ||
| } | ||
|
|
||
| function getDepts(){ | ||
| //Departments the user is allowed to access...based on the group they belong to + user's dept. | ||
| return array_filter(array_unique(array_merge(explode(',',$this->udata['dept_access']),array($this->dept_id)))); //Neptune help us | ||
| } | ||
|
|
||
| function getDept(){ | ||
|
|
||
| if(!$this->dept && $this->dept_id) | ||
| $this->dept= new Dept($this->dept_id); | ||
|
|
||
| return $this->dept; | ||
| } | ||
|
|
||
|
|
||
| function isManager() { | ||
| return (($dept=$this->getDept()) && $dept->getManagerId()==$this->getId())?true:false; | ||
| } | ||
|
|
||
| function isStaff(){ | ||
| return TRUE; | ||
| } | ||
|
|
||
| function isGroupActive() { | ||
| return ($this->udata['group_enabled'])?true:false; | ||
| } | ||
|
|
||
| function isactive(){ | ||
| return ($this->udata['isactive'])?true:false; | ||
| } | ||
|
|
||
| function isVisible(){ | ||
| return ($this->udata['isvisible'])?true:false; | ||
| } | ||
|
|
||
| function onVacation(){ | ||
| return ($this->udata['onvacation'])?true:false; | ||
| } | ||
|
|
||
| function isAvailable() { | ||
| return (!$this->isactive() || !$this->isGroupActive() || $this->onVacation())?false:true; | ||
| } | ||
|
|
||
| function isadmin(){ | ||
| return ($this->udata['isadmin'])?true:false; | ||
| } | ||
|
|
||
| /* canDos' logic explained | ||
| 1) First check id the user is super admin...if yes...super..allow | ||
| 2) Check if the user is allowed to do the Do...or a manager in some cases -- if yes...allow | ||
| 3) Check if he user's group is allowed...if yes...allow | ||
| 5) If I-2-3 fails...it is a NO.. you can cry yourself to sleep. | ||
| */ | ||
|
|
||
| function canAccessDept($deptid){ | ||
| return ($this->isadmin() ||in_array($deptid,$this->getDepts()))?true:false; | ||
| } | ||
|
|
||
| function canCreateTickets(){ | ||
| return ($this->isadmin() || $this->udata['can_create_tickets'])?true:false; | ||
| } | ||
|
|
||
| function canEditTickets(){ | ||
| return ($this->isadmin() || $this->udata['can_edit_tickets'])?true:false; | ||
| } | ||
|
|
||
| function canDeleteTickets(){ | ||
| return ($this->isadmin() || $this->udata['can_delete_tickets'])?true:false; | ||
| } | ||
|
|
||
| function canCloseTickets(){ | ||
| return ($this->isadmin() || $this->udata['can_close_tickets'])?true:false; | ||
| } | ||
|
|
||
| function canTransferTickets() { | ||
| return ($this->isadmin() || $this->isManager() || $this->udata['can_transfer_tickets'])?true:false; | ||
| } | ||
|
|
||
| function canManageBanList() { | ||
| return ($this->isadmin() || $this->isManager() || $this->udata['can_ban_emails'])?true:false; | ||
| } | ||
|
|
||
| function canManageTickets() { | ||
| return ($this->isadmin() | ||
| || $this->canDeleteTickets() | ||
| || $this->canManageBanList() | ||
| || $this->canCloseTickets())?true:false; | ||
| } | ||
|
|
||
| function canManageKb() { //kb = knowledge base. | ||
| return ($this->isadmin() || $this->udata['can_manage_kb'])?true:false; | ||
| } | ||
|
|
||
| function update($vars,&$errors) { | ||
| if($this->save($this->getId(),$vars,$errors)){ | ||
| $this->reload(); | ||
| return true; | ||
| } | ||
| return false; | ||
| } | ||
|
|
||
| function create($vars,&$errors) { | ||
| return Staff::save(0,$vars,$errors); | ||
| } | ||
|
|
||
|
|
||
| function save($id,$vars,&$errors) { | ||
|
|
||
| include_once(INCLUDE_DIR.'class.dept.php'); | ||
|
|
||
| if($id && $id!=$vars['staff_id']) | ||
| $errors['err']='Internal Error'; | ||
|
|
||
| if(!$vars['firstname'] || !$vars['lastname']) | ||
| $errors['name']='First and last name required'; | ||
|
|
||
| if(!$vars['username'] || strlen($vars['username'])<3) | ||
| $errors['username']='Username required'; | ||
| else{ | ||
| //check if the username is already in-use. | ||
| $sql='SELECT staff_id FROM '.STAFF_TABLE.' WHERE username='.db_input($vars['username']); | ||
| if($id) | ||
| $sql.=' AND staff_id!='.db_input($id); | ||
|
|
||
| if(db_num_rows(db_query($sql))) | ||
| $errors['username']='Username already in-use'; | ||
| } | ||
|
|
||
| if(!$vars['email'] || !Validator::is_email($vars['email'])) | ||
| $errors['email']='Valid email required'; | ||
| elseif(Email::getIdByEmail($vars['email'])) | ||
| $errors['email']='Already in-use system email'; | ||
|
|
||
| if($vars['phone'] && !Validator::is_phone($vars['phone'])) | ||
| $errors['phone']='Valid number required'; | ||
|
|
||
| if($vars['mobile'] && !Validator::is_phone($vars['mobile'])) | ||
| $errors['mobile']='Valid number required'; | ||
|
|
||
| if($vars['npassword'] || $vars['vpassword'] || !$id){ | ||
| if(!$vars['npassword'] && !$id) | ||
| $errors['npassword']='Temp password required'; | ||
| elseif($vars['npassword'] && strcmp($vars['npassword'],$vars['vpassword'])) | ||
| $errors['vpassword']='Password(s) do not match'; | ||
| elseif($vars['npassword'] && strlen($vars['npassword'])<6) | ||
| $errors['npassword']='Must be at least 6 characters'; | ||
| } | ||
|
|
||
| if(!$vars['dept_id']) | ||
| $errors['dept']='Department required'; | ||
|
|
||
| if(!$vars['group_id']) | ||
| $errors['group']='Group required'; | ||
|
|
||
|
|
||
| if(!$errors){ | ||
|
|
||
| $sql=' SET updated=NOW() '. | ||
| ',isadmin='.db_input($vars['isadmin']). | ||
| ',isactive='.db_input($vars['isactive']). | ||
| ',isvisible='.db_input(isset($vars['isvisible'])?1:0). | ||
| ',onvacation='.db_input(isset($vars['onvacation'])?1:0). | ||
| ',dept_id='.db_input($vars['dept_id']). | ||
| ',group_id='.db_input($vars['group_id']). | ||
| ',username='.db_input(Format::striptags($vars['username'])). | ||
| ',firstname='.db_input(Format::striptags($vars['firstname'])). | ||
| ',lastname='.db_input(Format::striptags($vars['lastname'])). | ||
| ',email='.db_input($vars['email']). | ||
| ',phone="'.db_input($vars['phone'],false).'"'. | ||
| ',phone_ext='.db_input($vars['phone_ext']). | ||
| ',mobile="'.db_input($vars['mobile'],false).'"'. | ||
| ',signature='.db_input(Format::striptags($vars['signature'])); | ||
|
|
||
| if($vars['npassword']) | ||
| $sql.=',passwd='.db_input(md5($vars['npassword'])); | ||
|
|
||
| if(isset($vars['resetpasswd'])) | ||
| $sql.=',change_passwd=1'; | ||
|
|
||
| if($id) { | ||
| $sql='UPDATE '.STAFF_TABLE.' '.$sql.' WHERE staff_id='.db_input($id); | ||
| if(!db_query($sql) || !db_affected_rows()) | ||
| $errors['err']='Unable to update the user. Internal error occured'; | ||
| }else{ | ||
| $sql='INSERT INTO '.STAFF_TABLE.' '.$sql.',created=NOW()'; | ||
| if(db_query($sql) && ($uID=db_insert_id())) | ||
| return $uID; | ||
|
|
||
| $errors['err']='Unable to create user. Internal error'; | ||
| } | ||
| } | ||
|
|
||
| return $errors?false:true; | ||
| } | ||
| } | ||
| ?> |