/* * This file is a part of Winix * and is not publicly distributed * * Copyright (c) 2008-2010, Tomasz Sowa * All rights reserved. * */ #include #include #include "log.h" #include "notify.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; void Notify::SetRequest(Request * prequest) { request = prequest; } void Notify::SetConfig(Config * pconfig) { config = pconfig; } void Notify::SetSystem(System * psystem) { system = psystem; } void Notify::SetTemplatesNotify(TemplatesNotify * ptemplates_notify) { templates_notify = ptemplates_notify; } /* 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::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 ; iRead(); 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 ; adir_tab.size() ; ++a) { dir += request->dir_tab[a]->url; dir += '/'; } } void Notify::CreateItemLink(std::string & link) { link = config->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 = system->mounts.pmount->type; n.doc_base_url = config->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=system->users.Begin() ; i != system->users.End() ; ++i) { sending = false; if( system->mounts.pmount->type == Mount::thread ) { if( (i->thread_notify & notify_code) != 0 ) sending = true; } else if( system->mounts.pmount->type == Mount::cms ) { if( (i->cms_notify & notify_code) != 0 ) sending = true; } if( sending ) { n.email = i->email; n.lang = Locale::StrToLang(config->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(); }