/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <log4cxx/net/smtpappender.h>
#include <log4cxx/level.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/helpers/optionconverter.h>
#include <log4cxx/spi/loggingevent.h>
#include <log4cxx/helpers/stringhelper.h>
#include <log4cxx/helpers/stringtokenizer.h>
#include <log4cxx/helpers/transcoder.h>
#include <log4cxx/helpers/synchronized.h>
#if !defined(LOG4CXX)
	#define LOG4CXX 1
#endif
#include <log4cxx/private/log4cxx_private.h>



#include <apr_strings.h>
#include <vector>

using namespace log4cxx;
using namespace log4cxx::helpers;
using namespace log4cxx::net;
using namespace log4cxx::spi;

#if LOG4CXX_HAVE_LIBESMTP
	#include <auth-client.h>
	#include <libesmtp.h>
#endif

namespace log4cxx
{
namespace net
{
//
//   The following two classes implement an C++ SMTP wrapper over libesmtp.
//   The same signatures could be implemented over different SMTP implementations
//   or libesmtp could be combined with libgmime to enable support for non-ASCII
//   content.

#if LOG4CXX_HAVE_LIBESMTP
/**
 *   SMTP Session.
 */
class SMTPSession
{
	public:
		/**
		*   Create new instance.
		*/
		SMTPSession(const LogString& smtpHost,
			int smtpPort,
			const LogString& smtpUsername,
			const LogString& smtpPassword,
			Pool& p) : session(0), authctx(0),
			user(toAscii(smtpUsername, p)),
			pwd(toAscii(smtpPassword, p))
		{
			auth_client_init();
			session = smtp_create_session();

			if (session == 0)
			{
				throw Exception("Could not initialize session.");
			}

			std::string host(toAscii(smtpHost, p));
			host.append(1, ':');
			host.append(p.itoa(smtpPort));
			smtp_set_server(session, host.c_str());

			authctx = auth_create_context();
			auth_set_mechanism_flags(authctx, AUTH_PLUGIN_PLAIN, 0);
			auth_set_interact_cb(authctx, authinteract, (void*) this);

			if (*user || *pwd)
			{
				smtp_auth_set_context(session, authctx);
			}
		}

		~SMTPSession()
		{
			smtp_destroy_session(session);
			auth_destroy_context(authctx);
		}

		void send(Pool& p)
		{
			int status = smtp_start_session(session);

			if (!status)
			{
				size_t bufSize = 128;
				char* buf = p.pstralloc(bufSize);
				smtp_strerror(smtp_errno(), buf, bufSize);
				throw Exception(buf);
			}
		}

		operator smtp_session_t()
		{
			return session;
		}

		static char* toAscii(const LogString& str, Pool& p)
		{
			char* buf = p.pstralloc(str.length() + 1);
			char* current = buf;

			for (LogString::const_iterator iter = str.begin();
				iter != str.end();
				iter++)
			{
				unsigned int c = *iter;

				if (c > 0x7F)
				{
					c = '?';
				}

				*current++ = c;
			}

			*current = 0;
			return buf;
		}

	private:
		SMTPSession(SMTPSession&);
		SMTPSession& operator=(SMTPSession&);
		smtp_session_t session;
		auth_context_t authctx;
		char* user;
		char* pwd;

		/**
		 *   This method is called if the SMTP server requests authentication.
		 */
		static int authinteract(auth_client_request_t request, char** result, int fields,
			void* arg)
		{
			SMTPSession* pThis = (SMTPSession*) arg;

			for (int i = 0; i < fields; i++)
			{
				int flag = request[i].flags & 0x07;

				if (flag == AUTH_USER)
				{
					result[i] = pThis->user;
				}
				else if (flag == AUTH_PASS)
				{
					result[i] = pThis->pwd;
				}
			}

			return 1;
		}


};

/**
 *  A message in an SMTP session.
 */
class SMTPMessage
{
	public:
		SMTPMessage(SMTPSession& session,
			const LogString& from,
			const LogString& to,
			const LogString& cc,
			const LogString& bcc,
			const LogString& subject,
			const LogString msg, Pool& p)
		{
			message = smtp_add_message(session);
			body = current = toMessage(msg, p);
			messagecbState = 0;
			smtp_set_reverse_path(message, toAscii(from, p));
			addRecipients(to, "To", p);
			addRecipients(cc, "Cc", p);
			addRecipients(bcc, "Bcc", p);

			if (!subject.empty())
			{
				smtp_set_header(message, "Subject", toAscii(subject, p));
			}

			smtp_set_messagecb(message, messagecb, this);
		}
		~SMTPMessage()
		{
		}

