/* * kakumei.c * * Private group web. * * Author: Dario Rodriguez dario@softhome.net * This progran is licensed under the terms of the Affero GPL v1+ */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include "gen_res.h" #include "socklib.h" #include "webkernel.h" #include "kakumei.h" #include "kakumei_session.h" #include "kakumei_pass.h" static int signal_init(int signum, void (*fn)(int)); static void sigint(int signum); volatile int sigint_flag=0; wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr); wk_action http_login(wk *web, int connid, wk_uri *uri, void *userptr); wk_action http_newuser(wk *web, int connid, wk_uri *uri, void *userptr); int main(int argc, char *argv[]) { int port; int timeout=500; kakumei *ka,kastore; memset(&kastore,0,sizeof(kastore)); ka=&kastore; if(argc!=2) { printf("Syntax: %s port\n",argv[0]); return(1); } port=atoi(argv[1]); if((ka->ssel=sselect_init())==NULL) { fprintf(stderr,"ERROR: insufficient memory\n"); return(1); } if((ka->web=wk_init(port,ka->ssel,NULL,callback_http,NULL,NULL,ka))==NULL) { sselect_free(ka->ssel),ka->ssel=NULL; fprintf(stderr,"ERROR: couldn't init web server\n"); return(2); } sigint_flag=0; signal_init(SIGINT,sigint); while(!sigint_flag) { sselect_wait(ka->ssel,timeout); wk_service(ka->web); } wk_free(ka->web),ka->web=NULL; sselect_free(ka->ssel),ka->ssel=NULL; return(0); } int kakumei_uservalid(kakumei *ka, char *username) { if(username==NULL) return(-1); if(strchr(username,'/')!=NULL) return(-1); if(strcmp(username,".")==0 || strcmp(username,"..")==0) return(-1); return(0); } int kakumei_userexists(kakumei *ka, char *username) { char filename[1024]; struct stat st; if(kakumei_uservalid(ka,username)!=0) return(-1); snprintf(filename,sizeof(filename),"%s/%s/passwd",USERSDIR,username); filename[sizeof(filename)-1]='\0'; if(stat(filename,&st)!=0 || !S_ISREG(st.st_mode)) return(-1); return(0); } wk_action callback_http(wk *web, int connid, wk_uri *uri, void *userptr) { kakumei *ka=(kakumei *)userptr; resindex *res; char partialpath[1024]; char *ptr; if(ka==NULL) return(wkact_finished); printf("http: %s\n",uri->path); strncpy(partialpath,uri->path,sizeof(partialpath)-1); partialpath[sizeof(partialpath)-1]='\0'; if((ptr=strchr(partialpath,'?'))!=NULL) *ptr='\0'; if((strcmp(uri->path,"/")==0 && (res=res_find(resindexdata,"index.html"))!=NULL) || (partialpath[0]=='/' && (res=res_find(resindexdata,partialpath+1))!=NULL)) { wk_serve_buffer_as_file(web,connid,res->data,res->len,mime_getdefault(res->name,"application/octet-stream")); return(wkact_finished); } if(memcmp(uri->path,"/login?",7)==0) { return(http_login(web,connid,uri,userptr)); } else if(memcmp(uri->path,"/newuser?",9)==0) { return(http_newuser(web,connid,uri,userptr)); } printf("URI not found: %s\n",uri->path); wk_serve_error(web,connid,wkerr_notfound); return(wkact_finished); } static int signal_init(int signum, void (*fn)(int)) { struct sigaction sa; sa.sa_handler=fn; sigemptyset(&sa.sa_mask); sa.sa_flags=0; return(sigaction(signum,&sa,0)); } static void sigint(int signum) { sigint_flag=1; } wk_action http_login(wk *web, int connid, wk_uri *uri, void *userptr) { char u[128],p[128]; char reply[1024]; char invitepath[1024]; char userpath[1024]; char session[1024]; struct stat st; kakumei *ka=(kakumei *)userptr; if(web==NULL || connid<0 || uri==NULL || ka==NULL) return(wkact_finished); /* internal error */ if(wk_uri_copyvar(uri,"u",u,sizeof(u))==NULL) u[0]='\0'; if(wk_uri_copyvar(uri,"p",p,sizeof(p))==NULL) p[0]='\0'; /* check for invitation */ snprintf(invitepath,sizeof(invitepath),"%s/%s",INVITESDIR,p); invitepath[sizeof(invitepath)-1]='\0'; snprintf(userpath,sizeof(userpath),"%s/%s/passwd",USERSDIR,u); userpath[sizeof(userpath)-1]='\0'; if(strcmp(u,INVITATIONUSER)==0 && strchr(p,'/')==NULL && strchr(p,'.')==NULL && stat(invitepath,&st)==0 && S_ISREG(st.st_mode)) { /* valid invitation */ snprintf(reply,sizeof(reply),"/newuser.html?i=%s",p); reply[sizeof(reply)-1]='\0'; wk_serve_buffer_as_file(web,connid,reply,strlen(reply),"text/plain"); return(wkact_finished); } else if(strchr(u,'/')==NULL && strchr(u,'.')==NULL && stat(userpath,&st)==0 && S_ISREG(st.st_mode) && pass_check(ka,u,p)==0 && session_new(ka,u,session,sizeof(session))!=NULL) { /* valid login */ snprintf(reply,sizeof(reply),"/posts.html?s=%s",session); reply[sizeof(reply)-1]='\0'; wk_serve_buffer_as_file(web,connid,reply,strlen(reply),"text/plain"); return(wkact_finished); } wk_serve_error(web,connid,wkerr_internal); return(wkact_finished); } wk_action http_newuser(wk *web, int connid, wk_uri *uri, void *userptr) { #warning TODO wk_serve_error(web,connid,wkerr_internal); return(wkact_finished); }