class.audit.php'^5 .DS_Store'^t audit.php'^c,I plugin.php'^6 config.php'^-templates/.DS_Store'^jmtemplates/auditlogs.tmpl.php'^\templates/agent-audit.tmpl.php'^F8Stemplates/ticket-audit.tmpl.php '^ 2+Qtemplates/user-audit.tmpl.php'^߼ ܶ AUDIT_TABLE, 'pk' => array('id'), 'ordering' => array('-timestamp'), 'select_related' => array('staff', 'user'), 'joins' => array( 'staff' => array( 'constraint' => array('staff_id' => 'Staff.staff_id'), 'null' => true, ), 'user' => array( 'constraint' => array('user_id' => 'User.id'), 'null' => true, ), ), ); //return an array with the object model, getName function, and url prefix static $types = array( 'S' => array('Staff', 'getName', 'staff.php'), 'B' => array('Canned', 'getTitle', 'canned.php'), 'C' => array('Category', 'getName', 'categories.php'), 'X' => array('ConfigItem', 'none', 'none'), 'D' => array('Dept', 'getName', 'departments.php'), 'M' => array('Email', 'getName', 'emails.php'), 'I' => array('EmailTemplateGroup', 'getName', 'templates.php'), 'Q' => array('FAQ', 'getQuestion', 'faq.php'), 'N' => array('DynamicForm', 'getTitle', 'forms.php'), 'H' => array('Topic', 'getName', 'helptopics.php'), 'L' => array('DynamicList', 'getName', 'lists.php'), 'O' => array('Organization', 'getName', 'orgs.php'), 'G' => array('Page', 'getName', 'pages.php'), 'R' => array('Role', 'getName', 'roles.php'), 'V' => array('SLA', 'getName', 'slas.php'), 'A' => array('Task', 'getNumber', 'tasks.php'), 'E' => array('Team', 'getName', 'teams.php'), 'T' => array('Ticket', 'getNumber', 'tickets.php'), 'F' => array('Filter', 'getName', 'filters.php'), 'U' => array('User', 'getName', 'users.php'), 'J' => array('ClientAccount', 'getUserName', 'users.php'), ); static function bootstrap() { Signal::connect('object.view', array('AuditEntry', 'auditObjectEvent')); Signal::connect('object.created', array('AuditEntry', 'auditObjectEvent')); Signal::connect('object.deleted', array('AuditEntry', 'auditObjectEvent')); Signal::connect('object.edited', array('AuditEntry', 'auditObjectEvent')); Signal::connect('person.login', array('AuditEntry', 'auditSpecialEvent')); Signal::connect('person.logout', array('AuditEntry', 'auditSpecialEvent')); } function getObjectName($class) { switch ($class) { case 'Dept': return __('Department'); break; case 'OrganizationModel': return __('Organization'); break; case 'Canned': return __('Canned Response'); break; case 'Topic': return __('Help Topic'); break; case 'Staff': return __('Agent'); break; case 'Filter': return __('Ticket Filter'); break; case 'EmailTemplateGroup': return __('Email Template'); break; case 'DynamicList': return __('List'); break; case 'DynamicForm': return __('Form'); break; case 'ConfigItem': return __('Configuration'); break; case 'ClientAccount': return __('User Account'); break; default: return $class; break; } } static $configurations = array( 'time_format' => 'Time Format', //Configurations 'date_format' => 'Date Format', 'datetime_format' => 'Date and Time Format', 'daydatetime_format' => 'Day Date and Time Format', 'default_priority_id' => 'Default Priority', 'reply_separator' => 'Reply Separator Tag', 'isonline' => 'Helpdesk Status', 'staff_ip_binding' => 'Bind Agent Session to IP', 'staff_max_logins' => 'Staff Max Logins', 'staff_login_timeout' => 'Staff Login TImeout', 'staff_session_timeout' => 'Agent Session Timeout', 'passwd_reset_period' => 'Password Expiration Policy', 'client_max_logins' => 'User Max Logins', 'client_login_timeout' => 'User Login TImeout', 'client_session_timeout' => 'User Session Timeout', 'max_page_size' => 'Default Page Size', 'max_open_tickets' => 'Maximum Open Tickets', 'autolock_minutes' => 'Collision Avoidance Duration', 'default_priority_id' => 'Ticket Default Priority', 'default_smtp_id' => 'Default MTA', 'use_email_priority' => 'Emailed Tickets Priority', 'enable_kb' => 'Enable Knowledge Base', 'enable_premade' => 'Enable Canned Responses', 'enable_captcha' => 'Human Verification:', 'enable_auto_cron' => 'Fetch on auto-cron', 'enable_mail_polling' => 'Email Fetching', 'send_sys_errors' => 'System Errors', 'send_sql_errors' => 'SQL Errors', 'send_login_errors' => 'Excessive failed login attempts', 'strip_quoted_reply' => 'Strip Quoted Reply', 'ticket_autoresponder' => 'New Ticket Autoresponder', 'message_autoresponder' => 'New Message Submitter Autoresponder', 'ticket_notice_active' => 'New Ticket by Agent Autoresponder', 'ticket_alert_active' => 'New Ticket Alert', 'ticket_alert_admin' => 'Admin New Ticket Alert', 'ticket_alert_dept_manager' => 'Manager New Ticket Alert', 'ticket_alert_dept_members' => 'Dept Members New Ticket Alert', 'message_alert_active' => 'New Message Alert', 'message_alert_laststaff' => 'Last Respondent New Message Alert', 'message_alert_assigned' => 'Assigned Agent / Team New Message Alert', 'message_alert_dept_manager' => 'Department Manager New Message Alert', 'note_alert_active' => 'New Internal Activity Alert', 'note_alert_laststaff' => 'Last Respondent Internal Activity Alert', 'note_alert_assigned' => 'Assigned Agent / Team Internal Activity Alert', 'note_alert_dept_manager' => 'Department Manager Internal Activity Alert', 'transfer_alert_active' => 'Ticket Transfer Alert', 'transfer_alert_assigned' => 'Assigned Agent / Team Ticket Transfer Alert', 'transfer_alert_dept_manager' => 'Department Manager Ticket Transfer Alert', 'transfer_alert_dept_members' => 'Department Members Ticket Transfer Alert', 'overdue_alert_active' => 'Overdue Ticket Alert', 'overdue_alert_assigned' => 'Assigned Agent / Team Overdue Ticket Alert', 'overdue_alert_dept_manager' => 'Department Manager Overdue Ticket Alert', 'overdue_alert_dept_members' => 'Department Members Overdue Ticket Alert', 'assigned_alert_active' => 'Ticket Assignment Alert', 'assigned_alert_staff' => 'Assigned Agent Ticket Assignment Alert', 'assigned_alert_team_lead' => 'Team Lead Ticket Assignment Alert', 'assigned_alert_team_members' => 'Team Members Ticket Assignment Alert', 'auto_claim_tickets' => 'Claim on Response', 'collaborator_ticket_visibility' => 'Collaborator Tickets Visibility', 'require_topic_to_close' => 'Require Help Topic to Close', 'hide_staff_name' => 'Agent Identity Masking', 'overlimit_notice_active' => 'Overlimit Notice Autoresponder', 'email_attachments' => 'Email Attachments', 'ticket_number_format' => 'Default Ticket Number Format', 'ticket_sequence_id' => 'Default Ticket Number Sequence', 'queue_bucket_counts' => 'Top-Level Ticket Counts', 'task_number_format' => 'Default Task Number Format', 'task_sequence_id' => 'Default Task Number Sequence', 'log_level' => 'Default Log Level', 'log_graceperiod' => 'Purge Logs', 'client_registration' => 'Registration Method', 'default_ticket_queue' => 'Default Ticket Queue', 'accept_unregistered_email' => 'Accept All Emails', 'add_email_collabs' => 'Accept Email Collaborators', 'helpdesk_url' => 'Helpdesk URL', 'helpdesk_title' => 'Helpdesk Name/Title', 'default_dept_id' => 'Default Department', 'enable_avatars' => 'Show Avatars', 'enable_richtext' => 'Enable Rich Text', 'default_locale' => 'Default Locale', 'default_timezone' => 'Default Time Zone', 'date_formats' => 'Date and Time Format', 'system_language' => 'Primary Language', 'add_secondary_language' => 'Secondary Languages', 'default_storage_bk' => 'Store Attachments', 'max_file_size' => 'Agent Maximum File Size', 'files_req_auth' => 'Login required', 'default_ticket_status_id' => 'Default Status', 'default_sla_id' => 'Default SLA', 'default_help_topic' => 'Default Help Topic', 'ticket_lock' => 'Lock Semantics', 'message_autoresponder_collabs' => 'New Message Participant Autoresponder', 'ticket_alert_acct_manager' => 'Account Manager New Ticket Alert', 'message_alert_acct_manager' => 'Account Manager New Message Alert', 'default_task_priority_id' => 'Default Task Priority', 'task_alert_active' => 'New Task Alert', 'task_alert_admin' => 'New Task Admin Alert', 'task_alert_dept_manager' => 'New Task Department Manager Alert', 'task_alert_dept_members' => 'New Task Department Members Alert', 'task_activity_alert_active' => 'New Task Activity Alert', 'task_activity_alert_laststaff' => 'New Task Activity Last Respondent', 'task_activity_alert_assigned' => 'New Task Activity Assigned Agent / Team', 'task_activity_alert_dept_manager' => 'New Task Activity Department Manager', 'task_assignment_alert_active' => 'Task Assignment Alert', 'task_assignment_alert_staff' => 'Task Assignment Alert Assigned Agent / Team', 'task_assignment_alert_team_lead' => 'Task Assignment Alert Team Lead', 'task_assignment_alert_team_members' => 'Task Assignment Alert Team Members', 'task_transfer_alert_active' => 'Task Transfer Alert', 'task_transfer_alert_assigned' => 'Task Transfer Alert Assigned Agent / Team', 'task_transfer_alert_dept_manager' => 'Task Transfer Alert Department Manager', 'task_transfer_alert_dept_members' => 'Task Transfer Alert Department Members', 'task_overdue_alert_active' => 'Overdue Task Alert', 'task_overdue_alert_assigned' => 'Overdue Task Alert Assigned Agent / Team', 'task_overdue_alert_dept_manager' => 'Overdue Task Alert Department Manager', 'task_overdue_alert_dept_members' => 'Overdue Task Alert Department Members', 'agent_name_format' => 'Agent Name Formatting', 'agent_avatar' => 'Agent Avatar Source', 'allow_pw_reset' => 'Allow Password Resets', 'pw_reset_window' => 'Reset Token Expiration', 'client_name_format' => 'User Name Formatting', 'client_avatar' => 'User Avatar Source', 'clients_only' => 'Registration Required', 'allow_auth_tokens' => 'Authentication Token', 'client_verify_email' => 'Client Quick Access', 'restrict_kb' => 'Knowledgebase Require Client Login', 'default_template_id' => 'Default Template Set', 'default_email_id' => 'Default System Email', 'alert_email_id' => 'Default Alert Email', 'admin_email' => 'Admin Email Address', 'verify_email_addrs' => 'Verify Email Addresses', 'name' => 'Name', // Common Configurations 'isactive' => 'Status', 'notes' => 'Notes', 'topic_id' => 'Help Topic', // Email Configurations 'userid' => 'Username', 'mail_active' => 'Mail Active', 'mail_host' => 'Fetching Hostname', 'mail_port' => 'Fetching Port', 'mail_proto' => 'Mail Box Protocol', 'mail_fetchfreq' => 'Fetch Frequency', 'mail_fetchmax' => 'Emails Per Fetch', 'postfetch' => 'Fetched Emails', 'mail_archivefolder' => 'Mail Archive Folder', 'smtp_active' => 'SMTP Active', 'smtp_host' => 'SMTP Hostname', 'smtp_port' => 'SMTP Port', 'smtp_auth' => 'Authentication Required', 'smtp_spoofing' => 'Header Spoofing', 'mail_encryption' => 'Mail Encryption', 'topic' => 'Name', // Help Topic Configurations 'ispublic' => 'Type', 'topic_pid' => 'Parent Topic', 'dept_id' => 'Department', 'custom-numbers' => 'Ticket Number Format', 'number_format' => 'Number Format', 'sequence_id' => 'Number Sequence', 'priority_id' => 'Priority', 'sla_id' => 'SLA Plan', 'page_id' => 'Thank-You Page', 'assign' => 'Auto-assign To', 'noautoresp' => 'Auto-Response', 'pid' => 'Parent', // Department Configurations 'ispublic' => 'Type', 'sla_id' => 'SLA', 'manager_id' => 'Manager', 'assignment_flag' => 'Ticket Assignment', 'disable_auto_claim' => 'Claim on Response', 'disable_reopen_auto_assign' => 'Reopen Auto Assignment', 'email_id' => 'Outgoing Email', 'tpl_id' => 'Template Set', 'ticket_auto_response' => 'New Ticket', 'message_auto_response' => 'New Message', 'autoresp_email_id' => 'Auto-Response Email', 'group_membership' => 'Recipients', 'signature' => 'Department Signature', 'grace_period' => 'Grace Period', // SLA Configurations 'transient' => 'Transient', 'disable_overdue_alerts' => 'Ticket Overdue Alerts', 'type' => 'Type', // Page Configurations 'body' => 'Page Content', 'name_plural' => 'Plural Name', // List Configurations 'sort_mode' => 'Sort Order', 'ticket.activity.notice' => 'New Activity Notice', // Email Template Configurations 'message.autoresp' => 'New Message Auto-response', 'ticket.autoreply' => 'New Ticket Auto-reply', 'ticket.autoresp' => 'New Ticket Auto-response', 'ticket.notice' => 'New Ticket Notice', 'ticket.overlimit' => 'Overlimit Notice', 'note.alert' => 'Internal Activity Alert', 'message.alert' => 'New Message Alert', 'ticket.alert' => 'New Ticket Alert', 'ticket.overdue' => 'Overdue Ticket Alert', 'assigned.alert' => 'Ticket Assignment Alert', 'transfer.alert' => 'Ticket Transfer Alert', 'task.activity.alert' => 'New Activity Alert', 'task.activity.notice' => 'New Activity Notice', 'task.alert' => 'New Task Alert', 'task.overdue.alert' => 'Overdue Task Alert', 'task.assignment.alert' => 'Task Assignment Alert', 'task.transfer.alert' => 'Task Transfer Alert', 'firstname' => 'First Name', // Agent Configurations 'lastname' => 'Last Name', 'email' => 'Email', 'phone' => 'Phone Number', 'phone_ext' => 'Phone Extension', 'mobile' => 'Mobile Number', 'username' => 'Username', 'default_from_name' => 'Default From Name', 'thread_view_order' => 'Thread View Order', 'default_ticket_queue_id' => 'Default Ticket Queue', 'reply_redirect' => 'Reply Redirect', 'islocked' => 'Locked', 'isadmin' => 'Administrator', 'assigned_only' => 'Limit Access to Assigned', 'onvacation' => 'Vacation Mode', 'dept_access' => 'Department Access', 'role_id' => 'Role', 'passwd' => 'Password', 'backend' => 'Backend', 'lang' => 'Language', 'timezone' => 'Timezone', 'locale' => 'Locale', 'isvisible' => 'Visible', 'show_assigned_tickets' => 'Show Assigned Tickets', 'change_passwd' => 'Change Password', 'auto_refresh_rate' => 'Auto Refresh Rate', 'default_signature_type' => 'Default Signature Type', 'default_paper_size' => 'Default Paper Size', 'user.create' => 'Create Users', // Agent Permissions 'user.delete' => 'Delete Users', 'user.edit' => 'Edit Users', 'user.manage' => 'Manage Users', 'user.dir' => 'User Directory', 'org.create' => 'Create Organizations', 'org.delete' => 'Delete Organizations', 'org.edit' => 'Edit Organizations', 'faq.manage' => 'Manage FAQs', 'emails.banlist' => 'Banlist', 'search.all' => 'Search All', 'stats.agents' => 'Stats', 'isenabled' => 'Status', // Team Configurations 'lead_id' => 'Team Lead', 'noalerts' => 'Assignment Alert', 'ticket.assign' => 'Ticket Assign', // Role Configurations 'ticket.close' => 'Ticket Close', 'ticket.create' => 'Ticket Create', 'ticket.delete' => 'Ticket Delete', 'ticket.edit' => 'Ticket Edit', 'thread.edit' => 'Ticket Thread Edit', 'ticket.reply' => 'Ticket Reply', 'ticket.refer' => 'Ticket Refer', 'ticket.release' => 'Ticket Release', 'ticket.transfer' => 'Ticket Transfer', 'task.assign' => 'Task Assign', 'task.close' => 'Task Close', 'task.create' => 'Task Create', 'task.delete' => 'Task Delete', 'task.edit' => 'Task Edit', 'task.reply' => 'Task Reply', 'task.transfer' => 'Task Transfer', 'canned.manage' => 'Manage Canned Responses', 'execorder' => 'Execution Order', // Ticket Filter Configurations 'target' => 'Target Channel', 'match_all_rules' => 'Match All Criteria', 'stop_onmatch' => 'Stop On Match', 'manager' => 'Account Manager', // Organization Configurations 'assign-am-flag' => 'Auto-Assignment', 'contacts' => 'Contacts', 'sharing' => 'Ticket Sharing', 'collab-pc-flag' => 'Auto Collaboration - Primary Contacts', 'collab-all-flag' => 'Auto Collaboration - Organization Members', 'domain' => 'Email Domain', 'org' => 'Organization', // User Account Configurations 'timezone' => 'Timezone', 'password' => 'Password', 'locked-flag' => 'Administratively Locked', 'unlocked-flag' => 'Unlocked', 'pwreset-flag' => 'Password Reset Required', 'pwreset-sent' => 'Send Password Reset EMail', 'user-registered' => 'Registered', 'user-org' => 'Add to Organization', 'forbid-pwchange-flag' => 'User cannot change password', ); static $show_view_audits; function __toString() { return (string) $this->id; } //allows you to specify which part of the $types array you want returned function getTypeExtra($objectType, $infoType) { foreach (self::getTypes() as $key => $info) { if ($objectType == $key) { switch ($infoType) { case 'Model': $extra = __($info[0]); break; case 'Name': $extra = __($info[1]); break; case 'URL': $extra = __($info[2]); break; } } } return $extra; } function getPageNav($qwhere) { $qselect = 'SELECT audit.* '; $qfrom=' FROM '.AUDIT_TABLE.' audit '; $total=db_count("SELECT count(*) $qfrom $qwhere"); $page = ($_GET['p'] && is_numeric($_GET['p']))?$_GET['p']:1; //pagenate $pageNav=new Pagenate($total, $page, PAGE_LIMIT); return $pageNav; } function getQwhere($objectId, $hide_views=false, $type='') { $class = is_object($objectId) ? get_class($objectId) : $objectId; switch ($class) { case 'User': $qwhere = sprintf(' WHERE audit.user_id=%s', is_object($objectId) ? $objectId->getId() : $objectId); break; case 'Staff': $qwhere = sprintf(' WHERE audit.staff_id=%s', is_object($objectId) ? $objectId->getId() : $objectId); break; case 'Ticket': $qwhere = sprintf(' WHERE audit.object_id=%s', is_object($objectId) ? $objectId->getId() : $objectId); break; case 'AuditEntry': $qwhere =' WHERE 1'; $qwhere.=' AND object_type='.db_input($_REQUEST['type'] ?: 'D'); if ($hide_views) $qwhere.=' AND event_id='.db_input(Event::getIdByName($_REQUEST['state'])); if ($_REQUEST['state'] && $_REQUEST['state'] != __('All')) { $event_id = Event::getIdByName(lcfirst($_REQUEST['state'])); $qwhere.=' AND event_id='.db_input($event_id); } //dates $startTime =($_REQUEST['startDate'] && (strlen($_REQUEST['startDate'])>=8))?strtotime($_REQUEST['startDate']):0; $endTime =($_REQUEST['endDate'] && (strlen($_REQUEST['endDate'])>=8))?strtotime($_REQUEST['endDate']):0; if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0)){ $startTime=$endTime=0; } else { if($startTime) $qwhere.=' AND timestamp>=FROM_UNIXTIME('.$startTime.')'; if($endTime) $qwhere.=' AND timestamp<=FROM_UNIXTIME('.$endTime.')'; } break; default: $qwhere = $type ? sprintf(' WHERE audit.object_id=%d AND audit.object_type = "%s"', $objectId, $type) : sprintf('WHERE audit.object_id=%d', $objectId); break; } if (!self::$show_view_audits) $qwhere.=' AND event_id !='.db_input(Event::getIdByName('viewed')); return $qwhere; } function getOrder($order) { if($_REQUEST['order'] && $orderWays[strtoupper($_REQUEST['order'])]) { $order=$orderWays[strtoupper($_REQUEST['order'])]; } $order=$order?$order:'DESC'; return $order; } function getQuery($qs, $objectId, $pageNav, $export, $type='') { $qselect = 'SELECT audit.* '; $qfrom=' FROM '.AUDIT_TABLE.' audit '; $qwhere =self::getQwhere($objectId, false, $type); $sortOptions=array('id'=>'audit.id', 'object_id'=>'audit.object_id', 'state'=>'audit.state','type'=>'audit.object_type','ip'=>'audit.ip' ,'timestamp'=>'audit.timestamp'); $orderWays=array('DESC'=>'DESC','ASC'=>'ASC'); $sort=($_REQUEST['sort'] && $sortOptions[strtolower($_REQUEST['sort'])])?strtolower($_REQUEST['sort']):'timestamp'; //Sorting options... if($sort && $sortOptions[$sort]) { $order_column =$sortOptions[$sort]; } $order_column=$order_column?$order_column:'timestamp'; $order = self::getOrder($_REQUEST['order']); if($order_column && strpos($order_column,',')){ $order_column=str_replace(','," $order,",$order_column); } $x=$sort.'_sort'; $$x=' class="'.strtolower($order).'" '; $order_by="$order_column $order "; $query = sprintf("$qselect $qfrom $qwhere %s", $export ? '' : "ORDER BY $order_by LIMIT ".$pageNav->getStart().",".$pageNav->getLimit()); return $query; } function getTableInfo($objectId, $export=false, $type='') { $qs = array(); if($_REQUEST['type']) { $qs += array('type' => $_REQUEST['type']); } //pagenate $qwhere =self::getQwhere($objectId, false, $type); $pageNav=self::getPageNav($qwhere); $query = self::getQuery($qs, $objectId, $pageNav, $export, $type); $audits=db_query($query); if($audits && ($num=db_num_rows($audits))) $showing=$pageNav->showing().' '.$title; $table = array(); $count = 0; foreach ($audits as $event) { $class = is_object($objectId) ? get_class($objectId) : $objectId; $table[$count]['id'] = $event['id']; $table[$count]['staff_id'] = $event['staff_id']; $table[$count]['user_id'] = $event['user_id']; $table[$count]['event_id'] = $event['event_id']; $table[$count]['description'] = self::getDescription($event, $export); $table[$count]['timestamp'] = Format::datetime($event['timestamp']); $table[$count]['ip'] = $event['ip']; $count++; } return $table; } static function getTypes() { return self::$types; } static function getConfigurations() { return self::$configurations; } function getDescription($event, $export=false, $userType='') { $event = is_object($event) ? $event->ht : $event; $data = json_decode($event['data'], true); $name = ''; if (!is_array($event)) $event = $event->ht; if (!$person = $data['person']) $person = $event['staff_id'] ? (Staff::lookup($event['staff_id'])) : (User::lookup($event['user_id'])); if ($person) $name = is_string($person) ? $person : $person->getName()->name; if (!$userType) $userType = $event['staff_id'] ? __('Agent') : __('User'); $model = AuditEntry::getTypeExtra($event['object_type'], 'Model'); $objectName = AuditEntry::getObjectName($model); $link = $event['object_type'] ? AuditEntry::getObjectLink($event) : ''; $eventName = Event::getNameById($event['event_id']); $description = sprintf(__('%s %s %s %s %s'), $userType, $name, $eventName, $objectName, $link); switch ($eventName) { case 'message': $message = sprintf(__('%s %s posted a %s to %s %s'), $userType, $name, $userType == 'Agent' ? 'reply' : 'message', $objectName, $link); break; case 'note': $message = sprintf(__('%s %s posted a %s to %s %s'), $userType, $name, $eventName, $objectName, $link); break; case 'collab': $msg = $data['add'] ? 'Added ' : 'Deleted '; $data = $data['add'] ?: $data['del']; $name = array(); $i = 0; foreach ($data as $key => $value) { if (is_numeric($key) && $i < 5) $name[] = ($i < 4) ? $value['name'] : $value['name'] . '...'; $i++; } $name = implode(',', $name); $message = sprintf(__('%s %s %s Collaborator(s): %s Ticket: %s'), $userType, $person, $msg, $name, $link); break; case 'edited': switch ($event['object_type']) { case 'X': foreach (self::getConfigurations() as $key => $value) { if ($data['key'] == $key) $configuration = __($value); } $message = sprintf(__('%s %s %s: %s'), $name ?: $userType, $data['type'] ?: 'Edited', $objectName, $configuration ?: $data['key']); break; case 'T': case 'A': if ($data['fields']) { $fields = array(); foreach ($data['fields'] as $key => $value) { if (is_array($data['fields'][$key]) && $key == 'fields') $key = key($data['fields'][$key]); if (is_numeric($key)) { $field = DynamicFormField::objects()->filter(array('id'=>$key))->values_flat('label')->first() ?: array(); $fields[] = $field[0]; } else { $field[0] = ucfirst($key); } $message = sprintf(__('%s %s Edited Field(s): %s %s: %s '), $userType, $name ?: $userType, !empty($fields) ? implode(',',$fields) : ($field[0] ?: '-'), $objectName, $link); } } break; default: if ($data['key']) { foreach (self::getConfigurations() as $key => $value) { if ($data['key'] == $key) $configuration = __($value); } } $message = sprintf(__('%s %s %s %s %s'), $name ?: $userType, $data['status'] ?: 'Edited', $objectName, $link, $configuration ?: $data['key'] ?: ''); break; } break; case 'login': case 'logout': $message = sprintf(__('%s %s %s'),$userType, $name, $data['msg'] ?: Event::getNameById($event['event_id'])); break; case 'referred': case 'transferred': foreach ($data as $key => $value) { $name = is_array($value) ? '' : $value; if ($key != 'name') $msg = sprintf(__('%s to %s %s'), $description, self::getObjectName(ucfirst($key)), $name); } $message = __($msg ?: $description); break; case 'assigned': foreach ($data as $key => $value) { $assignee = is_array($value) ? '' : $value; if ($key != 'name' && $value) $msg = sprintf(__('%s to %s %s'), $description, self::getObjectName(ucfirst($key)), $assignee); if ($key == 'claim') $msg = sprintf(__('Agent %s Claimed %s'),$name ?: 'Agent', $link); if ($key == 'auto') $msg = sprintf(__('Agent SYSTEM Auto Assigned %s to %s'),$link, $name ?: 'Agent'); } $message = __($msg ?: Event::getNameById($event['event_id'])); break; default: $message = __($description); break; } return $export ? strip_tags($message) : $message; } function getDataById($id, $type) { $row = self::objects() ->filter(array('object_type'=>$type, 'object_id'=>$id)) ->values_flat('object_type', 'object_id', 'data') ->first(); return $row ? $row : 0; } function getObjectLink($event) { $types = self::getTypes(); $urlPrefix = self::getTypeExtra($event['object_type'], 'URL'); $data = json_decode($event['data'], true); $urlIdPrefix = $event['object_type'] == 'I' ? 'tpl_id' : 'id'; if ($event['event_id'] != 14) $link = sprintf('%s', $urlPrefix, $urlIdPrefix, $event['object_id'], $data['name']); else $link = sprintf('%s', $data['name']); return $link; } static function auditEvent($event_id, $object, $info) { global $thisstaff, $thisclient; $event = static::create(); if (isset($info['data'])) $event->data = $info['data']; //set the object_type based on the object's class if (is_object($object)) { foreach (self::getTypes() as $key => $info2) { if (get_class($object) == $info2[0]) $event->object_type = $key; } if ($event->object_type) $event->object_id = $object->ht['id'] ?: $object->getId(); else return false; } else { $event->object_type = $object[0]; $event->object_id = $object[1]; $event->data = $object[2]; } $event->event_id = $event_id; $event->ip = osTicket::get_client_ip(); if ($thisstaff) $event->staff_id = $thisstaff->getId(); elseif (is_object($object) && get_class($object) == 'Staff') $event->staff_id = $object->getId(); elseif (is_object($object) && get_class($object) == 'User') $event->user_id = $object->getId(); elseif ($info['uid']) $event->user_id = $info['uid']; elseif ($thisclient) $event->user_id = $thisclient->getId(); else $event->user_id = $object->getUserId(); return $event->save(); } static function auditSpecialEvent($object, $info=array()) { $data = array('person' => $object ? $object->getName()->name : '', 'msg' => $info['msg'] ?: ''); $info['data'] = json_encode($data); $event_id = Event::getIdByName($info['type']); return static::auditEvent($event_id, $object, $info); } static function auditObjectEvent($object, $info=array()) { global $thisstaff, $thisclient; $event_id = Event::getIdByName($info['type']); $types = self::getTypes(); foreach ($types as $abbrev => $data) { if (is_object($object) && (get_class($object) == $data[0])) { switch ($abbrev) { case 'X': $data = array('person' => $thisstaff->getName()->name, 'key' => $info['key']); $info['data'] = json_encode($data); break; default: $keys = array('updated', 'flags', 'mail_lastfetch', 'permissions', 'status'); $classes = array('Email', 'Filter', 'Page', 'Role', 'Staff', 'Topic'); if ($info['orm_audit'] && (!in_array(get_class($object), $classes) || in_array($info['key'], $keys))) return false; if (is_null($thisstaff) && is_null($thisclient) && get_class($object) == 'Ticket' && $info['type'] != 'assigned') { $person = $object->getUser()->getName()->name; } elseif (is_null($thisstaff) && is_null($thisclient)) $person = __('SYSTEM'); $name = $object ? call_user_func(array($object, $data[1])) : __('NA'); $data = array('name' => is_object($name) ? $name->name : $name, 'person' => $person ? $person : ($thisstaff ? $thisstaff->getName()->name : $thisclient->getName()->name)); foreach ($info as $key => $value) { if ($key != 'type') $data[$key] = $value; } $info['data'] = json_encode($data); break; } } } if (!is_object($object)) { if (!is_array($object)) { if ($data = AuditEntry::getDataById($object, $info['abbrev'])) $name = json_decode($data[2], true); else { $name = __('NA'); $data = array($info['abbrev'], $object); } $info['data'] = json_encode($data); return static::auditEvent($event_id, $data, $info); } else $info['data'] = json_encode($object); } return static::auditEvent($event_id, $object, $info); } static function create($vars=array()) { $event = new static($vars); $event->timestamp = SqlFunction::NOW(); return $event; } static function autoCreateTable() { $sql = 'SHOW TABLES LIKE \''.TABLE_PREFIX.'audit\''; if (db_num_rows(db_query($sql))) return true; else { $sql = sprintf('INSERT INTO `%s` VALUES ("", "login",""), ("", "logout",""), ("", "message",""), ("", "note","")', TABLE_PREFIX.'event'); db_query($sql); $sql = sprintf('CREATE TABLE `%s` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `object_type` char(1) NOT NULL DEFAULT \'\', `object_id` int(10) unsigned NOT NULL, `event_id` int(11) unsigned DEFAULT NULL, `staff_id` int(10) unsigned NOT NULL DEFAULT \'0\', `user_id` int(10) unsigned NOT NULL DEFAULT \'0\', `data` text, `ip` varchar(64) DEFAULT NULL, `timestamp` datetime NOT NULL, PRIMARY KEY (`id`), KEY `staff_id` (`staff_id`), KEY `object_type` (`object_type`,`object_id`) ) CHARSET=utf8', TABLE_PREFIX.'audit'); return db_query($sql); } } } Bud1 latesbw templatesbwspblobbplist00  ]ShowStatusBar_SidebarWidthTenElevenOrLater[ShowToolbar[ShowTabView_ContainerShowSidebar\WindowBounds[ShowSidebar[ShowPathbar#@`  _{{626, 293}, {770, 436}} 'FR^u templatesdsclbool templatesvSrnlong  @ @ @ @ E DSDB ` @ @ @getConfig(); if ($config->get('show_view_audits')) AuditEntry::$show_view_audits = $config->get('show_view_audits'); // Ticket audit Signal::connect('ticket.view.more', function($ticket, &$extras) { global $thisstaff; if (!$thisstaff || !$thisstaff->isAdmin()) return; echo sprintf('
  • getId() . '/view'); echo 'onclick="javascript: $.dialog($(this).attr(\'href\').substr(1), 201); return false;"'; echo sprintf('>', 'icon-book' ?: 'icon-cogs'); echo __('View Audit Log'); echo '
  • '; }); // User audit tab Signal::connect('usertab.audit', function($user, &$extras) { global $thisstaff; if (!$thisstaff || !$thisstaff->isAdmin()) return; $tabTitle = str_replace('-', ' ', __('audits')); echo sprintf('
  • %s
  • ', __('audits'), __(ucwords($tabTitle))); }); // User audit body Signal::connect('user.audit', function($user, &$extras) { global $thisstaff; if (!$thisstaff || !$thisstaff->isAdmin()) return; echo ''; }); // Agent audit tab Signal::connect('agenttab.audit', function($staff, &$extras) { global $thisstaff; if (!$thisstaff || !$thisstaff->isAdmin()) return; echo '
  • Audits
  • '; }); // Agent audit tab body Signal::connect('agent.audit', function($staff, &$extras) { global $thisstaff; if (!$thisstaff || !$thisstaff->isAdmin()) return; echo ''; }); // Ajax View Ticket Audit Signal::connect('ajax.scp', function($dispatcher) { $dispatcher->append( url_get('^/audit/ticket/(?P\d+)/view$', function($ticketId) { global $thisstaff; $row = Ticket::objects()->filter(array('ticket_id'=>$ticketId))->values_flat('number')->first(); if (!$row) Http::response(404, 'No such ticket'); if (!$thisstaff || !$thisstaff->isAdmin()) Http::response(403, 'Contact your administrator'); include 'templates/ticket-audit.tmpl.php'; }) ); }); // Ajax Audit Export Signal::connect('ajax.scp', function($dispatcher) { $dispatcher->append( url('^/audit/export/(?P\w+)/(?P\w+)|uid,(?P\d+)|sid,(?P\d+)|tid,(?P\d+)$', function($type=NULL, $state=NULL, $uid=NULL, $sid=NULL, $tid=NULL) { global $thisstaff; if (!$thisstaff) Http::response(403, 'Agent login is required'); $show = AuditEntry::$show_view_audits; $data = array(); if ($type) { $url = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_QUERY); $qarray = explode('&', $url); foreach ($qarray as $key => $value) { list($k, $v) = explode('=', $value); $data[$k] = $v; } foreach (AuditEntry::getTypes() as $abbrev => $info) { if ($type == $abbrev) $name = AuditEntry::getObjectName($info[0]); } $filename = sprintf('%s-audits-%s.csv', $name, strftime('%Y%m%d')); $export = array('audit', $filename, '', '', 'csv', $show, $data); } elseif ($uid) { $userName = User::getNameById($uid); $filename = sprintf('%s-audits-%s.csv', $userName->name, strftime('%Y%m%d')); $export = array('user', $filename, $tableInfo, $uid, 'csv', $show, $data); } elseif ($sid) { $staff = Staff::lookup($sid); $filename = sprintf('%s-audits-%s.csv', $staff->getName(), strftime('%Y%m%d')); $export = array('staff', $filename, $tableInfo, $sid, 'csv', $show, $data); } elseif ($tid) { $ticket = Ticket::lookup($tid); $filename = sprintf('%s-audits-%s.csv', $ticket->getNumber(), strftime('%Y%m%d')); $export = array('ticket', $filename, $tableInfo, $tid, 'csv', $show, $data); } try { $interval = 5; // Create desired exporter $exporter = new CsvExporter(); $extra = array('filename' => $filename, 'interval' => $interval); // Register the export in the session Exporter::register($exporter, $extra); // Flush response / return export id and check interval Http::flush(201, json_encode(['eid' => $exporter->getId(), 'interval' => $interval])); // Phew... now we're free to do the export session_write_close(); // Release session for other requests ignore_user_abort(1); // Leave us alone bro! @set_time_limit(0); // Useless when safe_mode is on // Export to the exporter $export[] = $exporter; call_user_func_array(array('Export', 'audits'), $export); $exporter->close(); // Sleep 3 times the interval to allow time for file download sleep($interval*3); // Email the export if it exists $exporter->email($thisstaff); // Delete the file. @$exporter->delete(); exit; } catch (Exception $ex) { $errors['err'] = __('Unable to prepare the export'); } include 'templates/export.tmpl.php'; }) ); }); } function enable() { AuditEntry::autoCreateTable(); return parent::enable(); } } 'audit:ticket', # notrans 'version' => '0.1', 'name' => 'Help Desk Audit', 'author' => 'Adriane Alexander', 'description' => 'Provides a configurable mechanism to audit viewing and other activity of tickets.', 'url' => 'http://www.osticket.com/download', 'plugin' => 'audit.php:AuditPlugin', ); ?> new BooleanField(array( 'label' => __('Show View Audits'), 'default' => true, 'configuration' => array( 'desc' => __('Show Audit Logs for when a User or Agent views Tickets') ) )), ); } function pre_save(&$config, &$errors) { global $msg; if (!$errors) $msg = __('Configuration updated successfully'); return true; } } Bud1%  @ @ @ @ E%DSDB` @ @ @isAdmin()) die('Access Denied'); $qs = array(); if($_REQUEST['type']) $qs += array('type' => $_REQUEST['type']); $type='D'; if ($_REQUEST['type']) $type=$_REQUEST['type']; if($_REQUEST['state']) $qs += array('state' => $_REQUEST['state']); $state=__('All'); if ($_REQUEST['state']) $state=$_REQUEST['state']; //dates $startTime =($_REQUEST['startDate'] && (strlen($_REQUEST['startDate'])>=8))?strtotime($_REQUEST['startDate']):0; $endTime =($_REQUEST['endDate'] && (strlen($_REQUEST['endDate'])>=8))?strtotime($_REQUEST['endDate']):0; if( ($startTime && $startTime>time()) or ($startTime>$endTime && $endTime>0)){ $errors['err']=__('Entered date span is invalid. Selection ignored.'); $startTime=$endTime=0; } else { if($startTime) $qs += array('startDate' => $_REQUEST['startDate']); if($endTime) $qs += array('endDate' => $_REQUEST['endDate']); } $order = AuditEntry::getOrder($_REQUEST['order']); $qs += array('order' => (($order=='DESC') ? 'ASC' : 'DESC')); $qstr = '&'. Http::build_query($qs); $args = array(); parse_str($_SERVER['QUERY_STRING'], $args); unset($args['p'], $args['_pjax']); // Apply pagination $events = AuditEntry::getTableInfo('AuditEntry'); $total = count($events); $qwhere = AuditEntry::getQwhere('AuditEntry'); $pageNav=AuditEntry::getPageNav($qwhere); $pageNav->setURL('audits.php', $args); ?>

    '.$pageNav->showing().''; else echo __('No audits found'); ?>
    Description href="audits.php?&sort=timestamp"> IP Address
    '; if ($total) { //Show options.. echo ' '.__('Page').':'.$pageNav->getPageLinks().' '; } echo sprintf('%s', $type, $state, 'audit-export', __('Export')); ?>
    getId()) { $events = AuditEntry::getTableInfo($staff); $total = count($events); $qwhere = AuditEntry::getQwhere($staff); $pageNav=AuditEntry::getPageNav($qwhere); $pageNav->setURL('staff.php', $args); } ?>


    " . $staff->getName() . " has performed.
    " ); ?>
    '.$pageNav->showing().''; else echo sprintf(__('%s does not have any audits'), __('Agent')); ?>
    Description Timestamp IP Address

    '; if ($staffId) echo ' '.__('Page').':'.$pageNav->getPageLinks('audits').' '; echo sprintf('%s', $staffId, 'audit-export', __('Export')); echo ''; } ?> setURL('tickets.php', $args); $order = AuditEntry::getOrder($_REQUEST['order']); $qs = array(); $qsReverse = array(); $qs += array('order' => $order); $qsReverse += array('order' => ($order=='DESC' ? 'ASC' : 'DESC')); $qstr = Http::build_query($qs); $qstrReverse = Http::build_query($qsReverse); $url = '#audit/ticket/' . $ticketId . '/view?'; $qstr = sprintf('%s&sort=timestamp', $qstr); ?>


    '.$pageNav->showing().''; else echo sprintf(__('%s does not have any audits'), __('Ticket')); ?>
    Description > IP Address

    getPageLinks('audits'); $links = str_replace(''; echo ' '.__('Page').':'.$links.' '; echo sprintf('%s', $ticketId, 'audit-export', __('Export')); echo '
    '; ?>

    setURL('users.php', $args); ?>


    '.$pageNav->showing().''; else echo sprintf(__('%s does not have any audits'), __('User')); ?>

    '; echo ' '.__('Page').':'.$pageNav->getPageLinks('audits').' '; echo sprintf('%s', $user->getId(), 'audit-export', __('Export')); echo ''; } ?> ԵYt;2`_GBMB