<?php
/*
 * (C) Copiright 2017 IntuView Ltd.
 * www.intuview.com
 * Author: Oz Shal-Bar aziz@intuview.com
 */

class ParseEmailState
{
	public $quotChar = "", $separator = "", $inEmail = false, $escaped = false
		, $bracketChar = ""; //probably unused
}

class EmailAddress
{
	public $name = "", $email = "";
}

function parseEmailAddress($emailAddress)
{
	$state = new ParseEmailState();
	$output = [new EmailAddress()];
	$currentName = "";
	for ($ind = 0; $ind < strlen($emailAddress); $ind++)
	{
		$currElement = &getCurrElement($output);
		$currChar = $emailAddress[$ind];
		if ($state->escaped)
		{
			$currElement->name .= $currChar;
			$state->escaped = false;
		}
		else if ($currChar == "\\")
		{
			$state->escaped = true;
		}
		else
		if ($state->quotChar)
		{
			if ($currChar == $state->quotChar)
			{
				$state->inEmail = true;
				$state->quotChar = "";
			}
			else {
				$currElement->name .= $currChar;
			}
		}
		else
		if ($currChar == "'" || $currChar == '"')
		{
			appendNew($output, $state);
			$state->quotChar = $currChar;
		}
		else
		if ($currChar == "<" || $currChar == "[")
		{
			if ($currElement->email)	appendNew($output, $state);
			$state->inEmail = true;
		}
		else
		if ($currChar == ">" || $currChar == "]")
		{
			appendNew($output, $state);
		}
		else
		if ($currChar == ";")
		{
			$state->separator = ";";
			appendNew($output, $state);
		}
		else
		if ($currChar == ",")
		{
			if ($state->separator != ";" || $state->inEmail)
				appendNew($output, $state);
			else
				$currElement->name .= $currChar; //if separator is ; the commans (,) are part of names
		}
		else
		if ($state->inEmail)
		{
			if (ctype_space($currChar))
			{
				//no white spaces in email
				if ($currElement->email)
					appendNew($output, $state);
			}
			else
			{
				$currElement->email .= $currChar;
			}
		}
		else
		if ($currChar == "@")
		{
			if (!$state->inEmail)
			{
				$currElement->email = $currElement->name;
				$currElement->name = "";
				$state->inEmail = true;
			}
			$currElement->email .= $currChar;
		}
		else
			$currElement->name .= $currChar;
	}
	$output = array_filter($output, function($a){return $a->name || $a->email;});
	return $output;
}

function appendNew(&$output, ParseEmailState &$state)
{
	$state->inEmail = false;
	$state->bracketChar = $state->quotChar = "";
	
	$currElement = &getCurrElement($output);
	$currElement->name = trim($currElement->name);
	$currElement->email = trim($currElement->email);
	//if empty - don't append
	if (!$currElement->name && !$currElement->email)
		return;
	
	$output[] = new EmailAddress();
}

function &getCurrElement(&$output) //:  EmailAddress //TODO: uncomment when switching to PHP 7
{
	return $output[count($output)-1];
}

function testParseEmailAddress()
{
	$samples = [
		"judy lotz <j.lots@there.com>, J. R. holding [jrh@b.c]",
		"morry@j.c;allen, george <ag@ag.ag>; 'holding\" a' [h@ab.c];;;",
		"\"alley's home\" alleys-home@goo.gle",
		"hello anybody"
	];
	foreach ($samples as $sample)
	{
		echo "\r\n<BR/>\r\n$sample: ";
		print_r(parseEmailAddress($sample));
	}
}

