Форум » LetoDB, HbNetio. » Вопросы новичка... (продолжение) » Ответить

Вопросы новичка... (продолжение)

Andrey: Взял последнюю версию с "Новая страница с бинарниками", установил на Win2008 Server, чуток помучился с портом... Собрал на МиниГуи+BCC 551 - \MiniGui\batch\hbmk2.bat rddleto.hbp Получил rddleto.lib - 131072 байт - правильный ли размер ? И еще Warning-и лезут: lib\.hbmk\win\bcc\rddsys.c: source\client\letocl.c: source\client\leto1.c: source\client\letomgmn.c: source\common\blowfish.c: source\common\common_c.c: source\common\hbip.c: TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation /P32 lib\rddleto.lib -+ lib\.hbmk\win\bcc\rddsys.obj -+ lib\.hbmk\win\bcc\letocl.obj -+ lib\.hbmk\win\bcc\leto1.obj -+ lib\.hbmk\win\bcc\letomgmn.obj -+ lib\.hbmk\win\bcc\blowfish.obj -+ lib\.hbmk\win\bcc\common_c.obj -+ lib\.hbmk\win\bcc\hbip.objWarning: 'rddsys' not found in library Warning: 'letocl' not found in library Warning: 'leto1' not found in library Warning: 'letomgmn' not found in library Warning: 'blowfish' not found in library Warning: 'common_c' not found in library Warning: 'hbip' not found in library Так должно быть или нет ? Вопрос сразу напрашивается с путями - как писать правильно "\" или "/" : Local cPathServer := "//127.0.0.1:2812/" cPathServer := cPathServer +"DATE_TEST_PATH\test.dbf" Помню что где то обсуждали, а результат не запомнил...

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

Петр: Pasha пишет: Вызывать можно функции, указанные в request, ну и некоторые другие. Я пересматривал этот набор - он вполне безопасен. Впрочем, я уже добавил параметр EnableUDF в letodb.ini, для возможности отключения udf. Для себя внес изменения в letofunc.c [pre2]const char * szErrUDF = "-UDF"; .. void leto_udf( PUSERSTRU pUStru, const char* szData ) // mt? .. if( uiCommand == 0 ) { leto_wUsLog(pUStru,"ERROR! UDF: not a valid command\r\n", 0); return; } nParam = leto_GetParam( szData, &pp2, &pp3, NULL, NULL ); // leto_writelog( NULL, 0, "UDF: %s, CMD=%d\r\n", pp2, uiCommand ); if( strlen( pp2 ) < 5 || hb_strnicmp( pp2, "UDF_", 4 ) != 0 ) { leto_wUsLog(pUStru,"ERROR! UDF: not a valid name\r\n", 0); leto_SendAnswer( pUStru, szErrUDF, 4 ); pUStru->bAnswerSent = 1; return; } if( nParam < ( uiCommand == 1 ? 3 : ( uiCommand == 3 ? 1 : 2 ) ) ) leto_SendAnswer( pUStru, szErr2, 4 ); else .. [/pre2] Т.е. имя UDF функции должно начинаться с UDF_ (UDF_() - не проходит) - хак с выполнением стандартных и функций leto через механизм leto_udf на сервере отсекается. Ну и сделал более осмысленным описание ошибки для leto_wUsLog. Мне кажется такое решение более логичным существующего.

SergKis: Pasha Скачал letodb-code-618295e5b48bf8ef2a50ca089ba73af8f1b57b85б :... + added EnableUDF option in letodb.ini но в HAPP нет считывания с letodb.ini EnableUGF и нет установки [pre2] leto_SetAppOptions( iif( Empty(::DataPath ),Nil,::DataPath ), ::nDriver, ::lFileFunc, ; ::lAnyExt, ::lPass4L, ::lPass4M, ::lPass4D, ::cPassName, ::lCryptTraffic, ; ::lShare, ::lNoSaveWA, nMaxVars, nMaxVarSize, nCacheRecords, nTables_max, nUsers_max, ; nDebugMode, lOptimize, nAutOrder, nMemoType, lForceOpt, ::cTrigger, ::cPendingTrigger, lSetTrigger ) // нет 25 элемента [/pre2] или я не там смотрю. EnableUDF = 1 - если 1 (по умолчанию), разрешено использование udf-функций; EnableUDF = 0 что делает, отключает все вызовы udf ? Если да, то чем отличается услановка в 0 и работа сервера без letoudf.hrb ?

