aboutsummaryrefslogtreecommitdiff
path: root/xp/navigator/cgi-src/navigator_cgi.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xp/navigator/cgi-src/navigator_cgi.cpp')
-rw-r--r--xp/navigator/cgi-src/navigator_cgi.cpp329
1 files changed, 329 insertions, 0 deletions
diff --git a/xp/navigator/cgi-src/navigator_cgi.cpp b/xp/navigator/cgi-src/navigator_cgi.cpp
new file mode 100644
index 0000000..20e152e
--- /dev/null
+++ b/xp/navigator/cgi-src/navigator_cgi.cpp
@@ -0,0 +1,329 @@
+#include <cstdio>
+#include <cstdlib>
+#include <ctime>
+#include <string>
+#include <sstream>
+
+#include <jsoncpp/json/json.h>
+
+#include <mysql/my_global.h>
+#include <mysql/mysql.h>
+MYSQL* sql;
+const char* rand_ch="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+Json::Value do_login(Json::Value o)
+{
+ MYSQL_RES* sqlr=NULL;
+ MYSQL_ROW row;
+ char q[256];
+ Json::Value ret;
+ std::string usrname=o["username"].asString();
+ std::string passwd=o["passwd"].asString();
+ std::string sessname=o["sessionname"].asString();
+ std::string token;
+ std::string qpwd;
+ if(usrname.length()<1){ret["result"]=1;goto fail;}
+ for(size_t i=0;i<usrname.length();++i)if(!isalnum(usrname[i])&&usrname[i]!='-'&&usrname[i]!='_'){ret["result"]=1;goto fail;}
+ for(size_t i=0;i<passwd.length();++i)if(!isalnum(passwd[i])){ret["result"]=1;goto fail;}
+ for(size_t i=0;i<sessname.length();++i)if(!isalnum(sessname[i])&&sessname[i]!='-'&&sessname[i]!='_'){ret["result"]=1;goto fail;}
+
+ snprintf(q,256,"select password from navigator_user where username='%s'",usrname.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ if(mysql_num_rows(sqlr)!=1){ret["result"]=4;goto fail;}
+ row=mysql_fetch_row(sqlr);
+ qpwd=std::string(row[0],64);
+ if(passwd!=qpwd)
+ {
+ ret["result"]=1;
+ goto fail;
+ }
+ mysql_free_result(sqlr);sqlr=NULL;
+
+ if(!sessname.length())
+ {
+ snprintf(q,256,"delete from navigator_session where sessionname='' and username='%s'",usrname.c_str());
+ mysql_query(sql,q);
+ mysql_commit(sql);
+ }
+ else
+ {
+ snprintf(q,256,"select sessionname from navigator_session where sessionname='%s' and username='%s'",
+ sessname.c_str(),usrname.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ if(mysql_num_rows(sqlr)>0){ret["result"]=2;goto fail;}
+ mysql_free_result(sqlr);sqlr=NULL;
+ }
+
+ do{
+ if(sqlr){mysql_free_result(sqlr);sqlr=NULL;}
+ token="";
+ for(int i=0;i<32;++i)token.push_back(rand_ch[rand()%62]);
+ snprintf(q,256,"select token from navigator_session where token='%s'",
+ token.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ }while(mysql_num_rows(sqlr));
+ mysql_free_result(sqlr);sqlr=NULL;
+
+ snprintf(q,256,"insert into navigator_session values('%s','%s','%s',%lld)",
+ usrname.c_str(),
+ token.c_str(),
+ sessname.c_str(),
+ time(NULL)
+ );
+ mysql_query(sql,q);
+ mysql_commit(sql);
+ ret["result"]=0;
+ ret["token"]=token;
+fail:
+ if(sqlr){mysql_free_result(sqlr);sqlr=NULL;}
+ return ret;
+}
+const int tsl[]={1800,86400,604800,1296000,2592000,5184000,7776000,15552000,31104000};
+void set_session_length(std::string user,int c)
+{
+ char q[256];
+ if(c>7)c=7;if(c<0)c=0;
+ snprintf(q,256,"update navigator_user set session_length=%d where username='%s'",user.c_str());
+ mysql_query(sql,q);
+ mysql_commit(sql);
+}
+int get_session_length(std::string user)
+{
+ MYSQL_RES* sqlr=NULL;
+ MYSQL_ROW row;
+ char q[256];
+ snprintf(q,256,"select session_length from navigator_user where username='%s'",user.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ if(mysql_num_rows(sqlr)!=1){mysql_free_result(sqlr);return -1;}
+ row=mysql_fetch_row(sqlr);
+ int sl=atoi(row[0]);
+ mysql_free_result(sqlr);
+ return sl;
+}
+std::string authenticate(std::string token)
+{
+ MYSQL_RES* sqlr=NULL;
+ MYSQL_ROW row;
+ char q[256];
+ if(token.length()!=32)return "";
+ snprintf(q,256,"select username,sessionname,date from navigator_session where token='%s'",token.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ if(mysql_num_rows(sqlr)!=1){mysql_free_result(sqlr);return "";}
+ row=mysql_fetch_row(sqlr);
+ std::string ret=std::string(row[0]);
+ bool is_temporary=strlen(row[1])>0;
+ long long d=atoll(row[2]);
+ mysql_free_result(sqlr);
+ int sl=get_session_length(ret);
+ if(sl<0||sl>7){return "";}
+ int reall=tsl[is_temporary?0:sl+1];
+ if(time(NULL)-d>reall)
+ {
+ snprintf(q,256,"delete from navigator_session where token='%s'",token.c_str());
+ mysql_query(sql,q);
+ mysql_commit(sql);
+ return "";
+ }
+ return ret;
+}
+Json::Value set_option(Json::Value o)
+{
+ Json::Value ret;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ int opt=o["option"].asInt();
+ int val=o["value"].asInt();
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ switch(opt)
+ {
+ case 0:
+ ret["result"]=0;
+ set_session_length(usr,val);
+ break;
+ default:
+ ret["result"]=1;
+ }
+fail:
+ return ret;
+}
+Json::Value get_option(Json::Value o)
+{
+ Json::Value ret;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ int opt=o["option"].asInt();
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ switch(opt)
+ {
+ case 0:
+ ret["result"]=0;
+ ret["value"]=get_session_length(usr);
+ break;
+ default:
+ ret["result"]=1;
+ }
+fail:
+ return ret;
+}
+Json::Value get_bookmarks(Json::Value o)
+{
+ MYSQL_RES* sqlr=NULL;
+ MYSQL_ROW row;
+ char q[256];
+ Json::Value ret;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ snprintf(q,256,"select bookmarks from navigator_user where username='%s'",usr.c_str());
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ if(mysql_num_rows(sqlr)!=1){mysql_free_result(sqlr);sqlr=NULL;ret["result"]=4;goto fail;}
+ row=mysql_fetch_row(sqlr);
+ ret["result"]=0;
+ ret["bookmarks"]=std::string(row[0]);
+ mysql_free_result(sqlr);sqlr=NULL;
+fail:
+ if(sqlr){mysql_free_result(sqlr);sqlr=NULL;}
+ return ret;
+}
+Json::Value set_bookmarks(Json::Value o)
+{
+ char *q=(char*)malloc(65537);
+ Json::Value ret;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ snprintf(q,65536,"update navigator_user set bookmarks='%s' where username='%s'",o["bookmarks"].asString().c_str(),usr.c_str());
+ mysql_query(sql,q);
+ mysql_commit(sql);
+ ret["result"]=0;
+fail:
+ free(q);
+ return ret;
+}
+Json::Value list_sessions(Json::Value o)
+{
+ MYSQL_RES* sqlr=NULL;
+ MYSQL_ROW row;
+ char q[256];
+ Json::Value ret,ss;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ snprintf(q,256,"select sessionname,date from navigator_session where username='%s'",usr.c_str());
+
+ mysql_query(sql,q);
+ sqlr=mysql_store_result(sql);
+ for(int i=0;row=mysql_fetch_row(sqlr);++i)
+ {
+ Json::Value c;
+ c["sessionname"]=std::string(row[0]);
+ c["date"]=atoi(row[1]);
+ ss[i]=c;
+ }
+ mysql_free_result(sqlr);sqlr=NULL;
+ ret["result"]=0;ret["sessions"]=ss;
+fail:
+ return ret;
+}
+Json::Value remove_session(Json::Value o)
+{
+ char q[256];
+ Json::Value ret;
+ std::string token=o["token"].asString();
+ std::string usr=authenticate(token);
+ std::string sess=o["session"].asString();
+ if(!usr.length()){ret["result"]=1;goto fail;}
+ snprintf(q,256,"delete from navigator_session where username='%s' and sessionname='%s'",usr.c_str(),sess.c_str());
+ mysql_query(sql,q);
+ mysql_commit(sql);
+ ret["result"]=0;
+fail:
+ return ret;
+}
+int main()
+{
+ if(!getenv("CONTENT_LENGTH"))return -1;
+ int len=atoi(getenv("CONTENT_LENGTH"));
+ char *buf;buf=(char*)malloc(len+1);
+ fread(buf,1,len,stdin);buf[len]=0;
+ std::string sbuf(buf,len);
+ free(buf);
+ std::stringstream ss(sbuf);
+ Json::Value o,r;ss>>o;
+
+ sql=mysql_init(NULL);
+ if(!sql)return -1;
+ if(!mysql_real_connect(sql,"localhost","chrisoft",NULL,"chrisoft",0,"/var/run/mysqld/mysqld.sock",0))
+ return -1;
+
+ switch(o.get("op",-1).asInt())
+ {
+ case 0://login
+ r=do_login(o);
+ break;
+ case 1://get bookmarks
+ r=get_bookmarks(o);
+ break;
+ case 2://set bookmarks
+ r=set_bookmarks(o);
+ break;
+ case 3://list sessions
+ r=list_sessions(o);
+ break;
+ case 4://remove session
+ r=remove_session(o);
+ break;
+ case 5://set option
+ r=set_option(o);
+ break;
+ case 6://get option
+ r=get_option(o);
+ break;
+ }
+ printf("Status: 200 OK\r\n");
+ printf("Content-type: application/json; charset=utf-8\r\n\r\n");
+ std::ostringstream oss;
+ oss<<r;
+ fputs(oss.str().c_str(),stdout);
+ return 0;
+}
+//TODO: set cookie in HTTP header
+
+/*
+ * session_length:
+ * 0=1d=86400
+ * 1=7d=604800
+ * 2=15d=1296000
+ * 3=30d=2592000
+ * 4=60d=5184000
+ * 5=90d=7776000
+ * 6=180d=15552000
+ * 7=360d=31104000
+ */
+/*navigator_user:
+ * username:varchar(PRI) passwd:char(64) bookmarks:text
+ *navigator_session:
+ * username:varchar token:char(32)(PRI) sessionname:varchar date:bigint
+ */
+/*
+create table navigator_user(
+ username varchar(32),
+ password char(64),
+ bookmarks text,
+ session_length int,
+ primary key(username)
+);
+create table navigator_session(
+ username varchar(32) not null,
+ token char(32),
+ sessionname varchar(32),
+ date bigint,
+ primary key(token)
+);
+insert into navigator_user values('chrisoft','8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92','',6);
+*/