Kselax.ru

Hacker Kselax — the best hacker in the world

Menu
  • Блог
  • Контакты
  • wp plugin генератор
  • Русский
    • Русский
    • English
Menu

Работа с curl. visual studio 2010.

Posted on 27 сентября, 20138 августа, 2017 by admin

Рассмотрим библиотеку curl ее возможности, посмотрим как ее подключать и настраивать. Попытаюсь всеобще раскрыть данную тему, потому что она для меня очень важна, я собираюсь писать программы под веб, а с плохими знаниями этой библиотеки будет тяжело что нить сделать. Итак начнем.[tip] libcurl это свободная и простая в использовании клиентская библиотека по передачи данных по URL, она поддерживает DICT, FILE, FTP, FTPS, GOPHER, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, POP3, POP3S, RTMP, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET и TFTP. Также libcurl имеет поддержку SSL сертификатов, HTTP POST, HTTP PUT, FTP загрузку, HTTP form загрузку, proxy, cookies, user+password авторизацию (Basic, Digest, NTLM, Negotiate, Kerberos), докачивания файлов, http прокси туннелирования и многого другого.

libcurl легко переносима, она собирается и работает на многих платформах, включая Solaris, NetBSD, FreeBSD, OpenBSD, Darwin, HPUX, IRIX, AIX, Tru64, Linux, UnixWare, HURD, Windows, Amiga, OS/2, BeOs, Mac OS X, Ultrix, QNX, OpenVMS, RISC OS, Novell NetWare, DOS и остальные…

libcurl свободна, потокобезопасна, совместима с IPv6, функциональна, имеет хорошую поддержку, быстрая, тщательно задокументирована и уже используется во многих известных, крупных и успешных компаний и в многочисленных приложениях. [/tip]


 

Содержание:

1. Установка библиотеки.
2. Основные принципы.
3. Простой пример.
4. Заголовки.
5. Обработка ошибок.
6. Загрузка в буфер.
7. Загрузка в файл.
8. Перенаправление (редирект).
9. Cookie
10. Преобразование в URL вид.
11. POST запрос для входа авторизации на сайте vk.com. (контакт)
12. Получение страниц в сжатом виде.
13. Передача с использованием https


1. Установка библиотеки 

Windows

1. Заходим на сайт http://curl.haxx.se/download.html и скачиваем версию библиотеки для виндовс Win32 — MSVC  ftp://ftp.sunet.se/pub/www/utilities…2-ssl-msvc.zip .

[tip]Там я смотрел по ссылке той либы что раньше была уже нет, поэтому вот ссылка на старую либу которую я использую https://yadi.sk/d/Iu7nUbr4gzrto[/tip]

2. Распаковываем архив и берем оттуда все dll файлы:

  1. curllib.dll
  2. libeay32.dll
  3. openldap.dll
  4. ssleay32.dll

И папку curl ( там заголовойные файлы) находящуюся в папке .\libcurl-7.19.3-win32-ssl-msvc\include.

3. Так же берем curllib.lib из папки .\libcurl-7.19.3-win32-ssl-msvc\lib\Release.

Теперь для подключения curl нужно написать:

1
2
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")

Для работы программы также может понадобиться libsasl.dll ( из OpenSSL ). В таком случае при запуске программы из IDE она сразу же будет прекращать работу после без какой либо ошибки. Если же запустить сам exe файл то вылезит окошко указывающее на недостающую библиотеку. Требуемые dll несложно найти и скачать с интернета.

 

2. Основные принципы.

curl предоставляет несколько интерфейсов:

  1. Easy (Простой режим)
  2. Multi (Многопоточный режим)
  3. Share

При использовании в libcurl «простого» интерфейса вы инициализируете сеанс и получаете handle (часто упоминается как «easy handle»), который вы используете в качестве аргумента в функциях Easy интерфейса. Используйте curl_easy_init, чтобы получить handle.

После получения вы должны установить все нужные параметры в предстоящей передаче, наиболее важным среди которых является URL (передавать что-то без заданного URL невозможно). Вы можете задавать различные функции обратного вызова, которые будут вызываться из библиотеки, при получении данных и т.д. Для всего этого используется curl_easy_setopt.