function fetchEmailData($mysqli, $id, $contents, $line, $emailid, $parentFolderId){
    //incase its in PDF format - fetch the content of email
    $ext = strtolower(pathinfo($line, PATHINFO_EXTENSION));
    
    //WARNING: dont use this yet
    $emailArr = array(
        "from_field" => "from",
        "to_field" => "to",
        "cc_field" => "cc",
        "bcc_field" => "bcc"
    );
    
    //extract email files (from/to/...)
    $emailData = parseEmail(str_replace("\xEF\xBB\xBF",'', $contents), $ext, $emailArr);
    
    if ($emailData && $emailData["headers"])
    {
        //get emmail id's
        if ($emailid != 0){
            $sql = "SELECT id,filename FROM files WHERE parentFolderId=$parentFolderId ";
            $res = sqlQuery($mysqli, $sql);
            $emailidArr = array();
            while ($row = $res->fetch_object()){
                $curr_id = $row->id;
                $curr_name = $row->filename;
                
                //if it's a list of emails in same folder - than skip
                if($curr_id !== $id &&  in_array($ext, ['split','original'])){
                    continue;
                }
                else{
                    $emailidArr[$row->id] = $row->id;
                }
            }
        }
        else
        {
            //for demo enron emails - take only the file id
            $emailidArr = [ $id =>  $id];
        }
        $date = parseDate(array_key_exists("date", $emailData["headers"])? $emailData["headers"]["date"] : $emailData["headers"]["received"] ?? "");
        if ($date == NULL)
        {
            write_to_log("ERROR", "no date found in email $emailid"); //changed it since the data itself was too big
        }
        
        $parseEmails = true;//function_exists('imap_rfc822_parse_adrlist');
        
        foreach ($emailArr as $k => $e_val){
            $val = isset($emailData["headers"][$e_val]) ? trim($emailData["headers"][$e_val]) : null;
            if (empty($e_val))
                continue;
                
                
                $valArr = [];
                $additionalFields = "";
                
                $additionalFields = ", display_name, email";
                $valArr = parseEmailAddress($val);
                
                foreach ($emailidArr as $v){
                    
                    $sql = "INSERT INTO $k (docId,value$additionalFields) VALUES ";
                    
                    $vValArr = [];
                    foreach ($valArr as $valItem)
                    {
                        $values = "(\"$v\", ";
                        if ($parseEmails && (is_object($valItem) || is_array($valItem)))
                        {
                            
                            $display_name = $valItem->name;
                            $email = $valItem->email;
                            $emailValue = empty($display_name)? $email : $display_name;
                            $values .= "\"" . toDbString($mysqli, trim($emailValue)) . "\"";
                            $values .= ", \"" . toDbString($mysqli, $display_name) . "\"";
                            $values .= ", \"" . toDbString($mysqli, $email) . "\"";
                        }
                        else
                        {
                            write_to_log("ERROR", "Expected valItem to be an array: " . print_r($valItem, true));
                            $vValArr = [];
                            break;
                            //obsolete
                            $values .= "\"" . toDbString($mysqli, trim($valItem)) . "\"";
                        }
                        
                        $values .= ")";
                        $vValArr[] = $values;
                    }
                    if (empty($vValArr))
                    {
                        write_to_log("INFO", "doc $id: No values were inserted for $k: $val");
                        continue;
                    }
                    
                    $sql .= join(", ", array_unique($vValArr));
                    
                    $res = sqlQuery($mysqli, $sql);
                }
        }
        foreach ($emailidArr as $v){
            $sql = "INSERT INTO emailid (docId,value) VALUES (\"$v\",\"$emailid\")";
            sqlQuery($mysqli, $sql);
            if (!empty($date)){
                $sql = "INSERT INTO date_field (docId,value) VALUES (\"$v\",\"$date\")";
                $res = sqlQuery($mysqli, $sql);
            }
            //handle subject_field separately
            if (array_key_exists("subject", $emailData["headers"]))
            {
                $escapedSubject = toDbString($mysqli, $emailData["headers"]["subject"]);
                $sql = "INSERT INTO subject_field (docId,value)	VALUES (\"$v\",\"$escapedSubject\")";
                sqlQuery($mysqli, $sql);
            }
            
        }
        
    }
    return $emailData;
}


//for testing - uncomment this line and open in browser
//testParseEmailAddress();

?>