Pasha: Прошу прощения, пропустил при коммите server.prg. Поправлю. Да, EnableUDF запрещает вызовы UDF. Может быть, имеет смысл еще добавить флаг UDFPrefix, который позволял бы вызовы только функций с именами UDF_*


Петр: Как вариант, еще вместо одного letoudf.hrb можно использовать 2 (или более), например, letoudf_st.hrb и letoudf_us.hrb. Запуск letoudf_st.hrb не зависит от EnableUDF, запуск letoudf_us.hrb (и остальных), соответственно, зависит.

Петр: Pasha пишет: Может быть, имеет смысл еще добавить флаг UDFPrefix Имеет, мой голос - за

SergKis: Pasha пишет Может быть, имеет смысл еще добавить флаг UDFPrefix Я тоже за Но можно просто обойтись режимом 0 1 2 - спрефиксоом udf_ (пока не вижу причин нескольких префиксов, но может ошибаюсь) а то возникнет желание на каждого user уст. разрешено\нет udf, как с файловыми, mg ф-ими

Петр: SergKis пишет: а то возникнет желание на каждого user уст. разрешено можно и на уровне функций, т.е. доступна ли функция a() пользователю b

SergKis: Петр пишет можно и на уровне функций, т.е. доступна ли функция a() пользователю b Скорее возникает желание в udf знать что то с LETO_USERGETRIGHTS( nUserStru ) (такой нет) + доп. установку на user в Pass_File = "leto_users" доплнительных данных (байт 10-20). Например так на клиенте LETO_USERPARAM( cUserName, cParam ) --> lSuccess LETO_USERPARAM( cUserName ) --> cParam и на сервере LETO_USERPARAM( nUserStru [, cUserName ] ) --> cParam LETO_USERGETRIGHTS( nUserStru[, cUserName ] ) --> cRights

SergKis: Еще такая есть хотелка - класс для работы с Hash массивом с синхронизированными методами доступа к его элементам, для работы в udf

SergKis: И еще есть желание (многие сервера обеспечивают) иметь алиасные пути к файлам и таблицам, например секция в letodb.ini (привязка разработки к реальном данным на сервере) [ALIAS] \TMP\ = \TEST\TABL\BLS\ \WRK\ = \TEST\WRK\ \MY1\ = \TEST\MY1\ \MY2\ = \TEST\MY2\ на клиенте пишем \tmp\table01.dbf \tmp\table02.dbf на сервере происходит подмена на реальное значение \TMP\ и т.д. в 2-х поточной версии для dbf я это делал, для файловых ф-й ( C ) сложновато для меня

SergKis: И последнее. Не хватает команды типа ( если стоит EnableFileFunc = 0 и нет hrb, а теперь и режим 0 для udf) 1. CRATE TABLE myTable ... IF NOT EXISTS - трудно управлять созданием таблицы, особенно если нет созданных каталогов к ней, возможно по установке в ini (а может и всегда) разрешать автосоздание дирректорий при их отсутсвии 2. DROP TABLE myTable - удалить таблицу вместе с индексами