Список опций можно найти в документации http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTURL

После того как все настройки окончены, вы сообщаете libcurl выполнение передачи с помощью curl_easy_perform. Она проделает все операции и вернет результат своей работы типа перечисления CURLcode.

После передачи, вы можете установить новые настройки и сделать еще передачу, или, если вы уже закончили, вызовите очистку сессии curl_easy_cleanup. Если вы хотите иметь постоянное подключение, не освобождайте handle сразу, вместо этого выполните другие передачи с использованием этого же handle.

Никогда не используйте один и тот же хендл в разных потоках! (можно сделать синхронизацию, но это сведёт на нет плюсы многопоточности)

 

3. Простой пример.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <cstdio>
 
//подключаем curl
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
int main()
{
CURL* curl;//объект
CURLcode res;//сюда запишитса результат
 
//легкая инициализация
curl=curl_easy_init();
 
//если удалось инициализаровать объект
if(curl)
{
//задаем url адресс
curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru");
//выполняем запрос
res=curl_easy_perform(curl);
//закрываем дескриптор curl
curl_easy_cleanup(curl);
}
 
getchar();
 
return 0;
}

 

Этот код выводит в консоль содержимое html страницы.

Начитает easy(простую) сессию curll и возвращает ее дескриптор если не удачно установленный в NULL функция:

1
CURL *curl_easy_init();

 

Завершает работу сессии функция:

1
void curl_easy_cleanup(CURL * curl);

 

Функция:

1
CURLcode curl_easy_setopt(CURL *curl, CURLoption option, parameter);

Задает соответствующего поведение через установку опций, возвращает CURLE_OK (0) если успешно, в противном случае код ошибки определенный константами в файле curl/curl.h.
Опция CURLOPT_URL относится NETWORK-опциям и задает url- адрес. Этот параметр должен иметь вид согласно RFC 3986 формата: «scheme://host:port/path»

 

Функция:

1
CURLcode curl_easy_perform(CURL *curl);

Выполняет отправку запроса на сервер и возвращает CURLE_OK в случае успеха, в противном случае код ошибки.

 

4. Заголовки.

Заголовки запроса можно установить с помощью опций, но в зависимости от версии libcurl, константы определяющие опции могут отличатся.

1
2
3
4
5
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT,"Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0");
curl_easy_setopt(curl_handle, CURLOPT_ENCODING, "gzip,deflate"); // если curl скомпилина вместе с gzip
// curl_easy_setopt(curl_handle, CURLOPT_TCP_KEEPALIVE , 1);  // не нашло такой опции в версии 7.19.3
// curl_easy_setopt(curl_handle, CURLOPT_REFERER,"http://some.com"); // yстанавливает referer
curl_easy_setopt(curl_handle, CURLOPT_AUTOREFERER,1);// автоматически заполняет поле referer

Если установить

1
curl_easy_setopt(curl_handle, CURLOPT_HEADER, 1);

то заголовки ответа http сервера будут отображаться вместе с телом ответа.

 

5. Обработка ошибок.

В случае возникновения ошибки при выполнении функции curl_easy_perform() можно получить ее описание с помощью:

1
const char *curl_easy_strerror(CURLcode errornum);

Эта функция возвращает строку с описанием кода ошибки CURLcode указанным в аргументе:

1
2
3
CURLcode res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
     printf( "curl_easy_perform() failed: %s\n", curl_easy_strerror(res) );

Так же есть возможность получить сообщение об ошибке из буфера ошибок, для этого нужно включить параметр CURLOPT_ERRORBUFFER с помощью ф-ции curl_easy_setopt() указать буфер.

1
2
3
4
5
6
7
static char ErrorBuffer[CURL_ERROR_SIZE]; // размер определяется константой curl
//...
curl_easy_setopt(curl_handle, CURLOPT_ERRORBUFFER, errorBuffer); // указывает буфер ошибок
//...
CURLcode res = curl_easy_perform(curl_handle);
if(res != CURLE_OK)
     cout<<"Error!"<<ErrorBuffer<< endl;

 

6. Загрузка в буфер.

