Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Программа для изменения url.  (Прочитано 16433 раз)
0 Пользователей и 1 Гость смотрят эту тему.
aus
Гость
« : 18-11-2005 12:38 » 

Суть программы в следующем. Это упрощенный фильтрующий прокси.
Пользователь запускает программу, которая слушает порт 7777 и сворачивается в трей.
В настройках Internet Explorera прописывается использование прокси localhost:7777.
Прокси все запросы например http://www.ya.ru преобразует в http://site.ru/dir/script.php?url=http://www.ya.ru.
Т.е. серфинг по интернету осуществляется не заметно для клиента через прокси http://site.ru.
Интересует как можно реализовать замену url на С++, какие библиотеки использовать.
Модуль для соединения по порту 7777 уже написал, используя сокеты.
Готовые программы наподобие proxomitrona не предлагать, интересует сама реализация.
Записан
ILIS
Гость
« Ответ #1 : 02-12-2005 16:07 » 

Если ты хочешь редиректить запросы с Интернет Експлорера - почитай про Browser Helper Object,
если любые хттп запросы - надо написать свой Layered Service Provider, или хукать Wininet.dll
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 02-12-2005 17:12 » 

Вопрос-то не по редиректам и да же не по сетям, вопрос - об ф-иях С++ для работы со строками.
Только, тут нужнее почитать RFC по HTTP 1.1 и 1.0. Современные браузеры давно работают по 1.1 и имя сайта передают в строке "Host" HTTP-запроса. Надо просто заменить на свой и подсоединиться к соотв. серверу. Так же стоит предусмотреть совместимость с кривыми решениями: передача полного URL в первой строке запроса. Кроме того, для полноценного прокси нужна поддержка https (работа через SSL).
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 02-12-2005 17:18 » 

Посмотри на sourceforge проект webcleaner http://webcleaner.sourceforge.net/

Они заявляют о себе,
Цитата
WebCleaner - a filtering HTTP proxy

Features:
remove unwanted HTML (adverts, flash, etc.)
popup blocker
disable animated GIFs
filter images by size, remove banner adverts
compress documents on-the-fly (with gzip)
reduce images to low-bandwidth JPEGs
remove/add/modify arbitrary HTTP headers
configurable over web interface
usage of SquidGuard blacklists
antivirus filter module
detection and correction of known HTML security flaws
Basic, Digest and (untested) NTLM proxy authentication support
per-host access control
HTTP/1.1 support (persistent connections, pipelining)
HTTPS support (both forwarding and filtering)

Жирным шрифтом я выделил фичу, которой тебе достаточно, чтобы реализовать свой редиректор.  Или посмотреть, как это делают другие.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #4 : 02-12-2005 19:48 » 

В общем-то, все то же может и Privoxy. Я им пользуюсь для резки рекламы и HTML вообще, но может и многое другое:
8.5. Actions

    8.5.1. add-header
    8.5.2. block
    8.5.3. crunch-incoming-cookies
    8.5.4. crunch-outgoing-cookies
    8.5.5. deanimate-gifs
    8.5.6. downgrade-http-version
    8.5.7. fast-redirects
    8.5.8. filter
    8.5.9. handle-as-image
    8.5.10. hide-forwarded-for-headers
    8.5.11. hide-from-header
    8.5.12. hide-referrer
    8.5.13. hide-user-agent
    8.5.14. kill-popups
    8.5.15. limit-connect
    8.5.16. prevent-compression
    8.5.17. send-vanilla-wafer
    8.5.18. send-wafer
    8.5.19. session-cookies-only
    8.5.20. set-image-blocker

http://www.privoxy.org/user-manual/
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
aus
Гость
« Ответ #5 : 05-12-2005 13:00 » 

Код:
#include <windows.h>

// НАСТРОЙКА  ПАРАМЕТРОВ
#define IN_PORT     80
#define OUT_IP      "192.168.22.253"
#define OUT_PORT    3128
#define MAX_DATA    1024
#define MAXCONN 1000
#define IDE_MSG 110
#define WM_ASYNC_CLIENTEVENT  WM_USER+1
#define WM_ASYNC_PROXYEVENT WM_USER+10

LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam);
void ConnectToProxy(SOCKET);

SOCKET hListenSockTCP   = INVALID_SOCKET; //Слушающий сокет, на который будут коннектиться клиенты.
SOCKADDR_IN     myaddrTCP,proxyaddrTCP;

char buf[MAX_DATA]; //Это будет буфер для принятых данных.
char file[MAX_PATH]="http://phpscript.ru/r.php?url=";
char host[MAX_PATH]="Host: phpscript.ru\n";
char tempfile[15][MAX_DATA];
char newbuf[MAX_DATA];
char ch;
char n;


SOCKET sockets[MAXCONN];
HWND hwndMain;
//Вставка символа с в строку s на позицию at
int insert(char s[], int at,char c)
    {

            char *p;
            s += at; p = s;
            while(*p) p++;  /* на конец строки */
            p[1] = '\0';    /* закрыть строку  */
            for( ; p != s; p-- )
                    p[0] = p[-1];
            *s = c;
    }

