#include "scurl.h" #include #include #include int SCURL::m_nUsage = 0; quint64 SCURL::m_nFileSize = 0; quint64 SCURL::m_nCurrentRead = 0; int SCURL::m_nPrevCount = 0; int SCURL::m_nErrorCount = 0; #include #include #include #include #ifdef WIN32 #include #else #include #endif #include #include "mainwindow.h" /* * Performs an FTP upload and renames the file just after a successful * transfer. * */ SCURL* g_pThis = NULL; typedef struct _GlobalInfo { CURLM *multi; int still_running; } GlobalInfo; /* Information associated with a specific easy handle */ typedef struct _ConnInfo { CURL *easy; char *url; GlobalInfo *global; char error[CURL_ERROR_SIZE]; } ConnInfo; static curl_socket_t opensocket(void *clientp, curlsocktype purpose, struct curl_sockaddr *address) { g_pThis->m_SocketFD = *(curl_socket_t *)clientp; /* the actual externally set socket is passed in via the OPENSOCKETDATA option */ return g_pThis->m_SocketFD; } static int sockopt_callback(void *clientp, curl_socket_t curlfd, curlsocktype purpose) { /* This return code was added in libcurl 7.21.5 */ return CURL_SOCKOPT_ALREADY_CONNECTED; } //static size_t read_callback(char *ptr, size_t size, size_t nmemb, void *stream) size_t SCURL::read_callback(char *ptr, size_t size, size_t nmemb, void *stream) { unsigned long nread; /* in real-world cases, this would probably get this data differently as this fread() stuff is exactly what the library already would do by default internally */ size_t retcode = fread(ptr, size, nmemb, (FILE*)stream); m_nCurrentRead += retcode; g_pThis->SetProgressExportPercent(m_nCurrentRead, m_nFileSize); usleep(10); if(retcode > 0) { nread = (unsigned long)retcode; //fprintf(stderr, "*** We read %lu bytes from file\n", nread); } return retcode; } int SCURL::CurlProgress(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) { if(g_pThis->m_bStop==true) { curl_socket_t sockfd; auto res = curl_easy_getinfo(g_pThis->m_pCURL, CURLINFO_ACTIVESOCKET, &sockfd); // ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there close(sockfd); curl_easy_reset( g_pThis->m_pCURL ); return CURLE_UNRECOVERABLE_POLL; } if( dltotal > 0 || dlnow > 0 || ultotal > 0 || ulnow > 0) { g_pThis->m_nFileSize = ultotal; g_pThis->m_nCurrentRead = ulnow; if(g_pThis->m_nCurrentRead==g_pThis->m_nPrevCount) { g_pThis->m_nErrorCount++; if(g_pThis->m_nErrorCount>5) { curl_socket_t sockfd; auto res = curl_easy_getinfo(g_pThis->m_pCURL, CURLINFO_ACTIVESOCKET, &sockfd); // ASSERT_EQ(res, CURLE_OK); - no point in doing anything if the socket is not there close(sockfd); curl_easy_reset( g_pThis->m_pCURL ); return CURLE_UNRECOVERABLE_POLL; } } else { g_pThis->m_nErrorCount = 0; } g_pThis->m_nPrevCount = ulnow; //static int m_nPrevCount; //static int m_nErrorCount; //fprintf(stderr, "Up: %d/%d\n", ulnow, ultotal); //CryLogAlways("UP: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T " DOWN: %" CURL_FORMAT_CURL_OFF_T " of %" CURL_FORMAT_CURL_OFF_T "\r\n", ulnow, ultotal, dlnow, dltotal); } return CURLE_OK; } SCURL::SCURL() { m_nUsage++; g_pThis = this; m_bStop = false; connect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); } SCURL::~SCURL() { m_nUsage--; disconnect(&m_Timer, SIGNAL(timeout()), this, SLOT(OnTimer())); } void SCURL::OnTimer() { if(m_nPrevCount==m_nCurrentRead) { m_nErrorCount++; if(m_nErrorCount>2) { curl_easy_reset( m_pCURL ); m_Timer.stop(); } } else { m_nErrorCount = 0; } m_nPrevCount = m_nCurrentRead; } void SCURL::Init() { curl_global_init(CURL_GLOBAL_ALL); } void SCURL::Release() { curl_global_cleanup(); } int SCURL::UploadFTP2(QString strFilename) { return 0; } int SCURL::UploadFTP(QString strFilename) { if(IsConnectNetwork()==false) { return -11; } CURLcode res; FILE *hd_src; struct stat file_info; unsigned long fsize; struct curl_slist *headerlist = NULL; //static const char buf_1 [] = "RNFR " UPLOAD_FILE_AS; //static const char buf_2 [] = "RNTO " RENAME_FILE_TO; QFileInfo fi(strFilename); QString strFile = fi.fileName(); QString strPath = fi.path(); strPath = strPath.replace("/data/video/", ""); int nRet = 0; CommonData* pCommonData = MainWindow::GetCommonData(); NetworkShareInfo* pShareInfo = pCommonData->GetNetworkShareInfo(); QString strID; QString strPassword; int nPort = 21; bool bUseSSL = false; strID = pShareInfo->m_strID; strPassword = pShareInfo->m_strPassword; nPort = pShareInfo->m_strIP.toInt(); QString strTargetFolder = pShareInfo->m_strShareFolder; if(pShareInfo->m_strVersion.contains("SSL")==true) { bUseSSL = true; } //QString strUrl = QString("ftp://192.168.1.19/OK/%1/%2").arg(strPath).arg(strFile); QString strUrl = QString("%1/%2/%3").arg(strTargetFolder).arg(strPath).arg(strFile); /* get the file size of the local file */ if(stat(strFilename.toStdString().c_str(), &file_info)) { printf("Couldn't open '%s': %s\n", strFilename.toStdString().c_str(), strerror(errno)); return -1; } fsize = (unsigned long)file_info.st_size; m_nFileSize = fsize; m_nCurrentRead = 0; m_nErrorCount = 0; m_nPrevCount = -1; SetProgressExportPercent(m_nCurrentRead, m_nFileSize); printf("Local file size: %lu bytes.\n", fsize); /* get a FILE * of the same file */ hd_src = fopen(strFilename.toStdString().c_str(), "rb"); /* get a curl handle */ m_pCURL = curl_easy_init(); if(m_pCURL) { /* build a list of commands to pass to libcurl */ //headerlist = curl_slist_append(headerlist, strFileFrom.toStdString().c_str()); //headerlist = curl_slist_append(headerlist, strFileTo.toStdString().c_str()); /* call this function to get a socket */ //curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket); //curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &m_SocketFD); /* call this function to set options for the socket */ //curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback); curl_easy_setopt(m_pCURL, CURLOPT_CONNECTTIMEOUT_MS, 1000L); //1 Second curl_easy_setopt(m_pCURL, CURLOPT_TIMEOUT_MS, 1000*60*10); //10 Minutes curl_easy_setopt(m_pCURL, CURLOPT_PROTOCOLS, CURLPROTO_FTP); /* we want to use our own read function */ curl_easy_setopt(m_pCURL, CURLOPT_READFUNCTION, read_callback); /* enable uploading */ curl_easy_setopt(m_pCURL, CURLOPT_UPLOAD, 1L); /* specify target */ curl_easy_setopt(m_pCURL, CURLOPT_URL, strUrl.toStdString().c_str()); /* now specify which file to upload */ curl_easy_setopt(m_pCURL, CURLOPT_READDATA, hd_src); /* Set the size of the file to upload (optional). If you give a *_LARGE option you MUST make sure that the type of the passed-in argument is a curl_off_t. If you use CURLOPT_INFILESIZE (without _LARGE) you must make sure that to pass in a type 'long' argument. */ curl_easy_setopt(m_pCURL, CURLOPT_INFILESIZE_LARGE, (curl_off_t)fsize); curl_easy_setopt(m_pCURL, CURLOPT_FTP_CREATE_MISSING_DIRS, (long)CURLFTP_CREATE_DIR); //curl_easy_setopt(curl, CURLOPT_USERNAME, "birdhead"); //curl_easy_setopt(curl, CURLOPT_PASSWORD, "1"); curl_easy_setopt(m_pCURL, CURLOPT_USERNAME, strID.toStdString().c_str()); curl_easy_setopt(m_pCURL, CURLOPT_PASSWORD, strPassword.toStdString().c_str()); curl_easy_setopt(m_pCURL, CURLOPT_PORT, nPort); //curl_easy_setopt(m_pCURL, CURLOPT_VERBOSE, 1L); curl_easy_setopt(m_pCURL, CURLOPT_VERBOSE, 0L); curl_easy_setopt(m_pCURL, CURLOPT_LOGIN_OPTIONS, "AUTH=LOGIN"); if(bUseSSL==true) { //curl_easy_setopt(m_pCURL, CURLOPT_FTP_USE_EPSV, 0L); /* require use of SSL for this, or fail */ curl_easy_setopt(m_pCURL, CURLOPT_USE_SSL, (long)CURLUSESSL_ALL); //curl_easy_setopt(m_pCURL, CURLOPT_FTPPORT, nPort); curl_easy_setopt(m_pCURL, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(m_pCURL, CURLOPT_SSL_VERIFYHOST, 0L); //curl_easy_setopt(m_pCURL, CURLOPT_FTP_SSL, CURLFTPSSL_ALL); curl_easy_setopt(m_pCURL, CURLOPT_FTP_SSL, CURLFTPSSL_TRY); curl_easy_setopt(m_pCURL, CURLOPT_FTPSSLAUTH, CURLFTPAUTH_TLS); curl_easy_setopt(m_pCURL, CURLOPT_NOPROGRESS, 0L); //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); //curl_setopt($ch, CURLOPT_FTP_SSL, true); //curl_setopt($ch, CURLOPT_VERBOSE, true); } else { curl_easy_setopt(m_pCURL, CURLOPT_NOPROGRESS, 0L); } //curl_easy_setopt(m_pCURL, CURLOPT_TIMEOUT, 1L); curl_easy_setopt(m_pCURL, CURLOPT_XFERINFOFUNCTION, CurlProgress); //m_Timer.setSingleShot(true); //m_Timer.start(500); /* Now run off and do what you have been told! */ res = curl_easy_perform(m_pCURL); //m_Timer.stop(); /* Check for errors */ if(res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); nRet = -res; } /* clean up the FTP commands list */ curl_slist_free_all(headerlist); /* always cleanup */ curl_easy_cleanup(m_pCURL); } fclose(hd_src); /* close the local file */ return nRet; } bool SCURL::IsConnectNetwork() { bool bIsConnect = false; QList listNetworkInterface = QNetworkInterface::allInterfaces(); int nCount = listNetworkInterface.size(); int i=0; for(i=0 ; i listNetworkAddresssEntry = ni.addressEntries(); if(nType==QNetworkInterface::Ethernet) { if(strName.contains("eth")==true) { if(listNetworkAddresssEntry.size()==0) { bIsConnect = false; } else { bIsConnect = true; /* int j=0; for(j=0 ; j