private function _handleCronSensorsPost($event) { $logger = DevblocksPlatform::getConsoleLog(); $translate = DevblocksPlatform::getTranslationService(); $sensors = DAO_Sensor::getAll(); // Check that all external sensors aren't over their M.I.A. time if (is_array($sensors)) { foreach ($sensors as $sensor) { /* @var $sensor Model_Sensor */ // Only external sensors if ('sensor.external' != $sensor->extension_id) { continue; } // Skip if the sensor hasn't run once yet if (0 == $sensor->updated_date) { continue; } $mia_secs = intval($sensor->params->mia_secs); $elapsed = time() - $sensor->updated_date; if ($mia_secs && $elapsed > $mia_secs) { $fields = array(DAO_Sensor::STATUS => 2, DAO_Sensor::FAIL_COUNT => intval($sensor->fail_count) + 1, DAO_Sensor::METRIC => $translate->_('sensor.status.mia'), DAO_Sensor::OUTPUT => $translate->_('sensor.status.mia')); DAO_Sensor::update($sensor->id, $fields); $logger->info($sensor->name . " is M.I.A. for {$elapsed} seconds."); } } } }
function run(Model_Alert $alert, $sensors) { @($to = DevblocksPlatform::parseCsvString($alert->actions[self::EXTENSION_ID]['to'])); @($template_subject = $alert->actions[self::EXTENSION_ID]['template_subject']); @($template_body = $alert->actions[self::EXTENSION_ID]['template_body']); $logger = DevblocksPlatform::getConsoleLog(); // Assign template variables $tpl = DevblocksPlatform::getTemplateService(); $tpl->clear_all_assign(); $tpl->assign('alert', $alert); $tpl->assign('sensors', $sensors); $tpl->assign('num_sensors', count($sensors)); // Build template $tpl_builder = DevblocksPlatform::getTemplateBuilder(); $errors = array(); // Subject if (false == ($subject = $tpl_builder->build($template_subject))) { $errors += $tpl_builder->getErrors(); } // Body if (false == ($body = $tpl_builder->build($template_body))) { $errors += $tpl_builder->getErrors(); } if (!empty($errors)) { $logger->err(sprintf("Errors in mail template (skipping): %s", implode("<br>\r\n", $errors))); return false; } if (is_array($to)) { foreach ($to as $address) { $logger->info(sprintf("Sending mail to %s about %d sensors", $address, count($sensors))); PortSensorMail::quickSend($address, $subject, $body); } } }
function run() { $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[Heartbeat] Starting Heartbeat Task"); // Heartbeat Event $eventMgr = DevblocksPlatform::getEventService(); $eventMgr->trigger(new Model_DevblocksEvent('cron.heartbeat', array())); }
function run(Model_Alert $alert, $sensors) { @($to = DevblocksPlatform::parseCsvString($alert->actions[self::EXTENSION_ID]['to'])); @($template_msg = $alert->actions[self::EXTENSION_ID]['template_msg']); $result = true; $logger = DevblocksPlatform::getConsoleLog(); $settings = DevblocksPlatform::getPluginSettingsService(); // Assign template variables $tpl = DevblocksPlatform::getTemplateService(); $tpl->clear_all_assign(); $tpl->assign('alert', $alert); $tpl->assign('sensors', $sensors); $tpl->assign('num_sensors', count($sensors)); // Build template $tpl_builder = DevblocksPlatform::getTemplateBuilder(); $errors = array(); // Body if (false == ($text = $tpl_builder->build($template_msg))) { $errors += $tpl_builder->getErrors(); } if (!empty($errors)) { $logger->err(sprintf("Errors in SMS template (skipping): %s", implode("<br>\r\n", $errors))); return false; } // Truncate message to 155 chars if (155 <= strlen($text)) { $text = substr($text, 0, 152) . '...'; } // Clickatell SMS gateways $user = $settings->get('portsensor.sms', 'clickatell_username', ''); $password = $settings->get('portsensor.sms', 'clickatell_password', ''); $api_id = $settings->get('portsensor.sms', 'clickatell_api_id', ''); if (empty($user) || empty($password) || empty($api_id)) { return; } if (is_array($to)) { foreach ($to as $phone) { $logger->info(sprintf("Sending SMS to %s about %d sensors", $phone, count($sensors))); $url = sprintf("http://api.clickatell.com/http/sendmsg?user=%s&password=%s&api_id=%s&to=%s&text=%s", urlencode($user), urlencode($password), urlencode($api_id), urlencode($phone), urlencode($text)); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); $out = curl_exec($ch); curl_close($ch); $result = 0 == strcasecmp("ID:", substr($out, 0, 3)); } } return $result; }
/** * @param Model_DevblocksEvent $event */ function handleEvent(Model_DevblocksEvent $event) { switch ($event->id) { case 'cron.maint': $records_removed = 0; $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[Answernet.com Maint] Starting Purging Contact Addresses task"); @set_time_limit(0); // Unlimited (if possible) @ini_set('memory_limit', '128M'); $logger->info("[Answernet.com Maint] Overloaded memory_limit to: " . ini_get('memory_limit')); $logger->info("[Answernet.com Maint] Overloaded max_execution_time to: " . ini_get('max_execution_time')); $runtime = microtime(true); //Do something $db = DevblocksPlatform::getDatabaseService(); $sql = "SELECT a.id "; $sql .= "FROM address a "; $sql .= "LEFT JOIN message m ON a.id = m.address_id "; $sql .= "LEFT JOIN requester r ON a.id = r.address_id "; $sql .= "LEFT JOIN ticket_comment tc ON a.id = tc.address_id "; $sql .= "WHERE a.contact_org_id = 0 "; $sql .= "AND m.address_id IS NULL "; $sql .= "AND r.address_id IS NULL "; $sql .= "AND tc.address_id IS NULL "; $sql .= "ORDER BY a.id ASC "; $rs = $db->Execute($sql); while (!$rs->EOF) { // Loop though the records. DAO_Address::delete($rs->fields['id']); // Increament the records removed connecter $records_removed++; $rs->MoveNext(); } $logger->info("[Answernet.com Maint] Total Records Removed: " . $records_removed); $logger->info("[Answernet.com Maint] Total Runtime: " . (microtime(true) - $runtime) * 1000 . " ms"); break; } }
function handleRequest(DevblocksHttpRequest $request) { @($reload = DevblocksPlatform::importGPC($_REQUEST['reload'], 'integer', 0)); @($loglevel = DevblocksPlatform::importGPC($_REQUEST['loglevel'], 'integer', 0)); $logger = DevblocksPlatform::getConsoleLog(); $translate = DevblocksPlatform::getTranslationService(); $settings = CerberusSettings::getInstance(); $authorized_ips_str = $settings->get(CerberusSettings::AUTHORIZED_IPS); $authorized_ips = DevblocksPlatform::parseCrlfString($authorized_ips_str); $authorized_ip_defaults = DevblocksPlatform::parseCsvString(AUTHORIZED_IPS_DEFAULTS); $authorized_ips = array_merge($authorized_ips, $authorized_ip_defaults); @($is_ignoring_wait = DevblocksPlatform::importGPC($_REQUEST['ignore_wait'], 'integer', 0)); $pass = false; foreach ($authorized_ips as $ip) { if (substr($ip, 0, strlen($ip)) == substr($_SERVER['REMOTE_ADDR'], 0, strlen($ip))) { $pass = true; break; } } if (!$pass) { echo vsprintf($translate->_('cron.ip_unauthorized'), $_SERVER['REMOTE_ADDR']); return; } $stack = $request->path; array_shift($stack); // cron $job_id = array_shift($stack); @set_time_limit(0); // Unlimited (if possible) $url = DevblocksPlatform::getUrlService(); $timelimit = intval(ini_get('max_execution_time')); if ($reload) { $reload_url = sprintf("%s?reload=%d&loglevel=%d&ignore_wait=%d", $url->write('c=cron' . ($job_id ? "&a=" . $job_id : "")), intval($reload), intval($loglevel), intval($is_ignoring_wait)); echo "<HTML>" . "<HEAD>" . "<TITLE></TITLE>" . "<meta http-equiv='Refresh' content='" . intval($reload) . ";" . $reload_url . "'>" . "<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>" . "</HEAD>" . "<BODY>"; // onload=\"setTimeout(\\\"window.location.replace('".$url->write('c=cron')."')\\\",30);\" } // [TODO] Determine if we're on a time limit under 60 seconds $cron_manifests = DevblocksPlatform::getExtensions('cerberusweb.cron', true, true); $jobs = array(); if (empty($job_id)) { // do everything // Determine who wants to go first by next time and longest waiting $nexttime = time() + 86400; if (is_array($cron_manifests)) { foreach ($cron_manifests as $idx => $instance) { /* @var $instance CerberusCronPageExtension */ $lastrun = $instance->getParam(CerberusCronPageExtension::PARAM_LASTRUN, 0); if ($instance->isReadyToRun($is_ignoring_wait)) { if ($timelimit) { if ($lastrun < $nexttime) { $jobs[0] = $cron_manifests[$idx]; $nexttime = $lastrun; } } else { $jobs[] =& $cron_manifests[$idx]; } } } } } else { // single job $manifest = DevblocksPlatform::getExtension($job_id, false, true); if (empty($manifest)) { exit; } $instance = $manifest->createInstance(); if ($instance) { if ($instance->isReadyToRun($is_ignoring_wait)) { $jobs[0] =& $instance; } } } if (!empty($jobs)) { foreach ($jobs as $nextjob) { $nextjob->setParam(CerberusCronPageExtension::PARAM_LOCKED, time()); $nextjob->_run(); } } elseif ($reload) { $logger->info(vsprintf($translate->_('cron.nothing_to_do'), intval($reload))); } if ($reload) { echo "</BODY>" . "</HTML>"; } exit; }
function run() { $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[POP3] Starting POP3 Task"); if (!extension_loaded("imap")) { die("IMAP Extension not loaded!"); } @set_time_limit(0); // Unlimited (if possible) @ini_set('memory_limit', '64M'); $accounts = DAO_Mail::getPop3Accounts(); /* @var $accounts CerberusPop3Account[] */ $timeout = ini_get('max_execution_time'); // Allow runtime overloads (by host, etc.) @($gpc_pop3_max = DevblocksPlatform::importGPC($_REQUEST['pop3_max'], 'integer')); $max_downloads = !empty($gpc_pop3_max) ? $gpc_pop3_max : $this->getParam('max_messages', $timeout ? 20 : 50); // [JAS]: Make sure our output directory is writeable if (!is_writable(APP_MAIL_PATH . 'new' . DIRECTORY_SEPARATOR)) { $logger->err("[POP3] The mail storage directory is not writeable. Skipping POP3 download."); return; } foreach ($accounts as $account) { /* @var $account CerberusPop3Account */ if (!$account->enabled) { continue; } $logger->info('[POP3] Account being parsed is ' . $account->nickname); switch ($account->protocol) { default: case 'pop3': // 110 $connect = sprintf("{%s:%d/pop3/notls}INBOX", $account->host, $account->port); break; case 'pop3-ssl': // 995 $connect = sprintf("{%s:%d/pop3/ssl/novalidate-cert}INBOX", $account->host, $account->port); break; case 'imap': // 143 $connect = sprintf("{%s:%d/notls}INBOX", $account->host, $account->port); break; case 'imap-ssl': // 993 $connect = sprintf("{%s:%d/imap/ssl/novalidate-cert}INBOX", $account->host, $account->port); break; } $runtime = microtime(true); if (false === ($mailbox = @imap_open($connect, !empty($account->username) ? $account->username : "", !empty($account->password) ? $account->password : ""))) { $logger->err("[POP3] Failed with error: " . imap_last_error()); continue; } $messages = array(); $check = imap_check($mailbox); // [TODO] Make this an account setting? $total = min($max_downloads, $check->Nmsgs); $logger->info('[POP3] Init time: ' . (microtime(true) - $runtime) * 1000, " ms"); $runtime = microtime(true); for ($i = 1; $i <= $total; $i++) { /* * [TODO] Logic for max message size (>1MB, etc.) handling. If over a * threshold then use the attachment parser (imap_fetchstructure) to toss * non-plaintext until the message fits. */ $msgno = $i; $time = microtime(true); $headers = imap_fetchheader($mailbox, $msgno); $body = imap_body($mailbox, $msgno); do { $unique = sprintf("%s.%04d", time(), mt_rand(0, 9999)); $filename = APP_MAIL_PATH . 'new' . DIRECTORY_SEPARATOR . $unique; } while (file_exists($filename)); $fp = fopen($filename, 'w'); if ($fp) { fwrite($fp, $headers, strlen($headers)); fwrite($fp, "\r\n\r\n"); fwrite($fp, $body, strlen($body)); @fclose($fp); } /* * [JAS]: We don't add the .msg extension until we're done with the file, * since this will safely be ignored by the parser until we're ready * for it. */ rename($filename, dirname($filename) . DIRECTORY_SEPARATOR . basename($filename) . '.msg'); unset($headers); unset($body); $time = microtime(true) - $time; $logger->info("[POP3] Downloaded message " . $msgno . " (" . sprintf("%d", $time * 1000) . " ms)"); imap_delete($mailbox, $msgno); continue; } imap_expunge($mailbox); imap_close($mailbox); imap_errors(); $logger->info("[POP3] Total Runtime: " . (microtime(true) - $runtime) * 1000 . " ms"); } }
function run() { $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[Alerts] Starting..."); $alerts = DAO_Alert::getAll(); $check_sensors = DAO_Sensor::getAll(); $workers = DAO_Worker::getAll(); if (is_array($alerts)) { foreach ($alerts as $alert) { /* @var $alert Model_Alert */ if (!isset($workers[$alert->worker_id])) { continue; } $logger->info(sprintf("[Alerts] Checking '%s' for %s...", $alert->name, $workers[$alert->worker_id]->getName())); $hit_sensors = $alert->getMatches($check_sensors); if (is_array($hit_sensors)) { $alert->run($hit_sensors); } } } $logger->info("[Alerts] Finished!"); }
function run(Model_PreParseRule $filter, CerberusParserMessage $message) { $message_headers = $message->headers; $subject = $message->headers['subject']; $ticket_fields = DAO_CustomField::getAll(); $params = $filter->actions[self::EXTENSION_ID]; $day_of_week = date('N'); $logger = DevblocksPlatform::getConsoleLog(); $logger->info("Answernet: Running Filter on New Mail"); // Houser,Colin <1034179><Missing Serviced Customer information> // Current custom_fields numbers // 1 = Due Date // 2 = RM Employee ID // 3 = RM Name // 4 = Topic_metlife /0/2/4/6/8/10/12/14 // 5 = SLA // 6 = New Hire Yes = 0 / No = 2 // $sub = explode(',', $subject, 2); $lname = $sub[0]; $sub2 = explode("<", $sub[1]); $fname = $sub2[0]; $emp_id = $sub2[1]; $topic_metlife = $sub2[2]; $message->custom_fields['2'] = substr($emp_id, 0, -1); $message->custom_fields['3'] = trim($fname) . " " . trim($lname); // If topic == Import contacts if (preg_match('/import/i', $topic_metlife)) { $message->custom_fields['4'] = "Import contacts"; $message->custom_fields['5'] = 1; $message->custom_fields['6'] = "Yes"; } // If topic == Create mailing list from existing data if (preg_match('/mailing/i', $topic_metlife)) { $message->custom_fields['4'] = "Create mailing list from existing data"; $message->custom_fields['5'] = 3; $message->custom_fields['6'] = "Yes"; } // If topic == Update existing contacts if (preg_match('/Update/i', $topic_metlife)) { $message->custom_fields['4'] = "Update existing contacts"; $message->custom_fields['5'] = 3; $message->custom_fields['6'] = "No"; } // If topic == Research missing customer info if (preg_match('/Research/i', $topic_metlife)) { $message->custom_fields['4'] = "Research missing customer info"; $message->custom_fields['5'] = 5; $message->custom_fields['6'] = "No"; } // If topic == Create labels if (preg_match('/labels/i', $topic_metlife)) { $message->custom_fields['4'] = "Create labels"; $message->custom_fields['5'] = 1; $message->custom_fields['6'] = "No"; } // If topic == Export third-party file if (preg_match('/third/i', $topic_metlife)) { $message->custom_fields['4'] = "Export third-party file"; $message->custom_fields['5'] = 3; $message->custom_fields['6'] = "No"; } // If topic == Other if (preg_match('/Other/i', $topic_metlife)) { $message->custom_fields['4'] = "Other"; $message->custom_fields['5'] = 5; $message->custom_fields['6'] = "No"; } // SLA of 1. Process day of week Busness Days suck. if ($message->custom_fields['5'] == 1) { if ($day_of_week < 5 || $day_of_week == 7) { $message->custom_fields['1'] = strtotime("+1 Days"); } if ($day_of_week == 6) { $message->custom_fields['1'] = strtotime("+2 Days"); } if ($day_of_week == 5) { $message->custom_fields['1'] = strtotime("+3 Days"); } } // SLA of 3. Process day of week Busness Days suck. if ($message->custom_fields['5'] == 3) { if ($day_of_week < 4 || $day_of_week == 7) { $message->custom_fields['1'] = strtotime("+3 Days"); } if ($day_of_week == 6) { $message->custom_fields['1'] = strtotime("+4 Days"); } if ($day_of_week > 3 && $day_of_week < 6) { $message->custom_fields['1'] = strtotime("+5 Days"); } } // SLA of 5. Process day of week Busness Days suck. if ($message->custom_fields['5'] == 5) { if ($day_of_week == 1 || $day_of_week == 7) { $message->custom_fields['1'] = strtotime("+5 Days"); } if ($day_of_week == 6) { $message->custom_fields['1'] = strtotime("+6 Days"); } if ($day_of_week > 1 && $day_of_week < 6) { $message->custom_fields['1'] = strtotime("+7 Days"); } } }
/** * Enter description here... * * @param CerberusParserMessage $message * @return integer */ public static function parseMessage(CerberusParserMessage $message, $options = array()) { /* * options: * 'no_autoreply' */ $logger = DevblocksPlatform::getConsoleLog(); $settings = DevblocksPlatform::getPluginSettingsService(); $helpdesk_senders = CerberusApplication::getHelpdeskSenders(); // Pre-parse mail filters $pre_filters = Model_PreParseRule::getMatches($message); if (is_array($pre_filters) && !empty($pre_filters)) { // Load filter action manifests for reuse $ext_action_mfts = DevblocksPlatform::getExtensions('cerberusweb.mail_filter.action', false); // Loop through all matching filters foreach ($pre_filters as $pre_filter) { // Do something with matching filter's actions foreach ($pre_filter->actions as $action_key => $action) { switch ($action_key) { case 'blackhole': return NULL; break; case 'redirect': @($to = $action['to']); CerberusMail::reflect($message, $to); return NULL; break; case 'bounce': @($msg = $action['message']); @($subject = 'Delivery failed: ' . self::fixQuotePrintableString($message->headers['subject'])); // [TODO] Follow the RFC spec on a true bounce if (null != ($fromAddressInst = CerberusParser::getAddressFromHeaders($message->headers))) { CerberusMail::quickSend($fromAddressInst->email, $subject, $msg); } return NULL; break; default: // Plugin pre-parser filter actions if (isset($ext_action_mfts[$action_key])) { if (null != @($ext_action = $ext_action_mfts[$action_key]->createInstance())) { try { /* @var $ext_action Extension_MailFilterAction */ $ext_action->run($pre_filter, $message); } catch (Exception $e) { } } } break; } } } } $headers =& $message->headers; // From if (null == ($fromAddressInst = CerberusParser::getAddressFromHeaders($headers))) { $logger->err("[Parser] 'From' address could not be created."); return NULL; } // To/Cc/Bcc $to = array(); $sTo = @$headers['to']; $bIsNew = true; if (!empty($sTo)) { // [TODO] Do we still need this RFC address parser? $to = CerberusParser::parseRfcAddress($sTo); } // Subject // Fix quote printable subject (quoted blocks can appear anywhere in subject) $sSubject = ""; if (isset($headers['subject']) && !empty($headers['subject'])) { $sSubject = $headers['subject']; if (is_array($sSubject)) { $sSubject = array_shift($sSubject); } } // The subject can still end up empty after QP decode if (empty($sSubject)) { $sSubject = "(no subject)"; } // Date $iDate = @strtotime($headers['date']); // If blank, or in the future, set to the current date if (empty($iDate) || $iDate > time()) { $iDate = time(); } // Is banned? if (1 == $fromAddressInst->is_banned) { $logger->info("[Parser] Ignoring ticket from banned address: " . $fromAddressInst->email); return NULL; } // Overloadable $enumSpamTraining = ''; // Message Id / References / In-Reply-To @($sMessageId = $headers['message-id']); $body_append_text = array(); $body_append_html = array(); // [mdf]Check attached files before creating the ticket because we may need to overwrite the message-id // also store any contents of rfc822 files so we can include them after the body foreach ($message->files as $filename => $file) { /* @var $file ParserFile */ switch ($file->mime_type) { case 'message/rfc822': $full_filename = $file->tmpname; $mail = mailparse_msg_parse_file($full_filename); $struct = mailparse_msg_get_structure($mail); $msginfo = mailparse_msg_get_part_data($mail); $inline_headers = $msginfo['headers']; if (isset($headers['from']) && (strtolower(substr($headers['from'], 0, 11)) == 'postmaster@' || strtolower(substr($headers['from'], 0, 14)) == 'mailer-daemon@')) { $headers['in-reply-to'] = $inline_headers['message-id']; } break; } } // [JAS] [TODO] References header may contain multiple message-ids to find if (null != ($ids = self::findParentMessage($headers))) { $bIsNew = false; $id = $ids['ticket_id']; $msgid = $ids['message_id']; // Is it a worker reply from an external client? If so, proxy if (null != ($worker_address = DAO_AddressToWorker::getByAddress($fromAddressInst->email))) { $logger->info("[Parser] Handling an external worker response from " . $fromAddressInst->email); if (!DAO_Ticket::isTicketRequester($worker_address->address, $id)) { // Watcher Commands [TODO] Document on wiki/etc if (0 != ($matches = preg_match_all("/\\[(.*?)\\]/i", $message->headers['subject'], $commands))) { @($command = strtolower(array_pop($commands[1]))); $logger->info("[Parser] Worker command: " . $command); switch ($command) { case 'close': DAO_Ticket::updateTicket($id, array(DAO_Ticket::IS_CLOSED => CerberusTicketStatus::CLOSED)); break; case 'take': DAO_Ticket::updateTicket($id, array(DAO_Ticket::NEXT_WORKER_ID => $worker_address->worker_id)); break; case 'comment': $comment_id = DAO_TicketComment::create(array(DAO_TicketComment::ADDRESS_ID => $fromAddressInst->id, DAO_TicketComment::CREATED => time(), DAO_TicketComment::TICKET_ID => $id, DAO_TicketComment::COMMENT => $message->body)); return $id; break; default: // Typo? break; } } $attachment_files = array(); $attachment_files['name'] = array(); $attachment_files['type'] = array(); $attachment_files['tmp_name'] = array(); $attachment_files['size'] = array(); $i = 0; foreach ($message->files as $filename => $file) { $attachment_files['name'][$i] = $filename; $attachment_files['type'][$i] = $file->mime_type; $attachment_files['tmp_name'][$i] = $file->tmpname; $attachment_files['size'][$i] = $file->file_size; $i++; } CerberusMail::sendTicketMessage(array('message_id' => $msgid, 'content' => $message->body, 'files' => $attachment_files, 'agent_id' => $worker_address->worker_id)); return $id; } else { // ... worker is a requester, treat as normal $logger->info("[Parser] The external worker was a ticket requester, so we're not treating them as a watcher."); } } else { // Reply: Not sent by a worker /* * [TODO] check that this sender is a requester on the matched ticket * Otherwise blank out the $id */ } } $group_id = 0; if (empty($id)) { // New Ticket $sMask = CerberusApplication::generateTicketMask(); $groups = DAO_Group::getAll(); // Routing new tickets if (null != ($routing_rules = Model_MailToGroupRule::getMatches($fromAddressInst, $message))) { if (is_array($routing_rules)) { foreach ($routing_rules as $rule) { // Only end up with the last 'move' action (ignore the previous) if (isset($rule->actions['move'])) { $group_id = intval($rule->actions['move']['group_id']); // We don't need to move again when running rule actions unset($rule->actions['move']); } } } } // Make sure the group exists if (!isset($groups[$group_id])) { $group_id = null; } // Last ditch effort to check for a default group to deliver to if (empty($group_id)) { if (null != ($default_team = DAO_Group::getDefaultGroup())) { $group_id = $default_team->id; } else { // Bounce return null; } } // [JAS] It's important to not set the group_id on the ticket until the messages exist // or inbox filters will just abort. $fields = array(DAO_Ticket::MASK => $sMask, DAO_Ticket::SUBJECT => $sSubject, DAO_Ticket::IS_CLOSED => 0, DAO_Ticket::FIRST_WROTE_ID => intval($fromAddressInst->id), DAO_Ticket::LAST_WROTE_ID => intval($fromAddressInst->id), DAO_Ticket::CREATED_DATE => $iDate, DAO_Ticket::UPDATED_DATE => $iDate, DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_OPENED); $id = DAO_Ticket::createTicket($fields); // Apply routing actions to our new ticket ID if (isset($routing_rules) && is_array($routing_rules)) { foreach ($routing_rules as $rule) { $rule->run($id); } } } // [JAS]: Add requesters to the ticket if (!empty($fromAddressInst->id) && !empty($id)) { // Don't add a requester if the sender is a helpdesk address if (isset($helpdesk_senders[$fromAddressInst->email])) { $logger->info("[Parser] Not adding ourselves as a requester: " . $fromAddressInst->email); } else { DAO_Ticket::createRequester($fromAddressInst->id, $id); } } // Add the other TO/CC addresses to the ticket // [TODO] This should be cleaned up and optimized if ($settings->get('cerberusweb.core', CerberusSettings::PARSER_AUTO_REQ, 0)) { @($autoreq_exclude_list = $settings->get('cerberusweb.core', CerberusSettings::PARSER_AUTO_REQ_EXCLUDE, '')); $destinations = self::getDestinations($headers); if (is_array($destinations) && !empty($destinations)) { // Filter out any excluded requesters if (!empty($autoreq_exclude_list)) { @($autoreq_exclude = DevblocksPlatform::parseCrlfString($autoreq_exclude_list)); if (is_array($autoreq_exclude) && !empty($autoreq_exclude)) { foreach ($autoreq_exclude as $excl_pattern) { $excl_regexp = DevblocksPlatform::parseStringAsRegExp($excl_pattern); // Check all destinations for this pattern foreach ($destinations as $idx => $dest) { if (@preg_match($excl_regexp, $dest)) { unset($destinations[$idx]); } } } } } foreach ($destinations as $dest) { if (null != ($destInst = CerberusApplication::hashLookupAddress($dest, true))) { // Skip if the destination is one of our senders or the matching TO if (isset($helpdesk_senders[$destInst->email])) { continue; } DAO_Ticket::createRequester($destInst->id, $id); } } } } $attachment_path = APP_STORAGE_PATH . '/attachments/'; // [TODO] This should allow external attachments (S3) $fields = array(DAO_Message::TICKET_ID => $id, DAO_Message::CREATED_DATE => $iDate, DAO_Message::ADDRESS_ID => $fromAddressInst->id); $email_id = DAO_Message::create($fields); // Content DAO_MessageContent::create($email_id, $message->body); // Headers foreach ($headers as $hk => $hv) { DAO_MessageHeader::create($email_id, $hk, $hv); } // [mdf] Loop through files to insert attachment records in the db, and move temporary files if (!empty($email_id)) { foreach ($message->files as $filename => $file) { /* @var $file ParserFile */ //[mdf] skip rfc822 messages since we extracted their content above if ($file->mime_type == 'message/rfc822') { continue; } $fields = array(DAO_Attachment::MESSAGE_ID => $email_id, DAO_Attachment::DISPLAY_NAME => $filename, DAO_Attachment::MIME_TYPE => $file->mime_type, DAO_Attachment::FILE_SIZE => intval($file->file_size)); $file_id = DAO_Attachment::create($fields); if (empty($file_id)) { @unlink($file->tmpname); // remove our temp file continue; } // Make file attachments use buckets so we have a max per directory $attachment_bucket = sprintf("%03d/", mt_rand(1, 100)); $attachment_file = $file_id; if (!file_exists($attachment_path . $attachment_bucket)) { @mkdir($attachment_path . $attachment_bucket, 0770, true); // [TODO] Needs error checking } rename($file->getTempFile(), $attachment_path . $attachment_bucket . $attachment_file); // [TODO] Split off attachments into its own DAO DAO_Attachment::update($file_id, array(DAO_Attachment::FILEPATH => $attachment_bucket . $attachment_file)); } } // Pre-load custom fields if (isset($message->custom_fields) && !empty($message->custom_fields)) { foreach ($message->custom_fields as $cf_id => $cf_val) { if (is_array($cf_val) && !empty($cf_val) || !is_array($cf_val) && 0 != strlen($cf_val)) { DAO_CustomFieldValue::setFieldValue('cerberusweb.fields.source.ticket', $id, $cf_id, $cf_val); } } } // Finalize our new ticket details (post-message creation) if ($bIsNew && !empty($id) && !empty($email_id)) { // First thread (needed for anti-spam) DAO_Ticket::updateTicket($id, array(DAO_Ticket::FIRST_MESSAGE_ID => $email_id)); // Prime the change fields (which a few things like anti-spam might change before we commit) $change_fields = array(DAO_Ticket::TEAM_ID => $group_id); $out = CerberusBayes::calculateTicketSpamProbability($id); if (!empty($group_id)) { @($spam_threshold = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_THRESHOLD, 80)); @($spam_action = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_ACTION, '')); @($spam_action_param = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_SPAM_ACTION_PARAM, '')); if ($out['probability'] * 100 >= $spam_threshold) { $enumSpamTraining = CerberusTicketSpamTraining::SPAM; switch ($spam_action) { default: case 0: // do nothing break; case 1: // delete $change_fields[DAO_Ticket::IS_CLOSED] = 1; $change_fields[DAO_Ticket::IS_DELETED] = 1; break; case 2: // move $buckets = DAO_Bucket::getAll(); // Verify bucket exists if (!empty($spam_action_param) && isset($buckets[$spam_action_param])) { $change_fields[DAO_Ticket::TEAM_ID] = $group_id; $change_fields[DAO_Ticket::CATEGORY_ID] = $spam_action_param; } break; } } } // end spam training // Save properties if (!empty($change_fields)) { DAO_Ticket::updateTicket($id, $change_fields); } } // Reply notifications (new messages are handled by 'move' listener) if (!$bIsNew) { // Inbound Reply Event $eventMgr = DevblocksPlatform::getEventService(); $eventMgr->trigger(new Model_DevblocksEvent('ticket.reply.inbound', array('ticket_id' => $id))); } // New ticket processing if ($bIsNew) { // Auto reply @($autoreply_enabled = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_AUTO_REPLY_ENABLED, 0)); @($autoreply = DAO_GroupSettings::get($group_id, DAO_GroupSettings::SETTING_AUTO_REPLY, '')); /* * Send the group's autoreply if one exists, as long as this ticket isn't spam */ if (!isset($options['no_autoreply']) && $autoreply_enabled && !empty($autoreply) && $enumSpamTraining != CerberusTicketSpamTraining::SPAM) { CerberusMail::sendTicketMessage(array('ticket_id' => $id, 'message_id' => $email_id, 'content' => str_replace(array('#ticket_id#', '#mask#', '#subject#', '#timestamp#', '#sender#', '#sender_first#', '#orig_body#'), array($id, $sMask, $sSubject, date('r'), $fromAddressInst->email, $fromAddressInst->first_name, ltrim($message->body)), $autoreply), 'is_autoreply' => true, 'dont_keep_copy' => true)); } } // end bIsNew unset($message); // Re-open and update our date on new replies if (!$bIsNew) { DAO_Ticket::updateTicket($id, array(DAO_Ticket::UPDATED_DATE => time(), DAO_Ticket::IS_WAITING => 0, DAO_Ticket::IS_CLOSED => 0, DAO_Ticket::IS_DELETED => 0, DAO_Ticket::LAST_WROTE_ID => $fromAddressInst->id, DAO_Ticket::LAST_ACTION_CODE => CerberusTicketActionCode::TICKET_CUSTOMER_REPLY)); // [TODO] The TICKET_CUSTOMER_REPLY should be sure of this message address not being a worker } @imap_errors(); // Prevent errors from spilling out into STDOUT return $id; }
header('Location: ' . dirname($_SERVER['PHP_SELF']) . '/install/index.php'); // [TODO] change this to a meta redirect exit; } require APP_PATH . '/api/Application.class.php'; DevblocksPlatform::init(); DevblocksPlatform::setExtensionDelegate('C4_DevblocksExtensionDelegate'); // Request $request = DevblocksPlatform::readRequest(); // Patches (if not on the patch page) if (@0 != strcasecmp(@$request->path[0], "update") && !DevblocksPlatform::versionConsistencyCheck()) { DevblocksPlatform::redirect(new DevblocksHttpResponse(array('update', 'locked'))); } //DevblocksPlatform::readPlugins(); $session = DevblocksPlatform::getSessionService(); // Localization DevblocksPlatform::setLocale(isset($_SESSION['locale']) && !empty($_SESSION['locale']) ? $_SESSION['locale'] : 'en_US'); if (isset($_SESSION['timezone'])) { @date_default_timezone_set($_SESSION['timezone']); } // Initialize Logging if (method_exists('DevblocksPlatform', 'getConsoleLog')) { $timeout = ini_get('max_execution_time'); $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[Devblocks] ** Platform starting (" . date("r") . ") **"); $logger->info('[Devblocks] Time Limit: ' . ($timeout ? $timeout : 'unlimited') . " secs"); $logger->info('[Devblocks] Memory Limit: ' . ini_get('memory_limit')); } // [JAS]: HTTP Request (App->Platform) CerberusApplication::processRequest($request); exit;
static function maint() { $db = DevblocksPlatform::getDatabaseService(); $logger = DevblocksPlatform::getConsoleLog(); }
function SendReport($full_filename, $filename) { $logger = DevblocksPlatform::getConsoleLog(); $from = '*****@*****.**'; $personal = 'First Person'; $subject = 'DR Metlife Report Generated on ' . date("n/j/y"); $mail_headers = array(); $mail_headers['X-CerberusCompose'] = '1'; $toList = NULL; $abort = true; @($answernet_email01 = $this->getParam('answernet_email01', NULL)); @($answernet_email02 = $this->getParam('answernet_email02', NULL)); @($answernet_email03 = $this->getParam('answernet_email03', NULL)); @($answernet_email04 = $this->getParam('answernet_email04', NULL)); @($answernet_email05 = $this->getParam('answernet_email05', NULL)); if ($answernet_email01 != '') { $logger->info("[Answernet.com] answernet_email01 = " . $answernet_email01); $toList = $answernet_email01; $abort = false; } if ($answernet_email02 != '') { $logger->info("[Answernet.com] answernet_email02 = " . $answernet_email02); if (!is_null($toList)) { $toList .= ","; } $toList .= $answernet_email02; $abort = false; } if ($answernet_email03 != '') { $logger->info("[Answernet.com] answernet_email03 = " . $answernet_email03); if (!is_null($toList)) { $toList .= ","; } $toList .= $answernet_email03; $abort = false; } if ($answernet_email04 != '') { $logger->info("[Answernet.com] answernet_email04 = " . $answernet_email04); if (!is_null($toList)) { $toList .= ","; } $toList .= $answernet_email04; $abort = false; } if ($answernet_email05 != '') { $logger->info("[Answernet.com] answernet_email05 = " . $answernet_email05); if (!is_null($toList)) { $toList .= ","; } $toList .= $answernet_email05; $abort = false; } if ($abort) { $logger->info("[Answernet.com] Aborting email send."); return; } $logger->info("[Answernet.com] toList = " . $toList); $files['name']['0'] = $filename; $files['type']['0'] = 'application/vnd.ms-excel'; $files['tmp_name']['0'] = $full_filename; $properties = array('team_id' => 1771, 'content' => "Metlife DR report attached", 'subject' => $subject, 'closed' => 0, 'agent_id' => 0, 'to' => $toList, 'files' => $files); $ticket_id = CerberusMail::compose($properties); $logger->info("[Answernet.com] ticket_id = " . $ticket_id); return; }
static function maint() { $db = DevblocksPlatform::getDatabaseService(); $logger = DevblocksPlatform::getConsoleLog(); $sql = "DELETE QUICK category FROM category LEFT JOIN team ON category.team_id=team.id WHERE team.id IS NULL"; $db->Execute($sql); $logger->info('[Maint] Purged ' . $db->Affected_Rows() . ' category records.'); $sql = "DELETE QUICK group_setting FROM group_setting LEFT JOIN team ON group_setting.group_id=team.id WHERE team.id IS NULL"; $db->Execute($sql); $logger->info('[Maint] Purged ' . $db->Affected_Rows() . ' group_setting records.'); $sql = "DELETE QUICK custom_field FROM custom_field LEFT JOIN team ON custom_field.group_id=team.id WHERE custom_field.group_id > 0 AND team.id IS NULL"; $db->Execute($sql); $logger->info('[Maint] Purged ' . $db->Affected_Rows() . ' custom_field records.'); }
function ExportSnpp(Model_ExportType $export_type) { $logger = DevblocksPlatform::getConsoleLog(); $db = DevblocksPlatform::getDatabaseService(); @($snpp_current_hour = 0); @($snpp_sent_today = 0); $memory_limit = ini_get('memory_limit'); if (substr($memory_limit, 0, -1) < 128) { @ini_set('memory_limit', '128M'); } @set_time_limit(0); // Unlimited (if possible) $logger->info("[SNPP Exporter] Overloaded memory_limit to: " . ini_get('memory_limit')); $logger->info("[SNPP Exporter] Overloaded max_execution_time to: " . ini_get('max_execution_time')); $timeout = ini_get('max_execution_time'); $runtime = microtime(true); $sql = sprintf("SELECT mr.id " . "FROM message_recipient mr " . "inner join customer_recipient cr on mr.recipient_id = cr.id " . "WHERE mr.send_status in (0,3,4) " . "AND cr.is_disabled = 0 " . "AND cr.export_type = %d " . "AND cr.type = 2 ", $export_type->id); $rs = $db->Execute($sql); // Loop though pending outbound emails. while ($row = mysql_fetch_assoc($rs)) { $id = $row['id']; $logger->info("[SNPP Exporter] Procing MR ID: " . $id); $message_recipient = DAO_MessageRecipient::get($id); $message = DAO_Message::get($message_recipient->message_id); $message_lines = explode('\\n', substr($message->message, 1, -1)); $recipient = DAO_CustomerRecipient::get($message_recipient->recipient_id); $message_str = substr(implode("", $message_lines), 0, 160); // FIXME - Need to add in filter for now everything is unfiltered. // sendSnpp($phone_number, $message, $snpp_server="ann100sms01.answernet.com", $port=444) $send_status = FegSnpp::sendSnpp($recipient->address, $message_str); $logger->info("[SNPP Exporter] Send Status: " . ($send_status ? "Successful" : "Failure")); // Give plugins a chance to run export $eventMgr = DevblocksPlatform::getEventService(); $eventMgr->trigger(new Model_DevblocksEvent('cron.send.snpp', array('recipient' => $recipient, 'message' => $message, 'message_lines' => $message_lines, 'message_recipient' => $message_recipient, 'send_status' => $send_status))); if ($send_status) { $snpp_current_hour++; $snpp_sent_today++; } $fields = array(DAO_MessageRecipient::SEND_STATUS => $send_status ? 2 : 1, DAO_MessageRecipient::CLOSED_DATE => $send_status ? time() : 0); DAO_MessageRecipient::update($id, $fields); } mysql_free_result($rs); if ($snpp_current_hour) { $current_fields = DAO_Stats::get(0); $fields = array(DAO_Stats::SNPP_CURRENT_HOUR => $current_fields->snpp_current_hour + $snpp_current_hour, DAO_Stats::SNPP_SENT_TODAY => $current_fields->snpp_sent_today + $snpp_sent_today); DAO_Stats::update(0, $fields); } return NULL; }
function run() { $logger = DevblocksPlatform::getConsoleLog(); $logger->info("[] Syncing Repositories"); if (!extension_loaded("oauth")) { $logger->err("[] The 'oauth' extension is not loaded. Aborting!"); return false; } $timeout = ini_get('max_execution_time'); $runtime = microtime(true); $issue = Wgm_API::getInstance(); // get config $token = DevblocksPlatform::getPluginSetting('wgm.issues', 'access_token', ''); $issue->setCredentials($token); // get last sync repo $last_sync_repo = $this->getParam('repos.last_repo', ''); // max repos to sync $max_repos = $this->getParam('max_repos', 100); // get repos $repos = $issue->get('user/repos'); $synced = 0; if($last_sync_repo !== '' && array_key_exists($last_sync_repo, $repos)) $logger->info(sprintf("[] Starting sync from %s/%s", $repos[$last_sync_repo]['user'], $repos[$last_sync_repo]['name'])); foreach($repos as $repo) { if($last_sync_repo !== '' && $repo['id'] != $last_sync_repo) { $logger->info(sprintf("[] Skipping repository %s!", $repository)); continue; } // does the owner of the repository exist in the DB? if(null === $user = DAO_User::getByLogin($repo['owner']['login'])) { $user = $issue->get(sprintf('users/%s', $repo['owner']['login'])); $fields = array( DAO_User::NUMBER => $user['id'], DAO_User::LOGIN => $user['login'], DAO_User::NAME => $user['name'], DAO_User::EMAIL => $user['email'] ); $user = DAO_User::create($fields); } $fields = array( DAO_Repository::NUMBER => $repo['id'], DAO_Repository::NAME => $repo['name'], DAO_Repository::DESCRIPTION => $repo['description'], DAO_Repository::USER_ID => $user->id, DAO_Repository::ENABLED => true ); // does the repo exist in the DB? if(null === $repository = DAO_Repository::getByNumber($repo['id'])) { DAO_Repository::create($fields); } else { DAO_Repository::update($repository->id, $fields); } $synced++; // check amount of repos synced if($synced == $max_repos) { $this->setParam('repos.last_repo', $repo_id); break 2; } } foreach($repos as $repo) { // is the repo enabled? $user = DAO_User::get($repo->user_id); $repository = sprintf("%s/%s", $user->login, $repo->name); if($last_sync_repo !== '' && $repo_id != $last_sync_repo) { $logger->info(sprintf("[] Skipping repository %s!", $repository)); continue; } elseif(!$repo->enabled) { $logger->info(sprintf("[] Skipping repository %s since it isn't enabled!", $repository)); continue; } } $logger->info("[] Total Runtime: ".number_format((microtime(true)-$runtime)*1000,2)." ms"); }