#!/usr/local/bin/php
<?php
define('TICKETS_PIPE', true);
error_reporting(1);

$environment = 'development';

$system_path = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'system';

$application_folder = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'application';

if (realpath($system_path) !== false) {
    $system_path = realpath($system_path) . '/';
}

$system_path = rtrim($system_path, '/') . '/';

define('BASEPATH', str_replace('\\', '/', $system_path));
define('APPPATH', $application_folder . '/');
$view_folder = APPPATH . 'views';
define('VIEWPATH', $view_folder . DIRECTORY_SEPARATOR);
define('EXT', '.php');
define('ENVIRONMENT', $environment ? $environment : 'development');
define('FCPATH', dirname(__FILE__) . '/');

if (file_exists(APPPATH . 'config/' . ENVIRONMENT . '/constants.php')) {
    require(APPPATH . 'config/' . ENVIRONMENT . '/constants.php');
} else {
    require(APPPATH . 'config/constants.php');
}

require(BASEPATH . 'core/Common.php');

if ($composer_autoload = config_item('composer_autoload')) {
    if ($composer_autoload === true) {
        file_exists(APPPATH . 'vendor/autoload.php')
        ? require_once(APPPATH . 'vendor/autoload.php')
        : log_message('error', '$config[\'composer_autoload\'] is set to TRUE but ' . APPPATH . 'vendor/autoload.php was not found.');
    } elseif (file_exists($composer_autoload)) {
        require_once($composer_autoload);
    } else {
        log_message('error', 'Could not find the specified $config[\'composer_autoload\'] path: ' . $composer_autoload);
    }
} else {
    // Fix for user who don't replace all the files during update
    if (file_exists(APPPATH . 'vendor/autoload.php')) {
        require_once(APPPATH . 'vendor/autoload.php');
    }
}

// Only uses the hooks() function.
require_once(APPPATH . 'config/hooks.php');
// Load the classes autoloader
require_once(APPPATH . 'hooks/App_Autoloader.php');

(new App_Autoloader)->register();

if (extension_loaded('mbstring')) {
    define('MB_ENABLED', true);
    // This is required for mb_convert_encoding() to strip invalid characters.
    // That's utilized by CI_Utf8, but it's also done for consistency with iconv.
    mb_substitute_character('none');
} else {
    define('MB_ENABLED', false);
}

// There's an ICONV_IMPL constant, but the PHP manual says that using
// iconv's predefined constants is "strongly discouraged".
define('ICONV_ENABLED', extension_loaded('iconv'));

$GLOBALS['CFG'] = & load_class('Config', 'core');
$GLOBALS['UNI'] = & load_class('Utf8', 'core');

if (file_exists(BASEPATH . 'core/Security.php')) {
    $GLOBALS['SEC'] = & load_class('Security', 'core');
}

load_class('Router', 'core');
load_class('Input', 'core');
load_class('Lang', 'core');

require(BASEPATH . 'core/Controller.php');

function &get_instance()
{
    return CI_Controller::get_instance();
}

$class    = 'CI_Controller';
$instance = new $class();

$fd = fopen('php://stdin', 'r');

$input = '';

while (!feof($fd)) {
    $input .= fread($fd, 1024);
}

fclose($fd);

require_once(APPPATH . 'hooks/InitHook.php');

_app_init_load();

$instance->load->model('tickets_model');
$instance->load->helper('files');
$instance->load->helper('func');
$instance->load->helper('misc');
$instance->load->helper('database');

$mailParser = new \ZBateson\MailMimeParser\MailMimeParser();
$message    = $mailParser->parse($input);

$body = $message->getHtmlContent();

if (! $body) {
    $body = $message->getTextContent();
}

$body = trim($body);

if (! $body) {
    $body = 'No message found.';
}

$attachments     = [];
$mailAttachments = $message->getAllAttachmentParts();

foreach ($mailAttachments as $attachment) {
    $filename = $attachment->getFilename();
    $content  = $attachment->getContent();

    if (!$filename || !$content) {
        continue;
    }

    $attachments[] = [
        'data'     => $content,
        'filename' => sanitize_file_name($filename),
    ];
}

$subject   = $message->getHeaderValue('subject');
$fromemail = $message->getHeaderValue('from');
$fromname  = '';

if ($fromHeader = $message->getHeader('from')) {
    $fromname = $fromHeader->getPersonName();
}

if (empty($fromname)) {
    $fromname = $fromemail;
}

if ($reply_to = $message->getHeaderValue('reply-to')) {
    $fromemail = $reply_to;
}

$cc       = [];
$toemails = [];
foreach (['to', 'cc', 'bcc'] as $checkHeader) {
    $addreses = $message->getHeader($checkHeader);

    if ($addreses) {
        foreach ($addreses->getAddresses() as $addr) {
            $toemails[] = $addr->getEmail();
            if ($checkHeader === 'cc') {
                $cc[] = $addr->getEmail();
            }
        }
    }
}

$to = implode(',', $toemails);

if (class_exists('EmailReplyParser\EmailReplyParser')
    && get_option('ticket_import_reply_only') === '1'
    && (mb_substr_count($subject, 'FWD:') == 0 && mb_substr_count($subject, 'FW:') == 0)) {
    $parsedBody = \EmailReplyParser\EmailReplyParser::parseReply($body);

    $parsedBody = trim($parsedBody);

    // For some emails this is causing an issue and not returning the email, instead is returning empty string
    // In this case, only use parsed email reply if not empty
    if (!empty($parsedBody)) {
        $body = $parsedBody;
    }
}

$body = trim($body);
$body = str_replace('&nbsp;', ' ', $body);
$body = trim(remove_html_invisible_tags($body));
$body = preg_replace('/^<html[^>]*>/', '', $body);
$body = preg_replace('/.*<body[^>]*>(.*?)<\/body>.*/is', '$1', $body);
$body = trim($body);

// Remove duplicate new lines
$body = preg_replace("/[\r\n]+/", "\n", $body);
// new lines with <br />
$body = preg_replace('/\n(\s*\n)+/', '<br />', $body);
$body = preg_replace('/\n/', '<br>', $body);

$instance->tickets_model->insert_piped_ticket([
    'to'          => $to,
    'cc'          => $cc,
    'fromname'    => $fromname,
    'email'       => $fromemail,
    'subject'     => $subject,
    'body'        => $body,
    'attachments' => $attachments,
]);