int WINAPI WinMain(HINSTANCE hInst,HINSTANCE hPrevInst,LPSTR szCmdLine,int nCmdShow)
{
  //Инициализация среды перед использованием WinSock:
  WSADATA stWSADataTCPIP;
  if(WSAStartup(0x0101, &stWSADataTCPIP)) MessageBox(0,"WSAStartup error !","NET ERROR!!!",0);
 
  //Заполним массив дескрипторов сокетов нулями (на всякий случай).
  ZeroMemory(sockets,sizeof(sockets));
//Зарегистрируем класс и создадим окно. Получим  hwndMain - дескриптор
// окна.
  WNDCLASS wc;
  memset(&wc,0,sizeof(WNDCLASS));
  wc.style = CS_HREDRAW|CS_VREDRAW |CS_DBLCLKS ;
  wc.lpfnWndProc = (WNDPROC)MainWndProc;
  wc.hInstance = hInst;
  wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wc.lpszClassName = "CProxy";
  wc.lpszMenuName = NULL;
  wc.hCursor = LoadCursor(NULL,IDC_ARROW);
  wc.hIcon = LoadIcon(NULL,IDI_APPLICATION);
  if (!RegisterClass(&wc)) return 0;

  hwndMain=CreateWindow("CProxy","ProxyExample", WS_MINIMIZEBOX|WS_CLIPSIBLINGS|WS_CLIPCHILDREN|WS_MAXIMIZEBOX|WS_CAPTION|WS_BORDER|WS_SYSMENU|WS_THICKFRAME, CW_USEDEFAULT,0,CW_USEDEFAULT,0, NULL, NULL, hInst, NULL);
  ShowWindow(hwndMain,SW_SHOW);
  //Создадим сокет
  hListenSockTCP = socket (AF_INET,SOCK_STREAM,0);
//  Заполним структуру SOCKADDR_IN, указав тип протокола(family) и порт,
//  к которому будем "биндиться", и "привязываем" сокет.
  myaddrTCP.sin_family = AF_INET;
  myaddrTCP.sin_addr.s_addr = htonl (INADDR_ANY);
  myaddrTCP.sin_port = htons (IN_PORT);
  if(bind(hListenSockTCP,(LPSOCKADDR)&myaddrTCP, sizeof(struct sockaddr)))
  {
    MessageBox(hwndMain,"This port in use!","BIND TCP ERROR!!!",0);
  }
//Запускаем сокет "на прослушку".
  if (listen (hListenSockTCP, 5)) MessageBox(hwndMain,"listen error!","ERROR!!!",0);
//Привязываем  события  FD_ACCEPT, FD_READ, FD_CLOSE сокета к главному
//окну программы.
  WSAAsyncSelect (hListenSockTCP,hwndMain,WM_ASYNC_CLIENTEVENT,FD_ACCEPT|FD_READ|FD_CLOSE);
 

  MSG  msg;
  while(GetMessage(&msg,NULL,0,0))
  {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }
  return msg.wParam;

  return 0;
}


