winix/core/notify.cpp

266 lines
4.0 KiB
C++
Executable File

/*
* This file is a part of Winix
* and is not publicly distributed
*
* Copyright (c) 2008-2010, Tomasz Sowa
* All rights reserved.
*
*/
#include <pthread.h>
#include <unistd.h>
#include "log.h"
#include "notify.h"
#include "data.h"
#include "misc.h"
#include "request.h"
// the second thread uses this pointer to reference to 'this'
// (methods for the thread should be static)
Notify * Notify::obj;
/*
methods for the second thread
the thread can reference to 'this' by using 'obj' pointer
*/
void * Notify::ThreadRoutine(void * arg)
{
obj = (Notify*)arg;
while( true )
{
CheckQueue();
sleep(30);
}
}
void Notify::CheckQueue()
{
std::list<NotifyMsg>::iterator i = obj->notify_pool.begin();
while( i != obj->notify_pool.end() )
{
SendEmail(*i);
obj->Lock();
i = obj->notify_pool.erase(i);
obj->Unlock();
sleep(3);
}
}
void Notify::SendEmail(NotifyMsg & n)
{
TemplatesNotifyFunctions::notify_msg = &n;
obj->Lock(); // templates can be reloaded from the first thread
obj->templates_notify.Generate(n.lang);
obj->Unlock();
SendEmail(n.email, obj->templates_notify.notify_str.str());
}
void Notify::SendEmail(const std::string & email, const std::string & message)
{
nlog.PutDate(log1);
if( !ValidateEmail(email) )
{
nlog << "Notify: email: " << email << " is not correct" << logend;
return;
}
obj->command = "sendmail " + email;
FILE * sendmail = popen(obj->command.c_str(), "w");
if( !sendmail )
{
nlog << "Notify: can't run sendmail" << logend;
return;
}
SendMessage(sendmail, message);
pclose(sendmail);
nlog << "Notify: email to: " << email << " has been sent" << logend;
nlog << logsave;
}
void Notify::SendMessage(FILE * sendmail, const std::string & message)
{
for(size_t i=0 ; i<message.length() ; ++i)
{
if( message[i] == '\n' )
fprintf(sendmail, "\r\n");
else
fputc(message[i], sendmail);
}
}
/*
methods for main thread
*/
Notify::Notify() : mutex(PTHREAD_MUTEX_INITIALIZER)
{
}
Notify::~Notify()
{
}
void Notify::ReadTemplates()
{
// we are in the first thread here
// the second thread can use our templates and we must Lock()
// (the second thread is using Lock() too)
Lock();
templates_notify.Read();
Unlock();
}
bool Notify::Init()
{
templates_notify.CreateFunctions();
int t = pthread_create(&thread, 0, ThreadRoutine, (void*)this);
if( t != 0 )
{
// log (not nlog) here
log << log1 << "Notify: can't create a thread" << logend;
return false;
}
return true;
}
bool Notify::Lock()
{
if( pthread_mutex_lock(&mutex) != 0 )
return false;
return true;
}
void Notify::Unlock()
{
pthread_mutex_unlock(&mutex);
}
void Notify::CreateItemDir(std::string & dir, bool clear)
{
if( clear )
dir.clear();
for(size_t a=0 ; a<request.dir_table.size() ; ++a)
{
dir += request.dir_table[a]->url;
dir += '/';
}
}
void Notify::CreateItemLink(std::string & link)
{
link = data.base_url;
CreateItemDir(link, false);
link += request.item.url;
}
void Notify::ItemChanged(int notify_code)
{
bool sending;
Users::Iterator i;
if( notify_code == 0 )
return;
n.notify_code = notify_code;
n.current_mount_type = data.mounts.pmount->type;
n.doc_base_url = data.base_url;
CreateItemDir(n.item_dir);
CreateItemLink(n.item_link);
Lock();
try
{
// don't clear notify_pool here -- it is used (and will be cleared) by the second thread
for(i=data.users.Begin() ; i != data.users.End() ; ++i)
{
sending = false;
if( data.mounts.pmount->type == Mount::thread )
{
if( (i->thread_notify & notify_code) != 0 )
sending = true;
}
else
if( data.mounts.pmount->type == Mount::cms )
{
if( (i->cms_notify & notify_code) != 0 )
sending = true;
}
if( sending )
{
n.email = i->email;
n.lang = Locale::StrToLang(data.locale_str);// !! bedzie osobno dla kazdego uzytkownika
if( n.lang == Locale::lang_unknown )
n.lang = Locale::lang_en;
notify_pool.insert(notify_pool.end(), n);
}
}
}
catch(...)
{
Unlock();
throw;
}
Unlock();
}