/*************************************************************************** CFtpClient.c Advanced Network component (c) 2003-2008 Daniel Campos Fernández 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 __CFTPCLIENT_C #include #include #include #include #include #include #include #include "main.h" #include "gambas.h" #include "CCurl.h" #include "CFtpClient.h" #include "CProxy.h" /***************************************************** CURLM : a pointer to use curl_multi interface, allowing asynchrnous work without using threads in this class. Here also a pipe will be stablished to link with Gambas watching interface ******************************************************/ extern CURLM *CCURL_multicurl; /******************************************************************* #################################################################### CALLBACKS FROM CURL LIBRARY #################################################################### ********************************************************************/ int ftp_read_curl (void *buffer, size_t size, size_t nmemb, void *_object) { /* BM */ FILE *file = THIS_FILE; THIS_STATUS=4; if (!feof(file)) nmemb=fread(buffer,size,nmemb,file); else nmemb=0; return nmemb; } int ftp_write_curl(void *buffer, size_t size, size_t nmemb, void *_object) { THIS_STATUS=4; if (THIS_FILE) { return fwrite(buffer,size,nmemb,THIS_FILE); } else { if (!THIS->len_data) GB.Alloc((void**)POINTER(&THIS->buf_data),nmemb); else GB.Realloc((void**)POINTER(&THIS->buf_data),nmemb+THIS->len_data); memcpy(THIS->buf_data+THIS->len_data,buffer,nmemb); THIS->len_data+=nmemb; } if (THIS->async) { GB.Ref(THIS); GB.Post(CCURL_raise_read,(long)THIS); } return nmemb; } void ftp_reset(CFTPCLIENT *mythis) { if (mythis->curl.buf_data) { GB.Free((void**)POINTER(&mythis->curl.buf_data)); mythis->curl.buf_data=NULL; } mythis->curl.len_data=0; } void ftp_initialize_curl_handle(void *_object) { if (THIS_CURL) { if (Adv_Comp ( THIS->user.userpwd,THIS->user.user,THIS->user.pwd)) { CCURL_stop(_object); ftp_reset(_object); THIS_CURL=curl_easy_init(); #if DEBUG fprintf(stderr, "-- [%p] curl_easy_init() -> %p\n", THIS, THIS_CURL); #endif } } else { THIS_CURL=curl_easy_init(); #if DEBUG fprintf(stderr, "-- [%p] curl_easy_init() -> %p\n", THIS, THIS_CURL); #endif } if (!THIS->async) { curl_easy_setopt(THIS_CURL, CURLOPT_NOSIGNAL,1); curl_easy_setopt(THIS_CURL, CURLOPT_TIMEOUT,THIS->TimeOut); } curl_easy_setopt(THIS_CURL, CURLOPT_VERBOSE,1); curl_easy_setopt(THIS_CURL, CURLOPT_PRIVATE,(char*)_object); Adv_proxy_SET (&THIS->proxy.proxy,THIS_CURL); Adv_user_SET (&THIS->user, THIS_CURL); curl_easy_setopt(THIS_CURL, CURLOPT_URL,THIS_URL); ftp_reset(THIS_FTP); THIS_STATUS=6; CCURL_init_stream(THIS); } int ftp_get (void *_object) { if (THIS_STATUS > 0) return 1; THIS->iMethod=0; ftp_initialize_curl_handle(THIS); curl_easy_setopt(THIS_CURL, CURLOPT_WRITEFUNCTION , ftp_write_curl); curl_easy_setopt(THIS_CURL, CURLOPT_WRITEDATA , _object); curl_easy_setopt(THIS_CURL, CURLOPT_UPLOAD , 0); if (THIS->async) { #if DEBUG fprintf(stderr, "-- [%p] curl_multi_add_handle(%p)\n", THIS, THIS_CURL); #endif curl_multi_add_handle(CCURL_multicurl,THIS_CURL); CCURL_init_post(); return 0; } CCURL_Manage_ErrCode(_object,curl_easy_perform(THIS_CURL)); return 0; } int ftp_put (void *_object) { if (THIS_STATUS > 0) return 1; THIS->iMethod=1; ftp_initialize_curl_handle(THIS); curl_easy_setopt(THIS_CURL, CURLOPT_READFUNCTION , ftp_read_curl); curl_easy_setopt(THIS_CURL, CURLOPT_READDATA , _object); curl_easy_setopt(THIS_CURL, CURLOPT_UPLOAD , 1); if (THIS->async) { #if DEBUG fprintf(stderr, "-- [%p] curl_multi_add_handle(%p)\n", THIS, THIS_CURL); #endif curl_multi_add_handle(CCURL_multicurl,THIS_CURL); CCURL_init_post(); return 0; } CCURL_Manage_ErrCode(_object,curl_easy_perform(THIS_CURL)); return 0; } BEGIN_METHOD(CFTPCLIENT_Get,GB_STRING TargetHost;) if (!MISSING(TargetHost)) { if (THIS_STATUS > 0) { GB.Error("Still active"); return; } THIS_FILE=fopen(GB.ToZeroString(ARG(TargetHost)),"w"); if (!THIS_FILE) { GB.Error("Unable to open file for writing"); return; } } if (ftp_get(THIS)) GB.Error("Still active"); END_METHOD /************************************************* PUT FTP method *************************************************/ BEGIN_METHOD(CFTPCLIENT_Put,GB_STRING SourceFile;) if (THIS_STATUS > 0) { GB.Error("Still active"); return; } if (!LENGTH(SourceFile)) { GB.Error("Invalid File Name\n"); return; } THIS_FILE=fopen(GB.ToZeroString(ARG(SourceFile)),"r"); if (!THIS_FILE) { GB.Error("Unable to open file for reading"); return; } if (ftp_put (THIS) ) GB.Error("Still active"); END_METHOD BEGIN_METHOD_VOID(CFTPCLIENT_Stop) CCURL_stop(_object); ftp_reset(_object); END_METHOD BEGIN_METHOD_VOID(CFTPCLIENT_new) char *tmp=NULL; GB.Alloc((void**)POINTER(&tmp),sizeof(char)*(1+strlen("ftp://127.0.0.1:21"))); THIS_URL=tmp; strcpy(tmp,"ftp://127.0.0.1:21"); tmp=NULL; GB.Alloc((void**)POINTER(&tmp),7); strcpy(tmp,"ftp://"); THIS_PROTOCOL=tmp; Adv_user_SETAUTH (&THIS->user,CURLAUTH_BASIC); THIS->async = TRUE; END_METHOD BEGIN_METHOD_VOID(CFTPCLIENT_free) ftp_reset(THIS_FTP); END_METHOD //************************************************************************* //#################### GAMBAS INTERFACE ################################### //************************************************************************* GB_DESC CFtpClientDesc[] = { GB_DECLARE("FtpClient", sizeof(CFTPCLIENT)), GB_INHERITS("Curl"), GB_METHOD("_new", NULL, CFTPCLIENT_new, NULL), GB_METHOD("_free", NULL, CFTPCLIENT_free, NULL), GB_METHOD("Stop", NULL, CFTPCLIENT_Stop, NULL), GB_METHOD("Get", NULL, CFTPCLIENT_Get, "[(TargetFile)s]"), GB_METHOD("Put", NULL, CFTPCLIENT_Put, "(LocalFile)s"), GB_CONSTANT("_Properties", "s", FTP_PROPERTIES), GB_CONSTANT("_DefaultEvent", "s", "Read"), GB_END_DECLARE };