<?php

/**
 * Пример вызова:
 * /usr/bin/php /var/www/site.ru/httpdocs/cron/getmessages.php
 * 
 * Пример вызова с передачей php.ini (например, если бинарный php по умолчанию не видит ZendOptimizer)
 * /usr/bin/php --php-ini /etc/php.ini /var/www/site.ru/httpdocs/cron/getmessages.php
 * 
 * Реальный путь на сервере к корневой директории сайта уточните в службе поддержки хостинга.
 * 
 */

@set_time_limit(90000);

// Подключаем основные классы с учетов размещения в директории ./cron/
// При размещении в корневой директории '/../' заменить на '/'
require_once(dirname(__FILE__) . '/../' . 'main_classes.php');

$kernel = & singleton('kernel');

// Загрузка модулей
$kernel->LoadModules();

define('CURRENT_SITE', 1);

$helpdesk = new helpdesk();
$Mail = new Mail();

// Инициализация констант.
$kernel->InitConstants();

// Получаем список всех служб технической поддержки сайта
$helpdesk_result = $helpdesk->GetAllHelpdesk(CURRENT_SITE);

if ($helpdesk_result)
{
	while ($helpdesk_row = mysql_fetch_assoc($helpdesk_result))
	{
		// Получаем маску, по которой формируются название тикетов службы техподдержки
		$helpdesk_ticket_mask = $helpdesk_row['helpdesk_ticket_mask'];
		$helpdesk_ticket_category_id = $helpdesk_row['helpdesk_ticket_category_id'];
		$helpdesk_critical_level_id = $helpdesk_row['helpdesk_critical_level_id'];
		$helpdesk_id = $helpdesk_row['helpdesk_id'];
		$helpdesk_status_new_id = $helpdesk_row['helpdesk_status_new_id'];

		// Шаблон отчета
		$report_template = $helpdesk_row['helpdesk_report_for_query'];
		$helpdesk_report_for_query_subject = $helpdesk_row['helpdesk_report_for_query_subject'];
		$helpdesk_notify_for_query = $helpdesk_row['helpdesk_notify_for_query'];
		$helpdesk_message_type = $helpdesk_row['helpdesk_message_type'];
		$helpdesk_name = $helpdesk_row['helpdesk_name'];

		// Получаем список всех электронных адресов техподдержки
		$email_result = $helpdesk->GetAllEmail($helpdesk_id);

		// Счетчик добавленных тикетов
		$counter = 0;

		if ($email_result)
		{
			while ($email_row = mysql_fetch_assoc($email_result))
			{
				// Формируем массив параметров для получения корреспонденции
				$param_email = array();

				$param_email['email_login'] = $email_row['helpdesk_email_login'];
				$param_email['email_password'] = $email_row['helpdesk_email_password'];
				$param_email['delete'] = $email_row['helpdesk_email_delete_message'];
				$param_email['secury'] = to_bool($email_row['helpdesk_email_use_secury_protocol']);
				$param_email['email_pop3'] = $email_row['helpdesk_email_pop3'];
				$param_email['email_imap'] = $email_row['helpdesk_email_imap'];

				// Активность электронного адреса
				$is_active = $email_row['helpdesk_email_active'];

				// Получаем почту только с активных адресов
				if ($is_active)
				{
					// Получаем массив писем
					$mails_array = $Mail->GetMsgList($param_email);

					// Возникли ошибки при доступе к электронной почте
					if (isset($mails_array['error']))
					{
						if (count($mails_array['error']) > 0)
						{
							if (isset($mails_array['error']['no_letters']))
							{
								show_message(sprintf($GLOBALS['MSG_helpdesk']['receive_mail_error'], $email_row['helpdesk_email_email']) . " " .  $GLOBALS['MSG_helpdesk']['receive_mail_error_mailbox_empty']);
							}
							else
							{
								$EventJournal = & singleton('EventsJournal');
								show_error_message(sprintf($GLOBALS['MSG_helpdesk']['receive_mail_error'], $email_row['helpdesk_email_email']));

								foreach ($mails_array['error'] as $key => $value)
								{
									// Отображаем  ошибки пользователю
									show_error_message($value);

									// Получаем имя пользователя
									if (isset($_SESSION['valid_user']))
									{
										$login = to_str($_SESSION['valid_user']);
									}
									else
									{
										$login = USER_NONE;
									}

									// Записываем в журнал событий
									$EventJournal->log_access($login, $value, $status = 2, $send_email = true);
								}
							}
						}
					}
					else
					{
						// Получаем информацию о текущей службе техподдержки
						$helpdesk_row = $helpdesk->GetHelpdesk($helpdesk_id);

						//=======================================================================
						// Записываем сообщения
						//=======================================================================

						// Записываем информацию о сообщениях
						for ($i = 1; $i <= count($mails_array); $i++)
						{
							$param_email = array();

							// Проверяем, зарегистрированный ли пользователь, с e-mailа которого получено сообщение
							// Ищем e-mail  в таблице пользователей сайта
							$site_user_row = $helpdesk->GetSiteUserByEmail($mails_array[$i]['e_mail_from']);

							if ($site_user_row)
							{
								$param_email['site_users_id'] = $site_user_row['site_users_id'];
							}
							else
							{
								$param_email['site_users_id'] = 0;
							}

							// Разбираем тему сообщения

							// Получаем маску, по которой формируются название тикетов службы техподдержки
							if ($helpdesk_row)
							{
								$helpdesk_ticket_mask = $helpdesk_row['helpdesk_ticket_mask'];
							}
							else
							{
								$helpdesk_ticket_mask = '%09d';
							}

							// Маска формирования темы сообщения
							$format = str_replace("%", "%1$", $helpdesk_ticket_mask) . ":%2\$d";

							// Подстрока с именем тикета и порядковым номером письма-родителя
							$str = '';

							preg_match_all("'.*?\[([^\]]*?)\].*?'siu", $mails_array[$i]['subject_letter'], $matches);

							// Имя тикета
							$param_email['helpdesk_ticket_name'] = '';

							// В теме есть название тикета
							if (isset($matches[1]))
							{
								for ($j = 0; $j < count($matches[1]); $j++)
								{
									// Проверяем тему по маске формирования имени тикета
									$scanf = $helpdesk->sscanf($matches[1][$j], $format);

									// Есть имя тикета
									if (isset($scanf[0]) && isset($scanf[1]))
									{
										$param_email['helpdesk_ticket_name'] = sprintf($helpdesk_ticket_mask, to_int($scanf[0]));

										// Есть порядковый номер родительского письма
										if (isset($scanf[1]))
										{
											$param_email['helpdesk_message_parent_num'] = to_int($scanf[1]);
										}

										$str .= $matches[1][$j];
									}
								}
							}

							// Проверим, существует ли тикет с полученным из темы именем
							if ($param_email['helpdesk_ticket_name'] !== '')
							{
								if ($helpdesk_ticket_row = $helpdesk->GetTicketByName($param_email['helpdesk_ticket_name'], array('helpdesk_id' => $helpdesk_id)))
								{
									$param_email['helpdesk_ticket_id'] = $helpdesk_ticket_row['helpdesk_ticket_id'];

									// Адрес пользователя, указанный  в настройках тикета
									$e_mail_from = $helpdesk_ticket_row['helpdesk_ticket_email'];
								}
							}
							else
							{
								$param_email['helpdesk_ticket_id'] = 0;
								$e_mail_from = -1;
							}

							//=======================================================================
							// Создаем новый тикет, если название тикета не указано в теме,
							// либо указанный в теме тикет не существует, либо сообщение пришло
							// с другого адреса, нежели указан в настройках тикета
							//=======================================================================

							if (!isset($param_email['helpdesk_ticket_id'])
							|| $param_email['helpdesk_ticket_id'] == 0
							// Адреса не совпадают, при этом домены также не совпадают
							|| (mb_strtolower($mails_array[$i]['e_mail_from']) != mb_strtolower($e_mail_from)
							&& ereg("^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+)$", mb_strtolower($mails_array[$i]['e_mail_from']), $regs1)
							&& ereg("^([a-zA-Z0-9_\.\-]+)@([a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+)$", mb_strtolower($e_mail_from), $regs2))
							&& isset($regs1[2]) && isset($regs2[2]) && $regs1[2] != $regs2[2]
							)
							{
								$ticket_param = array();

								// Определяем категорию тикетов, к которой нужно отнести создаваемый тикет
								// Если категория по умолчанию для электронного ящика имеет идентификатор отличный от нуля
								if ($email_row['helpdesk_ticket_category_id'])
								{
									$ticket_param['helpdesk_ticket_category_id'] = to_int($email_row['helpdesk_ticket_category_id']);
								}
								// Вкладываем тикет в категорию по умолчанию для всех тикетов
								else
								{
									$ticket_param['helpdesk_ticket_category_id'] = to_int($helpdesk_row['helpdesk_ticket_category_id']);
								}

								// Проверяем, существует ли указанная категория тикетов. Если нет, то тикет определяем в корневую категорию
								$ticket_category_row = $helpdesk->GetTicketCategory($ticket_param['helpdesk_ticket_category_id']);

								if (!$ticket_category_row)
								{
									$ticket_param['helpdesk_ticket_category_id'] = 0;
								}

								$ticket_param['users_id'] = 0;
								$ticket_param['helpdesk_critical_level_id'] = to_int($helpdesk_row['helpdesk_critical_level_id']);
								$ticket_param['site_users_id'] = to_int($param_email['site_users_id']);
								$ticket_param['helpdesk_id'] = to_int($helpdesk_id);

								if (isset($mails_array[$i]['e_mail_from']))
								{
									$ticket_param['helpdesk_ticket_email'] = to_str($mails_array[$i]['e_mail_from']);
								}

								$ticket_param['helpdesk_ticket_datetime'] = date("Y-m-d H:i:s");
								$ticket_param['helpdesk_ticket_notify_status_message_change'] = 1;
								$ticket_param['helpdesk_ticket_sent_answer_for_message'] = 1;
								$ticket_param['helpdesk_ticket_is_open'] = 1;
								$ticket_param['helpdesk_ticket_source'] = 1;
								$ticket_param['helpdesk_email_id'] = to_int($email_row['helpdesk_email_id']);
								$ticket_param['show_message'] = false;

								// Добавляем информацию в БД.
								if ($helpdesk_ticket_id = $helpdesk->InsertTicket($ticket_param))
								{
									// ID тикета
									$param_email['helpdesk_ticket_id'] = $helpdesk_ticket_id;

									// Число созданных тикетов
									$counter++;
								}
								else
								{
									// ID тикета
									$param_email['helpdesk_ticket_id'] = 0;
								}
							}

							// если тикет создан успешно
							if ($param_email['helpdesk_ticket_id'])
							{
								// Получаем информацию о тикете
								$helpdesk_ticket_row = $helpdesk->GetTicket($param_email['helpdesk_ticket_id']);

								if ($helpdesk_ticket_row)
								{
									// Открываем тикет, если он был закрыт
									if ($helpdesk_ticket_row['helpdesk_ticket_is_open'] == 0)
									{
										$helpdesk->TicketStatusChange($helpdesk_ticket_row['helpdesk_ticket_id'], 1);
									}

									$ticket_email = $helpdesk_ticket_row['helpdesk_ticket_email'];

									// Проверяем, можно ли отсылать отчеты о получении сообщений и автоответы пользователю (защита от зацикливания - автоответы почтовых программ)
									$is_helpdesk_email = $helpdesk->GetEmailIsHelpdeskEmail($helpdesk_id, $ticket_email, $mails_array[$i]['subject_letter'], $param_email['helpdesk_ticket_id']);

									// Если в теме не указано родительское сообщение
									if (!isset($param_email['helpdesk_message_parent_num']))
									{
										// Кладем сообщение в корень
										$param_email['helpdesk_message_parent_id'] = 0;
									}
									else
									{
										// получаем id родительского сообщения
										if ($message_row = $helpdesk->GetMessageByNumber($param_email['helpdesk_ticket_id'], $param_email['helpdesk_message_parent_num']))
										{
											$param_email['helpdesk_message_parent_id'] = $message_row['helpdesk_message_id'];
										}
									}

									$param_email['helpdesk_status_id'] = $helpdesk_row['helpdesk_status_new_id'];
									$param_email['helpdesk_message_subject'] = html_entity_decode($mails_array[$i]['subject_letter'], ENT_COMPAT, 'UTF-8');

									if (strstr(mb_strtolower($mails_array[$i]['type']), 'html') !== false
									|| strstr(mb_strtolower($mails_array[$i]['subtype']), "html") !== false
									|| (isset($mails_array[$i]['structure_array']['parts'][0]['type'])
									&& strstr(mb_strtolower($mails_array[$i]['structure_array']['parts'][0]['type']), 'html') !== false)
									|| (isset($mails_array[$i]['structure_array']['parts'][0]['subtype'])
									&& strstr(mb_strtolower($mails_array[$i]['structure_array']['parts'][0]['subtype']), 'html') !== false))
									{
										// тип - html
										$param_email['helpdesk_message_type'] = 0;

										$text = $helpdesk->CutQuotetion($mails_array[$i]['body'], $param_email['helpdesk_message_type']);
										$param_email['helpdesk_message_message'] = strip_tags_attributes($text, $helpdesk->sAllowTag);
									}
									else
									{
										// тип - text
										$param_email['helpdesk_message_type'] = 1;
										$param_email['helpdesk_message_message'] = $helpdesk->CutQuotetion($mails_array[$i]['body'], $param_email['helpdesk_message_type']);
									}

									$param_email['helpdesk_message_creation_datetime'] = $mails_array[$i]['date'];
									$param_email['helpdesk_message_modification_datetime'] = $mails_array[$i]['date'];
									$param_email['helpdesk_message_grade'] = 0;
									$param_email['helpdesk_message_responsible_description'] = '';
									$param_email['helpdesk_message_processed'] = 0;
									$param_email['helpdesk_message_number'] = 0;
									$param_email['helpdesk_message_inbox'] = 1;
									$param_email['users_id'] = 0;

									$param_email['helpdesk_message_headers'] = $mails_array[$i]['headers'];

									if (isset($mails_array[$i]['structure']))
									{
										$param_email['helpdesk_message_headers'] .= $mails_array[$i]['structure'];
									}
									
									if (isset ($mails_array[$i]['fetchheader_str']))
									{
										$param_email['helpdesk_message_headers'] .= "\n\n" . trim($mails_array[$i]['fetchheader_str']);
									}

									$helpdesk_message_id = $helpdesk->InsertMessage($param_email);

									// Рассчитываем примерное время ответа
									$helpdesk->RecountAnswerDateTime($param_email['helpdesk_ticket_id']);

									$ticket_id = intval($param_email['helpdesk_ticket_id']);

									//=======================================================================
									// Сохраняем вложенные файлы
									//=======================================================================

									// Сохраняем вложенные файлы
									if (isset($mails_array[$i]['attachments']))
									{
										$param_attachments = array();
										$param_attachments = $helpdesk->LoadAttachments($mails_array[$i]['attachments'], $helpdesk_id, $param_email['helpdesk_ticket_id'], $helpdesk_message_id);

										$param_attach = array();

										foreach ($param_attachments as $key => $val)
										{
											$param['helpdesk_attachment_file_name'] = $val['name'];
											$param['helpdesk_attachment_file_path'] = $val['path'];

											// Вносим в БД имена записанных на сервер вложенных файлов
											$helpdesk->InsertAttachments($helpdesk_message_id, $param);
										}
									}

									//=======================================================================
									// Отправка отчета о получении запроса в службу техподдержки
									//=======================================================================

									// Отправка уведомления о получении запроса в службу техподдержки
									if ($helpdesk_row)
									{
										// Шаблон отчета
										$report_template = $helpdesk_row['helpdesk_report_for_query'];
										$helpdesk_report_for_query_subject = $helpdesk_row['helpdesk_report_for_query_subject'];
										$helpdesk_notify_for_query = $helpdesk_row['helpdesk_notify_for_query'];
										$helpdesk_message_type = $helpdesk_row['helpdesk_message_type'];
									}
									else
									{
										$report_template = '';
										$helpdesk_report_for_query_subject = '';
										$helpdesk_notify_for_query = 1;
										$helpdesk_message_type = 0;
									}

									// Необходимо отсылать отчет о получении запроса (должно быть указано как в настройках службы техподдержки, так и в настройках тикета, т.к. может произойти бесконечная автоматическая переписка с почтовыми агентами)
									if($helpdesk_notify_for_query && $helpdesk_ticket_row['helpdesk_ticket_sent_answer_for_message'])
									{
										// При поступлении запроса с обратным адресом, эквивалентным одному из тех, с которых получаем, отправлять автоматический ответ не нужно. Т.к. получится зацикливание и хэлпдеск сам себе будет слать письма
										// Письмо имеет не низкий приоритет и не помечено как рассылка или спам
										if (!$is_helpdesk_email && !((isset ($mails_array[$i]['fetchheader']['precedence']) && in_array($mails_array[$i]['fetchheader']['precedence'], array (
												'bulk',
												'junk',
												'list'
											)))
											|| (isset ($mails_array[$i]['fetchheader']['x-priority']) && intval($mails_array[$i]['fetchheader']['x-priority']) > 3)))
										{
											if ($helpdesk_report_for_query_subject == '')
											{
												$helpdesk_report_for_query_subject = $GLOBALS['MSG_helpdesk']['template_report_for_query_subject'];
											}

											$arr = array();
											$arr['helpdesk_message_id'] = $helpdesk_message_id;

											$report_template = $helpdesk->ReFormat($report_template, $helpdesk_message_type);

											$report_text = $helpdesk->ReplaceMailMacro($report_template, $arr);
											$helpdesk_report_for_query_subject = $helpdesk->ReplaceMailMacro($helpdesk_report_for_query_subject, $arr);

											$param_email['helpdesk_status_id'] = $helpdesk_row['helpdesk_status_new_id'];
											$param_email['helpdesk_ticket_id'] = $ticket_id;
											$param_email['helpdesk_message_message'] = $report_text;
											$param_email['helpdesk_message_parent_id'] = $helpdesk_message_id;
											$param_email['helpdesk_message_subject'] = $helpdesk_report_for_query_subject;
											$param_email['helpdesk_message_creation_datetime'] = $param['helpdesk_message_modification_datetime'] = date("Y-m-d H:i:s");
											$param_email['helpdesk_message_grade'] = 0;

											$param_email['users_id'] = 0;
											$param_email['site_users_id'] = 0;
											$param_email['helpdesk_message_processed'] = 1;
											$param_email['helpdesk_message_number'] = 0;
											$param_email['helpdesk_message_inbox'] = 0;
											$param_email['header'] = array('Precedence' => 'bulk',
											'X-Priority' => '5 (Lowest)',
											'X-HostCMS-Reason' => 'IncidentConfirm');

											// Отсылаем сообщение
											$helpdesk->SendMessage($param_email, $helpdesk_message_type);
										}
									}

									//=======================================================================
									// Отправка автоответа (только на первое сообщение тикета)
									//=======================================================================

									// Получаем информацию о сообщении
									$message_row = $helpdesk->GetMessage($helpdesk_message_id);

									if ($message_row)
									{
										// При поступлении запроса с обратным адресом, эквивалентным одному из тех, с которых получаем, отправлять автоматический ответ не нужно. Т.к. получится зацикливание и хэлпдеск сам себе будет слать письма
										// Письмо имеет не низкий приоритет и не помечено как рассылка или спам
										if (!$is_helpdesk_email && !((isset ($mails_array[$i]['fetchheader']['precedence']) && in_array($mails_array[$i]['fetchheader']['precedence'], array (
												'bulk',
												'junk',
												'list'
											))) || (isset ($mails_array[$i]['fetchheader']['x-priority']) && intval($mails_array[$i]['fetchheader']['x-priority']) > 3)))
										{
											if ($message_row['helpdesk_message_number'] == 1)
											{
												// Анализируем текст сообщения для автоматического ответа
												$helpdesk_letter_template_id = $helpdesk->AnalizeForKeyWords($helpdesk_id, $message_row['helpdesk_message_subject'] . "\n\n" . $message_row['helpdesk_message_message']);

												// Для автоматического ответа на сообщение подходит стандартный ответ
												// Формируем ответ на сообщение
												if ($helpdesk_letter_template_id)
												{
													$helpdesk->SentAutoAnswer($helpdesk_id, $helpdesk_letter_template_id, $helpdesk_message_id);
												}
											}
										}
									}
								}//if(ticket_row)
							}//if(helpdesk_ticket_id)
						}//for
					}
				}//if(is_active)
			}//while

			if ($counter)
			{
				if ($counter == 1)
				{
					?><h1><?php echo $GLOBALS['MSG_helpdesk']['add_ticket_success']; ?></h1><?php
				}
				else
				{
					?><h1><?php echo $GLOBALS['MSG_helpdesk']['add_ticket_many_success']; ?></h1><?php
				}
			}

			?><h2><?php echo "Получение корреспонденции для службы техподдержки \"$helpdesk_name\" завершено."; ?></h2><?php
		}

		// Закрываем старые тикеты
		$helpdesk->CloseOldTicket($helpdesk_id);
	}
}
else
{
	echo "Error: Helpdesk's not found";
}

?>