На главную
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
15 мая "Исходники.РУ" отмечают 20-летие присутствия в сети!
Поздравляем всех причастных и неравнодушных с юбилеем сайта!
И огромное спасибо всем, кто был с нами все эти годы!
msm.ru
! Правила раздела "Наши Исходники"
Раздел предназначен для публикации различных исходников и программных решений (в виде исходных текстов), которые Вы считаете достойными внимания и/или интересными. Язык исходника значения не имеет. Это может быть C/C++, Pascal, Perl, PHP, C#, Foth, Prolog или любой другой существующий язык программирования. Единственный момент – в названии темы этот язык должен быть указан. Например, «[C++] Представление чисел в римской записи». Сам исходный текст должен содержаться в первом посте темы. Если исходник занимает не больше одного-двух экранов, то допустимо его публикация непосредственно в посте. Иначе исходный текст должен быть прикреплен к посту в виде архива. Кроме того, первый пост должен содержать:

- Информацию о платформе/компиляторе, для которых предназначен исходный текст (если эта информация существенна)
- Ссылку на оригинал и автора (если публикуется чужой исходный текст)
- Максимально подробное описание – какую задачу решает опубликованный исходный текст, и чем он интересен.

Плагиат крайне не приветствуется. Также не приветствуется публикация исходных текстов вирусов, крэков и т. п. информации. Это элементарно противозаконно.

