/* Programme exécutant l'écriture sur les différents serveurs SQL */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fdpass.h" #include "hostname.h" static DEBUG_KEY D_PROTO ("proto","Protocol information"); enum CONNECT_TYPE { TYPE_NONE, TYPE_CONTROL, TYPE_CLIENT }; struct HANDLE_INFO: public ARRAY_OBJ{ CONNECT_TYPE type; int no; std::string host; REQUEST_INFO req; HANDLE_INFO(){ no = -1; type = TYPE_NONE; } }; #include "proto/trli-writed_control.protoh" #include "proto/trli-writed_client.protoh" using namespace std; #define trli_sessiond_admin_getsessioninfo_NOTNEED #include "proto/trli-sessiond_admin.protoch" #include "proto/trli-log.protoch" #include "proto/trli-log-admin.protoch" /* Create a uniq ID combining the process number of this instance, a random value and the time in micro-seconds */ static string trli_makeid (int noproc) { string ret; char tmp[100]; struct timeval t; if (gettimeofday(&t,NULL)!=-1){ static int fd = -1; static bool error_shown = false; if (fd == -1){ fd = open ("/dev/urandom",O_RDONLY,0); } if (fd == -1){ if (!error_shown){ tlmp_error ("Can't open /dev/urandom (%s)\n",strerror(errno)); error_shown = true; } }else{ char buf[8]; if (read(fd,buf,8)!=8){ close (fd); fd = -1; if (!error_shown){ tlmp_error ("Can't read 8 bytes from /dev/urandom (%s)\n",strerror(errno)); error_shown = true; } }else{ for (int i=0; i<8; i++) snprintf (tmp+i*2,3,"%02x",buf[i]); int n = snprintf (tmp+16,sizeof(tmp)-16-1,"%08lx%08lx",t.tv_sec,t.tv_usec); snprintf (tmp+16+n,sizeof(tmp)-16-n-1,"-%d",noproc); ret = tmp; } } } return ret; } /* Get the userid associated with the sessionid */ static unsigned trli_getsessionuser (CONNECT_INFO &con, const char *sessionid, string &userid_str) { glocal unsigned userid = 0; glocal string *userid_str = &userid_str; //long long start = fdpass_getnow(); //for (int i=0; i<10000; i++){ (con,sessionid); glocal.userid = userid; (*glocal.userid_str) = userid_str; //} //long long end = fdpass_getnow(); //printf ("exec time = %lf\n",(end-start)/1000000.0); return glocal.userid; } static unsigned trli_getsessionuser (CONNECT_INFO &con, const char *sessionid) { string tmp; return trli_getsessionuser (con,sessionid,tmp); } /* Return the numerical id if a record exist */ 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 trli_isadmin (NSQL *sq, unsigned userid) { glocal bool ret = false; (*sq,"select admin from users where userid=%u",userid); if (strcmp(row[0],"1")==0) glocal.ret = true; return glocal.ret; } static void trli_approve_reject ( CONNECT_INFO &con, NSQL *usq, const char *sessionid, const char *newsid, bool approve, bool &success, string &approved_by_id, string &msg) { glocal const char *field = approve ? "approved" : "rejected"; glocal unsigned userid = trli_getsessionuser(con,sessionid,approved_by_id); glocal bool *success = &success; glocal string *msg = &msg; success = false; if (glocal.userid != 0 && trli_isadmin(usq,glocal.userid)){ ("select newsid from news where newsid_str='%s' and approved is null and rejected is null" ,newsid); if (sql_action("update news set %s=now(),approved_by_id=%u where newsid=%s" ,glocal.field,glocal.userid,row[0])!=-1){ (*glocal.success)=true; }else{ (*glocal.msg)="Internal error"; } (*glocal.msg) = "No match"; } } static string writed_format_mail_newaccount( const char *nickname, PARAM_STRING id_str) { return string_f( "Hello!\r\n" "\r\n" "You just created an account using nickname %s on " TRUELIES "\r\n" "Just click on the link below to confirm the account.\r\n" "confirm\r\n" "\r\n" "Once done, you will be allowed to fully participate in the validation\r\n" "of all the news out there.\r\n" "\r\n" "Thanks for joining!\r\n" ,nickname ,TRUELIES,id_str.ptr); } static int writed_mail_newaccount( const char *mailserver, const char *mailport, const char *mailfrom, const char *nickname, const char *email, PARAM_STRING id_str) { string tmp = writed_format_mail_newaccount(nickname,id_str); return fdpass_sendmail (mailserver,mailport,mailfrom,email ,"Account confirmation on " TRUELIES ,tmp); } 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; } }; static int trli_compare (vector &t1, vector &t2) { int ret = -1; if (t1.size() == t2.size()){ sort (t1.begin(),t1.end()); sort (t2.begin(),t2.end()); ret = 0; for (unsigned i=0; i int main (int argc, char *argv[]) { glocal int ret = -1; glocal int noproc = 1; glocal const char *secretfile = "/etc/trli/secrets.client"; glocal const char *bind = "0.0.0.0"; glocal const char *port = "9100"; glocal const char *control = "/var/run/trli-writed.sock"; glocal const char *user = "trli"; glocal const char *logfile = "/var/log/trli/writed.log"; 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 *mysecret = NULL; glocal const char *sessionhost = "127.0.0.4"; glocal const char *sessionport = "9200"; glocal const char *sessionbind = ""; glocal const char *computeport = "/dev/compute.sock"; glocal const char *sql_tcpport = NULL; glocal const char *mailserver = "unix:"; glocal const char *mailport = "/dev/smtp.sock"; glocal const char *mailfrom = NULL; glocal bool daemon = false; glocal const char *pidfile = "/var/run/trli-writed.pid"; glocal bool writeonce_proof = false; glocal bool writeonce_comment = false; glocal const char *force_addr = NULL; glocal.ret = (argc,argv,"tlmpsql"); setproginfo ("trli-writed",VERSION,"..."); setgrouparg ("Networking"); setarg ('b',"bindaddr","Bind to this address (TCP)",glocal.bind,false); setarg ('p',"tcpport","Listen for command on this TCP port",glocal.port,false); setarg ('c',"control","Unix socket for trlid-control",glocal.control,false); setgrouparg ("Session server"); setarg (' ',"sessionhost","Host running the trli-sessiond server",glocal.sessionhost,false); setarg (' ',"sessionport","Port to reach the trli-sessiond server",glocal.sessionport,false); setarg (' ',"sessionbind","Bind to this IP to talk to trli-sessiond",glocal.sessionbind,false); setarg (' ',"mysecret","Secret used to talk to sessiond",glocal.mysecret,true); setgrouparg ("Compute server"); setarg (' ',"computeport","Port to reach the trli-log compute server",glocal.computeport,false); setgrouparg ("Misc."); setarg (' ',"secrets","File holding secrets for communication",glocal.secretfile,false); setarg (' ',"user","Run the program as this user",glocal.user,false); setarg (' ',"logfile","Log file to record request",glocal.logfile,false); setarg (' ',"daemon","Run in background",glocal.daemon,false); setarg (' ',"pidfile","FIle holding the PID of the process",glocal.pidfile,false); setarg (' ',"noproc","Identity of this process (UUID)",glocal.noproc,false); setarg (' ',"writeonce_proof","Proof can't be edited",glocal.writeonce_proof,false); setarg (' ',"writeonce_comment","Comment can't be edited",glocal.writeonce_comment,false); setgrouparg ("Mail"); setarg (' ',"mailserver","Mail relay to use",glocal.mailserver,false); setarg (' ',"mailport","TCP port of the relay (or unix socket)",glocal.mailport,false); setarg (' ',"forceaddr","Force email address",glocal.force_addr,false); setarg ( ' ',"mailfrom","Mail sender",glocal.mailfrom,true); 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,true); 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,true); setarg (' ',"sqltcpport","Database TCP port",glocal.sql_tcpport,false); glocal const char *msg = msg; ("/tmp/err.log",true); fprintf (fout,"%s\n",glocal.msg); return 0; 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); } glocal bool mailon = true; // Send confirmation mails (for testing) glocal unsigned long nbrequest_client = 0; glocal FILE *flog = NULL; glocal NSQL *usq; // SQL handle for the users database glocal CONNECT_INFO con; // Connection to the session manager glocal CONNECT_INFO con_comp; // Connection to the trli-log compute server glocal map 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.force_addr != NULL) fdpass_set_force_addr(glocal.force_addr); 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); nsql_sq.setunixpath ("/var/lib/mysql/mysql-users.sock"); glocal.usq = &nsql_sq; fdpass_readsecrets (glocal.secretfile,glocal.secrets); glocal.con.port = glocal.sessionport; glocal.con.bind = glocal.sessionbind; glocal.con.secret = glocal.mysecret; glocal.con_comp.port = glocal.computeport; glocal.con_comp.secret = glocal.mysecret; glocal string clientport = string_f ("unix:/tmp/writed-%s.sock",glocal.port); glocal string controlport = string_f ("unix:%s",glocal.control); glocal.con.fd = -1; int ret = -1; (glocal.bind,glocal.clientport,5); HANDLE_INFO *n = new HANDLE_INFO; info.data = n; if (string_cmp(info.port,glocal.controlport)==0){ n->type = TYPE_CONTROL; }else{ settcpnodelay(true); n->type = TYPE_CLIENT; char addr[20]; const char *addrstr = addr; if (strncmp(info.port,"unix:",5)==0){ addrstr = info.port; }else{ ipnum_ip2a (from,addr); } n->host = addrstr; n->req.secret = fdpass_findsecret (glocal.secrets,addrstr); debug_printf (D_PROTO,"newclient addr=%s secret=%s\n",addrstr,n->req.secret.c_str()); if (n->req.secret.empty()){ endclient = true; tlmp_error ("No secret for client %s\n",addrstr); } } HANDLE_INFO *c = (HANDLE_INFO*)info.data; debug_printf (D_PROTO,"receive line: %s\n",line); if (c->type == TYPE_CONTROL){ (this,c->req,line, info.linelen,endserver, endclient, no,c,c->host.c_str()); vector tb; tb.push_back(string_f("version %s",VERSION)); tb.push_back(string_f("nbrequest %lu",glocal.nbrequest_client)); tb.push_back(string_f("mailctrl %d \"%s\"",glocal.mailon,fdpass_get_force_addr())); rep_status (tb); endserver = true; if (on){ debug_seton(); }else{ debug_setoff(); } debug_setfdebug (filename); glocal bool on = on; glocal const char *email = email; (*glocal.usq,"select userid,admin from users where email='%s'",email); if (strcmp(row[1],"0")==0){ if (!glocal.on){ glocal.trli_writed_control.rep_makeadmin(false,"already not admin"); }else if (sql_action(*glocal.usq,"update users set admin=1 where userid=%s",row[0])==-1){ glocal.trli_writed_control.rep_makeadmin(false,"sql error"); }else{ glocal.trli_writed_control.rep_makeadmin(true,""); trli_log_makeadmin (glocal.flog,glocal.email,glocal.on); } }else if (glocal.on){ glocal.trli_writed_control.rep_makeadmin(false,"already admin"); }else{ if (sql_action(*glocal.usq,"update users set admin=0 where userid=%s",row[0])==-1){ glocal.trli_writed_control.rep_makeadmin(false,"sql error"); }else{ glocal.trli_writed_control.rep_makeadmin(true,""); trli_log_makeadmin (glocal.flog,glocal.email,glocal.on); } } glocal.trli_writed_control.rep_makeadmin(false,"user unknown"); bool success = false; fclose (glocal.flog); glocal.flog = fopen (glocal.logfile,"a"); if (glocal.flog == NULL){ glocal.TCPSERVER.sendf ("Can't open logfile %s (%s)\n",glocal.logfile,strerror(errno)); tlmp_error ("Can't open logfile %s (%s)\n",glocal.logfile,strerror(errno)); exit (-1); }else{ success = true; } rep_rotatelog (success); bool success = false; fclose (glocal.flog); glocal.flog = fopen (glocal.logfile,"w"); if (glocal.flog == NULL){ glocal.TCPSERVER.sendf ("Can't open logfile %s (%s)\n",glocal.logfile,strerror(errno)); tlmp_error ("Can't open logfile %s (%s)\n",glocal.logfile,strerror(errno)); exit (-1); }else{ success = true; } rep_truncatelog (success); glocal vector emails; time_t ti = time(NULL)-nbseconds; struct tm *tt = localtime(&ti); char date[100]; snprintf (date,sizeof(date)-1,"%04d-%02d-%02d %02d:%02d:%02d" ,tt->tm_year+1900,tt->tm_mon+1,tt->tm_mday ,tt->tm_hour,tt->tm_min,tt->tm_sec); (*glocal.usq,"select userid,userid_str,email from users where confirmed is null and created <= '%s'",date); if (sql_action(*glocal.usq,"delete from users where userid=%s",row[0])!=-1){ trli_log_del_incomplete(glocal.flog,row[1]); glocal.emails.push_back(row[2]); } rep_del_incomplete(glocal.emails); // Test sending mail int success = fdpass_sendmail (glocal.mailserver,glocal.mailport,glocal.mailfrom,addr,subject,body); rep_sendmail (success); glocal bool to_stdout = to_stdout; glocal string msg; glocal bool success = false; (*glocal.usq,"select name,email,userid_str from users where email='%s' and confirmed is null",email); if (glocal.to_stdout){ glocal.msg = writed_format_mail_newaccount(row[0],row[2]); glocal.success = true; }else{ if (writed_mail_newaccount (glocal.mailserver,glocal.mailport,glocal.mailfrom,row[0],row[1],row[2]) != -1){ glocal.success = true; } } rep_newacctresend (glocal.success,glocal.msg); glocal.mailon = on; if (strcmp(forceaddr,"keep")!=0) fdpass_set_force_addr (forceaddr); 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){ trli_log_setsubjects (glocal.flog,subjects); } rep_setsubjects(success); tlmp_error ("Control: Invalid command: %s\n",line); glocal.TCPSERVER.sendf ("Invalid command %s\n",line); endclient = true; }else if (c->type == TYPE_CLIENT){ glocal.nbrequest_client++; (this,c->req,line, info.linelen,endserver, endclient, no,c,c->host.c_str()); string userid_str; int userid = trli_getsessionuser(glocal.con,sessionid,userid_str); if (userid == 0) userid = -1; if (trli_rec_getid("select newsid from news where url='%s'",url)!=-1){ rep_addnews(false,"","already there"); }else{ string newsid = trli_makeid (glocal.noproc); trli_log_addnews (glocal.flog,userid_str,newsid,url,title,text,time(NULL)); if (sql_action("insert into news (userid,newsid_str,url,title,content)" " values (%d,'%s','%s','%s','%s')" ,userid,newsid.c_str(),url,title,text)!=-1){ rep_addnews(true,newsid.c_str(),""); }else{ rep_addnews(false,"","internal error"); } } glocal const char *sessionid = sessionid; glocal int valid = valid; glocal int type = type; glocal const char *title = title; glocal const char *text = text; glocal const char *newsid = newsid; glocal string userid_str; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,glocal.userid_str); if (glocal.userid != 0){ glocal int newsid_num = trli_rec_getid("select newsid from news where newsid_str='%s'",newsid); if (glocal.newsid_num == -1){ glocal.trli_writed_client.rep_addproof(false,"","news does not exist"); }else{ // Check if this user as already created a proof ("select proofid,proofid_str from proofs where newsid=%d and userid=%u",glocal.newsid_num,glocal.userid); if (glocal.writeonce_proof){ glocal.trli_writed_client.rep_addproof(false,"","An opinion can't be modified"); }else{ const char *proofid_str = row[1]; if(sql_action ("update proofs set valid=%d,type=%d,title='%s',content='%s' where proofid=%s and userid=%u" ,glocal.valid,glocal.type,glocal.title,glocal.text,row[0],glocal.userid)==-1){ glocal.trli_writed_client.rep_addproof(false,"","internal error1"); }else{ glocal.trli_writed_client.rep_addproof(true,row[1],"Proof updated"); trli_log_addproof (glocal.flog,glocal.userid_str,proofid_str ,glocal.newsid,glocal.valid,glocal.type,glocal.title,glocal.text,time(NULL)); } } string proofid = trli_makeid (glocal.noproc); if (sql_action("insert into proofs (proofid_str,userid,newsid,valid,type,title,content)" " values ('%s',%u,%d,%u,%u,'%s','%s')" ,proofid.c_str(),glocal.userid,glocal.newsid_num,glocal.valid,glocal.type,glocal.title,glocal.text)!=-1){ glocal.trli_writed_client.rep_addproof(true,proofid.c_str(),""); trli_log_addproof (glocal.flog,glocal.userid_str,proofid ,glocal.newsid,glocal.valid,glocal.type,glocal.title,glocal.text,time(NULL)); // We do not care if the following updates fail, because everything is recomputed once in a while // Update the proof count of the news sql_action ("update news set nbproofs=nbproofs+1,updated=now() where newsid=%d",glocal.newsid_num); (glocal.con_comp,glocal.newsid,proofid); }else{ glocal.trli_writed_client.rep_addproof(false,"","internal error2"); } } }else{ rep_addproof(false,"","not connected"); } // sessionid proofid vote text = success:b commentid msg glocal int vote = vote; glocal const char *text = text; glocal string userid_str; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,glocal.userid_str); if (glocal.userid != 0){ glocal const char *proofid_str = proofid; ("select proofid,newsid from proofs where proofid_str='%s'",proofid); glocal.trli_writed_client.rep_addcomment(false,"","proof does not exist"); glocal int proofid_num = atoi(row[0]); glocal int newsid_num = atoi(row[1]); // Check if this user as already created a comment ("select commentid,commentid_str from comments where proofid=%d and userid=%u",glocal.proofid_num,glocal.userid); if (glocal.writeonce_comment){ glocal.trli_writed_client.rep_addcomment(false,"","A comment/vote can't be modified"); }else{ const char *commentid_str = row[1]; if(sql_action ("update comments set vote=%d,content='%s' where commentid=%s and userid=%u" ,glocal.vote,glocal.text,row[0],glocal.userid)==-1){ glocal.trli_writed_client.rep_addcomment(false,"","internal error1"); }else{ sql_action ("update news set updated=now() where newsid=%d",glocal.newsid_num); glocal.trli_writed_client.rep_addcomment(true,row[1],"Comment updated"); trli_log_addcomment (glocal.flog,glocal.userid_str,commentid_str,glocal.proofid_str,glocal.vote ,glocal.text,time(NULL)); (glocal.con_comp,glocal.proofid_str); } } string commentid = trli_makeid (glocal.noproc); if (sql_action("insert into comments (commentid_str,userid,proofid,vote,content)" " values ('%s',%u,%d,%u,'%s')" ,commentid.c_str(),glocal.userid,glocal.proofid_num,glocal.vote,glocal.text)!=-1){ glocal.trli_writed_client.rep_addcomment(true,commentid.c_str(),""); trli_log_addcomment (glocal.flog,glocal.userid_str,commentid,glocal.proofid_str,glocal.vote ,glocal.text,time(NULL)); // We do not care if the following updates fail, because everything is recomputed once in a while // Update the comment count of the news sql_action ("update news set nbcomments=nbcomments+1,updated=now() where newsid=%d",glocal.newsid_num); // Update the comment count of the proofs sql_action ("update proofs set nbcomments=nbcomments+1 where proofid=%d",glocal.proofid_num); (glocal.con_comp,glocal.proofid_str); }else{ glocal.trli_writed_client.rep_addproof(false,"","internal error2"); } } glocal const char *name = name; glocal const char *email = email; glocal const char *password = password; (*glocal.usq,"select email from users where email='%s'",email); // Email already exist glocal.trli_writed_client.rep_adduser ("","An account using this email already exists"); (*glocal.usq,"select name from users where name='%s'",glocal.name); glocal.trli_writed_client.rep_adduser ("","An account is already using this nickname"); glocal string id_str = trli_makeid (glocal.noproc); if (sql_action(*glocal.usq,"insert into users (name,email,password,userid_str) values ('%s','%s',password('%s'),'%s')" ,glocal.name,glocal.email,glocal.password,glocal.id_str.c_str())==-1){ glocal.trli_writed_client.rep_adduser ("","can't create"); }else if (sql_action("insert into id2name (userid,name) values (%d,'%s')",glocal.usq->getlastid(),glocal.name)==-1){ glocal.trli_writed_client.rep_adduser ("","can't create2"); }else{ glocal.trli_writed_client.rep_adduser (glocal.id_str,""); // Retrieve the password hashed by MySQL (*glocal.usq,"select password from users where email='%s'",glocal.email); trli_log_adduser (glocal.flog,glocal.id_str,glocal.name,glocal.email,row[0],time(NULL)); if (glocal.mailon){ writed_mail_newaccount(glocal.mailserver,glocal.mailport,glocal.mailfrom ,glocal.name,glocal.email,glocal.id_str); } } glocal const char *confirmid = confirmid; (*glocal.usq,"select userid from users where userid_str='%s' and confirmed is null and disabled is null" ,confirmid); if (sql_action(*glocal.usq,"update users set confirmed=now() where userid=%s",row[0])!=-1){ glocal.trli_writed_client.rep_confirmuser(true,"New user confirmed"); trli_log_confirmuser (glocal.flog,glocal.confirmid,time(NULL)); }else{ glocal.trli_writed_client.rep_confirmuser(false,"Error, can't confirm new user"); } printf ("Confirm unknown users: %s\n",glocal.confirmid); glocal.trli_writed_client.rep_confirmuser(false,"Error, unknown confirmation ID"); glocal const char *sessionid=sessionid; glocal string userid_str; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,glocal.userid_str); if (glocal.userid != 0){ glocal string deleteid = trli_makeid(glocal.noproc); if (sql_action(*glocal.usq,"update users set deleteid='%s' where userid=%u",glocal.deleteid.c_str() ,glocal.userid)!=-1){ (*glocal.usq,"select email from users where userid=%u",glocal.userid); glocal.trli_writed_client.rep_deleteuser (row[0],glocal.deleteid.c_str()); trli_log_deleteuser (glocal.flog,glocal.userid_str,glocal.deleteid); } } glocal const char *confirmid = confirmid; (*glocal.usq,"select userid,userid_str from users where deleteid='%s' and deleted is null and disabled is null" ,confirmid); 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){ // And we terminated all sessions for this user (glocal.con,userid); trli_log_confirmdelete (glocal.flog,userid_str,glocal.confirmid); glocal.trli_writed_client.rep_confirmdelete (true,""); } glocal.trli_writed_client.rep_confirmdelete (false,"no user"); glocal const char *email = email; glocal const char *sessionid = sessionid; (*glocal.usq,"select userid,userid_str,name,email,lang,admin from users where email='%s' and password=password('%s')" " and disabled is null and deleted is null and confirmed is not null and nbfail < 3",email,password); debug_printf (D_PROTO,"login ok\n"); int userid = atoi(row[0]); (glocal.con,glocal.sessionid,userid,row[1],row[2],row[3],atoi(row[4]),atoi(row[5])); if (internal_error){ glocal.trli_writed_client.rep_login (false); }else{ debug_printf (D_PROTO,"login session ok %s\n",glocal.sessionid); sql_action (*glocal.usq,"update users set lastaccess=now() where email='%s'",glocal.email); glocal.trli_writed_client.rep_login (true); } // It fails, why ? debug_printf (D_PROTO,"login failed\n"); (*glocal.usq,"select userid,email,disabled,deleted,confirmed,nbfail from users where email='%s'" ,glocal.email); if (row[2] != NULL || row[3] != NULL || row[4] == NULL){ // disabled or deleted or not confirmed, nothing to do }else if (atoi(row[5]) < 3){ sql_action (*glocal.usq,"update users set nbfail=nbfail+1 where email='%s'",glocal.email); } glocal.trli_writed_client.rep_login (false); glocal const char *sessionid=sessionid; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid); if (glocal.userid != 0){ (glocal.con,glocal.sessionid); } glocal bool success = false; glocal vector news; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid); if (glocal.userid != 0 && trli_isadmin(glocal.usq,glocal.userid)){ ("select newsid_str from news where approved is null and rejected is null order by newsid limit %u,%u",offset,nb); glocal.news.push_back(row[0]); glocal.success = true; } rep_listnewnews(glocal.success,glocal.news); bool success; string msg; string approved_by_id; trli_approve_reject (glocal.con,glocal.usq,sessionid,newsid,false,success,approved_by_id,msg); rep_rejectnews (success,msg.c_str()); if (success) trli_log_rejectnews (glocal.flog,newsid,approved_by_id,time(NULL)); bool success; string msg; string approved_by_id; trli_approve_reject (glocal.con,glocal.usq,sessionid,newsid,true,success,approved_by_id,msg); rep_approvenews (success,msg); if (success) trli_log_approvenews (glocal.flog,newsid,approved_by_id,time(NULL)); glocal bool success=false; glocal bool updated=false; glocal string msg; glocal const char *content = content; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid); if (glocal.userid != 0 && trli_isadmin(glocal.usq,glocal.userid)){ ("select content,newsid from news where newsid_str='%s'",newsid); if(strcmp(glocal.content,row[0])!=0){ if (sql_action("update news set content='%s' where newsid=%s",glocal.content,row[1])==-1){ glocal.msg = "failed to update"; }else{ glocal.msg = "content updated"; glocal.success = true; glocal.updated = true; } }else{ glocal.success = true; glocal.msg = "content identical"; } } rep_modifynews (glocal.success,glocal.msg); if (glocal.updated) trli_log_modifynews (glocal.flog,newsid,content); glocal bool success=false; glocal bool updated=false; glocal string msg; glocal const char *blogid_str = blogid; glocal const char *title = title; glocal const char *content = content; glocal const char *created = created; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid); if (glocal.userid != 0 && trli_isadmin(glocal.usq,glocal.userid)){ ("select title,content,blogid from blog where blogid_str='%s'",blogid); if(strcmp(glocal.title,row[0])!=0 || strcmp(glocal.content,row[1])!=0){ if (sql_action("update blog set title='%s',content='%s' where blogid=%s" ,glocal.title,glocal.content,row[2])==-1){ glocal.msg = "failed to update"; }else{ glocal.msg = "content updated"; glocal.success = true; glocal.updated = true; } }else{ glocal.msg = "content identical"; glocal.success = true; } if (sql_action("insert into blog (blogid_str,title,content,created) values ('%s','%s','%s','%s')" ,glocal.blogid_str,glocal.title,glocal.content,glocal.created)!=-1){ glocal.success = true; glocal.msg = "blog entry added"; glocal.updated = true; }else{ glocal.msg = "Failed to insert"; } } rep_addblog (glocal.success,glocal.msg); if (glocal.updated) trli_log_addblog (glocal.flog,blogid,title,content,created); glocal bool success = false; glocal string msg; glocal const char *content = content; string userid_str; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,userid_str); if (glocal.userid != 0){ ("select blogid from blog where blogid_str='%s'",blogid); glocal const char *blogid = row[0]; ("select content from blogcomments where blogid=%s and userid=%u" ,row[0],glocal.userid); // The user has already have entered the comment if (strcmp(row[0],glocal.content)==0){ glocal.msg = "Content identical"; glocal.success = true; }else{ if (sql_action("update blogcomments set content='%s' where userid=%u and blogid=%s" ,glocal.content,glocal.userid,glocal.blogid)==-1){ glocal.msg = "Failed to update"; }else{ glocal.success = true; glocal.msg = "Content updated"; } } if (sql_action ("insert into blogcomments (userid,blogid,content) values (%u,%s,'%s')" ,glocal.userid,glocal.blogid,glocal.content)==-1){ glocal.msg = "Can't insert"; }else{ glocal.success = true; glocal.msg = "Content inserted"; } glocal.msg = "blog entry does not exist"; }else{ glocal.msg = "Unknown user"; } rep_addblogcomment (glocal.success,glocal.msg); if (glocal.success) trli_log_addblogcomment (glocal.flog,blogid,userid_str,content,time(NULL)); // Create a web session, not associated with any user glocal string sessionid = trli_makeid (glocal.noproc); (glocal.con,glocal.sessionid.c_str()); if (internal_error){ glocal.trli_writed_client.rep_createsession (""); }else{ debug_printf (D_PROTO,"create session ok %s\n",glocal.sessionid.c_str()); glocal.trli_writed_client.rep_createsession (glocal.sessionid.c_str()); } // sessionid newsid replyto title content = success:b msg string userid_str; glocal bool success = false; glocal string msg; glocal string argid; glocal const char *title = title; glocal const char *content = content; glocal const char *replyto = replyto; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,userid_str); glocal int newsid = trli_rec_getid("select newsid from news where newsid_str='%s'",newsid); if (glocal.newsid == -1){ glocal.msg = "Invalid news"; }else{ glocal int replyid = -1; if (glocal.replyto[0] != '\0'){ glocal.replyid = trli_rec_getid("select argid from arguments where argid_str='%s'",glocal.replyto); }else{ glocal.replyid = 0; } if (glocal.replyid == -1){ glocal.msg = "Invalid replyto"; }else{ glocal.argid = trli_makeid (glocal.noproc); if (sql_action("insert into arguments (argid_str,userid,newsid,replyto,title,content)" " values ('%s',%d,%d,%d,'%s','%s')" ,glocal.argid.c_str(),glocal.userid,glocal.newsid,glocal.replyid,glocal.title,glocal.content)==-1){ glocal.msg = "Can't insert"; }else{ glocal.success = true; } } } if (glocal.success){ sql_action ("update news set updated=now() where newsid=%d",glocal.newsid); trli_log_addargument(glocal.flog,glocal.argid,userid_str,newsid,replyto,time(NULL),title,content); (glocal.con_comp,newsid,glocal.argid); } rep_addargument (glocal.success,glocal.msg,glocal.argid); // sessionid newsid url content = success:b msg string userid_str; glocal bool is_admin = false; glocal bool success = false; glocal bool is_approved = false; glocal string msg; glocal const char *url = url; glocal const char *content = content; glocal int newsid=-1; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,userid_str); if (glocal.userid != 0){ glocal.is_admin = trli_isadmin (glocal.usq, glocal.userid); glocal.newsid = trli_rec_getid("select newsid from news where newsid_str='%s'",newsid); if (glocal.newsid == -1){ glocal.msg = "Invalid news"; }else{ ("select content from extraurls where newsid=%d and url='%s'",glocal.newsid,url); if (strcmp(row[0],glocal.content)==0 || !glocal.is_admin){ glocal.msg = "Url already there"; }else if (sql_action("update extraurls set content='%s' where newsid=%d and url='%s'" ,glocal.content,glocal.newsid,glocal.url)==-1){ glocal.msg = "Internal error"; }else{ glocal.msg = "Content updated"; glocal.success = true; } // For now, we let non admin post extra urls pre-approved if (glocal.is_admin || 1){ if (sql_action("insert into extraurls (userid,newsid,url,content,approved) values (%u,%d,'%s','%s',now())" ,glocal.userid,glocal.newsid,glocal.url,glocal.content)==-1){ glocal.msg = "Internal error"; }else{ glocal.msg = "Url added"; glocal.success = true; glocal.is_approved = true; } }else{ if (sql_action("insert into extraurls (userid,newsid,url,content) values (%u,%d,'%s','%s')" ,glocal.userid,glocal.newsid,glocal.url,glocal.content)==-1){ glocal.msg = "Internal error"; }else{ glocal.msg = "Url added"; glocal.success = true; } } } } if (glocal.success){ sql_action ("update news set updated=now() where newsid=%d",glocal.newsid); time_t now = time(NULL); trli_log_addnewsurl(glocal.flog,userid_str,newsid,url,content,now); if (glocal.is_approved) trli_log_approvenewsurl(glocal.flog,newsid,url,now); } rep_addnewsurl (glocal.success,glocal.msg); // sessionid newsid url = success:b msg string userid_str; glocal bool success = false; glocal string msg = "Only administrator are allowed"; glocal const char *url = url; glocal int newsid=-1; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid,userid_str); if (glocal.userid != 0){ bool is_admin = trli_isadmin (glocal.usq, glocal.userid); if (is_admin){ int newsid_num = trli_rec_getid("select newsid from news where newsid_str='%s'",newsid); if (newsid_num == -1){ glocal.msg = "Invalid news"; }else if (sql_action("update extraurls set approved=now() where newsid=%d and url='%s'" ,newsid_num,url)==-1){ glocal.msg = "Internal error"; }else{ glocal.msg = ""; glocal.success = true; } } } if (glocal.success){ trli_log_approvenewsurl(glocal.flog,newsid,url,time(NULL)); } rep_approvenewsurl (glocal.success,glocal.msg); glocal bool bdtrli=false; glocal bool bdusers=false; glocal bool sessiond=false; glocal bool compute=false; (*glocal.usq,"select count(*) from users"); glocal.bdusers=true; ("select count(*) from id2name"); glocal.bdtrli=true; (glocal.con); if (success) glocal.sessiond = true; (glocal.con_comp); glocal.compute=success; rep_test (glocal.bdtrli,glocal.bdusers,glocal.sessiond,glocal.compute); glocal const vector *subjects = &subjects; glocal const char *newsid_str = newsid; glocal bool success = false; glocal string msg; glocal unsigned userid = trli_getsessionuser(glocal.con,sessionid); if (glocal.userid != 0 && trli_isadmin(glocal.usq,glocal.userid)){ glocal vector new_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.new_ids.push_back(atoi(row[0])); if (glocal.new_ids.size() != subjects.size()){ glocal.msg = "One or more invalid subject(s)"; }else{ ("select newsid from news where newsid_str='%s'",newsid); unsigned newsid = atoi(row[0]); glocal vector old_ids; ("select subjectid from subnews where newsid=%u",newsid); glocal.old_ids.push_back(atoi(row[0])); if (trli_compare(glocal.old_ids,glocal.new_ids)==0){ glocal.success = true; glocal.msg = "No change"; }else{ if (sql_action("delete from subnews where newsid=%u",newsid)==-1){ glocal.msg = "Can't delete old assigment"; }else{ string q="insert into subnews (newsid,subjectid)"; const char *sep = "values"; for (auto sid:glocal.new_ids){ q += string_f(" %s (%u,%d)",sep,newsid,sid); sep = ","; } if (sql_action(q.c_str())==-1){ glocal.msg = "Can't insert new assignments"; }else{ glocal.success = true; vector subs; for (auto s:(*glocal.subjects)) subs.push_back(s); trli_log_assignsubjects (glocal.flog,glocal.newsid_str,subs); } } } } }else{ glocal.msg = "Not admin"; } rep_assignsubjects(glocal.success,glocal.msg); tlmp_error ("Client: Invalid command: %s\n",line); endclient = true; fflush (glocal.flog); } bool some_errors = false; if (fdpass_setcontrol(s,glocal.control,glocal.user)==-1){ some_errors = true; } if (!some_errors && s.is_ok()){ s.setrawmode(true); chmod (glocal.clientport.c_str()+5,0666); if (glocal.daemon){ daemon_init(glocal.pidfile,glocal.user); } glocal.flog = fopen (glocal.logfile,"a"); if (glocal.flog == NULL){ tlmp_error ("Can't open logfile %s (%s)\n",glocal.logfile,strerror(errno)); exit (-1); } s.loop(); ret = 0; } fclose (glocal.flog); return ret; return glocal.ret; }