⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ccurl.c

📁 Gambas is a graphical development environment based on a Basic interpreter, like Visual Basic. It us
💻 C
字号:
/***************************************************************************  CCurl.c  Advanced Network component  (c) 2003-2004 Daniel Campos Fernández <danielcampos@netcourrier.com>  This program is free software; you can redistribute it and/or modify  it under the terms of the GNU General Public License as published by  the Free Software Foundation; either version 1, or (at your option)  any later version.  This program is distributed in the hope that it will be useful,  but WITHOUT ANY WARRANTY; without even the implied warranty of  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  GNU General Public License for more details.  You should have received a copy of the GNU General Public License  along with this program; if not, write to the Free Software  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.***************************************************************************/#define __CCURL_C#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <curl/curl.h>#include <curl/easy.h>#include <curl/multi.h>#include "main.h"#include "gambas.h"#include "CCurl.h"#include "CProxy.h"DECLARE_EVENT (CURL_FINISHED);DECLARE_EVENT (CURL_ERROR);DECLARE_EVENT (CURL_CONNECT);DECLARE_EVENT (CURL_READ);/***************************************************** CURLM : a pointer to use curl_multi interface, allowing asynchrnous work without using threads in this class. ******************************************************/CURLM *CCURL_multicurl;int CCURL_pipe[]={-1,-1};/****************************************************** Events from this class ******************************************************/GB_STREAM_DESC CurlStream = {	CCURL_stream_open,	CCURL_stream_close,	CCURL_stream_read,	CCURL_stream_write,	CCURL_stream_seek,	CCURL_stream_tell,	CCURL_stream_flush,	CCURL_stream_eof,	CCURL_stream_lof};//////////////////////////////////////////////////////////////////////	STREAM							  ///////////////////////////////////////////////////////////////////////* not allowed stream methods */int CCURL_stream_open(GB_STREAM *stream, const char *path, int mode, void *data){return -1;}int CCURL_stream_seek(GB_STREAM *stream, long pos, int whence){	return -1;}int CCURL_stream_tell(GB_STREAM *stream, long *pos){return -1; }int CCURL_stream_flush(GB_STREAM *stream) {	return 0;}int CCURL_stream_close(GB_STREAM *stream) { return -1;}int CCURL_stream_write(GB_STREAM *stream, char *buffer, long len){return -1;}int CCURL_stream_lof(GB_STREAM *stream, long *len){	void *_object;		curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object);	*len=0;	if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1;	*len=THIS->len_data;	return 0;}int CCURL_stream_eof(GB_STREAM *stream){	void *_object;		curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object);		if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1;	if (!THIS->len_data) return -1;	return 0;}int CCURL_stream_read(GB_STREAM *stream, char *buffer, long len){	void *_object;		curl_easy_getinfo(stream->_free[1],CURLINFO_PRIVATE,(char**)&_object);		if ((THIS_STATUS !=4 ) && (THIS_STATUS != 0)) return -1;	if (THIS->len_data < len) return -1;	memcpy(buffer,THIS->buf_data,len);	if (THIS->len_data == len)	{		THIS->len_data=0;		GB.Free((void**)&THIS->buf_data);		return 0;	}	THIS->len_data-=len;	memmove(THIS->buf_data,len+THIS->buf_data,THIS->len_data);	GB.Realloc((void**)&THIS->buf_data,THIS->len_data);	return 0;}/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*******************************************************************####################################################################	POSTED FUNCTIONS TO RAISE EVENTS####################################################################********************************************************************/void CCURL_raise_finished(long lParam){	void *mythis;	mythis=(void*)lParam;	GB.Raise(mythis,CURL_FINISHED,0);	GB.Unref(&mythis);}void CCURL_raise_error(long lParam){	void *mythis;	mythis=(void*)lParam;	GB.Raise(mythis,CURL_ERROR,0);	GB.Unref(&mythis);}void CCURL_raise_connect(long lParam){	void *mythis;	mythis=(void*)lParam;	GB.Raise(mythis,CURL_CONNECT,0);	GB.Unref(&mythis);}void CCURL_raise_read(long lParam){	void *mythis;	mythis=(void*)lParam;	GB.Raise(mythis,CURL_READ,0);	GB.Unref(&mythis);}void CCURL_Manage_ErrCode(void *_object,long ErrCode){	if (THIS_FILE)	{		fclose(THIS_FILE);		THIS_FILE=NULL;	}			switch ( ErrCode )	{		case CURLE_OK:			curl_multi_remove_handle(CCURL_multicurl,THIS_CURL);			THIS_STATUS=0;			GB.Ref(THIS);			GB.Post(CCURL_raise_finished,(long)THIS);			break;        	default:			curl_multi_remove_handle(CCURL_multicurl,THIS_CURL);			THIS_STATUS=-1*(1000+ErrCode);			GB.Ref(THIS);			GB.Post(CCURL_raise_error,(long)THIS);			break;	}}/*************************************************************** This CallBack is called each event loop by Gambas to test the status of curl descriptors ***************************************************************/void CCURL_stop(void *_object){	if (THIS_FILE)	{		fclose(THIS_FILE);		THIS_FILE=NULL;	}		if (THIS_CURL)	{		curl_multi_remove_handle(CCURL_multicurl,THIS_CURL);		curl_easy_cleanup(THIS_CURL);		THIS_CURL=NULL;	}	THIS_STATUS=0;}void CCURL_init_post(void){	if (CCURL_pipe[0]!=-1) return;		pipe(CCURL_pipe);		GB.Watch (CCURL_pipe[0] ,GB_WATCH_READ,CCURL_post_curl,0);	write(CCURL_pipe[1],"1",sizeof(char));}void CCURL_post_curl(long data){	CURLMsg *Msg;	int nread;	int post=1;	void *_object;	struct timespec mywait;	do	{		mywait.tv_sec=0;		mywait.tv_nsec=1000000;		nanosleep(&mywait,NULL);		}	while(CURLM_CALL_MULTI_PERFORM == curl_multi_perform(CCURL_multicurl,&nread));		if (!nread) post=0;	do	{		Msg=curl_multi_info_read(CCURL_multicurl,&nread);		if (!Msg) nread=0;		if (Msg)		{			curl_easy_getinfo(Msg->easy_handle,CURLINFO_PRIVATE,(char**)&_object);			CCURL_Manage_ErrCode(THIS,Msg->data.result);		}	} 	while (nread);	if (!post)	{		GB.Watch (CCURL_pipe[0] ,GB_WATCH_NONE,CCURL_post_curl,0);		close(CCURL_pipe[0]);		close(CCURL_pipe[1]);		CCURL_pipe[0]=-1;	}		}//////////////////////////////////////////////////////////////////////////###################### PROXY related properties ######################/////////////////////////////////////////////////////////////////////////********************************************* Proxy name and port ( Host:Port format) *********************************************/BEGIN_PROPERTY (CCURL_Proxy)	GB.ReturnObject(THIS->proxy);END_PROPERTY//////////////////////////////////////////////////////////////////////////########################## Other properties ##########################/////////////////////////////////////////////////////////////////////////********************************************* FTP User ( User:Password format ) *********************************************/BEGIN_PROPERTY ( CCURL_sUser )	if (READ_PROPERTY)	{		GB.ReturnString(THIS->user.user);		return;	}	if (THIS_STATUS > 0)	{		GB.Error ("User property can not be changed while working");		return;  	}		if ( THIS->user.user ) GB.FreeString ( &(THIS->user.user) );	GB.StoreString(PROP(GB_STRING), &(THIS->user.user) );	END_PROPERTYBEGIN_PROPERTY ( CCURL_Password )	if (READ_PROPERTY)	{		GB.ReturnString(THIS->user.pwd);		return;	}	if (THIS_STATUS > 0)	{		GB.Error ("User property can not be changed while working");		return;  	}		if ( THIS->user.pwd ) GB.FreeString ( &(THIS->user.pwd) );	GB.StoreString(PROP(GB_STRING), &(THIS->user.pwd) );	END_PROPERTY/********************************************* Status : inactive, working or Error code *********************************************/BEGIN_PROPERTY ( CCURL_Status )	GB.ReturnInteger(THIS_STATUS);END_PROPERTY/***************************************************************** URL to work with *****************************************************************/BEGIN_PROPERTY ( CCURL_URL )	char *tmp=NULL;		if (READ_PROPERTY)	{		GB.ReturnNewString(THIS_URL,0);		return;	}	if (THIS_STATUS > 0)	{		GB.Error ("URL property can not be changed while working");		return;  	}	if (THIS_URL)	{		tmp=THIS_URL;		GB.Free((void**)&tmp);	}	GB.Alloc((void**)&tmp,(strlen(GB.ToZeroString(PROP(GB_STRING)))+1)*sizeof(char));	strcpy(tmp,GB.ToZeroString(PROP(GB_STRING)));	Adv_correct_url(&tmp,THIS_PROTOCOL);	THIS_URL=tmp;END_PROPERTYBEGIN_PROPERTY(CCURL_tag)	if (READ_PROPERTY)  	{		GB.ReturnPtr(GB_T_VARIANT, &THIS->tag);		return;	}	GB.StoreVariant(PROP(GB_VARIANT), (void *)&THIS->tag);END_METHODBEGIN_METHOD_VOID(CCURL_new)	THIS->stream.desc=NULL;	THIS_CURL=NULL;	THIS_URL=NULL;	THIS_FILE=NULL;	GB.StoreVariant(NULL, (void *)&THIS->tag);	Adv_user_NEW  (&THIS->user);	GB.New ((void**)&THIS->proxy,GB.FindClass(".Proxy"),NULL,NULL);	GB.Ref((void*)THIS->proxy);	Adv_proxy_NEW(&THIS->proxy->proxy);	THIS->proxy->parent_status=&THIS->stream._free[0];END_METHODBEGIN_METHOD_VOID(CCURL_free)		char *tmp=THIS_URL;		if (tmp) GB.Free((void**)&tmp);	if (THIS_FILE) fclose(THIS_FILE);	if (THIS_CURL) curl_easy_cleanup(THIS_CURL);	Adv_user_CLEAR  (&THIS->user);	Adv_proxy_CLEAR(&THIS->proxy->proxy);	GB.Unref((void**)&THIS->proxy);	tmp=THIS_PROTOCOL;	GB.Free((void**)&tmp);	END_METHODBEGIN_METHOD_VOID(CCURL_init)	CCURL_multicurl=curl_multi_init();END_METHODBEGIN_METHOD_VOID(CCURL_exit)	curl_multi_cleanup(CCURL_multicurl);END_METHODBEGIN_METHOD_VOID(CCURL_Peek)	if ( (THIS->len_data) && (THIS->buf_data) )	{		GB.ReturnNewString(THIS->buf_data,THIS->len_data);		return;	}	GB.ReturnNewString(NULL,0);END_METHOD//*************************************************************************//#################### GAMBAS INTERFACE ###################################//*************************************************************************GB_DESC CCurlDesc[] ={  GB_DECLARE("Curl", sizeof(CCURL)), GB_NOT_CREATABLE(),  GB_INHERITS(".Stream"),  GB_METHOD("_new", NULL, CCURL_new, NULL),  GB_METHOD("_free", NULL, CCURL_free, NULL),  GB_METHOD("Peek","s", CCURL_Peek, NULL),    GB_STATIC_METHOD("_init",NULL,CCURL_init, NULL),  GB_STATIC_METHOD("_exit",NULL,CCURL_exit, NULL),  GB_EVENT("Finished", NULL, NULL, &CURL_FINISHED),  GB_EVENT("Connect", NULL, NULL, &CURL_CONNECT),  GB_EVENT("Read", NULL, NULL, &CURL_READ),  GB_EVENT("Error", NULL,NULL, &CURL_ERROR),  GB_PROPERTY("URL", "s",CCURL_URL),  GB_PROPERTY("User","s",CCURL_sUser),  GB_PROPERTY("Password","s",CCURL_Password),    GB_PROPERTY("Tag", "v", CCURL_tag),  GB_PROPERTY_READ("Proxy",".Proxy",CCURL_Proxy),  GB_PROPERTY_READ("Status","i",CCURL_Status),  GB_END_DECLARE};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -