--- innwebd/innd.cpp 2004/06/25 07:01:51 1.1 +++ innwebd/innd.cpp 2004/07/04 08:04:08 1.7 @@ -1,10 +1,10 @@ /*******************************************************/ /* */ -/* LeafOK Innd */ +/* LeafOK Innbbsd */ /* Copyright (C) LeafOK.com, 2003-2004 */ /* */ /* Programmed by Leaf */ -/* E-mail:leaf@leafok.com QQ:6049044 */ +/* E-mail:leaflet@leafok.com QQ:6049044 */ /* */ /* http://bbs.leafok.com */ /* http://bbs.leafok.net */ @@ -12,84 +12,389 @@ /* */ /*******************************************************/ -// innd.cpp : 定义控制台应用程序的入口点。 -// - -#include "stdafx.h" -#include "afxsock.h" +#include "StdAfx.h" #include ".\innd.h" -#include ".\nntp_log.h" -#include ".\innd_service.h" -#include ".\bbs_fun.h" - -#ifdef _DEBUG -#define new DEBUG_NEW -#endif +#include ".\base_active.h" +#include ".\App_common.h" +using namespace std; -// 唯一的应用程序对象 +bool innd::thread_terminate = true; -CWinApp theApp; +innd::innd(void) +{ +} -using namespace std; +innd::~innd(void) +{ +} -int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) +int innd::Accept(void) { - // 初始化 MFC 并在失败时显示错误 - if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0)) + CString out,cmd; + char temp[256]; + + try { - // TODO: 更改错误代码以符合您的需要 - _tprintf(_T("致命错误: MFC 初始化失败\n")); - return 1; + out.Format("200 %s ready.",App_common::GetVersion()); + this->s_send(out); + while(!this->thread_terminate) + { + this->GetParentThread()->GetThreadPool()->SetThreadStatus(GetCurrentThreadId(),thread_pool::S_WAITING); + + if (this->s_receive(out) == 0) //Connection closed + break; + out.Trim(); + + this->GetParentThread()->GetThreadPool()->SetThreadStatus(GetCurrentThreadId(),thread_pool::S_WORKING); + + syslog << logfile::log_head << "Cmd: " << out << endl; + + if (sscanf(out,"%20s",temp) ==1) + cmd = strupr(temp); + else + cmd = ""; + + if (cmd == "") //Blank command + continue; + + if (cmd == "MODE") + { + if (sscanf(out,"%*s %20s",temp) ==1) + cmd = strupr(temp); + else + cmd = ""; + cmd.Trim(); + + if (cmd == "READER" || cmd == "STREAM") + { + if (cmd == "READER") + { + out.Format("200 %s ready .",App_common::GetVersion()); + this->s_send(out); + } + if (cmd == "STREAM") + { + this->s_send("203 StreamOK."); + } + } + else + { + this->s_send("501 reader"); + } + continue; + } + + if (cmd == "LIST") + { + this->cmd_list(); + continue; + } + + if (cmd == "IHAVE") + { + if (sscanf(out,"%*s %255s",temp) == 1) + cmd = strupr(temp); + else + cmd = ""; + cmd.Trim(); + + if (cmd != "" && cmd.Left(1) == "<" && cmd.Right(1) == ">") + { + if (this->access.ihave) + this->cmd_ihave(out); + else + this->s_send("480 Transfer permission denied"); + } + else + { + this->s_send("501 Message-ID"); + } + continue; + } + + if (cmd == "QUIT") + { + this->s_send("205 .\r\n"); + break; + } + + this->s_send("500 What?"); + } + } + catch(CException* e) + { + syslog << logfile::log_head << "Error in accept()" << endl; + e->Delete(); + return -1; } - // TODO: 在此处为应用程序的行为编写代码。 + return 0; +} + +innd* innd::new_client(void) +{ + return (new innd()); +} + +bool innd::IsShutdown(void) +{ + return this->thread_terminate; +} + +int innd::cmd_list(void) +{ + CRecordset RS(&(this->Db)); + CDBVariant dbVar; + CString sql,group,out; + long art_begin,art_end; + bool p; + + try + { + this->s_send("215 Newsgroups(group last first p)"); - // System settings - const char* log_file = _T("innd.log"); + sql = "select * from innd_conf order by `group`"; - nntp_log::nlog.open(log_file,ios_base::out | ios_base::app); + RS.Open(CRecordset::snapshot,sql,CRecordst::forwardOnly | CRecordset::readOnly); + while(!RS.IsEEOF()) + { + RS.GetFieldValue("group",dbVar,SQL_C_CHAR); + group = *(dbVar.m_pstring); + art_begin = 1; + art_end = 0;; + RS.GetFieldValue("in",dbVar,SQL_C_SSHORT); + p = (dbVar.m_iVal!=0); + out.Format("%s %.10ld %.10ld %c",group,art_end,art_begin,(p?'y':'n')); + this->s_send(out); + RS.MoveNext(); + } + RS.Close(); - if(!AfxSocketInit()) + this->s_send("."); + } + catch(CException* e) { - nntp_log::nlog << "Sockets init failed" << endl; - return 3; + syslog << logfile::log_head << "Error in cmd_list()" << endl; + e->Delete(); + return -1; } - // Create the service object - innd_service innd_srv; + return 0; +} - CString conf_file; - conf_file = argv[0]; - conf_file = conf_file.Left(conf_file.ReverseFind('\\')) + "\\innd.conf"; +int innd::cmd_ihave(const char* msg_id) +{ + CRecordset RS(&(this->Db)); + CStringArray group_list; + CDBVariant dbVar; + const char *p,*p1,*p2; + bool head_find; + char cmd[50],cancel_msg_id[256]; + CString head_name,head_value,path,control,newsgroups,organization; //Head + CString head,body,sql,out,group; + long sid[256]; + int sid_count = 0; + + try + { + this->s_send("335 OK, send article to be transferred."); + this->s_receive(out,".\r\n"); - innd_srv.nntp_ctrl.load_conf(conf_file); + if (out.Right(5) != "\r\n.\r\n") + { + this->s_send("437 Empty article"); + syslog << logfile::log_head << "Empty article" << endl; + return 1; + } + + out = out.Left(out.GetLength()-3); + head = out.Left(out.Find("\r\n\r\n")+2); + body = out.Mid(out.Find("\r\n\r\n")+4); + + p = p1 = p2 = head; + control = "none"; + newsgroups = organization = ""; - //Standalone mode - if (argc == 2 && _stricmp(argv[1], "-s") == 0) - { - innd_srv.nntp_ctrl.begin(); - innd_srv.nntp_ctrl.StartupChild(); + while(*p1) + { + head_find = false; + head_name = ""; + head_value = ""; + while (*p2) + { + if (!head_find && *p2==':' && *(p2+1)==' ') + { + //Get head name + head_name = head.Mid((int)(p1-p),(int)(p2-p1)); + head_find=true; + p2+=2; + p1=p2; + } + if (*p2=='\r' && *(p2+1)=='\n') + { + //Get head value + head_value = head.Mid((int)(p1-p),(int)(p2-p1)); + p2 += 2; + p1 = p2; + if (head_find) + { + //Set head info + if (head_name == "Path") + path = head_value; + if (head_name == "Control") + control = head_value; + if (head_name == "Newsgroups") + newsgroups = head_value; + if (head_name == "Organization") + organization = head_value; + } + break; + } + p2++; + } + } + + newsgroups = base::addslashes(newsgroups); + newsgroups.Replace(",","','"); + + sql.Format("select SID from innd_conf right join innd_access on" + " innd_conf.server=innd_access.server where `group` in ('%s') and" + " `in`=1 and innd_conf.passive_mode=1 and innd_access.ip='%s'", + newsgroups,this->access.ip); + + RS.Open(CRecordset::snapshot,sql,CRecordset::forwardOnly | CRecordset::readOnly); + while(!RS.IsEOF()) + { + RS.GetFieldValue("SID",dbVar,SQL_C_SSHORT); + sid[sid_count++] = dbVar.m_iVal; + RS.MoveNext(); + } + RS.Close(); + + if (sid_count == 0) + { + this->s_send("437 Not in a allowed newsgroup"); + syslog << logfile::log_head << "Not in a allowed newsgroup" << endl; + return 2; + } + + if (organization==this->innd_name || + path.Right(CString::StringLength(this->innd_id))==this->innd_id) + { + this->s_send("437 I already have it"); + syslog << logfile::log_head << "I already have it" << endl; + return 2; + } + + if (control == "none") + { + strcpy(cmd,""); + } + else + { + sscanf(control,"%s %s",cmd,cancel_msg_id); + } + + if (strcmp(cmd,"")==0) + { + for (int i=0; ibbs_post(head,body,sid[i],0) == 0) + { + syslog << logfile::log_head << "Post OK" << endl; + } + else + { + syslog << logfile::log_head << "Post failed" << endl; + } + } + this->s_send("235 Article transferred ok"); + return 0; + } - while (innd_srv.nntp_ctrl.IsRunning()) + if (strcmp(cmd,"cancel")==0 && strcmp(cancel_msg_id,"")!=0) //Empty Message-ID { - Sleep(100); - } + //Delete article + sql.Format("select AID from innd_log where msg_id='%s'" + " and op='I' and cancel=0",base::addslashes(cancel_msg_id)); + + RS.Open(CRecordset::snapshot,sql,CRecordset::forwardOnly | CRecordset::readOnly); + + if(!RS.IsEOF()) + { + RS.GetFieldValue("AID",dbVar,SQL_C_SLONG); + + if (this->bbs_delete(dbVar.m_lVal) == 0) + { + syslog << logfile::log_head << "Delete OK" << endl; + } + else + { + syslog << logfile::log_head << "Delete failed" << endl; + } + } + else + { + syslog << logfile::log_head << "Message-ID not found" << endl; + } + RS.Close(); + this->s_send("235 Article transferred ok"); + return 0; + } - innd_srv.nntp_ctrl.bbsd.end(); - innd_srv.nntp_ctrl.innd.end(); - innd_srv.nntp_ctrl.outd.end(); - innd_srv.nntp_ctrl.end(); + if (strcmp(cmd,"checkgroups")==0) + { + this->s_send("235 Article transferred ok"); + syslog << logfile::log_head << "Checkgroups" << endl; + return 0; + } - return 0; + this->s_send("235 Article transferred ok"); + syslog << logfile::log_head << "Incorrect message" << endl; + } + catch(CException* e) + { + char strErrMsg[256]; + e->GetErrorMessage(strErrMsg,256); + syslog << logfile::log_head << "Error in cmd_ihave() [" << strErrMsg << "]" << endl; + e->Delete(); + return -1; } - // Parse for standard arguments (install, uninstall, version etc.) - if (!innd_srv.ParseStandardArgs(argc, argv)) { - //DebugBreak(); - innd_srv.StartService(); - } + return 0; +} + +int innd::Shutdown(void) +{ + base_active nntpClient; + + if (this->thread_terminate) + return 1; + + this->thread_terminate = true; + nntpClient.configure(this->innd_id,this->innd_name,this->innd_server,this->innd_uid,this->w_address,0,this->w_conn_str); + nntpClient.s_connect((strlen(this->hostaddr)>0 ? this->hostaddr : "127.0.0.1"),this->port); + nntpClient.s_close(); + + return 0; +} + +int innd::Startup(void) +{ + if (!this->thread_terminate) + return 1; + + this->thread_terminate = false; + + return 0; +} - // When we get here, the service has been stopped - return innd_srv.m_Status.dwWin32ExitCode; +int innd::db_env_init(void) +{ + if (this->db_open(this->w_conn_str) != 0) + { + return -1; + } + return 0; }