/*
This file is part of Bolixo.
Bolixo is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Bolixo is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Bolixo. If not, see .
*/
/*
Manage public directory for all bolixo nodes.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "filesystem.h"
#include "bolixo.h"
#include "bolixo.m"
#define INSTRUMENT_DONOTOPEN
#include "instrument.h"
using namespace std;
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;
REQUEST_INFO req;
HANDLE_INFO(){
type = TYPE_NONE;
}
};
#define bo_sessiond_admin_getsessioninfo_NOTNEED
#define bo_sessiond_admin_deletesessions_NOTNEED
#define bo_sessiond_admin_setlang_NOTNEED
#define bo_sessiond_admin_setnotify_NOTNEED
#include "proto/bo-sessiond_admin.protoch"
#define webapi_test_NOTNEED
#define webapi_login_NOTNEED
#define webapi_logout_NOTNEED
#define webapi_addfile_NOTNEED
#define webapi_addfile_bob_NOTNEED
#define webapi_appendfile_NOTNEED
#define webapi_delfile_NOTNEED
#define webapi_undelete_NOTNEED
#define webapi_modifyfile_NOTNEED
#define webapi_modifyfile_bob_NOTNEED
#define webapi_rename_NOTNEED
#define webapi_copy_NOTNEED
#define webapi_readfile_NOTNEED
#define webapi_readfile_bob_NOTNEED
#define webapi_readmore_NOTNEED
#define webapi_mkdir_NOTNEED
#define webapi_rmdir_NOTNEED
#define webapi_listdir_NOTNEED
#define webapi_stat_NOTNEED
#define webapi_set_access_NOTNEED
#define webapi_markview_NOTNEED
#define webapi_verifysign_NOTNEED
#define webapi_list_inboxes_NOTNEED
#define webapi_list_msgs_NOTNEED
#define webapi_sendmsg_NOTNEED
#define webapi_sendmsg_project_NOTNEED
#define webapi_replymsg_NOTNEED
#define webapi_replymsg_project_NOTNEED
#define webapi_sendattach_NOTNEED
#define webapi_sendtalk_NOTNEED
#define webapi_sendtalk_file_NOTNEED
#define webapi_list_talk_NOTNEED
#define webapi_public_listdir_NOTNEED
#define webapi_public_readfile_NOTNEED
#define webapi_public_list_talk_NOTNEED
#define webapi_config_read_NOTNEED
#define webapi_config_write_NOTNEED
#define webapi_getpubkey_NOTNEED
#define webapi_registernode_NOTNEED
#define webapi_remotelogin_NOTNEED
#define webapi_remotepass_NOTNEED
#define webapi_nodelogin_NOTNEED
#define webapi_nodepass_NOTNEED
#define webapi_remote_interest_set_NOTNEED
#define webapi_remote_interest_unset_NOTNEED
#define webapi_contact_manage_NOTNEED
#define webapi_contact_request_NOTNEED
#define webapi_contact_list_NOTNEED
#define webapi_list_contacts_NOTNEED
#define webapi_list_lists_NOTNEED
#define webapi_list_groups_NOTNEED
#include "proto/webapi.protoch"
#include "proto/bolixod_control.protoh"
#include "proto/bolixod_client.protoh"
// Some tests to show everyting is connected
static void bolixod_test (CONNECT_INFO &con_sess, string &msg, bool &sessiond_ok, bool &db_ok, bool &fsok)
{
glocal string msg;
glocal bool sessiond_ok = false;
glocal bool db_ok = false;
glocal bool fsok = false;
(con_sess);
if (!success){
glocal.msg = "sessiond failed";
}else{
glocal.sessiond_ok = true;
}
("select count(*) from nodes");
glocal.db_ok = true;
static const char *testfile = "/var/lib/bolixod/test";
(testfile,false);
glocal.fsok = true;
return 0;
unlink (testfile);
sessiond_ok = glocal.sessiond_ok;
db_ok = glocal.db_ok;
fsok = glocal.fsok;
msg = glocal.msg;
}
static bool nonstrict = false;
static void bolixod_getpubkey (bool use_ssl, const char *hostname, const char *nodename, string &msg)
{
glocal string *msg = &msg;
glocal const char *nodename = nodename;
CONNECT_HTTP_INFO con;
if (nonstrict) con.setnonstrictmode();
con.use_ssl = use_ssl;
const char *pt = strchr(hostname,':');
if (pt == NULL){
con.host = hostname;
con.port = use_ssl ? "443" : "80";
}else{
con.host = string(hostname,pt-hostname);
con.port = pt+1;
}
(con);
if (internal_error){
*glocal.msg = "internal_error webapi:systempubkey";
}else if (pubkey[0] != '\0'){
if (fs_valid_pubkey(pubkey)==-1){
*glocal.msg = string_f("Invalid pubkey for nodename %s",glocal.nodename);
tlmp_error ("Inalid pubkey for nodename %s\n",glocal.nodename);
}else{
if (sql_action("update nodes set created=now(),pub_key='%s' where nodename='%s'"
,pubkey,glocal.nodename)==-1){
*glocal.msg = "Internal error, inserting node pubkey";
tlmp_error ("Internal error, inserting node pubkey\n");
}
}
}else{
*glocal.msg = string_f("No pubkey for nodename %s",glocal.nodename);
tlmp_error ("No pubkey for nodename %s\n",glocal.nodename);
}
}
static void bolixod_getpubkey (const char *nodename, string &msg)
{
if (strncasecmp(nodename,"http://",7)==0){
bolixod_getpubkey(false,nodename+7,nodename,msg);
}else if (strncasecmp(nodename,"https://",8)==0){
bolixod_getpubkey(true,nodename+8,nodename,msg);
}else{
msg = string_f ("getpubkey invalid nodename: %s",nodename);
tlmp_error ("getpubkey invalid nodename: %s\n",nodename);
}
}
// Get the information of this session.
// Return 1 for a new session
// Return 2 for an established session (login done)
// Return -1 for an invalid session
static int bolixod_sessionstate(
CONNECT_INFO &con_sess,
PARAM_STRING session,
unsigned expected_state,
string &nodename,
string &msg)
{
glocal CONNECT_INFO *con_sess = &con_sess;
glocal const char *session = session.ptr;
glocal unsigned expected = expected_state;
glocal string *msg = &msg;
glocal string *nodename = &nodename;
glocal int ret = -1;
(con_sess,session);
if (internal_error){
*glocal.msg = "Internal error";
}else if (!success){
*glocal.msg = "Invalid session";
}else if (userid != glocal.expected){
//tlmp_error ("userid=%d expected=%d session=%s\n",userid,glocal.expected,glocal.session);
*glocal.msg = "Invalid session";
(*glocal.con_sess,glocal.session);
}else{
glocal.ret = userid;
*glocal.nodename = userid_str;
}
return glocal.ret;
}
// Check if the nodename is a valid server URL
static int bolixod_parsenode(const char *node, string &name)
{
int ret = 0;
if (strncasecmp(node,"http://",7)==0){
node += 7;
}else if (strncasecmp(node,"https://",8)==0){
node += 8;
}else{
ret = -1;
}
if (ret != -1){
name = node;
while (*node != '\0'){
if (*node == '/' || *node <= ' '){
ret = -1;
break;
}
node++;
}
}
return ret;
}
static int bolixod_validnode(const char *node)
{
string name;
return bolixod_parsenode (node,name);
}
// Check if the nodename is a valid server URL and belongs to a domain
static int bolixod_validnode(const char *node, const char *domain)
{
string name;
int ret = bolixod_parsenode (node,name);
if (ret != -1){
const char *start = name.c_str();
const char *pt = strchr(start,':');
if (pt != NULL){
name = string(start,pt-start);
}
// The nodename must be a sub-domain of the domain. Not the domain itself.
start = name.c_str();
pt = strstr(start,domain);
if (pt == NULL){
ret = -1;
}else if (strcmp(pt,domain)!=0){
ret = -1;
}else if (pt == start){
ret = -1;
}else if (pt[-1] != '.'){
ret = -1;
}
//tlmp_error ("validnode name=:%s: domain=:%s: ret=%d\n",name.c_str(),domain,ret);
}
return ret;
}
// Check that a file (or a user id) is valid
static int bolixod_validfile(const char *file)
{
int ret = 0;
if (file[0] == '\0'){
ret = -1;
}else{
while (*file != '\0'){
if (*file == '/' || *file <= ' '){
ret = -1;
break;
}
file++;
}
}
return ret;
}
static void bolixod_updatephoto (PARAM_STRING fname, const BOB_TYPE &img)
{
if (img.getsize()==0){
unlink (fname.ptr);
}else{
FILE *fout = fopen (fname.ptr,"w");
if (fout == NULL){
tlmp_error ("Can't open file %s (%s)\n",fname.ptr,strerror(errno));
}else{
fwrite (img.getbuffer(),1,img.getsize(),fout);
fclose (fout);
}
}
}
// Get the directory where photos are stored for this node
static string bolixod_getnodedir(PARAM_STRING nodename)
{
string ret;
const char *node = nodename.ptr;
if (strncasecmp(node,"http://",7)==0){
node += 7;
}else if (strncasecmp(node,"https://",8)==0){
node += 8;
}
return string_f("/var/lib/bolixod/%s",node);
}
// Set the status of the photos (they exist or not)
static void bolixod_setphotos(USERPUBINFO &info)
{
string dir = bolixod_getnodedir(info.nodename);
string tmp = string_f("%s/%s-photo.jpg",dir.c_str(),info.user.c_str());
struct stat st;
if (stat(tmp.c_str(),&st)!=-1) info.photo = true;
tmp = string_f("%s/%s-mini-photo.jpg",dir.c_str(),info.user.c_str());
if (stat(tmp.c_str(),&st)!=-1) info.mini_photo = true;
}
int main (int argc, char *argv[])
{
glocal int ret = -1;
glocal unsigned clientport=0;
glocal const char *dbserv = "localhost";
glocal const char *dbname = "files";
glocal const char *dbuser = "bolixo";
glocal const char *control = "/var/run/bolixod.sock";
glocal const char *user = "bolixo";
glocal const char *sessport = "/dev/sessiond.sock";
glocal const char *mysecret = NULL;
glocal bool daemon = false;
glocal const char *pidfile = "/var/run/bolixod.pid";
glocal const char *client_secretfile = "/etc/bolixo/secrets.client";
glocal const char *domain = "bolixo.org";
glocal unsigned maxaccts = 200;
glocal bool devmode = false;
static const char *tbdic[]={"tlmpsql","bolixo",NULL};
glocal.ret = (argc,argv,tbdic);
setproginfo ("bolixod",VERSION,MSG_U(I_BOLIXOD,"Manage public information for all Bolixo nodes"));
setgrouparg (MSG_U(I_NETWORKING,"Networking"));
setarg ('c',"control",MSG_U(I_BOLIXOD_CONTROL,"Unix socket for bolixod"),glocal.control,false);
setarg ('p',"clientport",MSG_U(I_CLIENTPORT,"Number suffix to Unix socket"),glocal.clientport,false);
setarg (' ',"sessport",MSG_R(O_SESSPORT),glocal.sessport,false);
setarg (' ',"mysecret",MSG_R(O_MYSECRET),glocal.mysecret,true);
setgrouparg (MSG_U(I_DATABASE,"Database"));
setarg (' ',"dbserv",MSG_U(I_DBSERV,"Database server"),glocal.dbserv,false);
setarg (' ',"dbname",MSG_U(I_DBNAME,"Database name"),glocal.dbname,false);
setarg (' ',"dbuser",MSG_U(I_DBUSER,"Database user"),glocal.dbuser,true);
setgrouparg (MSG_U(I_MISC,"Misc."));
setarg (' ',"client_secrets",MSG_R(O_CLIENTSECRETS),glocal.client_secretfile,false);
setarg (' ',"user",MSG_U(I_RUNASUSER,"Run the program as this user"),glocal.user,false);
setarg (' ',"daemon",MSG_U(I_RUNBG,"Run in background"),glocal.daemon,false);
setarg (' ',"pidfile",MSG_U(I_PIDFILE,"File holding the PID of the process"),glocal.pidfile,false);
setarg (' ',"domain",MSG_U(O_DOMAIN,"Accept nodes only from this domain"),glocal.domain,false);
setarg (' ',"maxaccts",MSG_U(O_MAXACCOUNTSPER,"Maximum accounts per servers"),glocal.maxaccts,false);
setarg (' ',"devmode",MSG_U(O_DEVMODE,"Relax rule for registernode API"),glocal.devmode,false);
setarg (' ',"nonstrict",MSG_R(O_NONSTRICT),nonstrict,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;
glocal unsigned nbrequest=0;
glocal CONNECT_INFO con_sess;
glocal map client_secrets;
glocal string controlport = string_f("unix:%s",glocal.control);
glocal pid_t pid = (pid_t)-1;
glocal string unixportclient = string_f("unix:/tmp/bolixod-client-%u.sock",glocal.clientport);
glocal.con_sess.port = glocal.sessport;
glocal.con_sess.secret = glocal.mysecret;
const char *passwd = getenv("BOLIXOD_PWD");
if (passwd == NULL){
tlmp_error (MSG_U(E_DBPASS,"Can't get database password from environment, aborting\n"));
exit (-1);
}
fdpass_readsecrets (glocal.client_secretfile,glocal.client_secrets);
query_setdefaultdb (glocal.dbserv,glocal.dbname,glocal.dbuser,passwd);
query_getdefaultdb()->showerrormode(true);
("0.0.0.0",glocal.unixportclient,5);
HANDLE_INFO *n = new HANDLE_INFO;
info.data = n;
if (glocal.unixportclient == info.port){
n->req.secret = fdpass_findsecret (glocal.client_secrets,info.port);
if (n->req.secret.size() > 0){
n->type = TYPE_CLIENT;
}else{
tlmp_error ("Rejected client connexion from port %s\n",info.port);
endclient = true;
}
}else if (string_cmp(info.port,glocal.controlport)==0){
n->type = TYPE_CONTROL;
}
debug_printf (D_PROTO,"receive line: %s\n",line);
HANDLE_INFO *c = (HANDLE_INFO*)info.data;
static const char *tbtype[]={"none","control request","client request"};
ERROR_PREFIX prefix ("%s:",tbtype[c->type]);
if (c->type == TYPE_CONTROL){
(this,c->req,line, info.linelen,endserver, endclient, no,c);
vector tb;
tb.push_back(string_f ("Version: %s",VERSION));
tb.push_back(string_f ("maxaccts: %u",glocal.maxaccts));
tb.push_back(string_f ("nbrequest: %u",glocal.nbrequest));
tb.push_back(string_f ("devmode: %d",glocal.devmode));
tb.push_back(string_f("nonstrict: %d",nonstrict));
instrument_status(tb);
rep_status(tb);
toggle_instrument_file(on);
endserver = true;
glocal string msg;
("select nodeid from nodes where nodename='%s'",nodename);
glocal.msg = "Nodename not found";
if (sql_action("delete from nodes where nodeid=%s",row[0])==-1){
glocal.msg = "Internal error, can't delete node";
}else if (sql_action("delete from emails where nodeid=%s",row[0])==-1){
glocal.msg = "Internal error, can't delete emails for this node";
}
if (glocal.msg.size() > 0){
rep_deletenode (false,glocal.msg);
}else{
rep_deletenode (true,"");
}
if (on){
debug_seton();
}else{
debug_setoff();
}
debug_setfdebug (filename);
string msg;
bool sessiond,db,fsok;
bolixod_test (glocal.con_sess,msg,sessiond,db,fsok);
rep_test(msg,sessiond,db,fsok);
tlmp_error ("One error\n");
// connectto port send
glocal const char *send = send;
glocal vector lines;
// We want to test bolixod connectivity to the outside
(connectto,port,5);
sendf ("%s\n",glocal.send);
glocal.lines.push_back(line);
end = true;
glocal.lines.emplace_back(string_f("fail: %s\n",strerror(errno)));
rep_help_connect (glocal.lines);
tlmp_error ("Control: Invalid command: %s\n",line);
endclient = true;
}else if (c->type == TYPE_CLIENT){
glocal.nbrequest++;
(this,c->req,line, info.linelen,endserver, endclient, no,c);
// Register a new node
// nodename
glocal string msg;
glocal const char *nodename = nodename;
if (!glocal.devmode && strncasecmp(nodename,"https://",8) != 0){
glocal.msg = "Invalid nodename, only https node accepted";
}else if (bolixod_validnode (nodename,glocal.domain) == -1){
glocal.msg = "Invalid nodename";
}else{
("select pub_key from nodes where nodename='%s'",nodename);
if (row[0] == NULL){
bolixod_getpubkey (glocal.nodename,glocal.msg);
}else{
glocal.msg = "Already registered";
}
if (sql_action("insert into nodes (nodename) value ('%s')",glocal.nodename)==-1){
glocal.msg = "Internal error (nodes table)";
}else{
bolixod_getpubkey (glocal.nodename,glocal.msg);
}
}
if (glocal.msg.size() > 0){
rep_registernode(false,glocal.msg);
}else{
rep_registernode (true,"");
}
// nodename
glocal const char *nodename = nodename;
glocal string msg;
glocal string sessionid;
("select pub_key from nodes where nodename='%s'",nodename);
if (row[0] != NULL){
glocal.sessionid = fs_makeid ();
(glocal.con_sess,glocal.sessionid.c_str());
if (internal_error){
glocal.msg = "Internal error";
}else{
// We are reusing the same session manager as the nodes.
// We preserve the nodename. userid==1 means not logged yet.
(glocal.con_sess,glocal.sessionid
,1,glocal.nodename,"","","",false,0,"");
if (internal_error){
glocal.msg = "Internal error";
}
}
}else{
glocal.msg = "No public key for the node";
}
glocal.msg = "Node not registered";
if (glocal.msg.size() > 0){
rep_nodelogin(false,glocal.msg,"");
}else{
rep_nodelogin(true,"",glocal.sessionid);
}
// session sign
glocal string msg;
glocal const char *session = session;
glocal const char *sign = sign;
glocal string nodename;
int state = bolixod_sessionstate(glocal.con_sess,session,1,glocal.nodename,glocal.msg);
if (state == 1){
("select pub_key from nodes where nodename='%s'",glocal.nodename.c_str());
if (row[0] == NULL){
glocal.msg = MSG_R(E_NOPUBKEY);
}else{
EVP_PKEY *p = fs_load_public (row[0]);
if (p != NULL){
string sig = glocal.sign;
strip_end (sig);
if (fs_verify(glocal.session,p,sig)==-1){
glocal.msg = MSG_R(E_SIGNOMATCH);
}else{
// We switch userid to 2, it means login completed
(glocal.con_sess,glocal.session
,2,glocal.nodename,"","","",false,0,"");
if (internal_error){
glocal.msg = "Internal error";
}
}
fs_free_public (p);
}
}
glocal.msg = "Internal error reading public key";
}
if (glocal.msg.size() > 0){
(glocal.con_sess,session);
rep_nodepass(false,glocal.msg);
}else{
rep_nodepass(true,"");
}
// session
glocal string msg;
(glocal.con_sess,session);
if (internal_error){
glocal.msg = "nodelogout failed";
}
if (glocal.msg.size() > 0){
rep_nodelogout(false,glocal.msg);
}else{
rep_nodelogout(true,"");
}
// session user info
// &USERINFO fullname address1 address2 city zipcode state country email phone fax interest
glocal const USERINFO_receive *info = &info;
glocal const char *user = info.user;
glocal string msg;
glocal string nodename;
int state = bolixod_sessionstate(glocal.con_sess,session,2,glocal.nodename,glocal.msg);
if (state == 2){
("select nodes.nodeid,userid from nodes"
" left join users on users.nodeid=nodes.nodeid and users.name='%s'"
" where nodes.nodename='%s'",glocal.user,glocal.nodename.c_str());
if (row[1] == NULL){
if (sql_action("insert into users (nodeid,name,fullname,address1,address2,city,state,country"
" ,zipcode,email,phone,fax,bolixosite,website,interest)"
" value (%s,'%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')"
,row[0],glocal.user
,glocal.info->fullname
,glocal.info->address1
,glocal.info->address2
,glocal.info->city
,glocal.info->state
,glocal.info->country
,glocal.info->zipcode
,glocal.info->email
,glocal.info->phone
,glocal.info->fax
,glocal.info->bolixosite
,glocal.info->website
,glocal.info->interest
)==-1){
glocal.msg = "Internal error, insert in table";
}
}else{
if (sql_action("update users"
" set fullname='%s',address1='%s',address2='%s',city='%s',state='%s',country='%s'"
" ,zipcode='%s',email='%s',phone='%s',fax='%s'"
" ,bolixosite='%s',website='%s',interest='%s'"
" where userid=%s"
,glocal.info->fullname
,glocal.info->address1
,glocal.info->address2
,glocal.info->city
,glocal.info->state
,glocal.info->country
,glocal.info->zipcode
,glocal.info->email
,glocal.info->phone
,glocal.info->fax
,glocal.info->bolixosite
,glocal.info->website
,glocal.info->interest
,row[1])==-1){
glocal.msg = "Internal error, updating table";
}
}
// Copy or remove the photos
string dir = bolixod_getnodedir(glocal.nodename);
mkdir (dir.c_str(),0755);
string tmp = string_f("%s/%s-photo.jpg",dir.c_str(),glocal.user);
bolixod_updatephoto (tmp,glocal.info->photo);
tmp = string_f("%s/%s-mini-photo.jpg",dir.c_str(),glocal.user);
bolixod_updatephoto (tmp,glocal.info->mini_photo);
glocal.msg = "Node not found";
}
if (glocal.msg.size() > 0){
rep_publish(false,glocal.msg);
}else{
rep_publish(true,"");
}
// session user
string msg;
string nodename;
int state = bolixod_sessionstate(glocal.con_sess,session,2,nodename,msg);
if (state == 2){
if (sql_action("delete users from users join nodes on users.nodeid=nodes.nodeid"
" where users.name='%s' and nodes.nodename='%s'",user,nodename.c_str())==-1){
msg = "Internal error, deleting entry";
}else{
// Deletes the photos
string dir = bolixod_getnodedir(nodename);
string tmp = string_f("%s/%s-photo.jpg",dir.c_str(),user);
unlink (tmp.c_str());
tmp = string_f("%s/%s-mini-photo.jpg",dir.c_str(),user);
unlink (tmp.c_str());
}
}
if (msg.size() > 0){
rep_remove(false,msg);
}else{
rep_remove(true,"");
}
// filter:U{FILTER} offset:u nb:u = success:b msg users:v
glocal vector users;
NSQL_REQ query;
query.append ("select name,fullname"
",address1,address2,city,state,country"
",zipcode,email,phone,fax,bolixosite,website,interest,nodename"
" from users join nodes on nodes.nodeid=users.nodeid"
" where ");
auto start_size = query.size();
static const char *sepand = " and ";
const char *sep = "";
if (filter.user[0] != '\0'){
query.appendf ("name like '%%%s%%'",filter.user);
sep = sepand;
}
if (filter.fullname[0] != '\0'){
query.appendf("%sfullname like '%%%s%%'",sep,filter.fullname);
sep = sepand;
}
if (filter.address[0] != '\0'){
query.appendf("%s(address1 like '%%%s%%' or address2 like '%%%s%%')"
,sep,filter.address,filter.address);
sep = sepand;
}
if (filter.city[0] != '\0'){
query.appendf("%scity like '%%%s%%'",sep,filter.city);
sep = sepand;
}
if (filter.state[0] != '\0'){
query.appendf("%sstate like '%%%s%%'",sep,filter.state);
sep = sepand;
}
if (filter.country[0] != '\0'){
query.appendf("%scountry like '%%%s%%'",sep,filter.country);
sep = sepand;
}
if (filter.interest[0] != '\0'){
query.appendf("%sinterest like '%%%s%%'",sep,filter.interest);
}
if (query.size() == start_size){
rep_pub_search (false,"No filter specified",glocal.users);
}else{
query.appendf (" order by name,nodename limit %u,%u",offset,nb);
(query);
USERPUBINFO info;
info.user = row[0];
info.fullname = row[1];
info.address1 = row[2];
info.address2 = row[3];
info.city = row[4];
info.state = row[5];
info.country = row[6];
info.zipcode = row[7];
info.email = row[8];
info.phone = row[9];
info.fax = row[10];
info.bolixosite = row[11];
info.website = row[12];
info.interest = row[13];
info.nodename = row[14];
bolixod_setphotos (info);
glocal.users.push_back(info);
rep_pub_search (true,"",glocal.users);
}
// prefix offset:u nb:u = success:b msg users:v
glocal vector users;
("select users.name,fullname"
",address1,address2,city,state,country"
",zipcode,email,phone,fax,bolixosite,website,interest"
",nodes.nodename"
" from users join nodes on nodes.nodeid=users.nodeid"
" where name >= '%s' order by name limit %u,%u",prefix,offset,nb);
USERPUBINFO info;
info.user = row[0];
info.fullname = row[1];
info.address1 = row[2];
info.address2 = row[3];
info.city = row[4];
info.state = row[5];
info.country = row[6];
info.zipcode = row[7];
info.email = row[8];
info.phone = row[9];
info.fax = row[10];
info.bolixosite = row[11];
info.website = row[12];
info.interest = row[13];
info.nodename = row[14];
bolixod_setphotos (info);
glocal.users.push_back(info);
rep_pub_list (true,"",glocal.users);
// node user file = success:b msg modified content:o
string msg;
BOB_TYPE content;
string modified;
if (bolixod_validnode(node)==-1){
msg = "Invalid node name";
}else if (bolixod_validfile(user)==-1){
msg = "Invalid user";
}else if (bolixod_validfile(user)==-1){
msg = "Invalid file";
}else{
string dir = bolixod_getnodedir(node);
string path = string_f("%s/%s-%s",dir.c_str(),user,file);
FILE *fin = fopen(path.c_str(),"r");
if (fin == NULL){
msg = "Internal error opening file";
tlmp_error ("Can't open file %s (%s)\n",path.c_str(),strerror(errno));
}else{
char buf[REQ_CONTENT_CHUNK];
int len = fread(buf,1,sizeof(buf),fin);
if (len > 0){
struct stat st;
if (fstat(fileno(fin),&st)!=-1){
struct tm *t = localtime(&st.st_mtime);
modified = string_f("%04d/%02d/%02d %2d:%2d:%2d"
,t->tm_year+1900,t->tm_mon+1,t->tm_mday
,t->tm_hour,t->tm_min,t->tm_sec);
}
content.setbuffer(buf,len,true);
}else{
msg = "Internal error reading file";
tlmp_error ("Error reading file %s (%s)\n",path.c_str(),strerror(errno));
}
fclose (fin);
}
}
if (msg.size() > 0){
content.clear();
rep_readfile(false,msg,"",content);
}else{
rep_readfile(true,"",modified,content);
}
// session email userid = success:b msg
glocal const char *email = email;
glocal const char *userid = userid;
glocal string msg;
glocal string nodename;
int state = bolixod_sessionstate(glocal.con_sess,session,2,glocal.nodename,glocal.msg);
if (state == 2){
("select nodeid from nodes where nodename='%s'",glocal.nodename.c_str());
glocal.msg = "Unknown node";
glocal unsigned nodeid = atoi(row[0]);
("select 1 from emails where nodeid=%u and email='%s'"
,glocal.nodeid,glocal.email);
// Already there, ok
if (sql_action("insert into emails (email,userid,nodeid) values ('%s','%s',%u)"
,glocal.email,glocal.userid,glocal.nodeid)==-1){
glocal.msg = "Internal error, emails table";
}
// Compute the number of users for this node
("select count(*) from emails where nodeid=%u",glocal.nodeid);
if (sql_action("update nodes set nbuser=%s where nodeid=%u",row[0],glocal.nodeid)==-1){
tlmp_error ("Internal error updation user count for nodename %s\n",glocal.nodename.c_str());
}
}
if (glocal.msg.size() > 0){
rep_recordemail(false,glocal.msg);
}else{
rep_recordemail(true,"");
}
// email = success:b msg nodename
glocal string msg;
glocal string nodename;
("select nodename from emails"
" join nodes on nodes.nodeid=emails.nodeid"
" where email='%s'",email);
glocal.nodename = row[0];
glocal.msg = "Not found";
if (glocal.msg.size() > 0){
rep_getnode(false,glocal.msg,"");
}else{
rep_getnode(true,"",glocal.nodename);
}
// userid = success:b msg nodename
glocal string msg;
glocal string nodename;
("select distinct nodes.nodename,nodes.nbuser from nodes"
" left join emails on emails.nodeid=nodes.nodeid"
" where nodes.nbuser < %u and nodes.nodeid not in (select nodeid from emails where userid='%s')"
" order by nodes.nbuser asc limit 1"
,glocal.maxaccts,userid);
glocal.nodename = row[0];
glocal.msg = "No node available";
if (glocal.msg.size() > 0){
rep_newacct_findnode(false,"","");
}else{
rep_newacct_findnode(true,"",glocal.nodename);
}
string msg;
bool sessiond,db,fsok;
bolixod_test (glocal.con_sess,msg,sessiond,db,fsok);
rep_test(msg,sessiond,db,fsok);
tlmp_error ("Client: Invalid command: %s\n",line);
endclient = true;
}
bool some_errors = false;
if (fdpass_setcontrol(s,glocal.control,glocal.user)==-1){
some_errors = true;
}
if (!some_errors && s.is_ok()){
chmod (glocal.unixportclient.c_str()+5,0666);
s.setrawmode(true);
if (glocal.daemon){
daemon_init(glocal.pidfile,glocal.user);
}
open_instrument_file();
s.loop();
ret = 0;
}
return ret;
return ret;
return glocal.ret;
}