/*
thttpd上传文件
接收文件在thttpd内部完成
// 参考文献
// 参考文献
*/
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("<center><font color='red'>%s</font></center>" , 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,
"<html><head><title></title>\r\n"
"<META http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\r\n"
"</head><body>\n\n"
"File upload to complete!\n\n"
"</body></html>\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;
}