По умолчанию curl выводит данные в stdout то есть в окно консоли. Для того что бы сохранить данные в отдельном буфере нужно указать этот буфер в опции CURLOPT_WRITEDATA и callback функцию которая будет записывать туда данные при их приеме с помощью опции CURLOPT_WRITEFUNCTION.

Функция должна иметь вид:

1
size_t function( char *ptr, size_t size, size_t nmemb, void* userdata);

char * ptr — указатель на принимаемые данные.
size_t size — размер принимамого блока данных
size_t nmemb — общее количество блоков данных.
void* userdata — это параметр опции CURLOPT_WRITEDATA, в который производится запись — наш буфер.

Функция должна возвращать количество обработанных байт (size* nmemb). Если это количество будет отличаться от суммы, полученной на входе вашей функции, то будет отдан сигнал об ошибке в библиотеке. Это можно использовать для прервания передачи, с возвращенным значением CURLE_WRITE_ERROR.

Функция может вернуть значение CURL_WRITEFUNC_PAUSE, которое приведет к приостановке записи в этом соединении.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <cstdio>
#include <cstdlib>
using std::exit;
#include <cstring>
using std::strlen;
#include <iostream>
using std::cout;
using std::endl;
 
//подключаем curl
#include "curl/curl.h"
#pragma comment (lib,"curllib.lib")
 
//создаем буфер
const size_t BUF_SIZE=5000000;
char wr_buf[BUF_SIZE];//массив указателей из 5 милионов указателей
size_t wr_index=0;//переменная для индекса массива указателей (перебор указателей)
 
//Функция которая будет заполнять буфер
static size_t write_data(char* ptr, size_t size, size_t nmemb, char* data)
{
//Если выход за размеры буфера ошибка.
if(data==NULL||/*wr_index+*/size*nmemb>BUF_SIZE)return 0;
 
memcpy(&data[0],ptr,size*nmemb);//дописываем данные в конец
wr_index+=size*nmemb;//изменяем текущее положение
 
return size*nmemb;
}
 
int main()
{
CURL* curl;
CURLcode res;
 
memset(wr_buf,BUF_SIZE+1,0);//заполняем буфер нулями
 
curl=curl_easy_init();
if(curl)
{
curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru");
 
curl_easy_setopt(curl,CURLOPT_WRITEDATA,wr_buf);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data);
 
res=curl_easy_perform(curl);
if(res==CURLE_OK)
{
printf("%s\n Done!",wr_buf);//выводим буфер в консоль
}
else
printf("curle easy_perform() failed: %s\n",curl_easy_strerror(res));
 
curl_easy_cleanup(curl);
}
 
getchar();
return 0;
}

 

В качестве буфера можно использовать контейнер или поток STL например std::string.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
 
//подключаем curl
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
//создаем функцию для записи
static size_t my_fun(char* ptr,size_t size, size_t nmemb, string* str)
{
if(str)
{
//размещает в блоке памяти размером size*nmemb данные из ptr (видимо)
str->append(ptr,size*nmemb);
return size*nmemb;
}
else
return 0;//ошибка
}
 
int main()
{
CURL* curl;
CURLcode res;
 
string content;
curl=curl_easy_init();
if(curl)
{
curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru");
 
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_fun);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&content);
 
res=curl_easy_perform(curl);
if(res==CURLE_OK)cout <<content<<"\nDone!"<<endl;
else
cout <<"curl_easy_perform failed: "<<curl_easy_strerror(res)<<endl;
 
curl_easy_cleanup(curl);
}
 
getchar();
 
return 0;
}

 

7. Загрузка в файл.

Следующий пример показывает как можно сохранить тело ответа сервера в один файл, а заголовок в другой.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <cstdio>
#include <cstdlib>
 
//подключаем curl
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
//создаем функцию для записи
size_t my_func(char* ptr, size_t size, size_t nmemb, FILE* data)
{
return fwrite(ptr,size,nmemb,data);
}
 
