static void * accept_request(void *arg) { int sock = (int)arg; char buf[_SIZE_]; char method[_SIZE_/10]; char url[_SIZE_]; char path[_SIZE_]; memset(buf, '\0', sizeof(buf)); memset(buf, '\0', sizeof(method)); memset(buf, '\0', sizeof(url)); memset(buf, '\0', sizeof(path)); int cgi = 0; int ret = -1; char *query_string = NULL; // 数据参数 int len = sizeof(buf) / sizeof(buf[0]); #ifdef _DEBUG_ do { // http 请求 报文 按行存储 ret = get_line(sock, buf, len); printf("%s", buf); fflush(stdout); } while (ret > 0 && strcmp(buf, "\n") != 0); #endif ret = get_line(sock, buf, len); // 获取请求行 printf("line: %s\n", buf); if (ret < 0) { echo_errno(sock); return (void*)1; } // GET / HTTP/1.0 int i = 0; // method index int j = 0; // buf index // 请求行 包括 【方法(GET/POST)】【url】【HTTP/1.0(1.1)】 // 获取方法 GET/POST while ((i < sizeof(method) - 1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { method[i] = buf[j]; ++i; ++j; } method[i] = '\0'; // strcasecmp 忽略大小写的比较 if (strcasecmp(method, "GET") != 0 && strcasecmp(method, "POST") != 0) { echo_errno(sock); return (void*)2; } // 跳过空格 while (j < sizeof(buf) && isspace(buf[j])) { j++; } i = 0; // 获取url url是除了域名 端口号之后的 /。。。 while ((i < sizeof(url) - 1) && (j < sizeof(buf)) && (!isspace(buf[j]))) { url[i++] = buf[j++]; } url[i] = '\0'; //GET 所传递的参数 在URL中, 从server的QUERY_STRING 中获取 //POST 所传递的参数 在 数据包中 从server环境变量中CONTENT_LENGTH 环境变量中获取参数 数据的长度 if (strcasecmp(method, "POST") == 0) { cgi = 1; } if (strcasecmp(method, "GET") == 0) { query_string = url; // 路径和数据参数 以?分隔 如 http:// baidu.com /s ? k = v while (*query_string != '\0' && *query_string != '?') { ++query_string; } if(*query_string == '?') // GET 带参数 需要进一步处理参数 { cgi = 1; *query_string++ = '\0'; } } // 没指定具体网页 加默认网页 和 根文件夹(安全考虑) sprintf(path, "httpdoc%s", url); if (path[strlen(path) - 1] == '/') { strcat(path, "index.html"); } // method , query_string, cgi, path struct stat st; if (stat(path, &st) < 0) // 测文件在不在 { echo_errno(sock); return (void*)3; } else { if (S_ISDIR(st.st_mode))// 测是不是 文件夹 { strcat(path, "/index.html"); } else if( (st.st_mode & S_IXUSR) ||\ (st.st_mode & S_IXGRP) ||\ (st.st_mode & S_IXOTH)) // 查看cgi执行权限 { cgi = 1; } else {} if (cgi) { exec_cgi(sock, method, path, query_string); } else { clear_header(sock); // echo_www(sock, path, st.st_size); } } }
int handler_msg(int sock) //浏览器请求处理函数 { char buf[SIZE]; int count=get_line(sock,buf); int ret=0; char method[32]; char url[SIZE]; char *query_string=NULL; int i=0; int j=0; int cgi=0; //获取请求方法和请求路径 while(j<count) { if(isspace(buf[j])) { break; } method[i]=buf[j]; i++; j++; } method[i]='\0'; while(isspace(buf[j])&&j<SIZE) //过滤空格 { j++; } if(strcasecmp(method,"POST")&&strcasecmp(method,"GET")) { printf_log("method failed",FATAL); echo_error(sock,405); ret=5; goto end; } if(strcasecmp(method,"POST")==0) { cgi=1; } i=0; while(j<count) { if(isspace(buf[j])) { break; } if(buf[j]=='?') { query_string=&url[i]; query_string++; url[i]='\0'; } else url[i]=buf[j]; j++; i++; } url[i]='\0'; if(strcasecmp(method,"GET")==0&&query_string!=NULL) { cgi=1; } //找到请求的资源路径 char path[SIZE]; sprintf(path,"wwwroot%s",url); if(path[strlen(path)-1]=='/') //判断浏览器请求的是不是目录 { strcat(path,"index.html"); //如果请求的是目录,则就把该目录下的首页返回回去 } struct stat st; if(stat(path,&st)<0) //获取客户端请求的资源的相关属性 { printf_log("stat path faile\n",FATAL); echo_error(sock,404); ret=6; goto end; } else { if(S_ISDIR(st.st_mode)) { strcat(path,"/index.html"); } if(st.st_mode & (S_IXUSR | S_IXOTH | S_IXGRP)) { cgi=1; } } if(cgi) //请求的是可执行程序或者带参数用cgi程序处理 { ret=excu_cgi(sock,method,path,query_string); //处理CGI模式的请求 } else { clear_header(sock); ret=echo_www(sock,path,st.st_size); //如果是GET方法,而且没有参数,请求的也不是可执行程序,则直接返回资源 } end: close(sock); return ret; }
static void * accept_request(void* arg) { int sock = (int)arg; printf("%d\n",sock); char buf[SIZE]; int ret = 0; #ifdef _DEBUG_ do { ret = get_line(sock,buf,size); printf("%s",buf); fflush(stdout); }while(ret > 0 && strcmp(buf,'\n')); #endif char method[SIZE / 10]; char url[SIZE]; char* query_string = NULL; int cgi = 0; char path[SIZE]; memset(method,'\0',sizeof(method)); memset(url,'\0',sizeof(url)); ret = get_line(sock,buf,sizeof(buf)); if(ret < 0) { echo_errno(sock,1); return (void*)1; } printf("%s\n",buf); //1 get method //GET //xx//yy HTTP/1.1 int i = 0; int j =0; while(i< sizeof(method) - 1 && !isspace(buf[j]) && j < sizeof(buf) ) { method[i]=buf[j]; ++i; ++j; } method[i] = '\0'; //2 check method if(strcasecmp(method,"GET")!=0 && strcasecmp(method,"POST") != 0) { echo_errno(sock,1); return (void*)2; } //3 get url first step space while(isspace(buf[j])) { ++j; } i=0; while(!isspace(buf[j])&& (i < sizeof(url)-1) && j < sizeof(buf)) { url[i] = buf [j]; ++i; ++j; } if(strcasecmp(method,"POST") == 0) { cgi = 1; } printf("method: %s,url_path :%s\n ",method,url); if(strcasecmp(method,"GET") == 0) { query_string = url; } char *start = url; while( *start != '\0') { if( *start == '?') { cgi = 1; *start = '\0'; query_string = start+1; break; } ++start; } sprintf(path,"htdoc%s",url); if(path[strlen(path)-1] == '/') { strcat(path,"index.html"); } // printf("path:%s\n",path); printf("cgi:%d\n",cgi); //method,query_string,cgi,path struct stat st; if(stat(path,&st) < 0)//default -> htdoc/index.html { printf("stat error\n"); echo_errno(sock,1); return (void*)-3; } else { if(S_ISDIR(st.st_mode)) { strcpy(path,"htdoc/index.html"); } if(( st.st_mode & S_IXGRP)||\ ( st.st_mode & S_IXGRP)||\ st.st_mode & S_IXOTH) { cgi = 1; } else {} //path cgi if(cgi) { printf("cgi mode\n"); execut_cgi(sock,path,method,query_string); } else// 请求首页内容 { clear_head(sock); echo_www(sock,path,st.st_size); } } close(sock); //no face link return (void*) 0; }
static void* accept_request(void *arg) //static { int sock = (int)arg; char buf[SIZE]; int len = sizeof(buf)/sizeof(*buf); char method[SIZE/10]; char url[SIZE]; char path[SIZE]; int ret = -1; int i = 0; int j = 0; char *query_string = NULL; //aim at val(can shu) int cgi = 0; #ifdef _DEBUG_ // do // { // ret = get_line(sock, buf, len); // printf("%s", buf); // fflush(stdout); // }while(ret > 0 && (strcmp(buf, "\n") != 0) ); #endif memset(buf, '\0', sizeof(buf)); memset(method, '\0', sizeof(method)); memset(url, '\0', sizeof(url)); memset(path, '\0', sizeof(buf)); //Request Line ret = get_line(sock, buf, len); if(ret <= 0) { echo_errno(sock); return (void*)1; } i = 0; //method index j = 0; //buf index while((i < (sizeof(method)/sizeof(*method) - 1)) && (j < sizeof(buf)/sizeof(*buf) - 1) && (!isspace(buf[j]) ) ) { method[i] = buf[j]; ++i; ++j; } method[i] = '\0'; if((strcasecmp(method, "GET") != 0) && (strcasecmp(method, "POST")) ) { //echo_errno(sock); return (void*)2; } //URL while(isspace(buf[j])) //Remove Space { ++j; } i = 0; while( ( i < sizeof(url)/sizeof(*url)-1 ) && (j < sizeof(buf)/sizeof(*buf)) && (!isspace(buf[j])) ) { url[i] = buf[j]; ++i; ++j; } url[i] = '\0'; if( strcasecmp(method, "POST") == 0 ) { cgi = 1; sprintf(path, "%s", url+1); } if( strcasecmp(method, "GET") == 0 ) { query_string = url; while( *query_string != '\0' && *query_string != '?' ) { query_string++; } if(*query_string == '?') { cgi = 1; *query_string = '\0'; ++query_string; } } if( strcasecmp(method, "GET") == 0 ) { sprintf(path, "htdoc%s", url); if( path[strlen(path)-1] == '/' ) { strcat(path, "index.html"); } } struct stat st; if( stat(path, &st) < 0 ) { //echo_errno(); //404 return (void*)3; } else //case : DIR { if( S_ISDIR(st.st_mode) ) { strcat(path, "index.html"); } else if( (st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH) ) //bin(binary file) { cgi = 1; } else {} //noting to do } printf("!@!#%@^ %s !@%@^%\n", buf); if(cgi) // u+x file { printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!cgi\n"); exe_cgi(sock, method, path, query_string); //cgi mode } else //.jpg .html ... { printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!www\n"); clear_header(sock); //! important! echo_www(sock, path, st.st_size); } close(sock); return 0; }