1

hello :- )

bon, je commence à pas mal utiliser curl, et je viens de me faire un petit bout de code pour simplifier son utilisation
en espérant que ça puisse aider qq..

deux fichiers :
mycurl.h#include "../StdAfx.h" #include <stdio.h> #include <stdlib.h> #include "../curl/curl.h" #include "../curl/types.h" #include "../curl/easy.h" //#include "../console.h" #include "../log.h" struct MemoryStruct { char *memory; size_t size; }; size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data); class cURL {      //private:      public:      CURL *handle;      struct MemoryStruct *page;      char lastUrl[2048];      char findStr[1024];       cURL(void);      ~cURL(void);      void init(void);      void  logTo(const char*path);      const char * download(char*path,char*post=0);      char * find(char*start,char*end,char*out=0);      char * pfind(char*buffer,char*start,char*end,char*out); }; int curlShareInit(void); void curlStart(void); void curlEnd(void);

mycurl.cpp#include "StdAfx.h" #include "mycurl.h" int iscookiesblocked = 0; int isdnsblocked = 0; int isdatablocked = 0; CURLSH * curl_share_handle = 0; size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb;   struct MemoryStruct *mem = (struct MemoryStruct *)data;   mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);   if (mem->memory) {     memcpy(&(mem->memory[mem->size]), ptr, realsize);     mem->size += realsize;     mem->memory[mem->size] = 0;   }   return realsize; } /* lock callback */ void lock(CURL *handle, curl_lock_data data, curl_lock_access access,           void *useptr ) {   const char *what;   switch ( data ) {     case CURL_LOCK_DATA_SHARE:       what = "share ";        if(isdatablocked) while(isdatablocked) Sleep(1);        isdatablocked=1;       break;     case CURL_LOCK_DATA_DNS:       what = "dns   ";        if(isdnsblocked) while(isdnsblocked) Sleep(1);        isdnsblocked=1;       break;     case CURL_LOCK_DATA_COOKIE:       what = "cookie";        if(iscookiesblocked) while(iscookiesblocked) Sleep(1);        iscookiesblocked=1;       break;     default:       fprintf(stderr, "lock: no such data: %d\n",data);        system("pause");       return;   }   //printf("lock:   %s  <%s>\n", what, (char *)useptr);  } /* unlock callback */ void unlock(CURL *handle, curl_lock_data data, void *useptr ) {   const char *what;   switch ( data ) {     case CURL_LOCK_DATA_SHARE:       what = "share ";        if(!isdatablocked) while(!isdatablocked) Sleep(1);        isdatablocked=0;       break;     case CURL_LOCK_DATA_DNS:       what = "dns   ";        if(!isdnsblocked) while(!isdnsblocked) Sleep(1);           isdnsblocked=0;       break;     case CURL_LOCK_DATA_COOKIE:       what = "cookie";         if(!iscookiesblocked) while(!iscookiesblocked) Sleep(1);           iscookiesblocked=0;       break;     default:       fprintf(stderr, "unlock: no such data: %d\n",data);        system("pause");       return;   }   //printf("unlock: %s  <%s>\n", what, (char *)useptr);  } //log_file winlog("winlog.txt"); char *Utf8ToAnsi(const char * utf8, int len) {     char *utf8str = NULL;      int length = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, NULL );      WCHAR *lpszW = NULL;      lpszW = new WCHAR[length+1];      MultiByteToWideChar(CP_UTF8, 0, utf8, -1, lpszW, length );      int length1 = WideCharToMultiByte(CP_ACP, 0, lpszW, length, NULL, 0, NULL, NULL);      utf8str = ( char * ) calloc ( sizeof(char), length1+1 );      WideCharToMultiByte(CP_ACP, 0, lpszW, length, utf8str, length1, NULL, NULL);      utf8str[length1] = 0;      delete[] lpszW;      return utf8str; } cURL::cURL(void) {     page = (struct MemoryStruct *)malloc(sizeof(struct MemoryStruct));      page->memory = 0; page->size = 0;      *lastUrl = *findStr = 0; } void cURL::init(void) {     handle = curl_easy_init();      curl_easy_setopt(handle, CURLOPT_HEADER, 1);      curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);      curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);      curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0);      curl_easy_setopt(handle, CURLOPT_COOKIEJAR, "cookies");      curl_easy_setopt(handle, CURLOPT_COOKIEFILE, "cookies");      curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");      curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);      if(curl_share_handle)           curl_easy_setopt(handle, CURLOPT_SHARE, curl_share_handle); } void cURL::logTo(const char * path) {     log_file log(path);      log.mem2log(page->memory,page->size); } cURL::~cURL(void) {     curl_easy_cleanup(handle);      if(page) free(page); } const char *cURL::download(char*path,char*post) {     if(!handle || !page) return "error";      if(page->memory) free(page->memory);      page->memory = 0; page->size = 0;      if(post) curl_easy_setopt(handle, CURLOPT_POSTFIELDS,post);      curl_easy_setopt(handle, CURLOPT_POST, (post!=0));      curl_easy_setopt(handle, CURLOPT_REFERER, lastUrl); strcpy(lastUrl,path);      curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void*)page);      curl_easy_setopt(handle, CURLOPT_URL, path);      CURLcode returnValue = curl_easy_perform(handle);            if(page->size)           if(strstr(page->memory,"UTF-8"))           {     char * str = Utf8ToAnsi(page->memory,page->size);                CharToOem(str,str);                free(page->memory);                page->memory = str;                page->size   = strlen(page->memory);           }      if(returnValue) return curl_easy_strerror(returnValue);      return 0; } char * cURL::pfind(char*buffer,char*start, char*end, char*out=0) {     if(!buffer || !start || !end) return 0;      int startSize = strlen(start);      char * startptr = strstr(buffer,start);      if(!startptr) return 0;      char * endptr   = strstr(startptr+startSize,end);      if(!endptr)   return 0;      int valueSize = endptr - (startptr+startSize);      if(valueSize > 1023) return 0;      //static char internalbuffer[10240];      if(!out) out = findStr;      memcpy(out,&startptr[startSize],valueSize);      out[valueSize] = 0;      if(out != findStr) return &endptr[strlen(end)];      return out; } char * cURL::find(char*start, char*end, char*out) {     if(!page->size || !page->memory || !start || !end) return 0;      return pfind(page->memory,start,end,out); } int curlShareInit(void) {     CURLSHcode scode;      curl_share_handle = curl_share_init();      scode = curl_share_setopt(curl_share_handle,CURLSHOPT_SHARE,CURL_LOCK_DATA_COOKIE);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle,CURLSHOPT_SHARE,CURL_LOCK_DATA_DNS);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_LOCKFUNC,   lock);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_UNLOCKFUNC, unlock);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_USERDATA,   "muhuhuhahahaha!");      if ( CURLSHE_OK != scode ) return 0;      return 1; } void curlStart(void) {     curl_global_init(CURL_GLOBAL_ALL); } void curlEnd(void) {     if(curl_share_handle)           curl_share_cleanup(curl_share_handle);      curl_global_cleanup(); }
       } else Sleep(30000);      };   } }; qq lignes montrant comment initialiser tout ca #include "mycurl/mycurl.h" // on utilisera curl via 3 objets cURL auction; // un pour recuperer le temps restant dans les encheres cURL arene; // un pour le combat dans les arenes cURL player; // pour le log et recup des info des joueurs int main(void) {     curlStart(); // init générale de curl      curlShareInit(); // nous voulons partager les cookies entre objets      // init des objets      player.init();      arene.init();      auction.init();      // et voila, rien d'autre à faire tout est initialisé      // à partir de la tout votre blabla pour dl des truc      logToGame();      auctionTimer auctionThread;      auctionThread.StartAndWait();      while(1)      {     unsigned int SleepTime = arenaFight();           if(!SleepTime)     logToGame();           else  {     int m = SleepTime/60;                     int s = SleepTime - (m*60);                     shell.printc(JAUNE,"\nnow waiting %im %is",m,s);                     for(int n=0;n<m;n++)                     {     shell.printc(JAUNE,".");                          Sleep(60500);                     };                     shell.printc(VERT,".");                     Sleep(s*1000);                     printf("\n");                }      };      auctionThread.Terminate();      // fonction de fermeture de curl      curlEnd();      return 0; } // exemple du thread pour le temps restant dans l'enchere class auctionTimer:public CThread { public:   void OnRunning()   {     char url[1024];      char lastTime[1024];      char *timeStr;      int isveryshort=0;      *url = *lastTime = 0;      //Sleep(5000);     //shell.printc(JAUNE,"\nan hello from auction timer thread !\n");      while(1)      {                sprintf(url,"%sindex.php?mod=auction&sh=%s",server,shkey);           const char * rtn = auction.download(url);           if(rtn)           {     shell.printc(ROUGE,"! error !");                //logToGame();           }           //system("pause");           auction.logTo("auction.html");           timeStr = auction.find("description_span_right\"><b>","</b></span>");           if(timeStr)           {     if(!strcmp("very short",timeStr))                {     if(!isveryshort) isveryshort=30;                     shell.printc(ROUGE,"\n ** time left for auction less than %im!\n\a",isveryshort);                } else     { isveryshort=0;                                                              if(strcmp(lastTime,timeStr))                               {     strcpy(lastTime,timeStr);                                    shell.printc(ROUGE,"\n ** new timestamp for auction : %s\n\a",timeStr);                               }                          }           } else shell.printc(ROUGE,"auction : is logged ?");                      //system("pause");           if(isveryshort)           {     if(isveryshort > 5)                {     Sleep(300000); isveryshort-=5;                }     else { Sleep(60000); isveryshort--; }    
