00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef __HAVE_CURL__
00034 #include "mmstools/mmsfiletransfer.h"
00035 #include <string.h>
00036 #include <stdlib.h>
00037
00038 size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream) {
00039 return fread(ptr, size, nmemb, (FILE*) stream);
00040 }
00041
00042 size_t write_callback(void *buffer, size_t size, size_t nmemb, void *stream) {
00043 FtpFile *out = (FtpFile*) stream;
00044 if (out && !out->stream) {
00045
00046 out->stream = fopen(out->filename, "ab");
00047 if (!out->stream)
00048 return -1;
00049 }
00050
00051 return fwrite(buffer, size, nmemb, out->stream);
00052 }
00053
00054
00055
00056 size_t c_mem_write_callback(char *buffer, size_t size, size_t nitems, void *outstream) {
00057 if (outstream)
00058 return ((MMSFiletransfer *)outstream)->mem_write_callback(buffer, size, nitems, outstream);
00059 else
00060 return 0;
00061 }
00062
00063
00064 size_t MMSFiletransfer::mem_write_callback(char *buffer, size_t size, size_t nitems, void *outstream) {
00065 char *newbuff;
00066 unsigned int freebuff;
00067
00068
00069 size *= nitems;
00070
00071
00072 freebuff=this->buf_len - this->buf_pos;
00073
00074 if(size > freebuff) {
00075
00076 newbuff=(char*)realloc(this->buffer,this->buf_len + (size - freebuff));
00077 if(newbuff==NULL) {
00078 size=freebuff;
00079 }
00080 else {
00081
00082 this->buf_len+=size - freebuff;
00083 this->buffer=newbuff;
00084 }
00085 }
00086
00087 memcpy(&(this->buffer[this->buf_pos]), buffer, size);
00088 this->buf_pos += size;
00089
00090 return size;
00091 }
00092
00093
00094 int progress_callback(void *pclient, double dltotal, double dlnow, double ultotal, double ulnow) {
00095 ((MMSFiletransfer*) pclient)->progress.emit(dltotal != 0 ? (int) (.5 + 100* dlnow / dltotal) : (int) (.5 + 100* ulnow / ultotal));
00096 return 0;
00097 }
00098
00099 MMSFiletransfer::MMSFiletransfer(const string url, const unsigned int ftpPort = 0) :
00100 timeout(10),
00101 lowSpeedLimit(102400),
00102 port(ftpPort) {
00103 setRemoteUrl(url);
00104
00105
00106 curl_global_init(CURL_GLOBAL_ALL);
00107
00108
00109 this->ehandle = curl_easy_init();
00110
00111 if (!this->ehandle) {
00112 this->lasterror = CURLE_FAILED_INIT;
00113 } else {
00114
00115 curl_easy_setopt(this->ehandle, CURLOPT_LOW_SPEED_LIMIT, this->lowSpeedLimit);
00116 curl_easy_setopt(this->ehandle, CURLOPT_LOW_SPEED_TIME, this->timeout);
00117 if(this->port != 0)
00118 curl_easy_setopt(this->ehandle, CURLOPT_PORT, this->port);
00119 }
00120 }
00121
00122
00123 MMSFiletransfer::~MMSFiletransfer() {
00124 curl_easy_cleanup(this->ehandle);
00125 curl_global_cleanup();
00126 }
00127
00128
00129 void MMSFiletransfer::setVerboseInformation(bool enable) {
00130 curl_easy_setopt(this->ehandle, CURLOPT_VERBOSE, (enable ? 1L : 0L));
00131 }
00132
00133
00134 void MMSFiletransfer::setAuthData(const string user, const string password) {
00135 std::string auth = user;
00136 if (0 != password.length())
00137 auth += ":" + password;
00138
00139 curl_easy_setopt(this->ehandle, CURLOPT_USERPWD, auth.c_str());
00140 }
00141
00142
00143 bool MMSFiletransfer::performUpload(const string localfile, const string remoteName, bool resume) {
00144 FILE *hd_src;
00145 struct stat file_info;
00146
00147
00148 curl_easy_setopt(this->ehandle, CURLOPT_UPLOAD, 1L);
00149
00150 curl_easy_setopt(this->ehandle, CURLOPT_FTP_CREATE_MISSING_DIRS, 1L);
00151
00152
00153 curl_easy_setopt(this->ehandle, CURLOPT_NOPROGRESS, 0L);
00154 curl_easy_setopt(this->ehandle, CURLOPT_PROGRESSFUNCTION, progress_callback);
00155 curl_easy_setopt(this->ehandle, CURLOPT_PROGRESSDATA, this);
00156
00157 if (resume) {
00158 curl_easy_setopt(this->ehandle, CURLOPT_RESUME_FROM, -1L);
00159 }
00160
00161
00162 curl_easy_setopt(this->ehandle, CURLOPT_URL, (this->remoteUrl + remoteName).c_str());
00163
00164
00165 if (stat(localfile.c_str(), &file_info)) {
00166
00167 this->lasterror = CURLE_FILE_COULDNT_READ_FILE;
00168 return false;
00169 }
00170
00171
00172 hd_src = fopen(localfile.c_str(), "rb");
00173 if(!hd_src) {
00174 this->lasterror = CURLE_FILE_COULDNT_READ_FILE;
00175 return false;
00176 }
00177
00178
00179 curl_easy_setopt(this->ehandle, CURLOPT_READFUNCTION, read_callback);
00180 curl_easy_setopt(this->ehandle, CURLOPT_READDATA, hd_src);
00181
00182 curl_easy_setopt(this->ehandle, CURLOPT_INFILESIZE, (long)file_info.st_size);
00183
00184
00185 this->lasterror = curl_easy_perform(this->ehandle);
00186 if (this->lasterror != CURLE_OK)
00187 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 1);
00188 else
00189 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 0);
00190
00191 fclose(hd_src);
00192
00193 return (this->lasterror == CURLE_OK);
00194 }
00195
00196
00197 bool MMSFiletransfer::performDownload(const string localfile, const string remoteName, bool resume) {
00198 struct stat file_info;
00199 FtpFile ftpfile = { localfile.c_str(),
00200 NULL };
00201
00202
00203 curl_easy_setopt(this->ehandle, CURLOPT_NOPROGRESS, 0L);
00204 curl_easy_setopt(this->ehandle, CURLOPT_PROGRESSFUNCTION, progress_callback);
00205 curl_easy_setopt(this->ehandle, CURLOPT_PROGRESSDATA, this);
00206
00207 if (resume) {
00208 if (!stat(localfile.c_str(), &file_info)) {
00209 curl_easy_setopt(this->ehandle, CURLOPT_RESUME_FROM, (long)file_info.st_size);
00210 }
00211 }
00212
00213 if (!fopen(ftpfile.filename, (resume ? "ab" : "wb"))) {
00214 this->lasterror = CURLE_FILE_COULDNT_READ_FILE;
00215 return false;
00216 }
00217
00218 curl_easy_setopt(this->ehandle, CURLOPT_URL, (this->remoteUrl + remoteName).c_str());
00219
00220
00221 curl_easy_setopt(this->ehandle, CURLOPT_WRITEDATA, &ftpfile);
00222
00223
00224 curl_easy_setopt(this->ehandle, CURLOPT_WRITEFUNCTION, write_callback);
00225
00226 this->lasterror = curl_easy_perform(this->ehandle);
00227 if (this->lasterror != CURLE_OK)
00228 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 1);
00229 else
00230 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 0);
00231
00232
00233 if (ftpfile.stream) {
00234 fclose(ftpfile.stream);
00235 }
00236
00237 return (this->lasterror == CURLE_OK);
00238 }
00239
00240
00241 bool MMSFiletransfer::deleteRemoteFile(const string remoteFile) {
00242 std::string ftpcommand = "";
00243 struct curl_slist *slist=NULL;
00244
00245 ftpcommand = "DELE " + remoteFile;
00246 slist = curl_slist_append(slist, "CWD ~");
00247 slist = curl_slist_append(slist, ftpcommand.c_str());
00248
00249 curl_easy_setopt(this->ehandle, CURLOPT_QUOTE, slist);
00250
00251 curl_easy_setopt(this->ehandle, CURLOPT_URL, this->remoteUrl.c_str());
00252 curl_easy_setopt(this->ehandle, CURLOPT_HEADER, 1);
00253
00254
00255 curl_easy_setopt(this->ehandle, CURLOPT_NOBODY, 1);
00256 this->lasterror = curl_easy_perform(this->ehandle);
00257 if (this->lasterror != CURLE_OK)
00258 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 1);
00259 else
00260 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 0);
00261
00262 curl_easy_setopt(this->ehandle, CURLOPT_HEADER, 0);
00263 curl_easy_setopt(this->ehandle, CURLOPT_NOBODY, 0);
00264 curl_slist_free_all(slist);
00265 curl_easy_setopt(this->ehandle, CURLOPT_QUOTE, NULL);
00266
00267 return (this->lasterror == CURLE_OK);
00268 }
00269
00270
00271 bool MMSFiletransfer::getListing(char **buffer, string directory, bool namesOnly) {
00272 this->buffer = NULL;
00273 this->buf_len = 0;
00274 this->buf_pos = 0;
00275
00276
00277 if ((directory.length() - 1) != directory.find('/', directory.length() - 1)) {
00278 directory.append("/");
00279 }
00280 curl_easy_setopt(this->ehandle, CURLOPT_URL, (this->remoteUrl + directory).c_str());
00281
00282
00283 curl_easy_setopt(this->ehandle, CURLOPT_WRITEDATA, this);
00284
00285
00286 curl_easy_setopt(this->ehandle, CURLOPT_WRITEFUNCTION, c_mem_write_callback);
00287 curl_easy_setopt(this->ehandle, CURLOPT_DIRLISTONLY, (namesOnly ? 1L : 0L));
00288
00289 this->lasterror = curl_easy_perform(this->ehandle);
00290
00291 if (this->lasterror != CURLE_OK)
00292 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 1);
00293 else
00294 curl_easy_setopt(this->ehandle, CURLOPT_FRESH_CONNECT, 0);
00295
00296 *buffer = this->buffer;
00297 return (this->lasterror == CURLE_OK);
00298 }
00299
00300
00301 void MMSFiletransfer::setRemoteUrl(const string url) {
00302 this->remoteUrl = "ftp://" + url;
00303
00304
00305 if ((this->remoteUrl.length() - 1) != this->remoteUrl.find('/', this->remoteUrl.length() - 1)) {
00306 this->remoteUrl.append("/");
00307 }
00308 }
00309
00310
00311 const string MMSFiletransfer::getRemoteUrl() {
00312 return this->remoteUrl;
00313 }
00314
00315
00316 void MMSFiletransfer::setTimeout(const long timeout) {
00317 this->timeout = timeout;
00318 curl_easy_setopt(this->ehandle, CURLOPT_LOW_SPEED_TIME, timeout);
00319 }
00320
00321
00322 const long MMSFiletransfer::getTimeout() {
00323 return this->timeout;
00324 }
00325
00326
00327 void MMSFiletransfer::setFtpPort(const unsigned int ftpPort) {
00328 if((this->port != ftpPort) && (0 != ftpPort)) {
00329 this->port = ftpPort;
00330 curl_easy_setopt(this->ehandle, CURLOPT_PORT, this->port);
00331 }
00332 }
00333
00334
00335 const unsigned int MMSFiletransfer::getFtpPort() {
00336 return this->port;
00337 }
00338
00339
00340 void MMSFiletransfer::setLowSpeedLimit(const long limit) {
00341 this->lowSpeedLimit = limit;
00342 curl_easy_setopt(this->ehandle, CURLOPT_LOW_SPEED_LIMIT, limit);
00343 }
00344
00345
00346 const long MMSFiletransfer::getLowSpeedLimit() {
00347 return this->lowSpeedLimit;
00348 }
00349
00350
00351 int MMSFiletransfer::getLastError(string *errormsg = NULL) {
00352 if (errormsg) {
00353 *errormsg = (this->lasterror ? curl_easy_strerror(this->lasterror) : NULL);
00354 }
00355 return this->lasterror;
00356 }
00357
00358 #endif