Вот написал на C++ Builder'e локальную часть (plocal.pl).
Но почему то тяжёлые сайты не грузит, хотя на перловой версии всё норм.
Код:
//---------------------------------------------------------------------------
#include
#include
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "IdCoderMIME"
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
DWORD WINAPI ProxyThread(LPVOID lpParam);
//---------------------------------------------------------------------------
void ParseHeader(char *header, int header_size, TStringList *header_lst)
{
if(!header_lst) return;
AnsiString header_key = "", tmp;
for(int i = 0; i Add(header_key);
header_key = "";
}
}
}
//---------------------------------------------------------------------------
AnsiString RemoveHeaderVal(TStringList *header_lst, TStringList *remove_key)
{
for(int i = 0; i Count; i++)
{
for(int j = 0; j Count; j++)
{
AnsiString rem;
rem = remove_key->Strings[j];
if(header_lst->Strings[i].SubString(0, rem.Length() + 1) == (rem + ':'))
{
header_lst->Delete(i);
i--;
break;
}
}
}
return header_lst->Text + "\r\n";
}
//---------------------------------------------------------------------------
AnsiString GetHeaderVal(TStringList *header_lst, AnsiString key)
{
AnsiString result;
int flag = 0;
for(int i = 0; i Count; i++)
{
result = header_lst->Strings[i].SubString(0, key.Length() + 1);
if(result == (key + ':'))
{
result = header_lst->Strings[i].SubString(result.Length() + 1,
header_lst->Strings[i].Length());
break;
}
}
for(int i = 1; i bind_port);
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
res = bind(serv_sock, (sockaddr *)&serv_addr, sizeof(serv_addr));
if(res == SOCKET_ERROR) return -1;
listen(serv_sock, 100);
//MessageBox(0, proxy_data->remote_script.c_str(), 0, 0);
//цикл для клиентов
while(1)
{
int size;
size = sizeof(client_addr);
client_sock = accept(serv_sock, (sockaddr *)&client_addr, &size);
if(client_sock == SOCKET_ERROR) break;
proxy_data->client_sock = client_sock;
hThread = CreateThread(NULL, 0, ProxyThread, proxy_data, 0, NULL);
if(hThread == INVALID_HANDLE_VALUE) break;
CloseHandle(hThread);
}
closesocket(serv_sock);
return 0;
}
//----------------------------------------------------------------------------
DWORD WINAPI ProxyThread(LPVOID lpParam)
{
HTTP_PROXY_DATA *proxy_data = (HTTP_PROXY_DATA *)lpParam;
SOCKET client = proxy_data->client_sock;
int res, swap_len, cur;
char header[1024];
AnsiString result_header, result_host, swap;
TIdHTTP *tunnel = new TIdHTTP(Form1);
TStringStream *result = new TStringStream("");
TStringList *post = new TStringList;
TStringList *header_lst = new TStringList;
TStringList *remove_key = new TStringList;
//получаю хидер от браузера
res = recv(client, header, sizeof(header), 0);
if(res == SOCKET_ERROR || res == 0) return -1;
ParseHeader(header, res, header_lst);
//добавляю в хидер Connection: close
header_lst->Insert(1, "Connection: close");
//удаляю ключи
remove_key->Add("Proxy-Connection");
remove_key->Add("Keep-Alive");
result_header = RemoveHeaderVal(header_lst, remove_key);
//получаю host
result_host = GetHeaderVal(header_lst, "Host");
//перегоняю POST данные в base64
result_header = Form1->Base64Encode->Encode(result_header);
result_host = Form1->Base64Encode->Encode(result_host);
//с помощью TIdHTTP посылаю данные proxy.php
post->Add("query=" + result_header);
post->Add("host=" + result_host);
tunnel->Post(proxy_data->remote_script, post, result);
//посылаю результат обратно браузеру
swap = result->DataString;
swap_len = result->DataString.Length();
cur = 0;
Form1->Memo1->Lines->Add(swap);
while(swap_len > 0)
{
res = send(client, (swap.c_str() + cur), swap_len, 0);
if(res == 0) break;
else if(res == SOCKET_ERROR) {
Form1->Memo->Lines->Add("Ошибка при передачи данных браузеру");
break;
}
swap_len -= res;
cur += res;
}
delete tunnel, post, header_lst, remove_key, result;
closesocket(client);
return 0;
}
//----------------------------------------------------------------------------
void __fastcall TForm1::BStartClick(TObject *Sender)
{
HANDLE hThread;
proxy_data.remote_script = EScript->Text;
proxy_data.bind_port = EPort->Text.ToInt();
hThread = CreateThread(0, 0, ServerProxyThread, &proxy_data, 0, 0);
if(hThread == INVALID_HANDLE_VALUE)
{
Memo->Lines->Add("Не могу создать поток");
return;
}
CloseHandle(hThread);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
WSADATA wsaData;
if(WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
Memo->Lines->Add("WSAStartup error");
return;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
WSACleanup();
}
//---------------------------------------------------------------------------