Для быстрого поиска нужного исходника можно воспользоваться навигатором:
Быстрый поиск по разделу
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> [C++] azHttpSock, Отправка POST и GET запросов
    Кл(юч)евые слова: WinSock, Sockets, Win, Windows, WinApi, Win32, POST, GET, HTTP, AZote, Азот

    azHttpSock - работа с протоколом HTTP посредством сокетов

    На форуме продолжают часто создавать темы с призывами о помощи в работе с передачей данных по интернету. Больше всего людей волнует схема отправки POST-запроса, а в частности заливка файла и авторизация на сайте. И я не удивлен, знаете ли. Чтобы передать на сайт всего лишь один файл, нужно сформировать довольно ёмкий текстовый запрос. А всего лишь одна ошибка в одном символе может привести к тому, что запрос будет отвергнут сервером или обрабатывающим скриптом. Поэтому автоматизация и упрощение схемы обращения с выше упомянутым протоколом - довольно острая и актуальная проблема для современного программиста!

    Ранее мною был создан и выложен в исходниках аналогичный компонент azHTTP. Однако написан он был на основе WinInet функций и потому имел всякого рода ограничения. Новый же компонент более эллегантен и оптимален! Он имеет ряд достоинств, делающих его использование удобным и приятным.
    Вот некоторые из них:
    - возможность прямой загрузки контента в файл;
    - слежение за прогрессом заливки / загрузки;
    - возможность загрузки кодированных в deflate и gzip данных (при использовании совместно с zlib);
    - поддержка перенаправлений (Location, Refresh);
    - возможность остановки передачи / приема данных;
    - поддержка таймаутов (использование неблокирующих сокетов);
    - и многое другое!

    Интерфейс пользователя

    ExpandedWrap disabled
      public: // Functions for users
       
          /*
          * Инициализация созданного объекта.
          *   <cp> - кодировка удаленного файла (по умолчанию CP_ACP);
          *   <agent> - идентификационная строка агента (по умолчанию Opera ...);
          *   <proxy> - адрес и порт прокси-сервера (000.000.000.000:0000);
          */
          azHttpSock(UINT cp = 0, LPCTSTR agent = 0, LPCTSTR proxy = 0);
          /* ... */
          ~azHttpSock();
          /*
          * Добавление / изменение заголовков запроса.
          *   <name> - название заголовка (User-Agent, Referer, etc);
          *   <cval> - значение заголовка в ascii ("Opera", "http://web.ru/", etc);
          *   <wval> - значение заголовка в юникоде (---);
          *   <uival> - значение заголовка в виде целого без знака;
          */
          void set_header(LPCSTR name, LPCSTR cval, bool toadd = false);
          void set_header(LPCSTR name, LPCWSTR wval, bool toadd = false);
          void set_header(LPCSTR name, UINT uival);
          void set_header(LPCSTR name); // Удаление заголовков
          /*
          * Функции установки куки.
          *   <name> - имя куки (login);
          *   <val> - значение куки (qwerty);
          *   <name_val> - имя и значение куки через знак равенства (login=qwerty);
          */
          void set_cookie(LPCSTR name, LPCSTR val);
          void set_cookie(LPCSTR name_val);
          /*
          * Установка прокси-сервера (не требующего авторизации)
          *   <proxy> - адрес и порт прокси сервера (000.000.000.000:0000);
          */
          void set_proxy(LPCTSTR proxy);
          /*
          * Установка таймаута ожидания запроса (ответа).
          *   <timeout> - количество секунд (от 10 до 300);
          */
          void set_timeout(long timeout);
          /*
          * Установка кодировки.
          */
          void set_charset(UINT charset);
          /*
          * Установка наблюдающей за прогрессом функции.
          *   <func> - ссылка на функцию (0 - удаление наблюдателя);
          *   <param> - указатель на доп. данные;
          */
          void set_watcher(PROGRESSWATCHERPROC func, void* param);
          /*
          * Посылка GET запроса и запись ответа в буфер памяти.
          *   <url> - ссылка на удаленный файл;
          */
          bool GET(LPCTSTR url);
          bool operator<<(LPCTSTR url);
          /*
          * Посылка GET запроса и запись ответа сразу в файл.
          *   <url> - ссылка на удаленный файл;
          *   <file> - файл, в который будет произведена запись ответа;
          */
          bool GET2file(LPCTSTR url, LPCTSTR file);
          /*
          * Посылка POST запроса и запись ответа в буфер памяти.
          *   <url> - ссылка на удаленный файл;
          */
          bool POST(LPCTSTR url);
          bool operator>>(LPCTSTR url);
          /*
          * Посылка HEAD запроса.
          *   <url> - ссылка на удаленный файл;
          */
          bool HEAD(LPCTSTR url);
          bool operator==(LPCTSTR url);
          /*
          * Получить ответ в байтах или в юникоде.
          */
          const CHAR* c_str();
          const WCHAR* w_str();
          /*
          * Получить полный адрес последнего запроса
          */
          const CHAR* c_url();
          const WCHAR* w_url();
          /*
          * Получить имя последнего сохраненного файла.
          */
          LPCTSTR get_file() { return db.s_outfile; }
          /*
          * Получить код ответа сервера для последнего запроса.
          */
          long get_respcode() { return db.l_respcode; }
          /*
          * Получить размер ответа в байтах.
          */
          long get_length() { return db.l_length; }
          /*
          * Получить код последней ошибки.
          */
          int get_error() { return db.i_err; }
          /*
          * Получить прогресс передачи / приема
          */
          double send_progress() { return db.d_send_progr; }
          double read_progress() { return db.d_read_progr; }
          /*
          * Получить код состояния обмена
          */
          int get_state() { return db.i_state; }
          /*
          * Очистка буферов (запрос, ответ).
          */
          void clear();
          /*
          * Добавление данных в тело POST-запроса.
          *   <name> - имя добавляемого поля ();
          *   <cval>,<wval>,<lval> - значения полей в ascii, unicode, integer ();
          *   <file> - путь к файлу;
          */
          void form_input(LPCSTR name, LPCSTR cval);
          void form_input(LPCSTR name, LPCWSTR wval);
          void form_input(LPCSTR name, long lval);
          bool form_file(LPCSTR name, LPCSTR file);
          bool form_file(LPCSTR name, LPCWSTR wfile);
          /*
          * Сохранение ответа в файл.
          *   <file> - путь и имя выходного файла (c:\index.html);
          */
          bool save(LPCTSTR file);
          /*
          * Прерывание передачи
          */
          void stop();


    Пример эксплуатации

    Пример демонстрирует заливку изображения на хостинг http://funkyimg.com/ и обратную загрузку этого изображения с хостинга в файл с другим именем.

    ExpandedWrap disabled
      #pragma comment(lib, "zlib/zdll.lib")
      #pragma comment(lib, "Ws2_32.lib")
       
      #include <windows.h>
      #include <stdlib.h>
      #include <fstream>
      #include <stdio.h>
      #include <conio.h>
       
      #include "azHttpSock.h"
       
      using namespace std;
       
      void CALLBACK progresswatcher(void* dat, int state, double progress, int totbytes);
       
      int main(int argc, char* argv[])
      {
          WSADATA wsaData;
          if (WSAStartup(MAKEWORD(2,2), &wsaData) != NO_ERROR) {
              printf("WSAStartup failed");
              return 0;
          }
          //
          //-----------------------------------------------
          //
          azHttpSock http;
          // Инициализация
          http.set_watcher(progresswatcher, 0);
          http.set_header("Referer", "http://funkyimg.com/");
          // Создание тела POST запроса
          http.form_input("uptype", "file");
          http.form_file("file", L"image.jpg");
          http.form_input("maxNumber", 1);
          http.form_input("maxId", 1);
          // Отправка запроса (заливаем картинку на funkyimg.com)
          printf("Uploading the image...\n\n");
          http >> L"http://funkyimg.com/up.php"; // http.POST(L"http://funkyimg.com/up.php");
          // Сохранение ответа в файл
          http.save(L"d:\\upload.html");
          // Парсинг ответа в поисках ссылки
          WCHAR url[MAX_PATH];
          WCHAR* ptr1 = (WCHAR*)http.w_str(); // Перекодирование ответа в юникод и получение указателя
          ptr1 = wcsstr(ptr1, L"Direct link to image");
          if(ptr1) {
              while(*ptr1 != ':') ptr1--; ptr1 -= 4;
              WCHAR* ptr2 = wcschr(ptr1, '\"');
              if(ptr1 && ptr2) {
                  wcsncpy_s(url, MAX_PATH, ptr1, ptr2 - ptr1);
                  wprintf_s(L"\nURL: %s\n\n", url);
              }
          }
          // Очистка буферов запроса
          http.clear();
          // Загрузим обратно картинку сразу в файл с другим именем
          printf("\nDownloading the image...\n\n");
          http.GET2file(url, L"image_back.jpg");
          //
          //-----------------------------------------------
          //
          WSACleanup();
          printf("\nPress any key to exit...");
          _getch();
          return 0;
      }
       
      void CALLBACK progresswatcher(void* dat, int state, double progress, int totbytes)
      {
          switch(state)
          {
          case AHS_STATE_SEND:
              printf("-> send : %03d %%\tbytes = %d\n", (int)(progress * 100), totbytes);
              break;
          case AHS_STATE_READ:
              printf("<- read : %03d %%\tbytes = %d\n", (int)(progress * 100), totbytes);
              break;
          }
      }


    Скриншот результата работы программы:
    user posted image


    Загрузить
    Demo project + azHttpSock v1.1Прикреплённый файлahs.7z (161,95 Кбайт, скачиваний: 440)
    Сообщение отредактировано: AZote -
    Моральная уверенность всегда является признаком культурной неполноценности.
    Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
      Цитата AZote @
      Инициализация созданного объекта.
      Э-э..., вообще-то, это называется "конструктор".
      Цитата AZote @
      <cp> - кодировка удаленного файла (по умолчанию CP_ACP);
      А что такое "кодировка удалённого файла"?

      А метод HEAD - поддерживается?
      А метод POST с данными не из файла и Content-Type не application/x-www-form-urlencoded - поддерживается?
      А при GET - есть возможность на "лету" по Content-Type решить, сохранять в файл или нет?
      А Transfer-Encoding: chunked - поддерживается? ;)

      Прогресс отсылки или передачи, это конечно здорово. Но в довесок неплохо бы иметь колбэки - на коннект, на дисконнект, на приём заголовка HTTP-пакета, наприём всего HTTP-пакета, на перенаправление.

      А почему не использовались std::string/std::wstring, а ужаснаястранная смесь из голых указателей на TCHAR, CHAR и WCHAR? С utf8, кстати, всё нормально?
        Цитата Adil @
        А что такое "кодировка удалённого файла"?

        Цитата
        <meta http-equiv="content-type" content="text/html; charset=windows-1251">


        Цитата Adil @
        А метод HEAD - поддерживается?

        Пока нет (за ненадобностью).

        Цитата Adil @
        А метод POST с данными не из файла и Content-Type не application/x-www-form-urlencoded - поддерживается?

        А если не из файла, так из чего еще например?
        А зачем поддерживать application/x-www-form-urlencoded, если это по сути тот же multipart/form-data только без медиа данных?

        Цитата Adil @
        А при GET - есть возможность на "лету" по Content-Type решить, сохранять в файл или нет?

        Нет.

        Цитата Adil @
        А Transfer-Encoding: chunked - поддерживается?

        Да, полностью поддерживается (сумел таки извратиться). :)

        Цитата Adil @
        на коннект, на дисконнект, на приём заголовка HTTP-пакета, наприём всего HTTP-пакета, на перенаправление.

        И что, для всех этих событий делать разные колбэки?? :huh:

        Цитата Adil @
        А почему не использовались std::string/std::wstring, а ужаснаястранная смесь из голых указателей на TCHAR, CHAR и WCHAR?

        Использовались, только внутри самого компонента. А так сделано для большей переносимости как любителями STL, так и нелюбителями.

        Цитата Adil @
        С utf8, кстати, всё нормально?

        Все нормально, если была правильно установлена кодировка удленного файла. Можно было конечно определять по Content-Encoding, но этот параметр мне необходим так же и для формирования POST запроса. Поэтому решил перенести заботу об этом на плечи пользователя этого класса.
        Моральная уверенность всегда является признаком культурной неполноценности.
        Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
          Цитата AZote @
          Цитата Adil @
          А что такое "кодировка удалённого файла"?

          Цитата
          <meta http-equiv="content-type" content="text/html; charset=windows-1251">
          Это же HTML-тег, что тогда означет эта поддержка? В классе происходит парсинг HTML? Тогда название класса станновато выглядит. Ведь HTTP != HTML

          Цитата AZote @
          Цитата Adil @
          А метод HEAD - поддерживается?

          Пока нет (за ненадобностью).
          За чьй не надобностью? Если ты предлагаешь компонент для удобной работы с HTTP, решая за пользоваиеля, что ему нужно, а что нет?

          Цитата AZote @
          Цитата Adil @
          А метод POST с данными не из файла и Content-Type не application/x-www-form-urlencoded - поддерживается?

          А если не из файла, так из чего еще например?
          А зачем поддерживать application/x-www-form-urlencoded, если это по сути тот же multipart/form-data только без медиа данных?
          Ну multipart - это "много частей", в отличие от.
          У меня там, кстати, стоит "Content-Type не application" - я думал, что у тебя так передача данных формы реализована :)
          А данные для пост могут быть любыми - тот же файл передать, на лету шифруя/сжимая. Просто какие-то данные передать - не делать эе для этого файл? Задание произвольного HTTP-заголовка есть, почему бы не добавить и отсылку произвольных данных? Т.е. что то вроде метода setPostData(const std::vector<unsigned char>&) ну или через указатели

          Цитата AZote @
          Цитата Adil @
          А при GET - есть возможность на "лету" по Content-Type решить, сохранять в файл или нет?

          Нет.
          Странно. А если там не файл?

          Цитата AZote @
          Цитата Adil @
          А Transfer-Encoding: chunked - поддерживается?

          Да, полностью поддерживается (сумел таки извратиться). :)
          Молодец. :)

          Цитата AZote @
          Цитата Adil @
          на коннект, на дисконнект, на приём заголовка HTTP-пакета, наприём всего HTTP-пакета, на перенаправление.

          И что, для всех этих событий делать разные колбэки?? :huh: .
          Ну можно и один, если получится. Ведь, например, как быть, если пользователь класса не хочет, чтобы его перенаправляли на другой сайт?
          Если бы класс был реализован как шаблон, то создание колбэков не представляло бы значительной трудности.

          Цитата AZote @
          Цитата Adil @
          А почему не использовались std::string/std::wstring, а ужаснаястранная смесь из голых указателей на TCHAR, CHAR и WCHAR?

          Использовались, только внутри самого компонента. А так сделано для большей переносимости как любителями STL, так и нелюбителями.
          Для "любителей" STL такой подход ужасен, а о "нелюбителях" STL можно уже и не думать, имхо.
            Цитата Adil @
            Это же HTML-тег, что тогда означет эта поддержка? В классе происходит парсинг HTML?

            Нет, парсинга не происходит. Этот параметр просто говорит, в какой кодировке пользователь ожидает файл, чтобы уже компонент при вызове его функции w_str правильно перекодировал текст.

            Цитата Adil @
            За чьй не надобностью? Если ты предлагаешь компонент для удобной работы с HTTP, решая за пользоваиеля, что ему нужно, а что нет?

            Ну если поступят просьбы с добавлением поддержки HEAD, то добавлю. Хотя этот метод используется крайне редко. Лично я его использовал лишь однажды и то в рамках любопытства. :D

            Цитата Adil @
            почему бы не добавить и отсылку произвольных данных?

            Да пожалуйста. Можно отправлять любые данные. Методы form_input и form_file к вашим услугам! :)

            Цитата Adil @
            Странно. А если там не файл?

            Иногда требуется сохранить просто текст страницы в формате html (ну или в чем придет ответ).

            Цитата Adil @
            Ведь, например, как быть, если пользователь класса не хочет, чтобы его перенаправляли на другой сайт?

            Браузер, помоему, тоже не спрашивает, хочет пользователь перенаправиться или нет. :whistle: Раз сервер приказал перенаправить, значит стоит его послушаться. :crazy:

            Цитата Adil @
            Для "любителей" STL такой подход ужасен, а о "нелюбителях" STL можно уже и не думать, имхо.

            Такой подход более универсален.
            При использовании STL пользователь так же легко получит то, что хочет, как если бы этот компонент был чисто для STL.
            ExpandedWrap disabled
              std::string page(http.c_str());

            Я являюсь частичным пользователем STL, поэтому о себе то я должен был побеспокоиться. :rolleyes:

            Добавлено
            Цитата AZote @
            Да пожалуйста. Можно отправлять любые данные. Методы form_input и form_file к вашим услугам!

            А-а, понял. Можно добавить метод form_data. Но какими тогда должны быть следующие параметры?
            ExpandedWrap disabled
              "Content-Disposition: form-data; name=\"%s\"\r\n"
              "Content-Type: %s\r\n"
            Моральная уверенность всегда является признаком культурной неполноценности.
            Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
              Цитата AZote @
              Нет, парсинга не происходит.
              Как же ты достаёшь этот тэг? :huh: Хотя бы частично, но должен парсить.

              Цитата AZote @
              Ну если поступят просьбы с добавлением поддержки HEAD, то добавлю. Хотя этот метод используется крайне редко. Лично я его использовал лишь однажды и то в рамках любопытства.
              Так его добавить-то - "две строчки кода". Вместо GET ставить HEAD.

              Цитата AZote @
              Браузер, помоему, тоже не спрашивает, хочет пользователь перенаправиться или нет. :whistle: Раз сервер приказал перенаправить, значит стоит его послушаться. :crazy:
              Это зависит от настроек браузера.

              Цитата AZote @
              А-а, понял. Можно добавить метод form_data. Но какими тогда должны быть следующие параметры?
              Пусть пользователь сам задаёт необходимые заголовки. И это необязательно должен быть "Content-Disposition: form-data; ..."


              Библиотка - она и есть библиотека. Всё предусмотреть невозможно. Поэтому можно реализовать часто используемый функционал протокола, но обязательно оставить возможность работать и с остальным. Это называется "гибкость" :)

              Добавлено
              Цитата AZote @
              При использовании STL пользователь так же легко получит то, что хочет, как если бы этот компонент был чисто для STL.
              Это то понятно, только тогда происходит лишнее копирование.
              ExpandedWrap disabled
                const std::string& page = http.asStdString();
              было бы лучше.

              З.Ы. Что за page кстати? Всё-таки складывается ощущение, что у тебя в этом класса http и html пересекаются. :)
              Сообщение отредактировано: Adil -
                Цитата Adil @
                Как же ты достаёшь этот тэг? Хотя бы частично, но должен парсить.

                Я его никак не достаю. Пользователь сам смотрит в каком виде кодируются на сайте страницы и соответствующим образом инициализирует компонент azHttpSock.
                Например, нужно мне загружать страницы с этого форума. Я посмотрю этот тег воочию, увижу что кодировка соответствует CP_ACP, и уже при написании программы создам объект azHttpSock http(CP_ACP).
                Если вдруг я захочу загружать страницы с radikal.ru, то я увижу, что у него этот тег принимает значение. соответствующее CP_UTF8. Поэтому объект я уже создам иным образом: azHttpSock http(CP_UTF8).

                Цитата Adil @
                З.Ы. Что за page кстати? Всё-таки складывается ощущение, что у тебя в этом класса http и html пересекаются.

                Это я просто так обозвал, подразумевая, что ответом является html страница.
                Моральная уверенность всегда является признаком культурной неполноценности.
                Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
                  Цитата AZote @
                  Например, нужно мне загружать страницы с этого форума. Я посмотрю этот тег воочию, увижу что кодировка соответствует CP_ACP, и уже при написании программы создам объект azHttpSock http(CP_ACP).
                  Если вдруг я захочу загружать страницы с radikal.ru, то я увижу, что у него этот тег принимает значение. соответствующее CP_UTF8. Поэтому объект я уже создам иным образом: azHttpSock http(CP_UTF8).
                  Хм. Обычно заранее кодировка не известна.

                  Цитата AZote @
                  Это я просто так обозвал, подразумевая, что ответом является html страница.
                  Но http.c_str() что возвращает?
                    Цитата Adil @
                    Но http.c_str() что возвращает?

                    Указатель на буфер байт, представляющий собой ответ сервера за вычетом заголовков.
                    Моральная уверенность всегда является признаком культурной неполноценности.
                    Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
                      Цитата AZote @
                      Указатель на буфер байт, представляющий собой ответ сервера за вычетом заголовков.
                      Буфер байт, или буфер char? Это разные вещи.
                        Цитата Adil @
                        Буфер байт, или буфер char? Это разные вещи.

                        Вообще буфер значится как char. Но не долго привести его к unsigned char.

                        BYTE* pbuff = (BYTE*)http.c_str();
                        Моральная уверенность всегда является признаком культурной неполноценности.
                        Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
                          А если там 0-терминатор посередине?
                            Цитата Adil @
                            А если там 0-терминатор посередине?

                            Для этого в следующей редакции будет функция ::get_length() :crazy:
                            Моральная уверенность всегда является признаком культурной неполноценности.
                            Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
                              Итак. Учел некоторые обсуждаемые нюансы и внес соответствующие изменения.
                              Версия 1.1 компонента теперь доступна для загрузки в первом сообщении.

                              Добавлено:
                              - поддержка HEAD запроса;
                              - функция get_length, возвращающая размер ответного блока данных за вычитом заголовков;
                              - устранение неполадок, выявленных на стадии тестирования.

                              Продолжение следует...

                              Добавлено
                              Если возникнут вопросы в процессе применения этого класса, смело задавайте их в этой теме, а уж никак не в личном сообщении. Ответы пригодятся для всех заинтересованных лиц.
                              Сообщение отредактировано: AZote -
                              Моральная уверенность всегда является признаком культурной неполноценности.
                              Чем менее цивилизован человек, тем больше он уверен в том, что знает, что правильно, а что неправильно.
                                У меня после подключения библиотеки валится регистрация.

                                C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: выход из команды "regsvr32 /s /c "C:\Projects\tickers\aToolBar2\Browsers\IE\6\.\Debug\ToolBand.dll"
                                C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: echo regsvr32 exec. time > ".\Debug\regsvr32.trg"
                                C:\Program Files\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(183,5): error MSB3073: :VCEnd" с кодом 3.

                                В чем может быть дело?
                                We want to sing a big shout to US, and to all ravers in the world!
                                And to Westbam, Marusha, Steve Mason, The Mystic Man, DJ Dick, Carl Cox, The Hooligan, Cosmic...
                                Kid Paul, Dag, Mike VanDike, Jens Lissat, Lenny D., Sven Vath, Mark Spoon, Marco Zaffarano...
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script Execution time: 0,2027 ]   [ 19 queries used ]   [ Generated: 26.05.20, 06:33 GMT ]