Форум » [x]Harbour » HBCURL » Ответить

HBCURL

Eduard: Dima пишет: [quote]Вот и все непонятки закончились после того как убил кучу времени. У DownloadFile проблема с длинными именами файлов , при чем в UploadFile этой проблемы нет. Не важно каков размер файла , важна для него длина имени файла. Прошу опровергнуть или подтвердить описанное поведение DownloadFile. [/quote] Добрый день. У меня точно такая же проблема нарисовалась в моей программе, как описывает Дима. Программа на отрез не хочет принимать с фтп длинные имена файлов. точь в точь как в этой теме http://clipper.borda.ru/?1-4-0-00000844-000-10001-0 Удалось ли Вам побороть данную проблему.? Как вышли из ситуации? Хочу перейти на HBCURL, но нужно описание всех функций, особенно получение списка файлов с фтп-сервера по маске и скачивание файлов с сервера. Поделитесь своими наработками пожалуйста. П.С. Вот кусок программы, в котором я пытаюсь скачать файлики с сервера, список получаю, а вот файл /файлы / скачать не удается... [more] curl_global_init() IF ! Empty( curl := curl_easy_init() ) DEFAULT cDL TO "ftp://"+ArmFTP+"/" curl_easy_setopt( curl, HB_CURLOPT_DOWNLOAD ) curl_easy_setopt( curl, HB_CURLOPT_DIRLISTONLY) curl_easy_setopt( curl, HB_CURLOPT_USERPWD, ArmLogin+":"+ArmPass ) curl_easy_setopt( curl, HB_CURLOPT_URL, cDL+"OUT"+"/"+ArmPostID+"/"+dt2+"/" ) curl_easy_setopt( curl, HB_CURLOPT_DL_BUFF_SETUP ) curl_easy_perform( curl ) //DOWNLOAD DIRLIST TO STRING dnfiles:= curl_easy_dl_buff_get( curl ) MsgInfo(dnfiles) curl_easy_reset( curl ) //получаю список файлов на сервере DEFAULT cDL TO "ftp://"+ArmFTP+"/" curl_easy_setopt( curl, HB_CURLOPT_DOWNLOAD ) curl_easy_setopt( curl, HB_CURLOPT_USERPWD, ArmLogin+":"+ArmPass ) curl_easy_setopt( curl, HB_CURLOPT_URL, cDL+"OUT"+"/"+ArmPostID+"/"+dt2+"/" ) curl_easy_setopt( curl, HB_CURLOPT_DL_FILE_SETUP, cFileName := "*.*" ) ??? по маске, либо через список не хочет. curl_easy_setopt( curl, HB_CURLOPT_FAILONERROR, .T. ) curl_easy_perform( curl ) MsgInfo("DOWNLOAD FILE _ FILENAME: ") а вот тут засада, файлы не скачиваются... нужна помощь. curl_easy_reset( curl ) curl_easy_cleanup( curl ) ENDIF curl_global_cleanup() [/more]

Ответов - 65, стр: 1 2 3 4 All

Dima: Eduard Забил я на HBCURL... Делаю все с помощью HBTIP , но есть непонятки с рядом провайдеров , точно как описано и у вас. В основном все работает нормально , НО есть не понятные провы у которых все глючит.....и хз почему. К одному как то обратились , оказалось он там какие то IP и DNS сцука не верно настроил , апосля перенастройки все заработало нормально. PS Как вариант можно пробнуть консольный вариант CURL Линк дам.

Eduard: Dima пишет: Как вариант можно пробнуть консольный вариант CURL Спасибо, не надо, есть у меня.

Softlog86: Я использую связь через функции из стандартной библиотеки Windows wininet.dll С приёмом-передачей файлов с длинными именами проблемы нет - использую только такие пример : 04231e1ae.20160615.60453.ready (ID-компьютера.дата.время.статус) Дату+время записываю в имя файла именно по причине какого-то глюка - сервер не всегда дату правильно отдаёт .... а это важно - например отчет о продаже . Вот примерно часть кода по приёму файла с FTP : hLib := LOADLIBRARY( "wininet.dll" ) // Используем "штатную" библиотеку Windows // открыли "интернет" + сделали соединение с FTP-сервером hInternet = INETOPEN( "Anystring", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0 ) hConnect = INETCONNECT( hInternet, Имя_сервера_FTP, INTERNET_DEFAULT_FTP_PORT, Имя_пользователя_FTP, Пароль_FTP, INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE , 0 ) FTPGETFILE( hConnect,'request/ORDERS/'+(Имя_Скачиваемого_файла),System.Tempfolder+'\'+(имя_файла), 0, FILE_ATTRIBUTE_ARCHIVE, 0, 0 ) InetCloseHandle( hConnect) && закрыли соединение с сервером InetCloseHandle( hInternet) && закрыли соединение с Интернет Если нужно более развернуто - сообщай .


Eduard: Softlog86 пишет: Если нужно более развернуто - сообщай Да, нужно. Взято отсюда? http://forums.fivetechsupport.com/viewtopic.php?f=3&t=23075 Там в принципе все понятно, только не понятно с этой функцией по получению списка файлов, особенно данный фрагмент текста function FTPDirectory( cMask,cIP,cUser,cPass ) local hFTPDir, aFiles := {} local oWin32FindData, cBuffer local i:=0 default cMask := "*.*" STRUCT oWin32FindData MEMBER nFileAttributes AS DWORD MEMBER nCreationTime AS STRING LEN 8 MEMBER nLastReadAccess AS STRING LEN 8 MEMBER nLastWriteAccess AS STRING LEN 8 MEMBER nSizeHight AS DWORD MEMBER nSizeLow AS DWORD MEMBER nReserved0 AS DWORD MEMBER nReserved1 AS DWORD MEMBER cFileName AS STRING LEN 260 MEMBER cAltName AS STRING LEN 14 ENDSTRUCT hInternet = INTERNETOPEN( "Anystring", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0 ) hConnect = INTERNETCONNECT( hInternet, cIP, INTERNET_INVALID_PORT_NUMBER, cUser, cPass, INTERNET_SERVICE_FTP, 0, 0 ) //msginfo(hConnect) if hConnect != nil cBuffer = oWin32FindData:cBuffer hFTPDir = FtpFindFirstFile( hConnect, cMask, @cBuffer, 0, 0 ) oWin32FindData:cBuffer = cBuffer if ! empty( oWin32FindData:cFileName ) aadd( aFiles, { oWin32FindData:cFileName,; oWin32FindData:nSizeLow } ) while InternetFindNextFile( hFTPDir, @cBuffer ) oWin32FindData:cBuffer = cBuffer aadd( aFiles, { oWin32FindData:cFileName,; oWin32FindData:nSizeLow } ) end endif InternetCloseHandle( hFTPDir ) endif for i=1 TO len(aFiles) msginfo(aFiles[i,1]) next i return aFiles Больше всего меня интересует получение файлов по маске, и потом скачивание их всех вместе за один раз.