	private:
		SMTPMessage(const SMTPMessage&);
		SMTPMessage& operator=(const SMTPMessage&);
		smtp_message_t message;
		const char* body;
		const char* current;
		int messagecbState;
		void addRecipients(const LogString& addresses, const char* field, Pool& p)
		{
			if (!addresses.empty())
			{
				char* str = p.pstrdup(toAscii(addresses, p));;
				smtp_set_header(message, field, NULL, str);
				char* last;

				for (char* next = apr_strtok(str, ",", &last);
					next;
					next = apr_strtok(NULL, ",", &last))
				{
					smtp_add_recipient(message, next);
				}
			}
		}
		static const char* toAscii(const LogString& str, Pool& p)
		{
			return SMTPSession::toAscii(str, p);
		}

		/**
		 *   Message bodies can only contain US-ASCII characters and
		 *   CR and LFs can only occur together.
		 */
		static const char* toMessage(const LogString& str, Pool& p)
		{
			//
			//    count the number of carriage returns and line feeds
			//
			int feedCount = 0;

			for (size_t pos = str.find_first_of(LOG4CXX_STR("\n\r"));
				pos != LogString::npos;
				pos = str.find_first_of(LOG4CXX_STR("\n\r"), ++pos))
			{
				feedCount++;
			}

			//
			//   allocate sufficient space for the modified message
			char* retval = p.pstralloc(str.length() + feedCount + 1);
			char* current = retval;
			char* startOfLine = current;

			//
			//    iterator through message
			//
			for (LogString::const_iterator iter = str.begin();
				iter != str.end();
				iter++)
			{
				unsigned int c = *iter;

				//
				//   replace non-ASCII characters with '?'
				//
				if (c > 0x7F)
				{
					*current++ = 0x3F; // '?'
				}
				else if (c == 0x0A || c == 0x0D)
				{
					//
					//   replace any stray CR or LF with CRLF
					//      reset start of line
					*current++ = 0x0D;
					*current++ = 0x0A;
					startOfLine = current;
					LogString::const_iterator next = iter + 1;

					if (next != str.end() && (*next == 0x0A || *next == 0x0D))
					{
						iter++;
					}
				}
				else
				{
					//
					//    truncate any lines to 1000 characters (including CRLF)
					//       as required by RFC.
					if (current < startOfLine + 998)
					{
						*current++ = (char) c;
					}
				}
			}

			*current = 0;
			return retval;
		}

		/**
		 *  Callback for message.
		 */
		static const char* messagecb(void** ctx, int* len, void* arg)
		{
			*ctx = 0;
			const char* retval = 0;
			SMTPMessage* pThis = (SMTPMessage*) arg;

			//   rewind message
			if (len == NULL)
			{
				pThis->current = pThis->body;
			}
			else
			{
				// we are asked for headers, but we don't have any
				if ((pThis->messagecbState)++ == 0)
				{
					return NULL;
				}

				if (pThis->current)
				{
					*len = strlen(pThis->current);
				}

				retval = pThis->current;
				pThis->current = 0;
			}

			return retval;
		}

};
#endif

class LOG4CXX_EXPORT DefaultEvaluator :
	public virtual spi::TriggeringEventEvaluator,
	public virtual helpers::ObjectImpl
{
	public:
		DECLARE_LOG4CXX_OBJECT(DefaultEvaluator)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(DefaultEvaluator)
		LOG4CXX_CAST_ENTRY(spi::TriggeringEventEvaluator)
		END_LOG4CXX_CAST_MAP()

		DefaultEvaluator();

		/**
		Is this <code>event</code> the e-mail triggering event?
		<p>This method returns <code>true</code>, if the event level
		has ERROR level or higher. Otherwise it returns
		<code>false</code>.
		*/
		virtual bool isTriggeringEvent(const spi::LoggingEventPtr& event);
	private:
		DefaultEvaluator(const DefaultEvaluator&);
		DefaultEvaluator& operator=(const DefaultEvaluator&);
}; // class DefaultEvaluator

}
}

IMPLEMENT_LOG4CXX_OBJECT(DefaultEvaluator)
IMPLEMENT_LOG4CXX_OBJECT(SMTPAppender)

DefaultEvaluator::DefaultEvaluator()
{
}

bool DefaultEvaluator::isTriggeringEvent(const spi::LoggingEventPtr& event)
{
	return event->getLevel()->isGreaterOrEqual(Level::getError());
}

SMTPAppender::SMTPAppender()
	: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
	  evaluator(new DefaultEvaluator())
{
}

