function getSMTPInfo($active = true) { $info = array(); if (!$active || $active && $this->isSMTPEnabled()) { $info = array('host' => $this->info['smtp_host'], 'port' => $this->info['smtp_port'], 'auth' => $this->info['smtp_auth'], 'username' => $this->info['userid'], 'password' => Misc::decrypt($this->info['userpass'], SECRET_SALT)); } return $info; }
<?php if(!defined('OSTADMININC') || basename($_SERVER['SCRIPT_NAME'])==basename(__FILE__)) die('Habari/Jambo rafiki? '); //Say hi to our friend.. if(!$thisuser || !$thisuser->isadmin()) die('Access Denied'); $info=($_POST && $errors)?$_POST:array(); //Re-use the post info on error...savekeyboards.org if($email && $_REQUEST['a']!='new'){ $title='Edit Email'; $action='update'; if(!$info) { $info=$email->getInfo(); $info['userpass']=$info['userpass']?Misc::decrypt($info['userpass'],SECRET_SALT):''; } $qstr='?t=email&id='.$email->getId(); }else { $title='New Email'; $action='create'; $info['smtp_auth']=isset($info['smtp_auth'])?$info['smtp_auth']:1; } $info=Format::htmlchars($info); //get the goodies. $depts= db_query('SELECT dept_id,dept_name FROM '.DEPT_TABLE); $priorities= db_query('SELECT priority_id,priority_desc FROM '.TICKET_PRIORITY_TABLE); ?> <div class="msg"><?=$title?></div> <table width="100%" border="0" cellspacing=0 cellpadding=0> <form action="admin.php<?=$qstr?>" method="post"> <input type="hidden" name="do" value="<?=$action?>"> <input type="hidden" name="a" value="<?=Format::htmlchars($_REQUEST['a'])?>"> <input type="hidden" name="t" value="email"> <input type="hidden" name="email_id" value="<?=$info['email_id']?>">
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: "******"\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); } } } }
function addLogDetail($action_id, $system_log_id, $object) { $start_time = microtime(TRUE); //Only log detail records on add,edit,delete,undelete //Logging data on Add/Delete/UnDelete, or anything but Edit will greatly bloat the database, on the order of tens of thousands of entries //per day. The issue though is its nice to know exactly what data was originally added, then what was edited, and what was finally deleted. //We may need to remove logging for added data, but leave it for edit/delete, so we know exactly what data was deleted. if (!in_array($action_id, array(10, 20, 30, 31, 40))) { Debug::text('Invalid Action ID: ' . $action_id, __FILE__, __LINE__, __METHOD__, 10); return FALSE; } if ($system_log_id > 0 and is_object($object)) { //Remove "Plugin" from the end of the class name incase plugins are enabled. $class = str_replace('Plugin', '', get_class($object)); Debug::text('System Log ID: ' . $system_log_id . ' Class: ' . $class, __FILE__, __LINE__, __METHOD__, 10); //Debug::Arr($object->data, 'Object Data: ', __FILE__, __LINE__, __METHOD__, 10); //Debug::Arr($object->old_data, 'Object Old Data: ', __FILE__, __LINE__, __METHOD__, 10); //Only store raw data changes, don't convert *_ID fields to full text names, it bloats the storage and slows down the logging process too much. //We can do the conversion when someone actually looks at the audit logs, which will obviously be quite rare in comparison. Even though this will //require quite a bit more code to handle. //There are also translation issues if we convert IDs to text at this point. However there could be continuity problems if ID values change in the future. $new_data = $object->data; //Debug::Arr($new_data, 'New Data Arr: ', __FILE__, __LINE__, __METHOD__, 10); if ($action_id == 20) { //Edit if (method_exists($object, 'setObjectFromArray')) { //Run the old data back through the objects own setObjectFromArray(), so any necessary values can be parsed. $tmp_class = new $class(); $tmp_class->setObjectFromArray($object->old_data); $old_data = $tmp_class->data; //If user_date_id changed, we need to display the differences for it. (user/date) //For example: if a schedule shift is assigned to a new user, just the user_date_id is modified if (isset($new_data['user_date_id']) and isset($old_data['user_date_id']) and $new_data['user_date_id'] != $old_data['user_date_id'] or isset($new_data['user_date_id']) and !isset($old_data['user_date_id']) or !isset($new_data['user_date_id']) and isset($old_data['user_date_id'])) { Debug::Text('User Date ID changed...', __FILE__, __LINE__, __METHOD__, 10); if (method_exists($object, 'getUserDateObject') and is_object($object->getUserDateObject())) { $new_data['user_id'] = $object->getUserDateObject()->getUser(); $new_data['pay_period_id'] = $object->getUserDateObject()->getPayPeriod(); $new_data['date_stamp'] = $object->getUserDateObject()->getDateStamp(); } if (method_exists($tmp_class, 'getUserDateObject') and is_object($tmp_class->getUserDateObject())) { $old_data['user_id'] = $tmp_class->getUserDateObject()->getUser(); $old_data['pay_period_id'] = $tmp_class->getUserDateObject()->getPayPeriod(); $old_data['date_stamp'] = $tmp_class->getUserDateObject()->getDateStamp(); } } unset($tmp_class); } else { $old_data = $object->old_data; } //We don't want to include any sub-arrays, as those classes should take care of their own logging, even though it may be slower in some cases. $diff_arr = array_diff_assoc((array) $new_data, (array) $old_data); } elseif ($action_id == 30) { //Delete $old_data = array(); if (method_exists($object, 'setObjectFromArray')) { //Run the old data back through the objects own setObjectFromArray(), so any necessary values can be parsed. $tmp_class = new $class(); $tmp_class->setObjectFromArray($object->data); $diff_arr = $tmp_class->data; unset($tmp_class); } else { $diff_arr = $object->data; } } else { //Add //Debug::text('Not editing, skipping the diff process...', __FILE__, __LINE__, __METHOD__, 10); //No need to store data that is added, as its already in the database, and if it gets changed or deleted we store it then. $old_data = array(); $diff_arr = $object->data; } //Debug::Arr($old_data, 'Old Data Arr: ', __FILE__, __LINE__, __METHOD__, 10); //Handle class specific fields. switch ($class) { case 'UserFactory': case 'UserListFactory': unset($diff_arr['labor_standard_industry'], $diff_arr['password'], $diff_arr['phone_password'], $diff_arr['password_reset_key'], $diff_arr['password_updated_date'], $diff_arr['last_login_date'], $diff_arr['full_name'], $diff_arr['first_name_metaphone'], $diff_arr['last_name_metaphone'], $diff_arr['ibutton_id'], $diff_arr['finger_print_1'], $diff_arr['finger_print_2'], $diff_arr['finger_print_3'], $diff_arr['finger_print_4'], $diff_arr['finger_print_1_updated_date'], $diff_arr['finger_print_2_updated_date'], $diff_arr['finger_print_3_updated_date'], $diff_arr['finger_print_4_updated_date']); break; case 'PayPeriodScheduleFactory': case 'PayPeriodScheduleListFactory': unset($diff_arr['primary_date_ldom'], $diff_arr['primary_transaction_date_ldom'], $diff_arr['primary_transaction_date_bd'], $diff_arr['secondary_date_ldom'], $diff_arr['secondary_transaction_date_ldom'], $diff_arr['secondary_transaction_date_bd']); break; case 'PayPeriodFactory': case 'PayPeriodListFactory': unset($diff_arr['is_primary']); break; case 'StationFactory': case 'StationListFactory': unset($diff_arr['last_poll_date'], $diff_arr['last_push_date'], $diff_arr['last_punch_time_stamp'], $diff_arr['last_partial_push_date'], $diff_arr['mode_flag'], $diff_arr['work_code_definition'], $diff_arr['allowed_date']); break; case 'ScheduleFactory': case 'ScheduleListFactory': unset($diff_arr['recurring_schedule_template_control_id'], $diff_arr['replaced_id']); break; case 'PunchFactory': case 'PunchListFactory': unset($diff_arr['actual_time_stamp'], $diff_arr['original_time_stamp'], $diff_arr['punch_control_id'], $diff_arr['station_id'], $diff_arr['latitude'], $diff_arr['longitude']); break; case 'PunchControlFactory': case 'PunchControlListFactory': unset($diff_arr['actual_total_time']); break; case 'PunchControlFactory': case 'PunchControlListFactory': unset($diff_arr['overlap']); break; case 'AccrualFactory': case 'AccrualListFactory': unset($diff_arr['user_date_total_id']); break; case 'JobItemFactory': case 'JobItemListFactory': unset($diff_arr['type_id'], $diff_arr['department_id']); break; case 'ClientContactFactory': case 'ClientContactListFactory': unset($diff_arr['password'], $diff_arr['password_reset_key'], $diff_arr['password_reset_date']); break; case 'UserReviewFactory': case 'UserReviewListFactory': unset($diff_arr['user_review_control_id']); break; case 'ClientPaymentFactory': case 'ClientPaymentListFactory': if (getTTProductEdition() >= TT_PRODUCT_CORPORATE) { //Only log secure values. if (isset($diff_arr['cc_number'])) { $old_data['cc_number'] = isset($old_data['cc_number']) ? $object->getSecureCreditCardNumber(Misc::decrypt($old_data['cc_number'])) : ''; $new_data['cc_number'] = isset($new_data['cc_number']) ? $object->getSecureCreditCardNumber(Misc::decrypt($new_data['cc_number'])) : ''; } if (isset($diff_arr['bank_account'])) { $old_data['bank_account'] = isset($old_data['bank_account']) ? $object->getSecureAccount($old_data['bank_account']) : ''; $new_data['bank_account'] = isset($old_data['bank_account']) ? $object->getSecureAccount($new_data['bank_account']) : ''; } if (isset($diff_arr['cc_check'])) { $old_data['cc_check'] = isset($old_data['cc_check']) ? $object->getSecureCreditCardCheck($old_data['cc_check']) : ''; $new_data['cc_check'] = isset($old_data['cc_check']) ? $object->getSecureCreditCardCheck($new_data['cc_check']) : ''; } } break; case 'JobApplicantFactory': case 'JobApplicantListFactory': unset($diff_arr['password'], $diff_arr['password_reset_key'], $diff_arr['password_reset_date'], $diff_arr['first_name_metaphone'], $diff_arr['last_name_metaphone']); break; } //Ignore specific columns here, like updated_date, updated_by, etc... unset($diff_arr['id'], $diff_arr['company_id'], $diff_arr['user_date_id'], $diff_arr['name_metaphone'], $diff_arr['created_date'], $diff_arr['created_by'], $diff_arr['created_by_id'], $diff_arr['updated_date'], $diff_arr['updated_by'], $diff_arr['updated_by_id'], $diff_arr['deleted_date'], $diff_arr['deleted_by'], $diff_arr['deleted_by_id'], $diff_arr['deleted']); //Debug::Arr($diff_arr, 'Array Diff: ', __FILE__, __LINE__, __METHOD__, 10); if (is_array($diff_arr) and count($diff_arr) > 0) { foreach ($diff_arr as $field => $value) { $old_value = NULL; if (isset($old_data[$field])) { $old_value = $old_data[$field]; if (is_bool($old_value) and $old_value === FALSE) { $old_value = NULL; } elseif (is_array($old_value)) { //$old_value = serialize($old_value); //If the old value is an array, replace it with NULL because it will always match the NEW value too. $old_value = NULL; } } $new_value = $new_data[$field]; if (is_bool($new_value) and $new_value === FALSE) { $new_value = NULL; } elseif (is_array($new_value)) { $new_value = serialize($new_value); } //Debug::Text('Old Value: '. $old_value .' New Value: '. $new_value, __FILE__, __LINE__, __METHOD__, 10); if (!($old_value == '' and $new_value == '')) { $ph[] = (int) $system_log_id; $ph[] = $field; $ph[] = $new_value; $ph[] = $old_value; $data[] = '(?,?,?,?)'; } } if (isset($data)) { //Save data in a single SQL query. $query = 'INSERT INTO ' . $this->getTable() . '(SYSTEM_LOG_ID,FIELD,NEW_VALUE,OLD_VALUE) VALUES' . implode(',', $data); //Debug::Text('Query: '. $query, __FILE__, __LINE__, __METHOD__, 10); $this->db->Execute($query, $ph); Debug::Text('Logged detail records in: ' . (microtime(TRUE) - $start_time), __FILE__, __LINE__, __METHOD__, 10); return TRUE; } } } Debug::Text('Not logging detail records, likely no data changed in: ' . (microtime(TRUE) - $start_time) . 's', __FILE__, __LINE__, __METHOD__, 10); return FALSE; }
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 deve ser compilado com extensão IMAP habilitado para buscar a trabalhar IMAP/POP3!'; Sys::log(LOG_WARN, 'Erro em buscar o email', $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 = "\nO sistema está tendo problemas para coletar e-mails da conta do e-mail seguinte: \n" . "\nUsuário: " . $row['userid'] . "\nHost: " . $row['mail_host'] . "\nErro: " . $fetcher->getLastError() . "\n\n " . $errors . ' erros consecutivos. Máximo de ' . $MAX_ERRORS . ' permitido' . "\n\n Isso pode ser problemas de conexão relacionados ao hospedeiro. Próxima tentativa de login em aprox. 10 minutos"; Sys::alertAdmin('Alerta de falha na busca por email', $msg, true); } } } }
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 debe ser compilado con la extensión IMAP habilitada para IMAP/POP3 fetch(captura de correo) para que funcione'; Sys::log(LOG_WARN, 'Error de captura de correo', $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 = "\nEl sistema está teniendo problemas para obtener los correos electrónicos de la cuenta de correo siguiente: \n" . "\nUsuario: " . $row['userid'] . "\nHost: " . $row['mail_host'] . "\nError: " . $fetcher->getLastError() . "\n\n " . $errors . ' errores consecutivos. Máximo de ' . $MAX_ERRORS . ' permitidos' . "\n\n Esto podría ser una cuestión relacionada con la conexión al host. Siguiente intento en aprox. 10 min"; Sys::alertAdmin('Alerta de fallo en la captura de correo', $msg, true); } } } }