Softlog86: скачиваю файлы по-одному , оказалось что время скачивания что группой что по одиночке почти одинаковое . Тем более что мне в процессе скачивания мне нужно ещё что-то с ними делать .... получение списка файлов по маске : function ftpDIR(cKAT, Mask) //******************************************************************************* // // создаём массив имён файлов из cKAT/ для маски MASK на сервере обновлений ..... // возвращаем МАССИВ {имя , дата} // //******************************************************************************* Local cUrl cUrl := "ftp://" + Alltrim( FTPUSERNAME )+":"+ Alltrim(FTPpassword ) +"@"+ alltrim(FTP_SERVER_NAME) oUrl := tURL():New( cUrl ) // IF Empty( oUrl ) return nil endif oClient := TIpClientFtp():new( oUrl, .F. ) IF Empty( oClient ) ; return nil ; endif oClient:nConnTimeout := 15000 // // Временем можно поиграть ... oClient:bUsePasv := .T. IF At( "@", FTPUSERNAME ) > 0 oClient:oUrl:cServer := FTP_SERVER_NAME oClient:oUrl:cUserID := FTPUSERNAME oClient:oUrl:cPassword := FTPPassword ENDIF IF oClient:Open() IF Empty( oClient:cReply ) oClient:Pasv() ELSE oClient:Pasv() ENDIF arFILES:={} arFILES:=FTPFILLDATETIME(cKAT, Mask ,oClient) // заполняем нужной информацией ELSE msgalert('Нет связи с сервером '+FTP_SERVER_NAME ,'Ошибка !') arFILES:={} ENDIF oClient:CLOSE() return aRFILES FUNCTION FtpFillDateTime(Katalog,cMask,oClient) LOCAL ctext, cSepChar, nPos, acDir, cLine, x, avalues, xpesq, xpos, cvalue, cvalue1 , aRET:={},a:={} LOCAL i clret:= oClient:PWD cpath := oClient:cReply cfolder:=cpath+"/"+KATALOG oClient:CWD(cfolder) a := oClient:Listfiles(cMask) oClient:reset() If LEN(a)>0 FOR i:=1 TO LEN(a) // { Файл.C , Дата.D , Время.C } // Коррекция времени ! TimEcorrection - так как на сервере идёт своё время ...... - прибавляем TimeCorrectionI (число секунд) Z:=SECTOTIME(TIMETOSEC(a[i,4])+TimeCorrectionI) AADD(aRET,{a[i,1] , a[i,3] , Z } ) NEXT i ENDIF // Возвращаем массив с { имя , дата , время } ) RETURN aRET

Dima: Eduard пишет: STRUCT oWin32FindData Это надо прицепить из FW source\classes\tstruct.prg include\struct.ch

