Apache2 access.log 相同数据包不同
Apache2 access.log different for same packets
我有一个 C++ 程序试图在 Apache2 网络服务器上使用 PHP 应用程序 运行 上传文件。我有一个非常奇怪的问题,我不知道该怎么做。因此,我使用 httpSendRequest() 函数创建了 HTTP 请求,并且在 wireshark 中查看时它的格式似乎正确。但是文件没有上传,当我查看 apache 的 access.log 文件时,它没有显示用户代理或内容长度,尽管两者都明显存在于数据包捕获中。
作为参考,返回 200 状态的请求与使用 burp 套件发送的数据包相同,而不是我使用 httpSendRequest 的程序发送的数据包,而且我也能够使用网络浏览器成功上传文件。
这是使用 httpSendRequest 创建请求的代码,其中大部分直接取自 this codeguru post。
#include <windows.h>
#include <wininet.h>
#include <iostream>
#define ERROR_OPEN_FILE 10
#define ERROR_MEMORY 11
#define ERROR_SIZE 12
#define ERROR_INTERNET_OPEN 13
#define ERROR_INTERNET_CONN 14
#define ERROR_INTERNET_REQ 15
#define ERROR_INTERNET_SEND 16
using namespace std;
int main()
{
// Local variables
static char *filename = "test.txt"; //Filename to be loaded
static char *type = "image/jpg";
static char boundary[] = "PaulRules"; //Header boundary
static char nameForm[] = "fileToUpload"; //Input form name
static char iaddr[] = "192.168.0.105"; //IP address
static char url[] = "upload.php"; //URL
char hdrs[255]; //Headers
char * buffer; //Buffer containing file + headers
char * content; //Buffer containing file
FILE * pFile; //File pointer
long lSize; //File size
size_t result;
// Open file
pFile = fopen ( filename , "rb" );
if (pFile==NULL) return ERROR_OPEN_FILE;
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
content = (char*) malloc (sizeof(char)*lSize);
if (content == NULL) return ERROR_MEMORY;
// copy the file into the buffer:
result = fread (content,1,lSize,pFile);
if (result != lSize) return ERROR_SIZE;
// terminate
fclose (pFile);
//allocate memory to contain the whole file + HEADER
buffer = (char*) malloc (sizeof(char)*lSize + 2048);
//print header
sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"test.bmp\"\r\n",boundary,nameForm,filename);
sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);
int cb = strlen(buffer);
char * bp = buffer + cb;
memcpy(bp, content, lSize);
bp += lSize;
int cw = sprintf(bp,"\r\n--%s--\r\n",boundary);
//Open internet connection
HINTERNET hSession = InternetOpen("Paul was here :)",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession==NULL) return ERROR_INTERNET_OPEN;
HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(hConnect==NULL) return ERROR_INTERNET_CONN;
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, (const char**)"*/*", 0, 1);
if(hRequest==NULL) return ERROR_INTERNET_REQ;
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw);
if(!sent) return ERROR_INTERNET_SEND;
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}
这里是服务器端的PHP脚本
<?php
$target_dir = "recvFile/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if file already exists
if (file_exists($target_file)) {
echo "File already exists";
$uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "File to large";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "ERROR File not uploaded";
}
//attempt to upload the file
else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
//echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
echo "Command:1";
}
else {
echo $_FILES["fileToUpload"]["tmp_name"];
echo "ERROR uploading file";
}
}
?>
您的源文件是 "test.txt"
,但您正在上传到 "test.bmp"
。使它们具有相同的扩展名。
type = "image/jpg";
如果这应该是文本,请将 type
更改为 "image/*"
或 "text/*"
。
您的操作可能成功,因为它打印了 "Command 1"
。该文件可能在那里,但它不是您期望的那个。如果不是,请查看可以从 PHP 端提取什么错误。
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; \
name=\"fileToUpload\"; filename=\"test.bmp\"\r\n",
boundary,nameForm,filename);
您有一个格式说明符 "%s"
和 4 个参数。删除最后两个参数。
按照推荐的方式使用HttpOpenRequest
:
const char *accept[] = { "image/*", NULL }; // or `"text/*"`
HttpOpenRequest(hConnect, "POST",url, NULL, NULL, accept, 0, 1);
使用 C++ 的代码
#include <Windows.h>
#include <Wininet.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#pragma comment(lib, "wininet.lib")
int main()
{
HINTERNET hsession = NULL;
HINTERNET hconnect = NULL;
HINTERNET hrequest = NULL;
const char* server = "localhost";
const char* url = "upload.php";
const char* type = "image/*";
std::string filename = "test.bmp";
std::ifstream infile("c:\test\test.bmp", std::ios::binary);
if(!infile)
return 0;
std::ostringstream oss;
oss << infile.rdbuf();
std::string headers = "Content-type: multipart/form-data, boundary=uniquestring";
std::string data = "--uniquestring\r\n\
Content-Disposition: form-data; name=\"fileToUpload\"; filename=\"%1\"\r\n\
Content-Type: %2\r\n\
\r\n\
%3\r\n\
--uniquestring--";
data.replace(data.find("%1"), 2, filename);
data.replace(data.find("%2"), 2, type);
data.replace(data.find("%3"), 2, oss.str());
hsession = InternetOpen("appname", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(!hsession)
goto cleanup;
hconnect = InternetConnect(hsession, server, INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(!hconnect)
goto cleanup;
const char *accept[] = { type, NULL };
hrequest = HttpOpenRequest(hconnect, "POST", url, NULL, NULL, accept, 0, 1);
if(!hrequest)
goto cleanup;
BOOL sent = HttpSendRequest(hrequest, headers.data(), headers.size(),
&data[0], data.size());
if(sent)
{
DWORD bufsize = 4096;
std::string read(bufsize, 0);
InternetReadFile(hrequest, &read[0], bufsize, &bufsize);
read.resize(bufsize);
std::cout << read << "\n";
}
else
{
goto cleanup;
}
cleanup:
if(hrequest) InternetCloseHandle(hrequest);
if(hconnect) InternetCloseHandle(hconnect);
if(hsession) InternetCloseHandle(hsession);
return 0;
}
为了完整起见,这里是完整的可操作代码
#include <windows.h>
#include <wininet.h>
#include <iostream>
using namespace std;
int main()
{
// Local variables
static char *filename = "Desert.jpg"; //Filename to be loaded
static char *type = "multipart/form-data";
static char boundary[] = "PaulRules"; //Header boundary
static char nameForm[] = "fileToUpload"; //Input form name
static char iaddr[] = "192.168.0.105"; //IP address
static char url[] = "upload.php"; //URL
char hdrs[255]; //Headers
char * buffer; //Buffer containing file + headers
char * content; //Buffer containing file
FILE * pFile; //File pointer
long lSize; //File size
size_t result;
// Open file
pFile = fopen ( filename , "rb" );
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
content = (char*) malloc (sizeof(char)*lSize);
// copy the file into the buffer:
result = fread (content,1,lSize,pFile);
// terminate
fclose (pFile);
//allocate memory to contain the whole file + HEADER
buffer = (char*) malloc (sizeof(char)*lSize + 2048);
//print header
sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"%s\"\r\n",boundary, filename);
sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);
int cb = strlen(buffer);
char * bp = buffer + cb;
memcpy(bp, content, lSize);
bp += lSize;
int cw = sprintf(bp,"\r\n--%s--\r\n",boundary);
//Open internet connection
HINTERNET hSession = InternetOpen("Winsock",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
const char* accept[] = {"*/*", NULL};
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, accept, 0, 1);
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw);
DWORD dwSize, dwRead;
CHAR szBuffer[1024];
if(!InternetQueryDataAvailable(hRequest, &dwSize, 0, 0)){
std::cout << "QUERYDATA ERROR: " << GetLastError() << std::endl;
}
else{
while(InternetReadFile(hRequest, szBuffer, sizeof(szBuffer)-1, &dwRead) && dwRead) {
szBuffer[dwRead] = 0;
dwRead=0;
}
cout << szBuffer;
}
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}
我有一个 C++ 程序试图在 Apache2 网络服务器上使用 PHP 应用程序 运行 上传文件。我有一个非常奇怪的问题,我不知道该怎么做。因此,我使用 httpSendRequest() 函数创建了 HTTP 请求,并且在 wireshark
作为参考,返回 200 状态的请求与使用 burp 套件发送的数据包相同,而不是我使用 httpSendRequest 的程序发送的数据包,而且我也能够使用网络浏览器成功上传文件。
这是使用 httpSendRequest 创建请求的代码,其中大部分直接取自 this codeguru post。
#include <windows.h>
#include <wininet.h>
#include <iostream>
#define ERROR_OPEN_FILE 10
#define ERROR_MEMORY 11
#define ERROR_SIZE 12
#define ERROR_INTERNET_OPEN 13
#define ERROR_INTERNET_CONN 14
#define ERROR_INTERNET_REQ 15
#define ERROR_INTERNET_SEND 16
using namespace std;
int main()
{
// Local variables
static char *filename = "test.txt"; //Filename to be loaded
static char *type = "image/jpg";
static char boundary[] = "PaulRules"; //Header boundary
static char nameForm[] = "fileToUpload"; //Input form name
static char iaddr[] = "192.168.0.105"; //IP address
static char url[] = "upload.php"; //URL
char hdrs[255]; //Headers
char * buffer; //Buffer containing file + headers
char * content; //Buffer containing file
FILE * pFile; //File pointer
long lSize; //File size
size_t result;
// Open file
pFile = fopen ( filename , "rb" );
if (pFile==NULL) return ERROR_OPEN_FILE;
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
content = (char*) malloc (sizeof(char)*lSize);
if (content == NULL) return ERROR_MEMORY;
// copy the file into the buffer:
result = fread (content,1,lSize,pFile);
if (result != lSize) return ERROR_SIZE;
// terminate
fclose (pFile);
//allocate memory to contain the whole file + HEADER
buffer = (char*) malloc (sizeof(char)*lSize + 2048);
//print header
sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"test.bmp\"\r\n",boundary,nameForm,filename);
sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);
int cb = strlen(buffer);
char * bp = buffer + cb;
memcpy(bp, content, lSize);
bp += lSize;
int cw = sprintf(bp,"\r\n--%s--\r\n",boundary);
//Open internet connection
HINTERNET hSession = InternetOpen("Paul was here :)",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(hSession==NULL) return ERROR_INTERNET_OPEN;
HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(hConnect==NULL) return ERROR_INTERNET_CONN;
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, (const char**)"*/*", 0, 1);
if(hRequest==NULL) return ERROR_INTERNET_REQ;
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw);
if(!sent) return ERROR_INTERNET_SEND;
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}
这里是服务器端的PHP脚本
<?php
$target_dir = "recvFile/";
$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
// Check if file already exists
if (file_exists($target_file)) {
echo "File already exists";
$uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
echo "File to large";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "ERROR File not uploaded";
}
//attempt to upload the file
else {
if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
//echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
echo "Command:1";
}
else {
echo $_FILES["fileToUpload"]["tmp_name"];
echo "ERROR uploading file";
}
}
?>
您的源文件是 "test.txt"
,但您正在上传到 "test.bmp"
。使它们具有相同的扩展名。
type = "image/jpg";
如果这应该是文本,请将 type
更改为 "image/*"
或 "text/*"
。
您的操作可能成功,因为它打印了 "Command 1"
。该文件可能在那里,但它不是您期望的那个。如果不是,请查看可以从 PHP 端提取什么错误。
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; \
name=\"fileToUpload\"; filename=\"test.bmp\"\r\n",
boundary,nameForm,filename);
您有一个格式说明符 "%s"
和 4 个参数。删除最后两个参数。
按照推荐的方式使用HttpOpenRequest
:
const char *accept[] = { "image/*", NULL }; // or `"text/*"`
HttpOpenRequest(hConnect, "POST",url, NULL, NULL, accept, 0, 1);
使用 C++ 的代码
#include <Windows.h>
#include <Wininet.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#pragma comment(lib, "wininet.lib")
int main()
{
HINTERNET hsession = NULL;
HINTERNET hconnect = NULL;
HINTERNET hrequest = NULL;
const char* server = "localhost";
const char* url = "upload.php";
const char* type = "image/*";
std::string filename = "test.bmp";
std::ifstream infile("c:\test\test.bmp", std::ios::binary);
if(!infile)
return 0;
std::ostringstream oss;
oss << infile.rdbuf();
std::string headers = "Content-type: multipart/form-data, boundary=uniquestring";
std::string data = "--uniquestring\r\n\
Content-Disposition: form-data; name=\"fileToUpload\"; filename=\"%1\"\r\n\
Content-Type: %2\r\n\
\r\n\
%3\r\n\
--uniquestring--";
data.replace(data.find("%1"), 2, filename);
data.replace(data.find("%2"), 2, type);
data.replace(data.find("%3"), 2, oss.str());
hsession = InternetOpen("appname", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
if(!hsession)
goto cleanup;
hconnect = InternetConnect(hsession, server, INTERNET_DEFAULT_HTTP_PORT,
NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
if(!hconnect)
goto cleanup;
const char *accept[] = { type, NULL };
hrequest = HttpOpenRequest(hconnect, "POST", url, NULL, NULL, accept, 0, 1);
if(!hrequest)
goto cleanup;
BOOL sent = HttpSendRequest(hrequest, headers.data(), headers.size(),
&data[0], data.size());
if(sent)
{
DWORD bufsize = 4096;
std::string read(bufsize, 0);
InternetReadFile(hrequest, &read[0], bufsize, &bufsize);
read.resize(bufsize);
std::cout << read << "\n";
}
else
{
goto cleanup;
}
cleanup:
if(hrequest) InternetCloseHandle(hrequest);
if(hconnect) InternetCloseHandle(hconnect);
if(hsession) InternetCloseHandle(hsession);
return 0;
}
为了完整起见,这里是完整的可操作代码
#include <windows.h>
#include <wininet.h>
#include <iostream>
using namespace std;
int main()
{
// Local variables
static char *filename = "Desert.jpg"; //Filename to be loaded
static char *type = "multipart/form-data";
static char boundary[] = "PaulRules"; //Header boundary
static char nameForm[] = "fileToUpload"; //Input form name
static char iaddr[] = "192.168.0.105"; //IP address
static char url[] = "upload.php"; //URL
char hdrs[255]; //Headers
char * buffer; //Buffer containing file + headers
char * content; //Buffer containing file
FILE * pFile; //File pointer
long lSize; //File size
size_t result;
// Open file
pFile = fopen ( filename , "rb" );
// obtain file size:
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file:
content = (char*) malloc (sizeof(char)*lSize);
// copy the file into the buffer:
result = fread (content,1,lSize,pFile);
// terminate
fclose (pFile);
//allocate memory to contain the whole file + HEADER
buffer = (char*) malloc (sizeof(char)*lSize + 2048);
//print header
sprintf(hdrs,"Content-Type: multipart/form-data; boundary=%s",boundary);
sprintf(buffer,"--%s\r\nContent-Disposition: form-data; name=\"fileToUpload\"; filename=\"%s\"\r\n",boundary, filename);
sprintf(buffer,"%sContent-Type: %s\r\n\r\n",buffer,type);
int cb = strlen(buffer);
char * bp = buffer + cb;
memcpy(bp, content, lSize);
bp += lSize;
int cw = sprintf(bp,"\r\n--%s--\r\n",boundary);
//Open internet connection
HINTERNET hSession = InternetOpen("Winsock",INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
HINTERNET hConnect = InternetConnect(hSession, iaddr,INTERNET_DEFAULT_HTTP_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 1);
const char* accept[] = {"*/*", NULL};
HINTERNET hRequest = HttpOpenRequest(hConnect, (const char*)"POST",url, NULL, NULL, accept, 0, 1);
BOOL sent= HttpSendRequest(hRequest, hdrs, strlen(hdrs), buffer, cb + lSize + cw);
DWORD dwSize, dwRead;
CHAR szBuffer[1024];
if(!InternetQueryDataAvailable(hRequest, &dwSize, 0, 0)){
std::cout << "QUERYDATA ERROR: " << GetLastError() << std::endl;
}
else{
while(InternetReadFile(hRequest, szBuffer, sizeof(szBuffer)-1, &dwRead) && dwRead) {
szBuffer[dwRead] = 0;
dwRead=0;
}
cout << szBuffer;
}
//close any valid internet-handles
InternetCloseHandle(hSession);
InternetCloseHandle(hConnect);
InternetCloseHandle(hRequest);
return 0;
}