SergKis: PS Реализация CREATE TABLE ... IF NOT EXISTS могла бы выглядеть к примеру так:[pre2] FUNCTION hs_createtable( nUserStru, cCommand ) ... LOCAL cRecData LOCAL lTable := .F., lAutoCreate := leto_GetAppOptions( 26 ) // к примеру ... IF Lower(cName) = "/mem:" cDataPath := "" cName := Substr(cName, 2) ELSE cDataPath := leto_GetAppOptions( 1 ) ENDIF cFileName := cDataPath + cName IF !empty(cDataPath) // обработка алиаса, если использовать механизм cFileName := SetAlias2Path( cFileName ) // заменяем ALIAS (если есть) на реальный путь // If lAutoCreate lTable := hb_FileExists(cFileName) If ! lTable CreateDir(cFileName) EndIf EndIf ENDIF If ! lTable BEGIN SEQUENCE WITH { |e|break( e ) } leto_SetUserEnv( nUserStru ) dbCreate( cFileName, aStru, leto_Driver( nDriver ), .T. , cRealAlias ) RECOVER USING oError lres := .F. END SEQUENCE EndIf ... STATIC FUNCTION CreateDir( cDBF ) LOCAL aCt := {} LOCAL i := RAt(DEF_SEP, cDBF) LOCAL cCt := Left(cDBF, i-1) DO WHILE ! hb_DirExists( cCt ) i := RAt(DEF_SEP, cCt) IF i == 0 ; EXIT ENDIF AAdd( aCt , subs(cCt, i+1) ) cCt := Left( cCt, i-1) ENDDO i := Len( aCt ) DO WHILE i > 0 cCt += (DEF_SEP + aCt[i--]) MakeDir( cCt ) ENDDO RETURN .T. [/pre2]

Pasha: SergKis пишет: Еще такая есть хотелка - класс для работы с Hash массивом с синхронизированными методами доступа к его элементам, для работы в udf Добавил request на сервере для хеш-функций. Сделал префикс UDF_* обязательным по умолчанию для вызовов udf, с возможностью отключения этого режима. А функция hb_dbDrop поддерживается letodb уже давно, т.к. метод letoDrop реализован на клиенте.

SergKis: Pasha А что по поводу варианта CREATE TABLE ... IF NOT EXISTS