/**
Use <code>evaluator</code> passed as parameter as the
TriggeringEventEvaluator for this SMTPAppender.  */
SMTPAppender::SMTPAppender(spi::TriggeringEventEvaluatorPtr evaluator)
	: smtpPort(25), bufferSize(512), locationInfo(false), cb(bufferSize),
	  evaluator(evaluator)
{
}

SMTPAppender::~SMTPAppender()
{
	finalize();
}

bool SMTPAppender::requiresLayout() const
{
	return true;
}


LogString SMTPAppender::getFrom() const
{
	return from;
}

void SMTPAppender::setFrom(const LogString& newVal)
{
	from = newVal;
}


LogString SMTPAppender::getSubject() const
{
	return subject;
}

void SMTPAppender::setSubject(const LogString& newVal)
{
	subject = newVal;
}

LogString SMTPAppender::getSMTPHost() const
{
	return smtpHost;
}

void SMTPAppender::setSMTPHost(const LogString& newVal)
{
	smtpHost = newVal;
}

int SMTPAppender::getSMTPPort() const
{
	return smtpPort;
}

void SMTPAppender::setSMTPPort(int newVal)
{
	smtpPort = newVal;
}

bool SMTPAppender::getLocationInfo() const
{
	return locationInfo;
}

void SMTPAppender::setLocationInfo(bool newVal)
{
	locationInfo = newVal;
}

LogString SMTPAppender::getSMTPUsername() const
{
	return smtpUsername;
}

void SMTPAppender::setSMTPUsername(const LogString& newVal)
{
	smtpUsername = newVal;
}

LogString SMTPAppender::getSMTPPassword() const
{
	return smtpPassword;
}

void SMTPAppender::setSMTPPassword(const LogString& newVal)
{
	smtpPassword = newVal;
}





