12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394 |
- /*-
- * Copyright 2016 Vsevolod Stakhov
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #include "lua_common.h"
- #include "libmime/message.h"
- #include "libutil/expression.h"
- #include "libserver/composites.h"
- #include "libserver/cfg_file_private.h"
- #include "libmime/lang_detection.h"
- #include "lua/lua_map.h"
- #include "lua/lua_thread_pool.h"
- #include "utlist.h"
- #include <math.h>
-
- /***
- * This module is used to configure rspamd and is normally available as global
- * variable named `rspamd_config`. Unlike other modules, it is not necessary to
- * require it before usage.
- * @module rspamd_config
- * @example
- -- Register some callback symbol
- local function foo(task)
- -- do something
- end
- rspamd_config:register_symbol('SYMBOL', 1.0, foo)
-
- -- Get configuration
- local tab = rspamd_config:get_all_opt('module') -- get table for module's options
- local opts = rspamd_config:get_key('options') -- get content of the specified key in rspamd configuration
- */
-
- /* Config file methods */
- /***
- * @method rspamd_config:get_module_opt(mname, optname)
- * Returns value of specified option `optname` for a module `mname`,
- * @param {string} mname name of module
- * @param {string} optname option to get
- * @return {string or table} value of the option or `nil` if option is not found
- */
- LUA_FUNCTION_DEF (config, get_module_opt);
- /***
- * @method rspamd_config:get_all_opt(mname)
- * Returns value of all options for a module `mname`, flattening values into a single table consisting
- * of all sections with such a name.
- * @param {string} mname name of module
- * @return {table} table of all options for `mname` or `nil` if a module's configuration is not found
- */
- LUA_FUNCTION_DEF (config, get_all_opt);
-
- /***
- * @method rspamd_config:get_ucl()
- * Returns full configuration as a native Lua object (ucl to lua conversion).
- * This method uses caching if possible.
- * @return {table} table of all options in the configuration
- */
- LUA_FUNCTION_DEF (config, get_ucl);
- /***
- * @method rspamd_config:get_mempool()
- * Returns static configuration memory pool.
- * @return {mempool} [memory pool](mempool.md) object
- */
- LUA_FUNCTION_DEF (config, get_mempool);
- /***
- * @method rspamd_config:get_resolver()
- * Returns DNS resolver.
- * @return {dns_resolver} opaque DNS resolver pointer if any
- */
- LUA_FUNCTION_DEF (config, get_resolver);
- /***
- * @method rspamd_config:add_radix_map(mapline[, description])
- * Creates new dynamic map of IP/mask addresses.
- * @param {string} mapline URL for a map
- * @param {string} description optional map description
- * @return {map} radix tree object
- * @example
- local ip_map = rspamd_config:add_radix_map ('file:///path/to/file', 'my radix map')
- ...
- local function foo(task)
- local ip = task:get_from_ip()
- if ip_map:get_key(ip) then
- return true
- end
- return false
- end
- */
-
- /***
- * @method rspamd_config:radix_from_config(mname, optname)
- * Creates new embedded map of IP/mask addresses from config.
- * @param {string} mname name of module
- * @param {string} optname option to get
- * @return {map} radix tree object
- * @example
- local ip_map = rspamd_config:radix_from_config ('mymodule', 'ips')
- ...
- local function foo(task)
- local ip = task:get_from_ip()
- if ip_map:get_key(ip) then
- return true
- end
- return false
- end
- */
- /***
- * @method rspamd_config:radix_from_ucl(obj)
- * Creates new embedded map of IP/mask addresses from object.
- * @param {ucl} obj object
- * @return {map} radix tree object
- */
- /***
- * @method rspamd_config:add_hash_map(mapline[, description])
- * Creates new dynamic map string objects.
- * @param {string} mapline URL for a map
- * @param {string} description optional map description
- * @return {map} hash set object
- * @example
- local hash_map = rspamd_config:add_hash_map ('file:///path/to/file', 'my hash map')
- ...
- local function foo(task)
- local from = task:get_from()
- if hash_map:get_key(from['user']) then
- return true
- end
- return false
- end
- */
- /***
- * @method rspamd_config:add_kv_map(mapline[, description])
- * Creates new dynamic map of key/values associations.
- * @param {string} mapline URL for a map
- * @param {string} description optional map description
- * @return {map} hash table object
- * @example
- local kv_map = rspamd_config:add_kv_map ('file:///path/to/file', 'my kv map')
- ...
- local function foo(task)
- local from = task:get_from()
- if from then
- local value = kv_map:get_key(from['user'])
- if value then
- return true,value
- end
- end
- return false
- end
- */
- /***
- * @method rspamd_config:add_map({args})
- * Creates new dynamic map according to the attributes passed.
- *
- * - `type`: type of map to be created, can be one of the following set:
- * + `set`: set of strings
- * + `radix`: map of IP addresses to strings
- * + `map`: map of strings to strings
- * + `regexp`: map of regexps to strings
- * + `callback`: map processed by lua callback
- * - `url`: url to load map from
- * - `description`: map's description
- * - `callback`: lua callback for the map
- *
- * @return {map} `true` if map has been added
- * @example
-
- local str = ''
- local function process_map(in)
- str = in
- end
-
- rspamd_config:add_map('http://example.com/map', "settings map", process_map)
- */
- /***
- * @method rspamd_config:get_maps()
- * Get all maps defined as an array of rspamd{map} objects
- *
- * @return {table|rspamd{map}}
- */
- /***
- * @method rspamd_config:get_classifier(name)
- * Returns classifier config.
- * @param {string} name name of classifier (e.g. `bayes`)
- * @return {classifier} classifier object or `nil`
- */
- LUA_FUNCTION_DEF (config, get_classifier);
- /***
- * @method rspamd_config:register_symbol(table)
- * Register symbol of a specified type in rspamd. This function accepts table of arguments:
- *
- * - `name`: name of symbol (can be missing for callback symbols)
- * - `callback`: function to be called for symbol's check (can be absent for virtual symbols)
- * - `weight`: weight of symbol (should normally be 1 or missing)
- * - `priority`: priority of symbol (normally 0 or missing)
- * - `type`: type of symbol: `normal` (default), `virtual` or `callback`
- * - `flags`: various flags split by commas or spaces:
- * + `nice` if symbol can produce negative score;
- * + `empty` if symbol can be called for empty messages
- * + `skip` if symbol should be skipped now
- * + `nostat` if symbol should be excluded from stat tokens
- * + `trivial` symbol is trivial (e.g. no network requests)
- * + `explicit_disable` requires explicit disabling (e.g. via settings)
- * + `ignore_passthrough` executed even if passthrough result has been set
- * - `parent`: id of parent symbol (useful for virtual symbols)
- *
- * @return {number} id of symbol registered
- */
- LUA_FUNCTION_DEF (config, register_symbol);
- /***
- * @method rspamd_config:register_symbols(callback, [weight], callback_name, [, symbol, ...])
- * Register callback function to be called for a set of symbols with initial weight.
- * @param {function} callback callback function to be called for a specified symbol
- * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
- * @param {string} callback_name symbolic name of callback
- * @param {list of strings} symbol list of symbols registered by this function
- */
- LUA_FUNCTION_DEF (config, register_symbols);
- /***
- * @method rspamd_config:register_virtual_symbol(name, weight,)
- * Register virtual symbol that is not associated with any callback.
- *
- * **This method is deprecated and should not be used in newly written code **
- * @param {string} virtual name symbol's name
- * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
- */
- LUA_FUNCTION_DEF (config, register_virtual_symbol);
- /***
- * @method rspamd_config:register_callback_symbol(name, weight, callback)
- * Register callback function to be called for a specified symbol with initial weight. Symbol itself is
- * not registered in the metric and is not intended to be visible by a user.
- *
- * **This method is deprecated and should not be used in newly written code **
- * @param {string} name symbol's name (just for unique id purposes)
- * @param {number} weight initial weight of symbol (can be less than zero to specify non-spam symbols)
- * @param {function} callback callback function to be called for a specified symbol
- */
- LUA_FUNCTION_DEF (config, register_callback_symbol);
- LUA_FUNCTION_DEF (config, register_callback_symbol_priority);
-
- /***
- * @method rspamd_config:register_dependency(id, dep)
- * Create a dependency between symbol identified by `id` and a symbol identified
- * by some symbolic name `dep`
- * @param {number|string} id id or name of source (numeric id is returned by all register_*_symbol)
- * @param {string} dep dependency name
- * @example
- local function cb(task)
- ...
- end
-
- local id = rspamd_config:register_symbol('SYM', 1.0, cb)
- rspamd_config:register_dependency(id, 'OTHER_SYM')
- -- Alternative form
- rspamd_config:register_dependency('SYMBOL_FROM', 'SYMBOL_TO')
- */
- LUA_FUNCTION_DEF (config, register_dependency);
-
- /***
- * @method rspamd_config:get_symbol_flags(name)
- * Returns symbol flags
- * @param {string} name symbols's name
- * @return {table|string} list of flags for symbol or nil
- */
- LUA_FUNCTION_DEF (config, get_symbol_flags);
-
- /***
- * @method rspamd_config:add_symbol_flags(name, flags)
- * Adds flags to a symbol
- * @param {string} name symbols's name
- * @param {table|string} flags flags to add
- * @return {table|string} new set of flags
- */
- LUA_FUNCTION_DEF (config, add_symbol_flags);
-
- /**
- * @method rspamd_config:register_re_selector(name, selector_str)
- * Registers selector with the specific name to use in regular expressions in form
- * name=/re/$ or name=/re/{selector}
- * @param {string} name name of the selector
- * @param {selector_str} selector string
- * @return true if selector has been registered
- */
- LUA_FUNCTION_DEF (config, register_re_selector);
-
- /**
- * @method rspamd_config:set_symbol({table})
- * Sets the value of a specified symbol in a metric. This function accepts table with the following elements:
- *
- * - `name`: name of symbol (string)
- * - `score`: score for symbol (number)
- * - `metric`: name of metric (string, optional)
- * - `description`: description of symbol (string, optional)
- * - `group`: name of group for symbol (string, optional)
- * - `one_shot`: turn off multiple hits for a symbol (boolean, optional)
- * - `one_param`: turn off multiple options for a symbol (boolean, optional)
- * - `flags`: comma separated string of flags:
- * + `ignore`: do not strictly check validity of symbol and corresponding rule
- * + `one_shot`: turn off multiple hits for a symbol
- * + `one_param`: allow only one parameter for a symbol
- * - `priority`: priority of symbol's definition
- */
- LUA_FUNCTION_DEF (config, set_metric_symbol);
-
- /**
- * @method rspamd_config:set_action({table})
- * Sets the score of a specified action in a metric. This function accepts table with the following elements:
- *
- * - `action`: name of action (string)
- * - `score`: score for action (number)
- * - `metric`: name of metric (string, optional)
- * - `priority`: priority of action's definition
- */
- LUA_FUNCTION_DEF (config, set_metric_action);
-
- /**
- * @method rspamd_config:get_symbol(name)
- * Gets metric data for a specific symbol identified by `name`:
- *
- * - `score`: score for symbol (number)
- * - `description`: description of symbol (string, optional)
- * - `group`: name of group for symbol (string, optional)
- * - `one_shot`: turn off multiple hits for a symbol (boolean, optional)
- * - `flags`: comma separated string of flags:
- * + `ignore`: do not strictly check validity of symbol and corresponding rule
- * + `one_shot`: turn off multiple hits for a symbol
- *
- * @param {string} name name of symbol
- * @return {table} symbol's definition or nil in case of undefined symbol
- */
- LUA_FUNCTION_DEF (config, get_metric_symbol);
-
- /**
- * @method rspamd_config:get_action(name)
- * Gets data for a specific action in config. This function returns number reperesenting action's score
- *
- * @param {string} name name of action
- * @return {number} action's score or nil in case of undefined score or action
- */
- LUA_FUNCTION_DEF (config, get_metric_action);
-
- /**
- * @method rspamd_config:get_all_actions()
- * Gets data for all action in config
- * @return {table|str->num} action's score or nil in case of undefined score or action
- */
- LUA_FUNCTION_DEF (config, get_all_actions);
-
- /**
- * @method rspamd_config:add_composite(name, expression)
- * @param {string} name name of composite symbol
- * @param {string} expression symbolic expression of the composite rule
- * @return {bool} true if a composite has been added successfully
- */
- LUA_FUNCTION_DEF (config, add_composite);
- /***
- * @method rspamd_config:register_pre_filter(callback[, order])
- * Register function to be called prior to symbols processing.
- * @param {function} callback callback function
- * @param {number} order filters are called from lower orders to higher orders, order is equal to 0 by default
- * @example
- local function check_function(task)
- -- It is possible to manipulate the task object here: set settings, set pre-action and so on
- ...
- end
-
- rspamd_config:register_pre_filter(check_function)
- */
- LUA_FUNCTION_DEF (config, register_pre_filter);
- /***
- * @method rspamd_config:register_post_filter(callback[, order])
- * Register function to be called after symbols are processed.
- *
- * @param {function} callback callback function
- * @param {number} order filters are called from lower orders to higher orders, order is equal to 0 by default
- */
- LUA_FUNCTION_DEF (config, register_post_filter);
- /* XXX: obsoleted */
- LUA_FUNCTION_DEF (config, register_module_option);
- /* XXX: not needed now */
- LUA_FUNCTION_DEF (config, get_api_version);
- /***
- * @method rspamd_config:get_key(name)
- * Returns configuration section with the specified `name`.
- * @param {string} name name of config section
- * @return {variant} specific value of section
- * @example
-
- local set_section = rspamd_config:get_key("settings")
- if type(set_section) == "string" then
- -- Just a map of ucl
- if rspamd_config:add_map(set_section, "settings map", process_settings_map) then
- rspamd_config:register_pre_filter(check_settings)
- end
- elseif type(set_section) == "table" then
- if process_settings_table(set_section) then
- rspamd_config:register_pre_filter(check_settings)
- end
- end
- */
- LUA_FUNCTION_DEF (config, get_key);
-
- /***
- * @method rspamd_config:add_condition(symbol, condition)
- * Adds condition callback for specified symbol
- * @param {string} symbol symbol's name
- * @param {function} condition condition callback
- * @return {boolean} true if condition has been added
- * @example
-
- rspamd_config:add_condition('FUZZY_DENIED', function(task)
- if some_map:find_key(task:get_from()) then return false end
- return true
- end)
- */
- LUA_FUNCTION_DEF (config, add_condition);
-
- /***
- * @method rspamd_config:enable_symbol(symbol)
- * Enables execution for the specified symbol
- * @param {string} symbol symbol's name
- */
- LUA_FUNCTION_DEF (config, enable_symbol);
-
- /***
- * @method rspamd_config:disable_symbol(symbol)
- * Disables execution for the specified symbol
- * @param {string} symbol symbol's name
- */
- LUA_FUNCTION_DEF (config, disable_symbol);
-
- /***
- * @method rspamd_config:get_symbol_parent(symbol)
- * Returns a parent symbol for specific symbol (or symbol itself if top level)
- * @param {string} symbol symbol's name
- */
- LUA_FUNCTION_DEF (config, get_symbol_parent);
-
- /***
- * @method rspamd_config:get_group_symbols(group)
- * Returns list of symbols for a specific group
- * @param {string} group group's name
- * @available 2.0+
- * @return {list|string} list of all symbols in a specific group
- */
- LUA_FUNCTION_DEF (config, get_group_symbols);
-
- /***
- * @method rspamd_config:register_settings_id(name, symbols_enabled, symbols_disabled)
- * Register new static settings id in config
- * @param {string} name id name (not numeric!)
- * @param {map|string->string} symbols_enabled map from symbol's name to boolean (currently)
- * @param {map|string->string} symbols_disabled map from symbol's name to boolean (currently)
- * @available 2.0+
- */
- LUA_FUNCTION_DEF (config, register_settings_id);
-
- /***
- * @method rspamd_config:__newindex(name, callback)
- * This metamethod is called if new indicies are added to the `rspamd_config` object.
- * Technically, it is the equivalent of @see rspamd_config:register_symbol where `weight` is 1.0.
- * There is also table form invocation that allows to control more things:
- *
- * - `callback`: has the same meaning and acts as function of task
- * - `score`: default score for a symbol
- * - `group`: default group for a symbol
- * - `description`: default symbol's description
- * - `priority`: additional priority value
- * - `one_shot`: default value for one shot attribute
- * - `condition`: function of task that can enable or disable this specific rule's execution
- * @param {string} name index name
- * @param {function/table} callback callback to be called
- * @return {number} id of the new symbol added
- * @example
- rspamd_config.R_EMPTY_IMAGE = function (task)
- parts = task:get_text_parts()
- if parts then
- for _,part in ipairs(parts) do
- if part:is_empty() then
- images = task:get_images()
- if images then
- -- Symbol `R_EMPTY_IMAGE` is inserted
- return true
- end
- return false
- end
- end
- end
- return false
- end
-
- rspamd_config.SYMBOL = {
- callback = function(task)
- ...
- end,
- score = 5.1,
- description = 'sample symbol',
- group = 'sample symbols',
- condition = function(task)
- if task:get_from()[1]['addr'] == 'user@example.com' then
- return false
- end
- return true
- end
- }
- */
- LUA_FUNCTION_DEF (config, newindex);
-
- /***
- * @method rspamd_config:register_regexp(params)
- * Registers new re for further cached usage
- * Params is the table with the following fields (mandatory fields are marked with `*`):
- * - `re`* : regular expression object
- * - `type`*: type of regular expression:
- * + `mime`: mime regexp
- * + `rawmime`: raw mime regexp
- * + `header`: header regexp
- * + `rawheader`: raw header expression
- * + `body`: raw body regexp
- * + `url`: url regexp
- * - `header`: for header and rawheader regexp means the name of header
- * - `pcre_only`: flag regexp as pcre only regexp
- */
- LUA_FUNCTION_DEF (config, register_regexp);
-
- /***
- * @method rspamd_config:replace_regexp(params)
- * Replaces regexp with a new one
- * Params is the table with the following fields (mandatory fields are marked with `*`):
- * - `old_re`* : old regular expression object (must be in the cache)
- * - `new_re`* : old regular expression object (must not be in the cache)
- */
- LUA_FUNCTION_DEF (config, replace_regexp);
-
- /***
- * @method rspamd_config:register_worker_script(worker_type, script)
- * Registers the following script for workers of a specified type. The exact type
- * of script function depends on worker type
- * @param {string} worker_type worker type (e.g. "normal")
- * @param {function} script script for a worker
- * @return {boolean} `true` if a script has been registered
- */
- LUA_FUNCTION_DEF (config, register_worker_script);
-
- /***
- * @method rspamd_config:add_on_load(function(cfg, ev_base, worker) ... end)
- * Registers the following script to be executed when configuration is completely loaded
- * and the worker is already started (forked)
- * @param {function} script function to be executed
- * @example
- rspamd_config:add_on_load(function(cfg, ev_base, worker)
- rspamd_config:add_periodic(ev_base, 1.0, function(cfg, ev_base)
- local logger = require "rspamd_logger"
- logger.infox(cfg, "periodic function in worker %s", worker:get_name())
- return true
- end)
- end)
- */
- LUA_FUNCTION_DEF (config, add_on_load);
-
- /***
- * @method rspamd_config:add_periodic(event_base, timeout, function(cfg, ev_base) ... end, [jitter = false])
- * Registers function to be periodically executed by Rspamd
- * @param {ev_base} event_base event base that is needed for async events
- * @param {number} timeout time in seconds (could be fractional)
- * @param {function} script function to be executed
- * @param {boolean} jitter `true` if timeout jittering is needed
- * @example
- rspamd_config:add_on_load(function(cfg, ev_base)
- rspamd_config:add_periodic(ev_base, 1.0, function(cfg, ev_base)
- local logger = require "rspamd_logger"
- logger.infox(cfg, "periodic function")
- return true -- if return false, then the periodic event is removed
- end)
- end)
- */
- LUA_FUNCTION_DEF (config, add_periodic);
-
- /***
- * @method rspamd_config:add_post_init(function(cfg) ... end)
- * Registers the following script to be executed when configuration is completely loaded
- * @available 2.0+
- * @param {function} script function to be executed
- */
- LUA_FUNCTION_DEF (config, add_post_init);
-
- /***
- * @method rspamd_config:add_config_unload(function(cfg) ... end)
- * Registers the following script to be executed when configuration is unloaded
- * @available 2.0+
- * @param {function} script function to be executed
- */
- LUA_FUNCTION_DEF (config, add_config_unload);
-
- /***
- * @method rspamd_config:get_symbols_count()
- * Returns number of symbols registered in rspamd configuration
- * @return {number} number of symbols registered in the configuration
- */
- LUA_FUNCTION_DEF (config, get_symbols_count);
-
- /***
- * @method rspamd_config:get_symbols_cksum()
- * Returns checksum for all symbols in the cache
- * @return {int64} boxed value of the 64 bit checksum
- */
- LUA_FUNCTION_DEF (config, get_symbols_cksum);
-
- /***
- * @method rspamd_config:get_symbols_counters()
- * Returns table of all counters in the cache (weights, frequencies etc)
- * @return {table|tables} all symbols indexed by name
- */
- LUA_FUNCTION_DEF (config, get_symbols_counters);
-
- /***
- * @method rspamd_config:get_symbols()
- * Returns table of all scores defined in config. From version 2.0 returns table:
- * - name
- * - score
- * - flags (e.g. `ignore` or `oneparam`)
- * - nshots (== maxhits)
- * - group - main group
- * - groups - array of all groups
- * @available 2.0+
- * @return {table|tables} all symbols indexed by name
- */
- LUA_FUNCTION_DEF (config, get_symbols);
-
- /***
- * @method rspamd_config:get_symbol_callback(name)
- * Returns callback function for the specified symbol if it is a lua registered callback
- * @return {function} callback function or nil
- */
- LUA_FUNCTION_DEF (config, get_symbol_callback);
-
- /***
- * @method rspamd_config:get_symbol_stat(name)
- * Returns table with statistics for a specific symbol:
- * - `frequency`: frequency for symbol's hits
- * - `stddev`: standard deviation of `frequency`
- * - `time`: average time in seconds (floating point)
- * - `count`: total number of hits
- * @return {table} symbol stats
- */
- LUA_FUNCTION_DEF (config, get_symbol_stat);
-
- /***
- * @method rspamd_config:set_symbol_callback(name, callback)
- * Sets callback for the specified symbol
- * @return {boolean} true if function has been replaced
- */
- LUA_FUNCTION_DEF (config, set_symbol_callback);
-
- /***
- * @method rspamd_config:register_finish_script(callback)
- * Adds new callback that is called on worker process termination when all
- * tasks pending are processed
- *
- * @param callback {function} a function with one argument (rspamd_task)
- */
- LUA_FUNCTION_DEF (config, register_finish_script);
-
- /***
- * @method rspamd_config:register_monitored(url, type, [{params}])
- * Registers monitored resource to watch its availability. Supported types:
- *
- * - `dns`: DNS monitored object
- *
- * Params are optional table specific for each type. For DNS it supports the
- * following options:
- *
- * - `prefix`: prefix to add before making request
- * - `type`: type of request (e.g. 'a' or 'txt')
- * - `ipnet`: array of ip/networks to expect on reply
- * - `rcode`: expected return code (e.g. `nxdomain`)
- *
- * Returned object has the following methods:
- *
- * - `alive`: returns `true` if monitored resource is alive
- * - `offline`: returns number of seconds of the current offline period (or 0 if alive)
- * - `total_offline`: returns number of seconds of the overall offline
- * - `latency`: returns the current average latency in seconds (or 0 if offline)
- *
- * @param {string} url resource to monitor
- * @param {string} type type of monitoring
- * @param {table} opts optional parameters
- * @return {rspamd_monitored} rspamd monitored object
- */
- LUA_FUNCTION_DEF (config, register_monitored);
-
- /***
- * @method rspamd_config:add_doc(path, option, doc_string, [{params}])
- * Adds new documentation string for an option `option` at path `path`
- * Options defines optional params, such as:
- *
- * - `default`: default option value
- * - `type`: type of an option (`string`, `number`, `object`, `array` etc)
- * - `reqired`: if an option is required
- *
- * @param {string} path documentation path (e.g. module name)
- * @param {string} option name of the option
- * @param {string} doc_string documentation string
- * @param {table} params optional parameters
- */
- LUA_FUNCTION_DEF (config, add_doc);
-
- /***
- * @method rspamd_config:add_example(path, option, doc_string, example)
- * Adds new documentation
- *
- * @param {string} path documentation path (e.g. module name or nil for top)
- * @param {string} option name of the option
- * @param {string} doc_string documentation string
- * @param {string} example example in ucl format, comments are also parsed
- */
- LUA_FUNCTION_DEF (config, add_example);
-
- /***
- * @method rspamd_config:set_peak_cb(function)
- * Sets a function that will be called when frequency of some symbol goes out of
- * stddev * 2 over the last period of refreshment.
- *
- * @example
- rspamd_config:set_peak_cb(function(ev_base, sym, mean, stddev, value, error)
- -- ev_base: event base for async events (e.g. redis)
- -- sym: symbol's name
- -- mean: mean frequency value
- -- stddev: standard deviation of frequency
- -- value: current frequency value
- -- error: squared error
- local logger = require "rspamd_logger"
- logger.infox(rspamd_config, "symbol %s has changed frequency significantly: %s(%s) over %s(%s)",
- sym, value, error, mean, stddev)
- end)
- */
- LUA_FUNCTION_DEF (config, set_peak_cb);
- /***
- * @method rspamd_config:get_cpu_flags()
- * Returns architecture dependent flags supported by the CPU
- * Currently, only x86 flags are supported:
- * - 'ssse3'
- * - 'sse42'
- * - 'avx'
- * - 'avx2'
- * @return {table} flag -> true table
- */
- LUA_FUNCTION_DEF (config, get_cpu_flags);
-
- /***
- * @method rspamd_config:has_torch()
- * Returns true if Rspamd is compiled with torch support and the runtime CPU
- * supports sse4.2 required for torch.
- * @return {boolean} true if torch is compiled and supported
- */
- LUA_FUNCTION_DEF (config, has_torch);
-
- /***
- * @method rspamd_config:experimental_enabled()
- * Returns true if experimental plugins are enabled
- * @return {boolean} true if experimental plugins are enabled
- */
- LUA_FUNCTION_DEF (config, experimental_enabled);
-
- /***
- * @method rspamd_config:load_ucl(filename[, include_trace])
- * Loads config from the UCL file (but does not perform parsing using rcl)
- * @param {string} filename file to load
- * @return true or false + error message
- */
- LUA_FUNCTION_DEF (config, load_ucl);
-
- /***
- * @method rspamd_config:parse_rcl([skip_sections])
- * Parses RCL using loaded ucl file
- * @param {table|string} sections to skip
- * @return true or false + error message
- */
- LUA_FUNCTION_DEF (config, parse_rcl);
-
- /***
- * @method rspamd_config:init_modules()
- * Initialize lua and internal modules
- * @return true or false
- */
- LUA_FUNCTION_DEF (config, init_modules);
-
- /***
- * @method rspamd_config:init_subsystem(str)
- * Initialize config subsystem from a comma separated list:
- * - `modules` - init modules
- * - `langdet` - language detector
- * - `dns` - DNS resolver
- * - TODO: add more
- */
- LUA_FUNCTION_DEF (config, init_subsystem);
-
- /***
- * @method rspamd_config:get_tld_path()
- * Returns path to TLD file
- * @return {string} path to tld file
- */
- LUA_FUNCTION_DEF (config, get_tld_path);
-
- static const struct luaL_reg configlib_m[] = {
- LUA_INTERFACE_DEF (config, get_module_opt),
- LUA_INTERFACE_DEF (config, get_mempool),
- LUA_INTERFACE_DEF (config, get_resolver),
- LUA_INTERFACE_DEF (config, get_all_opt),
- LUA_INTERFACE_DEF (config, get_ucl),
- LUA_INTERFACE_DEF (config, add_radix_map),
- LUA_INTERFACE_DEF (config, radix_from_config),
- LUA_INTERFACE_DEF (config, radix_from_ucl),
- LUA_INTERFACE_DEF (config, add_hash_map),
- LUA_INTERFACE_DEF (config, add_kv_map),
- LUA_INTERFACE_DEF (config, add_map),
- LUA_INTERFACE_DEF (config, get_maps),
- LUA_INTERFACE_DEF (config, get_classifier),
- LUA_INTERFACE_DEF (config, register_symbol),
- LUA_INTERFACE_DEF (config, register_symbols),
- LUA_INTERFACE_DEF (config, register_virtual_symbol),
- LUA_INTERFACE_DEF (config, register_callback_symbol),
- LUA_INTERFACE_DEF (config, register_callback_symbol_priority),
- LUA_INTERFACE_DEF (config, register_dependency),
- LUA_INTERFACE_DEF (config, register_settings_id),
- LUA_INTERFACE_DEF (config, get_symbol_flags),
- LUA_INTERFACE_DEF (config, add_symbol_flags),
- LUA_INTERFACE_DEF (config, set_metric_symbol),
- {"set_symbol", lua_config_set_metric_symbol},
- LUA_INTERFACE_DEF (config, set_metric_action),
- {"set_action", lua_config_set_metric_action},
- LUA_INTERFACE_DEF (config, get_metric_symbol),
- {"get_symbol", lua_config_get_metric_symbol},
- LUA_INTERFACE_DEF (config, get_metric_action),
- {"get_action", lua_config_get_metric_action},
- LUA_INTERFACE_DEF (config, get_all_actions),
- LUA_INTERFACE_DEF (config, add_composite),
- LUA_INTERFACE_DEF (config, register_module_option),
- LUA_INTERFACE_DEF (config, register_pre_filter),
- LUA_INTERFACE_DEF (config, register_post_filter),
- LUA_INTERFACE_DEF (config, get_api_version),
- LUA_INTERFACE_DEF (config, get_key),
- LUA_INTERFACE_DEF (config, add_condition),
- LUA_INTERFACE_DEF (config, enable_symbol),
- LUA_INTERFACE_DEF (config, disable_symbol),
- LUA_INTERFACE_DEF (config, register_regexp),
- LUA_INTERFACE_DEF (config, replace_regexp),
- LUA_INTERFACE_DEF (config, register_worker_script),
- LUA_INTERFACE_DEF (config, register_re_selector),
- LUA_INTERFACE_DEF (config, add_on_load),
- LUA_INTERFACE_DEF (config, add_periodic),
- LUA_INTERFACE_DEF (config, add_post_init),
- LUA_INTERFACE_DEF (config, add_config_unload),
- LUA_INTERFACE_DEF (config, get_symbols_count),
- LUA_INTERFACE_DEF (config, get_symbols_cksum),
- LUA_INTERFACE_DEF (config, get_symbols_counters),
- {"get_symbols_scores", lua_config_get_symbols},
- LUA_INTERFACE_DEF (config, get_symbols),
- LUA_INTERFACE_DEF (config, get_symbol_callback),
- LUA_INTERFACE_DEF (config, set_symbol_callback),
- LUA_INTERFACE_DEF (config, get_symbol_stat),
- LUA_INTERFACE_DEF (config, get_symbol_parent),
- LUA_INTERFACE_DEF (config, get_group_symbols),
- LUA_INTERFACE_DEF (config, register_finish_script),
- LUA_INTERFACE_DEF (config, register_monitored),
- LUA_INTERFACE_DEF (config, add_doc),
- LUA_INTERFACE_DEF (config, add_example),
- LUA_INTERFACE_DEF (config, set_peak_cb),
- LUA_INTERFACE_DEF (config, get_cpu_flags),
- LUA_INTERFACE_DEF (config, has_torch),
- LUA_INTERFACE_DEF (config, experimental_enabled),
- LUA_INTERFACE_DEF (config, load_ucl),
- LUA_INTERFACE_DEF (config, parse_rcl),
- LUA_INTERFACE_DEF (config, init_modules),
- LUA_INTERFACE_DEF (config, init_subsystem),
- LUA_INTERFACE_DEF (config, get_tld_path),
- {"__tostring", rspamd_lua_class_tostring},
- {"__newindex", lua_config_newindex},
- {NULL, NULL}
- };
-
- LUA_FUNCTION_DEF (monitored, alive);
- LUA_FUNCTION_DEF (monitored, latency);
- LUA_FUNCTION_DEF (monitored, offline);
- LUA_FUNCTION_DEF (monitored, total_offline);
-
- static const struct luaL_reg monitoredlib_m[] = {
- LUA_INTERFACE_DEF (monitored, alive),
- LUA_INTERFACE_DEF (monitored, latency),
- LUA_INTERFACE_DEF (monitored, offline),
- LUA_INTERFACE_DEF (monitored, total_offline),
- {"__tostring", rspamd_lua_class_tostring},
- {NULL, NULL}
- };
-
- static const guint64 rspamd_lua_callback_magic = 0x32c118af1e3263c7ULL;
-
- struct rspamd_config *
- lua_check_config (lua_State * L, gint pos)
- {
- void *ud = rspamd_lua_check_udata (L, pos, "rspamd{config}");
- luaL_argcheck (L, ud != NULL, pos, "'config' expected");
- return ud ? *((struct rspamd_config **)ud) : NULL;
- }
-
- static struct rspamd_monitored *
- lua_check_monitored (lua_State * L, gint pos)
- {
- void *ud = rspamd_lua_check_udata (L, pos, "rspamd{monitored}");
- luaL_argcheck (L, ud != NULL, pos, "'monitored' expected");
- return ud ? *((struct rspamd_monitored **)ud) : NULL;
- }
-
- /*** Config functions ***/
- static gint
- lua_config_get_api_version (lua_State *L)
- {
- msg_warn ("get_api_version is deprecated, do not use it");
- lua_pushnumber (L, 100);
-
- return 1;
- }
-
- static gint
- lua_config_get_module_opt (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *mname, *optname;
- const ucl_object_t *obj;
-
- if (cfg) {
- mname = luaL_checkstring (L, 2);
- optname = luaL_checkstring (L, 3);
-
- if (mname && optname) {
- obj = rspamd_config_get_module_opt (cfg, mname, optname);
- if (obj) {
- return ucl_object_push_lua (L, obj, TRUE);
- }
- }
- }
- lua_pushnil (L);
- return 1;
- }
-
- static int
- lua_config_get_mempool (lua_State * L)
- {
- LUA_TRACE_POINT;
- rspamd_mempool_t **ppool;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL) {
- ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *));
- rspamd_lua_setclass (L, "rspamd{mempool}", -1);
- *ppool = cfg->cfg_pool;
- }
- else {
- lua_pushnil (L);
- }
- return 1;
- }
-
- static int
- lua_config_get_resolver (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_dns_resolver **pres;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL && cfg->dns_resolver) {
- pres = lua_newuserdata (L, sizeof (*pres));
- rspamd_lua_setclass (L, "rspamd{resolver}", -1);
- *pres = cfg->dns_resolver;
- }
- else {
- lua_pushnil (L);
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_all_opt (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *mname;
- const ucl_object_t *obj, *cur, *cur_elt;
- ucl_object_iter_t it = NULL;
- gint i;
-
- if (cfg) {
- mname = luaL_checkstring (L, 2);
-
- if (mname) {
- obj = ucl_obj_get_key (cfg->rcl_obj, mname);
- /* Flatten object */
- if (obj != NULL && (ucl_object_type (obj) == UCL_OBJECT ||
- ucl_object_type (obj) == UCL_ARRAY)) {
-
- lua_newtable (L);
- it = ucl_object_iterate_new (obj);
-
- LL_FOREACH (obj, cur) {
- it = ucl_object_iterate_reset (it, cur);
-
- while ((cur_elt = ucl_object_iterate_safe (it, true))) {
- lua_pushstring (L, ucl_object_key (cur_elt));
- ucl_object_push_lua (L, cur_elt, true);
- lua_settable (L, -3);
- }
- }
-
- ucl_object_iterate_free (it);
-
- return 1;
- }
- else if (obj != NULL) {
- lua_newtable (L);
- i = 1;
-
- LL_FOREACH (obj, cur) {
- lua_pushinteger (L, i++);
- ucl_object_push_lua (L, cur, true);
- lua_settable (L, -3);
- }
-
- return 1;
- }
- }
- }
- lua_pushnil (L);
-
- return 1;
- }
-
- struct rspamd_lua_cached_config {
- lua_State *L;
- gint ref;
- };
-
- static void
- lua_config_ucl_dtor (gpointer p)
- {
- struct rspamd_lua_cached_config *cached = p;
-
- luaL_unref (cached->L, LUA_REGISTRYINDEX, cached->ref);
- }
-
- static gint
- lua_config_get_ucl (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_lua_cached_config *cached;
-
- if (cfg) {
- cached = rspamd_mempool_get_variable (cfg->cfg_pool, "ucl_cached");
-
- if (cached) {
- lua_rawgeti (L, LUA_REGISTRYINDEX, cached->ref);
- }
- else {
- ucl_object_push_lua (L, cfg->rcl_obj, true);
- lua_pushvalue (L, -1);
- cached = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (*cached));
- cached->L = L;
- cached->ref = luaL_ref (L, LUA_REGISTRYINDEX);
- rspamd_mempool_set_variable (cfg->cfg_pool, "ucl_cached",
- cached, lua_config_ucl_dtor);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
-
- static gint
- lua_config_get_classifier (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_classifier_config *clc = NULL, **pclc = NULL;
- const gchar *name;
- GList *cur;
-
- if (cfg) {
- name = luaL_checkstring (L, 2);
-
- cur = g_list_first (cfg->classifiers);
- while (cur) {
- clc = cur->data;
- if (g_ascii_strcasecmp (clc->name, name) == 0) {
- pclc = &clc;
- break;
- }
- cur = g_list_next (cur);
- }
- if (pclc) {
- pclc = lua_newuserdata (L,
- sizeof (struct rspamd_classifier_config *));
- rspamd_lua_setclass (L, "rspamd{classifier}", -1);
- *pclc = clc;
- return 1;
- }
- }
-
- lua_pushnil (L);
- return 1;
-
- }
-
- struct lua_callback_data {
- guint64 magic;
- lua_State *L;
- gchar *symbol;
-
- union {
- gchar *name;
- gint ref;
- } callback;
- gboolean cb_is_ref;
-
- /* Dynamic data */
- gint stack_level;
- gint order;
- struct rspamd_symcache_item *item;
- };
-
- /*
- * Unref symbol if it is local reference
- */
- static void
- lua_destroy_cfg_symbol (gpointer ud)
- {
- struct lua_callback_data *cd = ud;
-
- /* Unref callback */
- if (cd->cb_is_ref) {
- luaL_unref (cd->L, LUA_REGISTRYINDEX, cd->callback.ref);
- }
- }
-
- static gint
- lua_config_register_module_option (lua_State *L)
- {
- return 0;
- }
-
- static gint
- rspamd_compare_order_func (gconstpointer a, gconstpointer b)
- {
- const struct lua_callback_data *cb1 = a, *cb2 = b;
-
- /* order of call goes from lower to higher */
- return cb2->order - cb1->order;
- }
-
- static void
- lua_metric_symbol_callback (struct rspamd_task *task,
- struct rspamd_symcache_item *item,
- gpointer ud)
- {
- struct lua_callback_data *cd = ud;
- struct rspamd_task **ptask;
- gint level = lua_gettop (cd->L), nresults, err_idx, ret;
- lua_State *L = cd->L;
- struct rspamd_symbol_result *s;
-
- cd->item = item;
- rspamd_symcache_item_async_inc (task, item, "lua symbol");
- lua_pushcfunction (L, &rspamd_lua_traceback);
- err_idx = lua_gettop (L);
-
- level ++;
-
- if (cd->cb_is_ref) {
- lua_rawgeti (L, LUA_REGISTRYINDEX, cd->callback.ref);
- }
- else {
- lua_getglobal (L, cd->callback.name);
- }
-
- ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
- rspamd_lua_setclass (L, "rspamd{task}", -1);
- *ptask = task;
-
- if ((ret = lua_pcall (L, 1, LUA_MULTRET, err_idx)) != 0) {
- msg_err_task ("call to (%s) failed (%d): %s", cd->symbol, ret,
- lua_tostring (L, -1));
- lua_settop (L, err_idx); /* Not -1 here, as err_func is popped below */
- }
- else {
- nresults = lua_gettop (L) - level;
-
- if (nresults >= 1) {
- /* Function returned boolean, so maybe we need to insert result? */
- gint res = 0;
- gint i;
- gdouble flag = 1.0;
- gint type;
-
- type = lua_type (cd->L, level + 1);
-
- if (type == LUA_TBOOLEAN) {
- res = lua_toboolean (L, level + 1);
- }
- else if (type == LUA_TNUMBER) {
- res = lua_tonumber (L, level + 1);
- }
- else if (type == LUA_TNIL) {
- /* Can happen sometimes... */
- res = FALSE;
- }
- else {
- g_assert_not_reached ();
- }
-
- if (res) {
- gint first_opt = 2;
-
- if (lua_type (L, level + 2) == LUA_TNUMBER) {
- flag = lua_tonumber (L, level + 2);
- /* Shift opt index */
- first_opt = 3;
- }
- else {
- flag = res;
- }
-
- s = rspamd_task_insert_result (task, cd->symbol, flag, NULL);
-
- if (s) {
- guint last_pos = lua_gettop (L);
-
- for (i = level + first_opt; i <= last_pos; i++) {
- if (lua_type (L, i) == LUA_TSTRING) {
- const char *opt = lua_tostring (L, i);
-
- rspamd_task_add_result_option (task, s, opt);
- }
- else if (lua_type (L, i) == LUA_TTABLE) {
- lua_pushvalue (L, i);
-
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- const char *opt = lua_tostring (L, -1);
-
- rspamd_task_add_result_option (task, s, opt);
- }
-
- lua_pop (L, 1);
- }
- }
- }
-
- }
-
- lua_pop (L, nresults);
- }
- }
-
- lua_pop (L, 1); /* Error function */
- rspamd_symcache_item_async_dec_check (task, cd->item, "lua symbol");
- g_assert (lua_gettop (L) == level - 1);
- }
-
- static void lua_metric_symbol_callback_return (struct thread_entry *thread_entry,
- int ret);
-
- static void lua_metric_symbol_callback_error (struct thread_entry *thread_entry,
- int ret,
- const char *msg);
-
- static void
- lua_metric_symbol_callback_coro (struct rspamd_task *task,
- struct rspamd_symcache_item *item,
- gpointer ud)
- {
- struct lua_callback_data *cd = ud;
- struct rspamd_task **ptask;
- struct thread_entry *thread_entry;
-
- rspamd_symcache_item_async_inc (task, item, "lua coro symbol");
- thread_entry = lua_thread_pool_get_for_task (task);
-
- g_assert(thread_entry->cd == NULL);
- thread_entry->cd = cd;
-
- lua_State *thread = thread_entry->lua_state;
- cd->stack_level = lua_gettop (thread);
- cd->item = item;
-
- if (cd->cb_is_ref) {
- lua_rawgeti (thread, LUA_REGISTRYINDEX, cd->callback.ref);
- }
- else {
- lua_getglobal (thread, cd->callback.name);
- }
-
- ptask = lua_newuserdata (thread, sizeof (struct rspamd_task *));
- rspamd_lua_setclass (thread, "rspamd{task}", -1);
- *ptask = task;
-
- thread_entry->finish_callback = lua_metric_symbol_callback_return;
- thread_entry->error_callback = lua_metric_symbol_callback_error;
-
- lua_thread_call (thread_entry, 1);
- }
-
- static void
- lua_metric_symbol_callback_error (struct thread_entry *thread_entry,
- int ret,
- const char *msg)
- {
- struct lua_callback_data *cd = thread_entry->cd;
- struct rspamd_task *task = thread_entry->task;
- msg_err_task ("call to coroutine (%s) failed (%d): %s", cd->symbol, ret, msg);
-
- rspamd_symcache_item_async_dec_check (task, cd->item, "lua coro symbol");
- }
-
- static void
- lua_metric_symbol_callback_return (struct thread_entry *thread_entry, int ret)
- {
- struct lua_callback_data *cd = thread_entry->cd;
- struct rspamd_task *task = thread_entry->task;
- int nresults;
- struct rspamd_symbol_result *s;
-
- (void)ret;
-
- lua_State *L = thread_entry->lua_state;
-
- nresults = lua_gettop (L) - cd->stack_level;
-
- if (nresults >= 1) {
- /* Function returned boolean, so maybe we need to insert result? */
- gint res = 0;
- gint i;
- gdouble flag = 1.0;
- gint type;
-
- type = lua_type (L, cd->stack_level + 1);
-
- if (type == LUA_TBOOLEAN) {
- res = lua_toboolean (L, cd->stack_level + 1);
- }
- else if (type == LUA_TFUNCTION) {
- g_assert_not_reached ();
- }
- else {
- res = lua_tonumber (L, cd->stack_level + 1);
- }
-
- if (res) {
- gint first_opt = 2;
-
- if (lua_type (L, cd->stack_level + 2) == LUA_TNUMBER) {
- flag = lua_tonumber (L, cd->stack_level + 2);
- /* Shift opt index */
- first_opt = 3;
- }
- else {
- flag = res;
- }
-
- s = rspamd_task_insert_result (task, cd->symbol, flag, NULL);
-
- if (s) {
- guint last_pos = lua_gettop (L);
-
- for (i = cd->stack_level + first_opt; i <= last_pos; i++) {
- if (lua_type (L, i) == LUA_TSTRING) {
- const char *opt = lua_tostring (L, i);
-
- rspamd_task_add_result_option (task, s, opt);
- }
- else if (lua_type (L, i) == LUA_TTABLE) {
- lua_pushvalue (L, i);
-
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- const char *opt = lua_tostring (L, -1);
-
- rspamd_task_add_result_option (task, s, opt);
- }
-
- lua_pop (L, 1);
- }
- }
- }
-
- }
-
- lua_pop (L, nresults);
- }
-
- g_assert (lua_gettop (L) == cd->stack_level); /* we properly cleaned up the stack */
-
- cd->stack_level = 0;
- rspamd_symcache_item_async_dec_check (task, cd->item, "lua coro symbol");
- }
-
- static guint32*
- rspamd_process_id_list (const gchar *entries, guint32 *plen)
- {
- gchar **sym_elts;
- guint32 *ids, nids;
-
- sym_elts = g_strsplit_set (entries, ",;", -1);
- nids = g_strv_length (sym_elts);
-
- ids = g_malloc (nids * sizeof (guint32));
-
- for (guint i = 0; i < nids; i ++) {
- ids[i] = rspamd_config_name_to_id (sym_elts[i], strlen (sym_elts[i]));
- }
-
- *plen = nids;
- g_strfreev (sym_elts);
-
- return ids;
- }
-
- static gint
- rspamd_register_symbol_fromlua (lua_State *L,
- struct rspamd_config *cfg,
- const gchar *name,
- gint ref,
- gdouble weight,
- gint priority,
- enum rspamd_symbol_type type,
- gint parent,
- const gchar *allowed_ids,
- const gchar *forbidden_ids,
- gboolean optional)
- {
- struct lua_callback_data *cd;
- gint ret = -1;
- guint32 *ids, nids;
-
- if (priority == 0 && weight < 0) {
- priority = 1;
- }
-
- if ((ret = rspamd_symcache_find_symbol (cfg->cache, name)) != -1) {
- if (optional) {
- msg_debug_config ("duplicate symbol: %s, skip registering", name);
-
- return ret;
- }
- else {
- msg_err_config ("duplicate symbol: %s, skip registering", name);
-
- return -1;
- }
- }
-
- if (allowed_ids && !(type & SYMBOL_TYPE_EXPLICIT_DISABLE)) {
- /* Mark symbol as explicit allow */
- msg_info_config ("mark symbol %s as explicit enable as its execution is"
- "allowed merely on specific settings ids", name);
- type |= SYMBOL_TYPE_EXPLICIT_ENABLE;
- }
-
- if (ref != -1) {
- cd = rspamd_mempool_alloc0 (cfg->cfg_pool,
- sizeof (struct lua_callback_data));
- cd->magic = rspamd_lua_callback_magic;
- cd->cb_is_ref = TRUE;
- cd->callback.ref = ref;
- cd->L = L;
-
- if (name) {
- cd->symbol = rspamd_mempool_strdup (cfg->cfg_pool, name);
- }
-
- if (type & SYMBOL_TYPE_USE_CORO) {
- ret = rspamd_symcache_add_symbol (cfg->cache,
- name,
- priority,
- lua_metric_symbol_callback_coro,
- cd,
- type,
- parent);
- }
- else {
- ret = rspamd_symcache_add_symbol (cfg->cache,
- name,
- priority,
- lua_metric_symbol_callback,
- cd,
- type,
- parent);
- }
- rspamd_mempool_add_destructor (cfg->cfg_pool,
- (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol,
- cd);
- }
- else {
- /* No callback */
- ret = rspamd_symcache_add_symbol (cfg->cache,
- name,
- priority,
- NULL,
- NULL,
- type,
- parent);
- }
-
- if (allowed_ids) {
- ids = rspamd_process_id_list (allowed_ids, &nids);
-
- if (nids > 0) {
- GString *dbg = g_string_new ("");
-
- for (guint i = 0; i < nids; i ++) {
- rspamd_printf_gstring (dbg, "%ud,", ids[i]);
- }
-
- dbg->len --;
-
- msg_debug_config ("allowed ids for %s are: %v", name, dbg);
- g_string_free (dbg, TRUE);
-
- rspamd_symcache_set_allowed_settings_ids (cfg->cache, name,
- ids, nids);
-
- g_free (ids);
- }
- }
-
- if (forbidden_ids) {
- ids = rspamd_process_id_list (forbidden_ids, &nids);
-
- if (nids > 0) {
- GString *dbg = g_string_new ("");
-
- for (guint i = 0; i < nids; i ++) {
- rspamd_printf_gstring (dbg, "%ud,", ids[i]);
- }
-
- dbg->len --;
-
- msg_debug_config ("forbidden ids for %s are: %v", name, dbg);
- g_string_free (dbg, TRUE);
-
- rspamd_symcache_set_forbidden_settings_ids (cfg->cache, name,
- ids, nids);
-
- g_free (ids);
- }
- }
-
- return ret;
- }
-
- static gint
- lua_config_register_post_filter (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- gint order = 0, cbref, ret;
-
- if (cfg) {
- if (lua_type (L, 3) == LUA_TNUMBER) {
- order = lua_tonumber (L, 3);
- }
-
- if (lua_type (L, 2) == LUA_TFUNCTION) {
- lua_pushvalue (L, 2);
- /* Get a reference */
- cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- }
- else {
- return luaL_error (L, "invalid type for callback: %s",
- lua_typename (L, lua_type (L, 2)));
- }
-
- msg_warn_config ("register_post_filter function is deprecated, "
- "use register_symbol instead");
-
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- NULL,
- cbref,
- 1.0,
- order,
- SYMBOL_TYPE_POSTFILTER|SYMBOL_TYPE_CALLBACK,
- -1,
- NULL, NULL,
- FALSE);
-
- lua_pushboolean (L, ret);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_register_pre_filter (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- gint order = 0, cbref, ret;
-
- if (cfg) {
- if (lua_type (L, 3) == LUA_TNUMBER) {
- order = lua_tonumber (L, 3);
- }
-
- if (lua_type (L, 2) == LUA_TFUNCTION) {
- lua_pushvalue (L, 2);
- /* Get a reference */
- cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- }
- else {
- return luaL_error (L, "invalid type for callback: %s",
- lua_typename (L, lua_type (L, 2)));
- }
-
- msg_warn_config ("register_pre_filter function is deprecated, "
- "use register_symbol instead");
-
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- NULL,
- cbref,
- 1.0,
- order,
- SYMBOL_TYPE_PREFILTER|SYMBOL_TYPE_CALLBACK,
- -1,
- NULL, NULL,
- FALSE);
-
- lua_pushboolean (L, ret);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_key (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name;
- size_t namelen;
- const ucl_object_t *val;
-
- name = luaL_checklstring(L, 2, &namelen);
- if (name && cfg) {
- val = ucl_object_lookup_len(cfg->rcl_obj, name, namelen);
- if (val != NULL) {
- ucl_object_push_lua (L, val, val->type != UCL_ARRAY);
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static guint
- lua_parse_symbol_flags (const gchar *str)
- {
- guint ret = 0;
-
- if (str) {
- if (strstr (str, "fine") != NULL) {
- ret |= SYMBOL_TYPE_FINE;
- }
- if (strstr (str, "nice") != NULL) {
- ret |= SYMBOL_TYPE_FINE;
- }
- if (strstr (str, "empty") != NULL) {
- ret |= SYMBOL_TYPE_EMPTY;
- }
- if (strstr (str, "skip") != NULL) {
- ret |= SYMBOL_TYPE_SKIPPED;
- }
- if (strstr (str, "nostat") != NULL) {
- ret |= SYMBOL_TYPE_NOSTAT;
- }
- if (strstr (str, "idempotent") != NULL) {
- ret |= SYMBOL_TYPE_IDEMPOTENT;
- }
- if (strstr (str, "trivial") != NULL) {
- ret |= SYMBOL_TYPE_TRIVIAL;
- }
- if (strstr (str, "ghost") != NULL) {
- ret |= SYMBOL_TYPE_GHOST;
- }
- if (strstr (str, "mime") != NULL) {
- ret |= SYMBOL_TYPE_MIME_ONLY;
- }
- if (strstr (str, "ignore_passthrough") != NULL) {
- ret |= SYMBOL_TYPE_IGNORE_PASSTHROUGH;
- }
- if (strstr (str, "explicit_disable") != NULL) {
- ret |= SYMBOL_TYPE_EXPLICIT_DISABLE;
- }
- if (strstr (str, "explicit_enable") != NULL) {
- ret |= SYMBOL_TYPE_EXPLICIT_ENABLE;
- }
- if (strstr (str, "coro") != NULL) {
- ret |= SYMBOL_TYPE_USE_CORO;
- }
- }
-
- return ret;
- }
-
- static guint
- lua_parse_symbol_type (const gchar *str)
- {
- guint ret = SYMBOL_TYPE_NORMAL;
- gchar **vec;
- guint i, l;
-
- if (str) {
- vec = g_strsplit_set (str, ",;", -1);
-
- if (vec) {
- l = g_strv_length (vec);
-
- for (i = 0; i < l; i ++) {
- str = vec[i];
-
- if (g_ascii_strcasecmp (str, "virtual") == 0) {
- ret = SYMBOL_TYPE_VIRTUAL;
- } else if (g_ascii_strcasecmp (str, "callback") == 0) {
- ret = SYMBOL_TYPE_CALLBACK;
- } else if (g_ascii_strcasecmp (str, "normal") == 0) {
- ret = SYMBOL_TYPE_NORMAL;
- } else if (g_ascii_strcasecmp (str, "prefilter") == 0) {
- ret = SYMBOL_TYPE_PREFILTER | SYMBOL_TYPE_GHOST;
- } else if (g_ascii_strcasecmp (str, "postfilter") == 0) {
- ret = SYMBOL_TYPE_POSTFILTER | SYMBOL_TYPE_GHOST;
- } else if (g_ascii_strcasecmp (str, "idempotent") == 0) {
- ret = SYMBOL_TYPE_POSTFILTER | SYMBOL_TYPE_GHOST |
- SYMBOL_TYPE_IDEMPOTENT;
- } else {
- gint fl = 0;
-
- fl = lua_parse_symbol_flags (str);
-
- if (fl == 0) {
- msg_warn ("bad type: %s", str);
- }
- else {
- ret |= fl;
- }
- }
- }
-
- g_strfreev (vec);
- }
- }
-
- return ret;
- }
-
- enum lua_push_symbol_flags_opts {
- LUA_SYMOPT_FLAG_CREATE_ARRAY = 1u << 0u,
- LUA_SYMOPT_FLAG_CREATE_MAP = 1u << 1u,
- LUA_SYMOPT_FLAG_USE_MAP = 1u << 2u,
- LUA_SYMOPT_FLAG_USE_ARRAY = 1u << 3u,
- };
-
- #define LUA_SYMOPT_IS_ARRAY(f) ((f) & (LUA_SYMOPT_FLAG_CREATE_ARRAY|LUA_SYMOPT_FLAG_USE_ARRAY))
- #define LUA_SYMOPT_IS_CREATE(f) ((f) & (LUA_SYMOPT_FLAG_CREATE_ARRAY|LUA_SYMOPT_FLAG_CREATE_MAP))
- #define LUA_OPTION_PUSH(nm) do { \
- if (LUA_SYMOPT_IS_ARRAY(fl)) { \
- lua_pushstring (L, #nm); \
- lua_rawseti (L, -2, i++); \
- } \
- else { \
- lua_pushboolean (L, true); \
- lua_setfield (L, -2, #nm); \
- } \
- } while(0)
-
- static void
- lua_push_symbol_flags (lua_State *L, guint flags, enum lua_push_symbol_flags_opts fl)
- {
- guint i = 1;
-
- if (LUA_SYMOPT_IS_CREATE (fl)) {
- lua_newtable (L);
- }
-
- if (flags & SYMBOL_TYPE_FINE) {
- LUA_OPTION_PUSH (fine);
- }
-
- if (flags & SYMBOL_TYPE_EMPTY) {
- LUA_OPTION_PUSH (empty);
- }
-
- if (flags & SYMBOL_TYPE_EXPLICIT_DISABLE) {
- LUA_OPTION_PUSH (explicit_disable);
- }
-
- if (flags & SYMBOL_TYPE_EXPLICIT_ENABLE) {
- LUA_OPTION_PUSH (explicit_enable);
- }
-
- if (flags & SYMBOL_TYPE_IGNORE_PASSTHROUGH) {
- LUA_OPTION_PUSH (ignore_passthrough);
- }
-
- if (flags & SYMBOL_TYPE_NOSTAT) {
- LUA_OPTION_PUSH (nostat);
- }
-
- if (flags & SYMBOL_TYPE_IDEMPOTENT) {
- LUA_OPTION_PUSH (idempotent);
- }
-
- if (flags & SYMBOL_TYPE_MIME_ONLY) {
- LUA_OPTION_PUSH (mime);
- }
-
- if (flags & SYMBOL_TYPE_TRIVIAL) {
- LUA_OPTION_PUSH (trivial);
- }
-
- if (flags & SYMBOL_TYPE_SKIPPED) {
- LUA_OPTION_PUSH (skip);
- }
- }
-
- static gint
- lua_config_get_symbol_flags (lua_State *L)
- {
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = luaL_checkstring (L, 2);
- guint flags;
-
- if (cfg && name) {
- flags = rspamd_symcache_get_symbol_flags (cfg->cache,
- name);
-
- if (flags != 0) {
- lua_push_symbol_flags (L, flags, LUA_SYMOPT_FLAG_CREATE_ARRAY);
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_add_symbol_flags (lua_State *L)
- {
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = luaL_checkstring (L, 2);
- guint flags, new_flags = 0;
-
- if (cfg && name && lua_istable (L, 3)) {
-
- for (lua_pushnil (L); lua_next (L, 3); lua_pop (L, 1)) {
- new_flags |= lua_parse_symbol_flags (lua_tostring (L, -1));
- }
-
- flags = rspamd_symcache_get_symbol_flags (cfg->cache,
- name);
-
- if (flags != 0) {
- rspamd_symcache_add_symbol_flags (cfg->cache, name, new_flags);
- /* Push old flags */
- lua_push_symbol_flags (L, flags, LUA_SYMOPT_FLAG_CREATE_ARRAY);
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_register_symbol (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = NULL, *flags_str = NULL, *type_str = NULL,
- *description = NULL, *group = NULL, *allowed_ids = NULL,
- *forbidden_ids = NULL;
- double weight = 0, score = NAN, parent_float = NAN;
- gboolean one_shot = FALSE;
- gint ret = -1, cbref = -1, type, flags = 0;
- gint64 parent = 0, priority = 0, nshots = 0;
- GError *err = NULL;
-
- if (cfg) {
- if (!rspamd_lua_parse_table_arguments (L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "name=S;weight=N;callback=F;flags=S;type=S;priority=I;parent=D;"
- "score=D;description=S;group=S;one_shot=B;nshots=I;"
- "allowed_ids=S;forbidden_ids=S",
- &name, &weight, &cbref, &flags_str, &type_str,
- &priority, &parent_float,
- &score, &description, &group, &one_shot, &nshots,
- &allowed_ids, &forbidden_ids)) {
- msg_err_config ("bad arguments: %e", err);
- g_error_free (err);
-
- return luaL_error (L, "invalid arguments");
- }
-
- if (nshots == 0) {
- nshots = cfg->default_max_shots;
- }
-
- type = lua_parse_symbol_type (type_str);
-
- if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
- return luaL_error (L, "no symbol name but type is not callback");
- }
- else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
- return luaL_error (L, "no callback for symbol %s", name);
- }
-
- if (flags_str) {
- type |= lua_parse_symbol_flags (flags_str);
- }
-
- if (isnan (parent_float)) {
- parent = -1;
- }
- else {
- parent = parent_float;
- }
-
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- name,
- cbref,
- weight == 0 ? 1.0 : weight,
- priority,
- type,
- parent,
- allowed_ids, forbidden_ids,
- FALSE);
-
- if (!isnan (score) || group) {
- if (one_shot) {
- nshots = 1;
- }
-
- if (!isnan (score)) {
- rspamd_config_add_symbol (cfg, name,
- score, description, group, flags,
- 0, nshots);
- }
- else {
- rspamd_config_add_symbol (cfg, name,
- 0.0, description, group, flags,
- 0, nshots);
- }
-
- lua_pushstring (L, "groups");
- lua_gettable (L, 2);
-
- if (lua_istable (L, -1)) {
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- if (lua_isstring (L, -1)) {
- rspamd_config_add_symbol_group (cfg, name,
- lua_tostring (L, -1));
- }
- else {
- return luaL_error (L, "invalid groups element");
- }
- }
- }
-
- lua_pop (L, 1);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- lua_pushinteger (L, ret);
-
- return 1;
- }
-
- static gint
- lua_config_register_symbols (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- gint i, top, idx, ret = -1;
- const gchar *sym;
- gdouble weight = 1.0;
-
- if (lua_gettop (L) < 3) {
- if (cfg) {
- msg_err_config ("not enough arguments to register a function");
- }
-
- lua_error (L);
-
- return 0;
- }
- if (cfg) {
- if (lua_type (L, 2) == LUA_TSTRING) {
- lua_getglobal (L, luaL_checkstring (L, 2));
- }
- else {
- lua_pushvalue (L, 2);
- }
- idx = luaL_ref (L, LUA_REGISTRYINDEX);
-
- if (lua_type (L, 3) == LUA_TNUMBER) {
- weight = lua_tonumber (L, 3);
- top = 4;
- }
- else {
- top = 3;
- }
- sym = luaL_checkstring (L, top ++);
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- sym,
- idx,
- weight,
- 0,
- SYMBOL_TYPE_CALLBACK,
- -1,
- NULL, NULL,
- FALSE);
-
- for (i = top; i <= lua_gettop (L); i++) {
- if (lua_type (L, i) == LUA_TTABLE) {
- lua_pushvalue (L, i);
- lua_pushnil (L);
- while (lua_next (L, -2)) {
- lua_pushvalue (L, -2);
- sym = luaL_checkstring (L, -2);
- rspamd_symcache_add_symbol (cfg->cache, sym,
- 0, NULL, NULL,
- SYMBOL_TYPE_VIRTUAL, ret);
- lua_pop (L, 2);
- }
- lua_pop (L, 1);
- }
- else if (lua_type (L, i) == LUA_TSTRING) {
- sym = luaL_checkstring (L, i);
- rspamd_symcache_add_symbol (cfg->cache, sym,
- 0, NULL, NULL,
- SYMBOL_TYPE_VIRTUAL, ret);
- }
- }
- }
-
- lua_pushinteger (L, ret);
-
- return 1;
- }
-
- static gint
- lua_config_register_virtual_symbol (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name;
- double weight;
- gint ret = -1, parent = -1;
-
- if (cfg) {
- name = luaL_checkstring (L, 2);
- weight = luaL_checknumber (L, 3);
-
- if (lua_gettop (L) > 3) {
- parent = lua_tonumber (L, 4);
- }
-
- if (name) {
- ret = rspamd_symcache_add_symbol (cfg->cache, name,
- weight > 0 ? 0 : -1, NULL, NULL,
- SYMBOL_TYPE_VIRTUAL, parent);
- }
- }
-
- lua_pushinteger (L, ret);
-
- return 1;
- }
-
- static gint
- lua_config_register_callback_symbol (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = NULL;
- double weight;
- gint ret = -1, top = 2;
-
- if (cfg) {
- if (lua_type (L, 2) == LUA_TSTRING) {
- /* Legacy syntax */
- name = luaL_checkstring (L, 2);
- top ++;
- }
-
- weight = luaL_checknumber (L, top);
-
- if (lua_type (L, top + 1) == LUA_TSTRING) {
- lua_getglobal (L, luaL_checkstring (L, top + 1));
- }
- else {
- lua_pushvalue (L, top + 1);
- }
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- name,
- luaL_ref (L, LUA_REGISTRYINDEX),
- weight,
- 0,
- SYMBOL_TYPE_CALLBACK,
- -1,
- NULL, NULL,
- FALSE);
- }
-
- lua_pushinteger (L, ret);
-
- return 1;
- }
-
- static gint
- lua_config_register_callback_symbol_priority (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = NULL;
- double weight;
- gint priority, ret = -1, top = 2;
-
- if (cfg) {
- if (lua_type (L, 2) == LUA_TSTRING) {
- /* Legacy syntax */
- name = luaL_checkstring (L, 2);
- top ++;
- }
-
- weight = luaL_checknumber (L, top);
- priority = luaL_checknumber (L, top + 1);
-
- if (lua_type (L, top + 2) == LUA_TSTRING) {
- lua_getglobal (L, luaL_checkstring (L, top + 2));
- }
- else {
- lua_pushvalue (L, top + 2);
- }
-
- ret = rspamd_register_symbol_fromlua (L,
- cfg,
- name,
- luaL_ref (L, LUA_REGISTRYINDEX),
- weight,
- priority,
- SYMBOL_TYPE_CALLBACK,
- -1,
- NULL, NULL,
- FALSE);
- }
-
- lua_pushinteger (L, ret);
-
- return 1;
- }
-
-
- static gint
- lua_config_register_dependency (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *parent = NULL, *child = NULL;
- gint child_id;
-
- if (cfg == NULL) {
- lua_error (L);
- return 0;
- }
-
- if (lua_type (L, 2) == LUA_TNUMBER) {
- child_id = luaL_checknumber (L, 2);
- parent = luaL_checkstring (L, 3);
-
- msg_warn_config ("calling for obsolete method to register deps for symbol %d->%s",
- child_id, parent);
-
- if (child_id > 0 && parent != NULL) {
-
- rspamd_symcache_add_dependency (cfg->cache, child_id, parent,
- -1);
- }
- }
- else {
- child = luaL_checkstring (L,2);
- parent = luaL_checkstring (L, 3);
-
- if (child != NULL && parent != NULL) {
- rspamd_symcache_add_delayed_dependency (cfg->cache, child,
- parent);
- }
- }
-
- return 0;
- }
-
- static gint
- lua_config_set_metric_symbol (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *description = NULL,
- *group = NULL, *name = NULL, *flags_str = NULL;
- double weight;
- gboolean one_shot = FALSE, one_param = FALSE;
- GError *err = NULL;
- gdouble priority = 0.0;
- guint flags = 0;
- gint64 nshots = 0;
-
- if (cfg) {
-
- if (lua_type (L, 2) == LUA_TTABLE) {
- if (!rspamd_lua_parse_table_arguments (L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "*name=S;score=N;description=S;"
- "group=S;one_shot=B;one_param=B;priority=N;flags=S;"
- "nshots=I",
- &name, &weight, &description,
- &group, &one_shot, &one_param,
- &priority, &flags_str, &nshots)) {
- msg_err_config ("bad arguments: %e", err);
- g_error_free (err);
-
- return 0;
- }
- }
- else {
- name = luaL_checkstring (L, 2);
- weight = luaL_checknumber (L, 3);
-
- if (lua_gettop (L) > 3 && lua_type (L, 4) == LUA_TSTRING) {
- description = luaL_checkstring (L, 4);
- }
- if (lua_gettop (L) > 4 && lua_type (L, 5) == LUA_TSTRING) {
- /* XXX: metrics */
- }
- if (lua_gettop (L) > 5 && lua_type (L, 6) == LUA_TSTRING) {
- group = luaL_checkstring (L, 6);
- }
- if (lua_gettop (L) > 6 && lua_type (L, 7) == LUA_TBOOLEAN) {
- one_shot = lua_toboolean (L, 7);
- }
- }
-
- if (nshots == 0) {
- nshots = cfg->default_max_shots;
- }
-
- if (one_shot) {
- nshots = 1;
- }
- if (one_param) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
-
- if (flags_str) {
- if (strstr (flags_str, "one_shot") != NULL) {
- nshots = 1;
- }
- if (strstr (flags_str, "ignore") != NULL) {
- flags |= RSPAMD_SYMBOL_FLAG_IGNORE;
- }
- if (strstr (flags_str, "one_param") != NULL) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
- }
-
- rspamd_config_add_symbol (cfg, name,
- weight, description, group, flags, (guint) priority, nshots);
-
-
- if (lua_type (L, 2) == LUA_TTABLE) {
- lua_pushstring (L, "groups");
- lua_gettable (L, 2);
-
- if (lua_istable (L, -1)) {
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- if (lua_isstring (L, -1)) {
- rspamd_config_add_symbol_group (cfg, name,
- lua_tostring (L, -1));
- } else {
- return luaL_error (L, "invalid groups element");
- }
- }
- }
-
- lua_pop (L, 1);
- }
- }
- else {
- return luaL_error (L, "invalid arguments, rspamd_config expected");
- }
-
- return 0;
- }
-
- static gint
- lua_config_get_metric_symbol (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym_name = luaL_checkstring (L, 2);
- struct rspamd_symbol *sym_def;
- struct rspamd_symbols_group *sym_group;
- guint i;
-
- if (cfg && sym_name) {
- sym_def = g_hash_table_lookup (cfg->symbols, sym_name);
-
- if (sym_def == NULL) {
- lua_pushnil (L);
- }
- else {
- lua_createtable (L, 0, 3);
- lua_pushstring (L, "score");
- lua_pushnumber (L, sym_def->score);
- lua_settable (L, -3);
-
- if (sym_def->description) {
- lua_pushstring (L, "description");
- lua_pushstring (L, sym_def->description);
- lua_settable (L, -3);
- }
-
- if (sym_def->gr) {
- lua_pushstring (L, "group");
- lua_pushstring (L, sym_def->gr->name);
- lua_settable (L, -3);
- }
-
- lua_pushstring (L, "groups");
- lua_createtable (L, sym_def->groups->len, 0);
-
- PTR_ARRAY_FOREACH (sym_def->groups, i, sym_group) {
- lua_pushstring (L, sym_group->name);
- lua_rawseti (L, -2, i + 1);
- }
-
- lua_settable (L, -3);
- }
- }
- else {
- luaL_error (L, "Invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_set_metric_action (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = NULL;
- double threshold = NAN;
- GError *err = NULL;
- gdouble priority = 0.0;
- ucl_object_t *obj_tbl = NULL;
-
- if (cfg) {
-
- if (lua_type (L, 2) == LUA_TTABLE) {
- if (!rspamd_lua_parse_table_arguments (L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "*action=S;score=N;"
- "priority=N",
- &name, &threshold,
- &priority)) {
- msg_err_config ("bad arguments: %e", err);
- g_error_free (err);
-
- return 0;
- }
- }
- else if (lua_type (L, 2) == LUA_TSTRING && lua_type (L, 3) == LUA_TTABLE) {
- name = lua_tostring (L, 2);
- obj_tbl = ucl_object_lua_import (L, 3);
-
- if (obj_tbl) {
- if (name) {
- rspamd_config_set_action_score (cfg, name, obj_tbl);
- ucl_object_unref (obj_tbl);
- }
- else {
- ucl_object_unref (obj_tbl);
- return luaL_error (L, "invalid first argument, action name expected");
- }
- }
- else {
- return luaL_error (L, "invalid second argument, table expected");
- }
- }
- else {
- return luaL_error (L, "invalid arguments, table expected");
- }
-
- if (name != NULL && !isnan (threshold) && threshold != 0) {
- obj_tbl = ucl_object_typed_new (UCL_OBJECT);
- ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (threshold),
- "score", 0, false);
- ucl_object_insert_key (obj_tbl, ucl_object_fromdouble (priority),
- "priority", 0, false);
- rspamd_config_set_action_score (cfg, name, obj_tbl);
- ucl_object_unref (obj_tbl);
- }
- }
- else {
- return luaL_error (L, "invalid arguments, rspamd_config expected");
- }
-
- return 0;
- }
-
- static gint
- lua_config_get_metric_action (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *act_name = luaL_checkstring (L, 2);
- struct rspamd_action *act;
-
- if (cfg && act_name) {
- act = rspamd_config_get_action (cfg, act_name);
-
- if (act) {
- if (!isnan (act->threshold)) {
- lua_pushnumber (L, act->threshold);
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- return luaL_error (L, "invalid arguments, rspamd_config expected");
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_all_actions (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_action *act, *tmp;
-
- if (cfg) {
- lua_createtable (L, 0, HASH_COUNT (cfg->actions));
-
- HASH_ITER (hh, cfg->actions, act, tmp) {
- if (!isnan (act->threshold)) {
- lua_pushstring (L, act->name);
- lua_pushnumber (L, act->threshold);
- lua_settable (L, -3);
- }
- }
- }
- else {
- return luaL_error (L, "invalid arguments, rspamd_config expected");
- }
-
- return 1;
- }
-
- static gint
- lua_config_add_composite (lua_State * L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_expression *expr;
- gchar *name;
- const gchar *expr_str;
- struct rspamd_composite *composite;
- gboolean ret = FALSE, new = TRUE;
- GError *err = NULL;
-
- if (cfg) {
- name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2));
- expr_str = luaL_checkstring (L, 3);
-
- if (name && expr_str) {
- if (!rspamd_parse_expression (expr_str, 0, &composite_expr_subr,
- NULL, cfg->cfg_pool, &err, &expr)) {
- msg_err_config ("cannot parse composite expression %s: %e",
- expr_str,
- err);
- g_error_free (err);
- }
- else {
- if (g_hash_table_lookup (cfg->composite_symbols, name) != NULL) {
- msg_warn_config ("composite %s is redefined", name);
- new = FALSE;
- }
-
- composite = rspamd_mempool_alloc0 (cfg->cfg_pool,
- sizeof (struct rspamd_composite));
- composite->expr = expr;
- composite->id = g_hash_table_size (cfg->composite_symbols);
- composite->str_expr = rspamd_mempool_strdup (cfg->cfg_pool,
- expr_str);
- composite->sym = name;
- g_hash_table_insert (cfg->composite_symbols,
- (gpointer)name,
- composite);
-
- if (new) {
- rspamd_symcache_add_symbol (cfg->cache, name,
- 0, NULL, composite, SYMBOL_TYPE_COMPOSITE, -1);
- }
-
- ret = TRUE;
- }
- }
- }
-
- lua_pushboolean (L, ret);
-
- return 1;
- }
-
- static gint
- lua_config_newindex (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name, *allowed_ids = NULL, *forbidden_ids = NULL;
- gint id, nshots, flags = 0;
- gboolean optional = FALSE;
-
- name = luaL_checkstring (L, 2);
-
- if (cfg != NULL && name != NULL && lua_gettop (L) == 3) {
-
- if (lua_type (L, 3) == LUA_TFUNCTION) {
- /* Normal symbol from just a function */
- lua_pushvalue (L, 3);
- rspamd_register_symbol_fromlua (L,
- cfg,
- name,
- luaL_ref (L, LUA_REGISTRYINDEX),
- 1.0,
- 0,
- SYMBOL_TYPE_NORMAL,
- -1,
- NULL, NULL,
- FALSE);
- }
- else if (lua_type (L, 3) == LUA_TTABLE) {
- gint type = SYMBOL_TYPE_NORMAL, priority = 0, idx;
- gdouble weight = 1.0, score = NAN;
- const char *type_str, *group = NULL, *description = NULL;
-
- /*
- * Table can have the following attributes:
- * "callback" - should be a callback function
- * "weight" - optional weight
- * "priority" - optional priority
- * "type" - optional type (normal, virtual, callback)
- * "flags" - optional flags
- * -- Metric options
- * "score" - optional default score (overridden by metric)
- * "group" - optional default group
- * "one_shot" - optional one shot mode
- * "description" - optional description
- */
- lua_pushvalue (L, 3);
- lua_pushstring (L, "callback");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) != LUA_TFUNCTION) {
- lua_pop (L, 2);
- msg_info_config ("cannot find callback definition for %s",
- name);
- return 0;
- }
- idx = luaL_ref (L, LUA_REGISTRYINDEX);
-
- /* Optional fields */
- lua_pushstring (L, "weight");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TNUMBER) {
- weight = lua_tonumber (L, -1);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "priority");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TNUMBER) {
- priority = lua_tonumber (L, -1);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "optional");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TBOOLEAN) {
- optional = lua_toboolean (L, -1);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "type");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TSTRING) {
- type_str = lua_tostring (L, -1);
- type = lua_parse_symbol_type (type_str);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "flags");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TSTRING) {
- type_str = lua_tostring (L, -1);
- type |= lua_parse_symbol_flags (type_str);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "allowed_ids");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TSTRING) {
- allowed_ids = lua_tostring (L, -1);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "forbidden_ids");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TSTRING) {
- forbidden_ids = lua_tostring (L, -1);
- }
- lua_pop (L, 1);
-
- id = rspamd_register_symbol_fromlua (L,
- cfg,
- name,
- idx,
- weight,
- priority,
- type,
- -1,
- allowed_ids, forbidden_ids,
- optional);
-
- if (id != -1) {
- /* Check for condition */
- lua_pushstring (L, "condition");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TFUNCTION) {
- gint condref;
-
- /* Here we pop function from the stack, so no lua_pop is required */
- condref = luaL_ref (L, LUA_REGISTRYINDEX);
- g_assert (name != NULL);
- rspamd_symcache_add_condition_delayed (cfg->cache,
- name, L, condref);
- }
- else {
- lua_pop (L, 1);
- }
- }
-
- /*
- * Now check if a symbol has not been registered in any metric and
- * insert default value if applicable
- */
- if (g_hash_table_lookup (cfg->symbols, name) == NULL) {
- nshots = cfg->default_max_shots;
-
- lua_pushstring (L, "score");
- lua_gettable (L, -2);
- if (lua_type (L, -1) == LUA_TNUMBER) {
- score = lua_tonumber (L, -1);
-
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "group");
- lua_gettable (L, -2);
- if (lua_type (L, -1) == LUA_TSTRING) {
- group = lua_tostring (L, -1);
- }
- lua_pop (L, 1);
-
- if (!isnan (score) || group != NULL) {
- lua_pushstring (L, "description");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TSTRING) {
- description = lua_tostring (L, -1);
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "one_shot");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean (L, -1)) {
- nshots = 1;
- }
- }
- lua_pop (L, 1);
-
- lua_pushstring (L, "one_param");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean (L, -1)) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
- }
- lua_pop (L, 1);
-
- /*
- * Do not override the existing symbols (using zero priority),
- * since we are defining default values here
- */
- if (!isnan (score)) {
- rspamd_config_add_symbol (cfg, name, score,
- description, group, flags, 0, nshots);
- }
- else if (group) {
- /* Add with zero score */
- rspamd_config_add_symbol (cfg, name, 0.0,
- description, group, flags, 0, nshots);
- }
-
- lua_pushstring (L, "groups");
- lua_gettable (L, -2);
-
- if (lua_istable (L, -1)) {
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- if (lua_isstring (L, -1)) {
- rspamd_config_add_symbol_group (cfg, name,
- lua_tostring (L, -1));
- }
- else {
- return luaL_error (L, "invalid groups element");
- }
- }
- }
-
- lua_pop (L, 1);
- }
- }
-
- /* Remove table from stack */
- lua_pop (L, 1);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_add_condition (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
- gboolean ret = FALSE;
- gint condref;
-
- if (cfg && sym && lua_type (L, 3) == LUA_TFUNCTION) {
- lua_pushvalue (L, 3);
- condref = luaL_ref (L, LUA_REGISTRYINDEX);
-
- ret = rspamd_symcache_add_condition_delayed (cfg->cache, sym, L,
- condref);
-
- if (!ret) {
- luaL_unref (L, LUA_REGISTRYINDEX, condref);
- }
- }
-
- lua_pushboolean (L, ret);
- return 1;
- }
-
- static gint
- lua_config_set_peak_cb (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- gint condref;
-
- if (cfg && lua_type (L, 2) == LUA_TFUNCTION) {
- lua_pushvalue (L, 2);
- condref = luaL_ref (L, LUA_REGISTRYINDEX);
- rspamd_symcache_set_peak_callback (cfg->cache,
- condref);
- }
-
- return 0;
- }
-
- static gint
- lua_config_enable_symbol (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
-
- if (cfg && sym) {
- rspamd_symcache_enable_symbol_perm (cfg->cache, sym);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_disable_symbol (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
-
- if (cfg && sym) {
- rspamd_symcache_disable_symbol_perm (cfg->cache, sym);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_register_regexp (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_lua_regexp *re = NULL;
- rspamd_regexp_t *cache_re;
- const gchar *type_str = NULL, *header_str = NULL;
- gsize header_len = 0;
- GError *err = NULL;
- enum rspamd_re_type type = RSPAMD_RE_BODY;
- gboolean pcre_only = FALSE;
- guint old_flags;
-
- /*
- * - `re`* : regular expression object
- * - `type`*: type of regular expression:
- * + `mime`: mime regexp
- * + `rawmime`: raw mime regexp
- * + `header`: header regexp
- * + `rawheader`: raw header expression
- * + `body`: raw body regexp
- * + `url`: url regexp
- * - `header`: for header and rawheader regexp means the name of header
- * - `pcre_only`: allow merely pcre for this regexp
- */
- if (cfg != NULL) {
- if (!rspamd_lua_parse_table_arguments (L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "*re=U{regexp};*type=S;header=S;pcre_only=B",
- &re, &type_str, &header_str, &pcre_only)) {
- msg_err_config ("cannot get parameters list: %e", err);
-
- if (err) {
- g_error_free (err);
- }
- }
- else {
- type = rspamd_re_cache_type_from_string (type_str);
-
- if ((type == RSPAMD_RE_HEADER ||
- type == RSPAMD_RE_RAWHEADER ||
- type == RSPAMD_RE_MIMEHEADER) &&
- header_str == NULL) {
- msg_err_config (
- "header argument is mandatory for header/rawheader regexps");
- }
- else {
- if (pcre_only) {
- old_flags = rspamd_regexp_get_flags (re->re);
- old_flags |= RSPAMD_REGEXP_FLAG_PCRE_ONLY;
- rspamd_regexp_set_flags (re->re, old_flags);
- }
-
- if (header_str != NULL) {
- /* Include the last \0 */
- header_len = strlen (header_str) + 1;
- }
-
- cache_re = rspamd_re_cache_add (cfg->re_cache, re->re, type,
- (gpointer) header_str, header_len);
-
- /*
- * XXX: here are dragons!
- * Actually, lua regexp contains internal rspamd_regexp_t
- * and it owns it.
- * However, after this operation we have some OTHER regexp,
- * which we really would like to use.
- * So we do the following:
- * 1) Remove old re and unref it
- * 2) Replace the internal re with cached one
- * 3) Increase its refcount to share ownership between cache and
- * lua object
- */
- if (cache_re != re->re) {
- rspamd_regexp_unref (re->re);
- re->re = rspamd_regexp_ref (cache_re);
- }
- }
- }
- }
-
- return 0;
- }
-
- static gint
- lua_config_replace_regexp (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_lua_regexp *old_re = NULL, *new_re = NULL;
- GError *err = NULL;
-
- if (cfg != NULL) {
- if (!rspamd_lua_parse_table_arguments (L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "*old_re=U{regexp};*new_re=U{regexp}",
- &old_re, &new_re)) {
- msg_err_config ("cannot get parameters list: %e", err);
-
- if (err) {
- g_error_free (err);
- }
- }
- else {
- rspamd_re_cache_replace (cfg->re_cache, old_re->re, new_re->re);
- }
- }
-
- return 0;
- }
-
- static gint
- lua_config_register_worker_script (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *worker_type = luaL_checkstring (L, 2), *wtype;
- struct rspamd_worker_conf *cf;
- GList *cur;
- struct rspamd_worker_lua_script *sc;
- gboolean found = FALSE;
-
- if (cfg == NULL || worker_type == NULL || lua_type (L, 3) != LUA_TFUNCTION) {
- return luaL_error (L, "invalid arguments");
- }
-
- for (cur = g_list_first (cfg->workers); cur != NULL; cur = g_list_next (cur)) {
- cf = cur->data;
- wtype = g_quark_to_string (cf->type);
-
- if (g_ascii_strcasecmp (wtype, worker_type) == 0) {
- sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
- lua_pushvalue (L, 3);
- sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- DL_APPEND (cf->scripts, sc);
- found = TRUE;
- }
- }
-
- lua_pushboolean (L, found);
-
- return 1;
- }
-
- static gint
- lua_config_add_on_load (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_config_cfg_lua_script *sc;
-
- if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
- return luaL_error (L, "invalid arguments");
- }
-
- sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
- lua_pushvalue (L, 2);
- sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- DL_APPEND (cfg->on_load_scripts, sc);
-
- return 0;
- }
-
- static gint
- lua_config_add_post_init (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_config_cfg_lua_script *sc;
-
- if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
- return luaL_error (L, "invalid arguments");
- }
-
- sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
- lua_pushvalue (L, 2);
- sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- DL_APPEND (cfg->post_init_scripts, sc);
-
- return 0;
- }
-
- static gint
- lua_config_add_config_unload (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_config_cfg_lua_script *sc;
-
- if (cfg == NULL || lua_type (L, 2) != LUA_TFUNCTION) {
- return luaL_error (L, "invalid arguments");
- }
-
- sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
- lua_pushvalue (L, 2);
- sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- DL_APPEND (cfg->config_unload_scripts, sc);
-
- return 0;
- }
-
-
- static void lua_periodic_callback_finish (struct thread_entry *thread, int ret);
- static void lua_periodic_callback_error (struct thread_entry *thread, int ret, const char *msg);
-
- struct rspamd_lua_periodic {
- struct ev_loop *event_loop;
- struct rspamd_config *cfg;
- gchar *lua_src_pos;
- lua_State *L;
- gdouble timeout;
- ev_timer ev;
- gint cbref;
- gboolean need_jitter;
- ref_entry_t ref;
- };
-
- static void
- lua_periodic_dtor (struct rspamd_lua_periodic *periodic)
- {
- luaL_unref (periodic->L, LUA_REGISTRYINDEX, periodic->cbref);
- ev_timer_stop (periodic->event_loop, &periodic->ev);
- }
-
- static void
- lua_periodic_fin (gpointer p)
- {
- struct rspamd_lua_periodic *periodic = (struct rspamd_lua_periodic *)p;
-
- REF_RELEASE (periodic);
- }
-
- static void
- lua_periodic_callback (struct ev_loop *loop, ev_timer *w, int revents)
- {
- struct rspamd_lua_periodic *periodic = (struct rspamd_lua_periodic *)w->data;
- struct rspamd_config **pcfg, *cfg;
- struct ev_loop **pev_base;
- struct thread_entry *thread;
- lua_State *L;
-
- REF_RETAIN (periodic);
- thread = lua_thread_pool_get_for_config (periodic->cfg);
- thread->cd = periodic;
- thread->finish_callback = lua_periodic_callback_finish;
- thread->error_callback = lua_periodic_callback_error;
-
- L = thread->lua_state;
-
- lua_rawgeti (L, LUA_REGISTRYINDEX, periodic->cbref);
- pcfg = lua_newuserdata (L, sizeof (*pcfg));
- rspamd_lua_setclass (L, "rspamd{config}", -1);
- cfg = periodic->cfg;
- *pcfg = cfg;
- pev_base = lua_newuserdata (L, sizeof (*pev_base));
- rspamd_lua_setclass (L, "rspamd{ev_base}", -1);
- *pev_base = periodic->event_loop;
-
- lua_thread_call (thread, 2);
- }
-
- static void
- lua_periodic_callback_finish (struct thread_entry *thread, int ret)
- {
- lua_State *L;
- struct rspamd_lua_periodic *periodic = thread->cd;
- gboolean plan_more = FALSE;
- gdouble timeout = 0.0;
-
- L = thread->lua_state;
-
- ev_now_update (periodic->event_loop);
-
- if (ret == 0) {
- if (lua_type (L, -1) == LUA_TBOOLEAN) {
- plan_more = lua_toboolean (L, -1);
- timeout = periodic->timeout;
- }
- else if (lua_type (L, -1) == LUA_TNUMBER) {
- timeout = lua_tonumber (L, -1);
- plan_more = timeout > 0 ? TRUE : FALSE;
- }
-
- lua_pop (L, 1); /* Return value */
- }
- if (plan_more) {
- if (periodic->need_jitter) {
- timeout = rspamd_time_jitter (timeout, 0.0);
- }
-
- periodic->ev.repeat = timeout;
- ev_timer_again (periodic->event_loop, &periodic->ev);
- }
- else {
- ev_timer_stop (periodic->event_loop, &periodic->ev);
- }
-
- REF_RELEASE (periodic);
- }
-
- static void
- lua_periodic_callback_error (struct thread_entry *thread, int ret, const char *msg)
- {
- struct rspamd_config *cfg;
- struct rspamd_lua_periodic *periodic = thread->cd;
- cfg = periodic->cfg;
-
- msg_err_config ("call to periodic script (registered at %s) failed: %s",
- periodic->lua_src_pos, msg);
-
- lua_periodic_callback_finish (thread, ret);
- }
-
-
- static gint
- lua_config_add_periodic (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct ev_loop *ev_base = lua_check_ev_base (L, 2);
- gdouble timeout = lua_tonumber (L, 3);
- struct rspamd_lua_periodic *periodic;
- gboolean need_jitter = FALSE;
- lua_Debug d;
- gchar tmp[256], *p;
-
- if (cfg == NULL || timeout < 0 || lua_type (L, 4) != LUA_TFUNCTION) {
- return luaL_error (L, "invalid arguments");
- }
-
- if (lua_type (L, 5) == LUA_TBOOLEAN) {
- need_jitter = lua_toboolean (L, 5);
- }
-
- if (lua_getstack (L, 1, &d) == 1) {
- (void) lua_getinfo (L, "Sl", &d);
- if ((p = strrchr (d.short_src, '/')) == NULL) {
- p = d.short_src;
- }
- else {
- p++;
- }
-
- if (strlen (p) > 20) {
- rspamd_snprintf (tmp, sizeof (tmp), "%10s...]:%d", p,
- d.currentline);
- }
- else {
- rspamd_snprintf (tmp, sizeof (tmp), "%s:%d", p,
- d.currentline);
- }
- }
-
- periodic = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*periodic));
- periodic->timeout = timeout;
- periodic->L = L;
- periodic->cfg = cfg;
- periodic->event_loop = ev_base;
- periodic->need_jitter = need_jitter;
- periodic->lua_src_pos = rspamd_mempool_strdup (cfg->cfg_pool, tmp);
- lua_pushvalue (L, 4);
- periodic->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
-
- if (need_jitter) {
- timeout = rspamd_time_jitter (timeout, 0.0);
- }
-
- ev_timer_init (&periodic->ev, lua_periodic_callback, timeout, 0.0);
- periodic->ev.data = periodic;
- ev_timer_start (ev_base, &periodic->ev);
- REF_INIT_RETAIN (periodic, lua_periodic_dtor);
-
- rspamd_mempool_add_destructor (cfg->cfg_pool, lua_periodic_fin,
- periodic);
-
- return 0;
- }
-
- static gint
- lua_config_get_symbols_count (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- guint res = 0;
-
- if (cfg != NULL) {
- res = rspamd_symcache_stats_symbols_count (cfg->cache);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- lua_pushinteger (L, res);
-
- return 1;
- }
-
- static gint
- lua_config_get_symbols_cksum (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- guint64 res = 0, *pres;
-
- if (cfg != NULL) {
- res = rspamd_symcache_get_cksum (cfg->cache);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- pres = lua_newuserdata (L, sizeof (res));
- *pres = res;
- rspamd_lua_setclass (L, "rspamd{int64}", -1);
-
- return 1;
- }
-
- static gint
- lua_config_get_symbols_counters (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- ucl_object_t *counters;
-
- if (cfg != NULL) {
- counters = rspamd_symcache_counters (cfg->cache);
- ucl_object_push_lua (L, counters, true);
- ucl_object_unref (counters);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- struct lua_metric_symbols_cbdata {
- lua_State *L;
- struct rspamd_config *cfg;
- };
-
- static void
- lua_metric_symbol_inserter (gpointer k, gpointer v, gpointer ud)
- {
- struct lua_metric_symbols_cbdata *cbd = (struct lua_metric_symbols_cbdata *)ud;
- lua_State *L;
- const gchar *sym = k;
- struct rspamd_symbol *s = (struct rspamd_symbol *) v;
- struct rspamd_symbols_group *gr;
- gint i;
-
- L = cbd->L;
-
- lua_pushstring (L, sym); /* Symbol name */
-
- lua_createtable (L, 0, 6);
- lua_pushstring (L, "score");
- lua_pushnumber (L, s->score);
- lua_settable (L, -3);
- lua_pushstring (L, "description");
- lua_pushstring (L, s->description);
- lua_settable (L, -3);
-
- lua_pushstring (L, "flags");
- lua_createtable (L, 0, 3);
-
- if (s->flags & RSPAMD_SYMBOL_FLAG_IGNORE) {
- lua_pushstring (L, "ignore");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (s->flags & RSPAMD_SYMBOL_FLAG_ONEPARAM) {
- lua_pushstring (L, "oneparam");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (s->flags & RSPAMD_SYMBOL_FLAG_UNGROUPPED) {
- lua_pushstring (L, "ungroupped");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
-
- if (s->cache_item) {
- guint sflags = rspamd_symcache_get_symbol_flags (cbd->cfg->cache, sym);
-
- lua_push_symbol_flags (L, sflags, LUA_SYMOPT_FLAG_USE_MAP);
-
- guint nids;
- const guint *allowed_ids = rspamd_symcache_get_allowed_settings_ids (cbd->cfg->cache,
- sym, &nids);
-
- if (allowed_ids && nids > 0) {
- lua_createtable (L, nids, 0);
-
- for (i = 0; i < nids; i ++) {
- lua_pushinteger (L, allowed_ids[i]);
- lua_rawseti (L, -2, i + 1);
- }
-
- lua_setfield (L, -2, "allowed_ids");
- }
-
- const guint *forbidden_ids = rspamd_symcache_get_forbidden_settings_ids (
- cbd->cfg->cache,
- sym, &nids);
-
- if (forbidden_ids && nids > 0) {
- lua_createtable (L, nids, 0);
-
- for (i = 0; i < nids; i ++) {
- lua_pushinteger (L, forbidden_ids[i]);
- lua_rawseti (L, -2, i + 1);
- }
-
- lua_setfield (L, -2, "forbidden_ids");
- }
- }
-
- lua_settable (L, -3); /* Flags -> flags_table */
-
- lua_pushstring (L, "nshots");
- lua_pushinteger (L, s->nshots);
- lua_settable (L, -3);
-
- if (s->gr) {
- lua_pushstring (L, "group");
- lua_pushstring (L, s->gr->name);
- lua_settable (L, -3);
- }
-
- if (s->groups && s->groups->len > 0) {
- lua_pushstring (L, "groups");
- lua_createtable (L, s->groups->len, 0);
-
- PTR_ARRAY_FOREACH (s->groups, i, gr) {
- lua_pushstring (L, gr->name);
- lua_rawseti (L, -2, i + 1); /* Groups[i + 1] = group_name */
- }
-
- lua_settable (L, -3); /* Groups -> groups_table */
- }
- else {
- lua_createtable (L, 0, 0);
- lua_setfield (L, -2, "groups");
- }
-
- lua_settable (L, -3); /* Symname -> table */
- }
-
- static gint
- lua_config_get_symbols (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL) {
- struct lua_metric_symbols_cbdata cbd;
-
- cbd.L = L;
- cbd.cfg = cfg;
-
- lua_createtable (L, 0, g_hash_table_size (cfg->symbols));
- g_hash_table_foreach (cfg->symbols,
- lua_metric_symbol_inserter,
- &cbd);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
-
- static gint
- lua_config_get_symbol_callback (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
- struct rspamd_abstract_callback_data *abs_cbdata;
- struct lua_callback_data *cbd;
-
- if (cfg != NULL && sym != NULL) {
- abs_cbdata = rspamd_symcache_get_cbdata (cfg->cache, sym);
-
- if (abs_cbdata == NULL || abs_cbdata->magic != rspamd_lua_callback_magic) {
- lua_pushnil (L);
- }
- else {
- cbd = (struct lua_callback_data *)abs_cbdata;
-
- if (cbd->cb_is_ref) {
- lua_rawgeti (L, LUA_REGISTRYINDEX, cbd->callback.ref);
- }
- else {
- lua_getglobal (L, cbd->callback.name);
- }
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_set_symbol_callback (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
- struct rspamd_abstract_callback_data *abs_cbdata;
- struct lua_callback_data *cbd;
-
- if (cfg != NULL && sym != NULL && lua_type (L, 3) == LUA_TFUNCTION) {
- abs_cbdata = rspamd_symcache_get_cbdata (cfg->cache, sym);
-
- if (abs_cbdata == NULL || abs_cbdata->magic != rspamd_lua_callback_magic) {
- lua_pushboolean (L, FALSE);
- }
- else {
- cbd = (struct lua_callback_data *)abs_cbdata;
-
- if (cbd->cb_is_ref) {
- luaL_unref (L, LUA_REGISTRYINDEX, cbd->callback.ref);
- }
- else {
- cbd->cb_is_ref = TRUE;
- }
-
- lua_pushvalue (L, 3);
- cbd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX);
- lua_pushboolean (L, TRUE);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_symbol_stat (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2);
- gdouble freq, stddev, tm;
- guint hits;
-
- if (cfg != NULL && sym != NULL) {
- if (!rspamd_symcache_stat_symbol (cfg->cache, sym, &freq,
- &stddev, &tm, &hits)) {
- lua_pushnil (L);
- }
- else {
- lua_createtable (L, 0, 4);
- lua_pushstring (L, "frequency");
- lua_pushnumber (L, freq);
- lua_settable (L, -3);
- lua_pushstring (L, "sttdev");
- lua_pushnumber (L, stddev);
- lua_settable (L, -3);
- lua_pushstring (L, "time");
- lua_pushnumber (L, tm);
- lua_settable (L, -3);
- lua_pushstring (L, "hits");
- lua_pushinteger (L, hits);
- lua_settable (L, -3);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_symbol_parent (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *sym = luaL_checkstring (L, 2), *parent;
-
- if (cfg != NULL && sym != NULL) {
- parent = rspamd_symcache_get_parent (cfg->cache, sym);
-
- if (parent) {
- lua_pushstring (L, parent);
- }
- else {
- lua_pushnil (L);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_group_symbols (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *gr_name = luaL_checkstring (L, 2);
-
- if (cfg != NULL && gr_name != NULL) {
- struct rspamd_symbols_group *group;
-
- group = g_hash_table_lookup (cfg->groups, gr_name);
-
- if (group == NULL) {
- lua_pushnil (L);
- }
- else {
- guint i = 1;
- gpointer k, v;
- GHashTableIter it;
-
- lua_createtable (L, g_hash_table_size (group->symbols), 0);
- g_hash_table_iter_init (&it, group->symbols);
-
- while (g_hash_table_iter_next (&it, &k, &v)) {
- lua_pushstring (L, k);
- lua_rawseti (L, -2, i);
- i ++;
- }
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_register_finish_script (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_config_cfg_lua_script *sc;
-
- if (cfg != NULL && lua_type (L, 2) == LUA_TFUNCTION) {
- sc = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*sc));
- lua_pushvalue (L, 2);
- sc->cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- DL_APPEND (cfg->on_term_scripts, sc);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_register_settings_id (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *settings_name = luaL_checkstring (L, 2);
-
- if (cfg != NULL && settings_name) {
- ucl_object_t *sym_enabled, *sym_disabled;
- enum rspamd_config_settings_policy policy = RSPAMD_SETTINGS_POLICY_DEFAULT;
-
- sym_enabled = ucl_object_lua_import (L, 3);
-
- if (sym_enabled != NULL && ucl_object_type (sym_enabled) != UCL_OBJECT) {
- ucl_object_unref (sym_enabled);
-
- return luaL_error (L, "invalid symbols enabled");
- }
-
- sym_disabled = ucl_object_lua_import (L, 4);
-
- if (sym_disabled != NULL && ucl_object_type (sym_disabled) != UCL_OBJECT) {
- ucl_object_unref (sym_enabled);
- ucl_object_unref (sym_disabled);
-
- return luaL_error (L, "invalid symbols enabled");
- }
-
- /* Check policy */
- if (lua_isstring (L, 5)) {
- const gchar *policy_str = lua_tostring (L, 5);
-
- if (strcmp (policy_str, "default") == 0) {
- policy = RSPAMD_SETTINGS_POLICY_DEFAULT;
- }
- else if (strcmp (policy_str, "implicit_allow") == 0) {
- policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_ALLOW;
- }
- else if (strcmp (policy_str, "implicit_deny") == 0) {
- policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_DENY;
- }
- else {
- return luaL_error (L, "invalid settings policy: %s", policy_str);
- }
- }
- else {
- /* Apply heuristic */
- if (!sym_enabled) {
- policy = RSPAMD_SETTINGS_POLICY_IMPLICIT_ALLOW;
- }
- }
-
- rspamd_config_register_settings_id (cfg, settings_name, sym_enabled,
- sym_disabled, policy);
-
- if (sym_enabled) {
- ucl_object_unref (sym_enabled);
- }
-
- if (sym_disabled) {
- ucl_object_unref (sym_disabled);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_register_monitored (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_monitored *m, **pm;
- const gchar *url, *type;
- ucl_object_t *params = NULL;
-
- url = lua_tostring (L, 2);
- type = lua_tostring (L, 3);
-
- if (cfg != NULL && url != NULL && type != NULL) {
- if (g_ascii_strcasecmp (type, "dns") == 0) {
- lua_Debug ar;
-
- if (lua_type (L, 4) == LUA_TTABLE) {
- params = ucl_object_lua_import (L, 4);
- }
-
- /* Get lua line and source */
- lua_getstack (L, 1, &ar);
- lua_getinfo (L, "nSl", &ar);
-
- m = rspamd_monitored_create_ (cfg->monitored_ctx, url,
- RSPAMD_MONITORED_DNS, RSPAMD_MONITORED_DEFAULT,
- params, ar.short_src);
-
- if (m) {
- pm = lua_newuserdata (L, sizeof (*pm));
- *pm = m;
- rspamd_lua_setclass (L, "rspamd{monitored}", -1);
- }
- else {
- lua_pushnil (L);
- }
-
- if (params) {
- ucl_object_unref (params);
- }
- }
- else {
- return luaL_error (L, "invalid monitored type: %s", type);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_add_doc (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg;
- const gchar *path = NULL, *option, *doc_string;
- const gchar *type_str = NULL, *default_value = NULL;
- ucl_type_t type = UCL_NULL;
- gboolean required = FALSE;
- GError *err = NULL;
-
- cfg = lua_check_config (L, 1);
-
- if (lua_type (L, 2 ) == LUA_TSTRING) {
- path = luaL_checkstring (L, 2);
- }
-
- option = luaL_checkstring (L, 3);
- doc_string = luaL_checkstring (L, 4);
-
- if (cfg && option && doc_string) {
- if (lua_type (L, 5) == LUA_TTABLE) {
- if (!rspamd_lua_parse_table_arguments (L, 5, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "type=S;default=S;required=B",
- &type_str, &default_value, &required)) {
- msg_err_config ("cannot get parameters list: %e", err);
-
- if (err) {
- g_error_free (err);
- }
-
- if (type_str) {
- if (!ucl_object_string_to_type (type_str, &type)) {
- msg_err_config ("invalid type: %s", type_str);
- }
- }
- }
- }
-
- rspamd_rcl_add_doc_by_path (cfg, path, doc_string, option,
- type, NULL, 0, default_value, required);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_add_example (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg;
- const gchar *path = NULL, *option, *doc_string, *example;
- gsize example_len;
-
- cfg = lua_check_config (L, 1);
-
- if (lua_type (L, 2 ) == LUA_TSTRING) {
- path = luaL_checkstring (L, 2);
- }
-
- option = luaL_checkstring (L, 3);
- doc_string = luaL_checkstring (L, 4);
- example = luaL_checklstring (L, 5, &example_len);
-
- if (cfg && option && doc_string && example) {
-
- rspamd_rcl_add_doc_by_example (cfg, path, doc_string, option,
- example, example_len);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_get_cpu_flags (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- struct rspamd_cryptobox_library_ctx *crypto_ctx;
-
- if (cfg != NULL) {
- crypto_ctx = cfg->libs_ctx->crypto_ctx;
- lua_newtable (L);
-
- if (crypto_ctx->cpu_config & CPUID_SSSE3) {
- lua_pushstring (L, "ssse3");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_SSE41) {
- lua_pushstring (L, "sse41");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_SSE42) {
- lua_pushstring (L, "sse42");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_SSE2) {
- lua_pushstring (L, "sse2");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_SSE3) {
- lua_pushstring (L, "sse3");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_AVX) {
- lua_pushstring (L, "avx");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- if (crypto_ctx->cpu_config & CPUID_AVX2) {
- lua_pushstring (L, "avx2");
- lua_pushboolean (L, true);
- lua_settable (L, -3);
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_has_torch (lua_State *L)
- {
- msg_warn ("use of the obsoleted `has_torch` function");
- lua_pushboolean (L, false);
-
- return 1;
- }
-
- static gint
- lua_config_experimental_enabled (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL) {
- lua_pushboolean (L, cfg->enable_experimental);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- struct rspamd_lua_include_trace_cbdata {
- lua_State *L;
- gint cbref;
- };
-
- static void
- lua_include_trace_cb (struct ucl_parser *parser,
- const ucl_object_t *parent,
- const ucl_object_t *args,
- const char *path,
- size_t pathlen,
- void *user_data)
- {
- struct rspamd_lua_include_trace_cbdata *cbdata =
- (struct rspamd_lua_include_trace_cbdata *)user_data;
- gint err_idx;
- lua_State *L;
-
- L = cbdata->L;
- lua_pushcfunction (L, &rspamd_lua_traceback);
- err_idx = lua_gettop (L);
-
- lua_rawgeti (L, LUA_REGISTRYINDEX, cbdata->cbref);
- /* Current filename */
- lua_pushstring (L, ucl_parser_get_cur_file (parser));
- /* Included filename */
- lua_pushlstring (L, path, pathlen);
- /* Params */
- if (args) {
- ucl_object_push_lua (L, args, true);
- }
- else {
- lua_newtable (L);
- }
- /* Parent */
- if (parent) {
- lua_pushstring (L, ucl_object_key (parent));
- }
- else {
- lua_pushnil (L);
- }
-
- if (lua_pcall (L, 4, 0, err_idx) != 0) {
- msg_err ("lua call to local include trace failed: %s", lua_tostring (L, -1));
- }
-
- lua_settop (L, err_idx - 1);
- }
-
- #define LUA_TABLE_TO_HASH(htb, idx) do { \
- lua_pushstring (L, (idx)); \
- lua_gettable (L, -2); \
- if (lua_isstring (L, -1)) { \
- g_hash_table_insert ((htb), (idx), g_strdup (lua_tostring (L, -1))); \
- } \
- lua_pop (L, 1); \
- } while(0)
-
- static gint
- lua_config_load_ucl (lua_State *L)
- {
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *filename;
- GHashTable *paths = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal,
- NULL, g_free);
- GError *err = NULL;
-
- if (cfg) {
- if (lua_isstring (L, 2)) {
- filename = lua_tostring (L, 2);
- }
- else {
- filename = RSPAMD_CONFDIR "/rspamd.conf";
- }
-
- /* Convert rspamd_paths */
- lua_getglobal (L, "rspamd_paths");
-
- if (lua_istable (L, -1)) {
- LUA_TABLE_TO_HASH(paths, RSPAMD_CONFDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_LOCAL_CONFDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_RUNDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_DBDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_LOGDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_WWWDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_PLUGINSDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_RULESDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_LUALIBDIR_INDEX);
- LUA_TABLE_TO_HASH(paths, RSPAMD_PREFIX_INDEX);
- }
-
- lua_pop (L, 1);
-
- if (lua_isfunction (L, 3)) {
- struct rspamd_lua_include_trace_cbdata cbd;
-
- lua_pushvalue (L, 3);
- cbd.cbref = luaL_ref (L, LUA_REGISTRYINDEX);
- cbd.L = L;
-
- if (!rspamd_config_parse_ucl (cfg, filename, paths,
- lua_include_trace_cb, &cbd, lua_toboolean (L, 4), &err)) {
- luaL_unref (L, LUA_REGISTRYINDEX, cbd.cbref);
- lua_pushboolean (L, false);
- lua_pushfstring (L, "failed to load config: %s", err->message);
- g_error_free (err);
- g_hash_table_unref (paths);
-
- return 2;
- }
-
- luaL_unref (L, LUA_REGISTRYINDEX, cbd.cbref);
- }
- else {
- if (!rspamd_config_parse_ucl (cfg, filename, paths, NULL, NULL,
- lua_toboolean (L, 3), &err)) {
- lua_pushboolean (L, false);
- lua_pushfstring (L, "failed to load config: %s", err->message);
- g_error_free (err);
- g_hash_table_unref (paths);
-
- return 2;
- }
- }
-
- rspamd_rcl_maybe_apply_lua_transform (cfg);
- rspamd_config_calculate_cksum (cfg);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- g_hash_table_unref (paths);
- lua_pushboolean (L, true);
-
- return 1;
- }
-
- #undef IDX_TO_HASH
-
- static gint
- lua_config_parse_rcl (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- GHashTable *excluded = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal,
- g_free, NULL);
- GError *err = NULL;
- struct rspamd_rcl_section *top;
-
- if (cfg) {
- if (lua_istable (L, 2)) {
- lua_pushvalue (L, 2);
-
- for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
- g_hash_table_insert (excluded, g_strdup (lua_tostring (L, -1)),
- GINT_TO_POINTER (-1));
- }
-
- lua_pop (L, 1);
- }
-
- top = rspamd_rcl_config_init (cfg, excluded);
-
- if (!rspamd_rcl_parse (top, cfg, cfg, cfg->cfg_pool, cfg->rcl_obj, &err)) {
- lua_pushboolean (L, false);
- lua_pushfstring (L, "failed to load config: %s", err->message);
- g_error_free (err);
- g_hash_table_unref (excluded);
- rspamd_rcl_section_free (top);
-
- return 2;
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- g_hash_table_unref (excluded);
- rspamd_rcl_section_free (top);
- lua_pushboolean (L, true);
-
- return 1;
- }
-
- static gint
- lua_config_init_modules (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL) {
- rspamd_lua_post_load_config (cfg);
- lua_pushboolean (L, rspamd_init_filters (cfg, FALSE));
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_config_init_subsystem (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *subsystem = luaL_checkstring (L, 2);
- gchar **parts;
- guint nparts, i;
-
- if (cfg != NULL && subsystem != NULL) {
- parts = g_strsplit_set (subsystem, ";,", -1);
- nparts = g_strv_length (parts);
-
- for (i = 0; i < nparts; i ++) {
- if (strcmp (parts[i], "filters") == 0) {
- rspamd_lua_post_load_config (cfg);
- rspamd_init_filters (cfg, FALSE);
- }
- else if (strcmp (parts[i], "langdet") == 0) {
- cfg->lang_det = rspamd_language_detector_init (cfg);
- }
- else if (strcmp (parts[i], "stat") == 0) {
- rspamd_stat_init (cfg, NULL);
- }
- else if (strcmp (parts[i], "dns") == 0) {
- struct ev_loop *ev_base = lua_check_ev_base (L, 3);
-
- if (ev_base) {
- cfg->dns_resolver = rspamd_dns_resolver_init (rspamd_logger_get_singleton (),
- ev_base,
- cfg);
- }
- else {
- g_strfreev (parts);
-
- return luaL_error (L, "no event base specified");
- }
- }
- else {
- g_strfreev (parts);
-
- return luaL_error (L, "invalid param: %s", parts[i]);
- }
- }
-
- g_strfreev (parts);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 0;
- }
-
- static gint
- lua_config_register_re_selector (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
- const gchar *name = luaL_checkstring (L, 2);
- const gchar *selector_str = luaL_checkstring (L, 3);
- const gchar *delimiter = "";
- gint top = lua_gettop (L);
- bool res = false;
-
- if (cfg && name && selector_str) {
- if (lua_gettop (L) >= 4) {
- delimiter = luaL_checkstring (L, 4);
- }
-
- if (luaL_dostring (L, "return require \"lua_selectors\"") != 0) {
- msg_warn_config ("cannot require lua_selectors: %s",
- lua_tostring (L, -1));
- }
- else {
- if (lua_type (L, -1) != LUA_TTABLE) {
- msg_warn_config ("lua selectors must return "
- "table and not %s",
- lua_typename (L, lua_type (L, -1)));
- }
- else {
- lua_pushstring (L, "create_selector_closure");
- lua_gettable (L, -2);
-
- if (lua_type (L, -1) != LUA_TFUNCTION) {
- msg_warn_config ("create_selector_closure must return "
- "function and not %s",
- lua_typename (L, lua_type (L, -1)));
- }
- else {
- gint err_idx, ret;
- struct rspamd_config **pcfg;
-
- lua_pushcfunction (L, &rspamd_lua_traceback);
- err_idx = lua_gettop (L);
-
- /* Push function */
- lua_pushvalue (L, -2);
-
- pcfg = lua_newuserdata (L, sizeof (*pcfg));
- rspamd_lua_setclass (L, "rspamd{config}", -1);
- *pcfg = cfg;
- lua_pushstring (L, selector_str);
- lua_pushstring (L, delimiter);
-
- if ((ret = lua_pcall (L, 3, 1, err_idx)) != 0) {
- msg_err_config ("call to create_selector_closure lua "
- "script failed (%d): %s", ret,
- lua_tostring (L, -1));
- }
- else {
- if (lua_type (L, -1) != LUA_TFUNCTION) {
- msg_warn_config ("create_selector_closure "
- "invocation must return "
- "function and not %s",
- lua_typename (L, lua_type (L, -1)));
- }
- else {
- ret = luaL_ref (L, LUA_REGISTRYINDEX);
- rspamd_re_cache_add_selector (cfg->re_cache,
- name, ret);
- res = true;
- }
- }
- }
- }
- }
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- lua_settop (L, top);
- lua_pushboolean (L, res);
-
- if (res) {
- msg_info_config ("registered regexp selector %s", name);
- }
-
- return 1;
- }
-
- static gint
- lua_config_get_tld_path (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config (L, 1);
-
- if (cfg != NULL) {
- lua_pushstring (L, cfg->tld_file);
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_monitored_alive (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_monitored *m = lua_check_monitored (L, 1);
-
- if (m) {
- lua_pushboolean (L, rspamd_monitored_alive (m));
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_monitored_offline (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_monitored *m = lua_check_monitored (L, 1);
-
- if (m) {
- lua_pushnumber (L, rspamd_monitored_offline_time (m));
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_monitored_total_offline (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_monitored *m = lua_check_monitored (L, 1);
-
- if (m) {
- lua_pushnumber (L, rspamd_monitored_total_offline_time (m));
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- static gint
- lua_monitored_latency (lua_State *L)
- {
- LUA_TRACE_POINT;
- struct rspamd_monitored *m = lua_check_monitored (L, 1);
-
- if (m) {
- lua_pushnumber (L, rspamd_monitored_latency (m));
- }
- else {
- return luaL_error (L, "invalid arguments");
- }
-
- return 1;
- }
-
- void
- luaopen_config (lua_State * L)
- {
- rspamd_lua_new_class (L, "rspamd{config}", configlib_m);
-
- lua_pop (L, 1);
-
- rspamd_lua_new_class (L, "rspamd{monitored}", monitoredlib_m);
-
- lua_pop (L, 1);
- }
-
- void
- lua_call_finish_script (struct rspamd_config_cfg_lua_script *sc,
- struct rspamd_task *task) {
-
- struct rspamd_task **ptask;
- struct thread_entry *thread;
-
- thread = lua_thread_pool_get_for_task (task);
- thread->task = task;
-
- lua_State *L = thread->lua_state;
-
- lua_rawgeti (L, LUA_REGISTRYINDEX, sc->cbref);
-
- ptask = lua_newuserdata (L, sizeof (struct rspamd_task *));
- rspamd_lua_setclass (L, "rspamd{task}", - 1);
- *ptask = task;
-
- lua_thread_call (thread, 1);
- }
|