et la le mec il le pécho par le bras et il lui dit '

2

du C/C++ pour interfacer de la ligne de commande, c'est pas commun ça Ô_Ô
avatar
Il n'a pas de mots
Décrire son mépris
Perdre les rênes
Il a perdu la foi

3

j'aurais plutôt du dire libcurl, je n'utilise pas l'exe

ça fait ce qu'il faut pour initialiser la lib avec son mode 'sharing' ou l'on peu télécharger de plusieurs thread en partageant les cookies

bref ici je m'en sert pour me loger à un jeux, utiliser un thread qui vérifie les enchères, un pour combattre, et d'autre plus tard pour les quêtes et donjons

cette petite classe contient aussi du code pour extraire du texte inclus entre deux balises (style les caractéristiques des autres joueurs)

bref un petit couteau suisse pour me coder un bot ^^
et la le mec il le pécho par le bras et il lui dit '

4

kim (./2) :
du C/C++ pour interfacer de la ligne de commande, c'est pas commun ça Ô_Ô


yep, en asm c'est mieux love
parsing
	|==================================================================
	|	1. Check number of args
	|==================================================================
	move.w	ARGC(%fp),%d4				|number of args, including program name
	subq.w	#1,%d4					|at least 1 arg after program name ?
	bne.s	EnoughArgs				|yes
