<?php
/*
 * Copyright (c) 2013, webvariants GbR, http://www.webvariants.de
 *
 * This file is released under the terms of the MIT license. You can find the
 * complete text in the attached LICENSE file or online at:
 *
 * http://www.opensource.org/licenses/mit-license.php
 */

abstract class WV_Mail {
	/**
	 * eMail-Adresse kodieren
	 *
	 * Diese Funktion kodiert eine eMail-Adresse derartig, dass sie im Browser
	 * noch normal angezeigt wird, für Harvester aber (hoffentlich) nicht mehr
	 * zu erkennen ist. Mittels der nospammail.js kann das erzeugte HTML
	 * beim Mouseover direkt in einen echten mailto-Link umgewandelt werden.
	 *
	 * @param  string $email  mail adress to protect
	 * @param  string $title  optional title, will be used as linktext
	 * @return string         human readable mail-adress, will be converted into hyperlink via javascript
	 */
	public static function getSpamProtectedMail($email, $title = '', $classes = '') {
		if (mb_strlen($email) === 0) return '';

		$dispatcher = sly_Core::dispatcher();

		try {
			$result = $dispatcher->filter('WV_MAIL_SPAMPROTECT', null, compact('email', 'title', 'classes'));
		}
		catch (Exception $e) {
			// go next
		}

		if (!isset($result)) {
			// foo@bar[.com] => foo AT bar[ DOT com]
			if (preg_match('#(.+)@(.+?)(?:\.([a-zA-Z]{2,}))?$#', $email, $match)) {
				$user   = $match[1];
				$host   = $match[2];
				$frmt   = isset($match[3]) ? '%s AT %s DOT %s' : '%s AT %s';
				$result = sprintf('<span class="liam%s">'.$frmt.'</span>', $classes ? ' '.trim($classes) : '', $user, $host, isset($match[3]) ? $match[3] : '');
			}
			else {
				$result = $email;
			}
		}

		return $result;
	}

	private static function buildProtectedMail($email, $title, $attr) {
		preg_match('#class="([^"]*)"#ie', stripslashes($attr), $match);
		$classes = !empty($match) ? ' '.$match[1] : '';

//		ignore title attribute due to lacking functionality in mapson
//		preg_match('#title="([^"]*)"#ie', stripslashes($attr), $match);
//		$title = !empty($match) ? $match[1] : $title;

		return self::getSpamProtectedMail($email, $title, $classes);
	}

	public static function protectEmailInHtml($html) {
		if (!sly_Core::isBackend()) {
			return preg_replace(
				'~<a ([^>]*)href="mailto:([^"]+)"([^>]*)>([^<]+)</a>~ie',
				"WV_Mail::buildProtectedMail('\$2', '\$4', '\$1 \$3')",
				$html
			);
		}

		return $html;
	}

	public static function isValid($email) {
		return sly_Mail::isValid($email);
	}

	public static function splitAddress($address) {
		if (sly_Mail::isValid($address)) {
			return array('address' => $address, 'name' => '');
		}

		if (preg_match('#^([^\x00-\x1F]+) <(.+?)>$#', $address, $match)) {
			return array('address' => $match[2], 'name' => $match[1]);
		}

		return null;
	}

	/**
	 * Prüft eine eMail-Adresse auf syntaxktische Korrektheit
	 *
	 * Akzeptiert die folgenden Formate:
	 *
	 *  * foobar@example.com
	 *  * Name <foobar@example.com>
	 *  * "Name" <foobar@example.com>
	 *
	 * Bei Erfolg wird die eMail-Adresse (foobar@example.com) zurückgegeben,
	 * ansonsten false.
	 *
	 * @return mixed  false im Fehlerfall, sonst die eMail-Adresse
	 */
	public static function isValidEx($address) {
		$parts = self::splitAddress($address);
		return ($parts && sly_Mail::isValid($parts['address'])) ? $parts['address'] : false;
	}

	public static function sendMail($from, $fromName, $to, $toName, $subject, $body, $contentType = 'text/plain', $encoding = 'UTf-8', $strict = false, $headers = array(), $params = '') {
		// Alle lower-ASCII-Zeichen (inkl. Newlines, netterweise) entfernen

		$from     = preg_replace('#[\x00-\x1F]#', '', $from);
		$fromName = preg_replace('#[\x00-\x1F]#', '', $fromName);
		$to       = preg_replace('#[\x00-\x1F]#', '', $to);
		$toName   = preg_replace('#[\x00-\x1F]#', '', $toName);
		$subject  = preg_replace('#[\x00-\x1F]#', '', $subject);

		$from     = trim($from);
		$fromName = trim($fromName);
		$to       = trim($to);
		$toName   = trim($toName);
		$subject  = trim($subject);
		$body     = trim($body);

		// Empfänger und Absender auf syntaktische Korrektheit prüfen

		if (!self::isValidEx($from)) {
			throw new WV_Exception_Mail(t('devutils_mail_invalid_from'));
		}

		if (!self::isValidEx($to)) {
			throw new WV_Exception_Mail(t('devutils_mail_invalid_to'));
		}

		// Strict-Modus: Keine leeren eMails zulassen

		if ($strict && empty($subject)) {
			throw new WV_Exception_Mail(t('devutils_mail_empty_subject'));
		}

		if ($strict && empty($body)) {
			throw new WV_Exception_Mail(t('devutils_mail_empty_body'));
		}

		// sly_Mail erstellen

		$mail = sly_Mail::factory();
		$mail->setContentType($contentType);
		$mail->setCharset($encoding);
		$mail->setSubject($subject);
		$mail->setFrom($from, empty($fromName) ? null : $fromName);
		$mail->addTo($to, empty($toName) ? null : $toName);
		$mail->setBody($body);

		// Header und Parameter setzen

		foreach ($headers as $key => $value) {
			$mail->addHeader($key, $value);
		}

		// Und ab dafür!

		try {
			return $mail->send();
		}
		catch (Exception $e) {
			// callers expect a WV_Exception_Mail
			throw new WV_Exception_Mail(t('devutils_mail_error'));
		}
	}
}