SergKis: Pasha HApp разсогласовался по переменным DATA и LOCAL в Method New, потому прошла ошибка[pre2] ELSEIF aIni[i,2,j,1] == "ENABLEUDF" ::lUDF := ( aIni[i,2,j,2] == '1' ) ... leto_SetAppOptions( iif( Empty(::DataPath ),Nil,::DataPath ), ::nDriver, ::lFileFunc, ; ::lAnyExt, ::lPass4L, ::lPass4M, ::lPass4D, ::cPassName, ::lCryptTraffic, ; ::lShare, ::lNoSaveWA, nMaxVars, nMaxVarSize, nCacheRecords, nTables_max, nUsers_max, ; nDebugMode, lOptimize, nAutOrder, nMemoType, lForceOpt, ::cTrigger, ::cPendingTrigger, lSetTrigger, lUDF ) [/pre2] Предлагаю [pre2] CLASS HApp DATA nPort INIT 2812 DATA ip DATA nTimeOut INIT -1 DATA DataPath INIT "" DATA LogFile INIT "" DATA lLower INIT .F. DATA lFileFunc INIT .F. DATA lAnyExt INIT .F. DATA lShare INIT .F. // .T. - new mode, which allows share tables with other processes DATA lNoSaveWA INIT .F. // .T. - new mode, which forces dbUseArea() each time "open table" is demanded DATA nDriver INIT 0 DATA lPass4M INIT .F. DATA lPass4L INIT .F. DATA lPass4D INIT .F. DATA cPassName INIT "leto_users" DATA lCryptTraffic INIT .F. DATA cTrigger DATA cPendingTrigger DATA nMaxVars DATA nMaxVarSize DATA nCacheRecords INIT 10 DATA nTables_max DATA nUsers_max DATA nDebugMode INIT 0 DATA lOptimize INIT .F. DATA nAutOrder DATA nMemoType DATA lForceOpt INIT .F. DATA lSetTrigger INIT .F. DATA lUDF INIT .T. METHOD New() ENDCLASS METHOD New() CLASS HApp LOCAL cIniName := "letodb.ini" LOCAL aIni, i, j, cTemp, cPath, nDriver LOCAL nPort := ::nPort // LOCAL nMaxVars, nMaxVarSize LOCAL nCacheRecords := ::nCacheRecords LOCAL nTables_max := NIL LOCAL nUsers_max := NIL LOCAL nDebugMode := 0 // LOCAL lOptimize := .F. // LOCAL nAutOrder LOCAL nMemoType // LOCAL lForceOpt := .F. // LOCAL lSetTrigger := .F. // LOCAL lUDF := .T. #ifdef __LINUX__ IF File( cDirBase + cIniName ) aIni := rdIni( cDirBase + cIniName ) ELSEIF File( "/etc/" + cIniName ) aIni := rdIni( "/etc/" + cIniName ) ENDIF #else IF File( cDirBase + cIniName ) aIni := rdIni( cDirBase + cIniName ) ENDIF #endif IF !Empty( aIni ) FOR i := 1 TO Len( aIni ) IF aIni[i,1] == "MAIN" FOR j := 1 TO Len( aIni[i,2] ) IF aIni[i,2,j,1] == "PORT" IF ( nPort := Val( aIni[i,2,j,2] ) ) >= 2000 ::nPort := nPort ENDIF ELSEIF aIni[i,2,j,1] == "IP" ::ip := aIni[i,2,j,2] ELSEIF aIni[i,2,j,1] == "TIMEOUT" ::nTimeOut := Val( aIni[i,2,j,2] ) ELSEIF aIni[i,2,j,1] == "DATAPATH" ::DataPath := StrTran( aIni[i,2,j,2], DEF_CH_SEP, DEF_SEP ) IF Right( ::DataPath, 1 ) $ DEF_SEP ::DataPath := Left( ::DataPath, Len( ::DataPath ) - 1 ) ENDIF ELSEIF aIni[i,2,j,1] == "LOGPATH" ::LogFile := StrTran( aIni[i,2,j,2], DEF_CH_SEP, DEF_SEP ) IF !EMPTY( ::LogFile ) IF Right( ::LogFile, 1 ) != DEF_SEP ::LogFile += DEF_SEP ENDIF leto_setDirBase( ::LogFile ) ENDIF ELSEIF aIni[i,2,j,1] == "LOWER_PATH" ::lLower := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "ENABLEFILEFUNC" ::lFileFunc := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "ENABLEANYEXT" ::lAnyExt := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "ENABLEUDF" ::lUDF := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "SHARE_TABLES" ::lShare := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "NO_SAVE_WA" ::lNoSaveWA := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "DEFAULT_DRIVER" ::nDriver := iif( Lower( aIni[i,2,j,2] ) == "ntx", LETO_NTX, 0 ) ELSEIF aIni[i,2,j,1] == "PASS_FOR_LOGIN" ::lPass4L := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "PASS_FOR_MANAGE" ::lPass4M := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "PASS_FOR_DATA" ::lPass4D := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "PASS_FILE" ::cPassName := aIni[i,2,j,2] ELSEIF aIni[i,2,j,1] == "CRYPT_TRAFFIC" ::lCryptTraffic := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "MAX_VARS_NUMBER" ::nMaxVars := Val( aIni[i,2,j,2] ) ELSEIF aIni[i,2,j,1] == "MAX_VAR_SIZE" ::nMaxVarSize := Val( aIni[i,2,j,2] ) ELSEIF aIni[i,2,j,1] == "CACHE_RECORDS" IF ( nCacheRecords := Val( aIni[i,2,j,2] ) ) <= 0 nCacheRecords := 10 ENDIF ::nCacheRecords := nCacheRecords ELSEIF aIni[i,2,j,1] == "TABLES_MAX" IF ( nTables_max := Val( aIni[i,2,j,2] ) ) <= 100 .OR. nTables_max > 200000 nTables_max := NIL ENDIF ::nTables_max := nTables_max ELSEIF aIni[i,2,j,1] == "USERS_MAX" IF ( nUsers_max := Val( aIni[i,2,j,2] ) ) <= 10 .OR. nUsers_max > 100000 nUsers_max := NIL ENDIF ::nUsers_max := nUsers_max ELSEIF aIni[i,2,j,1] == "DEBUG" IF ( nDebugMode := Val( aIni[i,2,j,2] ) ) <= 0 nDebugMode := 0 ENDIF ::nDebugMode := nDebugMode ELSEIF aIni[i,2,j,1] == "OPTIMIZE" ::lOptimize := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "AUTORDER" ::nAutOrder := Val( aIni[i,2,j,2] ) ELSEIF aIni[i,2,j,1] == "MEMO_TYPE" IF Lower( aIni[i,2,j,2] ) = 'dbt' nMemoType := DB_MEMO_DBT ELSEIF Lower( aIni[i,2,j,2] ) = 'fpt' nMemoType := DB_MEMO_FPT ELSEIF Lower( aIni[i,2,j,2] ) = 'smt' nMemoType := DB_MEMO_SMT ENDIF ::nMemoType := nMemoType ELSEIF aIni[i,2,j,1] == "FORCEOPT" ::lForceOpt := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "ENABLESETTRIGGER" ::lSetTrigger := ( aIni[i,2,j,2] == '1' ) ELSEIF aIni[i,2,j,1] == "TRIGGER" ::cTrigger := aIni[i,2,j,2] ELSEIF aIni[i,2,j,1] == "PENDINGTRIGGER" ::cPendingTrigger := aIni[i,2,j,2] ENDIF NEXT ELSEIF aIni[i,1] == "DATABASE" cPath := nDriver := Nil FOR j := 1 TO Len( aIni[i,2] ) IF aIni[i,2,j,1] == "DATAPATH" cPath := StrTran( aIni[i,2,j,2], DEF_CH_SEP, DEF_SEP ) IF Right( cPath, 1 ) $ DEF_SEP cPath := Left( cPath, Len( cPath ) - 1 ) ENDIF ELSEIF aIni[i,2,j,1] == "DRIVER" nDriver := iif( ( cTemp := Lower( aIni[i,2,j,2] ) ) == "cdx", ; 0, iif( cTemp == "ntx", LETO_NTX, Nil ) ) ENDIF NEXT IF cPath != Nil cPath := StrTran( cPath, DEF_CH_SEP, DEF_SEP ) IF Left( cPath,1 ) != DEF_SEP cPath := DEF_SEP + cPath ENDIF IF Right( cPath,1 ) != DEF_SEP cPath += DEF_SEP ENDIF leto_AddDataBase( cPath, iif( nDriver == Nil,::nDriver,nDriver ) ) ENDIF ENDIF NEXT ENDIF IF ::lLower SET( _SET_FILECASE, 1 ) SET( _SET_DIRCASE, 1 ) ENDIF IF ::lNoSaveWA ::lShare := .T. ENDIF leto_SetAppOptions( iif( Empty(::DataPath ),Nil,::DataPath ), ::nDriver, ::lFileFunc, ; ::lAnyExt, ::lPass4L, ::lPass4M, ::lPass4D, ::cPassName, ::lCryptTraffic, ; ::lShare, ::lNoSaveWA, ::nMaxVars, ::nMaxVarSize, ::nCacheRecords, ::nTables_max, ::nUsers_max, ; ::nDebugMode, ::lOptimize, ::nAutOrder, ::nMemoType, ::lForceOpt, ::cTrigger, ::cPendingTrigger, ; ::lSetTrigger, ::lUDF ) RETURN Self [/pre2]