Eduard: В какой библиотеке находиться функция LoadLibrary кто знает? Компилятор MinGw дает ошибку при этапе линковки программы C:/Users/Eduard/AppData/Local/Temp/hbmk_760jxf.dir/ft.o:ft.c:(.data+0xb28): unde fined reference to `HB_FUN_LOADLIBRARY' collect2.exe: error: ld returned 1 exit status hbmk2: Error: Running linker. 1 gcc.exe C:/Users/Eduard/AppData/Local/Temp/hbmk_760jxf.dir/ft.o C:/Users/Eduard/ AppData/Local/Temp/hbmk_760jxf.dir/hbmk_0kicmk.o f:/hmg/minigui/Samples/ft/_temp .o -m32 -mwindows -Wl,--start-group -lminigui -lhbprinter -lminiprint -lsocke t -ladordd -lcalldll -ltsbrowse -lhbct -lhbmisc -lhbtip -lhbziparc -lhbmzip -lmi nizip -lhbwin -lxhb -lmsvfw32 -lvfw32 -lcurldll -lhbcurl -lwininet -lhbextern -l hbdebug -lhbvm -lhbrtl -lhblang -lhbcpage -lgtcgi -lgtstd -lgtpca -lgtwin -lgtwv t -lgtgui -lhbrdd -lhbusrrdd -lrddntx -lrddcdx -lrddnsx -lrddfpt -lhbrdd -lhbhsx -lhbsix -lhbmacro -lhbcplr -lhbpp -lhbcommon -lhbmainwin -lkernel32 -luser32 -l gdi32 -ladvapi32 -lws2_32 -liphlpapi -lwinspool -lcomctl32 -lcomdlg32 -lshell32 -luuid -lole32 -loleaut32 -lmpr -lwinmm -lmapi32 -limm32 -lmsimg32 -lwininet -lh bpcre -lhbzlib -Wl,--end-group -oft.exe -Lf:/HMG/harbour/lib -Lf:/HMG/minigui /lib hbmk2: Error: Referenced, missing, but unrecognized Harbour function(s): LOADLIBRARY() # hmg paths {win}incpaths=include {win}libpaths=lib {win}incpaths=${hb_curdir} # hmg resources {win}sources=${hb_curdir}_temp.o # gui mode {win}gt=gtgui # core {win}libs=minigui hbprinter miniprint socket # core additional binary {win}libs=adordd calldll tsbrowse # Harbour needed contrib {win}libs=hbct # Harbour additional contribs {win}libs=hbmisc hbtip hbziparc hbmzip minizip hbwin xhb # system {win}libs=msvfw32 vfw32 curldll hbcurl wininet hbwin

Softlog86: Eduard в файле .HBC Вашего проекта нужно добавить строчку : libpaths=c:\borland\bcc55\lib;c:\borland\lib\PSDK; Ну или как-то по-другому подключить .... Вроде как LOADLIBRARY() лежит в c:\borland\lib\PSDK\kernel32.lib

Dima: Eduard Кажись это FW source\winapi\dll.c Можно пробнуть hb_DynCall

Dima: Softlog86 пишет: libpaths=c:\borland\bcc55\lib;c:\borland\lib\PSDK; У него MINGW

Softlog86: Тогда понятно ....

SergKis: Eduard пишет В какой библиотеке находиться функция LoadLibrary MiniGui\SOURCE\Dll\_windll.c там есть

Eduard: Softlog86 пишет: hConnect = INETCONNECT( hInternet, Имя_сервера_FTP, INTERNET_DEFAULT_FTP_PORT, Имя_пользователя_FTP, Пароль_FTP, INTERNET_SERVICE_FTP,INTERNET_FLAG_PASSIVE , 0 ) Где можно посмотреть описания вот этих переменных что выделены жирным? есть какой ch-файл? Есть команда, для перехода в каталог, типа CWD?

Softlog86: Да , CWD () выбор директории Старая школа ещё помнит что такое 21-й порт :) #define FILE_ATTRIBUTE_ARCHIVE 128 #DEFINE FTP_TRANSFER_TYPE_UNKNOWN 0 #DEFINE FTP_TRANSFER_TYPE_ASCII 1 #DEFINE FTP_TRANSFER_TYPE_BINARY 2 #define INTERNET_INVALID_PORT_NUMBER 0 // use the protocol-specific default #DEFINE INTERNET_DEFAULT_FTP_PORT 21 // ' порт по умолчанию для FTP серверов #define INTERNET_DEFAULT_GOPHER_PORT 70 // " " gopher " #define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP " #define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS " #define INTERNET_DEFAULT_SOCKS_PORT 1080 // default for SOCKS firewall servers. #DEFINE INTERNET_SERVICE_FTP 1 #define INTERNET_SERVICE_GOPHER 2 #define INTERNET_SERVICE_HTTP 3 #DEFINE INTERNET_FLAG_PASSIVE 134217728 // used for FTP connections #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0 // Use registry configuration #DEFINE INTERNET_OPEN_TYPE_DIRECT 1 // direct to net #DEFINE INTERNET_OPEN_TYPE_PROXY 3 // via named proxy #DEFINE INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS

Dima: Eduard По поводу функций wininet https://searchcode.com/codesearch/view/4487644/

Eduard: Dima пишет: По поводу функций wininet https://searchcode.com/codesearch/view/4487644/ Спасибо, пригодиться. Вчера на скорую руку закончил проект, но надо еще внести пару правок в программу, т.к. сроки на работе поджимают. Есть возможность добавить ПрогрессБар к функции для приема/передачи файлов, что-то такое похожее на это?: Когда был HBTip то функция работала. oFtp:exGauge := { | done, size| ShowGaugePriem( done, size ) } PROCEDURE ShowGaugePriem( nSent, nSize ) Local nValue nValue := 100 * nSent/nSize IF nSent > 0 ft.Text_1.Value := Str(nValue,3)+" %" ft.ProgressBar_1.value := nValue DO EVENTS ENDIF RETURN

Dima: Eduard Это ведь Минигуи если я верно понял. Что то мне кажется что юзая функции "wininet.dll" не получится сделать ПрогрессБар (возможно ошибаюсь) Поэтому вижу варианты: 1. Повесить в окне "крутилку" , примеры есть 2. Заюзать AVI файл , типа как для копирования 3. Вывесить типа WAIT окна , "Ждите" 4. Повесить ПрогрессБар как в винде 10 , он бегает тудым сюдым И по ходу если файлы по размерам не очень большие , то и смысла нет что то вешать.

Softlog86: Дима верно всё говорит . Поэтому я и передаю файлы по-одиночке и завязываю это событие на прогресс-бар . (Поди не Дуал-ап - Интернет ? ) Моих юзеров при всяких операциях с фтп-приемом-передачей задержки не напрягают . На уровне открытия тяжелой страницы сайта . Да и их в это время можно чем-то занять (см Дима ) :) Большие , даже огромные , dbf файлы зипуются в очень компактную пачку . В любом случае передача быстрая . Для очень больших файлов есть смысл предусмотреть контроль полученного файла хотя-бы на уровне размера . Ох уж эта вредная привычка еще с CLIPPERовских времён всё экономить : память , размеры полей , "чтоб всё летало" :)

Eduard: Dima пишет: И по ходу если файлы по размерам не очень большие , то и смысла нет что то вешать. Да, файлики не большие от 5 кб. и до 100-120 кб. в редких случаях до 200. Все дело в том, что там где данная программа используется очень плохие каналы связи, стоят модемы от Укртелекома АДСЛ корпоративный канал до 128 - 512 кб/с. В основном скорость 128 кб./с Хотелось бы видеть процесс закачки. п.с. Предприятие ПАТ "Укрпошта", вот такие каналы стоят в отделениях свази.

Eduard: Eduard пишет: Для очень больших файлов есть смысл предусмотреть контроль полученного файла хотя-бы на уровне размера . Да такое у меня предусмотрено, идет проверка на контрольную сумму, crc посредством фтп-сервера.

Haz: Dima пишет: о то мне кажется что юзая функции "wininet.dll" не получится сделать ПрогрессБар (возможно ошибаюсь) Возможно и ошибаешься))) https://www.google.ru/url?sa=t&source=web&rct=j&url=https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa385120 Пишу "возможно" тк сам не пробовал, но какой лопатой рыть и куда, уже ясно

Dima: Haz пишет: Пишу "возможно" тк сам не пробовал Аналогично

Softlog86: тем более если файлики маленькие , зачем прогресс-бар ? Ставить прогресс на всю очередь и делу конец . Даже по диал-апу 50к/б файл зальётся за секунду Эдуард , получилось из наших советов что хотел ?

Eduard: Softlog86 пишет: Эдуард , получилось из наших советов что хотел ? Да, все работает.

Vlad04: Eduard Да, все работает. А как бы поделится самодостаточным необльшим примером, а то материалов по этой теме не густо.

Eduard: Да, без проблем, вот процедура из моей программы: Procedure ImpMailObmen() LOCAL curl, aGauge, nPos := 1 LOCAL a, tt, dt2, cFile, hInternet, hConnect, dlfiles olddir:= DIRCHANGE() DIRCHANGE(ArmImpDir) tt:=InputBoxDate("Введите дату отправки почты из обмена","Дата", DATE()) dt2:=SUBSTR(DTOC(tt),1,2)+"-"+SUBSTR(DTOC(tt),4,2)+"-"+SUBSTR(DTOC(tt),9,2) // формат папки на сервере 02-01-13 cFile := "CM"+BazaObmen+ArmPostID+"*"+"."+"*" addtextList2("Ждите, идет получение почты с сервера") dlfiles := ftpDIRArmVZ("OUT"+"/"+ArmPostID+"/"+dt2+"/", cFile) //получаем список файлов сервера по маске // открыли "интернет" + сделали соединение с FTP-сервером hInternet = INTERNETOPEN( "Anystring", INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0 ) if hInternet <> 0 hConnect = INTERNETCONNECT( hInternet, ArmFTP, INTERNET_DEFAULT_FTP_PORT, ArmLogin, ArmPass, INTERNET_SERVICE_FTP, INTERNET_FLAG_PASSIVE , 0 ) // ArmFTP - имя сервера ФТП, //ArmLogin, ArmPass - Логин и Пароль для доступа к серверу FTPSETCURRENTDIRECTORY(hConnect, "OUT") //переходим в нужную директорию на сервере... FTPSETCURRENTDIRECTORY(hConnect, ArmPostID) IF FTPSETCURRENTDIRECTORY(hConnect, dt2) IF Len( dlfiles ) > 0 FOR EACH cFile IN dlfiles FTPGETFILE( hConnect, cFile[F_NAME], ArmImpDir+cFile[F_NAME], 0, FTP_TRANSFER_TYPE_UNKNOWN, 0, 0 ) //получаем файлы addtextList2("Файл "+cFile[F_NAME] +" получен с сервера") NEXT ENDIF addtextList2("Вся почта была удачно получена!") MsgInfo("Вся почта была удачно получена!") ELSE MsgStop("На сервере отсутствует почта за дату "+DTOC(tt)) return 0 INTERNETCLOSEHANDLE( hConnect) && закрыли соединение с сервером INTERNETCLOSEHANDLE( hInternet) && закрыли соединение с Интернет ENDIF ELSE msgalert('Нет связи с сервером '+ArmFTP ,'Ошибка !') return 0 INTERNETCLOSEHANDLE( hConnect) && закрыли соединение с сервером INTERNETCLOSEHANDLE( hInternet) && закрыли соединение с Интернет ENDIF RETURN ******* function ftpDIRArmVZ(cKAT, Mask) //dir, maska Local cUrl cUrl := "ftp://" + Alltrim( ArmLogin )+":"+ Alltrim( ArmPass ) +"@"+ alltrim( ArmFTP ) //ftpusername, ftpuserpassword, ftpserver oUrl := tURL():New( cUrl ) // IF Empty( oUrl ) return nil endif oClient := TIpClientFtp():new( oUrl, .F. ) IF Empty( oClient ) ; return nil ; endif oClient:nConnTimeout := 20000 // // Временем можно поиграть ... oClient:bUsePasv := .T. IF At( "@", ArmLogin ) > 0 oClient:oUrl:cServer := ArmFTP oClient:oUrl:cUserID := ArmLogin oClient:oUrl:cPassword := ArmPass ENDIF IF oClient:Open() IF Empty( oClient:cReply ) oClient:Pasv() ELSE oClient:Pasv() ENDIF arFILES:={} arFILES:=FTPFILLARMVZ(cKAT, Mask ,oClient) // заполняем нужной информацией ELSE msgalert('Нет связи с сервером '+ArmFTP ,'Ошибка !') return 0 arFILES:={} ENDIF oClient:CLOSE() return aRFILES ******* FUNCTION FTPFILLARMVZ(Katalog,cMask,oClient) LOCAL ctext, cSepChar, nPos, acDir, cLine, x, avalues, xpesq, xpos, cvalue, cvalue1 , aRET:={},a:={} LOCAL i clret:= oClient:PWD cpath := oClient:cReply cfolder:=cpath+KATALOG *cfolder:=cpath+"/"+KATALOG oClient:CWD(cfolder) a := oClient:Listfiles(cMask) oClient:reset() If LEN(a)>0 FOR i:=1 TO LEN(a) // { Файл.C } //, Дата.D , Время.C } //у себя дату и время не использую... // Коррекция времени ! TimEcorrection - так как на сервере идёт своё время ...... - прибавляем TimeCorrectionI (число секунд) *Z:=SECTOTIME(TIMETOSEC(a[i,4])+TimeCorrectionI) AADD(aRET,{a[i,1]}) // , a[i,3] , Z } ) NEXT i ENDIF // Возвращаем массив с { имя } //, дата , время } ) RETURN aRET Ну и собственно, сами функции для работы с ФТП-сервером Объявления переменных в главной программе #define FILE_ATTRIBUTE_ARCHIVE 128 #DEFINE FTP_TRANSFER_TYPE_UNKNOWN 0 #DEFINE FTP_TRANSFER_TYPE_ASCII 1 #DEFINE FTP_TRANSFER_TYPE_BINARY 2 #define INTERNET_INVALID_PORT_NUMBER 0 // use the protocol-specific default #DEFINE INTERNET_DEFAULT_FTP_PORT 21 // ' порт по умолчанию для FTP серверов #define INTERNET_DEFAULT_GOPHER_PORT 70 // " " gopher " #define INTERNET_DEFAULT_HTTP_PORT 80 // " " HTTP " #define INTERNET_DEFAULT_HTTPS_PORT 443 // " " HTTPS " #define INTERNET_DEFAULT_SOCKS_PORT 1080 // default for SOCKS firewall servers. #DEFINE INTERNET_SERVICE_FTP 1 #define INTERNET_SERVICE_GOPHER 2 #define INTERNET_SERVICE_HTTP 3 #DEFINE INTERNET_FLAG_PASSIVE 134217728 // used for FTP connections #DEFINE INTERNET_OPEN_TYPE_PRECONFIG 0 // Use registry configuration #DEFINE INTERNET_OPEN_TYPE_DIRECT 1 // direct to net #DEFINE INTERNET_OPEN_TYPE_PROXY 3 // via named proxy #DEFINE INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY 4 // prevent using java/script/INS ****************** Функции: #pragma BEGINDUMP #include "windows.h" #include "wininet.h" #include "hbapi.h" HB_FUNC( INTERNETOPEN ) { hb_retnl( ( LONG ) InternetOpen( hb_parc( 1 ), hb_parnl( 2 ), hb_parc( 3 ), hb_parc( 4 ), hb_parnl( 5 ) ) ); } HB_FUNC( INTERNETCLOSEHANDLE ) { hb_retl( InternetCloseHandle( ( HINTERNET ) hb_parnl( 1 ) ) ); } HB_FUNC( INTERNETCONNECT ) { hb_retnl( ( LONG ) InternetConnect( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ), ( INTERNET_PORT ) hb_parnl( 3 ), hb_parc( 4 ), hb_parc( 5 ), hb_parnl( 6 ), hb_parnl( 7 ), hb_parnl( 8 ) ) ); } HB_FUNC( FTPGETFILE ) { hb_retl( FtpGetFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ), hb_parc( 3 ), hb_parl( 4 ), hb_parnl( 5 ), hb_parnl( 6 ), hb_parnl( 7 ) ) ); } HB_FUNC( FTPPUTFILE ) { hb_retl( FtpPutFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ), hb_parc( 3 ), hb_parnl( 4 ), hb_parnl( 5 ) ) ); } HB_FUNC( FTPDELETEFILE ) { hb_retl( FtpDeleteFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ) ) ); } HB_FUNC( FTPCREATEDIRECTORY ) { hb_retl( FtpCreateDirectory( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ) ) ); } HB_FUNC( FTPSETCURRENTDIRECTORY ) { hb_retl( FtpSetCurrentDirectory( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ) ) ); } HB_FUNC( FTPREMOVEDIRECTORY ) { hb_retl( FtpRemoveDirectory( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ) ) ); } HB_FUNC( FTPFINDFIRSTFILE ) { hb_retnl( ( LONG ) FtpFindFirstFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ), ( WIN32_FIND_DATA * ) hb_parc( 3 ), hb_parnl( 4 ), hb_parnl( 5 ) ) ); } HB_FUNC( INTERNETFINDNEXTFILE ) { hb_retl( InternetFindNextFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ) ) ); } HB_FUNC( INTERNETREADFILE ) { DWORD nBytesRead; BOOL lSuccess = InternetReadFile( ( HINTERNET ) hb_parnl( 1 ), ( LPVOID ) hb_parc( 2 ), hb_parclen( 2 ), &nBytesRead ); if ( !lSuccess ) hb_retnl( -1 ); else hb_retnl( nBytesRead ); } HB_FUNC( INTERNETWRITEFILE ) { DWORD nBytesWritten; BOOL lSuccess = InternetWriteFile( ( HINTERNET ) hb_parnl( 1 ), hb_parc( 2 ), hb_parnl( 3 ), &nBytesWritten ); hb_retl( lSuccess ); } #pragma ENDDUMP

Gosha: Подскажите как в hbcurl при подключении по ftp, сменить директорию.

Dima: Gosha Наверное так curl_easy_setopt( curl, HB_CURLOPT_URL, cDL ) где cDL твоя "дорога"

Gosha: При попытке сделать, например: curl_easy_setopt( curl, HB_CURLOPT_URL, "ftp://user:pass@192.168.1.1/home/MOJCATALOG/mojfailik.txt" ) я поподаю не в /home/MOJCATALOG/, а в /home/user/.

Dima: Gosha Логин и пасс вроде отдельно задаются HB_CURLOPT_USERNAME HB_CURLOPT_PASSWORD или HB_CURLOPT_USERPWD примерчик

Gosha: В примере hbcurl - ftp_uldl.prg логинятся и так "ftp://harbour:power@localhost/". Но вопрос не в этом, логинюсь я номально (лог сервера подтверждает), а вот как мне перейти в другой каталог? т.е. как сделать cd /?

Dima: Gosha Можно погуглить например. https://ec.haxx.se/ftp-traversedir.html Или обратить внимание на это #define HB_CURLFTPMETHOD_DEFAULT 0 /* let libcurl pick */ #define HB_CURLFTPMETHOD_MULTICWD 1 /* single CWD operation for each path part */ #define HB_CURLFTPMETHOD_NOCWD 2 /* no CWD at all */ #define HB_CURLFTPMETHOD_SINGLECWD 3 /* one CWD to full dir, then work on file */ PS Возможно я ошибаюсь...

Dima: Простой вопрос есть , вроде. Хочу сделать так что бы моя программа если при запуске обнаруживает libcurl.dll тогда FTP запросы у меня работают через HBCURL , если не находит то работаем через HBTIP. Реализовать это все я смогу. Но есть проблема , программа при запуске сразу вылетает если не находит libcurl.dll , хотя первой строкой идет обычный WAIT "test" Как то можно это побороть ?

Петр: Dima пишет: Простой вопрос есть , вроде. Вопрос простой, ответ не очень. Вот здесь вы найдете причину вылета. А вот решите ли проблему.. А статически прилинковывать libcurl set HB_STATIC_CURL=yes не пробовали?

Dima: Петр пишет: А статически прилинковывать libcurl set HB_STATIC_CURL=yes не пробовали? С таким SET не собирается ) [pre2] Compiling 'ftp_uldl.PRG'... Lines 372, Functions/Procedures 3 Generating C source output to 'obj\ftp_uldl.c'... Done. C:/MinGW12/bin/../lib/gcc/i686-w64-mingw32/4.9.2/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lssh2 collect2.exe: error: ld returned 1 exit status hbmk2[msklad]: Error: Running linker. 1 [/pre2] Почитал еще у Кресина и заюзал опции hbmk2 -shared -hbdynvm Собралось приложение но при запуске пишет что оно не приложение WIN32 ))

Dima: Хотел юзать LIBCURL.DLL примерно так hLib := hb_LibLoad( "LIBCURL.DLL" ) ********** тут поюзали --------- hb_LibFree( hLib )

Петр: Dima пишет: С таким SET не собирается ) С этой опцией должен собираться libcurl set HB_STATIC_CURL=yes Dima пишет: Почитал еще у Кресина и заюзал опции hbmk2 -shared -hbdynvm shared это для работы с harbour.dll а hbdynvm - create dynamic library (with linked Harbour VM), можно использовать в программах на C, PASCAL и пр.

Петр: И еще из hbcurl.hbc # NOTE: Static mode requires additional libs be linked: # OpenSSL

Dima: Петр пишет: С этой опцией должен собираться libcurl set HB_STATIC_CURL=yes Да тупанул , с ней и собрано

Dima: Собственно после сборки получил 3 либы libhbcurl.a libhbcurls.a liblibcurl.a Приложение собираю батником [pre2] set path=C:\MinGW\bin\ c:\hb32mingw\bin\hbmk2 test.hbp [/pre2] содержимое test.hbp [pre2] C:\hb32mingw\contrib\hbcurl\hbcurl.hbc -workdir=obj -otest.exe -std mytest.PRG [/pre2] Прога при запуске сразу хочет libcurl.dll и не стартует (если его нет) а хотелось бы рученятами когда нужно то грузить этот DLL и после использования выгружать. Не пойму как это сделать и возможно ли вообще , вот вопрос ?

Петр: Я давно не собирал libcurl.dll и программ с его использованием соответственно. Попробую найти время и посмотреть. Это сделать можно, вот вариант решения Другое дело можно ли это сделать для mingw и какие телодвижения нужно совершить для этого А чем не устраивает hbtip или curl, если он с 10-й действительно поставляется? Просто интересно

Dima: Петр С DelayLoad хорошее решение Но такой фичи похоже нет в MINGW , что печально.

Dima: Петр пишет: А чем не устраивает hbtip или curl, если он с 10-й действительно поставляется? Hbtip устраивает но у ряда провайдеров UPLOAD/DOWNLOAD (особенно последний) глючит по FTP и не докачивает файлы , хотя фтп-сервер один и тот же. Игрался с CURL.EXE у таких провов и FTP , вот с ним нет проблем. Если с LIBCURL.DLL не получится как задумал , возможно придется юзать CURL.EXE Спасибо

AndreyZh: Если устроит "колхозное" решение - стал применять, обнаружив, что не закачиваются на ftp файлы с длинными именами, а именно УПД [pre] aFiles := Directory(_OUTBOX+cShab+"*.xml") aBin := Directory(_OUTBOX+cShab+"*.bin") nLen := Len(aFiles) IF nLen <= 0 THEN RETU // Выход при отсутствии файлов для сохранения на FTP // Отключена технология моей работы с FTP. Попытка открытия канала и при отказе выход из режима oFtp := TIpClientFtp():new( _ZFTP ) // Создаю экземпляр класса объекта IF !oFtp:open() THEN RETU //*** Штатные средства не умеют работать с длинными именами файлов, как у УПД - делаю через жопу IF cShab == "ON_" // 04.12.2020 Оставляю технику без изменений - добавив в условие удаление из OUTBOX == не проверяю успешность отправки oFtp:close() // Закрываю канал - соединение FOR nI := 1 TO nLen cW := "wwput.bat "+_OUTBOX+" "+aFiles[nI,1]+" "+FTP_OUTBOX RUN &cW NEXT nI // Для некоторых КА могут быть и файлы подписи. Анализирую и отправляю nBin := Len(aBin) FOR nI := 1 TO nBin cW := "wwput.bat "+_OUTBOX+" "+aBin[nI,1]+" "+FTP_OUTBOX RUN &cW NEXT nI // 04.12.2020 FOR nI := 1 TO nLen DO FileDelete( _OUTBOX+aFiles[nI,1] ) FOR nI := 1 TO nBin DO FileDelete( _OUTBOX+aBin[nI,1] ) ELSE // Старые документы и УПД от Э-КОМ сохраняю средствами программы без "моргания" [/pre] где wwput.bat wput.exe -u --reupload %1%2 ftp://name:password@adress_ftp.ru/%3/%2

Dima: Потестил HBCURL. В программе доступ с HBTIP переписал под HBCURL для доступа к FTP. Глюков нет , работает шустро и стабильно Так что для доступа к FTP , это отличный выбор. PS Проблемы со скобками в именах файлов и символом # , решены. То что лишний DLL надо с собой таскать не проблема и так тягаю DLL от ADS и PageScript

SergKis: Dima пишет Так что для доступа к FTP , это отличный выбор. Поделиться примерчиком можешь ? Сюда или сам знаешь куда. Я не осилил по времени, curl.exe с ftp опробовал и вернулся к hbtip (от примера, т.к. время поджимало)

Dima: SergKis пишет: Поделиться примерчиком можешь ? Да подготовлю

Dima: По быстрому , на коленке. [pre2] #include "fileio.ch" #include "hbcurl.ch" #include "directry.ch" proc main Local aftpPar Local LocalDir:=hb_DirSepAdd(hb_CurDrive()+":\"+CurDir()) Local cfile:="testupload.txt" local cfilezip:="__#[test]#[upload]" curl_global_init() aftpPar:=LoadNastrFtp() // загружаем настройки FTP из базы if hb_MemoWrit( LocalDir+cfile, "bla bla bla" ) if HB_ZIPFILE(LocalDir+cfilezip+".tmp",{cfile}) ferase(LocalDir+cfile) ? TestUpl(aftpPar[6],aftpPar[4],aftpPar[5],aftpPar[14],Localdir,cfilezip,"/minisklad") ferase(LocalDir+cfilezip+".tmp") endif endif curl_global_cleanup() return ************ FUNCTION TestUpl( cserver,cuser,cpassword,nport,localdir,cfile,rdir) LOCAL cUrl LOCAL lRet := .f. local aftp Local Cftp:="ftp://"+cserver+":"+hb_ntos(nport) local nas:=0 local nerr curl := curl_easy_init() if empty(curl) ? "Bad curl_easy_init" return lRet endif do while .t. curl_easy_setopt( curl, HB_CURLOPT_DOWNLOAD ) curl_easy_setopt( curl, HB_CURLOPT_URL, cftp ) curl_easy_setopt( curl, HB_CURLOPT_USERPWD,cuser+":"+cpassword) curl_easy_setopt( curl, HB_CURLOPT_FTP_USE_EPSV,0) // 0 PASV 1 EPASV curl_easy_setopt( curl, HB_CURLOPT_DL_BUFF_SETUP ) curl_easy_setopt( curl, HB_CURLOPT_QUOTE, { "CWD "+rdir} ) curl_easy_setopt( curl, HB_CURLOPT_CUSTOMREQUEST,"LIST "+cfile+".zip") * если LIST средствами CURL получать через HB_CURLOPT_DIRLISTONLY * там только имена nerr:=curl_easy_perform( curl ) if nerr#0 ? CurlError(nerr) exit endif aftp:=listfilesftp(cfile, curl_easy_dl_buff_get( curl )) // функцию слямздил в HBTIP LISTFILES // хотя можно было и свою сваять nas:=ascan(aftp,{|x| x[1]==cfile+".zip"}) ******* if nas#0 lret:=.t. exit endif curl_easy_reset( curl ) curl_easy_setopt( curl, HB_CURLOPT_UPLOAD,1 ) curl_easy_setopt( curl, HB_CURLOPT_URL,cftp+"/"+hb_StrReplace(cfile+".tmp","#",{"%23"}) ) curl_easy_setopt( curl, HB_CURLOPT_USERPWD, cuser+":"+cpassword ) curl_easy_setopt( curl, HB_CURLOPT_UL_FILE_SETUP,localdir+cfile+".tmp" ) curl_easy_setopt( curl, HB_CURLOPT_POSTQUOTE, { "RNFR " + cfile+".tmp", "RNTO " +cfile+".zip" } ) nerr:=curl_easy_perform( curl ) if nerr#0 ? CurlError(nerr) else lRet:=.t. endif exit enddo curl_easy_cleanup( curl ) RETURN lRet ******* Func ListFilesFtp( cFileSpec,clist ) LOCAL aMonth := { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } LOCAL aList, aFile, cEntry, nStart, nEnd LOCAL cYear, cMonth, cDay, cTime // LOCAL cList := ::list( cFileSpec ) IF Empty( cList ) RETURN {} ENDIF aList := hb_ATokens( cList, .T. ) FOR EACH cEntry IN aList DESCEND IF Empty( cEntry ) hb_ADel( aList, cEntry:__enumIndex(), .T. ) ELSE aFile := Array( F_LEN + 3 ) nStart := 1 nEnd := hb_At( " ", cEntry, nStart ) // file permissions (attributes) aFile[ F_ATTR ] := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd IF Val( StrTran( aFile[ F_ATTR ], "-" ) ) == 0 // continue with Unix format // # of links DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) aFile[ F_LEN + 1 ] := Val( SubStr( cEntry, nStart, nEnd - nStart ) ) nStart := nEnd // owner name DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) aFile[ F_LEN + 2 ] := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd // group name DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) aFile[ F_LEN + 3 ] := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd // file size DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) aFile[ F_SIZE ] := Val( SubStr( cEntry, nStart, nEnd - nStart ) ) nStart := nEnd // Month DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) cMonth := StrZero( hb_AScan( aMonth, SubStr( cEntry, nStart, nEnd - nStart ), , , .T. ), 2 ) nStart := nEnd // Day DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) cDay := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd // Year DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) cYear := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd IF ":" $ cYear cTime := cYear cYear := StrZero( Year( Date() ), 4 ) ELSE cTime := "" ENDIF aFile[ F_DATE ] := hb_SToD( cYear + cMonth + cDay ) aFile[ F_TIME ] := cTime ELSE // DOS style/IIS format aFile[ F_LEN + 1 ] := 0 aFile[ F_LEN + 2 ] := aFile[ F_LEN + 3 ] := aFile[ F_ATTR ] := "" aFile[ F_DATE ] := hb_CToD( aFile[ F_ATTR ], "mm-dd-yy" ) // # time DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) cTime := SubStr( cEntry, nStart, nEnd - nStart ) nStart := nEnd aFile[ F_TIME ] := Left( TString( Secs( Left( cTime, 5 ) ) + iif( Right( cTime, 2 ) == "PM", 43200, 0 ) ), 5 ) // file size DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO nEnd := hb_At( " ", cEntry, nStart ) aFile[ F_SIZE ] := Val( SubStr( cEntry, nStart, nEnd - nStart ) ) nStart := nEnd ENDIF // file name DO WHILE SubStr( cEntry, ++nStart, 1 ) == " " ENDDO aFile[ F_NAME ] := SubStr( cEntry, nStart ) cEntry := aFile ENDIF NEXT RETURN aList ************************** Func CurlError(n) * тут можно и расшифровку вставить по коду ошибки return "Curl_Error "+hb_ntos(n) [/pre2]

SergKis: Dima пишет По быстрому , на коленке. Спасибо Буду разбираться

Dima: SergKis Есть тонкость с HB_CURLOPT_UPLOAD и заливкой файла на FTP. Даже если curl_easy_perform уже отработал , локально заливаемый файл остается залоченным самим CURL , пока не сделаем curl_easy_reset или curl_easy_cleanup

Dima: У одного клиента мобильный инет Киевстар. Иногда при попытке подключения к FTP и получения LIST получаю ошибку CURLE_OPERATION_TIMEDOUT (28) Версия LibCurl 7.76.0 Смотрел логи FTP сервера , там все красиво , ни каких ошибок. Таймауты я не трогал. Погуглил , но решения не нашел. Не понятно как решить проблемку............. PS У всех остальных у кого нормальный инет (не мобильный) такого не возникало Возможно (не уверен) 7.76.1 решит проблему https://github.com/curl/curl/pull/6859

Dima: Каким образом перехватить то что выводит HB_CURLOPT_VERBOSE и писать в файл ? curl_easy_setopt( curl, HB_CURLOPT_VERBOSE, .t.) Пробовал HB_CURLOPT_STDERR HB_CURLOPT_FILE HB_CURLOPT_WRITEHEADER Результат нулевой........

Петр: Dima пишет: Каким образом перехватить то что выводит HB_CURLOPT_VERBOSE и писать в файл ? The verbose information will be sent to stderr, or the stream set with CURLOPT_STDERR CURLOPT_STDERR в hbcurl не реализован. Значит остается /* NOTE: Redirect STDERR to a file to see the verbose output. */ - примечание из примера к hbcurl

Петр: Петр пишет: Значит остается... Или самому написать что-то такое [pre2] static HB_GARBAGE_FUNC( FILE_release ) { void ** ph = ( void ** ) Cargo; /* Check if pointer is not NULL to avoid multiple freeing */ if( ph && *ph ) { /* Destroy the object */ fclose( ( FILE * ) *ph ); /* set pointer to NULL to avoid multiple freeing */ *ph = NULL; } } static const HB_GC_FUNCS s_gcFILEFuncs = { FILE_release, hb_gcDummyMark }; static void hb_FILE_ret( FILE * p ) { if( p ) { void ** ph = ( void ** ) hb_gcAllocate( sizeof( FILE * ), &s_gcFILEFuncs ); *ph = p; hb_retptrGC( ph ); } else hb_retptr( NULL ); } static FILE * hb_FILE_par( int iParam ) { void ** ph = ( void ** ) hb_parptrGC( &s_gcFILEFuncs, iParam ); return ph ? ( FILE * ) *ph : NULL; } HB_FUNC( CURL_FOPEN ) { hb_FILE_ret( hb_fopen( hb_parcx( 1 ), "w+b" ) ); } HB_FUNC( CURL_EASY_SETOPT2 ) { if( PHB_CURL_is( 1 ) && HB_ISNUM( 2 ) ) { PHB_CURL hb_curl = PHB_CURL_par( 1 ); CURLcode res = ( CURLcode ) HB_CURLE_ERROR; if( hb_curl && ( hb_parni( 2 ) == HB_CURLOPT_STDERR ) ) { res = curl_easy_setopt( hb_curl->curl, CURLOPT_STDERR, hb_FILE_par( 3 ) ); } hb_retnl( ( long ) res ); } else hb_errRT_BASE( EG_ARG, 2010, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } [/pre2]

Петр: Здесь я использовал фрагменты кода из hbpgsql и hbcurl. Это нормально Добавил curl_easy_setopt2, хотя можно и curl_easy_setopt поправить. Использование: [pre2] LOCAL lVerbose := .T. LOCAL fStdErr := curl_fopen('verb.txt') ... ? curl_easy_setopt( curl, HB_CURLOPT_VERBOSE, lVerbose ) ? curl_easy_setopt2( curl, HB_CURLOPT_STDERR, fStdErr ) [/pre2]

Петр: Dima пишет: С DelayLoad хорошее решение Но такой фичи похоже нет в MINGW , что печально. Пока лучше с этим не связываться, геморно.

Dima: Петр пишет: Или самому написать что-то такое Спасибо , только не понятно куда этот кусок кода вставить , в сырец HBCURL и пересобрать ? Петр пишет: Пока лучше с этим не связыватся, геморно. Я уже смирился с этим

Петр: Dima пишет: Спасибо , только не понятно куда этот кусок кода вставить , в сырец HBCURL и пересобрать ? Да, добавить в hbcurl\core.c и пересобрать. В конец файла или я вот у себя добавил перед таким фрагментом /* Harbour interface */ /* ----------------- */

Dima: Петр пишет: Да, добавить в hbcurl\core.c и пересобрать. Да это работает , спасибо

Dima: Dima пишет: * если LIST средствами CURL получать через HB_CURLOPT_DIRLISTONLY * там только имена Был не прав и там еще 1 параметр и если он равен 0 тогда идет полный лист с размерами файлов и тд Но к сожалению свою маску задать не получится и там всегда *.* Поэтому юзаем HB_CURLOPT_CUSTOMREQUEST,"LIST "............

Dima: Как понять с помощью HBCURL что подключаемся мы через мобильного провайдера ? Среди опций curl_easy_getinfo данных о прове не увидел.....

Петр: Dima пишет: Как понять с помощью HBCURL что подключаемся мы через мобильного провайдера ? Среди опций curl_easy_getinfo данных о прове не увидел..... Для cURL можно так Запрос curl -X GET http://ip-api.com/json/?fields=status,message,country,countryCode,isp,query Результат {"status":"success","country":"Ukraine","countryCode":"UA","isp":"Kyivstar UA","query":"94.153.**.***"} Запрос curl -X GET http://ip-api.com/csv/?fields=status,message,country,countryCode,isp,query Результат success,Ukraine,UA,Kyivstar UA,46.211.**.*** Т.е. ответ можно получить в форматах JSON, XML, CSV.. [url=https://ip-api.com/docs/api:csv]Подробнее[/url]

Петр: Dima пишет: Как понять с помощью HBCURL что подключаемся мы через мобильного провайдера ? [pre2] #include "hbcurl.ch" #define CURL_HTTP_VERSION_2TLS 4 PROCEDURE Main() LOCAL curl, cStr curl_global_init() IF ! Empty( curl := curl_easy_init() ) curl_easy_setopt( curl, HB_CURLOPT_BUFFERSIZE, 102400 ) curl_easy_setopt( curl, HB_CURLOPT_URL, "http://ip-api.com/csv/?fields=status,message,country,mobile,isp,query" ) curl_easy_setopt( curl, HB_CURLOPT_NOPROGRESS, .T. ) curl_easy_setopt( curl, HB_CURLOPT_USERAGENT, "curl/7.75.0" ) curl_easy_setopt( curl, HB_CURLOPT_MAXREDIRS, 50 ) curl_easy_setopt( curl, HB_CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS ) curl_easy_setopt( curl, HB_CURLOPT_SSL_VERIFYPEER, .F. ) curl_easy_setopt( curl, HB_CURLOPT_SSL_VERIFYHOST, .F. ) curl_easy_setopt( curl, HB_CURLOPT_FTP_SKIP_PASV_IP, .F. ) curl_easy_setopt( curl, HB_CURLOPT_TCP_KEEPALIVE, .T. ) curl_easy_setopt( curl, HB_CURLOPT_DL_BUFF_SETUP ) curl_easy_perform( curl ) ? "EFFECTIVE URL:", curl_easy_getinfo( curl, HB_CURLINFO_EFFECTIVE_URL ) cStr := curl_easy_dl_buff_get( curl ) ? "RESULT: " + cStr IF hb_ATokens( cStr, "," )[ 4 ] == "true" ? "Mobile (cellular) connection." ENDIF curl_easy_reset( curl ) curl_easy_cleanup( curl ) ENDIF curl_global_cleanup() RETURN [/pre2] Опция cURL --libcurl <file> рулит..

Dima: Петр Понял. Спасибо. Одна проблема только есть , там где нужно чекнуть эту штуку , сисадмин закрыл 80 и 443 порты Разберемся.

Dima: Странная штука , вроде должно работать а не работает и ни какой реакции curl_easy_setopt( curl, HB_CURLOPT_PREQUOTE,{"CLNT testklient"}) Ежели вот так , то пашет конечно curl_easy_setopt( curl, HB_CURLOPT_QUOTE, {"CLNT testklient", "CWD "+rdir} )



полная версия страницы