Thttpd_文件上传

/*
     thttpd上传文件
     接收文件在thttpd内部完成
     // 参考文献
     http://www.justwinit.cn/post/6314/
     http://blog.sina.com.cn/s/blog_75a8cfac0100p9es.html
     http://likinliang.blog.163.com/blog/static/31005155200792302117542/
     http://blog.csdn.net/jszj/article/details/8705956
*/
enum
{
    STATE_START,
    STATE_GET_SIGN_CODE,
    STATE_GET_FILE_NAME,
    STATE_GET_FILE_START,
    STATE_GET_FILE_CONTENT,
    STATE_CHECK_END,
    STATE_END
};

#define DEAL_BUF_LEN  2048
#define SIGN_CODE_LEN 100
#define FILE_NAME_LEN 64
#define FILE_SAVE_DIR "/dev/"
#if 0
static void ShowErrorInfo(char * error)  
{  
        printf("Content-Type:text/html;charset=UTF-8\n\n");  
        printf("
%s
" , error ); } #endif int upload_file_2(int socked, httpd_conn *hc) { FILE *fp; /* 文件指针,保存我们要获得的文件 */ int getState = STATE_START; int contentLength;/*标准输入内容长度*/ int nowReadLen; int signCodeLen; int tmpLen; int content_len = 0; int upgrade_file_size = 0; char *nowReadP = NULL; char *nowWriteP = NULL; char dealBuf[DEAL_BUF_LEN]; char signCode[SIGN_CODE_LEN]; /*存储本次的特征码*/ char tmpSignCode[SIGN_CODE_LEN]; char fileName[FILE_NAME_LEN]; char content_buffer[4096] = {0}; FILE *web_fd = fdopen(hc->conn_fd, "w+"); memset(dealBuf,0,DEAL_BUF_LEN); memset(signCode,0,SIGN_CODE_LEN); memset(fileName,0,FILE_NAME_LEN); nowReadLen = 0; if ((char *)getenv("CONTENT_LENGTH")!=NULL) { contentLength = atoi((char *)getenv("CONTENT_LENGTH")); upgrade_file_size = contentLength; } else { exit(1); } while (contentLength > 0) { if (contentLength >= DEAL_BUF_LEN) { nowReadLen = DEAL_BUF_LEN; } else { nowReadLen = contentLength; } contentLength -= nowReadLen; // CGI程序适用 //if(fread(dealBuf,sizeof(char),nowReadLen,stdin) != nowReadLen) // thttpd内部接收需要使用socket直接接收 if (read(socked, dealBuf, nowReadLen) != nowReadLen) { exit(1); } nowReadP = dealBuf; while (nowReadLen > 0) { switch (getState) { case STATE_START: nowWriteP = signCode; getState = STATE_GET_SIGN_CODE; case STATE_GET_SIGN_CODE: if (strncmp(nowReadP, "\r\n",2) == 0) { signCodeLen = nowWriteP - signCode; nowReadP++; nowReadLen--; *nowWriteP = 0; getState = STATE_GET_FILE_NAME; //ShowErrorInfo(signCode); } else { *nowWriteP = *nowReadP; nowWriteP++; } break; case STATE_GET_FILE_NAME: if (strncmp(nowReadP, "filename=", strlen("filename=")) == 0) { nowReadP += strlen("filename="); nowReadLen -= strlen("filename="); nowWriteP = fileName + strlen(FILE_SAVE_DIR); while (*nowReadP != '\r') { if (*nowReadP == '\\' || *nowReadP == '/') { nowWriteP = fileName + strlen(FILE_SAVE_DIR); } else if (*nowReadP != '\"') { *nowWriteP = *nowReadP; nowWriteP++; } nowReadP++; nowReadLen--; } *nowWriteP = 0; nowReadP++; nowReadLen--; getState = STATE_GET_FILE_START; memcpy(fileName,FILE_SAVE_DIR,strlen(FILE_SAVE_DIR)); if ((fp=fopen(fileName, "w"))==NULL) { exit(1); } //ShowErrorInfo(fileName); } break; case STATE_GET_FILE_START: if (strncmp(nowReadP, "\r\n\r\n", 4) == 0) { nowReadP += 3; nowReadLen -= 3; getState = STATE_GET_FILE_CONTENT; //ShowErrorInfo("get"); } break; case STATE_GET_FILE_CONTENT: if (*nowReadP != '\r') { fputc(*nowReadP,fp); } else { if (nowReadLen >= (signCodeLen + 2)) { if (strncmp(nowReadP + 2,signCode,signCodeLen) == 0) { getState = STATE_END; nowReadLen = 1; } else { fputc(*nowReadP,fp); } } else { getState = STATE_CHECK_END; nowWriteP = tmpSignCode; *nowWriteP = *nowReadP; nowWriteP++; tmpLen = 1; } } break; case STATE_CHECK_END: if (*nowReadP != '\r') { if (tmpLen < signCodeLen + 2) { *nowWriteP = *nowReadP; nowWriteP++; tmpLen++; if (tmpLen == signCodeLen + 2) { *nowWriteP = 0; if ((tmpSignCode[1] == '\n')&&(strncmp(tmpSignCode + 2,signCode,signCodeLen) == 0)) { getState = STATE_END; nowReadLen = 1; } else { fwrite(tmpSignCode,sizeof(char),tmpLen,fp); getState = STATE_GET_FILE_CONTENT; } } } } else { *nowWriteP = 0; fwrite(tmpSignCode,sizeof(char),tmpLen,fp); nowWriteP = tmpSignCode; *nowWriteP = *nowReadP; nowWriteP++; tmpLen = 1; } break; case STATE_END: nowReadLen = 1; break; default:break; } nowReadLen--; nowReadP++; } } if (fp != NULL) { fclose(fp); fp = NULL; } #if 1 // add by xxx 20160321 新增文件升级功能 // 1. 反馈传输完成 fprintf(web_fd, "HTTP/1.0 200 OK\r\n"); fprintf(web_fd, "Cache-Control: no-cache\r\n"); fprintf(web_fd, "Content-Type: text/html\r\n"); fprintf(web_fd, "Connection: close\r\n"); content_len = sprintf(content_buffer, "\r\n" "\r\n" "\n\n" "File upload to complete!\n\n" "\r\n"); fprintf(web_fd, "Content-Length: %d\r\n\r\n%s", strlen(content_buffer), content_buffer); // 反馈给upgrade升级 system("touch /dev/onvif_upgrade_flag"); #endif return 0; }


你可能感兴趣的:(Linux/Linux,C)