int main()
{
//Открываем файлы для заголовка и тела
const char* head="head.txt";
const char* body="body.html";
 
FILE* headfile=fopen(head,"w");
if(headfile==NULL)
return -1;
FILE* bodyfile=fopen(body,"w");
if(bodyfile==NULL)
return -1;
 
//выполняем запрос
CURL* curl=curl_easy_init();
if(curl)
{
curl_easy_setopt(curl,CURLOPT_URL,"http://www.kselax.ru");
 
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,my_func);
 
//записываем заголовок
curl_easy_setopt(curl,CURLOPT_WRITEHEADER,headfile);
//записываем тело
curl_easy_setopt(curl,CURLOPT_WRITEDATA,bodyfile);
 
//отправка запроса
CURLcode res=curl_easy_perform(curl);
if(res!=CURLE_OK)
printf("curl_easy_perform() failed: %s \n",curl_easy_strerror(res));
 
curl_easy_cleanup(curl);
}
 
puts("\n Done!");
getchar();
 
return 0;
}

 

8. Перенаправление (редирект).

Для автоматического перехода на перенаправляемую страницу необходимо установить опцию CURLOPT_FOLLOWLOCATION в 1

1
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1);

Для того что бы ограничить количество перенаправлений нужно установить опцию CURLOPT_MAXREDIRS ее параметр указывает их максимальное количество

1
curl_easy_setopt(curl_handle, CURLOPT_MAXREDIRS, 10); //  останавливаться после 10-ого редиректа

 

9. Cookie

Далее описание опций для работы с cookie

CURLOPT_COOKIE

1
curl_easy_setopt(curl_handle, CURLOPT_COOKIE, cookiestring);

Параметр -указатель на строку в стиле Си для установки cookies в http-запросе.Формат строки должен быть вида name=contents, где name имя cookie, а contents-ее содержание.

Используется, когда вы хотите указать точное содержание cookie-заголовка для отправки на сервер.

Если нужно передать несколько cookie, то строка должна выглядеть как «name1 = content1; name2 = content2;» и т.д.

CURLOPT_COOKIEFILE

1
curl_easy_setopt(curl_handle, CURLOPT_COOKIEFILE, cookiefilename);

Принимает указатель на строку в стиле Си, в которой храниться путь к файлу, который содержит cookies. Cookies должны храниться в формате куков Netscape/Mazilla или в обычном HTTP-стиле заголовков (Set-Cookie: …) помещенных в файл

Если указать несуществующий файл или пустую строку («»), то это разрешит libcurl полученные использовать cookie в следующих запросах для данного дескриптора curl.

Можно несколько раз устанавливать эту опцию для загрузки нескольких файлов с куками.

CURLOPT_COOKIEJAR

1
curl_easy_setopt(curl_handle, CURLOPT_COOKIEJAR, cookiefilename);

Запишет все известные cookies в указанный файл. Если cookies нет файл не будет создан. Если указать «-» вместо имени файла cookies будут выведены в окно консоли (stdout), и будет разрешено использование cookies для этой сессии.

Если файл не может быть создан или сохранен libcurl не выдаст ошибку.Использование опций CURLOPT_VERBOSE или CURLOPT_DEBUGFUNCTION вызовет вывод предупреждения

CURLOPT_COOKIESESSION

1
curl_easy_setopt(curl_handle, CURLOPT_COOKIESESSION, 1);

Установка в 1 укажет текущему сеансу начать новую «сессию» cookies. Это заставит libcurl проигнорировать все «сессионные» cookies, которые она должна была бы загрузить, полученные из предыдущих сессий. По умолчанию, libcurl всегда сохраняет и загружает все cookies, вне зависимости от того, являются ли они «сессионными» или нет. «Сессионные» cookies-это cookies без срока истечения, которые должны существовать только для текущей «сессии».

CURLOPT_COOKIELIST

1
curl_easy_setopt(curl_handle, CURLOPT_COOKIELIST, "ALL"); // Чистка cookies

Устанавливает cookies.

Если задать параметр «ALL» то все cookies будут очищены, если «FLUSH» будут сохранены в файл указанный в опции CURLOPT_COOKIEJAR

Для вывода информации о cookie можно воспользоваться функцией из примера cookie_interface.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//получает объект curl
static void print_cookies(CURL *curl)
{
    CURLcode res;//код для ошибки
//непонятные структуры
    struct curl_slist *cookies;
    struct curl_slist *nc;
    int i;
 
    printf("Cookies, curl knows:\n");
    res = curl_easy_getinfo(curl, CURLINFO_COOKIELIST, &cookies);//получить инфо о куки
    if (res != CURLE_OK)//если не ок, то вывод ошибки
    {
        fprintf(stderr, "Curl curl_easy_getinfo failed: %s\n",
                        curl_easy_strerror(res ));
        exit(1);
    }
 
//вывод всех куки
    nc= cookies, i = 1;
    while (nc)
    {
        printf("[%d]: %s\n", i, nc->data);
        nc = nc->next;//переход к следующей куке
        i++;
    }
    if (i == 1)  printf("(none)\n");//типо нету куки
 
    curl_slist_free_all(cookies);//эта функция видимо удаляет
}

 

10. Преобразование в URL вид.

Иногда возникает необходимость передавать GET/POST запросы параметры которые содержат в себе символы требующие «экранирования» (кириллица, символ @).К примеру необходимо выполнить поиск в яндексе по слову «Программирование», если посмотреть в строку браузера, то там это будет выглядеть так:

1
http://yandex.ua/yandsearch?text=Программирование

Слово «Программирование» должно экранироваться при запроссе.

1
http://yandex.ua/yandsearch?text=%CF%F0%EE%E3%F0%E0%EC%EC%E8%F0%EE%E2%E0%ED%E8%E5

Для этих целей в curl предусмотрена функция.

1
char* curl_easy_escape( CURL* curl , char* url , int length );

Эта функция преобразует входную строку в закодированную для URL строку и возвращает ее в качестве новой выделенной строки. Все входные символы, кроме a-z, A-Z, 0-9 преобразуются в их «замаскированные» версии (%NN, где NN — двузначное шестнадцатеричное число).

Если длинна аргумента имеет значение 0 (ноль), curl_easy_escape() использует strlen() на входной строке чтобы вычислить размер.

Вы должны освободить полученную строку с помощью curl_free, после окончания работы с ней

1
void curl_free ( char* ptr );

curl_free освобождает память которая была была выделена внутри функции curl. Необходимо использовать curl_free() вместо free(), что бы избежать ошибок, которые могут возникнуть по причине возможных различий при управлении памятью в вашем приложении и curl.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <cstdio>
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
#include <string>
using std::string;
 
//подключаем curl
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
int main()
{
CURL* curl;
CURLcode res;
 
curl=curl_easy_init();
if(curl)
{
char ru_txt[]="Животные";
//преобразовываем русский текст
char* esc_text=curl_easy_escape(curl,ru_txt,0);
if(!esc_text)//если нул
{
cout <<"Can not convert string to URL"<<endl;
curl_easy_cleanup(curl);
getchar();
return 1;
}
 
string url="http://www.google.ru/#newwindow=1&q=";
url+=esc_text;
 
//освобождаем память
curl_free(esc_text);
 
//задаем url-адресс
curl_easy_setopt(curl,CURLOPT_URL,url.c_str());
//разрешаем перенаправление
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
//выполняем запрос
res=curl_easy_perform(curl);
 
curl_easy_cleanup(curl);//удаляем дескриптора
}
 
getchar();
 
return 0;
}

 

Для удобства использования c std::string можно написать такую функцию:

1
2
3
4
5
6
7
8
9
10
11
std::string escape(CURL *curl_handle, const std::string& text)
{
    std::string result;
    char* esc_text= curl_easy_escape(curl_handle, text.c_str(), text.length());
    if(!esc_text) throw std::runtime_error("Can not convert string to URL");
 
    result = esc_text;
    curl_free(esc_text);
 
    return result;
}

 

11. POST запрос для входа авторизации на сайте vk.com. (контакт)

В качестве примера приведу авторизацию на vk.com с последующим переходом на страницу для поиска людей, для работы примера вам необходимо указать свой e-mail и пароль. Результат работы программы она копирует страницу поиска и создает файл text.html.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#include <cstdio>
#include <cstdlib>
using std::exit;
 
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
using std::cin;
using std::ostream;
using std::runtime_error;
 
//подключаем curl
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
//функция экранирования
string escape(CURL* curl,const string& text)
{
string result;
char* esc_text=curl_easy_escape(curl,text.c_str(),text.length());
if(!esc_text)throw runtime_error("Can not convert string to URL");
 
result=esc_text;
curl_free(esc_text);
 
return result;
}
 
static size_t write_data(char* ptr, size_t size, size_t nmemb, string* data)
{
if(data)
{
data->append(ptr,size*nmemb);
return size*nmemb;
}
else return 0;
}
 
static size_t write_head(char* ptr, size_t size, size_t nmemb, ostream* stream)
{
(*stream)<< string(ptr, size*nmemb);
return size*nmemb;
}
 
int main()
{
string content;
 
/*Пользовательские данные*/
//string url_dologin="http://www.cyberforum.ru/login.php?do=login";//страница входа
string url_dologin="http://login.vk.com/?act=login";
 
string user_name;//e-mail
string password;//pass
 
cout <<"email: "; getline(cin,user_name);
cout <<"password: "; getline(cin,password);
cout <<endl;
 
string url_user="http://vk.com/search?c[name]=1&c[photo]=1&c[section]=people"; // Мой кабинет
 
//инициализация curl
CURL* curl=curl_easy_init();
 
if(curl)
{
//формирование запросса на основе пользовательских данных
 
std::string post_data;
        post_data+= "vb_login_username="  + escape(curl, user_name);
        post_data+= "&cookieuser=1";
        post_data+= "&vb_login_password=" + escape(curl, password);
        post_data+= "&s=&securitytoken=guest";
        post_data+= "&do=login";
        post_data+= "&vb_login_md5password=";
        post_data+= "&vb_login_md5password_utf=";
 
post_data+="act=login";
post_data+="role=al_frame";
post_data+="expire=";
post_data+="captcha_sid=";
post_data+="captcha_key=";
post_data+="_origin=http%3A%2F%2Fvk.com";
post_data+="ip_h=";
post_data+="email="+escape(curl,user_name);
post_data+="pass="+escape(curl,password);
 
curl_easy_setopt(curl,CURLOPT_URL,url_dologin.c_str());
 
//сохроняем html код страницы в строку content
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data);
curl_easy_setopt(curl,CURLOPT_WRITEDATA,&content);
 
//Заголовок ответа сервера выводим в консоль
curl_easy_setopt(curl,CURLOPT_HEADERFUNCTION,write_head);
curl_easy_setopt(curl,CURLOPT_WRITEHEADER,&cout);
 
//автоперенаправление
curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1);
//max 5 перенаправлений
curl_easy_setopt(curl,CURLOPT_MAXREDIRS,5);
//разрешаем использовать cookie (разрешает куки использовать в текущем curl)
curl_easy_setopt(curl,CURLOPT_COOKIEFILE,"");
 
/* POST - запрос с авторизацией (происходит получение кукисов)*/
curl_easy_setopt(curl,CURLOPT_POSTFIELDS, post_data.c_str());
curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,post_data.length());
 
CURLcode res=curl_easy_perform(curl);
if(res!=CURLE_OK)
{
cout <<curl_easy_strerror(res)<<endl;
getchar();
return 0;
}
// cout <<"dsfsdafsa"<<endl;exit(1);
//Проверяем успешно ли авторизовались
//if(content.find("Спасибо, что зашли")!=string::npos)
if(content.size()!=0)
{
cout <<"Autentificated!"<<endl;
}
else
{
cout <<"Non-autentificated!"<<endl;
curl_easy_cleanup(curl);
getchar();
return 0;
}
 
/* Get- запросс для перехода в "Мой кабинет форума" */
content.clear();//очищаем строку
//меняем post режим на get
curl_easy_setopt(curl,CURLOPT_POST,0);
curl_easy_setopt(curl,CURLOPT_HTTPGET,1);
//меняем url
curl_easy_setopt(curl,CURLOPT_URL,url_user.c_str());
 
//отправляем запрос
res=curl_easy_perform(curl);
 
if(res!=CURLE_OK)
{
cout <<curl_easy_strerror(res)<<endl;
}
 
//Проверяем получили то что ожидали
if(content.size()!=0)
{
cout <<content<<endl;
FILE* f=fopen("text.html","w");
fprintf(f,"%s",content.c_str());
fclose(f);
cout <<"content.size()= "<<content.size()<<endl;
cout <<"Done!"<<endl;
}
else
{
cout <<"Is not my cabinet page"<<endl;
}
curl_easy_cleanup(curl);
}
 
