You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lua_task.c 112KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842
  1. /*-
  2. * Copyright 2016 Vsevolod Stakhov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include "lua_common.h"
  17. #include "message.h"
  18. #include "images.h"
  19. #include "archives.h"
  20. #include "utlist.h"
  21. #include "unix-std.h"
  22. #include "libmime/smtp_parsers.h"
  23. #include "libserver/mempool_vars_internal.h"
  24. #include <math.h>
  25. /***
  26. * @module rspamd_task
  27. * This module provides routines for tasks manipulation in rspamd. Tasks usually
  28. * represent messages being scanned, and this API provides access to such elements
  29. * as headers, symbols, metrics and so on and so forth. Normally, task objects
  30. * are passed to the lua callbacks allowing to check specific properties of messages
  31. * and add the corresponding symbols to the scan's results.
  32. @example
  33. rspamd_config.DATE_IN_PAST = function(task)
  34. local dm = task:get_date{format = 'message', gmt = true}
  35. local dt = task:get_date{format = 'connect', gmt = true}
  36. -- A day
  37. if dt - dm > 86400 then
  38. return true
  39. end
  40. return false
  41. end
  42. */
  43. /* Task methods */
  44. LUA_FUNCTION_DEF (task, get_message);
  45. LUA_FUNCTION_DEF (task, process_message);
  46. /***
  47. * @method task:get_cfg()
  48. * Get configuration object for a task.
  49. * @return {rspamd_config} (config.md)[configuration object] for the task
  50. */
  51. LUA_FUNCTION_DEF (task, get_cfg);
  52. LUA_FUNCTION_DEF (task, set_cfg);
  53. LUA_FUNCTION_DEF (task, destroy);
  54. /***
  55. * @method task:get_mempool()
  56. * Returns memory pool valid for a lifetime of task. It is used internally by
  57. * many rspamd routines.
  58. * @return {rspamd_mempool} memory pool object
  59. */
  60. LUA_FUNCTION_DEF (task, get_mempool);
  61. /***
  62. * @method task:get_session()
  63. * Returns asynchronous session object that is used by many rspamd asynchronous
  64. * utilities internally.
  65. * @return {rspamd_session} session object
  66. */
  67. LUA_FUNCTION_DEF (task, get_session);
  68. /***
  69. * @method task:get_ev_base()
  70. * Return asynchronous event base for using in callbacks and resolver.
  71. * @return {rspamd_ev_base} event base
  72. */
  73. LUA_FUNCTION_DEF (task, get_ev_base);
  74. /***
  75. * @method task:get_worker()
  76. * Returns a worker object associated with the task
  77. * @return {rspamd_worker} worker object
  78. */
  79. LUA_FUNCTION_DEF (task, get_worker);
  80. /***
  81. * @method task:insert_result(symbol, weight[, option1, ...])
  82. * Insert specific symbol to the tasks scanning results assigning the initial
  83. * weight to it.
  84. * @param {string} symbol symbol to insert
  85. * @param {number} weight initial weight (this weight is multiplied by the metric weight)
  86. * @param {string} options list of optional options attached to a symbol inserted
  87. @example
  88. local function cb(task)
  89. if task:get_header('Some header') then
  90. task:insert_result('SOME_HEADER', 1.0, 'Got some header')
  91. end
  92. end
  93. */
  94. LUA_FUNCTION_DEF (task, insert_result);
  95. /***
  96. * @method task:adjust_result(symbol, score[, option1, ...])
  97. * Alters the existing symbol's score to a new score. It is not affected by
  98. * metric score or grow factor. You can also add new options
  99. * using this method. Symbol must be already inserted into metric or an error
  100. * will be emitted.
  101. * @param {string} symbol symbol to adjust
  102. * @param {number} score this value is NOT multiplied by the metric score
  103. * @param {string/table} options list of optional options attached to a symbol adjusted
  104. */
  105. LUA_FUNCTION_DEF (task, adjust_result);
  106. /***
  107. * @method task:set_pre_result(action, description)
  108. * Sets pre-result for a task. It is used in pre-filters to specify early result
  109. * of the task scanned. If a pre-filter sets some result, then further processing
  110. * may be skipped. For selecting action it is possible to use global table
  111. * `rspamd_actions` or a string value:
  112. *
  113. * - `reject`: reject message permanently
  114. * - `add header`: add spam header
  115. * - `rewrite subject`: rewrite subject to spam subject
  116. * - `greylist`: greylist message
  117. * - `accept` or `no action`: whitelist message
  118. * @param {rspamd_action or string} action a numeric or string action value
  119. * @param {string} description optional description
  120. @example
  121. local function cb(task)
  122. local gr = task:get_header('Greylist')
  123. if gr and gr == 'greylist' then
  124. task:set_pre_result(rspamd_actions['greylist'], 'Greylisting required')
  125. end
  126. end
  127. */
  128. LUA_FUNCTION_DEF (task, set_pre_result);
  129. /***
  130. * @method task:append_message(message)
  131. * Adds a message to scanning output.
  132. * @param {string} message
  133. @example
  134. local function cb(task)
  135. task:append_message('Example message')
  136. end
  137. */
  138. LUA_FUNCTION_DEF (task, append_message);
  139. /***
  140. * @method task:get_urls([need_emails])
  141. * Get all URLs found in a message.
  142. * @param {boolean} need_emails if `true` then reutrn also email urls
  143. * @return {table rspamd_url} list of all urls found
  144. @example
  145. local function phishing_cb(task)
  146. local urls = task:get_urls();
  147. if urls then
  148. for _,url in ipairs(urls) do
  149. if url:is_phished() then
  150. return true
  151. end
  152. end
  153. end
  154. return false
  155. end
  156. */
  157. LUA_FUNCTION_DEF (task, get_urls);
  158. /***
  159. * @method task:has_urls([need_emails])
  160. * Returns 'true' if a task has urls listed
  161. * @param {boolean} need_emails if `true` then reutrn also email urls
  162. * @return {boolean} true if a task has urls (urls or emails if `need_emails` is true)
  163. */
  164. LUA_FUNCTION_DEF (task, has_urls);
  165. /***
  166. * @method task:get_content()
  167. * Get raw content for the specified task
  168. * @return {text} the data contained in the task
  169. */
  170. LUA_FUNCTION_DEF (task, get_content);
  171. /***
  172. * @method task:get_filename()
  173. * Returns filename for a specific task
  174. * @return {string|nil} filename or nil if unknown
  175. */
  176. LUA_FUNCTION_DEF (task, get_filename);
  177. /***
  178. * @method task:get_rawbody()
  179. * Get raw body for the specified task
  180. * @return {text} the data contained in the task
  181. */
  182. LUA_FUNCTION_DEF (task, get_rawbody);
  183. /***
  184. * @method task:get_emails()
  185. * Get all email addresses found in a message.
  186. * @return {table rspamd_url} list of all email addresses found
  187. */
  188. LUA_FUNCTION_DEF (task, get_emails);
  189. /***
  190. * @method task:get_text_parts()
  191. * Get all text (and HTML) parts found in a message
  192. * @return {table rspamd_text_part} list of text parts
  193. */
  194. LUA_FUNCTION_DEF (task, get_text_parts);
  195. /***
  196. * @method task:get_parts()
  197. * Get all mime parts found in a message
  198. * @return {table rspamd_mime_part} list of mime parts
  199. */
  200. LUA_FUNCTION_DEF (task, get_parts);
  201. /***
  202. * @method task:get_request_header(name)
  203. * Get value of a HTTP request header.
  204. * @param {string} name name of header to get
  205. * @return {rspamd_text} value of an HTTP header
  206. */
  207. LUA_FUNCTION_DEF (task, get_request_header);
  208. /***
  209. * @method task:set_request_header(name, value)
  210. * Set value of a HTTP request header. If value is omitted, then a header is removed
  211. * @param {string} name name of header to get
  212. * @param {rspamd_text/string} value new header's value
  213. */
  214. LUA_FUNCTION_DEF (task, set_request_header);
  215. /***
  216. * @method task:get_subject()
  217. * Returns task subject (either from the protocol override or from a header)
  218. * @return {string} value of a subject (decoded)
  219. */
  220. LUA_FUNCTION_DEF (task, get_subject);
  221. /***
  222. * @method task:get_header(name[, case_sensitive])
  223. * Get decoded value of a header specified with optional case_sensitive flag.
  224. * By default headers are searched in caseless matter.
  225. * @param {string} name name of header to get
  226. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  227. * @return {string} decoded value of a header
  228. */
  229. LUA_FUNCTION_DEF (task, get_header);
  230. /***
  231. * @method task:get_header_raw(name[, case_sensitive])
  232. * Get raw value of a header specified with optional case_sensitive flag.
  233. * By default headers are searched in caseless matter.
  234. * @param {string} name name of header to get
  235. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  236. * @return {string} raw value of a header
  237. */
  238. LUA_FUNCTION_DEF (task, get_header_raw);
  239. /***
  240. * @method task:get_header_full(name[, case_sensitive])
  241. * Get raw value of a header specified with optional case_sensitive flag.
  242. * By default headers are searched in caseless matter. This method returns more
  243. * information about the header as a list of tables with the following structure:
  244. *
  245. * - `name` - name of a header
  246. * - `value` - raw value of a header
  247. * - `decoded` - decoded value of a header
  248. * - `tab_separated` - `true` if a header and a value are separated by `tab` character
  249. * - `empty_separator` - `true` if there are no separator between a header and a value
  250. * @param {string} name name of header to get
  251. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  252. * @return {list of tables} all values of a header as specified above
  253. @example
  254. function check_header_delimiter_tab(task, header_name)
  255. for _,rh in ipairs(task:get_header_full(header_name)) do
  256. if rh['tab_separated'] then return true end
  257. end
  258. return false
  259. end
  260. */
  261. LUA_FUNCTION_DEF (task, get_header_full);
  262. /***
  263. * @method task:get_raw_headers()
  264. * Get all undecoded headers of a message as a string
  265. * @return {rspamd_text} all raw headers for a message as opaque text
  266. */
  267. LUA_FUNCTION_DEF (task, get_raw_headers);
  268. /***
  269. * @method task:get_received_headers()
  270. * Returns a list of tables of parsed received headers. A tables returned have
  271. * the following structure:
  272. *
  273. * - `from_hostname` - string that represents hostname provided by a peer
  274. * - `from_ip` - string representation of IP address as provided by a peer
  275. * - `real_hostname` - hostname as resolved by MTA
  276. * - `real_ip` - string representation of IP as resolved by PTR request of MTA
  277. * - `by_hostname` - MTA hostname
  278. * - `proto` - protocol, e.g. ESMTP or ESMTPS
  279. * - `timestamp` - received timestamp
  280. * - `for` - for value (unparsed mailbox)
  281. *
  282. * Please note that in some situations rspamd cannot parse all the fields of received headers.
  283. * In that case you should check all strings for validity.
  284. * @return {table of tables} list of received headers described above
  285. */
  286. LUA_FUNCTION_DEF (task, get_received_headers);
  287. /***
  288. * @method task:get_queue_id()
  289. * Returns queue ID of the message being processed.
  290. */
  291. LUA_FUNCTION_DEF (task, get_queue_id);
  292. /***
  293. * @method task:get_uid()
  294. * Returns ID of the task being processed.
  295. */
  296. LUA_FUNCTION_DEF (task, get_uid);
  297. /***
  298. * @method task:get_resolver()
  299. * Returns ready to use rspamd_resolver object suitable for making asynchronous DNS requests.
  300. * @return {rspamd_resolver} resolver object associated with the task's session
  301. * @example
  302. local logger = require "rspamd_logger"
  303. local function task_cb(task)
  304. local function dns_cb(resolver, to_resolve, results, err)
  305. -- task object is available due to closure
  306. task:inc_dns_req()
  307. if results then
  308. logger.info(string.format('<%s> [%s] resolved for symbol: %s',
  309. task:get_message_id(), to_resolve, 'EXAMPLE_SYMBOL'))
  310. task:insert_result('EXAMPLE_SYMBOL', 1)
  311. end
  312. end
  313. local r = task:get_resolver()
  314. r:resolve_a(task:get_session(), task:get_mempool(), 'example.com', dns_cb)
  315. end
  316. */
  317. LUA_FUNCTION_DEF (task, get_resolver);
  318. /***
  319. * @method task:inc_dns_req()
  320. * Increment number of DNS requests for the task. Is used just for logging purposes.
  321. */
  322. LUA_FUNCTION_DEF (task, inc_dns_req);
  323. /***
  324. * @method task:get_dns_req()
  325. * Get number of dns requests being sent in the task
  326. * @return {number} number of DNS requests
  327. */
  328. LUA_FUNCTION_DEF (task, get_dns_req);
  329. /***
  330. * @method task:has_recipients([type])
  331. * Return true if there are SMTP or MIME recipients for a task.
  332. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP recipients and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP recipients and `2` or `mime` means MIME recipients only
  333. * @return {bool} `true` if there are recipients of the following type
  334. */
  335. LUA_FUNCTION_DEF (task, has_recipients);
  336. /***
  337. * @method task:get_recipients([type])
  338. * Return SMTP or MIME recipients for a task. This function returns list of internet addresses each one is a table with the following structure:
  339. *
  340. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  341. * - `addr` - address part of the address
  342. * - `user` - user part (if present) of the address, e.g. `blah`
  343. * - `domain` - domain part (if present), e.g. `foo.com`
  344. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP recipients and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP recipients and `2` or `mime` means MIME recipients only
  345. * @return {list of addresses} list of recipients or `nil`
  346. */
  347. LUA_FUNCTION_DEF (task, get_recipients);
  348. /***
  349. * @method task:get_principal_recipient()
  350. * Returns a single string with so called `principal recipient` for a message. The order
  351. * of check is the following:
  352. *
  353. * - deliver-to request header
  354. * - the first recipient (envelope)
  355. * - the first recipient (mime)
  356. * @return {string} principal recipient
  357. */
  358. LUA_FUNCTION_DEF (task, get_principal_recipient);
  359. /***
  360. * @method task:set_recipients([type], {rcpt1, rcpt2...})
  361. * Sets sender for a task. This function accepts table that will be converted to the address.
  362. * If some fields are missing they are subsequently reconstructed by this function. E.g. if you
  363. * specify 'user' and 'domain', then address and raw string will be reconstructed
  364. *
  365. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  366. * - `addr` - address part of the address
  367. * - `user` - user part (if present) of the address, e.g. `blah`
  368. * - `domain` - domain part (if present), e.g. `foo.com`
  369. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP recipients and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP recipients and `2` or `mime` means MIME recipients only
  370. * @param {list of tables} recipients recipients to set
  371. * @return {boolean} result of the operation
  372. */
  373. LUA_FUNCTION_DEF (task, set_recipients);
  374. /***
  375. * @method task:has_from([type])
  376. * Return true if there is SMTP or MIME sender for a task.
  377. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP recipients and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP recipients and `2` or `mime` means MIME recipients only
  378. * @return {bool} `true` if there is sender of the following type
  379. */
  380. LUA_FUNCTION_DEF (task, has_from);
  381. /***
  382. * @method task:get_from([type])
  383. * Return SMTP or MIME sender for a task. This function returns an internet address which one is a table with the following structure:
  384. *
  385. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  386. * - `addr` - address part of the address
  387. * - `user` - user part (if present) of the address, e.g. `blah`
  388. * - `domain` - domain part (if present), e.g. `foo.com`
  389. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP sender and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP sender and `2` or `mime` means MIME `From:` only
  390. * @return {address} sender or `nil`
  391. */
  392. LUA_FUNCTION_DEF (task, get_from);
  393. /***
  394. * @method task:set_from(type, addr)
  395. * Sets sender for a task. This function accepts table that will be converted to the address.
  396. * If some fields are missing they are subsequently reconstructed by this function. E.g. if you
  397. * specify 'user' and 'domain', then address and raw string will be reconstructed
  398. *
  399. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  400. * - `addr` - address part of the address
  401. * - `user` - user part (if present) of the address, e.g. `blah`
  402. * - `domain` - domain part (if present), e.g. `foo.com`
  403. * @param {integer|string} type if specified has the following meaning: `0` or `any` means try SMTP sender and fallback to MIME if failed, `1` or `smtp` means checking merely SMTP sender and `2` or `mime` means MIME `From:` only
  404. * @param {table
  405. * @return {boolean} success or not
  406. */
  407. LUA_FUNCTION_DEF (task, set_from);
  408. /***
  409. * @method task:get_user()
  410. * Returns authenticated user name for this task if specified by an MTA.
  411. * @return {string} username or nil
  412. */
  413. LUA_FUNCTION_DEF (task, get_user);
  414. LUA_FUNCTION_DEF (task, set_user);
  415. /***
  416. * @method task:get_from_ip()
  417. * Returns [ip_addr](ip.md) object of a sender that is provided by MTA
  418. * @return {rspamd_ip} ip address object
  419. */
  420. LUA_FUNCTION_DEF (task, get_from_ip);
  421. /***
  422. * @method task:set_from_ip(str)
  423. * Set tasks's IP address based on the passed string
  424. * @param {string} str string representation of ip
  425. */
  426. LUA_FUNCTION_DEF (task, set_from_ip);
  427. LUA_FUNCTION_DEF (task, get_from_ip_num);
  428. /***
  429. * @method task:get_client_ip()
  430. * Returns [ip_addr](ip.md) object of a client connected to rspamd (normally, it is an IP address of MTA)
  431. * @return {rspamd_ip} ip address object
  432. */
  433. LUA_FUNCTION_DEF (task, get_client_ip);
  434. /***
  435. * @method task:get_helo()
  436. * Returns the value of SMTP helo provided by MTA.
  437. * @return {string} HELO value
  438. */
  439. LUA_FUNCTION_DEF (task, get_helo);
  440. LUA_FUNCTION_DEF (task, set_helo);
  441. /***
  442. * @method task:get_hostname()
  443. * Returns the value of sender's hostname provided by MTA
  444. * @return {string} hostname value
  445. */
  446. LUA_FUNCTION_DEF (task, get_hostname);
  447. LUA_FUNCTION_DEF (task, set_hostname);
  448. /***
  449. * @method task:get_images()
  450. * Returns list of all images found in a task as a table of `rspamd_image`.
  451. * Each image has the following methods:
  452. *
  453. * * `get_width` - return width of an image in pixels
  454. * * `get_height` - return height of an image in pixels
  455. * * `get_type` - return string representation of image's type (e.g. 'jpeg')
  456. * * `get_filename` - return string with image's file name
  457. * * `get_size` - return size in bytes
  458. * @return {list of rspamd_image} images found in a message
  459. */
  460. LUA_FUNCTION_DEF (task, get_images);
  461. /***
  462. * @method task:get_archives()
  463. * Returns list of all archives found in a task as a table of `rspamd_archive`.
  464. * Each archive has the following methods available:
  465. *
  466. * * `get_files` - return list of strings with filenames inside archive
  467. * * `get_files_full` - return list of tables with all information about files
  468. * * `is_encrypted` - return true if an archive is encrypted
  469. * * `get_type` - return string representation of image's type (e.g. 'zip')
  470. * * `get_filename` - return string with archive's file name
  471. * * `get_size` - return size in bytes
  472. * @return {list of rspamd_archive} archives found in a message
  473. */
  474. LUA_FUNCTION_DEF (task, get_archives);
  475. /***
  476. * @method task:get_symbol(name)
  477. * Searches for a symbol `name` in all metrics results and returns a list of tables
  478. * one per metric that describes the symbol inserted. Please note that this function
  479. * is intended to return values for **inserted** symbols, so if this symbol was not
  480. * inserted it won't be in the function's output. This method is useful for post-filters mainly.
  481. * The symbols are returned as the list of the following tables:
  482. *
  483. * - `metric` - name of metric
  484. * - `score` - score of a symbol in that metric
  485. * - `options` - a table of strings representing options of a symbol
  486. * - `group` - a group of symbol (or 'ungrouped')
  487. * @param {string} name symbol's name
  488. * @return {list of tables} list of tables or nil if symbol was not found in any metric
  489. */
  490. LUA_FUNCTION_DEF (task, get_symbol);
  491. /***
  492. * @method task:get_symbols_all()
  493. * Returns array of symbols matched in default metric with all metadata
  494. * @return {table} table of tables formatted as in `task:get_symbol()` except that `metric` is absent and `name` is added
  495. */
  496. LUA_FUNCTION_DEF (task, get_symbols_all);
  497. /***
  498. * @method task:get_symbols()
  499. * Returns array of all symbols matched for this task
  500. * @return {table, table} table of strings with symbols names + table of theirs scores
  501. */
  502. LUA_FUNCTION_DEF (task, get_symbols);
  503. /***
  504. * @method task:get_symbols_numeric()
  505. * Returns array of all symbols matched for this task
  506. * @return {table|number, table|number} table of numbers with symbols ids + table of theirs scores
  507. */
  508. LUA_FUNCTION_DEF (task, get_symbols_numeric);
  509. /***
  510. * @method task:get_symbols_tokens()
  511. * Returns array of all symbols as statistical tokens
  512. * @return {table|number} table of numbers
  513. */
  514. LUA_FUNCTION_DEF (task, get_symbols_tokens);
  515. /***
  516. * @method task:has_symbol(name)
  517. * Fast path to check if a specified symbol is in the task's results
  518. * @param {string} name symbol's name
  519. * @return {boolean} `true` if symbol has been found
  520. */
  521. LUA_FUNCTION_DEF (task, has_symbol);
  522. /***
  523. * @method task:get_date(type[, gmt])
  524. * Returns timestamp for a connection or for a MIME message. This function can be called with a
  525. * single table arguments with the following fields:
  526. *
  527. * * `format` - a format of date returned:
  528. * - `message` - returns a mime date as integer (unix timestamp)
  529. * - `message_str` - returns a mime date as string (UTC format)
  530. * - `connect` - returns a unix timestamp of a connection to rspamd
  531. * - `connect_str` - returns connection time in UTC format
  532. * * `gmt` - returns date in `GMT` timezone (normal for unix timestamps)
  533. *
  534. * By default this function returns connection time in numeric format.
  535. * @param {string} type date format as described above
  536. * @param {boolean} gmt gmt flag as described above
  537. * @return {string/number} date representation according to format
  538. * @example
  539. rspamd_config.DATE_IN_PAST = function(task)
  540. local dm = task:get_date{format = 'message', gmt = true}
  541. local dt = task:get_date{format = 'connect', gmt = true}
  542. -- A day
  543. if dt - dm > 86400 then
  544. return true
  545. end
  546. return false
  547. end
  548. */
  549. LUA_FUNCTION_DEF (task, get_date);
  550. /***
  551. * @method task:get_message_id()
  552. * Returns message id of the specified task
  553. * @return {string} if of a message
  554. */
  555. LUA_FUNCTION_DEF (task, get_message_id);
  556. LUA_FUNCTION_DEF (task, get_timeval);
  557. /***
  558. * @method task:get_metric_score(name)
  559. * Get the current score of metric `name`. Should be used in post-filters only.
  560. * @param {string} name name of a metric
  561. * @return {table} table containing the current score and required score of the metric
  562. */
  563. LUA_FUNCTION_DEF (task, get_metric_score);
  564. /***
  565. * @method task:get_metric_action(name)
  566. * Get the current action of metric `name`. Should be used in post-filters only.
  567. * @param {string} name name of a metric
  568. * @return {string} the current action of the metric as a string
  569. */
  570. LUA_FUNCTION_DEF (task, get_metric_action);
  571. /***
  572. * @method task:set_metric_score(name, score)
  573. * Set the current score of metric `name`. Should be used in post-filters only.
  574. * @param {string} name name of a metric
  575. * @param {number} score the current score of the metric
  576. */
  577. LUA_FUNCTION_DEF (task, set_metric_score);
  578. /***
  579. * @method task:set_metric_subject(subject)
  580. * Set the subject in the default metric
  581. * @param {string} subject subject to set
  582. */
  583. LUA_FUNCTION_DEF (task, set_metric_subject);
  584. /***
  585. * @method task:learn(is_spam[, classifier)
  586. * Learn classifier `classifier` with the task. If `is_spam` is true then message
  587. * is learnt as spam. Otherwise HAM is learnt. By default, this function learns
  588. * `bayes` classifier.
  589. * @param {boolean} is_spam learn spam or ham
  590. * @param {string} classifier classifier's name
  591. * @return {boolean} `true` if classifier has been learnt successfully
  592. */
  593. LUA_FUNCTION_DEF (task, learn);
  594. /***
  595. * @method task:set_settings(obj)
  596. * Set users settings object for a task. The format of this object is described
  597. * [here](https://rspamd.com/doc/configuration/settings.html).
  598. * @param {any} obj any lua object that corresponds to the settings format
  599. */
  600. LUA_FUNCTION_DEF (task, set_settings);
  601. /***
  602. * @method task:get_settings()
  603. * Gets users settings object for a task. The format of this object is described
  604. * [here](https://rspamd.com/doc/configuration/settings.html).
  605. * @return {lua object} lua object generated from UCL
  606. */
  607. LUA_FUNCTION_DEF (task, get_settings);
  608. /***
  609. * @method task:lookup_settings(key)
  610. * Gets users settings object with the specified key for a task.
  611. * @param {string} key key to lookup
  612. * @return {lua object} lua object generated from UCL
  613. */
  614. LUA_FUNCTION_DEF (task, lookup_settings);
  615. /***
  616. * @method task:get_settings_id()
  617. * Get numeric hash of settings id if specified for this task. 0 is returned otherwise.
  618. * @return {number} settings-id hash
  619. */
  620. LUA_FUNCTION_DEF (task, get_settings_id);
  621. /***
  622. * @method task:set_milter_reply(obj)
  623. * Set special reply for milter
  624. * @param {any} obj any lua object that corresponds to the settings format
  625. * @example
  626. task:set_milter_reply({
  627. add_headers = {['X-Lua'] = 'test'},
  628. -- 1 is the position of header to remove
  629. remove_headers = {['DKIM-Signature'] = 1},
  630. })
  631. */
  632. LUA_FUNCTION_DEF (task, set_milter_reply);
  633. /***
  634. * @method task:process_re(params)
  635. * Processes the specified regexp and returns number of captures (cached or new)
  636. * Params is the table with the following fields (mandatory fields are marked with `*`):
  637. * - `re`* : regular expression object
  638. * - `type`*: type of regular expression:
  639. * + `mime`: mime regexp
  640. * + `header`: header regexp
  641. * + `rawheader`: raw header expression
  642. * + `rawmime`: raw mime regexp
  643. * + `body`: raw body regexp
  644. * + `url`: url regexp
  645. * - `header`: for header and rawheader regexp means the name of header
  646. * - `strong`: case sensitive match for headers
  647. * @return {number} number of regexp occurrences in the task (limited by 255 so far)
  648. */
  649. LUA_FUNCTION_DEF (task, process_regexp);
  650. /***
  651. * @method task:cache_set(key, value)
  652. * Store some value to the task cache
  653. * @param {string} key key to use
  654. * @param {any} value any value (including functions and tables)
  655. */
  656. LUA_FUNCTION_DEF (task, cache_set);
  657. /***
  658. * @method task:cache_get(key)
  659. * Returns cached value or nil if nothing is cached
  660. * @param {string} key key to use
  661. * @return {any} cached value
  662. */
  663. LUA_FUNCTION_DEF (task, cache_get);
  664. /***
  665. * @method task:get_size()
  666. * Returns size of the task in bytes (that includes headers + parts size)
  667. * @return {number} size in bytes
  668. */
  669. LUA_FUNCTION_DEF (task, get_size);
  670. /***
  671. * @method task:set_flag(flag_name[, set])
  672. * Set specific flag for task:
  673. *
  674. * - `no_log`: do not log task summary
  675. * - `no_stat`: do not include task into scanned stats
  676. * - `pass_all`: check all filters for task
  677. * - `extended_urls`: output extended info about urls
  678. * - `skip`: skip task processing
  679. * - `learn_spam`: learn message as spam
  680. * - `learn_ham`: learn message as ham
  681. * - `broken_headers`: header data is broken for a message
  682. * @param {string} flag to set
  683. * @param {boolean} set set or clear flag (default is set)
  684. @example
  685. --[[
  686. For messages with undefined queue ID (scanned with rspamc or WebUI)
  687. do not include results into statistics and do not log task summary
  688. (it will not appear in the WebUI history as well).
  689. ]]--
  690. -- Callback function to set flags
  691. local function no_log_stat_cb(task)
  692. if not task:get_queue_id() then
  693. task:set_flag('no_log')
  694. task:set_flag('no_stat')
  695. end
  696. end
  697. rspamd_config:register_symbol({
  698. name = 'LOCAL_NO_LOG_STAT',
  699. type = 'postfilter',
  700. callback = no_log_stat_cb
  701. })
  702. */
  703. LUA_FUNCTION_DEF (task, set_flag);
  704. /***
  705. * @method task:has_flag(flag_name)
  706. * Checks for a specific flag in task:
  707. *
  708. * - `no_log`: do not log task summary
  709. * - `no_stat`: do not include task into scanned stats
  710. * - `pass_all`: check all filters for task
  711. * - `extended_urls`: output extended info about urls
  712. * - `skip`: skip task processing
  713. * - `learn_spam`: learn message as spam
  714. * - `learn_ham`: learn message as ham
  715. * - `broken_headers`: header data is broken for a message
  716. * @param {string} flag to check
  717. * @return {boolean} true if flags is set
  718. */
  719. LUA_FUNCTION_DEF (task, has_flag);
  720. /***
  721. * @method task:get_flags()
  722. * Get list of flags for task:
  723. *
  724. * - `no_log`: do not log task summary
  725. * - `no_stat`: do not include task into scanned stats
  726. * - `pass_all`: check all filters for task
  727. * - `extended_urls`: output extended info about urls
  728. * - `skip`: skip task processing
  729. * - `learn_spam`: learn message as spam
  730. * - `learn_ham`: learn message as ham
  731. * - `broken_headers`: header data is broken for a message
  732. * - `milter`: task is initiated by milter connection
  733. * @return {array of strings} table with all flags as strings
  734. */
  735. LUA_FUNCTION_DEF (task, get_flags);
  736. /***
  737. * @method task:get_digest()
  738. * Returns message's unique digest (32 hex symbols)
  739. * @return {string} hex digest
  740. */
  741. LUA_FUNCTION_DEF (task, get_digest);
  742. /***
  743. * @method task:store_in_file([mode|table])
  744. * If task was loaded using file scan, then this method just returns its name,
  745. * otherwise, a fresh temporary file is created and its name is returned. Default
  746. * mode is 0600. To convert lua number to the octal mode you can use the following
  747. * trick: `tonumber("0644", 8)`. The file is automatically removed when task is
  748. * destroyed.
  749. *
  750. * If table argument is specified, the following extra fields are allowed:
  751. *
  752. * - `mode`: same as mode argument
  753. * - `force_new`: always create a new file
  754. * - `filename`: use specific filename instead of a temporary one
  755. * - `tmpmask`: use specific tempmask, e.g. '/tmp/file-XXXXX', where XXXX will be replaced by some random letters
  756. * - `keep`: do not remove file after task is processed
  757. *
  758. * @param {number} mode mode for new file
  759. * @return {string} file name with task content
  760. */
  761. LUA_FUNCTION_DEF (task, store_in_file);
  762. /***
  763. * @method task:get_protocol_reply([flags])
  764. * This method being called from a **postfilter** will return reply for a message
  765. * as it is returned to a client. This method returns the Lua table corresponding
  766. * to the UCL object. Flags is a table that specify which information should be
  767. * there in a reply:
  768. *
  769. * - `basic`: basic info, such as message-id
  770. * - `metrics`: metrics and symbols
  771. * - `messages`: messages
  772. * - `dkim`: dkim signature
  773. * - `milter`: milter control block
  774. * - `extra`: extra data, such as profiling
  775. * - `urls`: list of all urls in a message
  776. *
  777. * @param {table} flags table of flags (default is all flags but `urls`)
  778. * @return {table} ucl object corresponding to the reply
  779. */
  780. LUA_FUNCTION_DEF (task, get_protocol_reply);
  781. /***
  782. * @method task:headers_foreach(callback, [params])
  783. * This method calls `callback` for each header that satisfies some condition.
  784. * By default, all headers are iterated unless `callback` returns `true`. Nil or
  785. * false means continue of iterations.
  786. * Params could be as following:
  787. *
  788. * - `full`: header value is full table of all attributes @see task:get_header_full for details
  789. * - `regexp`: return headers that satisfies the specified regexp
  790. * @param {function} callback function from header name and header value
  791. * @param {table} params optional parameters
  792. */
  793. LUA_FUNCTION_DEF (task, headers_foreach);
  794. /***
  795. * @method task:disable_action(action)
  796. * Disables some action for this task (e.g. 'greylist')
  797. *
  798. * @param {string} action action to disable
  799. * @return {boolean} true if an action was enabled and is disabled after the method call
  800. */
  801. LUA_FUNCTION_DEF (task, disable_action);
  802. /***
  803. * @method task:get_newlines_type()
  804. * Returns the most frequent newlines type met in a task
  805. *
  806. * @return {string} "cr" for \r, "lf" for \n, "crlf" for \r\n
  807. */
  808. LUA_FUNCTION_DEF (task, get_newlines_type);
  809. static const struct luaL_reg tasklib_f[] = {
  810. {NULL, NULL}
  811. };
  812. static const struct luaL_reg tasklib_m[] = {
  813. LUA_INTERFACE_DEF (task, get_message),
  814. LUA_INTERFACE_DEF (task, destroy),
  815. LUA_INTERFACE_DEF (task, process_message),
  816. LUA_INTERFACE_DEF (task, set_cfg),
  817. LUA_INTERFACE_DEF (task, get_cfg),
  818. LUA_INTERFACE_DEF (task, get_mempool),
  819. LUA_INTERFACE_DEF (task, get_session),
  820. LUA_INTERFACE_DEF (task, get_ev_base),
  821. LUA_INTERFACE_DEF (task, get_worker),
  822. LUA_INTERFACE_DEF (task, insert_result),
  823. LUA_INTERFACE_DEF (task, adjust_result),
  824. LUA_INTERFACE_DEF (task, set_pre_result),
  825. LUA_INTERFACE_DEF (task, append_message),
  826. LUA_INTERFACE_DEF (task, has_urls),
  827. LUA_INTERFACE_DEF (task, get_urls),
  828. LUA_INTERFACE_DEF (task, get_content),
  829. LUA_INTERFACE_DEF (task, get_filename),
  830. LUA_INTERFACE_DEF (task, get_rawbody),
  831. LUA_INTERFACE_DEF (task, get_emails),
  832. LUA_INTERFACE_DEF (task, get_text_parts),
  833. LUA_INTERFACE_DEF (task, get_parts),
  834. LUA_INTERFACE_DEF (task, get_request_header),
  835. LUA_INTERFACE_DEF (task, set_request_header),
  836. LUA_INTERFACE_DEF (task, get_header),
  837. LUA_INTERFACE_DEF (task, get_header_raw),
  838. LUA_INTERFACE_DEF (task, get_header_full),
  839. LUA_INTERFACE_DEF (task, get_raw_headers),
  840. LUA_INTERFACE_DEF (task, get_received_headers),
  841. LUA_INTERFACE_DEF (task, get_queue_id),
  842. LUA_INTERFACE_DEF (task, get_uid),
  843. LUA_INTERFACE_DEF (task, get_resolver),
  844. LUA_INTERFACE_DEF (task, inc_dns_req),
  845. LUA_INTERFACE_DEF (task, get_dns_req),
  846. LUA_INTERFACE_DEF (task, has_recipients),
  847. LUA_INTERFACE_DEF (task, get_recipients),
  848. LUA_INTERFACE_DEF (task, set_recipients),
  849. LUA_INTERFACE_DEF (task, get_principal_recipient),
  850. LUA_INTERFACE_DEF (task, has_from),
  851. LUA_INTERFACE_DEF (task, get_from),
  852. LUA_INTERFACE_DEF (task, set_from),
  853. LUA_INTERFACE_DEF (task, get_user),
  854. LUA_INTERFACE_DEF (task, set_user),
  855. {"get_addr", lua_task_get_from_ip},
  856. {"get_ip", lua_task_get_from_ip},
  857. {"get_from_addr", lua_task_get_from_ip},
  858. LUA_INTERFACE_DEF (task, get_from_ip),
  859. LUA_INTERFACE_DEF (task, set_from_ip),
  860. LUA_INTERFACE_DEF (task, get_from_ip_num),
  861. LUA_INTERFACE_DEF (task, get_client_ip),
  862. LUA_INTERFACE_DEF (task, get_subject),
  863. LUA_INTERFACE_DEF (task, get_helo),
  864. LUA_INTERFACE_DEF (task, set_helo),
  865. LUA_INTERFACE_DEF (task, get_hostname),
  866. LUA_INTERFACE_DEF (task, set_hostname),
  867. LUA_INTERFACE_DEF (task, get_images),
  868. LUA_INTERFACE_DEF (task, get_archives),
  869. LUA_INTERFACE_DEF (task, get_symbol),
  870. LUA_INTERFACE_DEF (task, get_symbols),
  871. LUA_INTERFACE_DEF (task, get_symbols_all),
  872. LUA_INTERFACE_DEF (task, get_symbols_numeric),
  873. LUA_INTERFACE_DEF (task, get_symbols_tokens),
  874. LUA_INTERFACE_DEF (task, has_symbol),
  875. LUA_INTERFACE_DEF (task, get_date),
  876. LUA_INTERFACE_DEF (task, get_message_id),
  877. LUA_INTERFACE_DEF (task, get_timeval),
  878. LUA_INTERFACE_DEF (task, get_metric_score),
  879. LUA_INTERFACE_DEF (task, get_metric_action),
  880. LUA_INTERFACE_DEF (task, set_metric_score),
  881. LUA_INTERFACE_DEF (task, set_metric_subject),
  882. LUA_INTERFACE_DEF (task, learn),
  883. LUA_INTERFACE_DEF (task, set_settings),
  884. LUA_INTERFACE_DEF (task, get_settings),
  885. LUA_INTERFACE_DEF (task, lookup_settings),
  886. LUA_INTERFACE_DEF (task, get_settings_id),
  887. LUA_INTERFACE_DEF (task, cache_get),
  888. LUA_INTERFACE_DEF (task, cache_set),
  889. LUA_INTERFACE_DEF (task, process_regexp),
  890. LUA_INTERFACE_DEF (task, get_size),
  891. LUA_INTERFACE_DEF (task, set_flag),
  892. LUA_INTERFACE_DEF (task, get_flags),
  893. LUA_INTERFACE_DEF (task, has_flag),
  894. {"set_rmilter_reply", lua_task_set_milter_reply},
  895. LUA_INTERFACE_DEF (task, set_milter_reply),
  896. LUA_INTERFACE_DEF (task, get_digest),
  897. LUA_INTERFACE_DEF (task, store_in_file),
  898. LUA_INTERFACE_DEF (task, get_protocol_reply),
  899. LUA_INTERFACE_DEF (task, headers_foreach),
  900. LUA_INTERFACE_DEF (task, disable_action),
  901. LUA_INTERFACE_DEF (task, get_newlines_type),
  902. {"__tostring", rspamd_lua_class_tostring},
  903. {NULL, NULL}
  904. };
  905. /* Image methods */
  906. LUA_FUNCTION_DEF (image, get_width);
  907. LUA_FUNCTION_DEF (image, get_height);
  908. LUA_FUNCTION_DEF (image, get_type);
  909. LUA_FUNCTION_DEF (image, get_filename);
  910. LUA_FUNCTION_DEF (image, get_size);
  911. static const struct luaL_reg imagelib_m[] = {
  912. LUA_INTERFACE_DEF (image, get_width),
  913. LUA_INTERFACE_DEF (image, get_height),
  914. LUA_INTERFACE_DEF (image, get_type),
  915. LUA_INTERFACE_DEF (image, get_filename),
  916. LUA_INTERFACE_DEF (image, get_size),
  917. {"__tostring", rspamd_lua_class_tostring},
  918. {NULL, NULL}
  919. };
  920. /* Archive methods */
  921. LUA_FUNCTION_DEF (archive, get_type);
  922. LUA_FUNCTION_DEF (archive, get_files);
  923. LUA_FUNCTION_DEF (archive, get_files_full);
  924. LUA_FUNCTION_DEF (archive, is_encrypted);
  925. LUA_FUNCTION_DEF (archive, get_filename);
  926. LUA_FUNCTION_DEF (archive, get_size);
  927. static const struct luaL_reg archivelib_m[] = {
  928. LUA_INTERFACE_DEF (archive, get_type),
  929. LUA_INTERFACE_DEF (archive, get_files),
  930. LUA_INTERFACE_DEF (archive, get_files_full),
  931. LUA_INTERFACE_DEF (archive, is_encrypted),
  932. LUA_INTERFACE_DEF (archive, get_filename),
  933. LUA_INTERFACE_DEF (archive, get_size),
  934. {"__tostring", rspamd_lua_class_tostring},
  935. {NULL, NULL}
  936. };
  937. /* Blob methods */
  938. LUA_FUNCTION_DEF (text, len);
  939. LUA_FUNCTION_DEF (text, str);
  940. LUA_FUNCTION_DEF (text, ptr);
  941. LUA_FUNCTION_DEF (text, save_in_file);
  942. LUA_FUNCTION_DEF (text, take_ownership);
  943. LUA_FUNCTION_DEF (text, gc);
  944. static const struct luaL_reg textlib_m[] = {
  945. LUA_INTERFACE_DEF (text, len),
  946. LUA_INTERFACE_DEF (text, str),
  947. LUA_INTERFACE_DEF (text, ptr),
  948. LUA_INTERFACE_DEF (text, take_ownership),
  949. LUA_INTERFACE_DEF (text, save_in_file),
  950. {"__len", lua_text_len},
  951. {"__tostring", lua_text_str},
  952. {"__gc", lua_text_gc},
  953. {NULL, NULL}
  954. };
  955. /* Utility functions */
  956. struct rspamd_task *
  957. lua_check_task (lua_State * L, gint pos)
  958. {
  959. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{task}");
  960. luaL_argcheck (L, ud != NULL, pos, "'task' expected");
  961. return ud ? *((struct rspamd_task **)ud) : NULL;
  962. }
  963. struct rspamd_task *
  964. lua_check_task_maybe (lua_State * L, gint pos)
  965. {
  966. void *ud = rspamd_lua_check_udata_maybe (L, pos, "rspamd{task}");
  967. return ud ? *((struct rspamd_task **)ud) : NULL;
  968. }
  969. static struct rspamd_image *
  970. lua_check_image (lua_State * L)
  971. {
  972. void *ud = rspamd_lua_check_udata (L, 1, "rspamd{image}");
  973. luaL_argcheck (L, ud != NULL, 1, "'image' expected");
  974. return ud ? *((struct rspamd_image **)ud) : NULL;
  975. }
  976. static struct rspamd_archive *
  977. lua_check_archive (lua_State * L)
  978. {
  979. void *ud = rspamd_lua_check_udata (L, 1, "rspamd{archive}");
  980. luaL_argcheck (L, ud != NULL, 1, "'archive' expected");
  981. return ud ? *((struct rspamd_archive **)ud) : NULL;
  982. }
  983. struct rspamd_lua_text *
  984. lua_check_text (lua_State * L, gint pos)
  985. {
  986. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{text}");
  987. luaL_argcheck (L, ud != NULL, pos, "'text' expected");
  988. return ud ? (struct rspamd_lua_text *)ud : NULL;
  989. }
  990. static void
  991. lua_task_set_cached (lua_State *L, struct rspamd_task *task, const gchar *key,
  992. gint pos, guint id)
  993. {
  994. struct rspamd_lua_cached_entry *entry;
  995. lua_pushvalue (L, pos);
  996. entry = g_hash_table_lookup (task->lua_cache, key);
  997. if (G_UNLIKELY (entry != NULL)) {
  998. /* Unref previous value */
  999. luaL_unref (L, LUA_REGISTRYINDEX, entry->ref);
  1000. }
  1001. else {
  1002. entry = rspamd_mempool_alloc (task->task_pool, sizeof (*entry));
  1003. g_hash_table_insert (task->lua_cache, (void *)key, entry);
  1004. }
  1005. entry->ref = luaL_ref (L, LUA_REGISTRYINDEX);
  1006. entry->id = id;
  1007. }
  1008. static gboolean
  1009. lua_task_get_cached (lua_State *L, struct rspamd_task *task, const gchar *key,
  1010. guint id)
  1011. {
  1012. struct rspamd_lua_cached_entry *entry;
  1013. entry = g_hash_table_lookup (task->lua_cache, key);
  1014. if (entry != NULL && entry->id == id) {
  1015. lua_rawgeti (L, LUA_REGISTRYINDEX, entry->ref);
  1016. return TRUE;
  1017. }
  1018. return FALSE;
  1019. }
  1020. /* Task methods */
  1021. static int
  1022. lua_task_process_message (lua_State *L)
  1023. {
  1024. struct rspamd_task *task = lua_check_task (L, 1);
  1025. if (task != NULL) {
  1026. if (task->msg.len > 0) {
  1027. if (rspamd_message_parse (task) == 0) {
  1028. lua_pushboolean (L, TRUE);
  1029. }
  1030. else {
  1031. lua_pushboolean (L, FALSE);
  1032. }
  1033. }
  1034. else {
  1035. lua_pushnil (L);
  1036. }
  1037. }
  1038. else {
  1039. return luaL_error (L, "invalid arguments");
  1040. }
  1041. return 1;
  1042. }
  1043. static int
  1044. lua_task_get_cfg (lua_State *L)
  1045. {
  1046. struct rspamd_task *task = lua_check_task (L, 1);
  1047. struct rspamd_config **pcfg;
  1048. if (task) {
  1049. pcfg = lua_newuserdata (L, sizeof (gpointer));
  1050. rspamd_lua_setclass (L, "rspamd{config}", -1);
  1051. *pcfg = task->cfg;
  1052. }
  1053. else {
  1054. return luaL_error (L, "invalid arguments");
  1055. }
  1056. return 1;
  1057. }
  1058. static int
  1059. lua_task_set_cfg (lua_State *L)
  1060. {
  1061. struct rspamd_task *task = lua_check_task (L, 1);
  1062. void *ud = rspamd_lua_check_udata (L, 2, "rspamd{config}");
  1063. if (task) {
  1064. luaL_argcheck (L, ud != NULL, 1, "'config' expected");
  1065. task->cfg = ud ? *((struct rspamd_config **)ud) : NULL;
  1066. }
  1067. else {
  1068. return luaL_error (L, "invalid arguments");
  1069. }
  1070. return 0;
  1071. }
  1072. static int
  1073. lua_task_destroy (lua_State *L)
  1074. {
  1075. struct rspamd_task *task = lua_check_task (L, 1);
  1076. if (task != NULL) {
  1077. rspamd_task_free (task);
  1078. }
  1079. return 0;
  1080. }
  1081. static int
  1082. lua_task_get_message (lua_State * L)
  1083. {
  1084. return luaL_error (L, "task:get_message is no longer supported");
  1085. }
  1086. static int
  1087. lua_task_get_mempool (lua_State * L)
  1088. {
  1089. rspamd_mempool_t **ppool;
  1090. struct rspamd_task *task = lua_check_task (L, 1);
  1091. if (task != NULL) {
  1092. ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *));
  1093. rspamd_lua_setclass (L, "rspamd{mempool}", -1);
  1094. *ppool = task->task_pool;
  1095. }
  1096. else {
  1097. return luaL_error (L, "invalid arguments");
  1098. }
  1099. return 1;
  1100. }
  1101. static int
  1102. lua_task_get_session (lua_State * L)
  1103. {
  1104. struct rspamd_async_session **psession;
  1105. struct rspamd_task *task = lua_check_task (L, 1);
  1106. if (task != NULL) {
  1107. psession = lua_newuserdata (L, sizeof (void *));
  1108. rspamd_lua_setclass (L, "rspamd{session}", -1);
  1109. *psession = task->s;
  1110. }
  1111. else {
  1112. return luaL_error (L, "invalid arguments");
  1113. }
  1114. return 1;
  1115. }
  1116. static int
  1117. lua_task_get_ev_base (lua_State * L)
  1118. {
  1119. struct event_base **pbase;
  1120. struct rspamd_task *task = lua_check_task (L, 1);
  1121. if (task != NULL) {
  1122. pbase = lua_newuserdata (L, sizeof (struct event_base *));
  1123. rspamd_lua_setclass (L, "rspamd{ev_base}", -1);
  1124. *pbase = task->ev_base;
  1125. }
  1126. else {
  1127. return luaL_error (L, "invalid arguments");
  1128. }
  1129. return 1;
  1130. }
  1131. static int
  1132. lua_task_get_worker (lua_State * L)
  1133. {
  1134. struct rspamd_worker **pworker;
  1135. struct rspamd_task *task = lua_check_task (L, 1);
  1136. if (task != NULL) {
  1137. if (task->worker) {
  1138. pworker = lua_newuserdata (L, sizeof (struct rspamd_worker *));
  1139. rspamd_lua_setclass (L, "rspamd{worker}", -1);
  1140. *pworker = task->worker;
  1141. }
  1142. else {
  1143. lua_pushnil (L);
  1144. }
  1145. }
  1146. else {
  1147. return luaL_error (L, "invalid arguments");
  1148. }
  1149. return 1;
  1150. }
  1151. static gint
  1152. lua_task_insert_result (lua_State * L)
  1153. {
  1154. struct rspamd_task *task = lua_check_task (L, 1);
  1155. const gchar *symbol_name, *param;
  1156. double flag;
  1157. struct rspamd_symbol_result *s;
  1158. gint i, top;
  1159. if (task != NULL) {
  1160. symbol_name =
  1161. rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2));
  1162. flag = luaL_checknumber (L, 3);
  1163. top = lua_gettop (L);
  1164. s = rspamd_task_insert_result (task, symbol_name, flag, NULL);
  1165. /* Get additional options */
  1166. if (s) {
  1167. for (i = 4; i <= top; i++) {
  1168. if (lua_type (L, i) == LUA_TSTRING) {
  1169. param = luaL_checkstring (L, i);
  1170. rspamd_task_add_result_option (task, s, param);
  1171. }
  1172. else if (lua_type (L, i) == LUA_TTABLE) {
  1173. lua_pushvalue (L, i);
  1174. lua_pushnil (L);
  1175. while (lua_next (L, -2)) {
  1176. param = lua_tostring (L, -1);
  1177. rspamd_task_add_result_option (task, s, param);
  1178. lua_pop (L, 1);
  1179. }
  1180. lua_pop (L, 1);
  1181. }
  1182. }
  1183. }
  1184. }
  1185. else {
  1186. return luaL_error (L, "invalid arguments");
  1187. }
  1188. return 0;
  1189. }
  1190. static gint
  1191. lua_task_adjust_result (lua_State * L)
  1192. {
  1193. struct rspamd_task *task = lua_check_task (L, 1);
  1194. const gchar *symbol_name, *param;
  1195. struct rspamd_metric_result *metric_res;
  1196. struct rspamd_symbol_result *s = NULL;
  1197. double weight;
  1198. gint i, top;
  1199. if (task != NULL) {
  1200. symbol_name = luaL_checkstring (L, 2);
  1201. weight = luaL_checknumber (L, 3);
  1202. top = lua_gettop (L);
  1203. metric_res = task->result;
  1204. if (metric_res) {
  1205. s = g_hash_table_lookup (metric_res->symbols, symbol_name);
  1206. }
  1207. else {
  1208. return luaL_error (L, "no metric result");
  1209. }
  1210. if (s) {
  1211. metric_res->score -= s->score;
  1212. s->score = weight;
  1213. metric_res->score += s->score;
  1214. }
  1215. else {
  1216. return luaL_error (L, "symbol not found: %s", symbol_name);
  1217. }
  1218. /* Get additional options */
  1219. if (s) {
  1220. for (i = 4; i <= top; i++) {
  1221. if (lua_type (L, i) == LUA_TSTRING) {
  1222. param = luaL_checkstring (L, i);
  1223. rspamd_task_add_result_option (task, s, param);
  1224. }
  1225. else if (lua_type (L, i) == LUA_TTABLE) {
  1226. lua_pushvalue (L, i);
  1227. lua_pushnil (L);
  1228. while (lua_next (L, -2)) {
  1229. param = lua_tostring (L, -1);
  1230. rspamd_task_add_result_option (task, s, param);
  1231. lua_pop (L, 1);
  1232. }
  1233. lua_pop (L, 1);
  1234. }
  1235. }
  1236. }
  1237. }
  1238. else {
  1239. return luaL_error (L, "invalid arguments");
  1240. }
  1241. return 0;
  1242. }
  1243. static gint
  1244. lua_task_set_pre_result (lua_State * L)
  1245. {
  1246. struct rspamd_task *task = lua_check_task (L, 1);
  1247. gchar *action_str;
  1248. gint action = METRIC_ACTION_MAX;
  1249. if (task != NULL) {
  1250. if (lua_type (L, 2) == LUA_TNUMBER) {
  1251. action = lua_tointeger (L, 2);
  1252. }
  1253. else if (lua_type (L, 2) == LUA_TSTRING) {
  1254. rspamd_action_from_str (lua_tostring (L, 2), &action);
  1255. }
  1256. if (action < METRIC_ACTION_MAX && action >= METRIC_ACTION_REJECT) {
  1257. /* We also need to set the default metric to that result */
  1258. if (!task->result) {
  1259. task->result = rspamd_create_metric_result (task);
  1260. }
  1261. task->pre_result.action = action;
  1262. if (lua_gettop (L) >= 3) {
  1263. action_str = rspamd_mempool_strdup (task->task_pool,
  1264. luaL_checkstring (L, 3));
  1265. task->pre_result.str = action_str;
  1266. ucl_object_insert_key (task->messages,
  1267. ucl_object_fromstring (action_str), "smtp_message", 0,
  1268. false);
  1269. }
  1270. else {
  1271. task->pre_result.str = "unknown";
  1272. }
  1273. msg_info_task ("<%s>: set pre-result to %s: '%s'",
  1274. task->message_id, rspamd_action_to_str (action),
  1275. task->pre_result.str);
  1276. /* Don't classify or filter message if pre-filter sets results */
  1277. task->processed_stages |= (RSPAMD_TASK_STAGE_FILTERS |
  1278. RSPAMD_TASK_STAGE_CLASSIFIERS |
  1279. RSPAMD_TASK_STAGE_CLASSIFIERS_PRE |
  1280. RSPAMD_TASK_STAGE_CLASSIFIERS_POST);
  1281. }
  1282. else {
  1283. return luaL_error (L, "invalid arguments");
  1284. }
  1285. }
  1286. else {
  1287. return luaL_error (L, "invalid arguments");
  1288. }
  1289. return 0;
  1290. }
  1291. static gint
  1292. lua_task_append_message (lua_State * L)
  1293. {
  1294. struct rspamd_task *task = lua_check_task (L, 1);
  1295. const gchar *message = luaL_checkstring (L, 2), *category;
  1296. if (task != NULL) {
  1297. if (lua_type (L, 3) == LUA_TSTRING) {
  1298. category = luaL_checkstring (L, 3);
  1299. }
  1300. else {
  1301. category = "unknown";
  1302. }
  1303. ucl_object_insert_key (task->messages,
  1304. ucl_object_fromstring (message), category, 0,
  1305. true);
  1306. }
  1307. else {
  1308. return luaL_error (L, "invalid arguments");
  1309. }
  1310. return 0;
  1311. }
  1312. struct lua_tree_cb_data {
  1313. lua_State *L;
  1314. int i;
  1315. };
  1316. static void
  1317. lua_tree_url_callback (gpointer key, gpointer value, gpointer ud)
  1318. {
  1319. struct rspamd_lua_url *url;
  1320. struct lua_tree_cb_data *cb = ud;
  1321. url = lua_newuserdata (cb->L, sizeof (struct rspamd_lua_url));
  1322. rspamd_lua_setclass (cb->L, "rspamd{url}", -1);
  1323. url->url = value;
  1324. lua_rawseti (cb->L, -2, cb->i++);
  1325. }
  1326. static gint
  1327. lua_task_get_urls (lua_State * L)
  1328. {
  1329. struct rspamd_task *task = lua_check_task (L, 1);
  1330. struct lua_tree_cb_data cb;
  1331. gboolean need_emails = FALSE;
  1332. gsize sz;
  1333. if (task) {
  1334. if (lua_gettop (L) >= 2) {
  1335. need_emails = lua_toboolean (L, 2);
  1336. }
  1337. if (need_emails) {
  1338. sz = g_hash_table_size (task->urls) + g_hash_table_size (task->emails);
  1339. if (!lua_task_get_cached (L, task, "emails+urls", sz)) {
  1340. lua_createtable (L, sz, 0);
  1341. cb.i = 1;
  1342. cb.L = L;
  1343. g_hash_table_foreach (task->urls, lua_tree_url_callback, &cb);
  1344. g_hash_table_foreach (task->emails, lua_tree_url_callback, &cb);
  1345. lua_task_set_cached (L, task, "emails+urls", -1, sz);
  1346. }
  1347. }
  1348. else {
  1349. sz = g_hash_table_size (task->urls);
  1350. if (!lua_task_get_cached (L, task, "urls", sz)) {
  1351. lua_createtable (L, sz, 0);
  1352. cb.i = 1;
  1353. cb.L = L;
  1354. g_hash_table_foreach (task->urls, lua_tree_url_callback, &cb);
  1355. lua_task_set_cached (L, task, "urls", -1, sz);
  1356. }
  1357. }
  1358. }
  1359. else {
  1360. return luaL_error (L, "invalid arguments");
  1361. }
  1362. return 1;
  1363. }
  1364. static gint
  1365. lua_task_has_urls (lua_State * L)
  1366. {
  1367. struct rspamd_task *task = lua_check_task (L, 1);
  1368. gboolean need_emails = FALSE, ret = FALSE;
  1369. if (task) {
  1370. if (lua_gettop (L) >= 2) {
  1371. need_emails = lua_toboolean (L, 2);
  1372. }
  1373. if (g_hash_table_size (task->urls) > 0) {
  1374. ret = TRUE;
  1375. }
  1376. if (need_emails && g_hash_table_size (task->emails) > 0) {
  1377. ret = TRUE;
  1378. }
  1379. }
  1380. else {
  1381. return luaL_error (L, "invalid arguments");
  1382. }
  1383. lua_pushboolean (L, ret);
  1384. return 1;
  1385. }
  1386. static gint
  1387. lua_task_get_content (lua_State * L)
  1388. {
  1389. struct rspamd_task *task = lua_check_task (L, 1);
  1390. struct rspamd_lua_text *t;
  1391. if (task) {
  1392. t = lua_newuserdata (L, sizeof (*t));
  1393. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1394. t->len = task->msg.len;
  1395. t->start = task->msg.begin;
  1396. t->flags = 0;
  1397. }
  1398. else {
  1399. return luaL_error (L, "invalid arguments");
  1400. }
  1401. return 1;
  1402. }
  1403. static gint
  1404. lua_task_get_filename (lua_State * L)
  1405. {
  1406. struct rspamd_task *task = lua_check_task (L, 1);
  1407. if (task) {
  1408. if (task->msg.fpath) {
  1409. lua_pushstring (L, task->msg.fpath);
  1410. }
  1411. else {
  1412. lua_pushnil (L);
  1413. }
  1414. }
  1415. else {
  1416. return luaL_error (L, "invalid arguments");
  1417. }
  1418. return 1;
  1419. }
  1420. static gint
  1421. lua_task_get_rawbody (lua_State * L)
  1422. {
  1423. struct rspamd_task *task = lua_check_task (L, 1);
  1424. struct rspamd_lua_text *t;
  1425. if (task) {
  1426. t = lua_newuserdata (L, sizeof (*t));
  1427. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1428. if (task->raw_headers_content.len > 0) {
  1429. g_assert (task->raw_headers_content.len <= task->msg.len);
  1430. t->start = task->msg.begin + task->raw_headers_content.len;
  1431. t->len = task->msg.len - task->raw_headers_content.len;
  1432. }
  1433. else {
  1434. t->len = task->msg.len;
  1435. t->start = task->msg.begin;
  1436. }
  1437. t->flags = 0;
  1438. }
  1439. else {
  1440. return luaL_error (L, "invalid arguments");
  1441. }
  1442. return 1;
  1443. }
  1444. static gint
  1445. lua_task_get_emails (lua_State * L)
  1446. {
  1447. struct rspamd_task *task = lua_check_task (L, 1);
  1448. struct lua_tree_cb_data cb;
  1449. if (task) {
  1450. lua_createtable (L, g_hash_table_size (task->emails), 0);
  1451. cb.i = 1;
  1452. cb.L = L;
  1453. g_hash_table_foreach (task->emails, lua_tree_url_callback, &cb);
  1454. }
  1455. else {
  1456. return luaL_error (L, "invalid arguments");
  1457. }
  1458. return 1;
  1459. }
  1460. static gint
  1461. lua_task_get_text_parts (lua_State * L)
  1462. {
  1463. guint i;
  1464. struct rspamd_task *task = lua_check_task (L, 1);
  1465. struct rspamd_mime_text_part *part, **ppart;
  1466. if (task != NULL) {
  1467. if (!lua_task_get_cached (L, task, "text_parts", task->text_parts->len)) {
  1468. lua_createtable (L, task->text_parts->len, 0);
  1469. for (i = 0; i < task->text_parts->len; i ++) {
  1470. part = g_ptr_array_index (task->text_parts, i);
  1471. ppart = lua_newuserdata (L, sizeof (struct rspamd_mime_text_part *));
  1472. *ppart = part;
  1473. rspamd_lua_setclass (L, "rspamd{textpart}", -1);
  1474. /* Make it array */
  1475. lua_rawseti (L, -2, i + 1);
  1476. }
  1477. lua_task_set_cached (L, task, "text_parts", -1, task->text_parts->len);
  1478. }
  1479. }
  1480. else {
  1481. return luaL_error (L, "invalid arguments");
  1482. }
  1483. return 1;
  1484. }
  1485. static gint
  1486. lua_task_get_parts (lua_State * L)
  1487. {
  1488. guint i;
  1489. struct rspamd_task *task = lua_check_task (L, 1);
  1490. struct rspamd_mime_part *part, **ppart;
  1491. if (task != NULL) {
  1492. if (!lua_task_get_cached (L, task, "mime_parts", task->parts->len)) {
  1493. lua_createtable (L, task->parts->len, 0);
  1494. for (i = 0; i < task->parts->len; i ++) {
  1495. part = g_ptr_array_index (task->parts, i);
  1496. ppart = lua_newuserdata (L, sizeof (struct rspamd_mime_part *));
  1497. *ppart = part;
  1498. rspamd_lua_setclass (L, "rspamd{mimepart}", -1);
  1499. /* Make it array */
  1500. lua_rawseti (L, -2, i + 1);
  1501. }
  1502. lua_task_set_cached (L, task, "mime_parts", -1, task->parts->len);
  1503. }
  1504. }
  1505. else {
  1506. return luaL_error (L, "invalid arguments");
  1507. }
  1508. return 1;
  1509. }
  1510. static gint
  1511. lua_task_get_request_header (lua_State *L)
  1512. {
  1513. rspamd_ftok_t *hdr;
  1514. struct rspamd_task *task = lua_check_task (L, 1);
  1515. const gchar *s;
  1516. struct rspamd_lua_text *t;
  1517. s = luaL_checkstring (L, 2);
  1518. if (s && task) {
  1519. hdr = rspamd_task_get_request_header (task, s);
  1520. if (hdr) {
  1521. t = lua_newuserdata (L, sizeof (*t));
  1522. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1523. t->start = hdr->begin;
  1524. t->len = hdr->len;
  1525. t->flags = 0;
  1526. return 1;
  1527. }
  1528. else {
  1529. lua_pushnil (L);
  1530. }
  1531. }
  1532. else {
  1533. return luaL_error (L, "invalid arguments");
  1534. }
  1535. return 1;
  1536. }
  1537. static gint
  1538. lua_task_set_request_header (lua_State *L)
  1539. {
  1540. struct rspamd_task *task = lua_check_task (L, 1);
  1541. const gchar *s, *v = NULL;
  1542. rspamd_fstring_t *buf;
  1543. struct rspamd_lua_text *t;
  1544. rspamd_ftok_t *hdr, *new_name;
  1545. gsize len, vlen;
  1546. s = luaL_checklstring (L, 2, &len);
  1547. if (s && task) {
  1548. if (lua_type (L, 3) == LUA_TSTRING) {
  1549. v = luaL_checklstring (L, 2, &vlen);
  1550. }
  1551. else if (lua_type (L, 3) == LUA_TUSERDATA) {
  1552. t = lua_check_text (L, 3);
  1553. if (t != NULL) {
  1554. v = t->start;
  1555. vlen = t->len;
  1556. }
  1557. }
  1558. if (v != NULL) {
  1559. buf = rspamd_fstring_new_init (v, vlen);
  1560. hdr = rspamd_ftok_map (buf);
  1561. buf = rspamd_fstring_new_init (s, len);
  1562. new_name = rspamd_ftok_map (buf);
  1563. rspamd_task_add_request_header (task, new_name, hdr);
  1564. }
  1565. }
  1566. else {
  1567. return luaL_error (L, "invalid arguments");
  1568. }
  1569. return 0;
  1570. }
  1571. gint
  1572. rspamd_lua_push_header (lua_State *L, struct rspamd_mime_header *rh,
  1573. gboolean full, gboolean raw)
  1574. {
  1575. const gchar *val;
  1576. if (full) {
  1577. /* Create new associated table for a header */
  1578. lua_createtable (L, 0, 7);
  1579. rspamd_lua_table_set (L, "name", rh->name);
  1580. if (rh->value) {
  1581. rspamd_lua_table_set (L, "value", rh->value);
  1582. }
  1583. if (rh->decoded) {
  1584. rspamd_lua_table_set (L, "decoded", rh->decoded);
  1585. }
  1586. lua_pushstring (L, "tab_separated");
  1587. lua_pushboolean (L, rh->tab_separated);
  1588. lua_settable (L, -3);
  1589. lua_pushstring (L, "empty_separator");
  1590. lua_pushboolean (L, rh->empty_separator);
  1591. lua_settable (L, -3);
  1592. rspamd_lua_table_set (L, "separator", rh->separator);
  1593. lua_pushstring (L, "order");
  1594. lua_pushnumber (L, rh->order);
  1595. lua_settable (L, -3);
  1596. }
  1597. else {
  1598. if (!raw) {
  1599. val = rh->decoded;
  1600. }
  1601. else {
  1602. val = rh->value;
  1603. }
  1604. if (val) {
  1605. lua_pushstring (L, val);
  1606. }
  1607. else {
  1608. lua_pushnil (L);
  1609. }
  1610. }
  1611. return 1;
  1612. }
  1613. gint
  1614. rspamd_lua_push_header_array (lua_State * L,
  1615. GPtrArray *ar,
  1616. gboolean full,
  1617. gboolean raw)
  1618. {
  1619. struct rspamd_mime_header *rh;
  1620. guint i;
  1621. if (ar == NULL || ar->len == 0) {
  1622. lua_pushnil (L);
  1623. return 1;
  1624. }
  1625. if (full) {
  1626. lua_createtable (L, ar->len, 0);
  1627. }
  1628. PTR_ARRAY_FOREACH (ar, i, rh) {
  1629. if (full) {
  1630. rspamd_lua_push_header (L, rh, full, raw);
  1631. lua_rawseti (L, -2, i + 1);
  1632. }
  1633. else {
  1634. return rspamd_lua_push_header (L, rh, full, raw);
  1635. }
  1636. }
  1637. return 1;
  1638. }
  1639. static gint
  1640. lua_task_get_header_common (lua_State *L, gboolean full, gboolean raw)
  1641. {
  1642. gboolean strong = FALSE;
  1643. struct rspamd_task *task = lua_check_task (L, 1);
  1644. const gchar *name;
  1645. GPtrArray *ar;
  1646. name = luaL_checkstring (L, 2);
  1647. if (name && task) {
  1648. if (lua_gettop (L) == 3) {
  1649. strong = lua_toboolean (L, 3);
  1650. }
  1651. ar = rspamd_message_get_header_array (task, name, strong);
  1652. return rspamd_lua_push_header_array (L, ar, full, raw);
  1653. }
  1654. else {
  1655. return luaL_error (L, "invalid arguments");
  1656. }
  1657. }
  1658. static gint
  1659. lua_task_get_header_full (lua_State * L)
  1660. {
  1661. return lua_task_get_header_common (L, TRUE, TRUE);
  1662. }
  1663. static gint
  1664. lua_task_get_header (lua_State * L)
  1665. {
  1666. return lua_task_get_header_common (L, FALSE, FALSE);
  1667. }
  1668. static gint
  1669. lua_task_get_header_raw (lua_State * L)
  1670. {
  1671. return lua_task_get_header_common (L, FALSE, TRUE);
  1672. }
  1673. static gint
  1674. lua_task_get_raw_headers (lua_State *L)
  1675. {
  1676. struct rspamd_task *task = lua_check_task (L, 1);
  1677. struct rspamd_lua_text *t;
  1678. if (task) {
  1679. t = lua_newuserdata (L, sizeof (*t));
  1680. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1681. t->start = task->raw_headers_content.begin;
  1682. t->len = task->raw_headers_content.len;
  1683. t->flags = 0;
  1684. }
  1685. else {
  1686. return luaL_error (L, "invalid arguments");
  1687. }
  1688. return 1;
  1689. }
  1690. static gint
  1691. lua_task_get_received_headers (lua_State * L)
  1692. {
  1693. struct rspamd_task *task = lua_check_task (L, 1);
  1694. struct received_header *rh;
  1695. const gchar *proto;
  1696. guint i, k = 1;
  1697. if (task) {
  1698. if (!lua_task_get_cached (L, task, "received", task->received->len)) {
  1699. lua_createtable (L, task->received->len, 0);
  1700. for (i = 0; i < task->received->len; i ++) {
  1701. rh = g_ptr_array_index (task->received, i);
  1702. lua_createtable (L, 0, 10);
  1703. if (rh->hdr && rh->hdr->decoded) {
  1704. rspamd_lua_table_set (L, "raw", rh->hdr->decoded);
  1705. }
  1706. lua_pushstring (L, "flags");
  1707. lua_createtable (L, 0, 3);
  1708. lua_pushstring (L, "artificial");
  1709. if (rh->flags & RSPAMD_RECEIVED_FLAG_ARTIFICIAL) {
  1710. lua_pushboolean (L, true);
  1711. }
  1712. else {
  1713. lua_pushboolean (L, false);
  1714. }
  1715. lua_settable (L, -3);
  1716. lua_pushstring (L, "authenticated");
  1717. if (rh->flags & RSPAMD_RECEIVED_FLAG_AUTHENTICATED) {
  1718. lua_pushboolean (L, true);
  1719. }
  1720. else {
  1721. lua_pushboolean (L, false);
  1722. }
  1723. lua_settable (L, -3);
  1724. lua_pushstring (L, "ssl");
  1725. if (rh->flags & RSPAMD_RECEIVED_FLAG_SSL) {
  1726. lua_pushboolean (L, true);
  1727. }
  1728. else {
  1729. lua_pushboolean (L, false);
  1730. }
  1731. lua_settable (L, -3);
  1732. lua_settable (L, -3);
  1733. if (G_UNLIKELY (rh->from_ip == NULL &&
  1734. rh->real_ip == NULL &&
  1735. rh->real_hostname == NULL &&
  1736. rh->by_hostname == NULL && rh->timestamp == 0 &&
  1737. rh->for_mbox == NULL)) {
  1738. lua_rawseti (L, -2, k ++);
  1739. continue;
  1740. }
  1741. rspamd_lua_table_set (L, "from_hostname", rh->from_hostname);
  1742. rspamd_lua_table_set (L, "from_ip", rh->from_ip);
  1743. rspamd_lua_table_set (L, "real_hostname", rh->real_hostname);
  1744. lua_pushstring (L, "real_ip");
  1745. rspamd_lua_ip_push (L, rh->addr);
  1746. lua_settable (L, -3);
  1747. lua_pushstring (L, "proto");
  1748. switch (rh->type) {
  1749. case RSPAMD_RECEIVED_SMTP:
  1750. proto = "smtp";
  1751. break;
  1752. case RSPAMD_RECEIVED_ESMTP:
  1753. proto = "esmtp";
  1754. break;
  1755. case RSPAMD_RECEIVED_ESMTPS:
  1756. proto = "esmtps";
  1757. break;
  1758. case RSPAMD_RECEIVED_ESMTPA:
  1759. proto = "esmtpa";
  1760. break;
  1761. case RSPAMD_RECEIVED_ESMTPSA:
  1762. proto = "esmtpsa";
  1763. break;
  1764. case RSPAMD_RECEIVED_LMTP:
  1765. proto = "lmtp";
  1766. break;
  1767. case RSPAMD_RECEIVED_IMAP:
  1768. proto = "imap";
  1769. break;
  1770. case RSPAMD_RECEIVED_UNKNOWN:
  1771. default:
  1772. proto = "unknown";
  1773. break;
  1774. }
  1775. lua_pushstring (L, proto);
  1776. lua_settable (L, -3);
  1777. lua_pushstring (L, "timestamp");
  1778. lua_pushnumber (L, rh->timestamp);
  1779. lua_settable (L, -3);
  1780. rspamd_lua_table_set (L, "by_hostname", rh->by_hostname);
  1781. rspamd_lua_table_set (L, "for", rh->for_mbox);
  1782. lua_rawseti (L, -2, k ++);
  1783. }
  1784. lua_task_set_cached (L, task, "received", -1, task->received->len);
  1785. }
  1786. }
  1787. else {
  1788. return luaL_error (L, "invalid arguments");
  1789. }
  1790. return 1;
  1791. }
  1792. static gint
  1793. lua_task_get_queue_id (lua_State *L)
  1794. {
  1795. struct rspamd_task *task = lua_check_task (L, 1);
  1796. if (task) {
  1797. if (task->queue_id != NULL && strcmp (task->queue_id, "undef") != 0) {
  1798. lua_pushstring (L, task->queue_id);
  1799. }
  1800. else {
  1801. lua_pushnil (L);
  1802. }
  1803. }
  1804. else {
  1805. return luaL_error (L, "invalid arguments");
  1806. }
  1807. return 1;
  1808. }
  1809. static gint
  1810. lua_task_get_uid (lua_State *L)
  1811. {
  1812. struct rspamd_task *task = lua_check_task (L, 1);
  1813. if (task) {
  1814. lua_pushstring (L, task->task_pool->tag.uid);
  1815. }
  1816. else {
  1817. return luaL_error (L, "invalid arguments");
  1818. }
  1819. return 1;
  1820. }
  1821. static gint
  1822. lua_task_get_resolver (lua_State *L)
  1823. {
  1824. struct rspamd_task *task = lua_check_task (L, 1);
  1825. struct rspamd_dns_resolver **presolver;
  1826. if (task != NULL && task->resolver != NULL) {
  1827. presolver = lua_newuserdata (L, sizeof (void *));
  1828. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  1829. *presolver = task->resolver;
  1830. }
  1831. else {
  1832. return luaL_error (L, "invalid arguments");
  1833. }
  1834. return 1;
  1835. }
  1836. static gint
  1837. lua_task_inc_dns_req (lua_State *L)
  1838. {
  1839. struct rspamd_task *task = lua_check_task (L, 1);
  1840. if (task != NULL) {
  1841. task->dns_requests++;
  1842. }
  1843. else {
  1844. return luaL_error (L, "invalid arguments");
  1845. }
  1846. return 0;
  1847. }
  1848. static gint
  1849. lua_task_get_dns_req (lua_State *L)
  1850. {
  1851. struct rspamd_task *task = lua_check_task (L, 1);
  1852. if (task != NULL) {
  1853. lua_pushnumber (L, task->dns_requests);
  1854. }
  1855. else {
  1856. return luaL_error (L, "invalid arguments");
  1857. }
  1858. return 1;
  1859. }
  1860. enum rspamd_address_type {
  1861. RSPAMD_ADDRESS_ANY = 0,
  1862. RSPAMD_ADDRESS_SMTP = 1,
  1863. RSPAMD_ADDRESS_MIME = 2,
  1864. RSPAMD_ADDRESS_RAW_ANY = 3,
  1865. RSPAMD_ADDRESS_RAW_SMTP = 4,
  1866. RSPAMD_ADDRESS_RAW_MIME = 5,
  1867. RSPAMD_ADDRESS_MAX
  1868. };
  1869. /*
  1870. * Convert element at the specified position to the type
  1871. * for get_from/get_recipients
  1872. */
  1873. static enum rspamd_address_type
  1874. lua_task_str_to_get_type (lua_State *L, gint pos)
  1875. {
  1876. const gchar *type = NULL;
  1877. gint ret = RSPAMD_ADDRESS_ANY;
  1878. guint64 h;
  1879. gsize sz;
  1880. /* Get what value */
  1881. if (lua_type (L, pos) == LUA_TNUMBER) {
  1882. ret = lua_tonumber (L, pos);
  1883. if (ret >= RSPAMD_ADDRESS_ANY && ret < RSPAMD_ADDRESS_MAX) {
  1884. return ret;
  1885. }
  1886. return RSPAMD_ADDRESS_ANY;
  1887. }
  1888. else if (lua_type (L, pos) == LUA_TSTRING) {
  1889. type = lua_tolstring (L, pos, &sz);
  1890. if (type && sz > 0) {
  1891. h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
  1892. type, sz, 0xdeadbabe);
  1893. switch (h) {
  1894. case 0xDA081341FB600389ULL: /* mime */
  1895. ret = RSPAMD_ADDRESS_MIME;
  1896. break;
  1897. case 0xEEC8A7832F8C43ACULL: /* any */
  1898. ret = RSPAMD_ADDRESS_ANY;
  1899. break;
  1900. case 0x472274D5193B2A80ULL: /* smtp */
  1901. case 0xEFE0F586CC9F14A9ULL: /* envelope */
  1902. ret = RSPAMD_ADDRESS_SMTP;
  1903. break;
  1904. case 0x9DA887501690DE20ULL: /* raw_mime */
  1905. ret = RSPAMD_ADDRESS_RAW_MIME;
  1906. break;
  1907. case 0x6B54FE02DEB595A4ULL: /* raw_smtp */
  1908. case 0xE0E596C861777B02ULL: /* raw_envelope */
  1909. ret = RSPAMD_ADDRESS_RAW_SMTP;
  1910. break;
  1911. case 0x2C49DBE3A10A0197ULL: /* raw_any */
  1912. ret = RSPAMD_ADDRESS_RAW_ANY;
  1913. break;
  1914. }
  1915. }
  1916. }
  1917. return ret;
  1918. }
  1919. #define EMAIL_CHECK_FLAG(fl, str) do { \
  1920. if (addr->flags & (fl)) { \
  1921. lua_pushstring (L, (str)); \
  1922. lua_pushboolean (L, true); \
  1923. lua_settable (L, -3); \
  1924. } \
  1925. } while(0)
  1926. static void
  1927. lua_push_email_address (lua_State *L, struct rspamd_email_address *addr)
  1928. {
  1929. if (addr) {
  1930. lua_createtable (L, 0, 4);
  1931. if (addr->addr_len > 0) {
  1932. lua_pushstring (L, "addr");
  1933. lua_pushlstring (L, addr->addr, addr->addr_len);
  1934. lua_settable (L, -3);
  1935. }
  1936. else {
  1937. lua_pushstring (L, "addr");
  1938. lua_pushstring (L, "");
  1939. lua_settable (L, -3);
  1940. }
  1941. if (addr->domain_len > 0) {
  1942. lua_pushstring (L, "domain");
  1943. lua_pushlstring (L, addr->domain, addr->domain_len);
  1944. lua_settable (L, -3);
  1945. }
  1946. else {
  1947. lua_pushstring (L, "domain");
  1948. lua_pushstring (L, "");
  1949. lua_settable (L, -3);
  1950. }
  1951. if (addr->user_len > 0) {
  1952. lua_pushstring (L, "user");
  1953. lua_pushlstring (L, addr->user, addr->user_len);
  1954. lua_settable (L, -3);
  1955. }
  1956. else {
  1957. lua_pushstring (L, "user");
  1958. lua_pushstring (L, "");
  1959. lua_settable (L, -3);
  1960. }
  1961. if (addr->name) {
  1962. lua_pushstring (L, "name");
  1963. lua_pushstring (L, addr->name);
  1964. lua_settable (L, -3);
  1965. }
  1966. else {
  1967. lua_pushstring (L, "name");
  1968. lua_pushstring (L, "");
  1969. lua_settable (L, -3);
  1970. }
  1971. lua_pushstring (L, "flags");
  1972. lua_createtable (L, 0, 7);
  1973. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_VALID, "valid");
  1974. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_IP, "ip");
  1975. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_BRACED, "braced");
  1976. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_QUOTED, "quoted");
  1977. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_EMPTY, "empty");
  1978. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_HAS_BACKSLASH, "backslash");
  1979. EMAIL_CHECK_FLAG (RSPAMD_EMAIL_ADDR_HAS_8BIT, "8bit");
  1980. lua_settable (L, -3);
  1981. }
  1982. }
  1983. void
  1984. lua_push_emails_address_list (lua_State *L, GPtrArray *addrs)
  1985. {
  1986. struct rspamd_email_address *addr;
  1987. guint i;
  1988. lua_createtable (L, addrs->len, 0);
  1989. for (i = 0; i < addrs->len; i ++) {
  1990. addr = g_ptr_array_index (addrs, i);
  1991. lua_push_email_address (L, addr);
  1992. lua_rawseti (L, -2, i + 1);
  1993. }
  1994. }
  1995. static gboolean
  1996. lua_import_email_address (lua_State *L, struct rspamd_task *task,
  1997. gint pos,
  1998. struct rspamd_email_address **paddr)
  1999. {
  2000. struct rspamd_email_address *addr;
  2001. const gchar *p;
  2002. gchar *dst;
  2003. gsize len;
  2004. g_assert (paddr != NULL);
  2005. if (!lua_istable (L, pos)) {
  2006. return FALSE;
  2007. }
  2008. addr = g_malloc0 (sizeof (*addr));
  2009. lua_pushstring (L, "name");
  2010. lua_gettable (L, pos);
  2011. if (lua_type (L, -1) == LUA_TSTRING) {
  2012. p = lua_tolstring (L, -1, &len);
  2013. dst = rspamd_mempool_alloc (task->task_pool, len + 1);
  2014. rspamd_strlcpy (dst, p, len + 1);
  2015. addr->name = dst;
  2016. }
  2017. lua_pop (L, 1);
  2018. lua_pushstring (L, "user");
  2019. lua_gettable (L, pos);
  2020. if (lua_type (L, -1) == LUA_TSTRING) {
  2021. p = lua_tolstring (L, -1, &len);
  2022. addr->user = (const gchar *)rspamd_mempool_alloc (task->task_pool, len);
  2023. memcpy ((gchar *)addr->user, p, len);
  2024. addr->user_len = len;
  2025. }
  2026. lua_pop (L, 1);
  2027. lua_pushstring (L, "domain");
  2028. lua_gettable (L, pos);
  2029. if (lua_type (L, -1) == LUA_TSTRING) {
  2030. p = lua_tolstring (L, -1, &len);
  2031. addr->domain = (const gchar *)rspamd_mempool_alloc (task->task_pool, len);
  2032. memcpy ((gchar *)addr->domain, p, len);
  2033. addr->domain_len = len;
  2034. }
  2035. lua_pop (L, 1);
  2036. lua_pushstring (L, "addr");
  2037. lua_gettable (L, pos);
  2038. if (lua_type (L, -1) == LUA_TSTRING) {
  2039. p = lua_tolstring (L, -1, &len);
  2040. addr->addr = (const gchar *)rspamd_mempool_alloc (task->task_pool, len);
  2041. memcpy ((gchar *)addr->addr, p, len);
  2042. addr->addr_len = len;
  2043. }
  2044. else {
  2045. /* Construct addr */
  2046. len = addr->domain_len + addr->user_len + 1;
  2047. addr->addr = (const gchar *)rspamd_mempool_alloc (task->task_pool, len);
  2048. addr->addr_len = rspamd_snprintf ((gchar *)addr->addr, len, "%*s@%*s",
  2049. (int)addr->user_len, addr->user,
  2050. (int)addr->domain_len, addr->domain);
  2051. }
  2052. lua_pop (L, 1);
  2053. lua_pushstring (L, "raw");
  2054. lua_gettable (L, pos);
  2055. if (lua_type (L, -1) == LUA_TSTRING) {
  2056. p = lua_tolstring (L, -1, &len);
  2057. addr->raw = (const gchar *)rspamd_mempool_alloc (task->task_pool, len);
  2058. memcpy ((gchar *)addr->raw, p, len);
  2059. addr->raw_len = len;
  2060. }
  2061. else {
  2062. /* Construct raw addr */
  2063. len = addr->addr_len + 3;
  2064. if (addr->name) {
  2065. len += strlen (addr->name) + 1;
  2066. dst = rspamd_mempool_alloc (task->task_pool, len + 1);
  2067. addr->raw_len = rspamd_snprintf (dst, len, "%s <%*s>",
  2068. addr->name,
  2069. (int)addr->addr_len, addr->addr);
  2070. }
  2071. else {
  2072. dst = rspamd_mempool_alloc (task->task_pool, len + 1);
  2073. addr->raw_len = rspamd_snprintf (dst, len, "<%*s@%*s>",
  2074. (int)addr->user_len, addr->user,
  2075. (int)addr->domain_len, addr->domain);
  2076. }
  2077. addr->raw = dst;
  2078. }
  2079. lua_pop (L, 1);
  2080. addr->flags = RSPAMD_EMAIL_ADDR_VALID;
  2081. *paddr = addr;
  2082. return TRUE;
  2083. }
  2084. static gint
  2085. lua_task_get_recipients (lua_State *L)
  2086. {
  2087. struct rspamd_task *task = lua_check_task (L, 1);
  2088. GPtrArray *ptrs = NULL;
  2089. gint what = 0;
  2090. if (task) {
  2091. if (lua_gettop (L) == 2) {
  2092. /* Get what value */
  2093. what = lua_task_str_to_get_type (L, 2);
  2094. }
  2095. switch (what) {
  2096. case RSPAMD_ADDRESS_SMTP:
  2097. /* Here we check merely envelope rcpt */
  2098. ptrs = task->rcpt_envelope;
  2099. break;
  2100. case RSPAMD_ADDRESS_MIME:
  2101. /* Here we check merely mime rcpt */
  2102. ptrs = task->rcpt_mime;
  2103. break;
  2104. case RSPAMD_ADDRESS_ANY:
  2105. default:
  2106. if (task->rcpt_envelope) {
  2107. ptrs = task->rcpt_envelope;
  2108. }
  2109. else {
  2110. ptrs = task->rcpt_mime;
  2111. }
  2112. break;
  2113. }
  2114. if (ptrs) {
  2115. lua_push_emails_address_list (L, ptrs);
  2116. }
  2117. else {
  2118. lua_pushnil (L);
  2119. }
  2120. }
  2121. else {
  2122. return luaL_error (L, "invalid arguments");
  2123. }
  2124. return 1;
  2125. }
  2126. static gint
  2127. lua_task_set_recipients (lua_State *L)
  2128. {
  2129. struct rspamd_task *task = lua_check_task (L, 1);
  2130. GPtrArray *ptrs = NULL;
  2131. struct rspamd_email_address *addr = NULL;
  2132. gint what = 0, pos = 3;
  2133. if (task) {
  2134. if (lua_isstring (L, 2) || lua_isnumber (L, 2)) {
  2135. /* Get what value */
  2136. what = lua_task_str_to_get_type (L, 2);
  2137. }
  2138. else if (lua_istable (L, 2)) {
  2139. pos = 2;
  2140. }
  2141. switch (what) {
  2142. case RSPAMD_ADDRESS_SMTP:
  2143. /* Here we check merely envelope rcpt */
  2144. ptrs = task->rcpt_envelope;
  2145. break;
  2146. case RSPAMD_ADDRESS_MIME:
  2147. /* Here we check merely mime rcpt */
  2148. ptrs = task->rcpt_mime;
  2149. break;
  2150. case RSPAMD_ADDRESS_ANY:
  2151. default:
  2152. if (task->rcpt_envelope) {
  2153. ptrs = task->rcpt_envelope;
  2154. }
  2155. else {
  2156. ptrs = task->rcpt_mime;
  2157. }
  2158. break;
  2159. }
  2160. if (ptrs) {
  2161. guint i;
  2162. struct rspamd_email_address *tmp;
  2163. PTR_ARRAY_FOREACH (ptrs, i, tmp) {
  2164. rspamd_email_address_free (tmp);
  2165. }
  2166. g_ptr_array_set_size (ptrs, 0);
  2167. lua_pushvalue (L, pos);
  2168. for (lua_pushnil (L); lua_next (L, -2); lua_pop (L, 1)) {
  2169. if (lua_import_email_address (L, task, lua_gettop (L), &addr)) {
  2170. g_ptr_array_add (ptrs, addr);
  2171. }
  2172. }
  2173. lua_pop (L, 1);
  2174. lua_pushboolean (L, true);
  2175. }
  2176. else {
  2177. lua_pushboolean (L, false);
  2178. }
  2179. }
  2180. else {
  2181. return luaL_error (L, "invalid arguments");
  2182. }
  2183. return 1;
  2184. }
  2185. #define CHECK_EMAIL_ADDR(addr) do { \
  2186. if (addr == NULL) { \
  2187. ret = 0; \
  2188. } \
  2189. else { \
  2190. ret = addr->flags & RSPAMD_EMAIL_ADDR_VALID; \
  2191. } \
  2192. } while (0)
  2193. #define CHECK_EMAIL_ADDR_LIST(addr) do { \
  2194. if (addr == NULL) { \
  2195. ret = 0; \
  2196. } \
  2197. else { \
  2198. ret = addr->len > 0; \
  2199. } \
  2200. } while (0)
  2201. static gint
  2202. lua_task_has_from (lua_State *L)
  2203. {
  2204. struct rspamd_task *task = lua_check_task (L, 1);
  2205. gint what = 0;
  2206. gboolean ret = FALSE;
  2207. if (task) {
  2208. if (lua_gettop (L) == 2) {
  2209. /* Get what value */
  2210. what = lua_task_str_to_get_type (L, 2);
  2211. }
  2212. switch (what) {
  2213. case RSPAMD_ADDRESS_SMTP:
  2214. /* Here we check merely envelope rcpt */
  2215. CHECK_EMAIL_ADDR (task->from_envelope);
  2216. break;
  2217. case RSPAMD_ADDRESS_MIME:
  2218. /* Here we check merely mime rcpt */
  2219. CHECK_EMAIL_ADDR_LIST (task->from_mime);
  2220. break;
  2221. case RSPAMD_ADDRESS_ANY:
  2222. default:
  2223. CHECK_EMAIL_ADDR (task->from_envelope);
  2224. if (!ret) {
  2225. CHECK_EMAIL_ADDR_LIST (task->from_mime);
  2226. }
  2227. break;
  2228. }
  2229. }
  2230. else {
  2231. return luaL_error (L, "invalid arguments");
  2232. }
  2233. lua_pushboolean (L, ret);
  2234. return 1;
  2235. }
  2236. static gint
  2237. lua_task_has_recipients (lua_State *L)
  2238. {
  2239. struct rspamd_task *task = lua_check_task (L, 1);
  2240. gint what = 0;
  2241. gboolean ret = FALSE;
  2242. if (task) {
  2243. if (lua_gettop (L) == 2) {
  2244. /* Get what value */
  2245. what = lua_task_str_to_get_type (L, 2);
  2246. }
  2247. switch (what) {
  2248. case RSPAMD_ADDRESS_SMTP:
  2249. /* Here we check merely envelope rcpt */
  2250. CHECK_EMAIL_ADDR_LIST (task->rcpt_envelope);
  2251. break;
  2252. case RSPAMD_ADDRESS_MIME:
  2253. /* Here we check merely mime rcpt */
  2254. CHECK_EMAIL_ADDR_LIST (task->rcpt_mime);
  2255. break;
  2256. case RSPAMD_ADDRESS_ANY:
  2257. default:
  2258. CHECK_EMAIL_ADDR_LIST (task->rcpt_envelope);
  2259. if (!ret) {
  2260. CHECK_EMAIL_ADDR_LIST (task->rcpt_mime);
  2261. }
  2262. break;
  2263. }
  2264. }
  2265. else {
  2266. return luaL_error (L, "invalid arguments");
  2267. }
  2268. lua_pushboolean (L, ret);
  2269. return 1;
  2270. }
  2271. static gint
  2272. lua_task_get_from (lua_State *L)
  2273. {
  2274. struct rspamd_task *task = lua_check_task (L, 1);
  2275. GPtrArray *addrs = NULL;
  2276. struct rspamd_email_address *addr = NULL;
  2277. gint what = 0;
  2278. if (task) {
  2279. if (lua_gettop (L) == 2) {
  2280. /* Get what value */
  2281. what = lua_task_str_to_get_type (L, 2);
  2282. }
  2283. switch (what) {
  2284. case RSPAMD_ADDRESS_SMTP:
  2285. /* Here we check merely envelope rcpt */
  2286. addr = task->from_envelope;
  2287. break;
  2288. case RSPAMD_ADDRESS_MIME:
  2289. /* Here we check merely mime rcpt */
  2290. addrs = task->from_mime;
  2291. break;
  2292. case RSPAMD_ADDRESS_ANY:
  2293. default:
  2294. if (task->from_envelope) {
  2295. addr = task->from_envelope;
  2296. }
  2297. else {
  2298. addrs = task->from_mime;
  2299. }
  2300. break;
  2301. }
  2302. if (addrs) {
  2303. lua_push_emails_address_list (L, addrs);
  2304. }
  2305. else if (addr) {
  2306. /* Create table to preserve compatibility */
  2307. if (addr->addr) {
  2308. lua_createtable (L, 1, 0);
  2309. lua_push_email_address (L, addr);
  2310. lua_rawseti (L, -2, 1);
  2311. }
  2312. else {
  2313. lua_pushnil (L);
  2314. }
  2315. }
  2316. else {
  2317. lua_pushnil (L);
  2318. }
  2319. }
  2320. else {
  2321. return luaL_error (L, "invalid arguments");
  2322. }
  2323. return 1;
  2324. }
  2325. static gint
  2326. lua_task_set_from (lua_State *L)
  2327. {
  2328. struct rspamd_task *task = lua_check_task (L, 1);
  2329. GPtrArray *addrs = NULL;
  2330. struct rspamd_email_address **paddr = NULL, *addr;
  2331. gint what = 0, pos = 3;
  2332. if (task) {
  2333. if (lua_isstring (L, 2) || lua_isnumber (L, 2)) {
  2334. /* Get what value */
  2335. what = lua_task_str_to_get_type (L, 2);
  2336. }
  2337. else if (lua_istable (L, 2)) {
  2338. pos = 2;
  2339. }
  2340. switch (what) {
  2341. case RSPAMD_ADDRESS_SMTP:
  2342. /* Here we check merely envelope rcpt */
  2343. paddr = &task->from_envelope;
  2344. break;
  2345. case RSPAMD_ADDRESS_MIME:
  2346. /* Here we check merely mime rcpt */
  2347. addrs = task->from_mime;
  2348. break;
  2349. case RSPAMD_ADDRESS_ANY:
  2350. default:
  2351. if (task->from_envelope) {
  2352. paddr = &task->from_envelope;
  2353. }
  2354. else {
  2355. addrs = task->from_mime;
  2356. }
  2357. break;
  2358. }
  2359. if (addrs) {
  2360. if (lua_import_email_address (L, task, pos, &addr)) {
  2361. guint i;
  2362. struct rspamd_email_address *tmp;
  2363. PTR_ARRAY_FOREACH (addrs, i, tmp) {
  2364. rspamd_email_address_free (tmp);
  2365. }
  2366. g_ptr_array_set_size (addrs, 0);
  2367. g_ptr_array_add (addrs, addr);
  2368. lua_pushboolean (L, true);
  2369. }
  2370. else {
  2371. lua_pushboolean (L, false);
  2372. }
  2373. }
  2374. else if (paddr) {
  2375. if (lua_import_email_address (L, task, pos, &addr)) {
  2376. if (paddr) {
  2377. rspamd_email_address_free (*paddr);
  2378. }
  2379. *paddr = addr;
  2380. lua_pushboolean (L, true);
  2381. }
  2382. else {
  2383. lua_pushboolean (L, false);
  2384. }
  2385. }
  2386. else {
  2387. lua_pushboolean (L, false);
  2388. }
  2389. }
  2390. else {
  2391. return luaL_error (L, "invalid arguments");
  2392. }
  2393. return 1;
  2394. }
  2395. static gint
  2396. lua_task_get_principal_recipient (lua_State *L)
  2397. {
  2398. struct rspamd_task *task = lua_check_task (L, 1);
  2399. const gchar *r;
  2400. if (task) {
  2401. r = rspamd_task_get_principal_recipient (task);
  2402. if (r != NULL) {
  2403. lua_pushstring (L, r);
  2404. }
  2405. else {
  2406. lua_pushnil (L);
  2407. }
  2408. }
  2409. else {
  2410. return luaL_error (L, "invalid arguments");
  2411. }
  2412. return 1;
  2413. }
  2414. static gint
  2415. lua_task_get_user (lua_State *L)
  2416. {
  2417. struct rspamd_task *task = lua_check_task (L, 1);
  2418. if (task) {
  2419. if (task->user != NULL) {
  2420. lua_pushstring (L, task->user);
  2421. }
  2422. else {
  2423. lua_pushnil (L);
  2424. }
  2425. }
  2426. else {
  2427. return luaL_error (L, "invalid arguments");
  2428. }
  2429. return 1;
  2430. }
  2431. static gint
  2432. lua_task_set_user (lua_State *L)
  2433. {
  2434. struct rspamd_task *task = lua_check_task (L, 1);
  2435. const gchar *new_user;
  2436. if (task) {
  2437. new_user = luaL_checkstring (L, 2);
  2438. if (new_user) {
  2439. task->user = rspamd_mempool_strdup (task->task_pool, new_user);
  2440. }
  2441. }
  2442. else {
  2443. return luaL_error (L, "invalid arguments");
  2444. }
  2445. return 0;
  2446. }
  2447. static gint
  2448. lua_task_get_from_ip (lua_State *L)
  2449. {
  2450. struct rspamd_task *task = lua_check_task (L, 1);
  2451. if (task) {
  2452. rspamd_lua_ip_push (L, task->from_addr);
  2453. }
  2454. else {
  2455. return luaL_error (L, "invalid arguments");
  2456. }
  2457. return 1;
  2458. }
  2459. static gint
  2460. lua_task_set_from_ip (lua_State *L)
  2461. {
  2462. struct rspamd_task *task = lua_check_task (L, 1);
  2463. const gchar *ip_str = luaL_checkstring (L, 2);
  2464. rspamd_inet_addr_t *addr = NULL;
  2465. if (!task || !ip_str) {
  2466. lua_pushstring (L, "invalid parameters");
  2467. return lua_error (L);
  2468. }
  2469. else {
  2470. if (!rspamd_parse_inet_address (&addr,
  2471. ip_str,
  2472. 0)) {
  2473. msg_warn_task ("cannot get IP from received header: '%s'",
  2474. ip_str);
  2475. }
  2476. else {
  2477. if (task->from_addr) {
  2478. rspamd_inet_address_free (task->from_addr);
  2479. }
  2480. task->from_addr = addr;
  2481. }
  2482. }
  2483. return 0;
  2484. }
  2485. static gint
  2486. lua_task_get_from_ip_num (lua_State *L)
  2487. {
  2488. msg_err ("this function is deprecated and should no longer be used");
  2489. lua_pushnil (L);
  2490. return 1;
  2491. }
  2492. static gint
  2493. lua_task_get_client_ip (lua_State *L)
  2494. {
  2495. struct rspamd_task *task = lua_check_task (L, 1);
  2496. if (task) {
  2497. rspamd_lua_ip_push (L, task->client_addr);
  2498. }
  2499. else {
  2500. return luaL_error (L, "invalid arguments");
  2501. }
  2502. return 1;
  2503. }
  2504. static gint
  2505. lua_task_get_helo (lua_State *L)
  2506. {
  2507. struct rspamd_task *task = lua_check_task (L, 1);
  2508. if (task) {
  2509. if (task->helo != NULL) {
  2510. lua_pushstring (L, task->helo);
  2511. return 1;
  2512. }
  2513. else {
  2514. lua_pushnil (L);
  2515. }
  2516. }
  2517. else {
  2518. return luaL_error (L, "invalid arguments");
  2519. }
  2520. return 1;
  2521. }
  2522. static gint
  2523. lua_task_get_subject (lua_State *L)
  2524. {
  2525. struct rspamd_task *task = lua_check_task (L, 1);
  2526. if (task) {
  2527. if (task->subject != NULL) {
  2528. lua_pushstring (L, task->subject);
  2529. return 1;
  2530. }
  2531. else {
  2532. lua_pushnil (L);
  2533. }
  2534. }
  2535. else {
  2536. return luaL_error (L, "invalid arguments");
  2537. }
  2538. return 1;
  2539. }
  2540. static gint
  2541. lua_task_set_helo (lua_State *L)
  2542. {
  2543. struct rspamd_task *task = lua_check_task (L, 1);
  2544. const gchar *new_helo;
  2545. if (task) {
  2546. new_helo = luaL_checkstring (L, 2);
  2547. if (new_helo) {
  2548. task->helo = rspamd_mempool_strdup (task->task_pool, new_helo);
  2549. }
  2550. }
  2551. else {
  2552. return luaL_error (L, "invalid arguments");
  2553. }
  2554. return 0;
  2555. }
  2556. static gint
  2557. lua_task_get_hostname (lua_State *L)
  2558. {
  2559. struct rspamd_task *task = lua_check_task (L, 1);
  2560. if (task) {
  2561. if (task->hostname != NULL) {
  2562. /* Check whether it looks like an IP address */
  2563. if (*task->hostname == '[') {
  2564. /*
  2565. * From the milter documentation:
  2566. * If the reverse lookup fails or if none of the IP
  2567. * addresses of the resolved host name matches the
  2568. * original IP address, hostname will contain the
  2569. * message sender's IP address enclosed in square
  2570. * brackets (e.g. `[a.b.c.d]')
  2571. */
  2572. lua_pushstring (L, "unknown");
  2573. }
  2574. else {
  2575. lua_pushstring (L, task->hostname);
  2576. }
  2577. }
  2578. else {
  2579. lua_pushnil (L);
  2580. }
  2581. }
  2582. else {
  2583. return luaL_error (L, "invalid arguments");
  2584. }
  2585. return 1;
  2586. }
  2587. static gint
  2588. lua_task_set_hostname (lua_State *L)
  2589. {
  2590. struct rspamd_task *task = lua_check_task (L, 1);
  2591. const gchar *new_hostname;
  2592. if (task) {
  2593. new_hostname = luaL_checkstring (L, 2);
  2594. if (new_hostname) {
  2595. task->hostname = rspamd_mempool_strdup (task->task_pool,
  2596. new_hostname);
  2597. }
  2598. }
  2599. else {
  2600. return luaL_error (L, "invalid arguments");
  2601. }
  2602. return 0;
  2603. }
  2604. static gint
  2605. lua_task_get_images (lua_State *L)
  2606. {
  2607. struct rspamd_task *task = lua_check_task (L, 1);
  2608. guint nelt = 0, i;
  2609. struct rspamd_mime_part *part;
  2610. struct rspamd_image **pimg;
  2611. if (task) {
  2612. if (!lua_task_get_cached (L, task, "images", task->parts->len)) {
  2613. lua_createtable (L, task->parts->len, 0);
  2614. for (i = 0; i < task->parts->len; i ++) {
  2615. part = g_ptr_array_index (task->parts, i);
  2616. if (part->flags & RSPAMD_MIME_PART_IMAGE) {
  2617. pimg = lua_newuserdata (L, sizeof (struct rspamd_image *));
  2618. rspamd_lua_setclass (L, "rspamd{image}", -1);
  2619. *pimg = part->specific.img;
  2620. lua_rawseti (L, -2, ++nelt);
  2621. }
  2622. }
  2623. lua_task_set_cached (L, task, "images", -1, task->parts->len);
  2624. }
  2625. }
  2626. else {
  2627. return luaL_error (L, "invalid arguments");
  2628. }
  2629. return 1;
  2630. }
  2631. static gint
  2632. lua_task_get_archives (lua_State *L)
  2633. {
  2634. struct rspamd_task *task = lua_check_task (L, 1);
  2635. guint nelt = 0, i;
  2636. struct rspamd_mime_part *part;
  2637. struct rspamd_archive **parch;
  2638. if (task) {
  2639. if (!lua_task_get_cached (L, task, "archives", task->parts->len)) {
  2640. lua_createtable (L, task->parts->len, 0);
  2641. for (i = 0; i < task->parts->len; i ++) {
  2642. part = g_ptr_array_index (task->parts, i);
  2643. if (part->flags & RSPAMD_MIME_PART_ARCHIVE) {
  2644. parch = lua_newuserdata (L, sizeof (struct rspamd_archive *));
  2645. rspamd_lua_setclass (L, "rspamd{archive}", -1);
  2646. *parch = part->specific.arch;
  2647. lua_rawseti (L, -2, ++nelt);
  2648. }
  2649. }
  2650. lua_task_set_cached (L, task, "archives", -1, task->parts->len);
  2651. }
  2652. }
  2653. else {
  2654. return luaL_error (L, "invalid arguments");
  2655. }
  2656. return 1;
  2657. }
  2658. static inline gboolean
  2659. lua_push_symbol_result (lua_State *L,
  2660. struct rspamd_task *task,
  2661. const gchar *symbol,
  2662. struct rspamd_symbol_result *symbol_result,
  2663. gboolean add_metric,
  2664. gboolean add_name)
  2665. {
  2666. struct rspamd_metric_result *metric_res;
  2667. struct rspamd_symbol_result *s = NULL;
  2668. struct rspamd_symbol_option *opt;
  2669. gint j = 1, e = 4;
  2670. if (!symbol_result) {
  2671. metric_res = task->result;
  2672. if (metric_res) {
  2673. s = g_hash_table_lookup (metric_res->symbols, symbol);
  2674. }
  2675. }
  2676. else {
  2677. s = symbol_result;
  2678. }
  2679. if (s) {
  2680. if (add_metric) {
  2681. e++;
  2682. }
  2683. if (add_name) {
  2684. e++;
  2685. }
  2686. lua_createtable (L, 0, e);
  2687. if (add_name) {
  2688. lua_pushstring (L, "name");
  2689. lua_pushstring (L, symbol);
  2690. lua_settable (L, -3);
  2691. }
  2692. lua_pushstring (L, "score");
  2693. lua_pushnumber (L, s->score);
  2694. lua_settable (L, -3);
  2695. if (s->sym && s->sym->gr) {
  2696. lua_pushstring (L, "group");
  2697. lua_pushstring (L, s->sym->gr->name);
  2698. lua_settable (L, -3);
  2699. }
  2700. else {
  2701. lua_pushstring (L, "group");
  2702. lua_pushstring (L, "ungrouped");
  2703. lua_settable (L, -3);
  2704. }
  2705. if (s->options) {
  2706. lua_pushstring (L, "options");
  2707. lua_createtable (L, g_hash_table_size (s->options), 0);
  2708. DL_FOREACH (s->opts_head, opt) {
  2709. lua_pushstring (L, (const char*)opt->option);
  2710. lua_rawseti (L, -2, j++);
  2711. }
  2712. lua_settable (L, -3);
  2713. }
  2714. return TRUE;
  2715. }
  2716. return FALSE;
  2717. }
  2718. static gint
  2719. lua_task_get_symbol (lua_State *L)
  2720. {
  2721. struct rspamd_task *task = lua_check_task (L, 1);
  2722. const gchar *symbol;
  2723. gboolean found = FALSE;
  2724. gint i = 1;
  2725. symbol = luaL_checkstring (L, 2);
  2726. if (task && symbol) {
  2727. lua_createtable (L, 1, 0);
  2728. if ((found = lua_push_symbol_result (L, task, symbol,
  2729. NULL, TRUE, FALSE))) {
  2730. lua_rawseti (L, -2, i++);
  2731. }
  2732. else {
  2733. /* Pop table */
  2734. lua_pop (L, 1);
  2735. }
  2736. }
  2737. else {
  2738. return luaL_error (L, "invalid arguments");
  2739. }
  2740. if (!found) {
  2741. lua_pushnil (L);
  2742. }
  2743. return 1;
  2744. }
  2745. static gint
  2746. lua_task_has_symbol (lua_State *L)
  2747. {
  2748. struct rspamd_task *task = lua_check_task (L, 1);
  2749. const gchar *symbol;
  2750. struct rspamd_metric_result *mres;
  2751. gboolean found = FALSE;
  2752. symbol = luaL_checkstring (L, 2);
  2753. if (task && symbol) {
  2754. mres = task->result;
  2755. if (mres) {
  2756. found = g_hash_table_lookup (mres->symbols, symbol) != NULL;
  2757. }
  2758. lua_pushboolean (L, found);
  2759. }
  2760. else {
  2761. return luaL_error (L, "invalid arguments");
  2762. }
  2763. return 1;
  2764. }
  2765. static gint
  2766. lua_task_get_symbols (lua_State *L)
  2767. {
  2768. struct rspamd_task *task = lua_check_task (L, 1);
  2769. struct rspamd_metric_result *mres;
  2770. gint i = 1;
  2771. GHashTableIter it;
  2772. gpointer k, v;
  2773. struct rspamd_symbol_result *s;
  2774. if (task) {
  2775. mres = task->result;
  2776. if (mres) {
  2777. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2778. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2779. g_hash_table_iter_init (&it, mres->symbols);
  2780. while (g_hash_table_iter_next (&it, &k, &v)) {
  2781. s = v;
  2782. lua_pushstring (L, k);
  2783. lua_rawseti (L, -3, i);
  2784. lua_pushnumber (L, s->score);
  2785. lua_rawseti (L, -2, i);
  2786. i ++;
  2787. }
  2788. }
  2789. else {
  2790. lua_createtable (L, 0, 0);
  2791. lua_createtable (L, 0, 0);
  2792. }
  2793. }
  2794. else {
  2795. return luaL_error (L, "invalid arguments");
  2796. }
  2797. return 2;
  2798. }
  2799. static gint
  2800. lua_task_get_symbols_all (lua_State *L)
  2801. {
  2802. struct rspamd_task *task = lua_check_task (L, 1);
  2803. struct rspamd_metric_result *mres;
  2804. GHashTableIter it;
  2805. gpointer k, v;
  2806. gboolean found = FALSE;
  2807. gint i = 1;
  2808. if (task) {
  2809. mres = task->result;
  2810. if (mres) {
  2811. found = TRUE;
  2812. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2813. g_hash_table_iter_init (&it, mres->symbols);
  2814. while (g_hash_table_iter_next (&it, &k, &v)) {
  2815. lua_push_symbol_result (L, task, k, v, FALSE, TRUE);
  2816. lua_rawseti (L, -2, i++);
  2817. }
  2818. }
  2819. }
  2820. else {
  2821. return luaL_error (L, "invalid arguments");
  2822. }
  2823. if (!found) {
  2824. lua_pushnil (L);
  2825. }
  2826. return 1;
  2827. }
  2828. static gint
  2829. lua_task_get_symbols_numeric (lua_State *L)
  2830. {
  2831. struct rspamd_task *task = lua_check_task (L, 1);
  2832. struct rspamd_metric_result *mres;
  2833. gint i = 1, id;
  2834. GHashTableIter it;
  2835. gpointer k, v;
  2836. struct rspamd_symbol_result *s;
  2837. if (task) {
  2838. mres = task->result;
  2839. if (mres) {
  2840. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2841. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2842. g_hash_table_iter_init (&it, mres->symbols);
  2843. while (g_hash_table_iter_next (&it, &k, &v)) {
  2844. id = rspamd_symbols_cache_find_symbol (task->cfg->cache,
  2845. k);
  2846. s = v;
  2847. lua_pushnumber (L, id);
  2848. lua_rawseti (L, -3, i);
  2849. lua_pushnumber (L, s->score);
  2850. lua_rawseti (L, -2, i);
  2851. i ++;
  2852. }
  2853. }
  2854. else {
  2855. lua_createtable (L, 0, 0);
  2856. lua_createtable (L, 0, 0);
  2857. }
  2858. }
  2859. else {
  2860. return luaL_error (L, "invalid arguments");
  2861. }
  2862. return 2;
  2863. }
  2864. struct tokens_foreach_cbdata {
  2865. struct rspamd_task *task;
  2866. lua_State *L;
  2867. gint idx;
  2868. gboolean normalize;
  2869. };
  2870. static void
  2871. tokens_foreach_cb (gint id, const gchar *sym, gint flags, gpointer ud)
  2872. {
  2873. struct rspamd_metric_result *mres;
  2874. struct tokens_foreach_cbdata *cbd = ud;
  2875. struct rspamd_symbol_result *s;
  2876. if (flags & SYMBOL_TYPE_NOSTAT) {
  2877. return;
  2878. }
  2879. mres = cbd->task->result;
  2880. if (mres && (s = g_hash_table_lookup (mres->symbols, sym)) != NULL) {
  2881. if (cbd->normalize) {
  2882. lua_pushnumber (cbd->L, tanh (s->score));
  2883. }
  2884. else {
  2885. lua_pushnumber (cbd->L, s->score);
  2886. }
  2887. }
  2888. else {
  2889. lua_pushnumber (cbd->L, 0.0);
  2890. }
  2891. lua_rawseti (cbd->L, -2, cbd->idx++);
  2892. }
  2893. static gint
  2894. lua_task_get_symbols_tokens (lua_State *L)
  2895. {
  2896. struct rspamd_task *task = lua_check_task (L, 1);
  2897. struct tokens_foreach_cbdata cbd;
  2898. cbd.task = task;
  2899. cbd.L = L;
  2900. cbd.idx = 1;
  2901. cbd.normalize = TRUE;
  2902. if (lua_type (L, 2) == LUA_TBOOLEAN) {
  2903. cbd.normalize = lua_toboolean (L, 2);
  2904. }
  2905. else {
  2906. cbd.normalize = TRUE;
  2907. }
  2908. lua_createtable (L,
  2909. rspamd_symbols_cache_stats_symbols_count (task->cfg->cache), 0);
  2910. rspamd_symbols_cache_foreach (task->cfg->cache, tokens_foreach_cb, &cbd);
  2911. return 1;
  2912. }
  2913. enum lua_date_type {
  2914. DATE_CONNECT = 0,
  2915. DATE_MESSAGE,
  2916. DATE_CONNECT_STRING,
  2917. DATE_MESSAGE_STRING
  2918. };
  2919. static enum lua_date_type
  2920. lua_task_detect_date_type (struct rspamd_task *task,
  2921. lua_State *L, gint idx, gboolean *gmt)
  2922. {
  2923. enum lua_date_type type = DATE_CONNECT;
  2924. if (lua_type (L, idx) == LUA_TNUMBER) {
  2925. gint num = lua_tonumber (L, idx);
  2926. if (num >= DATE_CONNECT && num <= DATE_MESSAGE_STRING) {
  2927. return num;
  2928. }
  2929. }
  2930. else if (lua_type (L, idx) == LUA_TTABLE) {
  2931. const gchar *str;
  2932. lua_pushvalue (L, idx);
  2933. lua_pushstring (L, "format");
  2934. lua_gettable (L, -2);
  2935. str = lua_tostring (L, -1);
  2936. if (str) {
  2937. if (g_ascii_strcasecmp (str, "message") == 0) {
  2938. type = DATE_MESSAGE;
  2939. } else if (g_ascii_strcasecmp (str, "connect_str") == 0) {
  2940. type = DATE_CONNECT_STRING;
  2941. } else if (g_ascii_strcasecmp (str, "message_str") == 0) {
  2942. type = DATE_MESSAGE_STRING;
  2943. }
  2944. }
  2945. else {
  2946. msg_warn_task ("date format has not been specified");
  2947. }
  2948. lua_pop (L, 1);
  2949. lua_pushstring (L, "gmt");
  2950. lua_gettable (L, -2);
  2951. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2952. *gmt = lua_toboolean (L, -1);
  2953. }
  2954. /* Value and table */
  2955. lua_pop (L, 2);
  2956. }
  2957. return type;
  2958. }
  2959. static gint
  2960. lua_task_get_date (lua_State *L)
  2961. {
  2962. struct rspamd_task *task = lua_check_task (L, 1);
  2963. GPtrArray *hdrs;
  2964. gdouble tim;
  2965. enum lua_date_type type = DATE_CONNECT;
  2966. gboolean gmt = TRUE;
  2967. if (task != NULL) {
  2968. if (lua_gettop (L) > 1) {
  2969. type = lua_task_detect_date_type (task, L, 2, &gmt);
  2970. }
  2971. /* Get GMT date and store it to time_t */
  2972. if (type == DATE_CONNECT || type == DATE_CONNECT_STRING) {
  2973. tim = (tv_to_msec (&task->tv)) / 1000.;
  2974. if (!gmt) {
  2975. struct tm t;
  2976. time_t tt;
  2977. tt = tim;
  2978. rspamd_localtime (tt, &t);
  2979. #if !defined(__sun)
  2980. t.tm_gmtoff = 0;
  2981. #endif
  2982. t.tm_isdst = 0;
  2983. tim = mktime (&t);
  2984. }
  2985. }
  2986. else {
  2987. hdrs = rspamd_message_get_header_array (task, "Date",
  2988. FALSE);
  2989. if (hdrs && hdrs->len > 0) {
  2990. time_t tt;
  2991. struct tm t;
  2992. struct rspamd_mime_header *h;
  2993. h = g_ptr_array_index (hdrs, 0);
  2994. tt = rspamd_parse_smtp_date (h->decoded, strlen (h->decoded));
  2995. if (!gmt) {
  2996. rspamd_localtime (tt, &t);
  2997. #if !defined(__sun)
  2998. t.tm_gmtoff = 0;
  2999. #endif
  3000. t.tm_isdst = 0;
  3001. tim = mktime (&t);
  3002. }
  3003. else {
  3004. tim = tt;
  3005. }
  3006. }
  3007. else {
  3008. tim = 0.0;
  3009. }
  3010. }
  3011. if (type == DATE_CONNECT || type == DATE_MESSAGE) {
  3012. lua_pushnumber (L, tim);
  3013. }
  3014. else {
  3015. GTimeVal tv;
  3016. gchar *out;
  3017. double_to_tv (tim, &tv);
  3018. out = g_time_val_to_iso8601 (&tv);
  3019. lua_pushstring (L, out);
  3020. g_free (out);
  3021. }
  3022. }
  3023. else {
  3024. return luaL_error (L, "invalid arguments");
  3025. }
  3026. return 1;
  3027. }
  3028. static gint
  3029. lua_task_get_message_id (lua_State *L)
  3030. {
  3031. struct rspamd_task *task = lua_check_task (L, 1);
  3032. if (task != NULL) {
  3033. if (task->message_id != NULL) {
  3034. lua_pushstring (L, task->message_id);
  3035. }
  3036. else {
  3037. lua_pushnil (L);
  3038. }
  3039. }
  3040. else {
  3041. return luaL_error (L, "invalid arguments");
  3042. }
  3043. return 1;
  3044. }
  3045. static gint
  3046. lua_task_get_timeval (lua_State *L)
  3047. {
  3048. struct rspamd_task *task = lua_check_task (L, 1);
  3049. if (task != NULL) {
  3050. lua_createtable (L, 0, 2);
  3051. lua_pushstring (L, "tv_sec");
  3052. lua_pushnumber (L, (lua_Number)task->tv.tv_sec);
  3053. lua_settable (L, -3);
  3054. lua_pushstring (L, "tv_usec");
  3055. lua_pushnumber (L, (lua_Number)task->tv.tv_usec);
  3056. lua_settable (L, -3);
  3057. }
  3058. else {
  3059. return luaL_error (L, "invalid arguments");
  3060. }
  3061. return 1;
  3062. }
  3063. static gint
  3064. lua_task_get_size (lua_State *L)
  3065. {
  3066. struct rspamd_task *task = lua_check_task (L, 1);
  3067. if (task != NULL) {
  3068. lua_pushnumber (L, task->msg.len);
  3069. }
  3070. else {
  3071. return luaL_error (L, "invalid arguments");
  3072. }
  3073. return 1;
  3074. }
  3075. /**
  3076. * - `no_log`: do not log task summary
  3077. * - `no_stat`: do not include task into scanned stats
  3078. * - `pass_all`: check all filters for task
  3079. * - `extended_urls`: output extended info about urls
  3080. * - `skip`: skip task processing
  3081. */
  3082. #define LUA_TASK_FLAG_WRITE(flag, set) do { \
  3083. task->flags = (set) ? (task->flags | (flag)) : (task->flags & ~(flag)); \
  3084. } while(0)
  3085. #define LUA_TASK_SET_FLAG(flag, strname, macro, set) do { \
  3086. if (!found && strcmp ((flag), strname) == 0) { \
  3087. LUA_TASK_FLAG_WRITE((macro), set); \
  3088. found = TRUE; \
  3089. } \
  3090. } while(0)
  3091. #define LUA_TASK_FLAG_READ(flag) do { \
  3092. lua_pushboolean(L, !!(task->flags & (flag))); \
  3093. } while(0)
  3094. #define LUA_TASK_GET_FLAG(flag, strname, macro) do { \
  3095. if (!found && strcmp ((flag), strname) == 0) { \
  3096. LUA_TASK_FLAG_READ((macro)); \
  3097. found = TRUE; \
  3098. } \
  3099. } while(0)
  3100. static gint
  3101. lua_task_set_flag (lua_State *L)
  3102. {
  3103. struct rspamd_task *task = lua_check_task (L, 1);
  3104. const gchar *flag = luaL_checkstring (L, 2);
  3105. gboolean set = TRUE, found = FALSE;
  3106. if (lua_gettop (L) >= 3) {
  3107. set = lua_toboolean (L, 3);
  3108. }
  3109. if (task != NULL && flag != NULL) {
  3110. LUA_TASK_SET_FLAG (flag, "pass_all", RSPAMD_TASK_FLAG_PASS_ALL, set);
  3111. LUA_TASK_SET_FLAG (flag, "no_log", RSPAMD_TASK_FLAG_NO_LOG, set);
  3112. LUA_TASK_SET_FLAG (flag, "no_stat", RSPAMD_TASK_FLAG_NO_STAT, set);
  3113. LUA_TASK_SET_FLAG (flag, "skip", RSPAMD_TASK_FLAG_SKIP, set);
  3114. LUA_TASK_SET_FLAG (flag, "extended_urls", RSPAMD_TASK_FLAG_EXT_URLS, set);
  3115. LUA_TASK_SET_FLAG (flag, "learn_spam", RSPAMD_TASK_FLAG_LEARN_SPAM, set);
  3116. LUA_TASK_SET_FLAG (flag, "learn_ham", RSPAMD_TASK_FLAG_LEARN_HAM, set);
  3117. LUA_TASK_SET_FLAG (flag, "broken_headers",
  3118. RSPAMD_TASK_FLAG_BROKEN_HEADERS, set);
  3119. LUA_TASK_SET_FLAG (flag, "greylisted", RSPAMD_TASK_FLAG_GREYLISTED, set);
  3120. if (!found) {
  3121. msg_warn_task ("unknown flag requested: %s", flag);
  3122. }
  3123. }
  3124. else {
  3125. return luaL_error (L, "invalid arguments");
  3126. }
  3127. return 0;
  3128. }
  3129. static gint
  3130. lua_task_has_flag (lua_State *L)
  3131. {
  3132. struct rspamd_task *task = lua_check_task (L, 1);
  3133. const gchar *flag = luaL_checkstring (L, 2);
  3134. gboolean found = FALSE;
  3135. if (task != NULL && flag != NULL) {
  3136. LUA_TASK_GET_FLAG (flag, "pass_all", RSPAMD_TASK_FLAG_PASS_ALL);
  3137. LUA_TASK_GET_FLAG (flag, "no_log", RSPAMD_TASK_FLAG_NO_LOG);
  3138. LUA_TASK_GET_FLAG (flag, "no_stat", RSPAMD_TASK_FLAG_NO_STAT);
  3139. LUA_TASK_GET_FLAG (flag, "skip", RSPAMD_TASK_FLAG_SKIP);
  3140. LUA_TASK_GET_FLAG (flag, "extended_urls", RSPAMD_TASK_FLAG_EXT_URLS);
  3141. LUA_TASK_GET_FLAG (flag, "learn_spam", RSPAMD_TASK_FLAG_LEARN_SPAM);
  3142. LUA_TASK_GET_FLAG (flag, "learn_ham", RSPAMD_TASK_FLAG_LEARN_HAM);
  3143. LUA_TASK_GET_FLAG (flag, "greylisted", RSPAMD_TASK_FLAG_GREYLISTED);
  3144. LUA_TASK_GET_FLAG (flag, "broken_headers",
  3145. RSPAMD_TASK_FLAG_BROKEN_HEADERS);
  3146. LUA_TASK_GET_FLAG (flag, "milter",
  3147. RSPAMD_TASK_FLAG_MILTER);
  3148. if (!found) {
  3149. msg_warn_task ("unknown flag requested: %s", flag);
  3150. lua_pushboolean (L, 0);
  3151. }
  3152. }
  3153. else {
  3154. return luaL_error (L, "invalid arguments");
  3155. }
  3156. return 1;
  3157. }
  3158. static gint
  3159. lua_task_get_flags (lua_State *L)
  3160. {
  3161. struct rspamd_task *task = lua_check_task (L, 1);
  3162. gint idx = 1;
  3163. guint flags, bit, i;
  3164. if (task) {
  3165. lua_createtable (L, 8, 0);
  3166. flags = task->flags;
  3167. for (i = 0; i < sizeof (task->flags) * NBBY; i ++) {
  3168. bit = (1U << i);
  3169. if (flags & bit) {
  3170. switch (bit) {
  3171. case RSPAMD_TASK_FLAG_PASS_ALL:
  3172. lua_pushstring (L, "pass_all");
  3173. lua_rawseti (L, -2, idx ++);
  3174. break;
  3175. case RSPAMD_TASK_FLAG_NO_LOG:
  3176. lua_pushstring (L, "no_log");
  3177. lua_rawseti (L, -2, idx++);
  3178. break;
  3179. case RSPAMD_TASK_FLAG_NO_STAT:
  3180. lua_pushstring (L, "no_stat");
  3181. lua_rawseti (L, -2, idx++);
  3182. break;
  3183. case RSPAMD_TASK_FLAG_SKIP:
  3184. lua_pushstring (L, "skip");
  3185. lua_rawseti (L, -2, idx++);
  3186. break;
  3187. case RSPAMD_TASK_FLAG_EXT_URLS:
  3188. lua_pushstring (L, "extended_urls");
  3189. lua_rawseti (L, -2, idx++);
  3190. break;
  3191. case RSPAMD_TASK_FLAG_BROKEN_HEADERS:
  3192. lua_pushstring (L, "broken_headers");
  3193. lua_rawseti (L, -2, idx++);
  3194. break;
  3195. case RSPAMD_TASK_FLAG_LEARN_SPAM:
  3196. lua_pushstring (L, "learn_spam");
  3197. lua_rawseti (L, -2, idx++);
  3198. break;
  3199. case RSPAMD_TASK_FLAG_LEARN_HAM:
  3200. lua_pushstring (L, "learn_ham");
  3201. lua_rawseti (L, -2, idx++);
  3202. break;
  3203. case RSPAMD_TASK_FLAG_GREYLISTED:
  3204. lua_pushstring (L, "greylisted");
  3205. lua_rawseti (L, -2, idx++);
  3206. break;
  3207. case RSPAMD_TASK_FLAG_MILTER:
  3208. lua_pushstring (L, "milter");
  3209. lua_rawseti (L, -2, idx++);
  3210. break;
  3211. default:
  3212. break;
  3213. }
  3214. }
  3215. }
  3216. }
  3217. else {
  3218. return luaL_error (L, "invalid arguments");
  3219. }
  3220. return 1;
  3221. }
  3222. static gint
  3223. lua_task_get_digest (lua_State *L)
  3224. {
  3225. struct rspamd_task *task = lua_check_task (L, 1);
  3226. gchar hexbuf[33];
  3227. gint r;
  3228. if (task) {
  3229. r = rspamd_encode_hex_buf (task->digest, sizeof (task->digest),
  3230. hexbuf, sizeof (hexbuf) - 1);
  3231. if (r > 0) {
  3232. hexbuf[r] = '\0';
  3233. lua_pushstring (L, hexbuf);
  3234. }
  3235. else {
  3236. lua_pushnil (L);
  3237. }
  3238. }
  3239. else {
  3240. return luaL_error (L, "invalid arguments");
  3241. }
  3242. return 1;
  3243. }
  3244. static gint
  3245. lua_task_learn (lua_State *L)
  3246. {
  3247. struct rspamd_task *task = lua_check_task (L, 1);
  3248. gboolean is_spam = FALSE;
  3249. const gchar *clname = NULL;
  3250. GError *err = NULL;
  3251. int ret = 1;
  3252. if (task == NULL) {
  3253. return luaL_error (L, "invalid arguments");
  3254. }
  3255. is_spam = lua_toboolean(L, 2);
  3256. if (lua_gettop (L) > 2) {
  3257. clname = luaL_checkstring (L, 3);
  3258. }
  3259. if (!rspamd_learn_task_spam (task, is_spam, clname, &err)) {
  3260. lua_pushboolean (L, FALSE);
  3261. if (err != NULL) {
  3262. lua_pushstring (L, err->message);
  3263. ret = 2;
  3264. }
  3265. }
  3266. else {
  3267. lua_pushboolean (L, TRUE);
  3268. }
  3269. return ret;
  3270. }
  3271. static gint
  3272. lua_task_set_settings (lua_State *L)
  3273. {
  3274. struct rspamd_task *task = lua_check_task (L, 1);
  3275. ucl_object_t *settings;
  3276. const ucl_object_t *act, *elt, *metric_elt, *vars, *cur;
  3277. ucl_object_iter_t it = NULL;
  3278. struct rspamd_metric_result *mres;
  3279. guint i;
  3280. settings = ucl_object_lua_import (L, 2);
  3281. if (settings != NULL && task != NULL) {
  3282. metric_elt = ucl_object_lookup (settings, DEFAULT_METRIC);
  3283. if (metric_elt) {
  3284. task->settings = ucl_object_ref (metric_elt);
  3285. ucl_object_unref (settings);
  3286. }
  3287. else {
  3288. task->settings = settings;
  3289. }
  3290. act = ucl_object_lookup (task->settings, "actions");
  3291. if (act) {
  3292. /* Adjust desired actions */
  3293. mres = task->result;
  3294. if (mres == NULL) {
  3295. mres = rspamd_create_metric_result (task);
  3296. }
  3297. for (i = 0; i < METRIC_ACTION_MAX; i++) {
  3298. elt = ucl_object_lookup_any (act, rspamd_action_to_str (i),
  3299. rspamd_action_to_str_alt (i), NULL);
  3300. if (elt) {
  3301. mres->actions_limits[i] = ucl_object_todouble (elt);
  3302. msg_debug_task ("adjusted action %s to %.2f",
  3303. ucl_object_key (elt), mres->actions_limits[i]);
  3304. }
  3305. }
  3306. }
  3307. vars = ucl_object_lookup (task->settings, "variables");
  3308. if (vars && ucl_object_type (vars) == UCL_OBJECT) {
  3309. /* Set memory pool variables */
  3310. while ((cur = ucl_object_iterate (vars, &it, true)) != NULL) {
  3311. if (ucl_object_type (cur) == UCL_STRING) {
  3312. rspamd_mempool_set_variable (task->task_pool,
  3313. ucl_object_key (cur), rspamd_mempool_strdup (
  3314. task->task_pool,
  3315. ucl_object_tostring (cur)
  3316. ), NULL);
  3317. }
  3318. }
  3319. }
  3320. rspamd_symbols_cache_process_settings (task, task->cfg->cache);
  3321. }
  3322. else {
  3323. return luaL_error (L, "invalid arguments");
  3324. }
  3325. return 0;
  3326. }
  3327. static gint
  3328. lua_task_set_milter_reply (lua_State *L)
  3329. {
  3330. struct rspamd_task *task = lua_check_task (L, 1);
  3331. ucl_object_t *reply, *prev;
  3332. reply = ucl_object_lua_import (L, 2);
  3333. if (reply != NULL && task != NULL) {
  3334. prev = rspamd_mempool_get_variable (task->task_pool,
  3335. RSPAMD_MEMPOOL_MILTER_REPLY);
  3336. if (prev) {
  3337. ucl_object_merge (prev, reply, false);
  3338. ucl_object_unref (reply);
  3339. }
  3340. else {
  3341. rspamd_mempool_set_variable (task->task_pool,
  3342. RSPAMD_MEMPOOL_MILTER_REPLY,
  3343. reply, (rspamd_mempool_destruct_t) ucl_object_unref);
  3344. }
  3345. }
  3346. else {
  3347. return luaL_error (L, "invalid arguments");
  3348. }
  3349. return 0;
  3350. }
  3351. static gint
  3352. lua_task_get_settings (lua_State *L)
  3353. {
  3354. struct rspamd_task *task = lua_check_task (L, 1);
  3355. if (task != NULL) {
  3356. if (task->settings) {
  3357. return ucl_object_push_lua (L, task->settings, true);
  3358. }
  3359. else {
  3360. lua_pushnil (L);
  3361. }
  3362. }
  3363. else {
  3364. return luaL_error (L, "invalid arguments");
  3365. }
  3366. return 1;
  3367. }
  3368. static gint
  3369. lua_task_lookup_settings (lua_State *L)
  3370. {
  3371. struct rspamd_task *task = lua_check_task (L, 1);
  3372. const gchar *key = NULL;
  3373. const ucl_object_t *elt;
  3374. if (task != NULL) {
  3375. if (lua_isstring (L, 2)) {
  3376. key = lua_tostring (L, 2);
  3377. }
  3378. if (task->settings) {
  3379. if (key == NULL) {
  3380. return ucl_object_push_lua (L, task->settings, true);
  3381. }
  3382. else {
  3383. elt = ucl_object_lookup (task->settings, key);
  3384. if (elt) {
  3385. return ucl_object_push_lua (L, elt, true);
  3386. }
  3387. else {
  3388. lua_pushnil (L);
  3389. }
  3390. }
  3391. }
  3392. else {
  3393. lua_pushnil (L);
  3394. }
  3395. }
  3396. else {
  3397. return luaL_error (L, "invalid arguments");
  3398. }
  3399. return 1;
  3400. }
  3401. static gint
  3402. lua_task_get_settings_id (lua_State *L)
  3403. {
  3404. struct rspamd_task *task = lua_check_task (L, 1);
  3405. guint32 *hp;
  3406. if (task != NULL) {
  3407. hp = rspamd_mempool_get_variable (task->task_pool, "settings_hash");
  3408. if (hp) {
  3409. lua_pushnumber (L, *hp);
  3410. }
  3411. else {
  3412. lua_pushnil (L);
  3413. }
  3414. }
  3415. else {
  3416. return luaL_error (L, "invalid arguments");
  3417. }
  3418. return 1;
  3419. }
  3420. static gint
  3421. lua_task_cache_get (lua_State *L)
  3422. {
  3423. struct rspamd_task *task = lua_check_task (L, 1);
  3424. const gchar *key = luaL_checkstring (L, 2);
  3425. guint id = 0;
  3426. if (task && key) {
  3427. if (lua_type (L, 3) == LUA_TNUMBER) {
  3428. id = lua_tonumber (L, 3);
  3429. }
  3430. if (!lua_task_get_cached (L, task, key, id)) {
  3431. lua_pushnil (L);
  3432. }
  3433. }
  3434. else {
  3435. luaL_error (L, "invalid arguments");
  3436. }
  3437. return 1;
  3438. }
  3439. static gint
  3440. lua_task_cache_set (lua_State *L)
  3441. {
  3442. struct rspamd_task *task = lua_check_task (L, 1);
  3443. const gchar *key = luaL_checkstring (L, 2);
  3444. guint id = 0;
  3445. if (task && key && lua_gettop (L) >= 3) {
  3446. if (lua_type (L, 4) == LUA_TNUMBER) {
  3447. id = lua_tonumber (L, 4);
  3448. }
  3449. lua_task_set_cached (L, task, key, 3, id);
  3450. }
  3451. else {
  3452. luaL_error (L, "invalid arguments");
  3453. }
  3454. return 0;
  3455. }
  3456. struct lua_file_cbdata {
  3457. gchar *fname;
  3458. gint fd;
  3459. gboolean keep;
  3460. };
  3461. static void
  3462. lua_tmp_file_dtor (gpointer p)
  3463. {
  3464. struct lua_file_cbdata *cbdata = p;
  3465. if (!cbdata->keep) {
  3466. unlink (cbdata->fname);
  3467. }
  3468. close (cbdata->fd);
  3469. }
  3470. static gint
  3471. lua_task_store_in_file (lua_State *L)
  3472. {
  3473. struct rspamd_task *task = lua_check_task (L, 1);
  3474. gboolean force_new = FALSE, keep = FALSE;
  3475. gchar fpath[PATH_MAX];
  3476. const gchar *tmpmask = NULL, *fname = NULL;
  3477. guint64 mode = 00600;
  3478. gint fd;
  3479. struct lua_file_cbdata *cbdata;
  3480. GError *err = NULL;
  3481. if (task) {
  3482. if (lua_istable (L, 2)) {
  3483. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  3484. "filename=S;tmpmask=S;mode=I;force_new=B;keep=B",
  3485. &fname, &tmpmask, &mode, &force_new, &keep)) {
  3486. msg_err_task ("cannot get parameters list: %e", err);
  3487. if (err) {
  3488. g_error_free (err);
  3489. }
  3490. return luaL_error (L, "invalid arguments");
  3491. }
  3492. }
  3493. else if (lua_isnumber (L, 2)) {
  3494. mode = lua_tonumber (L, 2);
  3495. }
  3496. if (!force_new && (task->flags & RSPAMD_TASK_FLAG_FILE) &&
  3497. task->msg.fpath) {
  3498. lua_pushstring (L, task->msg.fpath);
  3499. }
  3500. else {
  3501. if (fname == NULL) {
  3502. if (tmpmask == NULL) {
  3503. rspamd_snprintf (fpath, sizeof (fpath), "%s%c%s",
  3504. task->cfg->temp_dir,
  3505. G_DIR_SEPARATOR, "rmsg-XXXXXXXXXX");
  3506. }
  3507. else {
  3508. rspamd_snprintf (fpath, sizeof (fpath), "%s", tmpmask);
  3509. }
  3510. fd = mkstemp (fpath);
  3511. fname = fpath;
  3512. if (fd != -1) {
  3513. fchmod (fd, mode);
  3514. }
  3515. }
  3516. else {
  3517. fd = rspamd_file_xopen (fname, O_WRONLY|O_CREAT|O_EXCL,
  3518. (guint)mode, FALSE);
  3519. }
  3520. if (fd == -1) {
  3521. msg_err_task ("cannot save file: %s", strerror (errno));
  3522. lua_pushnil (L);
  3523. }
  3524. else {
  3525. if (write (fd, task->msg.begin, task->msg.len) == -1) {
  3526. msg_err_task ("cannot write file %s: %s", fpath,
  3527. strerror (errno));
  3528. unlink (fname);
  3529. close (fd);
  3530. lua_pushnil (L);
  3531. return 1;
  3532. }
  3533. cbdata = rspamd_mempool_alloc (task->task_pool, sizeof (*cbdata));
  3534. cbdata->fd = fd;
  3535. cbdata->fname = rspamd_mempool_strdup (task->task_pool, fname);
  3536. cbdata->keep = keep;
  3537. lua_pushstring (L, cbdata->fname);
  3538. rspamd_mempool_add_destructor (task->task_pool,
  3539. lua_tmp_file_dtor, cbdata);
  3540. }
  3541. }
  3542. }
  3543. else {
  3544. luaL_error (L, "invalid arguments");
  3545. }
  3546. return 1;
  3547. }
  3548. static gint
  3549. lua_task_process_regexp (lua_State *L)
  3550. {
  3551. struct rspamd_task *task = lua_check_task (L, 1);
  3552. struct rspamd_lua_regexp *re = NULL;
  3553. gboolean strong = FALSE;
  3554. const gchar *type_str = NULL, *header_str = NULL;
  3555. gsize header_len = 0;
  3556. GError *err = NULL;
  3557. gint ret = 0;
  3558. enum rspamd_re_type type = RSPAMD_RE_BODY;
  3559. /*
  3560. * - `re`* : regular expression object
  3561. * - `type`*: type of regular expression:
  3562. * + `mime`: mime regexp
  3563. * + `rawmime`: raw mime regexp
  3564. * + `header`: header regexp
  3565. * + `rawheader`: raw header expression
  3566. * + `body`: raw body regexp
  3567. * + `url`: url regexp
  3568. * - `header`: for header and rawheader regexp means the name of header
  3569. * - `strong`: case sensitive match for headers
  3570. */
  3571. if (task != NULL) {
  3572. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  3573. "*re=U{regexp};*type=S;header=V;strong=B",
  3574. &re, &type_str, &header_len, &header_str,
  3575. &strong)) {
  3576. msg_err_task ("cannot get parameters list: %e", err);
  3577. if (err) {
  3578. g_error_free (err);
  3579. }
  3580. return luaL_error (L, "invalid arguments");
  3581. }
  3582. else {
  3583. type = rspamd_re_cache_type_from_string (type_str);
  3584. if ((type == RSPAMD_RE_HEADER || type == RSPAMD_RE_RAWHEADER)
  3585. && header_str == NULL) {
  3586. msg_err_task (
  3587. "header argument is mandatory for header/rawheader regexps");
  3588. }
  3589. else {
  3590. ret = rspamd_re_cache_process (task, re->re, type,
  3591. (gpointer) header_str, header_len, strong);
  3592. }
  3593. }
  3594. }
  3595. else {
  3596. return luaL_error (L, "invalid arguments");
  3597. }
  3598. lua_pushnumber (L, ret);
  3599. return 1;
  3600. }
  3601. static gint
  3602. lua_task_get_metric_score (lua_State *L)
  3603. {
  3604. struct rspamd_task *task = lua_check_task (L, 1);
  3605. gdouble rs;
  3606. struct rspamd_metric_result *metric_res;
  3607. if (task) {
  3608. if ((metric_res = task->result) != NULL) {
  3609. lua_createtable (L, 2, 0);
  3610. lua_pushnumber (L, isnan (metric_res->score) ? 0.0 : metric_res->score);
  3611. rs = rspamd_task_get_required_score (task, metric_res);
  3612. lua_rawseti (L, -2, 1);
  3613. lua_pushnumber (L, rs);
  3614. lua_rawseti (L, -2, 2);
  3615. }
  3616. else {
  3617. lua_pushnil (L);
  3618. }
  3619. }
  3620. else {
  3621. return luaL_error (L, "invalid arguments");
  3622. }
  3623. return 1;
  3624. }
  3625. static gint
  3626. lua_task_get_metric_action (lua_State *L)
  3627. {
  3628. struct rspamd_task *task = lua_check_task (L, 1);
  3629. struct rspamd_metric_result *metric_res;
  3630. enum rspamd_action_type action;
  3631. if (task) {
  3632. if ((metric_res = task->result) == NULL) {
  3633. metric_res = rspamd_create_metric_result (task);
  3634. }
  3635. action = rspamd_check_action_metric (task, metric_res);
  3636. lua_pushstring (L, rspamd_action_to_str (action));
  3637. }
  3638. else {
  3639. return luaL_error (L, "invalid arguments");
  3640. }
  3641. return 1;
  3642. }
  3643. static gint
  3644. lua_task_set_metric_score (lua_State *L)
  3645. {
  3646. struct rspamd_task *task = lua_check_task (L, 1);
  3647. struct rspamd_metric_result *metric_res;
  3648. gdouble nscore;
  3649. if (lua_isnumber (L, 2)) {
  3650. nscore = luaL_checknumber (L, 2);
  3651. }
  3652. else {
  3653. nscore = luaL_checknumber (L, 3);
  3654. }
  3655. if (task) {
  3656. if ((metric_res = task->result) != NULL) {
  3657. msg_debug_task ("set metric score from %.2f to %.2f",
  3658. metric_res->score, nscore);
  3659. metric_res->score = nscore;
  3660. lua_pushboolean (L, true);
  3661. }
  3662. else {
  3663. lua_pushboolean (L, false);
  3664. }
  3665. }
  3666. else {
  3667. return luaL_error (L, "invalid arguments");
  3668. }
  3669. return 1;
  3670. }
  3671. static gint
  3672. lua_task_disable_action (lua_State *L)
  3673. {
  3674. struct rspamd_task *task = lua_check_task (L, 1);
  3675. const gchar *action_name;
  3676. gint action;
  3677. action_name = luaL_checkstring (L, 2);
  3678. if (task && action_name && rspamd_action_from_str (action_name, &action)) {
  3679. if (!task->result) {
  3680. task->result = rspamd_create_metric_result (task);
  3681. }
  3682. if (isnan (task->result->actions_limits[action])) {
  3683. lua_pushboolean (L, false);
  3684. }
  3685. else {
  3686. task->result->actions_limits[action] = NAN;
  3687. lua_pushboolean (L, true);
  3688. }
  3689. }
  3690. else {
  3691. return luaL_error (L, "invalid arguments");
  3692. }
  3693. return 1;
  3694. }
  3695. static gint
  3696. lua_task_get_newlines_type (lua_State *L)
  3697. {
  3698. struct rspamd_task *task = lua_check_task (L, 1);
  3699. if (task) {
  3700. switch (task->nlines_type) {
  3701. case RSPAMD_TASK_NEWLINES_CR:
  3702. lua_pushstring (L, "cr");
  3703. break;
  3704. case RSPAMD_TASK_NEWLINES_LF:
  3705. lua_pushstring (L, "lf");
  3706. break;
  3707. case RSPAMD_TASK_NEWLINES_CRLF:
  3708. default:
  3709. lua_pushstring (L, "crlf");
  3710. break;
  3711. }
  3712. }
  3713. else {
  3714. return luaL_error (L, "invalid arguments");
  3715. }
  3716. return 1;
  3717. }
  3718. static gint
  3719. lua_task_set_metric_subject (lua_State *L)
  3720. {
  3721. struct rspamd_task *task = lua_check_task (L, 1);
  3722. const gchar *subject;
  3723. subject = luaL_checkstring (L, 2);
  3724. if (task && subject) {
  3725. rspamd_mempool_set_variable (task->task_pool, "metric_subject",
  3726. rspamd_mempool_strdup(task->task_pool, subject), NULL);
  3727. lua_pushboolean (L, true);
  3728. }
  3729. else {
  3730. return luaL_error (L, "invalid arguments");
  3731. }
  3732. return 1;
  3733. }
  3734. static gint
  3735. lua_task_get_protocol_reply (lua_State *L)
  3736. {
  3737. struct rspamd_task *task = lua_check_task (L, 1);
  3738. guint flags = 0;
  3739. ucl_object_t *obj;
  3740. if (!task) {
  3741. return luaL_error (L, "invalid arguments");
  3742. }
  3743. if (!(task->processed_stages & (RSPAMD_TASK_STAGE_POST_FILTERS >> 1))) {
  3744. return luaL_error (L, "must not be called before post-filters");
  3745. }
  3746. if (lua_istable (L, 2)) {
  3747. for (lua_pushnil (L); lua_next (L, 2); lua_pop (L, 1)) {
  3748. if (lua_isstring (L, -1)) {
  3749. const gchar *str = lua_tostring (L, -1);
  3750. if (strcmp (str, "default") == 0) {
  3751. flags |= RSPAMD_PROTOCOL_DEFAULT;
  3752. }
  3753. else if (strcmp (str, "basic") == 0) {
  3754. flags |= RSPAMD_PROTOCOL_BASIC;
  3755. }
  3756. else if (strcmp (str, "metrics") == 0) {
  3757. flags |= RSPAMD_PROTOCOL_METRICS;
  3758. }
  3759. else if (strcmp (str, "messages") == 0) {
  3760. flags |= RSPAMD_PROTOCOL_MESSAGES;
  3761. }
  3762. else if (strcmp (str, "rmilter") == 0) {
  3763. flags |= RSPAMD_PROTOCOL_RMILTER;
  3764. }
  3765. else if (strcmp (str, "dkim") == 0) {
  3766. flags |= RSPAMD_PROTOCOL_DKIM;
  3767. }
  3768. else if (strcmp (str, "extra") == 0) {
  3769. flags |= RSPAMD_PROTOCOL_EXTRA;
  3770. }
  3771. else {
  3772. msg_err_task ("invalid protocol flag: %s", str);
  3773. }
  3774. }
  3775. }
  3776. }
  3777. else {
  3778. flags = RSPAMD_PROTOCOL_DEFAULT;
  3779. }
  3780. obj = rspamd_protocol_write_ucl (task, flags);
  3781. if (obj) {
  3782. ucl_object_push_lua (L, obj, true);
  3783. }
  3784. else {
  3785. lua_pushnil (L);
  3786. }
  3787. return 1;
  3788. }
  3789. static gint
  3790. lua_task_headers_foreach (lua_State *L)
  3791. {
  3792. struct rspamd_task *task = lua_check_task (L, 1);
  3793. gboolean full = FALSE, raw = FALSE;
  3794. struct rspamd_lua_regexp *re = NULL;
  3795. GList *cur;
  3796. struct rspamd_mime_header *hdr;
  3797. gint old_top;
  3798. if (task && lua_isfunction (L, 2)) {
  3799. if (lua_istable (L, 3)) {
  3800. lua_pushstring (L, "full");
  3801. lua_gettable (L, 3);
  3802. if (lua_isboolean (L, -1)) {
  3803. full = lua_toboolean (L, -1);
  3804. }
  3805. lua_pop (L, 1);
  3806. lua_pushstring (L, "raw");
  3807. lua_gettable (L, 3);
  3808. if (lua_isboolean (L, -1)) {
  3809. raw = lua_toboolean (L, -1);
  3810. }
  3811. lua_pop (L, 1);
  3812. lua_pushstring (L, "regexp");
  3813. lua_gettable (L, 3);
  3814. if (lua_isuserdata (L, -1)) {
  3815. re = *(struct rspamd_lua_regexp **)
  3816. rspamd_lua_check_udata (L, -1, "rspamd{regexp}");
  3817. }
  3818. lua_pop (L, 1);
  3819. }
  3820. if (task->headers_order) {
  3821. cur = task->headers_order->head;
  3822. while (cur) {
  3823. hdr = cur->data;
  3824. if (re && re->re) {
  3825. if (!rspamd_regexp_match (re->re, hdr->name,
  3826. strlen (hdr->name),FALSE)) {
  3827. cur = g_list_next (cur);
  3828. continue;
  3829. }
  3830. }
  3831. old_top = lua_gettop (L);
  3832. lua_pushvalue (L, 2);
  3833. lua_pushstring (L, hdr->name);
  3834. rspamd_lua_push_header (L, hdr, full, raw);
  3835. if (lua_pcall (L, 2, LUA_MULTRET, 0) != 0) {
  3836. msg_err ("call to header_foreach failed: %s",
  3837. lua_tostring (L, -1));
  3838. lua_settop (L, old_top);
  3839. break;
  3840. }
  3841. else {
  3842. if (lua_gettop (L) > old_top) {
  3843. if (lua_isboolean (L, old_top + 1)) {
  3844. if (lua_toboolean (L, old_top + 1)) {
  3845. lua_settop (L, old_top);
  3846. break;
  3847. }
  3848. }
  3849. }
  3850. }
  3851. lua_settop (L, old_top);
  3852. cur = g_list_next (cur);
  3853. }
  3854. }
  3855. }
  3856. return 0;
  3857. }
  3858. /* Image functions */
  3859. static gint
  3860. lua_image_get_width (lua_State *L)
  3861. {
  3862. struct rspamd_image *img = lua_check_image (L);
  3863. if (img != NULL) {
  3864. lua_pushnumber (L, img->width);
  3865. }
  3866. else {
  3867. return luaL_error (L, "invalid arguments");
  3868. }
  3869. return 1;
  3870. }
  3871. static gint
  3872. lua_image_get_height (lua_State *L)
  3873. {
  3874. struct rspamd_image *img = lua_check_image (L);
  3875. if (img != NULL) {
  3876. lua_pushnumber (L, img->height);
  3877. }
  3878. else {
  3879. return luaL_error (L, "invalid arguments");
  3880. }
  3881. return 1;
  3882. }
  3883. static gint
  3884. lua_image_get_type (lua_State *L)
  3885. {
  3886. struct rspamd_image *img = lua_check_image (L);
  3887. if (img != NULL) {
  3888. lua_pushstring (L, rspamd_image_type_str (img->type));
  3889. }
  3890. else {
  3891. return luaL_error (L, "invalid arguments");
  3892. }
  3893. return 1;
  3894. }
  3895. static gint
  3896. lua_image_get_size (lua_State *L)
  3897. {
  3898. struct rspamd_image *img = lua_check_image (L);
  3899. if (img != NULL) {
  3900. lua_pushnumber (L, img->data->len);
  3901. }
  3902. else {
  3903. return luaL_error (L, "invalid arguments");
  3904. }
  3905. return 1;
  3906. }
  3907. static gint
  3908. lua_image_get_filename (lua_State *L)
  3909. {
  3910. struct rspamd_image *img = lua_check_image (L);
  3911. if (img != NULL && img->filename != NULL) {
  3912. lua_pushlstring (L, img->filename->begin, img->filename->len);
  3913. }
  3914. else {
  3915. return luaL_error (L, "invalid arguments");
  3916. }
  3917. return 1;
  3918. }
  3919. /* Arvhive methods */
  3920. static gint
  3921. lua_archive_get_type (lua_State *L)
  3922. {
  3923. struct rspamd_archive *arch = lua_check_archive (L);
  3924. if (arch != NULL) {
  3925. lua_pushstring (L, rspamd_archive_type_str (arch->type));
  3926. }
  3927. else {
  3928. return luaL_error (L, "invalid arguments");
  3929. }
  3930. return 1;
  3931. }
  3932. static gint
  3933. lua_archive_get_files (lua_State *L)
  3934. {
  3935. struct rspamd_archive *arch = lua_check_archive (L);
  3936. guint i;
  3937. struct rspamd_archive_file *f;
  3938. if (arch != NULL) {
  3939. lua_createtable (L, arch->files->len, 0);
  3940. for (i = 0; i < arch->files->len; i ++) {
  3941. f = g_ptr_array_index (arch->files, i);
  3942. lua_pushlstring (L, f->fname->str, f->fname->len);
  3943. lua_rawseti (L, -2, i + 1);
  3944. }
  3945. }
  3946. else {
  3947. return luaL_error (L, "invalid arguments");
  3948. }
  3949. return 1;
  3950. }
  3951. static gint
  3952. lua_archive_get_files_full (lua_State *L)
  3953. {
  3954. struct rspamd_archive *arch = lua_check_archive (L);
  3955. guint i;
  3956. struct rspamd_archive_file *f;
  3957. if (arch != NULL) {
  3958. lua_createtable (L, arch->files->len, 0);
  3959. for (i = 0; i < arch->files->len; i ++) {
  3960. f = g_ptr_array_index (arch->files, i);
  3961. lua_createtable (L, 0, 4);
  3962. lua_pushstring (L, "name");
  3963. lua_pushlstring (L, f->fname->str, f->fname->len);
  3964. lua_settable (L, -3);
  3965. lua_pushstring (L, "compressed_size");
  3966. lua_pushnumber (L, f->compressed_size);
  3967. lua_settable (L, -3);
  3968. lua_pushstring (L, "uncompressed_size");
  3969. lua_pushnumber (L, f->uncompressed_size);
  3970. lua_settable (L, -3);
  3971. lua_pushstring (L, "encrypted");
  3972. lua_pushboolean (L, (f->flags & RSPAMD_ARCHIVE_FILE_ENCRYPTED) ? true : false);
  3973. lua_settable (L, -3);
  3974. lua_rawseti (L, -2, i + 1);
  3975. }
  3976. }
  3977. else {
  3978. return luaL_error (L, "invalid arguments");
  3979. }
  3980. return 1;
  3981. }
  3982. static gint
  3983. lua_archive_is_encrypted (lua_State *L)
  3984. {
  3985. struct rspamd_archive *arch = lua_check_archive (L);
  3986. if (arch != NULL) {
  3987. lua_pushboolean (L, (arch->flags & RSPAMD_ARCHIVE_ENCRYPTED) ? true : false);
  3988. }
  3989. else {
  3990. return luaL_error (L, "invalid arguments");
  3991. }
  3992. return 1;
  3993. }
  3994. static gint
  3995. lua_archive_get_size (lua_State *L)
  3996. {
  3997. struct rspamd_archive *arch = lua_check_archive (L);
  3998. if (arch != NULL) {
  3999. lua_pushnumber (L, arch->size);
  4000. }
  4001. else {
  4002. return luaL_error (L, "invalid arguments");
  4003. }
  4004. return 1;
  4005. }
  4006. static gint
  4007. lua_archive_get_filename (lua_State *L)
  4008. {
  4009. struct rspamd_archive *arch = lua_check_archive (L);
  4010. if (arch != NULL) {
  4011. lua_pushlstring (L, arch->archive_name->begin, arch->archive_name->len);
  4012. }
  4013. else {
  4014. return luaL_error (L, "invalid arguments");
  4015. }
  4016. return 1;
  4017. }
  4018. /* Text methods */
  4019. static gint
  4020. lua_text_len (lua_State *L)
  4021. {
  4022. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4023. gsize l = 0;
  4024. if (t != NULL) {
  4025. l = t->len;
  4026. }
  4027. else {
  4028. return luaL_error (L, "invalid arguments");
  4029. }
  4030. lua_pushnumber (L, l);
  4031. return 1;
  4032. }
  4033. static gint
  4034. lua_text_str (lua_State *L)
  4035. {
  4036. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4037. if (t != NULL) {
  4038. lua_pushlstring (L, t->start, t->len);
  4039. }
  4040. else {
  4041. return luaL_error (L, "invalid arguments");
  4042. }
  4043. return 1;
  4044. }
  4045. static gint
  4046. lua_text_ptr (lua_State *L)
  4047. {
  4048. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4049. if (t != NULL) {
  4050. lua_pushlightuserdata (L, (gpointer)t->start);
  4051. }
  4052. else {
  4053. return luaL_error (L, "invalid arguments");
  4054. }
  4055. return 1;
  4056. }
  4057. static gint
  4058. lua_text_take_ownership (lua_State *L)
  4059. {
  4060. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4061. gchar *dest;
  4062. if (t != NULL) {
  4063. if (t->flags & RSPAMD_TEXT_FLAG_OWN) {
  4064. /* We already own it */
  4065. lua_pushboolean (L, true);
  4066. }
  4067. else {
  4068. dest = g_malloc (t->len);
  4069. memcpy (dest, t->start, t->len);
  4070. t->start = dest;
  4071. t->flags |= RSPAMD_TEXT_FLAG_OWN;
  4072. lua_pushboolean (L, true);
  4073. }
  4074. }
  4075. else {
  4076. return luaL_error (L, "invalid arguments");
  4077. }
  4078. return 1;
  4079. }
  4080. static gint
  4081. lua_text_save_in_file (lua_State *L)
  4082. {
  4083. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4084. const gchar *fname = luaL_checkstring (L, 2);
  4085. guint mode = 00644;
  4086. gint fd;
  4087. if (t != NULL && fname != NULL) {
  4088. if (lua_type (L, 3) == LUA_TNUMBER) {
  4089. mode = lua_tonumber (L, 3);
  4090. }
  4091. fd = rspamd_file_xopen (fname, O_CREAT | O_WRONLY | O_EXCL, mode, 0);
  4092. if (fd == -1) {
  4093. lua_pushboolean (L, false);
  4094. lua_pushstring (L, strerror (errno));
  4095. return 2;
  4096. }
  4097. if (write (fd, t->start, t->len) == -1) {
  4098. close (fd);
  4099. lua_pushboolean (L, false);
  4100. lua_pushstring (L, strerror (errno));
  4101. return 2;
  4102. }
  4103. close (fd);
  4104. lua_pushboolean (L, true);
  4105. }
  4106. else {
  4107. return luaL_error (L, "invalid arguments");
  4108. }
  4109. return 1;
  4110. }
  4111. static gint
  4112. lua_text_gc (lua_State *L)
  4113. {
  4114. struct rspamd_lua_text *t = lua_check_text (L, 1);
  4115. if (t != NULL) {
  4116. if (t->flags & RSPAMD_TEXT_FLAG_OWN) {
  4117. if (t->flags & RSPAMD_TEXT_FLAG_MMAPED) {
  4118. munmap ((gpointer)t->start, t->len);
  4119. }
  4120. else {
  4121. g_free ((gpointer)t->start);
  4122. }
  4123. }
  4124. }
  4125. return 0;
  4126. }
  4127. /* Init part */
  4128. static gint
  4129. lua_load_task (lua_State * L)
  4130. {
  4131. lua_newtable (L);
  4132. luaL_register (L, NULL, tasklib_f);
  4133. return 1;
  4134. }
  4135. static void
  4136. luaopen_archive (lua_State * L)
  4137. {
  4138. rspamd_lua_new_class (L, "rspamd{archive}", archivelib_m);
  4139. lua_pop (L, 1);
  4140. }
  4141. void
  4142. luaopen_task (lua_State * L)
  4143. {
  4144. rspamd_lua_new_class (L, "rspamd{task}", tasklib_m);
  4145. lua_pop (L, 1);
  4146. rspamd_lua_add_preload (L, "rspamd_task", lua_load_task);
  4147. luaopen_archive (L);
  4148. }
  4149. void
  4150. luaopen_image (lua_State * L)
  4151. {
  4152. rspamd_lua_new_class (L, "rspamd{image}", imagelib_m);
  4153. lua_pop (L, 1);
  4154. }
  4155. void
  4156. luaopen_text (lua_State *L)
  4157. {
  4158. rspamd_lua_new_class (L, "rspamd{text}", textlib_m);
  4159. lua_pop (L, 1);
  4160. }
  4161. void
  4162. rspamd_lua_task_push (lua_State *L, struct rspamd_task *task)
  4163. {
  4164. struct rspamd_task **ptask;
  4165. ptask = lua_newuserdata (L, sizeof (gpointer));
  4166. rspamd_lua_setclass (L, "rspamd{task}", -1);
  4167. *ptask = task;
  4168. }