头文件
#ifndef _UPLOAD
#define _UPLOAD
#include "fastcgi/fcgiapp.h"
//#include "sysinc.h"
#ifdef _WIN32
/*! \def GRCALL
* the calling convention of functions exported by modules.
*/
# define GRCALL __stdcall
# define GRINLINE __inline
#else
# define GRINLINE inline
/*! \def GRCALL
* the calling convention of functions exported by modules.
*/
# if defined(__CYGWIN__)
# define GRCALL __stdcall
# else
# define __stdcall
# define GRCALL
# endif
#endif
#define EUPLOAD_SUCCESS 0
#define EUPLOAD_NO_DATA -1
#define EUPLOAD_READ -2
#define EUPLOAD_WRITE -3
#ifdef __cpluscplus
extern "C" {
#endif
int GRCALL upload_file_save_as(FCGX_Stream* in,FCGX_Stream* out, FCGX_ParamArray envp,const char *save_path,char(* filePath)[260]);
int GRCALL upload_file_save_as(const char *save_path);
#ifdef __cpluscplus
}
#endif
#endif
cpp
#include "stdafx.h"
#include "fastcgi/upload.h"
//#include "logger.h"
#include "fastcgi/fcgi_stdio.h"
#include "string.h"
#include <stdlib.h>
#include <windows.h>
#define DEAL_BUF_LEN 1024
#define SIGN_CODE_LEN 100
#define FILE_NAME_LEN 64
enum
{
STATE_START,
STATE_GET_SIGN_CODE,
STATE_GET_FILE_NAME,
STATE_GET_FILE_START,
STATE_GET_FILE_CONTENT,
STATE_CHECK_END,
STATE_END
};
int GRCALL upload_file_save_as(FCGX_Stream* in, FCGX_Stream* out, FCGX_ParamArray envp, const char *saveas,char(* saveName)[260])
{
FILE *fp=NULL;
int getState = STATE_START;
// uploaded file content length
int contentLength;
int nowReadLen;
int signCodeLen;
int tmpLen;
char *nowReadP;
char *nowWriteP = NULL;
char dealBuf[DEAL_BUF_LEN];
// http boundary
char signCode[SIGN_CODE_LEN];
char tmpSignCode[SIGN_CODE_LEN];
char fileName[FILE_NAME_LEN];
memset(dealBuf, '0', DEAL_BUF_LEN);
memset(signCode, '0', SIGN_CODE_LEN);
memset(fileName, '0', FILE_NAME_LEN);
nowReadLen = 0;
int fileNum = 0;
//SYSTEMTIME sys;
//GetLocalTime(&sys);
//FCGX_FPrintF(out, " before 1: %02d:%02d.%03d 星期%1d ", sys.wMinute, sys.wSecond, sys.wMilliseconds, sys.wDayOfWeek);
if ((char *)FCGX_GetParam("CONTENT_LENGTH", envp) != NULL)
{
contentLength = atoi((char *)FCGX_GetParam("CONTENT_LENGTH", envp));
FCGX_FPrintF(out, "CONTENT_LENGTH %d \n", contentLength);
}
else
{
FCGX_FPrintF(out, "EUPLOAD_NO_DATA\n");
return EUPLOAD_NO_DATA;
}
while (contentLength > 0)
{
if (contentLength >= DEAL_BUF_LEN)
{
nowReadLen = DEAL_BUF_LEN;
}
else
{
nowReadLen = contentLength;
}
contentLength -= nowReadLen;
//if (FCGI_fread(dealBuf, sizeof(char), nowReadLen, FCGI_stdin) != (size_t)nowReadLen)
if (FCGX_GetStr(dealBuf, nowReadLen, in) != (size_t)nowReadLen)
{
//log_error("read error %d", nowReadLen);
FCGX_FPrintF(out, "read error %d \n", nowReadLen);
FCGX_FPrintF(out, "actual read %d \n", fread(dealBuf, sizeof(char), nowReadLen, FCGI_stdin));
return EUPLOAD_READ;
}
nowReadP = dealBuf;
//FCGX_FPrintF(out, "content is %s \n", dealBuf);
/*while (nowReadLen > 0)
{
FCGX_FPrintF(out, "%c \n", *nowReadP);
nowReadP++;
nowReadLen--;
}*/
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)
{
//FCGX_FPrintF(out, "## signCode is %s", signCode);
signCodeLen = nowWriteP - signCode;
//FCGX_FPrintF(out, "## signCode LENGTH is %d", signCodeLen);
nowReadP++;
nowReadLen--;
*nowWriteP = 0;
getState = STATE_GET_FILE_NAME;
}
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(saveas);
memset(fileName, '0', FILE_NAME_LEN);
while (*nowReadP != '\r')
{
if (*nowReadP == '\\' || *nowReadP == '/')
{
nowWriteP = fileName + strlen(saveas);
}
else if (*nowReadP != '\"')
{
*nowWriteP = *nowReadP;
nowWriteP++;
}
nowReadP++;
nowReadLen--;
if (nowReadLen <= 0)
break;
}
*nowWriteP = 0;
nowReadP++;
nowReadLen--;
getState = STATE_GET_FILE_START;
memcpy(fileName, saveas, strlen(saveas));
//
if (fileNum > 1)
fileNum = 1;
sprintf(saveName[fileNum], "%s",fileName);
//FCGX_FPrintF(out, "open file %s ", fileName);
if ((fp = fopen(fileName, "wb")) == NULL)
{
//log_error("open file %s error %d", fileName, errno);
FCGX_FPrintF(out, "open file %s error %d", fileName, errno);
return EUPLOAD_WRITE;
}
else
{
fileNum++;
}
}
break;
case STATE_GET_FILE_START:
if (strncmp(nowReadP, "\r\n\r\n", 4) == 0)
{
nowReadP += 3;
nowReadLen -= 3;
getState = STATE_GET_FILE_CONTENT;
}
break;
case STATE_GET_FILE_CONTENT:
if (*nowReadP != '\r')
{
//fputc(*nowReadP, fp);
fwrite(nowReadP, sizeof(char), 1, fp);
}
else
{
if (nowReadLen >= (signCodeLen + 2)) //\r\n=2
{
if (strncmp(nowReadP + 2, signCode, signCodeLen) == 0)
{
//FCGX_FPrintF(out, "STATE_GET_FILE_CONTENT and end:%d ,signCodeLen is %d ", nowReadLen, signCodeLen);
//FCGX_FPrintF(out, "nowReadp: %c ", *(nowReadP + 2 + signCodeLen));
//FCGX_FPrintF(out, "nowReadp: %c ", *(nowReadP + 2 + signCodeLen+1));
//FCGX_FPrintF(out, "nowReadp: %c ", *(nowReadP + 2 + signCodeLen+2));
//getState = STATE_END;
//nowReadLen = 1;
if (nowReadLen >= (signCodeLen + 4) && strncmp(nowReadP + 2 + signCodeLen, "--", 2) == 0)//真正的结尾
{
//FCGX_FPrintF(out, "## end ## ");
getState = STATE_END;
nowReadLen = 1;
}
//else if(nowReadLen<(signCodeLen + 4) )//刚好到boundary后面的-未读到时,break
//{
// break;
//}
else
{
//FCGX_FPrintF(out, "try to close file and start another file");
if (fp != NULL)
{
FCGX_FPrintF(out, "close file and start another file");
fclose(fp);
fp = NULL;
}
getState = STATE_GET_FILE_NAME;
//getState = STATE_START;
//memset(signCode, 0, SIGN_CODE_LEN);
//FCGX_FPrintF(out, "nowReadp ==r## and goto START");
}
//getState = STATE_END;
//nowReadLen = 1;
}
else
{
//fputc(*nowReadP, fp);
fwrite(nowReadP, sizeof(char), 1, fp);
//FCGX_FPrintF(out, "%s", nowReadP);
}
}
else
{
getState = STATE_CHECK_END;
nowWriteP = tmpSignCode;
*nowWriteP = *nowReadP;
nowWriteP++;
tmpLen = 1;
//FCGX_FPrintF(out, "check end nowRadp ==r##");
}
}
break;
case STATE_CHECK_END:
if (*nowReadP != '\r')
{
if (tmpLen < signCodeLen + 2)
{
*nowWriteP = *nowReadP;
nowWriteP++;
tmpLen++;
if (tmpLen == signCodeLen + 2)
{
*nowWriteP = 0;
//FCGX_FPrintF(out, "tmpSignCode is %s \n", tmpSignCode);
if ((tmpSignCode[1] == '\n') && (strncmp(tmpSignCode + 2, signCode, signCodeLen) == 0))
{
/*FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %02x ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %02x ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
getState = STATE_END;
nowReadLen = 1;
*/
/*
FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %02x ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %02x ", *nowReadP);
nowReadP++;
FCGX_FPrintF(out, "nowReadp: %c ", *nowReadP);
nowReadP -=3;
*/
nowReadP++;
nowReadLen--;
//if (nowReadLen >= (signCodeLen + 4) && strncmp(nowReadP + 2 + signCodeLen, "--", 2) == 0)//真正的结尾
if (nowReadLen >= 2 && strncmp(nowReadP, "--", 2) == 0)
{
//FCGX_FPrintF(out, "nowReadp ==r## and goto END");
//FCGX_FPrintF(out, "### check end,signCodeLen: %d,nowReadLen:%d", signCodeLen, nowReadLen);
getState = STATE_END;
nowReadLen = 1;
}
//else if(nowReadLen<2)//刚好到boundary后面的--未读到时,break
//{
// break;
//}
else
{
if (fp != NULL)
{
try {
FCGX_FPrintF(out, "close file checkend");
fclose(fp);
}
catch (...) {
}
}
getState = STATE_GET_FILE_NAME;
//getState = STATE_START;
//memset(signCode, 0, SIGN_CODE_LEN);
//FCGX_FPrintF(out, "nowReadp ==r## and goto START");
}
//getState = STATE_END;
//nowReadLen = 1;
}
else
{
//fprintf(fp,tmpSignCode);
fwrite(tmpSignCode, sizeof(char), tmpLen, fp);
getState = STATE_GET_FILE_CONTENT;
//FCGX_FPrintF(out, "check end and get fileContent,tempSignCode: %s", tmpSignCode);
//FCGX_FPrintF(out, "checkend and not end \n");
}
}
}
}
else
{
*nowWriteP = 0;
//fprintf(fp,tmpSignCode);
fwrite(tmpSignCode, sizeof(char), tmpLen, fp);
nowWriteP = tmpSignCode;
*nowWriteP = *nowReadP;
nowWriteP++;
tmpLen = 1;
FCGX_FPrintF(out, "checkend and nowReadP == r \n");
}
break;
case STATE_END:
nowReadLen = 1;
//FCGX_FPrintF(out, "state end \n");
break;
default:break;
}
if (getState != STATE_START)
{
nowReadLen--;
nowReadP++;
}
else
{
nowReadLen-=2;
nowReadP+=2;
}
}
}
//add for two picture by luodaliang
if (fp != NULL)
{
FCGX_FPrintF(out, "close file end");
fclose(fp);
}
//GetLocalTime(&sys);
//FCGX_FPrintF(out, " before 5: %02d:%02d.%03d 星期%1d ", sys.wMinute, sys.wSecond, sys.wMilliseconds, sys.wDayOfWeek);
return EUPLOAD_SUCCESS;
}