/** * Read event for EPOLLIN on the httpd protocol module. * * @param dcb The descriptor control block * @return */ static int httpd_read_event(DCB* dcb) { //SESSION *session = dcb->session; //ROUTER_OBJECT *router = session->service->router; //ROUTER *router_instance = session->service->router_instance; //void *rsession = session->router_session; int numchars = 1; char buf[HTTPD_REQUESTLINE_MAXLEN-1] = ""; char *query_string = NULL; char method[HTTPD_METHOD_MAXLEN-1] = ""; char url[HTTPD_SMALL_BUFFER] = ""; int cgi = 0; size_t i, j; int headers_read = 0; HTTPD_session *client_data = NULL; client_data = dcb->data; /** * get the request line * METHOD URL HTTP_VER\r\n */ numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; strcpy(client_data->method, method); /* check allowed http methods */ if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { //httpd_unimplemented(dcb->fd); return 0; } if (strcasecmp(method, "POST") == 0) cgi = 1; i = 0; while (ISspace(buf[j]) && (j < sizeof(buf))) { j++; } while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf))) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; /** * Get the query string if availble */ if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) query_string++; if (*query_string == '?') { cgi = 1; *query_string = '\0'; query_string++; } } /** * Get the request headers */ while ((numchars > 0) && strcmp("\n", buf)) { char *value = NULL; char *end = NULL; numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); if ( (value = strchr(buf, ':'))) { *value = '\0'; value++; end = &value[strlen(value) -1]; *end = '\0'; if (strncasecmp(buf, "Hostname", 6) == 0) { strcpy(client_data->hostname, value); } if (strncasecmp(buf, "useragent", 9) == 0) { strcpy(client_data->useragent, value); } } } if (numchars) { headers_read = 1; memcpy(&client_data->headers_received, &headers_read, sizeof(int)); } /** * Now begins the server reply */ /* send all the basic headers and close with \r\n */ httpd_send_headers(dcb, 1); /** * ToDO: launch proper content handling based on the requested URI, later REST interface * */ dcb_printf(dcb, "Welcome to HTTPD Gateway (c) %s\n\n", version_str); if (strcmp(url, "/show") == 0) { if (strlen(query_string)) { if (strcmp(query_string, "dcb") == 0) dprintAllDCBs(dcb); if (strcmp(query_string, "session") == 0) dprintAllSessions(dcb); } } /* force the client connecton close */ dcb->func.close(dcb); return 0; }
long httpd_client_thread(SOCKET sock) { static timeval tv = {30,30}; long rcv = 0; long post = 0; long post_len = 0; long post_got = 0; long ip = 0; long ok = 0; long fs = 0; char* request = NULL; char* str_tmp = NULL; char* str_tmp2 = NULL; char* cgi_params = NULL; char* query_str = NULL; char* req_page; char buffer[1028]; sHTTPDEnv httpd_env; cutSockf sf; cutMemf mf; cutMemf hdr; cutMemf req; sFDS fd; mb_event mbe = {MBT_WEBPAGE, 0}; httpd_sname(sock,NULL,(DWORD*)&ip); if(!mf.create(4*1024) || !(req.create(1024))) { //malloc error goto Error500; } //////////////////////////////////////// sf.open(sock); //////////////////////////////////////// *fd.fd_array = sock; fd.fd_count = 1; //////////////////////////////////////// httpd_env.sf = &sf; httpd_env.mf = &mf; httpd_env.req = &req; //////////////////////////////////////// while(select(0,(fd_set*)&fd,0,0,&tv) >= 1 && mf.tellpos() < svr_maxrequest) { if(!(rcv = httpd_rrecv(sock,buffer,1024,3000))) { //recv error httpd_logaccess((const char*)mf.getdata(),500,sf.size(),ip); goto End; } if(!mf.write(buffer,rcv)) { goto Error500; } mf.putc(0); if(post == FALSE) { if((rcv = mf.size()) > 4 && (request = (char*)strstr((const char*)mf.getdata(),"\r\n\r\n"))) { httpd_env.var_offset = req.written(); if(httpd_parse_headers(&mf, &httpd_env) != 1) { goto Error; } req.setpos(0); if(httpd_env.method == 1) { post = TRUE; str_tmp = httpd_hdr_get((const char*)req.getdata(),"CONTENT_LENGTH"); post_len = (str_tmp)?(strtoul(str_tmp,NULL,10)):(0); post_got = rcv - (request - ((const char*)mf.getdata()) + 4); if(!post_len || post_got >= post_len) { ok = TRUE; break; } } else { ok = TRUE; break; } } } else { post_got += rcv; if(post_got >= post_len) { ok = TRUE; break; } } } //////////////////////////////////////// if(!ok || mf.size() < 10 || !(request = (char*)mf.getdata())) { goto Error; } //////////////////////////////////////// if(request[4 + post] != '/')goto Error; { str_tmp = strchr(request + 5,' '); if(!str_tmp)goto Error; *str_tmp = '\0'; query_str = strchr(request + 5,'?'); *str_tmp = ' '; } if(post == TRUE) { cgi_params = strstr(request,"\r\n\r\n"); if(!cgi_params)goto Error; httpd_env.post_data = cgi_params + 4; httpd_env.post_length = post_len; if(post_got > post_len) { *(httpd_env.post_data + post_len) = '\0'; } cgi_params = NULL; } if(httpd_env.error_code != 200) { httpd_writeformatted(&sf,"HTTP/1.0 %u ERROR\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>%u ERROR</h4>",httpd_env.error_code,httpd_env.error_code); goto End; } //////////////////////////////////////// if(query_str) { *query_str = '\0'; req_page = request + 4 + post; //*cgi_params = '?'; } else { str_tmp = strchr(request + 4 + post,' '); if(!str_tmp)goto Error; *str_tmp = '\0'; req_page = request + 4 + post; //*str_tmp = ' '; } /////////////////////////// if(svr_auth_required && !httpd_authorize( httpd_hdr_get((const char*)req.getdata(),"HTTP_AUTHORIZATION") )) { goto Error401; } /////////////////////////// strlwr(req_page); httpd_unify(req_page); rcv = strlen(req_page); str_tmp = httpd_hdr_get((const char*)req.getdata(),"HTTP_AUTHORIZATION"); str_tmp2 = inet_ntoa(*(in_addr*)&ip); strncpy(buffer,req_page,sizeof(buffer)-1); ok = httpd_unify(buffer); if(ok && buffer[ok-1]!='/') { buffer[ok]='/'; buffer[ok+1]='\0'; } if((ok = httpd_authorize_host(buffer,str_tmp2?str_tmp2:"0.0.0.0",str_tmp?str_tmp:"")) < 1) { if(ok < 0) { goto Error403; } else { goto Error401; } } /////////////////////////// if(!(*req_page)) { _snprintf(buffer,MAX_PATH,"%s/index.php",svr_wwwroot); req_page = "/index.php"; } else if(req_page[rcv-1]=='/') { _snprintf(buffer,MAX_PATH,"%s%sindex.php",svr_wwwroot,req_page); req_page = buffer + strlen(svr_wwwroot); } else { _snprintf(buffer,MAX_PATH,"%s%s",svr_wwwroot,req_page); } httpd_unify(buffer); ok = help_fileexists(buffer,&fs); if(!ok) { ok = help_direxists(buffer); if(!ok) { goto Error404; } else { httpd_writeformatted(&sf,"HTTP/1.0 301 Moved Permanently\r\nConnection: close\r\nLocation: %s/\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>301 Document moved permanently!</h4>",req_page); goto End; } } else { //do the authorization for vhosts str_tmp = httpd_getextension(buffer); if(str_tmp && true == ut_str_match(".php*", str_tmp)) { if(query_str) { *query_str = '?'; if((str_tmp2 = strchr(query_str+1,' ')) || (str_tmp2 = strchr(query_str,'\r'))) { *str_tmp2 = '\0'; } } mbe.t1 = MBE_HTTPDENV; mbe.p1 = (void*)&httpd_env; if(!httpd_init_hdr(&hdr)) { goto Error500; } httpd_sname(sock,&req,NULL); req.write("SERVER_SOFTWARE\0MBot (c) Piotr Pawluczuk (www.piopawlu.net)",60); //SCRIPT_NAME req.write("SCRIPT_NAME",12); req.write(req_page,strlen(req_page)+1); //PHP_SELF req_page = strrchr(req_page,'/'); if(!req_page) { goto Error404; } req_page++; req.write("PHP_SELF",9); req.write(req_page,strlen(req_page)+1); //END OF VARIABLES req.putc(0); if(!LPHP_ExecutePage(buffer,(query_str)?(query_str+1):NULL, (const char**)&sf,(void*)&mbe,(LPHP_ENVCB)httpd_php_cb,1)) { goto Error500; } if(httpd_env.out_started == 0) { httpd_send_headers(&httpd_env); } httpd_logaccess((const char*)mf.getdata(),200,sf.size(),ip); goto End; } else { if(httpd_sendfile(buffer,&httpd_env,buffer)) { httpd_logaccess((const char*)mf.getdata(),200,sf.size(),ip); } else { httpd_logaccess((const char*)mf.getdata(),404,sf.size(),ip); } goto End; } } /////////////////////////// Error: /////////////////////////// httpd_logaccess((const char*)mf.getdata(),400,sf.size(),ip); httpd_writestring(&sf,"HTTP/1.0 400 Bad Request\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>400 Bad Request</h4>"); goto End; /////////////////////////// Error500: /////////////////////////// httpd_logaccess((const char*)mf.getdata(),500,sf.size(),ip); if(httpd_env.out_started == 0) { httpd_writestring(&sf,"HTTP/1.0 500 Internal Server Error\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>500 Internal Server Error</h4>"); } goto End; /////////////////////////// Error401: /////////////////////////// httpd_logaccess((const char*)mf.getdata(),401,sf.size(),ip); httpd_writestring(&sf,"HTTP/1.0 401 Authorization Required\r\nWWW-Authenticate: Basic realm=\"MSP Server HTTPD\"\r\nstatus: 401 Unauthorized\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>401 Authorization Required</h4>"); goto End; /////////////////////////// Error403: /////////////////////////// httpd_logaccess((const char*)mf.getdata(),401,sf.size(),ip); httpd_writestring(&sf,"HTTP/1.0 403 Access DENIED\r\nWWW-Authenticate: Basic realm=\"MSP Server HTTPD\"\r\nstatus: 403 Access DENIED\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>403 Access DENIED</h4>"); goto End; /////////////////////////// Error404: /////////////////////////// httpd_logaccess((const char*)mf.getdata(),404,sf.size(),ip); httpd_writestring(&sf,"HTTP/1.0 404 Not Found\r\nConnection: close\r\nPragma: no-cache\r\nContent-Type: text/html\r\n\r\n<h4>404 Not Found</h4>"); /////////////////////////// End: /////////////////////////// sf.close(); mf.close(); svr_cur_clients --; return 0; }
/** * Read event for EPOLLIN on the httpd protocol module. * * @param dcb The descriptor control block * @return */ static int httpd_read_event(DCB* dcb) { SESSION *session = dcb->session; ROUTER_OBJECT *router = session->service->router; ROUTER *router_instance = session->service->router_instance; void *rsession = session->router_session; int numchars = 1; char buf[HTTPD_REQUESTLINE_MAXLEN-1] = ""; char *query_string = NULL; char method[HTTPD_METHOD_MAXLEN-1] = ""; char url[HTTPD_SMALL_BUFFER] = ""; size_t i, j; int headers_read = 0; HTTPD_session *client_data = NULL; GWBUF *uri; client_data = dcb->data; /** * get the request line * METHOD URL HTTP_VER\r\n */ numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); i = 0; j = 0; while (!ISspace(buf[j]) && (i < sizeof(method) - 1)) { method[i] = buf[j]; i++; j++; } method[i] = '\0'; strcpy(client_data->method, method); /* check allowed http methods */ if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) { //httpd_unimplemented(dcb->fd); return 0; } i = 0; while ( (j < sizeof(buf)) && ISspace(buf[j])) { j++; } while ((j < sizeof(buf) - 1) && !ISspace(buf[j]) && (i < sizeof(url) - 1)) { url[i] = buf[j]; i++; j++; } url[i] = '\0'; /** * Get the query string if availble */ if (strcasecmp(method, "GET") == 0) { query_string = url; while ((*query_string != '?') && (*query_string != '\0')) { query_string++; } if (*query_string == '?') { *query_string = '\0'; query_string++; } } /** * Get the request headers */ while ((numchars > 0) && strcmp("\n", buf)) { char *value = NULL; char *end = NULL; numchars = httpd_get_line(dcb->fd, buf, sizeof(buf)); if ((value = strchr(buf, ':'))) { *value = '\0'; value++; end = &value[strlen(value) -1]; *end = '\0'; if (strncasecmp(buf, "Hostname", 6) == 0) { strcpy(client_data->hostname, value); } if (strncasecmp(buf, "useragent", 9) == 0) { strcpy(client_data->useragent, value); } } } if (numchars) { headers_read = 1; memcpy(&client_data->headers_received, &headers_read, sizeof(int)); } /** * Now begins the server reply */ /* send all the basic headers and close with \r\n */ httpd_send_headers(dcb, 1); #if 0 /** * ToDO: launch proper content handling based on the requested URI, later REST interface * */ if (strcmp(url, "/show") == 0) { if (query_string && strlen(query_string)) { if (strcmp(query_string, "dcb") == 0) { dprintAllDCBs(dcb); } if (strcmp(query_string, "session") == 0) { dprintAllSessions(dcb); } } } if (strcmp(url, "/services") == 0) { RESULTSET *set, *seviceGetList(); if ((set = serviceGetList()) != NULL) { resultset_stream_json(set, dcb); resultset_free(set); } } #endif if ((uri = gwbuf_alloc(strlen(url) + 1)) != NULL) { strcpy((char *)GWBUF_DATA(uri), url); gwbuf_set_type(uri, GWBUF_TYPE_HTTP); SESSION_ROUTE_QUERY(session, uri); } /* force the client connecton close */ dcb_close(dcb); return 0; }
long httpd_php_cb(long code, void* param1, void* param2, mb_event* mbe) { sHTTPDEnv* env; if(!mbe) { return 0; } env = (sHTTPDEnv*)mbe->p1; if(code == LPHP_CB_SETHDR) { char* hdr = (char*)param1; char* cp = NULL; char* sn; char* sv; char* cx; if(env->out_started || !hdr || !(cp = strchr(hdr,':'))) { return 0; } else { *cp = 0; sn = hdr; sv = cp + 1; cp = strchr(sv,'\r'); if(cp) { *cp = '\0'; cx = cp - 1; while(isspace(*cx) && cx!=sn) { *(cx--)=0; } } while(isspace(*sv)) { sv++; } while(isspace(*sn)) { sn++; } env->hdr[sn] = sv; if(stricmp(sn,"location") == 0) { env->error_code = 301; } return 1; } return 0; } else if(code == LPHP_CB_OUTSTARTED) { //start output if(env->out_started == 0) { httpd_send_headers(env); env->out_started = 1; } return 1; } else if(code == LPHP_CB_GETMETHOD) { //get method return (int)((env->method == 1)?"POST":"GET"); } else if(code == LPHP_CB_GETCOOKIE) { //get cookie return (int)httpd_hdr_get((const char*)env->req->getdata(),"HTTP_COOKIE"); } else if(code == 4) { // n/a return (int)NULL; } else if(code == LPHP_CB_POST_LENGTH) { //get post data length return (int)env->post_length; } else if(code == LPHP_CB_POST_DATA) { //get post data pointer return (int)env->post_data; } else if(code == LPHP_CB_GETENV) { param2 = (void*)httpd_hdr_get((const char*)env->req->getdata(),(const char*)param1); return (long)((param2)?(param2):getenv((const char*)param1)); } else if(code == LPHP_CB_GETCT) { return (long)httpd_hdr_get((const char*)env->req->getdata(),"CONTENT_TYPE"); } else if(code == LPHP_CB_GETCL) { char* tmp = httpd_hdr_get((const char*)env->req->getdata(),"CONTENT_LENGTH"); return (tmp)?(strtoul(tmp,NULL,10)):(0); } else if(code == LPHP_CB_GETVARS) { return ((long)env->req->getdata() + env->var_offset); } else { return NULL; } }