Автор: Bave
Дата сообщения: 09.05.2007 10:56
1. Операционка W2k
2. Все .cgi-шлюзы запускают библтотеку bgatemt.dll - в ней я релизовал всё, что связано с вытаскиванием контента из пришедшего HTTP запроса - т.е. вот код:
Код:
//Шлюз описывает структура (что-то типа дескриптора шлюза самапального):
typedef struct tagGATE_S //Дескриптор шлюза
{
BYTE m_bMethod; //используемый метод
BYTE m_bContentType; //тип контента (фактически enctype)
LPSTR m_lpszContentBuff; //указатель на память под контент
LPSTR m_lpszQuery; //query string из URL выделяется одельно
UINT m_uQuerySize; //её размер
UINT m_uContentSize; //размер контента
LPSTR m_lpszUserName; //имя пользователя - если вкл. авторизация
DWORD m_dwCSLimit; //Content Size Limit - ограничение
HANDLE m_hMutex; //Mutex для синхр. доступа шлюзов к базам данных
//Только для для случаев: multipart/form-data
PBYTE m_pBoundary; //Уникальный разделитель
WORD m_wBoundarySize; //его размер
} GATE_S, *PGATE_S;
//И вот собсно метод, который контент и вытаскивает и некоторые части заголовка
//запроса тоже:
BOOL _declspec(dllexport) bgate::httplookup(PGATE_S p_gate)
{
if(NULL == p_gate) return FALSE;
//Определяем метод:
char sz_method[8];
memset(sz_method, 0, sizeof(sz_method));
memcpy(sz_method, getenv(REQUEST_METHOD),
strlen(geten(REQUEST_METHOD)));
if(0 == strncmp(sz_method, "GET", 3)) p_gate->m_bMethod =
GATE_METHOD_GET;
else
{
if(0 == strncmp(sz_method, "POST", 4)) p_gate->m_bMethod =
GATE_METHOD_POST;
else
{
return FALSE;
}
}
//Определение кодировки данных:
LPSTR lpszContentType = _strdup(getenv(CONTENT_TYPE));
if(NULL == lpszContentType)
{
p_gate->m_bContentType = GATE_CONTENT_URLENCODE;
}
else
{
LPSTR lpszEncode = NULL;
LPSTR lpszBoundary = NULL;
p_gate->m_bContentType = 0;
if((lpszEncode = strstr(lpszContentType, "multipart/form-data")) != NULL)
{
if(lpszEncode == lpszContentType)
{
p_gate->m_bContentType = GATE_CONTENT_MULTIPART;
//Получаем разделитель:
if((lpszBoundary = strstr(lpszContentType, "boundary=")) == NULL) return FALSE;
else
{
lpszBoundary+=strlen("boundary=");
p_gate->m_wBoundarySize = (strlen(lpszBoundary) + 1);
p_gate->m_pBoundary = (PBYTE)malloc(p_gate->m_wBoundarySize);
memcpy(p_gate->m_pBoundary, lpszBoundary, p_gate->m_wBoundarySize);
if(p_gate->m_wBoundarySize < 2) return FALSE;
}
}
}
if(0 == p_gate->m_bContentType) p_gate->m_bContentType = GATE_CONTENT_URLENCODE;
}
if(lpszContentType) ::free(lpszContentType);
p_gate->m_lpszUserName = _strdup(getenv(REMOTE_USER));
//strlen(getenv(REMOTE_USER)));
//Вот тут то и начинаем вытаскивать контент:
switch(p_gate->m_bMethod)
{
case GATE_METHOD_GET:
{
//URL only:
p_gate->m_uContentSize = strlen(getenv(QUERY_STRING));
p_gate->m_lpszContentBuff = (LPSTR)malloc(p_gate->m_uContentSize + 1);
if(NULL == p_gate->m_lpszContentBuff) return FALSE;
memcpy(p_gate->m_lpszContentBuff, getenv(QUERY_STRING), p_gate->m_uContentSize);
p_gate->m_lpszContentBuff[p_gate->m_uContentSize] = '\0';
p_gate->m_lpszQuery = p_gate->m_lpszContentBuff;
p_gate->m_uQuerySize = p_gate->m_uContentSize;
} break;
case GATE_METHOD_POST:
{
//HTTP:
p_gate->m_uContentSize = (unsigned int)atoi(getenv(CONTENT_LENGTH));
//Проверка на превышение Content Size Limit:
if(p_gate->m_uContentSize > p_gate->m_dwCSLimit) return FALSE;
p_gate->m_lpszContentBuff = (LPSTR)malloc(p_gate->m_uContentSize + 1);
if(NULL == p_gate->m_lpszContentBuff) return FALSE;
switch(p_gate->m_bContentType)
{
case GATE_CONTENT_URLENCODE:
{
fread(p_gate->m_lpszContentBuff, p_gate->m_uContentSize, 1, stdin);
p_gate->m_lpszContentBuff[p_gate->m_uContentSize] = '\0';
} break;
case GATE_CONTENT_MULTIPART:
{
//А вот тут как раз и засада вся!!!
//Я уже вся ко пробовал и кусками читать по 1024 байта и по 512 байт читать пробовал
//И размер буфера менять, и переназначать буффер ввода на выделенную собой же память и т.д. и т.п. но после первых 1024 байт идёт пустотота!!!!
} break;
}
//URL:
p_gate->m_lpszQuery = _strdup(getenv(QUERY_STRING));
if(NULL != p_gate->m_lpszQuery) p_gate->m_uQuerySize = strlen(p_gate->m_lpszQuery);
} break;
}
return TRUE;
}