//функция обработки сообщений окна
//wParam - дескриптор  сокета
LRESULT CALLBACK MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
   WORD WSAEvent;
    int flag,i,j,z,c;
   DWORD currentsock;

   switch (msg)
          {
           case WM_COMMAND:
           break;
           
           case WM_DESTROY:
           PostQuitMessage(0);  // 10xu4yourtime
           break;

           case WM_ASYNC_CLIENTEVENT: // Сообщения про события сокетов, подключенных к клиенту...
           currentsock = wParam;
          // именно так узнаем, какое событие с сокетом произошло
           WSAEvent = WSAGETSELECTEVENT (lParam);
           switch (WSAEvent)
                  {
                  case FD_CLOSE :
                  shutdown(sockets[currentsock],1);
                  closesocket(currentsock);
                  return 0;

                  case FD_READ:
                  // ПЕРЕНАПРАВЛЕНИЕ ДАННЫХ (redirect). Берем от клиента, посылаем на сервер.
                   ZeroMemory(buf,1024);
                   i=recv(currentsock, buf, MAX_DATA, 0);
                //разложим запрос на строки и поместим в массив tempfile[]
                   z=0;
                   c=0; 
          while(buf[z]!='\0')
          {
           insert(tempfile[c],0,'\0');
           j=0;                 
           while(buf[z]!='\n')
           {
           insert(tempfile[c],j,buf[z]);                 
           j++;
           z++;
           }
           insert(tempfile[c],j,buf[z]);
           z++;
         //  MessageBox(0,tempfile[c],"file!!!",0);
           c++;                   
          }
         
       // изменим запрашиваемый url
            for(j=4;j<strlen(file)+4;j++)
                      {
                        insert(tempfile[0],j,file[j-4]);
           }
         //Сформируем новый запрос         
        ZeroMemory(newbuf,1024);       
         strcpy(newbuf,tempfile[0]);
         strcat(newbuf,"Accept:*/*\n");
         strcat(newbuf,host);
         strcat(newbuf,"Proxy-Connection: Keep-Alive\n");
         strcat(newbuf,"\n\n");
         
       MessageBox(0,newbuf,"file!!!",0);
        // MessageBox(0,buf,"file!!!",0);
           
            send(sockets[currentsock],newbuf, i, 0); // и отправляем...
           return 0;

                  //Это сообщение приходит тогда, когда к нам хотят подключиться.
                  case FD_ACCEPT:
                  //Разрешаем  подключение  клиента,  и  пытаемся теперь подключиться к
                  //нашему удаленному прокси.
                 
                   ConnectToProxy(accept(hListenSockTCP,NULL,NULL));
              return 0;
             
               }
                 break;

  case WM_ASYNC_PROXYEVENT:
       // Найдем соответствующий дескриптор.
       for (i=0;i<MAXCONN;i++)
       if (sockets[i] == wParam) { currentsock=i; break; }
       WSAEvent = WSAGETSELECTEVENT (lParam);
       switch (WSAEvent)
   {
         // Произошло подключение к удаленному хосту
         case FD_CONNECT :
           i=WSAGETSELECTERROR(lParam);
           if (i!=0)
           {
             shutdown(currentsock,1);
             closesocket(sockets[currentsock]);
             sockets[currentsock]=INVALID_SOCKET;
           }
        return 0;
   
   
// Сервер нас отрубает ...
case FD_CLOSE :
   shutdown(currentsock,1);
   closesocket(sockets[currentsock]);    sockets[currentsock]=INVALID_SOCKET;
   return 0;

// Перенаправление данных клиенту
  case FD_READ:
             ZeroMemory(buf,1024);
             i=recv(sockets[currentsock], buf, MAX_DATA, 0);
          //   MessageBox(0,buf,"buf-buf!!!",0);                       
     send(currentsock,buf, i, 0);
     return 0;
    }
break;
  }
  return DefWindowProc(hwnd,msg,wParam,lParam);
}

// Connect to PROXY Connect to PROXY Connect to PROXY Connect to PROXY Connect to PROXY Connect to PROXY

void ConnectToProxy(SOCKET nofsock)
{
  SOCKADDR_IN rmaddr;
  rmaddr.sin_family = AF_INET;
  rmaddr.sin_addr.s_addr = inet_addr(OUT_IP);
  rmaddr.sin_port = htons (OUT_PORT);

  sockets[nofsock] = socket (AF_INET,SOCK_STREAM,0);
  if(INVALID_SOCKET == sockets[nofsock]) MessageBox(0,"INVALID_SOCKET","ERROR!!!",0);

  WSAAsyncSelect (sockets[nofsock],hwndMain,WM_ASYNC_PROXYEVENT, FD_CONNECT|FD_READ|FD_CLOSE);
 
  connect (sockets[nofsock], (struct sockaddr *)&rmaddr,sizeof(rmaddr));
 
  return;  // Connect OK
}
Вот получилось это сделать модифицировав чужой исходник. Однако осталась одна маленькая проблема.
Как отключить(корректно удалить из исходника) использование внешнего прокси?
« Последнее редактирование: 20-12-2007 20:09 от Алексей1153++ » Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 05-12-2005 14:47 » 

Насколько я понимаю, именно это вам и нужно -- перенаправить запрос на удалённый адрес site.ru
В этом примере адрес site.ru надо прописать в rmaddr.  Ещё надо в первой строке переформировать URL в соответствии с образцом  http://site.ru/dir/script.php?url=
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
aus
Гость
« Ответ #7 : 05-12-2005 15:39 » 

Если я правильно понял, то
Код:
 
SOCKADDR_IN rmaddr;
rmaddr.sin_family = AF_INET;
rmaddr.sin_addr.s_addr =gethostbyname("site.ru"); //ip адрес
rmaddr.sin_port = htons (80);
но сайт находится на виртуальном хостинге, т.е по ip я не смогу получить его имя.
Записан
aus
Гость
« Ответ #8 : 05-12-2005 15:53 » 

Кажется разобрался. Вот здесь толково написано.
http://www.wasm.ru/print.php?article=1016003
Записан
npak
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 05-12-2005 15:53 » 

1.  gethostbyname возвращает не struct in_addr, a указатель на struct hostent.  Идея воспользоваться gethostbyname верна

2.  Где он хостится -- не важно.  Это проблема хостеров корректно зарегистрировать адрес сайта в DNS.  Браузеры тоже пользуются gethostbyname, и успешно находят адрес.  Значит ваш агент тоже справится.
Записан

UniTesK -- индустриальная технология надежного тестирования.

http://www.unitesk.com/ru/
aus
Гость
« Ответ #10 : 06-12-2005 11:09 » 

Спасибо, npak.
Сделал - заработало, только через некоторое время вываливается ошибка (память по такомуто адресу не может быть прочитана). Почоже на переполнение буфера или выход за пределы массива. Как мне выловить ошибку?
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines