c++ для antigate.com

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by eldar85, 6 Aug 2010.

  1. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    такая проблемка, хотел сделать многопоточную программку для работы с антикапчей, но код который предлогается на офсайте antigate.com полное г...
    функции используются глабольные, переменные все глобальные и получается если прога работает в один поток то еще более менее, но если в несколько то полная лажа.


    вот код имеющегося класса антикапчи

    PHP:
      #include <QtGui>
     #include <c++/iostream>
     #include <c++/string
    #include <curl/curl.h> 
    #include <c++/fstream> 
       
    using namespace std;
      
    string contents;
      
    string ackey;  
     
    size_t handle_data(void *ptr, size_t size, size_t nmemb, void *stream) 
    {     
     
    contents.clear();
         
    int numbytes = size*nmemb;    
     
    char lastchar = *((char *) ptr + numbytes - 1);  
       *((
    char *) ptr + numbytes - 1) = '\0';     contents.append((char *)ptr);     contents.append(1,lastchar);  
       *((
    char *) ptr + numbytes - 1) = lastchar; 
          return 
    size*nmemb; 
     }
     
    bool myCheckIn(string& HTML, int *pos, string str, bool reg)
     { 
      if(
    HTML.size() < *pos + str.size()) return false;  for(unsigned int i = 0; i < str.size(); i++)
      { 
      if(
    str[i] != HTML[i + *pos])
     return 
    false; 
     }
      *
    pos += str.size() - 1;  
     return 
    true;
     }
     
    int strpos(string& haystack, const char * needle)
     {      
      
    string tmp;  
       
    tmp=needle; 
        
    unsigned int hsize = haystack.size(); 
        for (
    unsigned int i=0;i<hsize;i++)  
       {      
       if (
    myCheckIn(haystack, (int *) &i,tmp,true))
     return (
    i-tmp.size()+1);  
       }    
      return -
    1; 
    }
     
    string substr(string& str, int pos, int offset)
     {    
      
    int i; 
        
    string res; 
        for (
    i=pos;i<(pos+offset);i++)  
       {      
       
    res += str[i];   
      }     
     return 
    res; 
    }  
    void file_put_contents(char *name, string res) 
    {    
      
    ofstream fout(name); 
        
    fout << res; 
        
    fout.close(); 
     } 
     class 
    Captcha
     
    {
     public:  
       
    string tempstr;  
        
    QString unfuck(QString captchafile);
       }; 
      
    QString Captcha::unfuck(QString captchafile) 
    {
      
    QString captcha; 
      
    int captcha_id=0;
     
    CURL *hCurl = NULL; CURLcode cc;
     
    QString text;
     
    char error_buffer[1024];
     
    char tmp_char[256];  
      if (!
    hCurl)  
      { 
         
    cc = curl_global_init(CURL_GLOBAL_ALL); 
          
    hCurl = curl_easy_init();  
      }   
      if (
    hCurl)   
     {     
        
    text = "Sending captcha...";   
        
    char *url = "http://antigate.com/in.php"; 
          
    struct curl_httppost *post=NULL;  
       
    struct curl_httppost *last=NULL;     curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, handle_data);  
       
    curl_easy_setopt(hCurl, CURLOPT_URL, url); 
        
    curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, &error_buffer);   
      
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "method",   CURLFORM_COPYCONTENTS, "post", CURLFORM_END); 
        
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "key",   CURLFORM_COPYCONTENTS, ackey.c_str(), CURLFORM_END);   
      
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "file",   CURLFORM_FILE, captchafile.toStdString().c_str(), CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END); 
            
    curl_easy_setopt(hCurl, CURLOPT_HTTPPOST, post); 
           
      
    curl_easy_perform(hCurl);  
           
    curl_formfree(post);
         
    curl_easy_cleanup(hCurl);   
      
    curl_global_cleanup(); 
           
       if (
    strpos(contents,"ERROR")!=-1)
         {     
        
    qDebug() << "ERROR!";   
          return 
    "1"; 
        }        
       
    QString gg = contents.c_str(); 
        
    qDebug() << gg; 
        
    qDebug() << contents.c_str(); 
        
    tempstr=substr(contents,3,10); 
        
    qDebug() << tempstr.c_str();  
       
    captcha_id=atoi(tempstr.c_str());
         if(!
    captcha_id)  
       {       
      
    qDebug() << "captcha not load!!";  
          return 
    "1";  
       }     
      
    contents="";    
         
    sprintf(tmp_char,"http://antigate.com/res.php?key=%s&action=get&id=%d",ackey.c_str(),captcha_id);   
          
      
    qDebug() << "Starting recognize..."; 
         while(
    1)   
      {      
        
    Sleep(2000);   
                
    hCurl = curl_easy_init();   
              
    curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, handle_data);  
               
    curl_easy_setopt(hCurl, CURLOPT_URL, tmp_char);       
          
    curl_easy_setopt(hCurl, CURLOPT_ERRORBUFFER, &error_buffer);
                 
    curl_easy_perform(hCurl);             curl_easy_cleanup(hCurl); 
                
    curl_global_cleanup(); 
                if (
    strpos(contents,"ERROR")!=-1)   
              {       
               return 
    "1";     
            }         
        if (
    strpos(contents,"OK")!=-1)   
              {        
              
                 
    tempstr=substr(contents,3,30);   
                   
    qDebug() << "Recognized captcha: "; 
                     
    qDebug() << tempstr.c_str();     
               
    captcha = tempstr.c_str();  
                    break;        
         }           
       
    contents="";   
       }   
        }
     else   
     {     }  
     return 
    captcha;
     }

    Хотелось бы убрать все эти глобальные функции и переменные, чтобы все было внутри класса, но попробовав сделать эти глобальные функции членнами класса, получается что курл их потом не видит в этой строке

    PHP:
    curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, handle_data);
    я так и не понял как функцию этого же члена класса определить в этой строке, как только не пробывал...
    понимаю что делаю не так, но прям никак недопрет что именно.
    кто нить сталкивался с подобной проблемой? или может большой знаток плюсов, посоветуйте как решить проблему плиз...
     
    #1 eldar85, 6 Aug 2010
    Last edited: 6 Aug 2010
  2. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    Пробовал сделать так, но как раз вот здесь и начинается проблема
     
  3. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    компилятор выдает
    error: invalid use of member (did you forget the '&' ?)

    на эти строки
    curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, handle_data);
     
  4. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    лучше конечно заново написать этот класс, единственное я не пойму какую функцию вот сюда нужно ставить
    curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, ???);
    что именно это строка вообще выполняет???
     
  5. slesh

    slesh Elder - Старейшина

    Joined:
    5 Mar 2007
    Messages:
    2,702
    Likes Received:
    1,224
    Reputations:
    455
    curl_easy_setopt(hCurl, CURLOPT_WRITEFUNCTION, ???);
    этим ты задаешь калбек функцию которая будет каждый раз вызываться при приходе данных с сети.
    Лично я делал всё не на классах а на по обычному, с учетом того что при ините создавал спец структуру по которой мог определять в келбек функции для какого именно коннекта пришлы данные
     
  6. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    удалось переделать)) нужно было эту функцию статично создать))
    вот рабочий вариант, еще немного подправить для красоты кода, но уже все рабочее и единственная глобальная переменная это ключь антикапчи, но он и так для всех потоков одинаков так что тут даже лучше что он глобален))

     
  7. Lee_fx

    Lee_fx Elder - Старейшина

    Joined:
    27 Sep 2008
    Messages:
    90
    Likes Received:
    14
    Reputations:
    0
    std::string нервно покуривает глазея на методы QString'a =)
    Раз программа на Qt, мне кажется использование родных для этой библиотеки классов было бы правильней, да и удобней они)
     
  8. keen6

    keen6 New Member

    Joined:
    7 Apr 2010
    Messages:
    46
    Likes Received:
    4
    Reputations:
    0
    Вот именно. Чем не устраивает QNetworkAccessManager ?
     
  9. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    да уж, чет рано я обрадывался)) совсем забыл что статические члены не прокатят для многопоточки))
    дело просто в тос что я более менее знаю курл, но совсем не знаю как пользоваться QNetworkAccessManager, поэтому и до сих пор вожусь с курлом. и вы думаете QNetworkAccessManager имеет такую же функциональность как курл? мне где то на форуме кто то ляпнул что он далеко не так мощен как курл...
    просто интересно мнение тех кто его уже использовал, на сколько он удобен...
     
  10. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    а использование курла и в правду очень затрудняет жизнь... если QNetworkAccessManager можно использовать так же хорошо как и курл то думаю конечно будет лучше осваивать его)) но опять же хотелось бы услышать совет от людей знающих побольше меня)
     
  11. keen6

    keen6 New Member

    Joined:
    7 Apr 2010
    Messages:
    46
    Likes Received:
    4
    Reputations:
    0
    QNetworkAccessManager думаю имеет все, что умеет curl. Однако его использование куда приятнее. Libcurl хорош тем ,что его можно воткнуть практически в любой язык. Соответственно, интеграция с самим языком (и средой) никакая.
     
  12. greki_hoy

    greki_hoy Member

    Joined:
    4 Mar 2010
    Messages:
    326
    Likes Received:
    57
    Reputations:
    41
    да но только хороший программист заточит Libcurl под свое окружение (напишет пачку врапперов) в любом языке и ему будет удобно а с QNetworkAccessManager где сядеш там и слезеш
     
  13. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    понятно, спасибо за советы, попробую пока поиспользовать оба варианта, QNetworkAccessManager как новшество для себя ну и курл, то к чему привык и посмотрю разницу) хотя в принципе я всегда собираюсь программировать именно на Qt так как мне он очень нравится, все удобно и развивается достаточно хорошо)
    попробую переписать класс для разгадки капчи на QNetworkAccessManager, посмотрю что получится... и самое хорошо что документация для QNetworkAccessManager еаписана на русском на кросплатформе, это уже плюс, потому что хоть я и знаю английский, но все же когда читаю на нем то усваиваю далеко не так как если бы читал на русском))
     
  14. keen6

    keen6 New Member

    Joined:
    7 Apr 2010
    Messages:
    46
    Likes Received:
    4
    Reputations:
    0
    Если писать с Qt, зачем юзать сторонние либы? Когда в нем и так все предусмотрено. Вот я к чему. Мне показалось, либо ты упомянул занятие велопроизводством? =D
     
  15. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    а все же как сделать функцию

    локальной, но не статической, чтобы на нее компилятор не ругался в строке

     
  16. keen6

    keen6 New Member

    Joined:
    7 Apr 2010
    Messages:
    46
    Likes Received:
    4
    Reputations:
    0
    У меня вот так:

    Code:
      static int write_proc(char *, size_t , size_t , std::string*);
     
  17. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,582
    Likes Received:
    1,310
    Reputations:
    1,557
    Файл:
    PHP:
    //---------------------------------------------------------------------------
    struct CaptchaFile
    {
        const 
    char *filename;
        
    FILE *stream;
    };
    //---------------------------------------------------------------------------
    static size_t CaptchaWrite(void *buffer, size_t size, size_t nmemb, void *stream)
    {
        
    struct CaptchaFile *out=(struct CaptchaFile *)stream;
        if(
    out && !out->stream)
        {
            
    out->stream=fopen(out->filename, "wb");
            if(!
    out->stream)
                return -
    1;
        }
        return 
    fwrite(buffer, size, nmemb, out->stream);
    }
    //---------------------------------------------------------------------------
    PHP:
    struct curl_httppost *post=NULL;
    struct curl_httppost *last=NULL;

    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "method",   CURLFORM_COPYCONTENTS, "post", CURLFORM_END);
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "soft_id",   CURLFORM_COPYCONTENTS, "5", CURLFORM_END);
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "key",   CURLFORM_COPYCONTENTS, apikey.c_str(), CURLFORM_END);
    curl_formadd(&post, &last,   CURLFORM_COPYNAME, "file",   CURLFORM_FILE, filename.c_str(), CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);

    curl_easy_setopt(curl, CURLOPT_URL, "http://antigate.com/in.php");
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, post);
    curl_easy_perform(curl);

    Память:
    PHP:
    //---------------------------------------------------------------------------
    static void *cap_realloc(void *ptr, size_t size)
    {
        return 
    ptr ? realloc(ptr, size) : malloc(size);
    }
    //---------------------------------------------------------------------------
    struct CaptchaBuffer
    {
        
    char* memory;
        
    size_t size;
    };
    //---------------------------------------------------------------------------
    static size_t CaptchaWrite(void *data, size_t size, size_t nmemb, void *buffer)
    {
        
    size_t realsize = size * nmemb;
        
    struct CaptchaBuffer *mem = (struct CaptchaBuffer *)buffer;
        
    mem->memory = (char*)cap_realloc(mem->memory, mem->size + realsize + 1);
        if(
    mem->memory)
        {
            
    memcpy(&(mem->memory[mem->size]), data, realsize);
            
    mem->size += realsize;
            
    mem->memory[mem->size] = 0;
        }
        return 
    realsize;
    }
    //---------------------------------------------------------------------------
    PHP:
    String VK::AntigateCheckCaptcha()
    {
        
    setopt(curl, CURLOPT_HEADER , 0);
        
    setopt(curl, CURLOPT_PROXY , "");
        
    setopt(curl, CURLOPT_PROXYTYPE , HTTP);

        
    struct curl_httppost *post = NULL;
        
    struct curl_httppost *last = NULL;
        
    formadd(&post, &last,   CURLFORM_COPYNAME, "method",   CURLFORM_COPYCONTENTS, "post", CURLFORM_END);
        
    formadd(&post, &last,   CURLFORM_COPYNAME, "soft_id",   CURLFORM_COPYCONTENTS, "5", CURLFORM_END);
        
    formadd(&post, &last,   CURLFORM_COPYNAME, "key",   CURLFORM_COPYCONTENTS, sAntigateKey, CURLFORM_END);
        
    formadd(&post, &last,   CURLFORM_COPYNAME, "file",    CURLFORM_BUFFER, "captcha.jpg", 
                                
    CURLFORM_BUFFERPTR, bufCaptcha.memory, CURLFORM_BUFFERLENGTH, bufCaptcha.size,  
                                
    CURLFORM_CONTENTTYPE, "image/jpeg", CURLFORM_END);

                        
        
    String sId = "";
        
        
    sUrl = "http://antigate.com/in.php";
        
    sPage = "";
        
    setopt(curl, CURLOPT_URL, sUrl);
        
    setopt(curl, CURLOPT_HTTPPOST, post);
        
    perform(curl);
        
    setopt(curl, CURLOPT_POST, 0);
        
    formfree(post);

        if(
    sPage.Pos("\r"))
            
    sPage.SetLength(sPage.Pos("\r") - 1);
                
        if(
    sPage.IsEmpty())
            return 
    "ERROR_REPLY_IN";
        else if(
    sPage.Pos("ERROR_"))
            return 
    sPage;
        else if(
    sPage.Pos("OK"))
            
    sId = sPage.SubString(sPage.Pos("|") + 1, sPage.Length() - sPage.Pos("|"));

        if(
    sId.IsEmpty())
            return 
    "ERROR_BAD_CAPTCHA_ID";
            
        for(
    int i = 0; i < 12; ++i)
        {
            
    Sleep(5000);

            
    sUrl =     "http://antigate.com/res.php?key=" +
                    
    sAntigateKey +
                    
    "&action=get&id=" +
                    
    sId;
            
    sPage = "";
            
    setopt(curl, CURLOPT_URL, sUrl);
            
    perform(curl);

            if(
    sPage.Pos("\r"))
                
    sPage.SetLength(sPage.Pos("\r") - 1);
                
            if(
    sPage.IsEmpty())
                return 
    "ERROR_REPLY_GET";
            else if(
    sPage.Pos("ERROR_"))
                return 
    sPage;
            else if(
    sPage.Pos("OK"))
            {
                
    sPage.Delete(1, sPage.Pos("|"));
                return 
    sPage;
            }
        }
        
        return 
    "ERROR_TIMEOUT";
    }
     
  18. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    спасибо большое. пробую сделать класс для работы на QNetworkAccessManager но нифига не пойму одного, вот сделал такой код:

    net.h

    net.cpp

    и вот вызов

     
  19. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    по идее exec() должен вернуть buffer с данными, он он гад ничего не возращает, причем в слоте
    загрузка производится, но exec() завершается до того как произойдет вывод reply в buffer. В чем же проблема???
     
  20. eldar85

    eldar85 New Member

    Joined:
    27 Aug 2009
    Messages:
    126
    Likes Received:
    1
    Reputations:
    0
    хотел спросить у M_script, ты такой код в многопоточных программах используешь? мне просто интересно у тебя капча в один и тот же файл сохраняется, а как быть если к примеру 10 потоков обратятся к разгадке капчи, получается они перезапишут файл captcha.jpg и разгадка будет неверной или я ошибаюсь?