InvalidCall:
		pea.l	StrInvalidCall(%pc)
		bra	QuitError
EnoughArgs:
	moveq.l	#1,%d3					|first arg

	|==================================================================
	|	2. Check for global options
	|==================================================================
	move.l	PUBLIC_FLAGS(%fp),%d5			|get compilation flag
CheckGlobalOptions:
	movea.l	ARGV(%fp),%a0				|&arg list
	move.w	%d3,%d0					|# current arg
	lsl.w	#2,%d0					|table of longwords
	movea.l	0(%a0,%d0.w),%a0			|&current arg
	bsr	CheckArgType				|get its type
	bne.s	EndOfGlobalOptions			|if it's not an option, stop global options registration
		bsr	RegisterOption			|perform stuff for this option
		addq.w	#1,%d3				|update # current arg
		cmp.w	%d3,%d4				|over last ?
		bcs	EndOfParsing			|yes, but perhaps there is just a command and nothing to assemble
			bra.s	CheckGlobalOptions	|else loop to parse the option
EndOfGlobalOptions:
	move.l	%d5,PUBLIC_FLAGS(%fp)			|Register global options


	|==================================================================
	|	3. Check if there is a binary/archive/raw file to create
	|==================================================================
	btst.l	#BIT_PROGRAM,%d5			|program to create ?
	bne.s	GlobalOutput				|yes, update args counter
	btst.l	#BIT_ARCHIVE,%d5			|archive to create ?
	bne.s	GlobalOutput				|yes, update args counter
	btst.l	#BIT_RAW,%d5				|raw file to create ?
	beq.s	NoGlobalOutput
