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 110KB

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