summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile4
-rw-r--r--src/core/ns_register.c40
-rw-r--r--src/core/ns_resetpass.c80
-rw-r--r--src/core/ns_sendpass.c43
-rw-r--r--src/mail.c283
-rw-r--r--src/mail.cpp151
-rw-r--r--src/memoserv.c29
-rw-r--r--src/threadengine_pthread.cpp24
-rw-r--r--src/threadengine_win32.cpp24
9 files changed, 258 insertions, 420 deletions
diff --git a/src/Makefile b/src/Makefile
index 3e66abc3d..c82f9f5b4 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -9,7 +9,7 @@ INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \
../include/messages.h ../include/services.h \
../include/timers.h ../include/extern.h \
../include/modules.h ../include/slist.h ../include/hashcomp.h \
- ../include/threadengine.h
+ ../include/threadengine.h ../include/mail.h
MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \
'LDFLAGS=${LDFLAGS}' 'INSTDIR=${INSTDIR}' 'INSTALL=${INSTALL}' \
@@ -51,7 +51,7 @@ ircd.o: ircd.c $(INCLUDES)
hostserv.o: hostserv.c $(INCLUDES)
language.o: language.c $(INCLUDES)
log.o: log.c $(INCLUDES)
-mail.o: mail.c $(INCLUDES)
+mail.o: mail.cpp $(INCLUDES)
main.o: main.c $(INCLUDES)
memory.o: memory.c $(INCLUDES)
memoserv.o: memoserv.c $(INCLUDES)
diff --git a/src/core/ns_register.c b/src/core/ns_register.c
index 9074f109f..89495eb57 100644
--- a/src/core/ns_register.c
+++ b/src/core/ns_register.c
@@ -14,7 +14,7 @@
#include "module.h"
-int do_sendregmail(User *u, NickRequest *nr);
+static bool SendRegmail(User *u, NickRequest *nr);
class CommandNSConfirm : public Command
{
@@ -279,7 +279,7 @@ class CommandNSRegister : public CommandNSConfirm
FOREACH_MOD(I_OnMakeNickRequest, OnMakeNickRequest(nr));
if (Config.NSEmailReg)
{
- if (!do_sendregmail(u, nr))
+ if (SendRegmail(u, nr))
{
notice_lang(Config.s_NickServ, u, NICK_ENTER_REG_CODE, email, Config.s_NickServ);
Alog() << Config.s_NickServ << ": sent registration verification code to " << nr->email;
@@ -337,7 +337,7 @@ class CommandNSResend : public Command
notice_lang(Config.s_NickServ, u, MAIL_LATER);
return MOD_CONT;
}
- if (!do_sendregmail(u, nr))
+ if (!SendRegmail(u, nr))
{
nr->lastmail = time(NULL);
notice_lang(Config.s_NickServ, u, NICK_REG_RESENT, nr->email);
@@ -375,6 +375,7 @@ class NSRegister : public Module
ModuleManager::Attach(I_OnNickServHelp, this);
}
+
void OnNickServHelp(User *u)
{
notice_lang(Config.s_NickServ, u, NICK_HELP_CMD_REGISTER);
@@ -386,33 +387,14 @@ class NSRegister : public Module
}
};
-/*************************************************************************/
-
-int do_sendregmail(User *u, NickRequest *nr)
+static bool SendRegmail(User *u, NickRequest *nr)
{
- MailInfo *mail = NULL;
- char buf[BUFSIZE];
-
- if (!nr && !u)
- return -1;
- snprintf(buf, sizeof(buf), getstring(NICK_REG_MAIL_SUBJECT), nr->nick);
- mail = MailRegBegin(u, nr, buf, Config.s_NickServ);
- if (!mail)
- return -1;
- fprintf(mail->pipe, "%s", getstring(NICK_REG_MAIL_HEAD));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(NICK_REG_MAIL_LINE_1), nr->nick);
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(NICK_REG_MAIL_LINE_2), Config.s_NickServ, nr->passcode.c_str());
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", getstring(NICK_REG_MAIL_LINE_3));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", getstring(NICK_REG_MAIL_LINE_4));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(NICK_REG_MAIL_LINE_5), Config.NetworkName);
- fprintf(mail->pipe, "\n.\n");
- MailEnd(mail);
- return 0;
+ char subject[BUFSIZE], message[BUFSIZE];
+
+ snprintf(subject, sizeof(subject), getstring(NICK_REG_MAIL_SUBJECT), nr->nick);
+ snprintf(message, sizeof(message), getstring(NICK_REG_MAIL), nr->nick, Config.NetworkName, Config.s_NickServ, nr->passcode.c_str(), Config.NetworkName);
+
+ return Mail(u, nr, Config.s_NickServ, subject, message);
}
MODULE_INIT(NSRegister)
diff --git a/src/core/ns_resetpass.c b/src/core/ns_resetpass.c
index c47fa0308..fc904d66c 100644
--- a/src/core/ns_resetpass.c
+++ b/src/core/ns_resetpass.c
@@ -14,6 +14,8 @@
#include "module.h"
+static bool SendResetEmail(User *u, NickAlias *na);
+
class CommandNSResetPass : public Command
{
public:
@@ -33,41 +35,11 @@ class CommandNSResetPass : public Command
notice_lang(Config.s_NickServ, u, NICK_X_FORBIDDEN, na->nick);
else
{
- char buf[BUFSIZE], message[BUFSIZE];
- snprintf(buf, sizeof(buf), getstring(na, NICK_RESETPASS_SUBJECT), na->nick);
-
- MailInfo *mail = MailBegin(u, na->nc, buf, Config.s_NickServ);
- if (!mail)
- return MOD_CONT;
-
- char passcode[20];
- int min = 1, max = 62;
- int chars[] = {
- ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
- 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
- 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
- };
-
- int idx;
- for (idx = 0; idx < 20; ++idx)
- passcode[idx] = chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
- passcode[idx] = '\0';
-
- snprintf(message, sizeof(message), getstring(na, NICK_RESETPASS_MESSAGE), na->nick, Config.s_NickServ, passcode, Config.NetworkName);
- fprintf(mail->pipe, "%s", message);
- fprintf(mail->pipe, "\n.\n");
- MailEnd(mail);
-
- na->nc->Shrink("ns_resetpass_code");
- na->nc->Shrink("ns_resetpass_time");
-
- na->nc->Extend("ns_resetpass_code", new ExtensibleItemPointerArray<char>(sstrdup(passcode)));
- na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(time(NULL)));
-
- Alog() << Config.s_NickServ << ": " << u->GetMask() << " used RESETPASS on " << na->nick << " (" << na->nc->display << ")";
- notice_lang(Config.s_NickServ, u, NICK_RESETPASS_COMPLETE, na->nick);
+ if (SendResetEmail(u, na))
+ {
+ Alog() << Config.s_NickServ << ": " << u->GetMask() << " used RESETPASS on " << na->nick << " (" << na->nc->display << ")";
+ notice_lang(Config.s_NickServ, u, NICK_RESETPASS_COMPLETE, na->nick);
+ }
}
return MOD_CONT;
@@ -110,14 +82,13 @@ class NSResetPass : public Module
EventReturn OnPreCommand(User *u, const std::string &service, const ci::string &command, const std::vector<ci::string> &params)
{
- time_t t;
- char *c;
-
if (service == Config.s_NickServ && command == "CONFIRM" && !params.empty())
{
NickAlias *na = findnick(u->nick);
- if (na && na->nc->GetExtArray("ns_resetpass_code", c) && na->nc->GetExtRegular<time_t>("ns_resetpass_time", t))
+ time_t t;
+ std::string c;
+ if (na && na->nc->GetExtRegular("ns_resetpass_code", c) && na->nc->GetExtRegular("ns_resetpass_time", t))
{
if (t < time(NULL) - 3600)
{
@@ -167,4 +138,35 @@ class NSResetPass : public Module
}
};
+static bool SendResetEmail(User *u, NickAlias *na)
+{
+ char subject[BUFSIZE], message[BUFSIZE], passcode[20];
+
+ snprintf(subject, sizeof(subject), getstring(na, NICK_RESETPASS_SUBJECT), na->nick);
+
+ int min = 1, max = 62;
+ int chars[] = {
+ ' ', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
+ 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
+ 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+ 'Z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
+ };
+
+ int idx;
+ for (idx = 0; idx < 20; ++idx)
+ passcode[idx] = chars[1 + static_cast<int>((static_cast<float>(max - min)) * getrandom16() / 65536.0) + min];
+ passcode[idx] = '\0';
+
+ snprintf(message, sizeof(message), getstring(na, NICK_RESETPASS_MESSAGE), na->nick, Config.s_NickServ, passcode, Config.NetworkName);
+
+ na->nc->Shrink("ns_resetpass_code");
+ na->nc->Shrink("ns_resetpass_time");
+
+ na->nc->Extend("ns_resetpass_code", new ExtensibleItemRegular<std::string>(passcode));
+ na->nc->Extend("ns_resetpass_time", new ExtensibleItemRegular<time_t>(time(NULL)));
+
+ return Mail(u, na->nc, Config.s_NickServ, subject, message);
+}
+
MODULE_INIT(NSResetPass)
diff --git a/src/core/ns_sendpass.c b/src/core/ns_sendpass.c
index 0ce8f6c5c..ffa4b6ece 100644
--- a/src/core/ns_sendpass.c
+++ b/src/core/ns_sendpass.c
@@ -14,6 +14,8 @@
#include "module.h"
+static bool SendPassMail(User *u, NickAlias *na, const std::string &pass);
+
class CommandNSSendPass : public Command
{
public:
@@ -34,34 +36,14 @@ class CommandNSSendPass : public Command
notice_lang(Config.s_NickServ, u, NICK_X_FORBIDDEN, na->nick);
else
{
- char buf[BUFSIZE];
std::string tmp_pass;
if (enc_decrypt(na->nc->pass,tmp_pass) == 1)
{
- MailInfo *mail;
-
- snprintf(buf, sizeof(buf), getstring(na, NICK_SENDPASS_SUBJECT), na->nick);
- mail = MailBegin(u, na->nc, buf, Config.s_NickServ);
- if (!mail)
- return MOD_CONT;
-
- fprintf(mail->pipe, "%s", getstring(na, NICK_SENDPASS_HEAD));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_1), na->nick);
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_2), tmp_pass.c_str());
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", getstring(na, NICK_SENDPASS_LINE_3));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", getstring(na, NICK_SENDPASS_LINE_4));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, getstring(na, NICK_SENDPASS_LINE_5), Config.NetworkName);
- fprintf(mail->pipe, "\n.\n");
-
- MailEnd(mail);
-
- Alog() << Config.s_NickServ << ": " << u->GetMask() << " used SENDPASS on " << nick;
- notice_lang(Config.s_NickServ, u, NICK_SENDPASS_OK, nick);
+ if (SendPassMail(u, na, tmp_pass))
+ {
+ Alog() << Config.s_NickServ << ": " << u->GetMask() << " used SENDPASS on " << nick;
+ notice_lang(Config.s_NickServ, u, NICK_SENDPASS_OK, nick);
+ }
}
else
notice_lang(Config.s_NickServ, u, NICK_SENDPASS_UNAVAILABLE);
@@ -102,10 +84,21 @@ class NSSendPass : public Module
ModuleManager::Attach(I_OnNickServHelp, this);
}
+
void OnNickServHelp(User *u)
{
notice_lang(Config.s_NickServ, u, NICK_HELP_CMD_SENDPASS);
}
};
+static bool SendPassMail(User *u, NickAlias *na, const std::string &pass)
+{
+ char subject[BUFSIZE], message[BUFSIZE];
+
+ snprintf(subject, sizeof(subject), getstring(na, NICK_SENDPASS_SUBJECT), na->nick);
+ snprintf(message, sizeof(message), getstring(na, NICK_SENDPASS), na->nick, pass.c_str(), Config.NetworkName);
+
+ return Mail(u, na->nc, Config.s_NickServ, subject, message);
+}
+
MODULE_INIT(NSSendPass)
diff --git a/src/mail.c b/src/mail.c
deleted file mode 100644
index ef3d6cd4d..000000000
--- a/src/mail.c
+++ /dev/null
@@ -1,283 +0,0 @@
-/* Mail utility routines.
- *
- * (C) 2003-2010 Anope Team
- * Contact us at team@anope.org
- *
- * Please read COPYING and README for further details.
- *
- * Based on the original code of Epona by Lara.
- * Based on the original code of Services by Andy Church.
- *
- *
- */
-
-#include "services.h"
-#include "language.h"
-
-/*************************************************************************/
-
-/**
- * Begins to send a mail. Must be followed by a MailEnd call.
- * Returns NULL if the call failed. Error messages are
- * automatically sent to the user.
- * @param u the User struct
- * @param nr NickReqest Struct
- * @param subject Subject of the email
- * @param service Service to respond with
- * @return MailInfo struct
- */
-MailInfo *MailRegBegin(User * u, NickRequest * nr, char *subject,
- char *service)
-{
- int timeToWait = 0;
- if (!u || !nr || !subject || !service) {
- return NULL;
- }
-
- if (!Config.UseMail) {
- notice_lang(service, u, MAIL_DISABLED);
- } else if ((time(NULL) - u->lastmail < Config.MailDelay)) {
- timeToWait = Config.MailDelay - (time(NULL) - u->lastmail);
- notice_lang(service, u, MAIL_DELAYED, timeToWait);
- } else if (!nr->email) {
- notice_lang(service, u, MAIL_INVALID, nr->nick);
- } else {
- MailInfo *mail;
-
- mail = new MailInfo;
- mail->sender = u;
- mail->recipient = NULL;
- mail->recip = nr;
-
- if (!(mail->pipe = popen(Config.SendMailPath, "w"))) {
- delete mail;
- notice_lang(service, u, MAIL_LATER);
- return NULL;
- }
-
- fprintf(mail->pipe, "From: %s\n", Config.SendFrom);
- if (Config.DontQuoteAddresses) {
- fprintf(mail->pipe, "To: %s <%s>\n", nr->nick, nr->email);
- } else {
- fprintf(mail->pipe, "To: \"%s\" <%s>\n", nr->nick, nr->email);
- }
- fprintf(mail->pipe, "Subject: %s\n", subject);
- return mail;
- }
-
- return NULL;
-}
-
-/*************************************************************************/
-
-/**
- * Begins to send a mail. Must be followed by a MailEnd call.
- * Returns NULL if the call failed. Error messages are
- * automatically sent to the user.
- * @param u the User struct
- * @param nc NickCore Struct
- * @param subject Subject of the email
- * @param service Service to respond with
- * @return MailInfo struct
- */
-MailInfo *MailBegin(User * u, NickCore * nc, char *subject, char *service)
-{
- if (!u || !nc || !subject || !service) {
- return NULL;
- }
-
- if (!Config.UseMail) {
- notice_lang(service, u, MAIL_DISABLED);
- } else if (((time(NULL) - u->lastmail < Config.MailDelay)
- || (time(NULL) - nc->lastmail < Config.MailDelay))
- && !(u->Account() && u->Account()->IsServicesOper())) {
- notice_lang(service, u, MAIL_DELAYED, Config.MailDelay);
- } else if (!nc->email) {
- notice_lang(service, u, MAIL_INVALID, nc->display);
- } else {
- MailInfo *mail;
-
- mail = new MailInfo;
- mail->sender = u;
- mail->recipient = nc;
- mail->recip = NULL;
-
- if (!(mail->pipe = popen(Config.SendMailPath, "w"))) {
- delete mail;
- notice_lang(service, u, MAIL_LATER);
- return NULL;
- }
-
- fprintf(mail->pipe, "From: %s\n", Config.SendFrom);
- if (Config.DontQuoteAddresses) {
- fprintf(mail->pipe, "To: %s <%s>\n", nc->display, nc->email);
- } else {
- fprintf(mail->pipe, "To: \"%s\" <%s>\n", nc->display,
- nc->email);
- }
- fprintf(mail->pipe, "Subject: %s\n", subject);
-
- return mail;
- }
-
- return NULL;
-}
-
-/*************************************************************************/
-
-/**
- * new function to send memo mails
- * @param nc NickCore Struct
- * @return MailInfo struct
- */
-MailInfo *MailMemoBegin(NickCore * nc)
-{
-
- if (!nc)
- return NULL;
-
- if (!Config.UseMail || !nc->email) {
- return NULL;
-
- } else {
- MailInfo *mail;
-
- mail = new MailInfo;
- mail->sender = NULL;
- mail->recipient = nc;
- mail->recip = NULL;
-
- if (!(mail->pipe = popen(Config.SendMailPath, "w"))) {
- delete mail;
- return NULL;
- }
-
- fprintf(mail->pipe, "From: %s\n", Config.SendFrom);
- if (Config.DontQuoteAddresses) {
- fprintf(mail->pipe, "To: %s <%s>\n", nc->display, nc->email);
- } else {
- fprintf(mail->pipe, "To: \"%s\" <%s>\n", nc->display,
- nc->email);
- }
- fprintf(mail->pipe, "Subject: %s\n",
- getstring(MEMO_MAIL_SUBJECT));
- return mail;
- }
-}
-
-/*************************************************************************/
-
-/**
- * Finish to send the mail. Cleanup everything.
- * @param mail MailInfo Struct
- * @return void
- */
-void MailEnd(MailInfo * mail)
-{
- /* - param checking modified because we don't
- have an user sending this mail.
- Certus, 02.04.2004 */
-
- if (!mail || !mail->pipe) { /* removed sender check */
- return;
- }
-
- if (!mail->recipient && !mail->recip) {
- return;
- }
-
- pclose(mail->pipe);
-
- if (mail->sender) /* added sender check */
- mail->sender->lastmail = time(NULL);
-
- if (mail->recipient)
- mail->recipient->lastmail = time(NULL);
- else
- mail->recip->lastmail = time(NULL);
-
-
- delete mail;
-}
-
-/*************************************************************************/
-
-/**
- * Resets the MailDelay protection.
- * @param u the User struct
- * @param nc NickCore Struct
- * @return void
- */
-void MailReset(User * u, NickCore * nc)
-{
- if (u)
- u->lastmail = 0;
- if (nc)
- nc->lastmail = 0;
-}
-
-/*************************************************************************/
-
-/**
- * Checks whether we have a valid, common e-mail address.
- * This is NOT entirely RFC compliant, and won't be so, because I said
- * *common* cases. ;) It is very unlikely that e-mail addresses that
- * are really being used will fail the check.
- *
- * FIXME: rewrite this a bit cleaner.
- * @param email Email to Validate
- * @return int
- */
-int MailValidate(const char *email)
-{
- int has_period = 0, len;
- char copy[BUFSIZE], *domain;
-
- static char specials[] =
- { '(', ')', '<', '>', '@', ',', ';', ':', '\\', '\"', '[', ']',
- ' '
- };
-
- if (!email)
- return 0;
- strlcpy(copy, email, sizeof(copy));
-
- domain = strchr(copy, '@');
- if (!domain)
- return 0;
- *domain = '\0';
- domain++;
-
- /* Don't accept NULL copy or domain. */
- if (*copy == 0 || *domain == 0)
- return 0;
-
- /* Check for forbidden characters in the name */
- for (unsigned int i = 0; i < strlen(copy); i++) {
-
- if (copy[i] <= 31 || copy[i] >= 127)
- return 0;
- for (unsigned int j = 0; j < 13; j++)
- if (copy[i] == specials[j])
- return 0;
- }
-
- /* Check for forbidden characters in the domain, and if it seems to be valid. */
- for (int i = 0; i < (len = strlen(domain)); i++) {
- if (domain[i] <= 31 || domain[i] >= 127)
- return 0;
- for (unsigned int j = 0; j < 13; j++)
- if (domain[i] == specials[j])
- return 0;
- if (domain[i] == '.') {
- if (i == 0 || i == len - 1)
- return 0;
- has_period = 1;
- }
- }
-
- if (!has_period)
- return 0;
-
- return 1;
-}
diff --git a/src/mail.cpp b/src/mail.cpp
new file mode 100644
index 000000000..9e1c60c6b
--- /dev/null
+++ b/src/mail.cpp
@@ -0,0 +1,151 @@
+#include "services.h"
+#include "language.h"
+
+MailThread::~MailThread()
+{
+ if (Success)
+ Alog() << "Successfully delivered mail for " << MailTo << " (" << Addr << ")";
+ else
+ Alog() << "Error delivering mail for " << MailTo << " (" << Addr << ")";
+}
+
+void MailThread::Run()
+{
+ FILE *pipe = popen(Config.SendMailPath, "w");
+
+ if (!pipe)
+ {
+ return;
+ }
+
+ fprintf(pipe, "From: %s\n", Config.SendFrom);
+ if (Config.DontQuoteAddresses)
+ fprintf(pipe, "To: %s <%s>\n", MailTo.c_str(), Addr.c_str());
+ else
+ fprintf(pipe, "To: \"%s\" <%s>\n", MailTo.c_str(), Addr.c_str());
+ fprintf(pipe, "Subject: %s\n", Subject.c_str());
+ fprintf(pipe, "%s", Message.c_str());
+ fprintf(pipe, "\n.\n");
+
+ pclose(pipe);
+
+ Success = true;
+}
+
+bool Mail(User *u, NickRequest *nr, const std::string &service, const std::string &subject, const std::string &message)
+{
+ if (!u || !nr || subject.empty() || service.empty() || message.empty())
+ return false;
+
+ time_t t = time(NULL);
+
+ if (!Config.UseMail)
+ notice_lang(service.c_str(), u, MAIL_DISABLED);
+ else if (t - u->lastmail < Config.MailDelay)
+ notice_lang(service.c_str(), u, MAIL_DELAYED, t - u->lastmail);
+ else if (!nr->email)
+ notice_lang(service.c_str(), u, MAIL_INVALID, nr->nick);
+ else
+ {
+ u->lastmail = nr->lastmail = t;
+ threadEngine.Start(new MailThread(nr->nick, nr->email, subject, message));
+ return true;
+ }
+
+ return false;
+}
+
+bool Mail(User *u, NickCore *nc, const std::string &service, const std::string &subject, const std::string &message)
+{
+ if (!u || !nc || subject.empty() || service.empty() || message.empty())
+ return false;
+
+ time_t t = time(NULL);
+
+ if (!Config.UseMail)
+ notice_lang(service.c_str(), u, MAIL_DISABLED);
+ else if (t - u->lastmail < Config.MailDelay)
+ notice_lang(service.c_str(), u, MAIL_DELAYED, t - u->lastmail);
+ else if (!nc->email)
+ notice_lang(service.c_str(), u, MAIL_INVALID, nc->display);
+ else
+ {
+ u->lastmail = nc->lastmail = t;
+ threadEngine.Start(new MailThread(nc->display, nc->email, subject, message));
+ return true;
+ }
+
+ return false;
+}
+
+bool Mail(NickCore *nc, const std::string &subject, const std::string &message)
+{
+ if (!Config.UseMail || !nc || !nc->email || subject.empty() || message.empty())
+ return false;
+
+ nc->lastmail = time(NULL);
+ threadEngine.Start(new MailThread(nc->display, nc->email, subject, message));
+
+ return true;
+}
+
+/**
+ * Checks whether we have a valid, common e-mail address.
+ * This is NOT entirely RFC compliant, and won't be so, because I said
+ * *common* cases. ;) It is very unlikely that e-mail addresses that
+ * are really being used will fail the check.
+ *
+ * @param email Email to Validate
+ * @return bool
+ */
+bool MailValidate(const std::string &email)
+{
+ bool has_period = false;
+ char copy[BUFSIZE];
+
+ static char specials[] = {
+ '(', ')', '<', '>', '@', ',', ';', ':', '\\', '\"', '[', ']', ' '
+ };
+
+ if (email.empty())
+ return false;
+ strlcpy(copy, email.c_str(), sizeof(copy));
+
+ char *domain = strchr(copy, '@');
+ if (!domain)
+ return false;
+ *domain++ = '\0';
+
+ /* Don't accept NULL copy or domain. */
+ if (!*copy || !*domain)
+ return false;
+
+ /* Check for forbidden characters in the name */
+ for (unsigned int i = 0; i < strlen(copy); i++)
+ {
+ if (copy[i] <= 31 || copy[i] >= 127)
+ return false;
+ for (unsigned int j = 0; j < 13; j++)
+ if (copy[i] == specials[j])
+ return false;
+ }
+
+ /* Check for forbidden characters in the domain */
+ for (unsigned int i = 0; i < strlen(domain); i++)
+ {
+ if (domain[i] <= 31 || domain[i] >= 127)
+ return false;
+ for (unsigned int j = 0; j < 13; j++)
+ if (domain[i] == specials[j])
+ return false;
+ if (domain[i] == '.')
+ {
+ if (i == 0 || i == strlen(domain) - 1)
+ return false;
+ has_period = true;
+ }
+ }
+
+ return has_period;
+}
+
diff --git a/src/memoserv.c b/src/memoserv.c
index 5236345f9..4ab9c76ff 100644
--- a/src/memoserv.c
+++ b/src/memoserv.c
@@ -18,7 +18,7 @@
/* *INDENT-OFF* */
E void moduleAddMemoServCmds();
-static void new_memo_mail(NickCore *nc, Memo *m);
+static bool SendMemoMail(NickCore *nc, Memo *m);
E void rsend_notify(User *u, Memo *m, const char *chan);
/*************************************************************************/
@@ -300,7 +300,7 @@ void memo_send(User * u, const char *name, const char *text, int z)
/* if (MSNotifyAll) */
/* let's get out the mail if set in the nickcore - certus */
if (nc->HasFlag(NI_MEMO_MAIL))
- new_memo_mail(nc, m);
+ SendMemoMail(nc, m);
} else {
Channel *c;
@@ -356,32 +356,17 @@ int delmemo(MemoInfo * mi, int num)
/*************************************************************************/
-static void new_memo_mail(NickCore * nc, Memo * m)
+static bool SendMemoMail(NickCore *nc, Memo *m)
{
- MailInfo *mail = NULL;
+ char message[BUFSIZE];
- if (!nc || !m)
- return;
+ snprintf(message, sizeof(message), getstring(NICK_MAIL_TEXT), nc->display, m->sender.c_str(), m->number, m->text);
- mail = MailMemoBegin(nc);
- if (!mail) {
- return;
- }
- fprintf(mail->pipe, getstring(MEMO_MAIL_TEXT1), nc->display);
- fprintf(mail->pipe, "\n");
- fprintf(mail->pipe, getstring(MEMO_MAIL_TEXT2), m->sender.c_str(),
- m->number);
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", getstring(MEMO_MAIL_TEXT3));
- fprintf(mail->pipe, "\n\n");
- fprintf(mail->pipe, "%s", m->text);
- fprintf(mail->pipe, "\n");
- MailEnd(mail);
- return;
+ return Mail(nc, getstring(MEMO_MAIL_SUBJECT), message);
}
-
/*************************************************************************/
+
/* Send receipt notification to sender. */
void rsend_notify(User * u, Memo * m, const char *chan)
diff --git a/src/threadengine_pthread.cpp b/src/threadengine_pthread.cpp
index 199bd0860..9d9bf160d 100644
--- a/src/threadengine_pthread.cpp
+++ b/src/threadengine_pthread.cpp
@@ -1,14 +1,5 @@
#include "services.h"
-/** Join to the thread, sets the exit state to true
- */
-void Thread::Join()
-{
- SetExitState();
- pthread_join(Handle, NULL);
- delete this;
-}
-
/* Threadengine attributes used by this thread engine */
static pthread_attr_t threadengine_attr;
@@ -19,6 +10,11 @@ static void *entry_point(void *parameter)
{
Thread *thread = static_cast<Thread *>(parameter);
thread->Run();
+ if (!thread->GetExitState())
+ {
+ thread->Join();
+ }
+ delete thread;
pthread_exit(0);
}
@@ -39,6 +35,14 @@ ThreadEngine::~ThreadEngine()
pthread_attr_destroy(&threadengine_attr);
}
+/** Join to the thread, sets the exit state to true
+ */
+void Thread::Join()
+{
+ SetExitState();
+ pthread_join(Handle, NULL);
+}
+
/** Start a new thread
* @param thread A pointer to a newley allocated thread
*/
@@ -47,7 +51,7 @@ void ThreadEngine::Start(Thread *thread)
if (pthread_create(&thread->Handle, &threadengine_attr, entry_point, thread))
{
delete thread;
- throw CoreException("Unable to create thread");
+ throw CoreException("Unable to create thread: " + std::string(strerror(errno)));
}
}
diff --git a/src/threadengine_win32.cpp b/src/threadengine_win32.cpp
index d3c0303f5..5ee2f4596 100644
--- a/src/threadengine_win32.cpp
+++ b/src/threadengine_win32.cpp
@@ -1,14 +1,5 @@
#include "services.h"
-/** Join to the thread, sets the exit state to true
- */
-void Thread::Join()
-{
- SetExitState();
- WaitForSingleObject(Handle, INFINITE);
- delete this;
-}
-
/** Entry point for the thread
* @param paramter A Thread* cast to a void*
*/
@@ -16,6 +7,11 @@ static DWORD WINAPI entry_point(void *parameter)
{
Thread *thread = static_cast<Thread *>(parameter);
thread->Run();
+ if (!thread->GetExitState())
+ {
+ thread->Join();
+ }
+ delete thread;
return 0;
}
@@ -31,6 +27,14 @@ ThreadEngine::~ThreadEngine()
{
}
+/** Join to the thread, sets the exit state to true
+ */
+void Thread::Join()
+{
+ SetExitState();
+ WaitForSingleObject(Handle, INFINITE);
+}
+
/** Start a new thread
* @param thread A pointer to a newley allocated thread
*/
@@ -41,7 +45,7 @@ void ThreadEngine::Start(Thread *thread)
if (!thread->Handle)
{
delete thread;
- throw CoreException("Unable to create thread");
+ throw CoreException("Unable to create thread: " + std::string(dlerror()));
}
}