GlobalOutput:
		subq.w	#1,%d4				|update d4 (last arg is the binary/archive name)
		cmp.w	%d3,%d4				|d4 < d3 ?
		bcs.s	InvalidCall			|If yes, there is a global output to create, but no source file in arg list !
NoGlobalOutput:
	suba.l	%a3,%a3					|no current source opened

	|==================================================================
	|	4. Register source files and their options
	|==================================================================
CmdLineLoop:
	movea.l	ARGV(%fp),%a0				|&arg list
	move.w	%d3,%d0					|# current arg
	lsl.w	#2,%d0					|table of longwords
	movea.l	0(%a0,%d0.w),%a0			|&current arg
	movea.l	%a0,%a2					|save &filename/&option
	bsr	CheckArgType				|get its type
	bne.s	CheckSource

	|==================================================================
	|	a. Register an option and add it immediately in the source table
	|==================================================================
	bsr	RegisterOption
	bclr.l	#BIT_PROGRAM,%d5			|clean impossible flags for a source file
	bclr.l	#BIT_RAW,%d5
	bclr.l	#BIT_ARCHIVE,%d5
	move.l	%d5,SOURCE.Flags(%a3)			|and then register flag
	bra.s	UpdateArgCounter

	|==================================================================
	|	b. Check for a valid source file and open it if possible
	|==================================================================
CheckSource:
	movea.l	%a2,%a0					|get &filename
	moveq.l	#NO_CHECK_INCLUDE,%d0			|don't check in /include/
	bsr	FileFind				|check if the file exists
	tst.w	%d0					|success ?
	bne.s	FileFound				|yes, continue
		pea.l	(%a2)				|&filename
		pea.l	StrFileNotFound(%pc)		|error string
		bra	QuitError			|and quit
FileFound:
	movea.l	%a2,%a0					|&filename
	moveq.l	#FILE_OBJECT+FILE_SOURCE+FILE_ARCHIVE,%d0
	bsr	FileCheckType				|check its type
	tst.w	%d0					|success ?
	bne.s	FileTypeOk				|yes, continue
		pea.l	(%a2)				|&filename
		pea.l	StrWrongFileType(%pc)		|error string
		bra	QuitError			|and quit
FileTypeOk:
	movea.l	%a2,%a0					|&filename
	bsr	FileOpen
	movea.l	%a0,%a3					|&entry
	bclr.l	#BIT_PROGRAM,%d5			|clean impossible flags for a source file
	bclr.l	#BIT_RAW,%d5
	bclr.l	#BIT_ARCHIVE,%d5
	move.l	%d5,SOURCE.Flags(%a3)

5

Si je peux me permettre quelques remarques :

- Dommage de laisser apparaître dans ta lib la contrainte d'initialisation de cURL, ça aurait été plus élégant de la rendre transparente (automatique via un constructeur de ta classe "cURL" par exemple)
- Même remarque pour la désinitialisation, d'autant plus qu'il y a un risque d'oublier et de leaker, ça gagnerait à être automatisé dans un destructeur
- La méthode "init" ne fait pas très C++, pourquoi ne pas avoir mis ce code dans le constructeur de la classe ?
- De même, les fonctions internes utilisées pour le fonctionnement de ta classe (lock, unlock) pourraient devenir des méthodes statiques privées
- Il n'y a aucune méthode qui permette de passer des variables en POST dans la requête ? (la méthode "download" fait beaucoup de choses à la fois)
- Et plein de petits détails genre des "const" qui pourraient apparaître aux endroits judicieux, etc ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

6

oui c'est codé à l'arash tongue

pour l'init et desinit de curl, je vais mettre en place un compteur d'objet crée ds le constructeur et destructeur, première instantation, on init dernière destruction on desinit

la fonction init est nécessaire, pour initialiser les objet après avoir utilisé ou non curlShareInit qui dit que l'on souhaite utiliser les même cookies dans tous les objets
bref je ne peu pas le mettre dans le constructeur, à moins que je mette un argument dans le constructeur spécifiant si l'on utilise ou non le 'share' de cookies (je vais faire ça en fait)

