#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fdpass.h" using namespace std; #include "proto/trli-log.protoh" enum CLIENT_TYPE {TYPE_NONE, TYPE_CONTROL, TYPE_PIPE, TYPE_PROC, TYPE_ADMIN}; struct HANDLE_INFO: public ARRAY_OBJ { CLIENT_TYPE type; REQUEST_INFO req; HANDLE_INFO (CLIENT_TYPE _type){ type = _type; } }; #include "proto/trli-log-control.protoh" #include "proto/trli-log-admin.protoh" struct WEIGHT{ int valid; int weight; WEIGHT(){ valid = 0; weight = 0; } }; struct NEWSSTATS { unsigned nbproofs; unsigned nbcomments; map weights; // Compute the weight of each proof NEWSSTATS(){ nbproofs = 0; nbcomments = 0; } }; /* Return the numerical id if a record exist */ static int trli_rec_getid(NSQL *sq,const char *query, ...) { va_list list; va_start (list,query); glocal int ret = -1; (*sq,query,list); glocal.ret = atoi(row[0]); va_end (list); return glocal.ret; } static int trli_rec_getid(const char *query, ...) { va_list list; va_start (list,query); glocal int ret = -1; (query,list); glocal.ret = atoi(row[0]); va_end (list); return glocal.ret; } static bool normuuid = false; static string nuuid(const char *s) { if (*s == '\0'){ return string(); }else if (normuuid){ int num = 0; static map uuids; static int alloc = 1; auto uu = uuids.find(s); if (uu == uuids.end()){ uuids[s] = alloc; num = alloc; alloc++; }else{ num = uu->second; } return string_f ("uuid-%04d",num); }else{ return string(s); } } static string nuuid_sub (const char *s) { string ret; while (*s != '\0'){ char car = *s++; if (car == '{'){ string tmp; while (*s != '\0' && *s != '}') tmp += *s++; ret += string("{") + nuuid(tmp.c_str()) + "}"; if (*s == '}') s++; }else{ ret += car; } } return ret; } static string normtime(unsigned t) { if (normuuid){ static unsigned start = (unsigned)-1; if (start == (unsigned)-1) start = t; int diff=t-start; if (diff >=0 && diff < 10) diff=0; return string_f("%d",diff); }else{ return string_f ("%u",t); } } static bool showstamp = false; static void printstamp (unsigned long long stamp) { if (showstamp){ time_t t = (time_t)(stamp/1000000); unsigned micro = (unsigned)(stamp%1000000); struct tm *tt = localtime (&t); printf ("%04d/%02d/%02d-%02d:%02d:%02d.%06u " ,tt->tm_year+1900,tt->tm_mon+1,tt->tm_mday ,tt->tm_hour,tt->tm_min,tt->tm_sec ,micro); } } // Compute the verdict for the opinions and votes static int trli_compute() { glocal map stats; glocal map proofvotes; glocal unsigned lastproof = (unsigned)-1; ("select news.newsid,proofs.proofid,comments.commentid,proofs.valid,comments.vote" " from news left join proofs on proofs.newsid=news.newsid" " left join comments on comments.proofid=proofs.proofid" " order by news.newsid,proofs.proofid"); unsigned newsid = atoi(row[0]); NEWSSTATS &s = glocal.stats[newsid]; if (row[1] == NULL){ // No proofs, so no comments // Do nothing, just getting a reference creates the record }else if (row[2] == NULL){ // No comments, so just add a proofs s.nbproofs++; }else{ unsigned proofid = atoi(row[1]); glocal.proofvotes[proofid]++; if (glocal.lastproof != proofid){ s.nbproofs++; glocal.lastproof = proofid; } auto &w = s.weights[proofid]; w.valid = atoi(row[3]); int vote = atoi(row[4]); if (vote == 0){ w.weight--; }else{ w.weight++; } s.nbcomments++; } debug_printf ("row=%u %s %s -> %s %s\n",newsid,row[1],row[2],row[3],row[4]); NSQL *sq = query_getdefaultdb (); for (auto s:glocal.stats){ debug_printf ("%u %u %u:",s.first,s.second.nbproofs,s.second.nbcomments); int verdict = 0; for (auto w:s.second.weights){ debug_printf (" %u=%d,%d",w.first,w.second.valid,w.second.weight); if (w.second.valid == 1){ verdict += w.second.weight; }else{ verdict -= w.second.weight; } } debug_printf ("\n"); if(sql_action ("update news set nbproofs=%u,nbcomments=%u,verdict=%d where newsid=%u" ,s.second.nbproofs,s.second.nbcomments,verdict,s.first)==-1){ tlmp_error ("SQL error: %s\n",sq->error ()); } } int ret = 0; for (auto s:glocal.proofvotes){ if (sql_action("update proofs set nbcomments=%u where proofid=%u",s.second,s.first)==-1){ tlmp_error ("SQL error: %s\n",sq->error ()); ret = -1; } } return ret; } struct ARGSPEC { unsigned level; unsigned order; unsigned suborder; ARGSPEC(){ level = 0; order = 0; suborder = 0; } }; static int trli_compute_args () { glocal int ret = 0; ("select newsid from news"); glocal map args; glocal unsigned order0 = 0; ("select argid,replyto from arguments where newsid=%s order by argid,replyto",row[0]); unsigned argid = atoi(row[0]); unsigned replyid = atoi(row[1]); static unsigned tbm[]={50*50*50*50*50,50*50*50*50,50*50*50,50*50,50,1}; static const unsigned max_level = sizeof(tbm)/sizeof(tbm[0]); if (replyid == 0){ ARGSPEC &a = glocal.args[argid]; a.level = 0; a.order = glocal.order0; glocal.order0 += tbm[0]; }else{ ARGSPEC &r = glocal.args[replyid]; ARGSPEC &a = glocal.args[argid]; a.level = r.level + 1; if (a.level >= max_level) a.level = max_level-1; r.suborder++; a.order = r.order+r.suborder*tbm[a.level]; } for (auto &a:glocal.args){ if (sql_action("update arguments set level=%u,pres_order=%u where argid=%u",a.second.level,a.second.order,a.first)==-1){ glocal.ret = -1; end = true; break; } } if (sql_action("update news set nbarguments=%lu where newsid=%s",glocal.args.size(),row[0])==-1){ glocal.ret = -1; end = true; } return glocal.ret; } struct SUBJECT{ bool seen; int id; string text; SUBJECT (int _id, const char *_text){ id = _id; text = _text; seen = false; } SUBJECT (int _id, const char *_text, bool _seen){ id = _id; text = _text; seen = _seen; } }; struct COMPUTE { pid_t procpid; // Background process use to re-compute unsigned request; // More request to execute long long start; // When the last compuration was started long long max_duration; // Longest duration long long total_duration; unsigned nbcomputes; // How many computation has been done COMPUTE(){ procpid = 0; start = 0; request = 0; total_duration = 0; max_duration = 0; nbcomputes = 0; } void addrequest(){ request++; } void run (_F_TCPSERVER_V1 *c){ if (procpid == (pid_t)0 && request > 0){ procpid = 0; int tb[2]; if (pipe(tb)==-1){ tlmp_warning ("run_compute: Can't set pipe (%s)\n",strerror(errno)); }else{ start = fdpass_getnow(); pid_t pid = fork(); if (pid == (pid_t)0){ close (tb[0]); int ok = trli_compute(); int okargs = trli_compute_args(); syslog (LOG_WARNING,"compute ok=%d okargs=%d",ok,okargs); query_getdefaultdb()->disconnect(); // No need to keep the connection _exit (0); }else if (pid == (pid_t)-1){ tlmp_error ("run_compute: Can't fork (%s)\n",strerror(errno)); }else{ nbcomputes++; procpid = pid; request = 0; close (tb[1]); c->inject(tb[0],new HANDLE_INFO(TYPE_PROC)); } } } } void end(){ procpid=0; long long duration = fdpass_getnow() - start; total_duration += duration; if (duration > max_duration) max_duration = duration; } }; static int trli_news_updated(const char *date, int newsid,const char *extraupdates) { int ret = 0; if (sql_action ("update news set updated='%s'%s where newsid=%d",date,extraupdates,newsid)==-1){ tlmp_error ("trli_news_updated failed, newid=%d\n",newsid); ret = -1; } return ret; } int main (int argc, char *argv[]) { glocal int ret = -1; glocal const char *admin_secretfile = "/etc/trli/secrets.admin"; glocal const char *data_dbserv = "localhost"; glocal const char *data_dbname = "trli"; glocal const char *data_dbuser = NULL; glocal const char *users_dbserv = "localhost"; glocal const char *users_dbname = "trliusers"; glocal const char *users_dbuser = NULL; glocal const char *sql_tcpport = NULL; glocal bool compute = false; glocal bool dump = false; glocal bool daemon = false; glocal const char *pidfile = "/var/run/trli-log.pid"; glocal const char *control = "/var/run/trli-log.sock"; glocal const char *user = "trli"; glocal const char *unixsockadmin = "unix:/var/run/compute.sock"; glocal.ret = (argc,argv,"tlmpsql"); setproginfo ("trli-log",VERSION ,"reads log produced by trli-writed and update the database\n"); setgrouparg ("Operation"); setarg (' ',"dump","Read a file and print the content",glocal.dump,false); setarg (' ',"normuuid","Normalise UUID, useful to do file compare",normuuid,false); setarg ('t',"showtimestamp","Display time stamps",showstamp,false); setarg (' ',"compute","Compute the stats for news",glocal.compute,false); setgrouparg ("Database"); setarg (' ',"data_dbserv","Database server",glocal.data_dbserv,false); setarg (' ',"data_dbname","Database name",glocal.data_dbname,false); setarg (' ',"data_dbuser","Database user",glocal.data_dbuser,false); setarg (' ',"users_dbserv","Database server for users",glocal.users_dbserv,false); setarg (' ',"users_dbname","Database name for users",glocal.users_dbname,false); setarg (' ',"users_dbuser","Database user for users",glocal.users_dbuser,false); setarg (' ',"sqltcpport","Database TCP port",glocal.sql_tcpport,false); setgrouparg ("Misc."); setarg (' ',"daemon","Goes in backgroup for compute mode",glocal.daemon,false); setarg (' ',"user","Run the program as this user",glocal.user,false); setarg (' ',"pidfile","FIle holding the PID of the process",glocal.pidfile,false); setarg ('c',"control","Unix socket for trli-log-control",glocal.control,false); setarg (' ',"unixadmin","Unix socket for admins",glocal.unixsockadmin,false); setarg (' ',"admin-secrets","File holding admin secrets for communication",glocal.admin_secretfile,false); if (glocal.daemon){ syslog (LOG_ERR,"%s",msg); }else{ fprintf (stderr,"%s",msg); } if (glocal.daemon){ syslog (LOG_WARNING,"%s",msg); }else{ fprintf (stderr,"%s",msg); } int ret = -1; if (glocal.dump){ for (int i=0; i(fin); // userid newsid url title text printstamp(timestamp); printf ("addnews: userid=%s newsid=%s url=%s title=%s text=%s\n" ,nuuid(userid).c_str(),nuuid(newsid).c_str(),url,title,text); // newsid content printstamp(timestamp); printf ("modifynews: newsid=%s text=%s\n" ,nuuid(newsid).c_str(),text); // userid proofid newsid valid:u type:u title text printstamp(timestamp); printf ("addproof: userid=%s proofid=%s newsid=%s valid=%u type=%u title=%s text=%s\n" ,nuuid(userid).c_str(),nuuid(proofid).c_str(),nuuid(newsid).c_str(),valid,type,title,text); // userid commentid proofid vote:u text printstamp(timestamp); printf ("addcomment: userid=%s commentid=%s proofid=%s vote=%u text=%s\n" ,nuuid(userid).c_str(),nuuid(commentid).c_str(),nuuid(proofid).c_str(),vote,text); // userid name email password printstamp(timestamp); printf ("adduser: userid=%s name=%s email=%s password=%s\n" ,nuuid(userid).c_str(),name,email,password); // userid printstamp(timestamp); printf ("confirmuser: userid=%s\n",nuuid(userid).c_str()); // userid deleteid printstamp(timestamp); printf ("deleteuser: userid=%s deleteid=%s\n",nuuid(userid).c_str(),nuuid(deleteid).c_str()); // userid deleteid printstamp(timestamp); printf ("confirmdelete: userid=%s deleteid=%s\n",nuuid(userid).c_str(),nuuid(deleteid).c_str()); // newsid approved_by_id printstamp(timestamp); printf ("approvenews: newsid=%s approved_by_id=%s\n",nuuid(newsid).c_str(),nuuid(approved_by_id).c_str()); // newsid approved_by_id printstamp(timestamp); printf ("rejectnews: newsid=%s approved_by_id=%s\n",nuuid(newsid).c_str(),nuuid(approved_by_id).c_str()); // email on printstamp(timestamp); printf ("makeadmin: email=%s on=%d\n",email,on); // userid printstamp(timestamp); printf ("del_incomplete: userid=%s\n",userid); printstamp(timestamp); printf ("addblog blogid=%s created=%s content=%s\n",blogid,created,content); printstamp(timestamp); printf ("addblogcomment blogid=%s created=%s content=%s\n",blogid,normtime(created).c_str(),content); printstamp(timestamp); printf ("addargument argid=%s userid=%s newsid=%s replyto=%s created=%s title=%s content=%s\n" ,nuuid(argid).c_str(),nuuid(userid).c_str(),nuuid(newsid).c_str(),nuuid(replyto).c_str(),normtime(created).c_str(),title,content); printstamp(timestamp); printf ("addnewsurl userid=%s newsid=%s created=%s url=%s content=%s\n" ,nuuid(userid).c_str(),nuuid(newsid).c_str(),normtime(created).c_str(),nuuid_sub(url).c_str(),nuuid_sub(content).c_str()); printstamp(timestamp); printf ("approvenewsurl newsid=%s url=%s approved=%s\n" ,nuuid(newsid).c_str(),nuuid_sub(url).c_str(),normtime(approved).c_str()); // subjects:v printstamp(timestamp); printf ("setsubjects"); for (auto x:subjects) printf (" \"%s\"",x); printf ("\n"); // newsid subjects:v printstamp(timestamp); printf ("assignsubjects %s",nuuid(newsid).c_str()); for (auto x:subjects) printf (" \"%s\"",x); printf ("\n"); printf ("invalid msg=%s\n",msg); end = true; } } }else if (glocal.data_dbuser == NULL){ tlmp_error ("Option --data_dbuser is required\n"); }else if (glocal.compute){ glocal map admin_secrets; fdpass_readsecrets (glocal.admin_secretfile,glocal.admin_secrets); const char *passwd = getenv("TRLI_WRITED_PWD"); if (passwd == NULL){ tlmp_error ("Can't get database password from environment, aborting\n"); exit (-1); } if (glocal.sql_tcpport != NULL) nsql_settcpport (atoi(glocal.sql_tcpport)); query_setdefaultdb (glocal.data_dbserv,glocal.data_dbname,glocal.data_dbuser,passwd); query_getdefaultdb()->showerrormode (true); if (glocal.daemon){ signal (SIGCHLD,SIG_IGN); glocal pid_t pid_watch = (pid_t)-1; glocal COMPUTE compute; (glocal.unixsockadmin,5); HANDLE_INFO *n = new HANDLE_INFO(TYPE_CONTROL); info.data = n; if (strcmp(info.port,glocal.unixsockadmin)==0){ n->req.secret = fdpass_findsecret (glocal.admin_secrets,info.port); if (n->req.secret.size() > 0){ n->type = TYPE_ADMIN; }else{ tlmp_error ("Rejected admin connexion from port %s\n",info.port); endclient = true; } } HANDLE_INFO *n = (HANDLE_INFO*)info.data; if (n->type == TYPE_PIPE){ tlmp_error ("Have lost the alarm process, ending\n"); endserver = true; }else if (n->type == TYPE_PROC){ glocal.compute.end(); glocal.compute.run (this); } HANDLE_INFO *n = (HANDLE_INFO*)info.data; if (n->type == TYPE_PIPE){ // Run a compute glocal.compute.addrequest(); glocal.compute.run (this); }else if (n->type == TYPE_CONTROL){ (this,n->req,line, info.linelen,endserver, endclient, no,n); vector tb; tb.push_back(string_f("Version %s",VERSION)); tb.push_back(string_f("Request=%u",glocal.compute.request)); tb.push_back(string_f("nbcomputes=%u",glocal.compute.nbcomputes)); long long avg = glocal.compute.nbcomputes == 0 ? 0 : glocal.compute.total_duration/glocal.compute.nbcomputes; tb.push_back(string_f("avg_time=%Ld.%06Ld",avg/1000000,avg%1000000)); tb.push_back(string_f("max_time=%Ld.%06Ld",glocal.compute.max_duration/1000000,glocal.compute.max_duration%1000000)); rep_status(tb); glocal.compute.addrequest(); glocal.compute.run (&glocal.TCPSERVER); endserver = true; if (on){ debug_seton(); }else{ debug_setoff(); } debug_setfdebug (filename); endclient = true; }else if (n->type == TYPE_ADMIN){ // For now, we recompute everything at every request (this,n->req,line, info.linelen,endserver, endclient, no,n); rep_test (true); glocal.compute.addrequest(); glocal.compute.run (&glocal.TCPSERVER); glocal.compute.addrequest(); glocal.compute.run (&glocal.TCPSERVER); glocal.compute.addrequest(); glocal.compute.run (&glocal.TCPSERVER); endclient = true; } if (fdpass_setcontrol(o,glocal.control,glocal.user)!=-1){ chmod (glocal.control,0666); daemon_init(glocal.pidfile,glocal.user); o.setrawmode(true); int tb[2]; if (pipe(tb)==-1){ tlmp_error ("Can't setup pipe (%s), aborting\n",strerror(errno)); exit (-1); }else{ glocal.pid_watch = fork(); if (glocal.pid_watch == (pid_t)0){ for (int i=3; i<1024; i++){ if (i != tb[1]) close (i); } time_t last = (time_t)0; while (1){ sleep (5); struct stat64 st; if (stat64(argv[0],&st)==-1){ tlmp_error ("Can't stat %s (%s)\n",argv[0],strerror(errno)); break; }else if (st.st_mtime != last){ last = st.st_mtime; if (write (tb[1]," ",1) != 1) break; } } _exit (0); }else if (glocal.pid_watch == (pid_t)-1){ tlmp_error ("Can't fork (%s), aborting\n",strerror(errno)); exit (-1); }else{ close (tb[1]); o.inject (tb[0],new HANDLE_INFO(TYPE_PIPE)); o.loop(); } } } if (glocal.pid_watch != (pid_t)-1) kill (glocal.pid_watch,SIGTERM); exit (0); }else{ if (trli_compute() != -1 && trli_compute_args() != -1) glocal.ret = 0; } }else if (glocal.users_dbuser == NULL){ tlmp_error ("Option --users_dbuser is required\n"); }else{ glocal NSQL *usq; // SQL handle for the users database const char *passwd = getenv("TRLI_WRITED_PWD"); if (passwd == NULL){ tlmp_error ("Can't get database password from environment, aborting\n"); exit (-1); } if (glocal.sql_tcpport != NULL) nsql_settcpport (atoi(glocal.sql_tcpport)); query_setdefaultdb (glocal.data_dbserv,glocal.data_dbname,glocal.data_dbuser,passwd); query_getdefaultdb()->showerrormode (true); NSQL nsql_sq (glocal.users_dbserv,glocal.users_dbname,glocal.users_dbuser,passwd); nsql_sq.showerrormode (true); glocal.usq = &nsql_sq; for (int i=0; i(fin); // userid url title text bool ok = false; char date[20]; fdpass_asctime(created,date); int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null",userid); if (userid_num != -1 || userid[0] == '\0'){ int newsid_num = trli_rec_getid ("select newsid from news where newsid_str='%s'",newsid); if (newsid_num == -1 && sql_action("insert into news (newsid_str,userid,url,title,content,created) values ('%s',%d,'%s','%s','%s','%s')" ,newsid,userid_num,url,title,text,date)!=-1){ newsid_num = sql_getlastid(); trli_news_updated (date,newsid_num,""); ok = true; } } if (ok){ printf ("addnews userid=%s newsid=%s url=%s title=%s text=%s\n",userid,newsid,url,title,text); }else{ fprintf (stderr,"fail: addnews userid=%s newsid=%s url=%s title=%s text=%s\n",userid,newsid,url,title,text); } // newsid text if (sql_action("update news set content='%s' where newsid_str='%s'",text,newsid)!=-1){ printf ("modifynews newsid=%s text=%s\n",newsid,text); }else{ fprintf (stderr,"fail: modifynews newsid=%s text=%s\n",newsid,text); } // userid newsid valid:u type:u title text char date[20]; fdpass_asctime(created,date); bool ok = false; int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null",userid); if (userid_num != -1){ int newsid_num = trli_rec_getid ("select newsid from news where newsid_str='%s'",newsid); if (newsid_num != -1){ int proofid_num = trli_rec_getid ("select proofid from proofs where proofid_str='%s'",proofid); if (proofid_num == -1){ if (sql_action("insert into proofs (proofid_str,userid,newsid,valid,type,title,content,created)" " values ('%s',%d,%d,%d,%d,'%s','%s','%s')" ,proofid,userid_num,newsid_num,valid,type,title,text,date)!=-1){ ok = true; } }else{ if (sql_action("update proofs set valid=%d,type=%d,title='%s',content='%s',created='%s' where proofid=%d" ,valid,type,title,text,date,proofid_num)!=-1){ ok = true; } } if (ok) trli_news_updated (date,newsid_num,",nbproofs=nbproofs+1"); } } if (ok){ printf ("addproof userid=%s proofid=%s newsid=%s valid=%u type=%u title=%s text=%s\n" ,userid,proofid,newsid,valid,type,title,text); }else{ fprintf (stderr,"fail: addproof userid=%s proofid=%s newsid=%s valid=%u type=%u title=%s text=%s\n" ,userid,proofid,newsid,valid,type,title,text); } // userid proofid vote:u text char date[20]; fdpass_asctime(created,date); bool ok = false; int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null",userid); if (userid_num != -1){ int proofid_num = trli_rec_getid ("select proofid from proofs where proofid_str='%s'",proofid); if (proofid_num != -1){ int commentid_num = trli_rec_getid ("select commentid from comments where commentid_str='%s'",commentid); if (commentid_num == -1){ if (sql_action("insert into comments (commentid_str,userid,proofid,vote,content,created)" " values ('%s',%d,%d,%d,'%s','%s')" ,commentid,userid_num,proofid_num,vote,text,date)!=-1){ ok = true; } }else{ if (sql_action("update comments set vote=%d,content='%s',created='%s' where commentid=%d" ,vote,text,date,commentid_num)!=-1){ ok = true; } } } } if (ok){ int newsid_num = trli_rec_getid ("select newsid from proofs where proofid_str='%s'",proofid); trli_news_updated (date,newsid_num,",nbcomments=nbcomments+1"); printf ("addcomment userid=%s commentid=%s proofid=%s vote=%u text=%s\n" ,userid,commentid,proofid,vote,text); }else{ fprintf (stderr,"fail: addcomment userid=%s commentid=%s proofid=%s vote=%u text=%s\n" ,userid,commentid,proofid,vote,text); } // userid name email password char date[20]; fdpass_asctime(created,date); int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s'",userid); if (userid_num != -1){ fprintf (stderr,"exist: adduser userid=%s name=%s email=%s\n",userid,name,email); }else if (sql_action(*glocal.usq,"insert into users (userid_str,name,email,password,created) values ('%s','%s','%s','%s','%s')" ,userid,name,email,password,date)==-1 || sql_action ("insert into id2name (userid,name) values (%d,'%s')",glocal.usq->getlastid(),name)==-1){ fprintf (stderr,"fail: adduser userid=%s name=%s email=%s\n",userid,name,email); }else{ printf ("adduser userid=%s name=%s email=%s\n",userid,name,email); } // confirmid confirmed char date[20]; fdpass_asctime(confirmed,date); int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is null",userid); if (userid_num == -1){ fprintf (stderr,"missing: confirmuser userid=%s\n",userid); }else if (sql_action(*glocal.usq,"update users set confirmed='%s' where userid=%d",date,userid_num)==-1){ fprintf (stderr,"fail: confirmuser userid=%s\n",userid); }else{ printf ("confirmuser userid=%s\n",userid); } // userid deleteid int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null and deleted is null",userid); if (userid_num == -1){ fprintf (stderr,"fail: deleteuser userid=%s deleteid=%s\n",userid,deleteid); }else{ if (sql_action(*glocal.usq,"update users set deleteid='%s' where userid=%u",deleteid ,userid_num)!=-1){ printf ("deleteuser userid=%s deleteid=%s\n",userid,deleteid); }else{ fprintf (stderr,"fail: deleteuser userid=%s deleteid=%s\n",userid,deleteid); } } // deleteid glocal const char *userid_str = userid; glocal const char *deleteid = deleteid; (*glocal.usq,"select userid,userid_str from users where deleteid='%s' and deleted is null and disabled is null" ,deleteid); unsigned userid = atoi(row[0]); const char *userid_str = row[1]; if (sql_action(*glocal.usq,"update users set deleted=now() where userid=%u",userid)!=-1){ printf ("confirmdelete: userid=%s deleteid=%s\n",userid_str,glocal.deleteid); } fprintf (stderr,"fail confirmdelete: userid=%s deleteid=%s\n",glocal.userid_str,glocal.deleteid); // newsid approved_by_id char date[20]; fdpass_asctime(approved,date); int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null",approved_by_id); if (userid_num == -1){ fprintf (stderr,"fail: approvenews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); }else{ if (sql_action ("update news set approved='%s',approved_by_id=%d where newsid_str='%s'" " and approved is null and rejected is null",date,userid_num,newsid)>0){ printf ("approvenews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); }else{ fprintf (stderr,"fail: approvenews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); } } // newsid approved_by_id char date[20]; fdpass_asctime(rejected,date); int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s' and confirmed is not null",approved_by_id); if (userid_num == -1){ fprintf (stderr,"fail: rejectnews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); }else{ if (sql_action ("update news set rejected='%s',approved_by_id=%d where newsid_str='%s'" " and approved is null and rejected is null",date,userid_num,newsid)>0){ printf ("rejectnews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); }else{ fprintf (stderr,"fail: rejectnews newsid=%s approved_by_id=%s\n",newsid,approved_by_id); } } // email on glocal bool on = on; glocal const char *email = email; glocal bool ok = false; (*glocal.usq,"select userid,admin from users where email='%s'",email); if (strcmp(row[1],"0")==0){ if (glocal.on && sql_action(*glocal.usq,"update users set admin=1 where userid=%s",row[0])!=-1){ glocal.ok = true; } }else{ if (sql_action(*glocal.usq,"update users set admin=0 where userid=%s",row[0])!=-1){ glocal.ok = true; } } if (glocal.ok){ printf ("makeadmin: email=%s on=%d\n",glocal.email,glocal.on); }else{ fprintf (stderr,"fail: makeadmin: email=%s on=%d\n",glocal.email,glocal.on); } // userid if (sql_action(*glocal.usq,"delete from users where userid_str='%s' and confirmed is null",userid)!=-1){ printf ("del_incomplete: userid=%s\n",userid); }else{ fprintf (stderr,"fail: del_incomplete: userid=%s\n",userid); } glocal const char *blogid = blogid; glocal const char *title = title; glocal const char *content = content; glocal const char *created = created; ("select blogid from blog where blogid_str='%s'",blogid); if (sql_action("update blog set title='%s',content='%s',created='%s' where blogid=%s" ,glocal.title,glocal.content,glocal.created,row[2])==-1){ printf ("addblog: modify blogid=%s\n",glocal.blogid); }else{ fprintf (stderr,"fail: addblog: modify blogid=%s\n",glocal.blogid); } if (sql_action("insert into blog (blogid_str,title,content,created) values ('%s','%s','%s','%s')" ,glocal.blogid,glocal.title,glocal.content,glocal.created)!=-1){ printf ("addblog: blogid=%s\n",glocal.blogid); }else{ fprintf (stderr,"fail: addblog: blogid=%s\n",glocal.blogid); } glocal bool success = false; glocal const char *content = content; glocal const char *blogid_str = blogid; glocal char date[20]; fdpass_asctime (created,glocal.date); (*glocal.usq,"select userid from users where userid_str='%s'",userid); glocal const char *userid=row[0]; ("select blogid from blog where blogid_str='%s'",glocal.blogid_str); if (sql_action("insert into blogcomments (blogid,userid,content,created)" " values (%s,%s,'%s','%s')",row[0],glocal.userid,glocal.content,glocal.date)!=-1){ glocal.success = true; } if (glocal.success){ printf ("addblogcomment: userid=%s blogid=%s\n",userid,blogid); }else{ fprintf (stderr,"fail: addblogcomment: userid=%s blogid=%s\n",userid,blogid); } glocal bool success=false; int userid_num = userid[0] == '\0' ? -1 : trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s'",userid); int newsid_num = trli_rec_getid ("select newsid from news where newsid_str='%s'",newsid); int replyid = replyto[0] == '\0' ? 0 : trli_rec_getid("select argid from arguments where argid_str='%s'",replyto); char date[20]; fdpass_asctime (created,date); if (newsid_num != -1 && replyid !=-1){ if (sql_action("insert into arguments (argid_str,userid,newsid,replyto,title,content,created)" " values ('%s',%d,%d,%d,'%s','%s','%s')" ,argid,userid_num,newsid_num,replyid,title,content,date)!=-1){ glocal.success = true; } } if (glocal.success){ trli_news_updated(date,newsid_num,",nbarguments=nbarguments+1"); printf ("addargument: date=%s argid=%s userid=%s newsid=%s replyto=%s\n",date,argid,userid,newsid,replyto); }else{ fprintf (stderr,"fail: addargument: date=%s argid=%s userid=%s newsid=%s replyto=%s\n",date,argid,userid,newsid,replyto); } glocal bool success=false; glocal const char *url = url; glocal const char *content = content; glocal int userid_num = trli_rec_getid (glocal.usq,"select userid from users where userid_str='%s'",userid); glocal int newsid_num = trli_rec_getid ("select newsid from news where newsid_str='%s'",newsid); glocal char date[20]; fdpass_asctime (created,glocal.date); if (glocal.newsid_num != -1){ ("select url from extraurls where newsid=%d and url='%s'",glocal.newsid_num,url); // Already there, just update content if (sql_action("update extraurls set content='%s' where newsid=%d and url='%s'" ,glocal.content,glocal.newsid_num,glocal.url)!=-1){ glocal.success = true; } if (sql_action("insert into extraurls (userid,newsid,url,content,created)" " values (%d,%d,'%s','%s','%s')" ,glocal.userid_num,glocal.newsid_num,glocal.url,glocal.content,glocal.date)!=-1){ glocal.success = true; } } if (glocal.success){ trli_news_updated(glocal.date,glocal.newsid_num,""); printf ("addnewsurl: date=%s newsid=%s url=%s\n",glocal.date,newsid,url); }else{ fprintf (stderr,"fail: addnewsurl: date=%s newsid=%s url=%s\n",glocal.date,newsid,url); } glocal bool success = false; char date[20]; fdpass_asctime (approved,date); int newsid_num = trli_rec_getid ("select newsid from news where newsid_str='%s'",newsid); if (newsid_num != -1){ if (sql_action("update extraurls set approved='%s' where newsid=%d and url='%s'",date,newsid_num,url)!=-1){ glocal.success=true; } } if (glocal.success){ printf ("approvenewsurl: date=%s newsid=%s url=%s\n",date,newsid,url); }else{ fprintf (stderr,"fail: approvenewsurl: date=%s newsid=%s url=%s\n",date,newsid,url); } // subjects:v glocal vector subs; bool success = true; ("select subjectid,text from subjects"); glocal.subs.push_back(SUBJECT(atoi(row[0]),row[1])); for (auto s:subjects){ bool found = false; int max_id = 0; for (auto &s1:glocal.subs){ if (s1.id > max_id) max_id = s1.id; if (strcmp(s,s1.text.c_str())==0){ found = true; s1.seen = true; } } if (!found){ max_id++; glocal.subs.push_back(SUBJECT(max_id,s,true)); if (sql_action("insert into subjects (subjectid,lang,text) values (%d,0,'%s')",max_id,s)==-1){ success = false; break; } } } for (auto s1:glocal.subs){ if (!s1.seen && sql_action ("delete from subjects where subjectid=%d",s1.id)==-1){ success = false; break; } } if (success){ printf ("setsubjects"); for (auto s:subjects) printf (" %s",s); printf ("\n"); }else{ fprintf (stderr,"fail: setsubjects\n"); } // newsid subjects:v glocal const char *newsid_str = newsid; glocal vector ids; string q = "select subjectid from subjects where text in "; const char *sep = "("; for (auto s:subjects){ q += string_f("%s'%s'",sep,s); sep = ","; } q += ")"; (q.c_str()); glocal.ids.push_back(atoi(row[0])); ("select newsid from news where newsid_str='%s'",newsid); unsigned newsid = atoi(row[0]); if (sql_action("delete from subnews where newsid=%u",newsid)==-1){ fprintf (stderr,"fail: assignsujects: newsid=%s Can't delete old assigment\n" ,glocal.newsid_str); }else{ string q="insert into subnews (newsid,subjectid)"; const char *sep = "values"; for (auto sid:glocal.ids){ q += string_f(" %s (%u,%d)",sep,newsid,sid); sep = ","; } if (sql_action(q.c_str())==-1){ fprintf (stderr,"fail: assignsujects: newsid=%s Can't insert new assignments\n" ,glocal.newsid_str); }else{ printf ("assignsubjects: newsid=%s\n",glocal.newsid_str); } } printf ("invalid msg=%s\n",msg); end = true; } } return ret; return glocal.ret; }