void SMTPAppender::setOption(const LogString& option,
	const LogString& value)
{
	if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BUFFERSIZE"), LOG4CXX_STR("buffersize")))
	{
		setBufferSize(OptionConverter::toInt(value, 512));
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("EVALUATORCLASS"), LOG4CXX_STR("evaluatorclass")))
	{
		setEvaluatorClass(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("FROM"), LOG4CXX_STR("from")))
	{
		setFrom(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPHOST"), LOG4CXX_STR("smtphost")))
	{
		setSMTPHost(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPUSERNAME"), LOG4CXX_STR("smtpusername")))
	{
		setSMTPUsername(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPASSWORD"), LOG4CXX_STR("smtppassword")))
	{
		setSMTPPassword(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SUBJECT"), LOG4CXX_STR("subject")))
	{
		setSubject(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("TO"), LOG4CXX_STR("to")))
	{
		setTo(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("CC"), LOG4CXX_STR("cc")))
	{
		setCc(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("BCC"), LOG4CXX_STR("bcc")))
	{
		setBcc(value);
	}
	else if (StringHelper::equalsIgnoreCase(option, LOG4CXX_STR("SMTPPORT"), LOG4CXX_STR("smtpport")))
	{
		setSMTPPort(OptionConverter::toInt(value, 25));
	}
	else
	{
		AppenderSkeleton::setOption(option, value);
	}
}


bool SMTPAppender::asciiCheck(const LogString& value, const LogString& field)
{
	for (LogString::const_iterator iter = value.begin();
		iter != value.end();
		iter++)
	{
		if (0x7F < (unsigned int) *iter)
		{
			LogLog::warn(field + LOG4CXX_STR(" contains non-ASCII character"));
			return false;
		}
	}

	return true;
}

/**
Activate the specified options, such as the smtp host, the
recipient, from, etc. */
void SMTPAppender::activateOptions(Pool& p)
{
	bool activate = true;

	if (layout == 0)
	{
		errorHandler->error(LOG4CXX_STR("No layout set for appender named [") + name + LOG4CXX_STR("]."));
		activate = false;
	}

	if (evaluator == 0)
	{
		errorHandler->error(LOG4CXX_STR("No TriggeringEventEvaluator is set for appender [") +
			name + LOG4CXX_STR("]."));
		activate = false;
	}

	if (smtpHost.empty())
	{
		errorHandler->error(LOG4CXX_STR("No smtpHost is set for appender [") +
			name + LOG4CXX_STR("]."));
		activate = false;
	}

	if (to.empty() && cc.empty() && bcc.empty())
	{
		errorHandler->error(LOG4CXX_STR("No recipient address is set for appender [") +
			name + LOG4CXX_STR("]."));
		activate = false;
	}

	activate &= asciiCheck(to, LOG4CXX_STR("to"));
	activate &= asciiCheck(cc, LOG4CXX_STR("cc"));
	activate &= asciiCheck(bcc, LOG4CXX_STR("bcc"));
	activate &= asciiCheck(from, LOG4CXX_STR("from"));

#if !LOG4CXX_HAVE_LIBESMTP
	errorHandler->error(LOG4CXX_STR("log4cxx built without SMTP support."));
	activate = false;
#endif

	if (activate)
	{
		AppenderSkeleton::activateOptions(p);
	}
}

/**
Perform SMTPAppender specific appending actions, mainly adding
the event to a cyclic buffer and checking if the event triggers
an e-mail to be sent. */
void SMTPAppender::append(const spi::LoggingEventPtr& event, Pool& p)
{
	if (!checkEntryConditions())
	{
		return;
	}

	LogString ndc;
	event->getNDC(ndc);
	event->getThreadName();
	// Get a copy of this thread's MDC.
	event->getMDCCopy();

	cb.add(event);

	if (evaluator->isTriggeringEvent(event))
	{
		sendBuffer(p);
	}
}

/**
This method determines if there is a sense in attempting to append.
<p>It checks whether there is a set output target and also if
there is a set layout. If these checks fail, then the boolean
value <code>false</code> is returned. */
bool SMTPAppender::checkEntryConditions()
{
#if LOG4CXX_HAVE_LIBESMTP

	if ((to.empty() && cc.empty() && bcc.empty()) || from.empty() || smtpHost.empty())
	{
		errorHandler->error(LOG4CXX_STR("Message not configured."));
		return false;
	}

	if (evaluator == 0)
	{
		errorHandler->error(LOG4CXX_STR("No TriggeringEventEvaluator is set for appender [") +
			name + LOG4CXX_STR("]."));
		return false;
	}


	if (layout == 0)
	{
		errorHandler->error(LOG4CXX_STR("No layout set for appender named [") + name + LOG4CXX_STR("]."));
		return false;
	}

	return true;
#else
	return false;
#endif
}



void SMTPAppender::close()
{
	this->closed = true;
}

LogString SMTPAppender::getTo() const
{
	return to;
}

void SMTPAppender::setTo(const LogString& addressStr)
{
	to = addressStr;
}

LogString SMTPAppender::getCc() const
{
	return cc;
}

void SMTPAppender::setCc(const LogString& addressStr)
{
	cc = addressStr;
}

LogString SMTPAppender::getBcc() const
{
	return bcc;
}

void SMTPAppender::setBcc(const LogString& addressStr)
{
	bcc = addressStr;
}

/**
Send the contents of the cyclic buffer as an e-mail message.
*/
void SMTPAppender::sendBuffer(Pool& p)
{
#if LOG4CXX_HAVE_LIBESMTP

	// Note: this code already owns the monitor for this
	// appender. This frees us from needing to synchronize on 'cb'.
	try
	{
		LogString sbuf;
		layout->appendHeader(sbuf, p);

		int len = cb.length();

		for (int i = 0; i < len; i++)
		{
			LoggingEventPtr event = cb.get();
			layout->format(sbuf, event, p);
		}

		layout->appendFooter(sbuf, p);

		SMTPSession session(smtpHost, smtpPort, smtpUsername, smtpPassword, p);

		SMTPMessage message(session, from, to, cc,
			bcc, subject, sbuf, p);

		session.send(p);

	}
	catch (std::exception& e)
	{
		LogLog::error(LOG4CXX_STR("Error occured while sending e-mail notification."), e);
	}

#endif
}

/**
Returns value of the <b>EvaluatorClass</b> option.
*/
LogString SMTPAppender::getEvaluatorClass()
{
	return evaluator == 0 ? LogString() : evaluator->getClass().getName();
}

log4cxx::spi::TriggeringEventEvaluatorPtr SMTPAppender::getEvaluator() const
{
	return evaluator;
}

void SMTPAppender::setEvaluator(log4cxx::spi::TriggeringEventEvaluatorPtr& trigger)
{
	evaluator = trigger;
}

/**
The <b>BufferSize</b> option takes a positive integer
representing the maximum number of logging events to collect in a
cyclic buffer. When the <code>BufferSize</code> is reached,
oldest events are deleted as new events are added to the
buffer. By default the size of the cyclic buffer is 512 events.
*/
void SMTPAppender::setBufferSize(int sz)
{
	this->bufferSize = sz;
	cb.resize(sz);
}

/**
The <b>EvaluatorClass</b> option takes a string value
representing the name of the class implementing the {@link
TriggeringEventEvaluator} interface. A corresponding object will
be instantiated and assigned as the triggering event evaluator
for the SMTPAppender.
*/
void SMTPAppender::setEvaluatorClass(const LogString& value)
{
	evaluator = OptionConverter::instantiateByClassName(value,
			TriggeringEventEvaluator::getStaticClass(), evaluator);
}