pour les méthodes statique privé, je vais voir ça

pour le post, pourquoi pas, ça virerais pas mal de sprintf de la couche supérieure
je vais faire la même chose pour le get aussi

et inclure la gestion de l'adresse 'mère' pourquoi pas (car la aussi 12000 sprintf :/)
et des valeur de post ou get utilisées à chaque requête pourrais être sympa (tjs pour la même raison)

pour les const ect oui, mais cela depend des endroits car des méthodes autant retourne une chaine const dans certain cas, autant dans d'autre elles retournes un pointeur
et la le mec il le pécho par le bras et il lui dit '

7

nouvelle version, plus de fonction et variables globales,
des méthode à la printf pour dl en post ou en get,
plus d'init à faire, la déclaration des objets suffit

mycurl.h#include "../StdAfx.h" #include <stdio.h> #include <stdlib.h> #include "../curl/curl.h" #include "../curl/types.h" #include "../curl/easy.h" #include "../log.h" struct MemoryStruct { char *memory; size_t size; }; class cURL {      public:      struct MemoryStruct *page;      cURL(int shareCookies=1);      ~cURL(void);      void  logTo(const char*path);      const char * download(char*path,char*post=0);      const char * postDl(char * path, const char * format, ...); // post sprintf      const char * urlDl(const char * format, ...); // url sprintf      char * find(char*start,char*end,char*out=0);      char * pfind(char*buffer,char*start,char*end,char*out=0); private:      static CURLSH * curl_share_handle;      static int objectCounter;      CURL *handle;      char lastUrl[2048];      char findStr[2048];      static char *Utf8ToAnsi(const char * utf8, int len);      static size_t WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data);      static void lockUnlock(curl_lock_data data,int lock);      static void lock(CURL *handle, curl_lock_data data, curl_lock_access access,void *useptr) { lockUnlock(data,1); };      static void unlock(CURL *handle, curl_lock_data data, void *useptr) { lockUnlock(data,0); };      static int curlShareInit(void); };
mycurl.cpp#include "StdAfx.h" #include "mycurl.h" CURLSH * cURL::curl_share_handle = 0; int cURL::objectCounter = 0; size_t cURL::WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { size_t realsize = size * nmemb;   struct MemoryStruct *mem = (struct MemoryStruct *)data;   mem->memory = (char *)realloc(mem->memory, mem->size + realsize + 1);   if(mem->memory)   { memcpy(&(mem->memory[mem->size]), ptr, realsize);     mem->size += realsize; mem->memory[mem->size] = 0;   }   return realsize; } void cURL::lockUnlock(curl_lock_data data,int lock) {     static int iscookiesblocked = 0;      static int isdnsblocked = 0;      static int isdatablocked = 0;   switch(data) {     case CURL_LOCK_DATA_SHARE:        if(isdatablocked == lock)             while(isdatablocked == lock) Sleep(1);        isdatablocked=lock;     break;     case CURL_LOCK_DATA_DNS:        if(isdnsblocked == lock)             while(isdnsblocked == lock) Sleep(1);        isdnsblocked=lock;     break;     case CURL_LOCK_DATA_COOKIE:        if(iscookiesblocked == lock)             while(iscookiesblocked == lock) Sleep(1);        iscookiesblocked=lock;     break;   }; } char *cURL::Utf8ToAnsi(const char * utf8, int len) {     char *utf8str = NULL;      int length = MultiByteToWideChar(CP_UTF8, 0, utf8, len, NULL, NULL );      WCHAR *lpszW = NULL;      lpszW = new WCHAR[length+1];      MultiByteToWideChar(CP_UTF8, 0, utf8, -1, lpszW, length );      int length1 = WideCharToMultiByte(CP_ACP, 0, lpszW, length, NULL, 0, NULL, NULL);      utf8str = ( char * ) calloc ( sizeof(char), length1+1 );      WideCharToMultiByte(CP_ACP, 0, lpszW, length, utf8str, length1, NULL, NULL);      utf8str[length1] = 0;      delete[] lpszW;      return utf8str; } cURL::cURL(int shareCookies) {     page = (struct MemoryStruct *)malloc(sizeof(struct MemoryStruct));      page->memory = 0; page->size = 0;      *lastUrl = *findStr = 0;      if(!objectCounter++) curl_global_init(CURL_GLOBAL_ALL);      handle = curl_easy_init();      curl_easy_setopt(handle, CURLOPT_HEADER, 1);      curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);      curl_easy_setopt(handle, CURLOPT_SSL_VERIFYPEER, 0);      curl_easy_setopt(handle, CURLOPT_SSL_VERIFYHOST, 0);      curl_easy_setopt(handle, CURLOPT_COOKIEJAR, "cookies");      curl_easy_setopt(handle, CURLOPT_COOKIEFILE, "cookies");      curl_easy_setopt(handle, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.0.3) Gecko/2008092417 Firefox/3.0.3");      curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);      if(shareCookies)      {     if(!curl_share_handle) curlShareInit();           if(curl_share_handle)                curl_easy_setopt(handle, CURLOPT_SHARE, curl_share_handle);      } } void cURL::logTo(const char * path) {     log_file log(path);      log.mem2log(page->memory,page->size); } cURL::~cURL(void) {     curl_easy_cleanup(handle);      if(page) free(page);      if(!--objectCounter)      {     if(curl_share_handle)                curl_share_cleanup(curl_share_handle);           curl_global_cleanup();      } } const char *cURL::download(char*path,char*post) {     if(!handle || !page) return "error";      if(page->memory) free(page->memory);      page->memory = 0; page->size = 0;      if(post) curl_easy_setopt(handle, CURLOPT_POSTFIELDS,post);      curl_easy_setopt(handle, CURLOPT_POST, (post!=0));      curl_easy_setopt(handle, CURLOPT_REFERER, lastUrl); strcpy(lastUrl,path);      curl_easy_setopt(handle, CURLOPT_WRITEDATA, (void*)page);      curl_easy_setopt(handle, CURLOPT_URL, path);      CURLcode returnValue = curl_easy_perform(handle);            if(page->size)           if(strstr(page->memory,"UTF-8"))           {     char * str = Utf8ToAnsi(page->memory,page->size);                CharToOem(str,str);                free(page->memory);                page->memory = str;                page->size   = strlen(page->memory);           }      if(returnValue) return curl_easy_strerror(returnValue);      return 0; } const char *cURL::postDl(char * path, const char * format, ...) {     va_list va;      va_start(va, format);      char post[4096];      wvsprintf(post,format,va);     return download(path,post); } const char *cURL::urlDl(const char * format, ...) {     va_list va;      va_start(va, format);      char url[4096];      wvsprintf(url,format,va);     return download(url,0); } char * cURL::pfind(char*buffer,char*start, char*end, char*out) {     if(!buffer || !start || !end) return 0;      int startSize = strlen(start);      char * startptr = strstr(buffer,start);      if(!startptr) return 0;      char * endptr   = strstr(startptr+startSize,end);      if(!endptr)   return 0;      int valueSize = endptr - (startptr+startSize);      if(valueSize > 2047) return 0;      //static char internalbuffer[10240];      if(!out) out = findStr;      memcpy(out,&startptr[startSize],valueSize);      out[valueSize] = 0;      if(out != findStr) return &endptr[strlen(end)];      return out; } char * cURL::find(char*start, char*end, char*out) {     if(!page->size || !page->memory || !start || !end) return 0;      return pfind(page->memory,start,end,out); } int cURL::curlShareInit(void) {     CURLSHcode scode;      curl_share_handle = curl_share_init();      scode = curl_share_setopt(curl_share_handle,CURLSHOPT_SHARE,CURL_LOCK_DATA_COOKIE);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle,CURLSHOPT_SHARE,CURL_LOCK_DATA_DNS);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_LOCKFUNC,   lock);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_UNLOCKFUNC, unlock);      if ( CURLSHE_OK != scode ) return 0;      scode = curl_share_setopt(curl_share_handle, CURLSHOPT_USERDATA,   "muhuhuhahahaha!");      if ( CURLSHE_OK != scode ) return 0;      return 1; }
et la le mec il le pécho par le bras et il lui dit '