return 0;
}

Основные моменты:

1. Для успешной авторизации и перехода по страницам нужно:

  1. разрешить использовать полученные cookie;
  2. включить автоматический переход по перенаправлениям

2. По умолчанию libcurl использует GET режим отправки запросов, после установки опции CURLOPT_POSTFIELDSIZE он переключается на POST, поэтому для осуществления последующего GET нужно переключить режим на GET

1
2
curl_easy_setopt(curl_handle, CURLOPT_POST, 0); // выключаем POST
curl_easy_setopt(curl_handle, CURLOPT_HTTPGET, 1);// включаем GET

3. Для анализа того что отправляет и принимает програмка удобно использовать снифер я вообще использую надстройку для фаерфокса, что бы посмотреть что отсылать.

 

12. Получение страниц в сжатом виде.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <string>
#include <iostream>
 
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")    // для VC++
//---------------------------------------------------------------------------
int main()
{
    std::string url= "http://www.google.ru/";
 
    CURL *curl_handle = curl_easy_init();
    if(curl_handle)
        {
            curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str() );
            curl_easy_setopt(curl_handle, CURLOPT_ENCODING, "gzip,deflate"); // Принудительно ставим gzip
 
            CURLcode res = curl_easy_perform(curl_handle);
            if(res != CURLE_OK)
                 std::cout<<"Error #"<<res<<" "<<curl_easy_strerror(res) <<std::endl;
 
            curl_easy_cleanup(curl_handle);
        }
 
    std::cout<<std::endl<<"Done!";
    getchar();
    return 0;
}

 

13. Передача с использованием https

Для работы по протоколу HTTPS необходимо что бы libcurl была собрана с поддержкой SSL, а также необходимы соответствующие dll-ки (из OpenSSL)Если библиотека собрана без SSL, то функция curl_easy_perform() вернет код CURLE_UNSUPPORTED_PROTOCOL (1) «Unsupported protocol»

Далее пример простого https— запроса :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include <cstdio>
#include <cstdlib>
#include <string>
using std::string;
#include <iostream>
using std::cout;
using std::endl;
 
#include "curl/curl.h"
#pragma comment(lib,"curllib.lib")
 
size_t write_data(char* ptr, size_t size, size_t nmemb, FILE* data)
{
return fwrite(ptr,size,nmemb,data);
}
 
int main()
{
//Открываем файлы для заголовка и тела
string body_filename="body.html";
FILE* body_file=fopen(body_filename.c_str(),"w");
if(body_file==NULL)return -1;
 
string url="https://my.webmoney.ru/login.aspx";
 
CURL* curl=curl_easy_init();
if(curl)
{
//сохранение в файл html-страницу
curl_easy_setopt(curl,CURLOPT_WRITEDATA,body_file);
curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,write_data);
//заголовки ответа выводим в консоль
curl_easy_setopt(curl,CURLOPT_WRITEHEADER,stdout);
 
//https - запрос
curl_easy_setopt(curl,CURLOPT_URL,url.c_str());
 
//не проверять ssl - сертификат
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYPEER,0);
//не проверять хост ssl - сертификата
curl_easy_setopt(curl,CURLOPT_SSL_VERIFYHOST,0);
 
//отправляем запрос
CURLcode res=curl_easy_perform(curl);
if(res!=CURLE_OK)
cout <<"error "<<res<<' '<<curl_easy_strerror(res)<<'\n';
else
cout <<"Done!"<<endl;
 
//закрываем curl
curl_easy_cleanup(curl);
}
 
getchar();
 
return 0;
}
 