SergKis: Pasha Что то в последней версии udf не работает. Сборка borland, hb из последнего Minigui. клиент [pre2] Function Test_Udf( cPath ) Local c,i,j,k,lRes IF Empty( cPath ) cPath := "//127.0.0.1:2812/" ELSE cPath := "//" + cPath + Iif( Right(cPath,1) $ "/\", "", "/" ) ENDIF ? "Connect to " + cPath + " - " IF ( leto_Connect( cPath ) ) == -1 nRes := leto_Connect_Err() ?? "Error", nRes IF nRes == LETO_ERR_LOGIN ?? "Login failed" ELSEIF nRes == LETO_ERR_RECV ?? "Recv Error" ELSEIF nRes == LETO_ERR_SEND ?? "Send Error" ELSE ?? "No connection" ENDIF Return Nil ELSE ?? "Ok" ENDIF ? If leto_UdfExist("leto_GetAppOptions") ? "leto_GetAppOptions found" Else ? "not found "+"leto_GetAppOptions" EndIf If leto_UdfExist('hb_DiskSpace') ? "hb_DiskSpace found", leto_udf( "hb_DiskSpace", "C:\", HB_DISK_FREE ) Else ? "not found "+"hb_DiskSpace" EndIf If leto_UdfExist('UDF_AppendRec') ? 'UDF_AppendRec - found' Else ? 'UDF_AppendRec - not found' EndIf ? "Press any key to finish..." ? Inkey(0) Return Nil результат Connect to //127.0.0.1:2812/ - Ok not found leto_GetAppOptions not found hb_DiskSpace UDF_AppendRec - not found Press any key to finish... letodb.ini Port = 2812 DataPath = . EnableFileFunc = 1 EnableUDF = 1 letodb.log 08/07/16 00:04:18: Leto DB Server has been started. Leto DB Server v.2.17b2 ! INIT: DataPath=., ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 08/07/16 00:04:18: C:\LETO\letodb-code-0324bd6820c3d9644f815b7dac76309859220501\bin\letoudf.hrb has been loaded. 08/07/16 00:11:54: Send STOP to server... 08/07/16 00:11:57: Server has been closed. сборка leto-core-6bc3... тот же пример ---------------------------------------------- letodb.ini Port = 2812 DataPath = . EnableFileFunc = 1 результат Connect to //127.0.0.1:2812/ - Ok leto_GetAppOptions found hb_DiskSpace found 422226853888 UDF_AppendRec - found Press any key to finish... letodb.log 08/06/16 23:47:17: Leto DB Server has been started. Leto DB Server v.2.17b2 ! INIT: DataPath=., ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 08/06/16 23:47:17: C:\LETO\letodb-code-6bc3e8f667ff4d65caeb620eafca574aba1bd166\bin\letoudf.hrb has been loaded. 08/06/16 23:49:51: Send STOP to server... 08/06/16 23:49:54: Server has been closed. [/pre2]

Pasha: Почему-то не был виден коммит, который я сделал позавчера, хотя у меня он прошел нормально. Сейчас я его повторил.

SergKis: Pasha Что не то [pre2] letodb.ini Port = 2812 DataPath = . EnableFileFunc = 1 EnableUDF = 1 letodb.log 08/07/16 09:10:27: Leto DB Server has been started. Leto DB Server v.2.17b2 ! INIT: DataPath=., ShareTables=0, MaxUsers=500, MaxTables=5000, CacheRecords=10 08/07/16 09:10:27: C:\LETO\letodb-code-7e89fed2f632e34d814bf8518ec08707be6b0e45\bin\letoudf.hrb has been loaded. 08/07/16 09:17:03: Send STOP to server... 08/07/16 09:17:06: Server has been closed. letodb_0.log 127.0.0.1 LENOVO Test_Udf.exe ERROR! UDF: not a valid name ERROR! UDF: not a valid name клиент пересобран с rddleto.lib из этой сборки результат Connect to //127.0.0.1:2812/ - Ok not found leto_GetAppOptions not found hb_DiskSpace UDF_AppendRec - found Press any key to finish... [/pre2]

SergKis: Pasha Не очень понимаю режим с EnableUDF = 0 Для меня важно, что бы удаленный "продвинутый" user не смог через вызов leto_udf("...") сломать инфу сервера (сборку всех серверов не проконтролируешь на request функций), т.е. leto_ferase, leto_fRename, leto_drop, leto_memowrit,leto_FileWrite, leto_dirremove, Leto_FileAttr, ... dbCreate, fErase, fRename, fCreate, hb_memowrit, StrFile, hb_DirBase, hb_progname, exename, ... leto_getAppOptions( ... ), что дает доступ к путям, файлам настройки, паролей сервера может еще какие, сразу не вспомнишь. Все это, если надо можно организовать в hrb

Pasha: Из readme: EnableUDF = 1 - если 1 (по умолчанию), разрешено использование udf-функций с префиксом "UDF_", если 2, разрешено использование udf-функций с любыми именами, если 0, вызовы udf-функций запрещены; По умолчанию, при значении параметра 1, разрешены только вызовы функций с префиксом udf_, т.е. вызов UDF_AppendRec разрешен, а hb_DiskSpace, dbCreate и пр. - нет. При значении 2 разрешены вызовы всех функций. При значении 0 вызовы udf запрещены. Если хочется ограничить вызовы опасных функций, то пусть будет значение по умолчанию, в для hb_DiskSpace и пр. надо сделать обертки в letoudf.hrb: например udf_DiskSpace



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