/*
#include <stdio.h>
#include <stdlib.h>
 
#include <string>
#include <iostream>
 
#include "curl/curl.h"
//#pragma comment(lib,"curllib-bcb.lib") // Для C++Builder
#pragma comment(lib,"curllib.lib")    // для VC++
//---------------------------------------------------------------------------
size_t write_data( char *ptr, size_t size, size_t nmemb, FILE* data)
{
    return fwrite(ptr, size, nmemb, data);
}
//---------------------------------------------------------------------------
int main()
{
    // Открываем файлы для заголовка и тела
    std::string body_filename  = "body.html";
    FILE *body_file =  fopen(body_filename.c_str(),"w");
    if (body_file == NULL)  return -1;
 
    std::string url= "https://my.webmoney.ru/login.aspx";
 
    CURL *curl_handle = curl_easy_init();
    if(curl_handle)
        {
            // сохранение в файл html-страницу
            curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, body_file);
            curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
            // заголовки ответа выводим в консоль
            curl_easy_setopt(curl_handle, CURLOPT_WRITEHEADER, stdout);
 
               /* HTTPs  Запрос
            curl_easy_setopt(curl_handle, CURLOPT_URL, url.c_str() );
 
             // не проверять SSL сертификат
            curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYPEER, 0);
            // не проверять Host SSL сертификата
            curl_easy_setopt(curl_handle, CURLOPT_SSL_VERIFYHOST, 0);
 
            CURLcode res = curl_easy_perform(curl_handle);
            if(res != CURLE_OK)
                 std::cout<<"Error #"<<res<<" "<<curl_easy_strerror(res) <<std::endl;
 
             curl_easy_cleanup(curl_handle);
        }
 
    std::cout<<std::endl<<"Done!";
    getchar();
    return 0;
}*/

Разультат запроса будет сохранен в файле body.html, заголовок ответа сервера будет выведен на экран.

 

1. Установка библиотеки.
2. Основные принципы.
3. Простой пример.
4. Заголовки.
5. Обработка ошибок.
6. Загрузка в буфер.
7. Загрузка в файл.
8. Перенаправление (редирект).
9. Cookie
10. Преобразование в URL вид.
11. POST запрос для входа авторизации на сайте vk.com. (контакт)
12. Получение страниц в сжатом виде.
13. Передача с использованием https

[youtube]https://www.youtube.com/watch?v=IZnkiJqZwOs[/youtube]

4 thoughts on “Работа с curl. visual studio 2010.”

  1. Андрей:
    25 февраля, 2015 в 20:51

    А что значит «2. Распаковываем архив и берем оттуда все dll файлы:» берём, а потом куда их скопировать надо?

    Ответить
    1. admin_kselax:
      28 февраля, 2015 в 12:02

      там dll-ки их все что в папке есть нужно скопировать в папку проекта — ту папку где находится исходные файлы, а потом когда создашь программу нужно копировать их в папку где будет находится исполняемый файл.

      Ответить
  2. Avazart:
    29 апреля, 2015 в 19:39

    Контент статьи ворованный:

    http://www.cyberforum.ru/blogs/131347/blog1151.html

    Ответить
    1. admin_kselax:
      5 мая, 2015 в 23:25

      Да ты мне еще на форуме помогал по curl, что то не получалось не помню, потом решил свою статью из твоей переделать, я чуток код поменял 🙂

      Ответить

Добавить комментарий Отменить ответ

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Рубрики

  • C++ (293)
  • JavaScript (1)
  • linux (1)
  • MFC (39)
  • node.js (2)
  • React (3)
  • uncategorized (3)
  • vBulletin (5)
  • Visual Studio (9)
  • wordpress (18)
  • Разное (121)

Метки

Ajax bootstrap CentOS CLI expressjs FormData GDlib google Invisible reCAPTCHA JWT media MFC php react-router-dom redux repository wordpress RTTI STL vBulletin vector Visual Studio WINAPI wordpress wp-plugins XMLHttpRequest Двоичное дерево Задачи С++ Игры С++ Исключения С++ О-большое Операторы_С++ Перегрузка операторов С++ Поиск С++ Потоки Проектирование_С++ С++ Типы_С++ Типы С++ Шаблоны С++ библиотеки локализация макросы С++ сортировка С++

Свежие комментарии

  • Proffirot к записи Программка для заполнения форума на vBulletin 3.8.7
  • RA3PKJ к записи visual C++, создание диалоговых окон.
  • JasonReant к записи Создание и использование статических библиотек .lib в visual studio.
  • MyWin2020 к записи Программка для заполнения форума на vBulletin 3.8.7
  • ScottJip к записи Создание и использование статических библиотек .lib в visual studio.
©2021 Kselax.ru Theme by ThemeGiant