Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

lua_task.c 83KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601
  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 "protocol.h"
  19. #include "filter.h"
  20. #include "dns.h"
  21. #include "util.h"
  22. #include "images.h"
  23. #include "archives.h"
  24. #include "cfg_file.h"
  25. #include "email_addr.h"
  26. #include "utlist.h"
  27. #include "cryptobox.h"
  28. #include "unix-std.h"
  29. /***
  30. * @module rspamd_task
  31. * This module provides routines for tasks manipulation in rspamd. Tasks usually
  32. * represent messages being scanned, and this API provides access to such elements
  33. * as headers, symbols, metrics and so on and so forth. Normally, task objects
  34. * are passed to the lua callbacks allowing to check specific properties of messages
  35. * and add the corresponding symbols to the scan's results.
  36. @example
  37. rspamd_config.DATE_IN_PAST = function(task)
  38. if rspamd_config:get_api_version() >= 5 then
  39. local dm = task:get_date{format = 'message', gmt = true}
  40. local dt = task:get_date{format = 'connect', gmt = true}
  41. -- A day
  42. if dt - dm > 86400 then
  43. return true
  44. end
  45. end
  46. return false
  47. end
  48. */
  49. /* Task methods */
  50. LUA_FUNCTION_DEF (task, get_message);
  51. LUA_FUNCTION_DEF (task, process_message);
  52. /***
  53. * @method task:get_cfg()
  54. * Get configuration object for a task.
  55. * @return {rspamd_config} (config.md)[configuration object] for the task
  56. */
  57. LUA_FUNCTION_DEF (task, get_cfg);
  58. LUA_FUNCTION_DEF (task, set_cfg);
  59. LUA_FUNCTION_DEF (task, destroy);
  60. /***
  61. * @method task:get_mempool()
  62. * Returns memory pool valid for a lifetime of task. It is used internally by
  63. * many rspamd routines.
  64. * @return {rspamd_mempool} memory pool object
  65. */
  66. LUA_FUNCTION_DEF (task, get_mempool);
  67. /***
  68. * @method task:get_session()
  69. * Returns asynchronous session object that is used by many rspamd asynchronous
  70. * utilities internally.
  71. * @return {rspamd_session} session object
  72. */
  73. LUA_FUNCTION_DEF (task, get_session);
  74. /***
  75. * @method task:get_ev_base()
  76. * Return asynchronous event base for using in callbacks and resolver.
  77. * @return {rspamd_ev_base} event base
  78. */
  79. LUA_FUNCTION_DEF (task, get_ev_base);
  80. /***
  81. * @method task:insert_result(symbol, weigth[, 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:set_pre_results(action, description)
  97. * Sets pre-result for a task. It is used in pre-filters to specify early results
  98. * of the task scanned. If a pre-filter sets some result, then further processing
  99. * may be skipped. For selecting action it is possible to use global table
  100. * `rspamd_actions` or a string value:
  101. *
  102. * - `reject`: reject message permanently
  103. * - `add header`: add spam header
  104. * - `rewrite subject`: rewrite subject to spam subject
  105. * - `greylist`: greylist message
  106. * - `accept` or `no action`: whitelist message
  107. * @param {rspamd_action or string} action a numeric or string action value
  108. * @param {string} description optional descripton
  109. @example
  110. local function cb(task)
  111. local gr = task:get_header('Greylist')
  112. if gr and gr == 'greylist' then
  113. task:set_pre_result(rspamd_actions['greylist'], 'Greylisting required')
  114. end
  115. end
  116. */
  117. LUA_FUNCTION_DEF (task, set_pre_result);
  118. /***
  119. * @method task:append_message(message)
  120. * Adds a message to scanning output.
  121. * @param {string} message
  122. @example
  123. local function cb(task)
  124. task:append_message('Example message')
  125. end
  126. */
  127. LUA_FUNCTION_DEF (task, append_message);
  128. /***
  129. * @method task:get_urls([need_emails])
  130. * Get all URLs found in a message.
  131. * @param {boolean} need_emails if `true` then reutrn also email urls
  132. * @return {table rspamd_url} list of all urls found
  133. @example
  134. local function phishing_cb(task)
  135. local urls = task:get_urls();
  136. if urls then
  137. for _,url in ipairs(urls) do
  138. if url:is_phished() then
  139. return true
  140. end
  141. end
  142. end
  143. return false
  144. end
  145. */
  146. LUA_FUNCTION_DEF (task, get_urls);
  147. /***
  148. * @method task:has_urls([need_emails])
  149. * Returns 'true' if a task has urls listed
  150. * @param {boolean} need_emails if `true` then reutrn also email urls
  151. * @return {boolean} true if a task has urls (urls or emails if `need_emails` is true)
  152. */
  153. LUA_FUNCTION_DEF (task, has_urls);
  154. /***
  155. * @method task:get_content()
  156. * Get raw content for the specified task
  157. * @return {text} the data contained in the task
  158. */
  159. LUA_FUNCTION_DEF (task, get_content);
  160. /***
  161. * @method task:get_rawbody()
  162. * Get raw body for the specified task
  163. * @return {text} the data contained in the task
  164. */
  165. LUA_FUNCTION_DEF (task, get_rawbody);
  166. /***
  167. * @method task:get_emails()
  168. * Get all email addresses found in a message.
  169. * @return {table rspamd_url} list of all email addresses found
  170. */
  171. LUA_FUNCTION_DEF (task, get_emails);
  172. /***
  173. * @method task:get_text_parts()
  174. * Get all text (and HTML) parts found in a message
  175. * @return {table rspamd_text_part} list of text parts
  176. */
  177. LUA_FUNCTION_DEF (task, get_text_parts);
  178. /***
  179. * @method task:get_parts()
  180. * Get all mime parts found in a message
  181. * @return {table rspamd_mime_part} list of mime parts
  182. */
  183. LUA_FUNCTION_DEF (task, get_parts);
  184. /***
  185. * @method task:get_request_header(name)
  186. * Get value of a HTTP request header.
  187. * @param {string} name name of header to get
  188. * @return {rspamd_text} value of an HTTP header
  189. */
  190. LUA_FUNCTION_DEF (task, get_request_header);
  191. /***
  192. * @method task:set_request_header(name, value)
  193. * Set value of a HTTP request header. If value is omitted, then a header is removed
  194. * @param {string} name name of header to get
  195. * @param {rspamd_text/string} value new header's value
  196. */
  197. LUA_FUNCTION_DEF (task, set_request_header);
  198. /***
  199. * @method task:get_header(name[, case_sensitive])
  200. * Get decoded value of a header specified with optional case_sensitive flag.
  201. * By default headers are searched in caseless matter.
  202. * @param {string} name name of header to get
  203. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  204. * @return {string} decoded value of a header
  205. */
  206. LUA_FUNCTION_DEF (task, get_header);
  207. /***
  208. * @method task:get_header_raw(name[, case_sensitive])
  209. * Get raw value of a header specified with optional case_sensitive flag.
  210. * By default headers are searched in caseless matter.
  211. * @param {string} name name of header to get
  212. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  213. * @return {string} raw value of a header
  214. */
  215. LUA_FUNCTION_DEF (task, get_header_raw);
  216. /***
  217. * @method task:get_header_full(name[, case_sensitive])
  218. * Get raw value of a header specified with optional case_sensitive flag.
  219. * By default headers are searched in caseless matter. This method returns more
  220. * information about the header as a list of tables with the following structure:
  221. *
  222. * - `name` - name of a header
  223. * - `value` - raw value of a header
  224. * - `decoded` - decoded value of a header
  225. * - `tab_separated` - `true` if a header and a value are separated by `tab` character
  226. * - `empty_separator` - `true` if there are no separator between a header and a value
  227. * @param {string} name name of header to get
  228. * @param {boolean} case_sensitive case sensitiveness flag to search for a header
  229. * @return {list of tables} all values of a header as specified above
  230. @example
  231. function check_header_delimiter_tab(task, header_name)
  232. for _,rh in ipairs(task:get_header_full(header_name)) do
  233. if rh['tab_separated'] then return true end
  234. end
  235. return false
  236. end
  237. */
  238. LUA_FUNCTION_DEF (task, get_header_full);
  239. /***
  240. * @method task:get_raw_headers()
  241. * Get all undecoded headers of a message as a string
  242. * @return {rspamd_text} all raw headers for a message as opaque text
  243. */
  244. LUA_FUNCTION_DEF (task, get_raw_headers);
  245. /***
  246. * @method task:get_received_headers()
  247. * Returns a list of tables of parsed received headers. A tables returned have
  248. * the following structure:
  249. *
  250. * - `from_hostname` - string that represents hostname provided by a peer
  251. * - `from_ip` - string representation of IP address as provided by a peer
  252. * - `real_hostname` - hostname as resolved by MTA
  253. * - `real_ip` - string representation of IP as resolved by PTR request of MTA
  254. * - `by_hostname` - MTA hostname
  255. * - `proto` - protocol, e.g. ESMTP or ESMTPS
  256. * - `timestamp` - received timetamp
  257. * - `for` - for value (unparsed mailbox)
  258. *
  259. * Please note that in some situations rspamd cannot parse all the fields of received headers.
  260. * In that case you should check all strings for validity.
  261. * @return {table of tables} list of received headers described above
  262. */
  263. LUA_FUNCTION_DEF (task, get_received_headers);
  264. /***
  265. * @method task:get_queue_id()
  266. * Returns queue ID of the message being processed.
  267. */
  268. LUA_FUNCTION_DEF (task, get_queue_id);
  269. /***
  270. * @method task:get_uid()
  271. * Returns ID of the task being processed.
  272. */
  273. LUA_FUNCTION_DEF (task, get_uid);
  274. /***
  275. * @method task:get_resolver()
  276. * Returns ready to use rspamd_resolver object suitable for making asynchronous DNS requests.
  277. * @return {rspamd_resolver} resolver object associated with the task's session
  278. * @example
  279. local logger = require "rspamd_logger"
  280. local function task_cb(task)
  281. local function dns_cb(resolver, to_resolve, results, err)
  282. -- task object is available due to closure
  283. task:inc_dns_req()
  284. if results then
  285. logger.info(string.format('<%s> [%s] resolved for symbol: %s',
  286. task:get_message_id(), to_resolve, 'EXAMPLE_SYMBOL'))
  287. task:insert_result('EXAMPLE_SYMBOL', 1)
  288. end
  289. end
  290. local r = task:get_resolver()
  291. r:resolve_a(task:get_session(), task:get_mempool(), 'example.com', dns_cb)
  292. end
  293. */
  294. LUA_FUNCTION_DEF (task, get_resolver);
  295. /***
  296. * @method task:inc_dns_req()
  297. * Increment number of DNS requests for the task. Is used just for logging purposes.
  298. */
  299. LUA_FUNCTION_DEF (task, inc_dns_req);
  300. /***
  301. * @method task:get_dns_req()
  302. * Get number of dns requests being sent in the task
  303. * @return {number} number of DNS requests
  304. */
  305. LUA_FUNCTION_DEF (task, get_dns_req);
  306. /***
  307. * @method task:has_recipients([type])
  308. * Return true if there are SMTP or MIME recipients for a task.
  309. * @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
  310. * @return {bool} `true` if there are recipients of the following type
  311. */
  312. LUA_FUNCTION_DEF (task, has_recipients);
  313. /***
  314. * @method task:get_recipients([type])
  315. * Return SMTP or MIME recipients for a task. This function returns list of internet addresses each one is a table with the following structure:
  316. *
  317. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  318. * - `addr` - address part of the address
  319. * - `user` - user part (if present) of the address, e.g. `blah`
  320. * - `domain` - domain part (if present), e.g. `foo.com`
  321. * @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
  322. * @return {list of addresses} list of recipients or `nil`
  323. */
  324. LUA_FUNCTION_DEF (task, get_recipients);
  325. /***
  326. * @method task:has_from([type])
  327. * Return true if there is SMTP or MIME sender for a task.
  328. * @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
  329. * @return {bool} `true` if there is sender of the following type
  330. */
  331. LUA_FUNCTION_DEF (task, has_from);
  332. /***
  333. * @method task:get_from([type])
  334. * Return SMTP or MIME sender for a task. This function returns list of internet addresses each one is a table with the following structure:
  335. *
  336. * - `name` - name of internet address in UTF8, e.g. for `Vsevolod Stakhov <blah@foo.com>` it returns `Vsevolod Stakhov`
  337. * - `addr` - address part of the address
  338. * - `user` - user part (if present) of the address, e.g. `blah`
  339. * - `domain` - domain part (if present), e.g. `foo.com`
  340. * @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
  341. * @return {list of addresses} list of recipients or `nil`
  342. */
  343. LUA_FUNCTION_DEF (task, get_from);
  344. /***
  345. * @method task:get_user()
  346. * Returns authenticated user name for this task if specified by an MTA.
  347. * @return {string} username or nil
  348. */
  349. LUA_FUNCTION_DEF (task, get_user);
  350. LUA_FUNCTION_DEF (task, set_user);
  351. /***
  352. * @method task:get_from_ip()
  353. * Returns [ip_addr](ip.md) object of a sender that is provided by MTA
  354. * @return {rspamd_ip} ip address object
  355. */
  356. LUA_FUNCTION_DEF (task, get_from_ip);
  357. /***
  358. * @method task:set_from_ip(str)
  359. * Set tasks's IP address based on the passed string
  360. * @param {string} str string representation of ip
  361. */
  362. LUA_FUNCTION_DEF (task, set_from_ip);
  363. LUA_FUNCTION_DEF (task, get_from_ip_num);
  364. /***
  365. * @method task:get_client_ip()
  366. * Returns [ip_addr](ip.md) object of a client connected to rspamd (normally, it is an IP address of MTA)
  367. * @return {rspamd_ip} ip address object
  368. */
  369. LUA_FUNCTION_DEF (task, get_client_ip);
  370. /***
  371. * @method task:get_helo()
  372. * Returns the value of SMTP helo provided by MTA.
  373. * @return {string} HELO value
  374. */
  375. LUA_FUNCTION_DEF (task, get_helo);
  376. LUA_FUNCTION_DEF (task, set_helo);
  377. /***
  378. * @method task:get_hostname()
  379. * Returns the value of sender's hostname provided by MTA
  380. * @return {string} hostname value
  381. */
  382. LUA_FUNCTION_DEF (task, get_hostname);
  383. LUA_FUNCTION_DEF (task, set_hostname);
  384. /***
  385. * @method task:get_images()
  386. * Returns list of all images found in a task as a table of `rspamd_image`.
  387. * Each image has the following methods:
  388. *
  389. * * `get_width` - return width of an image in pixels
  390. * * `get_height` - return height of an image in pixels
  391. * * `get_type` - return string representation of image's type (e.g. 'jpeg')
  392. * * `get_filename` - return string with image's file name
  393. * * `get_size` - return size in bytes
  394. * @return {list of rspamd_image} images found in a message
  395. */
  396. LUA_FUNCTION_DEF (task, get_images);
  397. /***
  398. * @method task:get_archives()
  399. * Returns list of all archives found in a task as a table of `rspamd_archive`.
  400. * Each archive has the following methods available:
  401. *
  402. * * `get_files` - return list of strings with filenames inside archive
  403. * * `get_files_full` - return list of tables with all information about files
  404. * * `is_encrypted` - return true if an archive is encrypted
  405. * * `get_type` - return string representation of image's type (e.g. 'zip')
  406. * * `get_filename` - return string with archive's file name
  407. * * `get_size` - return size in bytes
  408. * @return {list of rspamd_archive} archives found in a message
  409. */
  410. LUA_FUNCTION_DEF (task, get_archives);
  411. /***
  412. * @method task:get_symbol(name)
  413. * Searches for a symbol `name` in all metrics results and returns a list of tables
  414. * one per metric that describes the symbol inserted. Please note that this function
  415. * is intended to return values for **inserted** symbols, so if this symbol was not
  416. * inserted it won't be in the function's output. This method is useful for post-filters mainly.
  417. * The symbols are returned as the list of the following tables:
  418. *
  419. * - `metric` - name of metric
  420. * - `score` - score of a symbol in that metric
  421. * - `options` - a table of strings representing options of a symbol
  422. * - `group` - a group of symbol (or 'ungrouped')
  423. * @param {string} name symbol's name
  424. * @return {list of tables} list of tables or nil if symbol was not found in any metric
  425. */
  426. LUA_FUNCTION_DEF (task, get_symbol);
  427. /***
  428. * @method task:get_symbols()
  429. * Returns array of all symbols matched for this task
  430. * @return {table, table} table of strings with symbols names + table of theirs scores
  431. */
  432. LUA_FUNCTION_DEF (task, get_symbols);
  433. /***
  434. * @method task:get_symbols_numeric()
  435. * Returns array of all symbols matched for this task
  436. * @return {table|number, table|number} table of numbers with symbols ids + table of theirs scores
  437. */
  438. LUA_FUNCTION_DEF (task, get_symbols_numeric);
  439. /***
  440. * @method task:has_symbol(name)
  441. * Fast path to check if a specified symbol is in the task's results
  442. * @param {string} name symbol's name
  443. * @return {boolean} `true` if symbol has been found
  444. */
  445. LUA_FUNCTION_DEF (task, has_symbol);
  446. /***
  447. * @method task:get_date(type[, gmt])
  448. * Returns timestamp for a connection or for a MIME message. This function can be called with a
  449. * single table arguments with the following fields:
  450. *
  451. * * `format` - a format of date returned:
  452. * - `message` - returns a mime date as integer (unix timestamp)
  453. * - `message_str` - returns a mime date as string (UTC format)
  454. * - `connect` - returns a unix timestamp of a connection to rspamd
  455. * - `connect_str` - returns connection time in UTC format
  456. * * `gmt` - returns date in `GMT` timezone (normal for unix timestamps)
  457. *
  458. * By default this function returns connection time in numeric format.
  459. * @param {string} type date format as described above
  460. * @param {boolean} gmt gmt flag as described above
  461. * @return {string/number} date representation according to format
  462. * @example
  463. rspamd_config.DATE_IN_PAST = function(task)
  464. local dm = task:get_date{format = 'message', gmt = true}
  465. local dt = task:get_date{format = 'connect', gmt = true}
  466. -- A day
  467. if dt - dm > 86400 then
  468. return true
  469. end
  470. return false
  471. end
  472. */
  473. LUA_FUNCTION_DEF (task, get_date);
  474. /***
  475. * @method task:get_message_id()
  476. * Returns message id of the specified task
  477. * @return {string} if of a message
  478. */
  479. LUA_FUNCTION_DEF (task, get_message_id);
  480. LUA_FUNCTION_DEF (task, get_timeval);
  481. /***
  482. * @method task:get_metric_score(name)
  483. * Get the current score of metric `name`. Should be used in post-filters only.
  484. * @param {string} name name of a metric
  485. * @return {table} table containing the current score and required score of the metric
  486. */
  487. LUA_FUNCTION_DEF (task, get_metric_score);
  488. /***
  489. * @method task:get_metric_action(name)
  490. * Get the current action of metric `name`. Should be used in post-filters only.
  491. * @param {string} name name of a metric
  492. * @return {string} the current action of the metric as a string
  493. */
  494. LUA_FUNCTION_DEF (task, get_metric_action);
  495. /***
  496. * @method task:set_metric_score(name, score)
  497. * Set the current score of metric `name`. Should be used in post-filters only.
  498. * @param {string} name name of a metric
  499. * @param {number} score the current score of the metric
  500. */
  501. LUA_FUNCTION_DEF (task, set_metric_score);
  502. /***
  503. * @method task:set_metric_action(name, action)
  504. * Set the current action of metric `name`. Should be used in post-filters only.
  505. * @param {string} name name of a metric
  506. * @param {string} action name to set
  507. */
  508. LUA_FUNCTION_DEF (task, set_metric_action);
  509. /***
  510. * @method task:learn(is_spam[, classifier)
  511. * Learn classifier `classifier` with the task. If `is_spam` is true then message
  512. * is learnt as spam. Otherwise HAM is learnt. By default, this function learns
  513. * `bayes` classifier.
  514. * @param {boolean} is_spam learn spam or ham
  515. * @param {string} classifier classifier's name
  516. * @return {boolean} `true` if classifier has been learnt successfully
  517. */
  518. LUA_FUNCTION_DEF (task, learn);
  519. /***
  520. * @method task:set_settings(obj)
  521. * Set users settings object for a task. The format of this object is described
  522. * [here](https://rspamd.com/doc/configuration/settings.html).
  523. * @param {any} obj any lua object that corresponds to the settings format
  524. */
  525. LUA_FUNCTION_DEF (task, set_settings);
  526. /***
  527. * @method task:get_settings()
  528. * Gets users settings object for a task. The format of this object is described
  529. * [here](https://rspamd.com/doc/configuration/settings.html).
  530. * @return {lua object} lua object generated from UCL
  531. */
  532. LUA_FUNCTION_DEF (task, get_settings);
  533. /***
  534. * @method task:lookup_settings(key)
  535. * Gets users settings object with the specified key for a task.
  536. * @param {string} key key to lookup
  537. * @return {lua object} lua object generated from UCL
  538. */
  539. LUA_FUNCTION_DEF (task, lookup_settings);
  540. /***
  541. * @method task:get_settings_id()
  542. * Get numeric hash of settings id if specified for this task. 0 is returned otherwise.
  543. * @return {number} settings-id hash
  544. */
  545. LUA_FUNCTION_DEF (task, get_settings_id);
  546. /***
  547. * @method task:set_rmilter_reply(obj)
  548. * Set special reply for rmilter
  549. * @param {any} obj any lua object that corresponds to the settings format
  550. * @example
  551. task:set_rmilter_reply({
  552. add_headers = {['X-Lua'] = 'test'},
  553. -- 1 is the position of header to remove
  554. remove_headers = {['DKIM-Signature'] = 1},
  555. })
  556. */
  557. LUA_FUNCTION_DEF (task, set_rmilter_reply);
  558. /***
  559. * @method task:process_re(params)
  560. * Processes the specified regexp and returns number of captures (cached or new)
  561. * Params is the table with the follwoing fields (mandatory fields are marked with `*`):
  562. * - `re`* : regular expression object
  563. * - `type`*: type of regular expression:
  564. * + `mime`: mime regexp
  565. * + `header`: header regexp
  566. * + `rawheader`: raw header expression
  567. * + `rawmime`: raw mime regexp
  568. * + `body`: raw body regexp
  569. * + `url`: url regexp
  570. * - `header`: for header and rawheader regexp means the name of header
  571. * - `strong`: case sensitive match for headers
  572. * @return {number} number of regexp occurences in the task (limited by 255 so far)
  573. */
  574. LUA_FUNCTION_DEF (task, process_regexp);
  575. /*
  576. * Deprecated functions!
  577. */
  578. LUA_FUNCTION_DEF (task, cache_set);
  579. LUA_FUNCTION_DEF (task, cache_get);
  580. /***
  581. * @method task:get_size()
  582. * Returns size of the task in bytes (that includes headers + parts size)
  583. * @return {number} size in bytes
  584. */
  585. LUA_FUNCTION_DEF (task, get_size);
  586. /***
  587. * @method task:set_flag(flag_name[, set])
  588. * Set specific flag for task:
  589. *
  590. * - `no_log`: do not log task summary
  591. * - `no_stat`: do not include task into scanned stats
  592. * - `pass_all`: check all filters for task
  593. * - `extended_urls`: output extended info about urls
  594. * - `skip`: skip task processing
  595. * - `learn_spam`: learn message as spam
  596. * - `learn_ham`: learn message as ham
  597. * - `broken_headers`: header data is broken for a message
  598. * @param {string} flag to set
  599. * @param {boolean} set set or clear flag (default is set)
  600. @example
  601. --[[
  602. For messages with undefined queue ID (scanned with rspamc or WebUI)
  603. do not include results into statistics and do not log task summary
  604. (it will not appear in the WebUI history as well).
  605. ]]--
  606. -- Callback function to set flags
  607. local function no_log_stat_cb(task)
  608. if not task:get_queue_id() then
  609. task:set_flag('no_log')
  610. task:set_flag('no_stat')
  611. end
  612. end
  613. rspamd_config:register_symbol({
  614. name = 'LOCAL_NO_LOG_STAT',
  615. type = 'postfilter',
  616. callback = no_log_stat_cb
  617. })
  618. */
  619. LUA_FUNCTION_DEF (task, set_flag);
  620. /***
  621. * @method task:has_flag(flag_name)
  622. * Checks for a specific flag in task:
  623. *
  624. * - `no_log`: do not log task summary
  625. * - `no_stat`: do not include task into scanned stats
  626. * - `pass_all`: check all filters for task
  627. * - `extended_urls`: output extended info about urls
  628. * - `skip`: skip task processing
  629. * - `learn_spam`: learn message as spam
  630. * - `learn_ham`: learn message as ham
  631. * - `broken_headers`: header data is broken for a message
  632. * @param {string} flag to check
  633. * @return {boolean} true if flags is set
  634. */
  635. LUA_FUNCTION_DEF (task, has_flag);
  636. /***
  637. * @method task:get_flags()
  638. * Get list of flags for task:
  639. *
  640. * - `no_log`: do not log task summary
  641. * - `no_stat`: do not include task into scanned stats
  642. * - `pass_all`: check all filters for task
  643. * - `extended_urls`: output extended info about urls
  644. * - `skip`: skip task processing
  645. * - `learn_spam`: learn message as spam
  646. * - `learn_ham`: learn message as ham
  647. * - `broken_headers`: header data is broken for a message
  648. * @return {array of strings} table with all flags as strings
  649. */
  650. LUA_FUNCTION_DEF (task, get_flags);
  651. /***
  652. * @method task:get_digest()
  653. * Returns message's unique digest (32 hex symbols)
  654. * @return {string} hex digest
  655. */
  656. LUA_FUNCTION_DEF (task, get_digest);
  657. static const struct luaL_reg tasklib_f[] = {
  658. {NULL, NULL}
  659. };
  660. static const struct luaL_reg tasklib_m[] = {
  661. LUA_INTERFACE_DEF (task, get_message),
  662. LUA_INTERFACE_DEF (task, destroy),
  663. LUA_INTERFACE_DEF (task, process_message),
  664. LUA_INTERFACE_DEF (task, set_cfg),
  665. LUA_INTERFACE_DEF (task, get_cfg),
  666. LUA_INTERFACE_DEF (task, get_mempool),
  667. LUA_INTERFACE_DEF (task, get_session),
  668. LUA_INTERFACE_DEF (task, get_ev_base),
  669. LUA_INTERFACE_DEF (task, insert_result),
  670. LUA_INTERFACE_DEF (task, set_pre_result),
  671. LUA_INTERFACE_DEF (task, append_message),
  672. LUA_INTERFACE_DEF (task, has_urls),
  673. LUA_INTERFACE_DEF (task, get_urls),
  674. LUA_INTERFACE_DEF (task, get_content),
  675. LUA_INTERFACE_DEF (task, get_rawbody),
  676. LUA_INTERFACE_DEF (task, get_emails),
  677. LUA_INTERFACE_DEF (task, get_text_parts),
  678. LUA_INTERFACE_DEF (task, get_parts),
  679. LUA_INTERFACE_DEF (task, get_request_header),
  680. LUA_INTERFACE_DEF (task, set_request_header),
  681. LUA_INTERFACE_DEF (task, get_header),
  682. LUA_INTERFACE_DEF (task, get_header_raw),
  683. LUA_INTERFACE_DEF (task, get_header_full),
  684. LUA_INTERFACE_DEF (task, get_raw_headers),
  685. LUA_INTERFACE_DEF (task, get_received_headers),
  686. LUA_INTERFACE_DEF (task, get_queue_id),
  687. LUA_INTERFACE_DEF (task, get_uid),
  688. LUA_INTERFACE_DEF (task, get_resolver),
  689. LUA_INTERFACE_DEF (task, inc_dns_req),
  690. LUA_INTERFACE_DEF (task, get_dns_req),
  691. LUA_INTERFACE_DEF (task, has_recipients),
  692. LUA_INTERFACE_DEF (task, get_recipients),
  693. LUA_INTERFACE_DEF (task, has_from),
  694. LUA_INTERFACE_DEF (task, get_from),
  695. LUA_INTERFACE_DEF (task, get_user),
  696. LUA_INTERFACE_DEF (task, set_user),
  697. {"get_addr", lua_task_get_from_ip},
  698. {"get_ip", lua_task_get_from_ip},
  699. {"get_from_addr", lua_task_get_from_ip},
  700. LUA_INTERFACE_DEF (task, get_from_ip),
  701. LUA_INTERFACE_DEF (task, set_from_ip),
  702. LUA_INTERFACE_DEF (task, get_from_ip_num),
  703. LUA_INTERFACE_DEF (task, get_client_ip),
  704. LUA_INTERFACE_DEF (task, get_helo),
  705. LUA_INTERFACE_DEF (task, set_helo),
  706. LUA_INTERFACE_DEF (task, get_hostname),
  707. LUA_INTERFACE_DEF (task, set_hostname),
  708. LUA_INTERFACE_DEF (task, get_images),
  709. LUA_INTERFACE_DEF (task, get_archives),
  710. LUA_INTERFACE_DEF (task, get_symbol),
  711. LUA_INTERFACE_DEF (task, get_symbols),
  712. LUA_INTERFACE_DEF (task, get_symbols_numeric),
  713. LUA_INTERFACE_DEF (task, has_symbol),
  714. LUA_INTERFACE_DEF (task, get_date),
  715. LUA_INTERFACE_DEF (task, get_message_id),
  716. LUA_INTERFACE_DEF (task, get_timeval),
  717. LUA_INTERFACE_DEF (task, get_metric_score),
  718. LUA_INTERFACE_DEF (task, get_metric_action),
  719. LUA_INTERFACE_DEF (task, set_metric_score),
  720. LUA_INTERFACE_DEF (task, set_metric_action),
  721. LUA_INTERFACE_DEF (task, learn),
  722. LUA_INTERFACE_DEF (task, set_settings),
  723. LUA_INTERFACE_DEF (task, get_settings),
  724. LUA_INTERFACE_DEF (task, lookup_settings),
  725. LUA_INTERFACE_DEF (task, get_settings_id),
  726. LUA_INTERFACE_DEF (task, cache_get),
  727. LUA_INTERFACE_DEF (task, cache_set),
  728. LUA_INTERFACE_DEF (task, process_regexp),
  729. LUA_INTERFACE_DEF (task, get_size),
  730. LUA_INTERFACE_DEF (task, set_flag),
  731. LUA_INTERFACE_DEF (task, get_flags),
  732. LUA_INTERFACE_DEF (task, has_flag),
  733. LUA_INTERFACE_DEF (task, set_rmilter_reply),
  734. LUA_INTERFACE_DEF (task, get_digest),
  735. {"__tostring", rspamd_lua_class_tostring},
  736. {NULL, NULL}
  737. };
  738. /* Image methods */
  739. LUA_FUNCTION_DEF (image, get_width);
  740. LUA_FUNCTION_DEF (image, get_height);
  741. LUA_FUNCTION_DEF (image, get_type);
  742. LUA_FUNCTION_DEF (image, get_filename);
  743. LUA_FUNCTION_DEF (image, get_size);
  744. static const struct luaL_reg imagelib_m[] = {
  745. LUA_INTERFACE_DEF (image, get_width),
  746. LUA_INTERFACE_DEF (image, get_height),
  747. LUA_INTERFACE_DEF (image, get_type),
  748. LUA_INTERFACE_DEF (image, get_filename),
  749. LUA_INTERFACE_DEF (image, get_size),
  750. {"__tostring", rspamd_lua_class_tostring},
  751. {NULL, NULL}
  752. };
  753. /* Archive methods */
  754. LUA_FUNCTION_DEF (archive, get_type);
  755. LUA_FUNCTION_DEF (archive, get_files);
  756. LUA_FUNCTION_DEF (archive, get_files_full);
  757. LUA_FUNCTION_DEF (archive, is_encrypted);
  758. LUA_FUNCTION_DEF (archive, get_filename);
  759. LUA_FUNCTION_DEF (archive, get_size);
  760. static const struct luaL_reg archivelib_m[] = {
  761. LUA_INTERFACE_DEF (archive, get_type),
  762. LUA_INTERFACE_DEF (archive, get_files),
  763. LUA_INTERFACE_DEF (archive, get_files_full),
  764. LUA_INTERFACE_DEF (archive, is_encrypted),
  765. LUA_INTERFACE_DEF (archive, get_filename),
  766. LUA_INTERFACE_DEF (archive, get_size),
  767. {"__tostring", rspamd_lua_class_tostring},
  768. {NULL, NULL}
  769. };
  770. /* Blob methods */
  771. LUA_FUNCTION_DEF (text, len);
  772. LUA_FUNCTION_DEF (text, str);
  773. LUA_FUNCTION_DEF (text, ptr);
  774. LUA_FUNCTION_DEF (text, gc);
  775. static const struct luaL_reg textlib_m[] = {
  776. LUA_INTERFACE_DEF (text, len),
  777. LUA_INTERFACE_DEF (text, str),
  778. LUA_INTERFACE_DEF (text, ptr),
  779. {"__len", lua_text_len},
  780. {"__tostring", lua_text_str},
  781. {"__gc", lua_text_gc},
  782. {NULL, NULL}
  783. };
  784. /* Utility functions */
  785. struct rspamd_task *
  786. lua_check_task (lua_State * L, gint pos)
  787. {
  788. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{task}");
  789. luaL_argcheck (L, ud != NULL, pos, "'task' expected");
  790. return ud ? *((struct rspamd_task **)ud) : NULL;
  791. }
  792. struct rspamd_task *
  793. lua_check_task_maybe (lua_State * L, gint pos)
  794. {
  795. void *ud = rspamd_lua_check_udata_maybe (L, pos, "rspamd{task}");
  796. return ud ? *((struct rspamd_task **)ud) : NULL;
  797. }
  798. static struct rspamd_image *
  799. lua_check_image (lua_State * L)
  800. {
  801. void *ud = rspamd_lua_check_udata (L, 1, "rspamd{image}");
  802. luaL_argcheck (L, ud != NULL, 1, "'image' expected");
  803. return ud ? *((struct rspamd_image **)ud) : NULL;
  804. }
  805. static struct rspamd_archive *
  806. lua_check_archive (lua_State * L)
  807. {
  808. void *ud = rspamd_lua_check_udata (L, 1, "rspamd{archive}");
  809. luaL_argcheck (L, ud != NULL, 1, "'archive' expected");
  810. return ud ? *((struct rspamd_archive **)ud) : NULL;
  811. }
  812. struct rspamd_lua_text *
  813. lua_check_text (lua_State * L, gint pos)
  814. {
  815. void *ud = rspamd_lua_check_udata (L, pos, "rspamd{text}");
  816. luaL_argcheck (L, ud != NULL, pos, "'text' expected");
  817. return ud ? (struct rspamd_lua_text *)ud : NULL;
  818. }
  819. /* Task methods */
  820. static int
  821. lua_task_process_message (lua_State *L)
  822. {
  823. struct rspamd_task *task = lua_check_task (L, 1);
  824. if (task != NULL) {
  825. if (task->msg.len > 0) {
  826. if (rspamd_message_parse (task) == 0) {
  827. lua_pushboolean (L, TRUE);
  828. }
  829. else {
  830. lua_pushboolean (L, FALSE);
  831. }
  832. }
  833. else {
  834. lua_pushnil (L);
  835. }
  836. }
  837. else {
  838. return luaL_error (L, "invalid arguments");
  839. }
  840. return 1;
  841. }
  842. static int
  843. lua_task_get_cfg (lua_State *L)
  844. {
  845. struct rspamd_task *task = lua_check_task (L, 1);
  846. struct rspamd_config **pcfg;
  847. if (task) {
  848. pcfg = lua_newuserdata (L, sizeof (gpointer));
  849. rspamd_lua_setclass (L, "rspamd{config}", -1);
  850. *pcfg = task->cfg;
  851. }
  852. else {
  853. return luaL_error (L, "invalid arguments");
  854. }
  855. return 1;
  856. }
  857. static int
  858. lua_task_set_cfg (lua_State *L)
  859. {
  860. struct rspamd_task *task = lua_check_task (L, 1);
  861. void *ud = rspamd_lua_check_udata (L, 2, "rspamd{config}");
  862. if (task) {
  863. luaL_argcheck (L, ud != NULL, 1, "'config' expected");
  864. task->cfg = ud ? *((struct rspamd_config **)ud) : NULL;
  865. }
  866. else {
  867. return luaL_error (L, "invalid arguments");
  868. }
  869. return 0;
  870. }
  871. static int
  872. lua_task_destroy (lua_State *L)
  873. {
  874. struct rspamd_task *task = lua_check_task (L, 1);
  875. if (task != NULL) {
  876. rspamd_task_free (task);
  877. }
  878. return 0;
  879. }
  880. static int
  881. lua_task_get_message (lua_State * L)
  882. {
  883. GMimeMessage **pmsg;
  884. struct rspamd_task *task = lua_check_task (L, 1);
  885. if (task != NULL) {
  886. if (task->message != NULL) {
  887. pmsg = lua_newuserdata (L, sizeof (GMimeMessage *));
  888. rspamd_lua_setclass (L, "rspamd{message}", -1);
  889. *pmsg = task->message;
  890. }
  891. else {
  892. lua_pushnil (L);
  893. }
  894. }
  895. else {
  896. return luaL_error (L, "invalid arguments");
  897. }
  898. return 1;
  899. }
  900. static int
  901. lua_task_get_mempool (lua_State * L)
  902. {
  903. rspamd_mempool_t **ppool;
  904. struct rspamd_task *task = lua_check_task (L, 1);
  905. if (task != NULL) {
  906. ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *));
  907. rspamd_lua_setclass (L, "rspamd{mempool}", -1);
  908. *ppool = task->task_pool;
  909. }
  910. else {
  911. return luaL_error (L, "invalid arguments");
  912. }
  913. return 1;
  914. }
  915. static int
  916. lua_task_get_session (lua_State * L)
  917. {
  918. struct rspamd_async_session **psession;
  919. struct rspamd_task *task = lua_check_task (L, 1);
  920. if (task != NULL) {
  921. psession = lua_newuserdata (L, sizeof (void *));
  922. rspamd_lua_setclass (L, "rspamd{session}", -1);
  923. *psession = task->s;
  924. }
  925. else {
  926. return luaL_error (L, "invalid arguments");
  927. }
  928. return 1;
  929. }
  930. static int
  931. lua_task_get_ev_base (lua_State * L)
  932. {
  933. struct event_base **pbase;
  934. struct rspamd_task *task = lua_check_task (L, 1);
  935. if (task != NULL) {
  936. pbase = lua_newuserdata (L, sizeof (struct event_base *));
  937. rspamd_lua_setclass (L, "rspamd{ev_base}", -1);
  938. *pbase = task->ev_base;
  939. }
  940. else {
  941. return luaL_error (L, "invalid arguments");
  942. }
  943. return 1;
  944. }
  945. static gint
  946. lua_task_insert_result (lua_State * L)
  947. {
  948. struct rspamd_task *task = lua_check_task (L, 1);
  949. const gchar *symbol_name, *param;
  950. double flag;
  951. GList *params = NULL;
  952. gint i, top;
  953. if (task != NULL) {
  954. symbol_name =
  955. rspamd_mempool_strdup (task->task_pool, luaL_checkstring (L, 2));
  956. flag = luaL_checknumber (L, 3);
  957. top = lua_gettop (L);
  958. /* Get additional options */
  959. for (i = 4; i <= top; i++) {
  960. if (lua_type (L, i) == LUA_TSTRING) {
  961. param = luaL_checkstring (L, i);
  962. params =
  963. g_list_prepend (params,
  964. rspamd_mempool_strdup (task->task_pool, param));
  965. }
  966. else if (lua_type (L, i) == LUA_TTABLE) {
  967. lua_pushvalue (L, i);
  968. lua_pushnil (L);
  969. while (lua_next (L, -2)) {
  970. param = lua_tostring (L, -1);
  971. params = g_list_prepend (params,
  972. rspamd_mempool_strdup (task->task_pool,
  973. param));
  974. lua_pop (L, 1);
  975. }
  976. lua_pop (L, 1);
  977. }
  978. }
  979. if (params) {
  980. params = g_list_reverse (params);
  981. }
  982. rspamd_task_insert_result (task, symbol_name, flag, params);
  983. }
  984. else {
  985. return luaL_error (L, "invalid arguments");
  986. }
  987. return 0;
  988. }
  989. static gint
  990. lua_task_set_pre_result (lua_State * L)
  991. {
  992. struct rspamd_task *task = lua_check_task (L, 1);
  993. struct metric_result *mres;
  994. gchar *action_str;
  995. gint action = METRIC_ACTION_MAX;
  996. if (task != NULL) {
  997. if (lua_type (L, 2) == LUA_TNUMBER) {
  998. action = lua_tointeger (L, 2);
  999. }
  1000. else if (lua_type (L, 2) == LUA_TSTRING) {
  1001. rspamd_action_from_str (lua_tostring (L, 2), &action);
  1002. }
  1003. if (action < METRIC_ACTION_MAX && action >= METRIC_ACTION_REJECT) {
  1004. /* We also need to set the default metric to that result */
  1005. mres = rspamd_create_metric_result (task, DEFAULT_METRIC);
  1006. if (mres != NULL) {
  1007. mres->score = mres->metric->actions[action].score;
  1008. mres->action = action;
  1009. }
  1010. task->pre_result.action = action;
  1011. if (lua_gettop (L) >= 3) {
  1012. action_str = rspamd_mempool_strdup (task->task_pool,
  1013. luaL_checkstring (L, 3));
  1014. task->pre_result.str = action_str;
  1015. task->messages = g_list_prepend (task->messages, action_str);
  1016. }
  1017. else {
  1018. task->pre_result.str = "unknown";
  1019. }
  1020. msg_info_task ("<%s>: set pre-result to %s: '%s'",
  1021. task->message_id, rspamd_action_to_str (action),
  1022. task->pre_result.str);
  1023. /* Don't classify or filter message if pre-filter sets results */
  1024. task->processed_stages |= (RSPAMD_TASK_STAGE_FILTERS |
  1025. RSPAMD_TASK_STAGE_CLASSIFIERS |
  1026. RSPAMD_TASK_STAGE_CLASSIFIERS_PRE |
  1027. RSPAMD_TASK_STAGE_CLASSIFIERS_POST);
  1028. }
  1029. else {
  1030. return luaL_error (L, "invalid arguments");
  1031. }
  1032. }
  1033. else {
  1034. return luaL_error (L, "invalid arguments");
  1035. }
  1036. return 0;
  1037. }
  1038. static gint
  1039. lua_task_append_message (lua_State * L)
  1040. {
  1041. struct rspamd_task *task = lua_check_task (L, 1);
  1042. gchar *message;
  1043. if (task != NULL) {
  1044. message= rspamd_mempool_strdup (task->task_pool,
  1045. luaL_checkstring (L, 2));
  1046. task->messages = g_list_prepend (task->messages, message);
  1047. }
  1048. else {
  1049. return luaL_error (L, "invalid arguments");
  1050. }
  1051. return 0;
  1052. }
  1053. struct lua_tree_cb_data {
  1054. lua_State *L;
  1055. int i;
  1056. };
  1057. static void
  1058. lua_tree_url_callback (gpointer key, gpointer value, gpointer ud)
  1059. {
  1060. struct rspamd_lua_url *url;
  1061. struct lua_tree_cb_data *cb = ud;
  1062. url = lua_newuserdata (cb->L, sizeof (struct rspamd_lua_url));
  1063. rspamd_lua_setclass (cb->L, "rspamd{url}", -1);
  1064. url->url = value;
  1065. lua_rawseti (cb->L, -2, cb->i++);
  1066. }
  1067. static gint
  1068. lua_task_get_urls (lua_State * L)
  1069. {
  1070. struct rspamd_task *task = lua_check_task (L, 1);
  1071. struct lua_tree_cb_data cb;
  1072. gboolean need_emails = FALSE;
  1073. gsize sz;
  1074. if (task) {
  1075. if (lua_gettop (L) >= 2) {
  1076. need_emails = lua_toboolean (L, 2);
  1077. }
  1078. sz = g_hash_table_size (task->urls);
  1079. if (need_emails) {
  1080. sz += g_hash_table_size (task->emails);
  1081. }
  1082. lua_createtable (L, sz, 0);
  1083. cb.i = 1;
  1084. cb.L = L;
  1085. g_hash_table_foreach (task->urls, lua_tree_url_callback, &cb);
  1086. if (need_emails) {
  1087. g_hash_table_foreach (task->emails, lua_tree_url_callback, &cb);
  1088. }
  1089. }
  1090. else {
  1091. return luaL_error (L, "invalid arguments");
  1092. }
  1093. return 1;
  1094. }
  1095. static gint
  1096. lua_task_has_urls (lua_State * L)
  1097. {
  1098. struct rspamd_task *task = lua_check_task (L, 1);
  1099. gboolean need_emails = FALSE, ret = FALSE;
  1100. if (task) {
  1101. if (lua_gettop (L) >= 2) {
  1102. need_emails = lua_toboolean (L, 2);
  1103. }
  1104. if (g_hash_table_size (task->urls) > 0) {
  1105. ret = TRUE;
  1106. }
  1107. if (need_emails && g_hash_table_size (task->emails) > 0) {
  1108. ret = TRUE;
  1109. }
  1110. }
  1111. else {
  1112. return luaL_error (L, "invalid arguments");
  1113. }
  1114. lua_pushboolean (L, ret);
  1115. return 1;
  1116. }
  1117. static gint
  1118. lua_task_get_content (lua_State * L)
  1119. {
  1120. struct rspamd_task *task = lua_check_task (L, 1);
  1121. struct rspamd_lua_text *t;
  1122. if (task) {
  1123. t = lua_newuserdata (L, sizeof (*t));
  1124. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1125. t->len = task->msg.len;
  1126. t->start = task->msg.begin;
  1127. t->flags = 0;
  1128. }
  1129. else {
  1130. return luaL_error (L, "invalid arguments");
  1131. }
  1132. return 1;
  1133. }
  1134. static gint
  1135. lua_task_get_rawbody (lua_State * L)
  1136. {
  1137. struct rspamd_task *task = lua_check_task (L, 1);
  1138. struct rspamd_lua_text *t;
  1139. if (task) {
  1140. t = lua_newuserdata (L, sizeof (*t));
  1141. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1142. if (task->raw_headers_content.len > 0) {
  1143. g_assert (task->raw_headers_content.len <= task->msg.len);
  1144. t->start = task->msg.begin + task->raw_headers_content.len;
  1145. t->len = task->msg.len - task->raw_headers_content.len;
  1146. }
  1147. else {
  1148. t->len = task->msg.len;
  1149. t->start = task->msg.begin;
  1150. }
  1151. t->flags = 0;
  1152. }
  1153. else {
  1154. return luaL_error (L, "invalid arguments");
  1155. }
  1156. return 1;
  1157. }
  1158. static gint
  1159. lua_task_get_emails (lua_State * L)
  1160. {
  1161. struct rspamd_task *task = lua_check_task (L, 1);
  1162. struct lua_tree_cb_data cb;
  1163. if (task) {
  1164. lua_createtable (L, g_hash_table_size (task->emails), 0);
  1165. cb.i = 1;
  1166. cb.L = L;
  1167. g_hash_table_foreach (task->emails, lua_tree_url_callback, &cb);
  1168. }
  1169. else {
  1170. return luaL_error (L, "invalid arguments");
  1171. }
  1172. return 1;
  1173. }
  1174. static gint
  1175. lua_task_get_text_parts (lua_State * L)
  1176. {
  1177. guint i;
  1178. struct rspamd_task *task = lua_check_task (L, 1);
  1179. struct rspamd_mime_text_part *part, **ppart;
  1180. if (task != NULL) {
  1181. lua_createtable (L, task->text_parts->len, 0);
  1182. for (i = 0; i < task->text_parts->len; i ++) {
  1183. part = g_ptr_array_index (task->text_parts, i);
  1184. ppart = lua_newuserdata (L, sizeof (struct rspamd_mime_text_part *));
  1185. *ppart = part;
  1186. rspamd_lua_setclass (L, "rspamd{textpart}", -1);
  1187. /* Make it array */
  1188. lua_rawseti (L, -2, i + 1);
  1189. }
  1190. }
  1191. else {
  1192. return luaL_error (L, "invalid arguments");
  1193. }
  1194. return 1;
  1195. }
  1196. static gint
  1197. lua_task_get_parts (lua_State * L)
  1198. {
  1199. guint i;
  1200. struct rspamd_task *task = lua_check_task (L, 1);
  1201. struct rspamd_mime_part *part, **ppart;
  1202. if (task != NULL) {
  1203. lua_createtable (L, task->parts->len, 0);
  1204. for (i = 0; i < task->parts->len; i ++) {
  1205. part = g_ptr_array_index (task->parts, i);
  1206. ppart = lua_newuserdata (L, sizeof (struct rspamd_mime_part *));
  1207. *ppart = part;
  1208. rspamd_lua_setclass (L, "rspamd{mimepart}", -1);
  1209. /* Make it array */
  1210. lua_rawseti (L, -2, i + 1);
  1211. }
  1212. }
  1213. else {
  1214. return luaL_error (L, "invalid arguments");
  1215. }
  1216. return 1;
  1217. }
  1218. static gint
  1219. lua_task_get_request_header (lua_State *L)
  1220. {
  1221. rspamd_ftok_t *hdr;
  1222. struct rspamd_task *task = lua_check_task (L, 1);
  1223. const gchar *s;
  1224. struct rspamd_lua_text *t;
  1225. s = luaL_checkstring (L, 2);
  1226. if (s && task) {
  1227. hdr = rspamd_task_get_request_header (task, s);
  1228. if (hdr) {
  1229. t = lua_newuserdata (L, sizeof (*t));
  1230. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1231. t->start = hdr->begin;
  1232. t->len = hdr->len;
  1233. t->flags = 0;
  1234. return 1;
  1235. }
  1236. else {
  1237. lua_pushnil (L);
  1238. }
  1239. }
  1240. else {
  1241. return luaL_error (L, "invalid arguments");
  1242. }
  1243. return 1;
  1244. }
  1245. static gint
  1246. lua_task_set_request_header (lua_State *L)
  1247. {
  1248. struct rspamd_task *task = lua_check_task (L, 1);
  1249. const gchar *s, *v = NULL;
  1250. rspamd_fstring_t *buf;
  1251. struct rspamd_lua_text *t;
  1252. rspamd_ftok_t *hdr, *new_name;
  1253. gsize len, vlen;
  1254. s = luaL_checklstring (L, 2, &len);
  1255. if (s && task) {
  1256. if (lua_type (L, 3) == LUA_TSTRING) {
  1257. v = luaL_checklstring (L, 2, &vlen);
  1258. }
  1259. else if (lua_type (L, 3) == LUA_TUSERDATA) {
  1260. t = lua_check_text (L, 3);
  1261. if (t != NULL) {
  1262. v = t->start;
  1263. vlen = t->len;
  1264. }
  1265. }
  1266. if (v != NULL) {
  1267. buf = rspamd_fstring_new_init (v, vlen);
  1268. hdr = rspamd_ftok_map (buf);
  1269. buf = rspamd_fstring_new_init (s, len);
  1270. new_name = rspamd_ftok_map (buf);
  1271. rspamd_task_add_request_header (task, new_name, hdr);
  1272. }
  1273. }
  1274. else {
  1275. return luaL_error (L, "invalid arguments");
  1276. }
  1277. return 0;
  1278. }
  1279. gint
  1280. rspamd_lua_push_header (lua_State * L,
  1281. GPtrArray *ar,
  1282. const gchar *name,
  1283. gboolean strong,
  1284. gboolean full,
  1285. gboolean raw)
  1286. {
  1287. struct raw_header *rh;
  1288. guint i;
  1289. const gchar *val;
  1290. if (ar == NULL || ar->len == 0) {
  1291. lua_pushnil (L);
  1292. return 1;
  1293. }
  1294. if (full) {
  1295. lua_createtable (L, ar->len, 0);
  1296. }
  1297. PTR_ARRAY_FOREACH (ar, i, rh) {
  1298. if (full) {
  1299. /* Create new associated table for a header */
  1300. lua_createtable (L, 0, 6);
  1301. rspamd_lua_table_set (L, "name", rh->name);
  1302. if (rh->value) {
  1303. rspamd_lua_table_set (L, "value", rh->value);
  1304. }
  1305. if (rh->decoded) {
  1306. rspamd_lua_table_set (L, "decoded", rh->value);
  1307. }
  1308. lua_pushstring (L, "tab_separated");
  1309. lua_pushboolean (L, rh->tab_separated);
  1310. lua_settable (L, -3);
  1311. lua_pushstring (L, "empty_separator");
  1312. lua_pushboolean (L, rh->empty_separator);
  1313. lua_settable (L, -3);
  1314. rspamd_lua_table_set (L, "separator", rh->separator);
  1315. lua_rawseti (L, -2, i + 1);
  1316. }
  1317. else {
  1318. if (!raw) {
  1319. val = rh->decoded;
  1320. }
  1321. else {
  1322. val = rh->value;
  1323. }
  1324. if (val) {
  1325. lua_pushstring (L, val);
  1326. }
  1327. else {
  1328. lua_pushnil (L);
  1329. }
  1330. return 1;
  1331. }
  1332. }
  1333. return 1;
  1334. }
  1335. static gint
  1336. lua_task_get_header_common (lua_State *L, gboolean full, gboolean raw)
  1337. {
  1338. gboolean strong = FALSE;
  1339. struct rspamd_task *task = lua_check_task (L, 1);
  1340. const gchar *name;
  1341. GPtrArray *ar;
  1342. name = luaL_checkstring (L, 2);
  1343. if (name && task) {
  1344. if (lua_gettop (L) == 3) {
  1345. strong = lua_toboolean (L, 3);
  1346. }
  1347. ar = rspamd_message_get_header_array (task, name, strong);
  1348. return rspamd_lua_push_header (L, ar, name,
  1349. strong, full, raw);
  1350. }
  1351. else {
  1352. return luaL_error (L, "invalid arguments");
  1353. }
  1354. }
  1355. static gint
  1356. lua_task_get_header_full (lua_State * L)
  1357. {
  1358. return lua_task_get_header_common (L, TRUE, TRUE);
  1359. }
  1360. static gint
  1361. lua_task_get_header (lua_State * L)
  1362. {
  1363. return lua_task_get_header_common (L, FALSE, FALSE);
  1364. }
  1365. static gint
  1366. lua_task_get_header_raw (lua_State * L)
  1367. {
  1368. return lua_task_get_header_common (L, FALSE, TRUE);
  1369. }
  1370. static gint
  1371. lua_task_get_raw_headers (lua_State *L)
  1372. {
  1373. struct rspamd_task *task = lua_check_task (L, 1);
  1374. struct rspamd_lua_text *t;
  1375. if (task) {
  1376. t = lua_newuserdata (L, sizeof (*t));
  1377. rspamd_lua_setclass (L, "rspamd{text}", -1);
  1378. t->start = task->raw_headers_content.begin;
  1379. t->len = task->raw_headers_content.len;
  1380. t->flags = 0;
  1381. }
  1382. else {
  1383. return luaL_error (L, "invalid arguments");
  1384. }
  1385. return 1;
  1386. }
  1387. static gint
  1388. lua_task_get_received_headers (lua_State * L)
  1389. {
  1390. struct rspamd_task *task = lua_check_task (L, 1);
  1391. struct received_header *rh;
  1392. const gchar *proto;
  1393. guint i, k = 1;
  1394. if (task) {
  1395. lua_createtable (L, task->received->len, 0);
  1396. for (i = 0; i < task->received->len; i ++) {
  1397. rh = g_ptr_array_index (task->received, i);
  1398. if (G_UNLIKELY (rh->from_ip == NULL &&
  1399. rh->real_ip == NULL &&
  1400. rh->real_hostname == NULL &&
  1401. rh->by_hostname == NULL && rh->timestamp == 0 &&
  1402. rh->for_mbox == NULL)) {
  1403. continue;
  1404. }
  1405. lua_createtable (L, 0, 8);
  1406. rspamd_lua_table_set (L, "from_hostname", rh->from_hostname);
  1407. rspamd_lua_table_set (L, "from_ip", rh->from_ip);
  1408. rspamd_lua_table_set (L, "real_hostname", rh->real_hostname);
  1409. lua_pushstring (L, "real_ip");
  1410. rspamd_lua_ip_push (L, rh->addr);
  1411. lua_settable (L, -3);
  1412. lua_pushstring (L, "proto");
  1413. switch (rh->type) {
  1414. case RSPAMD_RECEIVED_SMTP:
  1415. proto = "smtp";
  1416. break;
  1417. case RSPAMD_RECEIVED_ESMTP:
  1418. proto = "esmtp";
  1419. break;
  1420. case RSPAMD_RECEIVED_ESMTPS:
  1421. proto = "esmtps";
  1422. break;
  1423. case RSPAMD_RECEIVED_ESMTPA:
  1424. proto = "esmtpa";
  1425. break;
  1426. case RSPAMD_RECEIVED_ESMTPSA:
  1427. proto = "esmtpsa";
  1428. break;
  1429. case RSPAMD_RECEIVED_LMTP:
  1430. proto = "lmtp";
  1431. break;
  1432. case RSPAMD_RECEIVED_IMAP:
  1433. proto = "imap";
  1434. break;
  1435. case RSPAMD_RECEIVED_UNKNOWN:
  1436. default:
  1437. proto = "unknown";
  1438. break;
  1439. }
  1440. lua_pushstring (L, proto);
  1441. lua_settable (L, -3);
  1442. lua_pushstring (L, "timestamp");
  1443. lua_pushnumber (L, rh->timestamp);
  1444. lua_settable (L, -3);
  1445. rspamd_lua_table_set (L, "by_hostname", rh->by_hostname);
  1446. rspamd_lua_table_set (L, "for", rh->for_mbox);
  1447. lua_rawseti (L, -2, k ++);
  1448. }
  1449. }
  1450. else {
  1451. return luaL_error (L, "invalid arguments");
  1452. }
  1453. return 1;
  1454. }
  1455. static gint
  1456. lua_task_get_queue_id (lua_State *L)
  1457. {
  1458. struct rspamd_task *task = lua_check_task (L, 1);
  1459. if (task) {
  1460. if (task->queue_id != NULL && strcmp (task->queue_id, "undef") != 0) {
  1461. lua_pushstring (L, task->queue_id);
  1462. }
  1463. else {
  1464. lua_pushnil (L);
  1465. }
  1466. }
  1467. else {
  1468. return luaL_error (L, "invalid arguments");
  1469. }
  1470. return 1;
  1471. }
  1472. static gint
  1473. lua_task_get_uid (lua_State *L)
  1474. {
  1475. struct rspamd_task *task = lua_check_task (L, 1);
  1476. if (task) {
  1477. lua_pushstring (L, task->task_pool->tag.uid);
  1478. }
  1479. else {
  1480. return luaL_error (L, "invalid arguments");
  1481. }
  1482. return 1;
  1483. }
  1484. static gint
  1485. lua_task_get_resolver (lua_State *L)
  1486. {
  1487. struct rspamd_task *task = lua_check_task (L, 1);
  1488. struct rspamd_dns_resolver **presolver;
  1489. if (task != NULL && task->resolver != NULL) {
  1490. presolver = lua_newuserdata (L, sizeof (void *));
  1491. rspamd_lua_setclass (L, "rspamd{resolver}", -1);
  1492. *presolver = task->resolver;
  1493. }
  1494. else {
  1495. return luaL_error (L, "invalid arguments");
  1496. }
  1497. return 1;
  1498. }
  1499. static gint
  1500. lua_task_inc_dns_req (lua_State *L)
  1501. {
  1502. struct rspamd_task *task = lua_check_task (L, 1);
  1503. if (task != NULL) {
  1504. task->dns_requests++;
  1505. }
  1506. else {
  1507. return luaL_error (L, "invalid arguments");
  1508. }
  1509. return 0;
  1510. }
  1511. static gint
  1512. lua_task_get_dns_req (lua_State *L)
  1513. {
  1514. struct rspamd_task *task = lua_check_task (L, 1);
  1515. if (task != NULL) {
  1516. lua_pushnumber (L, task->dns_requests);
  1517. }
  1518. else {
  1519. return luaL_error (L, "invalid arguments");
  1520. }
  1521. return 1;
  1522. }
  1523. enum rspamd_address_type {
  1524. RSPAMD_ADDRESS_ANY = 0,
  1525. RSPAMD_ADDRESS_SMTP = 1,
  1526. RSPAMD_ADDRESS_MIME = 2,
  1527. RSPAMD_ADDRESS_RAW_ANY = 3,
  1528. RSPAMD_ADDRESS_RAW_SMTP = 4,
  1529. RSPAMD_ADDRESS_RAW_MIME = 5,
  1530. RSPAMD_ADDRESS_MAX
  1531. };
  1532. /*
  1533. * Convert element at the specified position to the type
  1534. * for get_from/get_recipients
  1535. */
  1536. static enum rspamd_address_type
  1537. lua_task_str_to_get_type (lua_State *L, gint pos)
  1538. {
  1539. const gchar *type = NULL;
  1540. gint ret = RSPAMD_ADDRESS_ANY;
  1541. guint64 h;
  1542. gsize sz;
  1543. /* Get what value */
  1544. if (lua_type (L, pos) == LUA_TNUMBER) {
  1545. ret = lua_tonumber (L, pos);
  1546. if (ret >= RSPAMD_ADDRESS_ANY && ret < RSPAMD_ADDRESS_MAX) {
  1547. return ret;
  1548. }
  1549. return RSPAMD_ADDRESS_ANY;
  1550. }
  1551. else if (lua_type (L, pos) == LUA_TSTRING) {
  1552. type = lua_tolstring (L, pos, &sz);
  1553. if (type && sz > 0) {
  1554. h = rspamd_cryptobox_fast_hash_specific (RSPAMD_CRYPTOBOX_XXHASH64,
  1555. type, sz, 0xdeadbabe);
  1556. switch (h) {
  1557. case 0xDA081341FB600389ULL: /* mime */
  1558. ret = RSPAMD_ADDRESS_MIME;
  1559. break;
  1560. case 0xEEC8A7832F8C43ACULL: /* any */
  1561. ret = RSPAMD_ADDRESS_ANY;
  1562. break;
  1563. case 0x472274D5193B2A80ULL: /* smtp */
  1564. case 0xEFE0F586CC9F14A9ULL: /* envelope */
  1565. ret = RSPAMD_ADDRESS_SMTP;
  1566. break;
  1567. case 0x9DA887501690DE20ULL: /* raw_mime */
  1568. ret = RSPAMD_ADDRESS_RAW_MIME;
  1569. break;
  1570. case 0x6B54FE02DEB595A4ULL: /* raw_smtp */
  1571. case 0xE0E596C861777B02ULL: /* raw_envelope */
  1572. ret = RSPAMD_ADDRESS_RAW_SMTP;
  1573. break;
  1574. case 0x2C49DBE3A10A0197ULL: /* raw_any */
  1575. ret = RSPAMD_ADDRESS_RAW_ANY;
  1576. break;
  1577. }
  1578. }
  1579. }
  1580. return ret;
  1581. }
  1582. static void
  1583. lua_push_email_address (lua_State *L, struct rspamd_email_address *addr)
  1584. {
  1585. if (addr) {
  1586. lua_createtable (L, 0, 3);
  1587. if (addr->addr_len > 0) {
  1588. lua_pushstring (L, "addr");
  1589. lua_pushlstring (L, addr->addr, addr->addr_len);
  1590. lua_settable (L, -3);
  1591. }
  1592. else {
  1593. lua_pushstring (L, "addr");
  1594. lua_pushstring (L, "");
  1595. lua_settable (L, -3);
  1596. }
  1597. if (addr->domain_len > 0) {
  1598. lua_pushstring (L, "domain");
  1599. lua_pushlstring (L, addr->domain, addr->domain_len);
  1600. lua_settable (L, -3);
  1601. }
  1602. else {
  1603. lua_pushstring (L, "domain");
  1604. lua_pushstring (L, "");
  1605. lua_settable (L, -3);
  1606. }
  1607. if (addr->user_len > 0) {
  1608. lua_pushstring (L, "user");
  1609. lua_pushlstring (L, addr->user, addr->user_len);
  1610. lua_settable (L, -3);
  1611. }
  1612. else {
  1613. lua_pushstring (L, "user");
  1614. lua_pushstring (L, "");
  1615. lua_settable (L, -3);
  1616. }
  1617. }
  1618. }
  1619. static void
  1620. lua_push_emails_address_list (lua_State *L, GPtrArray *addrs)
  1621. {
  1622. struct rspamd_email_address *addr;
  1623. guint i;
  1624. lua_createtable (L, addrs->len, 0);
  1625. for (i = 0; i < addrs->len; i ++) {
  1626. addr = g_ptr_array_index (addrs, i);
  1627. lua_push_email_address (L, addr);
  1628. lua_rawseti (L, -2, i + 1);
  1629. }
  1630. }
  1631. static gint
  1632. lua_task_get_recipients (lua_State *L)
  1633. {
  1634. struct rspamd_task *task = lua_check_task (L, 1);
  1635. InternetAddressList *addrs = NULL;
  1636. GPtrArray *ptrs = NULL;
  1637. gint what = 0;
  1638. if (task) {
  1639. if (lua_gettop (L) == 2) {
  1640. /* Get what value */
  1641. what = lua_task_str_to_get_type (L, 2);
  1642. }
  1643. switch (what) {
  1644. case RSPAMD_ADDRESS_SMTP:
  1645. /* Here we check merely envelope rcpt */
  1646. ptrs = task->rcpt_envelope;
  1647. break;
  1648. case RSPAMD_ADDRESS_MIME:
  1649. /* Here we check merely mime rcpt */
  1650. addrs = task->rcpt_mime;
  1651. break;
  1652. case RSPAMD_ADDRESS_ANY:
  1653. default:
  1654. if (task->rcpt_envelope) {
  1655. ptrs = task->rcpt_envelope;
  1656. }
  1657. else {
  1658. addrs = task->rcpt_mime;
  1659. }
  1660. break;
  1661. }
  1662. if (addrs) {
  1663. lua_push_internet_address_list (L, addrs);
  1664. }
  1665. else if (ptrs) {
  1666. lua_push_emails_address_list (L, ptrs);
  1667. }
  1668. else {
  1669. lua_pushnil (L);
  1670. }
  1671. }
  1672. else {
  1673. return luaL_error (L, "invalid arguments");
  1674. }
  1675. return 1;
  1676. }
  1677. #define CHECK_ADDR(addr) do { \
  1678. if (addr == NULL) { \
  1679. ret = 0; \
  1680. } \
  1681. else { \
  1682. ret = internet_address_list_length (addr) > 0 ? 1 : 0; \
  1683. } \
  1684. } while (0)
  1685. #define CHECK_EMAIL_ADDR(addr) do { \
  1686. if (addr == NULL) { \
  1687. ret = 0; \
  1688. } \
  1689. else { \
  1690. ret = addr->flags & RSPAMD_EMAIL_ADDR_VALID; \
  1691. } \
  1692. } while (0)
  1693. #define CHECK_EMAIL_ADDR_LIST(addr) do { \
  1694. if (addr == NULL) { \
  1695. ret = 0; \
  1696. } \
  1697. else { \
  1698. ret = addr->len > 0; \
  1699. } \
  1700. } while (0)
  1701. static gint
  1702. lua_task_has_from (lua_State *L)
  1703. {
  1704. struct rspamd_task *task = lua_check_task (L, 1);
  1705. gint what = 0;
  1706. gboolean ret = FALSE;
  1707. if (task) {
  1708. if (lua_gettop (L) == 2) {
  1709. /* Get what value */
  1710. what = lua_task_str_to_get_type (L, 2);
  1711. }
  1712. switch (what) {
  1713. case RSPAMD_ADDRESS_SMTP:
  1714. /* Here we check merely envelope rcpt */
  1715. CHECK_EMAIL_ADDR (task->from_envelope);
  1716. break;
  1717. case RSPAMD_ADDRESS_MIME:
  1718. /* Here we check merely mime rcpt */
  1719. CHECK_ADDR (task->from_mime);
  1720. break;
  1721. case RSPAMD_ADDRESS_ANY:
  1722. default:
  1723. CHECK_EMAIL_ADDR (task->from_envelope);
  1724. if (!ret) {
  1725. CHECK_ADDR (task->from_mime);
  1726. }
  1727. break;
  1728. }
  1729. }
  1730. else {
  1731. return luaL_error (L, "invalid arguments");
  1732. }
  1733. lua_pushboolean (L, ret);
  1734. return 1;
  1735. }
  1736. static gint
  1737. lua_task_has_recipients (lua_State *L)
  1738. {
  1739. struct rspamd_task *task = lua_check_task (L, 1);
  1740. gint what = 0;
  1741. gboolean ret = FALSE;
  1742. if (task) {
  1743. if (lua_gettop (L) == 2) {
  1744. /* Get what value */
  1745. what = lua_task_str_to_get_type (L, 2);
  1746. }
  1747. switch (what) {
  1748. case RSPAMD_ADDRESS_SMTP:
  1749. /* Here we check merely envelope rcpt */
  1750. CHECK_EMAIL_ADDR_LIST (task->rcpt_envelope);
  1751. break;
  1752. case RSPAMD_ADDRESS_MIME:
  1753. /* Here we check merely mime rcpt */
  1754. CHECK_ADDR (task->rcpt_mime);
  1755. break;
  1756. case RSPAMD_ADDRESS_ANY:
  1757. default:
  1758. CHECK_EMAIL_ADDR_LIST (task->rcpt_envelope);
  1759. if (!ret) {
  1760. CHECK_ADDR (task->rcpt_mime);
  1761. }
  1762. break;
  1763. }
  1764. }
  1765. else {
  1766. return luaL_error (L, "invalid arguments");
  1767. }
  1768. lua_pushboolean (L, ret);
  1769. return 1;
  1770. }
  1771. static gint
  1772. lua_task_get_from (lua_State *L)
  1773. {
  1774. struct rspamd_task *task = lua_check_task (L, 1);
  1775. InternetAddressList *addrs = NULL;
  1776. struct rspamd_email_address *addr = NULL;
  1777. gint what = 0;
  1778. if (task) {
  1779. if (lua_gettop (L) == 2) {
  1780. /* Get what value */
  1781. what = lua_task_str_to_get_type (L, 2);
  1782. }
  1783. switch (what) {
  1784. case RSPAMD_ADDRESS_SMTP:
  1785. /* Here we check merely envelope rcpt */
  1786. addr = task->from_envelope;
  1787. break;
  1788. case RSPAMD_ADDRESS_MIME:
  1789. /* Here we check merely mime rcpt */
  1790. addrs = task->from_mime;
  1791. break;
  1792. case RSPAMD_ADDRESS_ANY:
  1793. default:
  1794. if (task->from_envelope) {
  1795. addr = task->from_envelope;
  1796. }
  1797. else {
  1798. addrs = task->from_mime;
  1799. }
  1800. break;
  1801. }
  1802. if (addrs) {
  1803. lua_push_internet_address_list (L, addrs);
  1804. }
  1805. else if (addr) {
  1806. /* Create table to preserve compatibility */
  1807. if (addr->addr) {
  1808. lua_createtable (L, 1, 0);
  1809. lua_push_email_address (L, addr);
  1810. lua_rawseti (L, -2, 1);
  1811. }
  1812. else {
  1813. lua_pushnil (L);
  1814. }
  1815. }
  1816. else {
  1817. lua_pushnil (L);
  1818. }
  1819. }
  1820. else {
  1821. return luaL_error (L, "invalid arguments");
  1822. }
  1823. return 1;
  1824. }
  1825. static gint
  1826. lua_task_get_user (lua_State *L)
  1827. {
  1828. struct rspamd_task *task = lua_check_task (L, 1);
  1829. if (task) {
  1830. if (task->user != NULL) {
  1831. lua_pushstring (L, task->user);
  1832. }
  1833. else {
  1834. lua_pushnil (L);
  1835. }
  1836. }
  1837. else {
  1838. return luaL_error (L, "invalid arguments");
  1839. }
  1840. return 1;
  1841. }
  1842. static gint
  1843. lua_task_set_user (lua_State *L)
  1844. {
  1845. struct rspamd_task *task = lua_check_task (L, 1);
  1846. const gchar *new_user;
  1847. if (task) {
  1848. new_user = luaL_checkstring (L, 2);
  1849. if (new_user) {
  1850. task->user = rspamd_mempool_strdup (task->task_pool, new_user);
  1851. }
  1852. }
  1853. else {
  1854. return luaL_error (L, "invalid arguments");
  1855. }
  1856. return 0;
  1857. }
  1858. static gint
  1859. lua_task_get_from_ip (lua_State *L)
  1860. {
  1861. struct rspamd_task *task = lua_check_task (L, 1);
  1862. if (task) {
  1863. rspamd_lua_ip_push (L, task->from_addr);
  1864. }
  1865. else {
  1866. return luaL_error (L, "invalid arguments");
  1867. }
  1868. return 1;
  1869. }
  1870. static gint
  1871. lua_task_set_from_ip (lua_State *L)
  1872. {
  1873. struct rspamd_task *task = lua_check_task (L, 1);
  1874. const gchar *ip_str = luaL_checkstring (L, 2);
  1875. rspamd_inet_addr_t *addr = NULL;
  1876. if (!task || !ip_str) {
  1877. lua_pushstring (L, "invalid parameters");
  1878. return lua_error (L);
  1879. }
  1880. else {
  1881. if (!rspamd_parse_inet_address (&addr,
  1882. ip_str,
  1883. 0)) {
  1884. msg_warn_task ("cannot get IP from received header: '%s'",
  1885. ip_str);
  1886. }
  1887. else {
  1888. if (task->from_addr) {
  1889. rspamd_inet_address_destroy (task->from_addr);
  1890. }
  1891. task->from_addr = addr;
  1892. }
  1893. }
  1894. return 0;
  1895. }
  1896. static gint
  1897. lua_task_get_from_ip_num (lua_State *L)
  1898. {
  1899. msg_err ("this function is deprecated and should no longer be used");
  1900. lua_pushnil (L);
  1901. return 1;
  1902. }
  1903. static gint
  1904. lua_task_get_client_ip (lua_State *L)
  1905. {
  1906. struct rspamd_task *task = lua_check_task (L, 1);
  1907. if (task) {
  1908. rspamd_lua_ip_push (L, task->client_addr);
  1909. }
  1910. else {
  1911. return luaL_error (L, "invalid arguments");
  1912. }
  1913. return 1;
  1914. }
  1915. static gint
  1916. lua_task_get_helo (lua_State *L)
  1917. {
  1918. struct rspamd_task *task = lua_check_task (L, 1);
  1919. if (task) {
  1920. if (task->helo != NULL) {
  1921. lua_pushstring (L, (gchar *)task->helo);
  1922. return 1;
  1923. }
  1924. else {
  1925. lua_pushnil (L);
  1926. }
  1927. }
  1928. else {
  1929. return luaL_error (L, "invalid arguments");
  1930. }
  1931. return 1;
  1932. }
  1933. static gint
  1934. lua_task_set_helo (lua_State *L)
  1935. {
  1936. struct rspamd_task *task = lua_check_task (L, 1);
  1937. const gchar *new_helo;
  1938. if (task) {
  1939. new_helo = luaL_checkstring (L, 2);
  1940. if (new_helo) {
  1941. task->helo = rspamd_mempool_strdup (task->task_pool, new_helo);
  1942. }
  1943. }
  1944. else {
  1945. return luaL_error (L, "invalid arguments");
  1946. }
  1947. return 0;
  1948. }
  1949. static gint
  1950. lua_task_get_hostname (lua_State *L)
  1951. {
  1952. struct rspamd_task *task = lua_check_task (L, 1);
  1953. if (task) {
  1954. if (task->hostname != NULL) {
  1955. /* Check whether it looks like an IP address */
  1956. if (*task->hostname == '[') {
  1957. /*
  1958. * From the milter documentation:
  1959. * If the reverse lookup fails or if none of the IP
  1960. * addresses of the resolved host name matches the
  1961. * original IP address, hostname will contain the
  1962. * message sender's IP address enclosed in square
  1963. * brackets (e.g. `[a.b.c.d]')
  1964. */
  1965. lua_pushstring (L, "unknown");
  1966. }
  1967. else {
  1968. lua_pushstring (L, task->hostname);
  1969. }
  1970. }
  1971. else {
  1972. lua_pushnil (L);
  1973. }
  1974. }
  1975. else {
  1976. return luaL_error (L, "invalid arguments");
  1977. }
  1978. return 1;
  1979. }
  1980. static gint
  1981. lua_task_set_hostname (lua_State *L)
  1982. {
  1983. struct rspamd_task *task = lua_check_task (L, 1);
  1984. const gchar *new_hostname;
  1985. if (task) {
  1986. new_hostname = luaL_checkstring (L, 2);
  1987. if (new_hostname) {
  1988. task->hostname = rspamd_mempool_strdup (task->task_pool,
  1989. new_hostname);
  1990. }
  1991. }
  1992. else {
  1993. return luaL_error (L, "invalid arguments");
  1994. }
  1995. return 0;
  1996. }
  1997. static gint
  1998. lua_task_get_images (lua_State *L)
  1999. {
  2000. struct rspamd_task *task = lua_check_task (L, 1);
  2001. guint nelt = 0, i;
  2002. struct rspamd_mime_part *part;
  2003. struct rspamd_image **pimg;
  2004. if (task) {
  2005. lua_newtable (L);
  2006. for (i = 0; i < task->parts->len; i ++) {
  2007. part = g_ptr_array_index (task->parts, i);
  2008. if (part->flags & RSPAMD_MIME_PART_IMAGE) {
  2009. pimg = lua_newuserdata (L, sizeof (struct rspamd_image *));
  2010. rspamd_lua_setclass (L, "rspamd{image}", -1);
  2011. *pimg = part->specific_data;
  2012. lua_rawseti (L, -2, ++nelt);
  2013. }
  2014. }
  2015. }
  2016. else {
  2017. return luaL_error (L, "invalid arguments");
  2018. }
  2019. return 1;
  2020. }
  2021. static gint
  2022. lua_task_get_archives (lua_State *L)
  2023. {
  2024. struct rspamd_task *task = lua_check_task (L, 1);
  2025. guint nelt = 0, i;
  2026. struct rspamd_mime_part *part;
  2027. struct rspamd_archive **parch;
  2028. if (task) {
  2029. lua_createtable (L, task->parts->len, 0);
  2030. for (i = 0; i < task->parts->len; i ++) {
  2031. part = g_ptr_array_index (task->parts, i);
  2032. if (part->flags & RSPAMD_MIME_PART_ARCHIVE) {
  2033. parch = lua_newuserdata (L, sizeof (struct rspamd_archive *));
  2034. rspamd_lua_setclass (L, "rspamd{archive}", -1);
  2035. *parch = part->specific_data;
  2036. lua_rawseti (L, -2, ++nelt);
  2037. }
  2038. }
  2039. }
  2040. else {
  2041. return luaL_error (L, "invalid arguments");
  2042. }
  2043. return 1;
  2044. }
  2045. static inline gboolean
  2046. lua_push_symbol_result (lua_State *L,
  2047. struct rspamd_task *task,
  2048. struct metric *metric,
  2049. const gchar *symbol)
  2050. {
  2051. struct metric_result *metric_res;
  2052. struct symbol *s;
  2053. gint j;
  2054. GList *opt;
  2055. metric_res = g_hash_table_lookup (task->results, metric->name);
  2056. if (metric_res) {
  2057. if ((s = g_hash_table_lookup (metric_res->symbols, symbol)) != NULL) {
  2058. j = 1;
  2059. lua_newtable (L);
  2060. lua_pushstring (L, "metric");
  2061. lua_pushstring (L, metric->name);
  2062. lua_settable (L, -3);
  2063. lua_pushstring (L, "score");
  2064. lua_pushnumber (L, s->score);
  2065. lua_settable (L, -3);
  2066. if (s->def && s->def->gr) {
  2067. lua_pushstring (L, "group");
  2068. lua_pushstring (L, s->def->gr->name);
  2069. lua_settable (L, -3);
  2070. }
  2071. else {
  2072. lua_pushstring (L, "group");
  2073. lua_pushstring (L, "ungrouped");
  2074. lua_settable (L, -3);
  2075. }
  2076. if (s->options) {
  2077. opt = s->options;
  2078. lua_pushstring (L, "options");
  2079. lua_newtable (L);
  2080. while (opt) {
  2081. lua_pushstring (L, opt->data);
  2082. lua_rawseti (L, -2, j++);
  2083. opt = g_list_next (opt);
  2084. }
  2085. lua_settable (L, -3);
  2086. }
  2087. return TRUE;
  2088. }
  2089. }
  2090. return FALSE;
  2091. }
  2092. static gint
  2093. lua_task_get_symbol (lua_State *L)
  2094. {
  2095. struct rspamd_task *task = lua_check_task (L, 1);
  2096. const gchar *symbol;
  2097. struct metric *metric;
  2098. GList *cur = NULL, *metric_list;
  2099. gboolean found = FALSE;
  2100. gint i = 1;
  2101. symbol = luaL_checkstring (L, 2);
  2102. if (task && symbol) {
  2103. metric_list = g_hash_table_lookup (task->cfg->metrics_symbols, symbol);
  2104. if (metric_list) {
  2105. lua_newtable (L);
  2106. cur = metric_list;
  2107. }
  2108. else {
  2109. metric = task->cfg->default_metric;
  2110. }
  2111. if (!cur && metric) {
  2112. if ((found = lua_push_symbol_result (L, task, metric, symbol))) {
  2113. lua_newtable (L);
  2114. lua_rawseti (L, -2, i++);
  2115. }
  2116. }
  2117. else {
  2118. while (cur) {
  2119. metric = cur->data;
  2120. if (lua_push_symbol_result (L, task, metric, symbol)) {
  2121. lua_rawseti (L, -2, i++);
  2122. found = TRUE;
  2123. }
  2124. cur = g_list_next (cur);
  2125. }
  2126. }
  2127. }
  2128. else {
  2129. return luaL_error (L, "invalid arguments");
  2130. }
  2131. if (!found) {
  2132. lua_pushnil (L);
  2133. }
  2134. return 1;
  2135. }
  2136. static gint
  2137. lua_task_has_symbol (lua_State *L)
  2138. {
  2139. struct rspamd_task *task = lua_check_task (L, 1);
  2140. const gchar *symbol;
  2141. struct metric_result *mres;
  2142. gboolean found = FALSE;
  2143. symbol = luaL_checkstring (L, 2);
  2144. if (task && symbol) {
  2145. mres = g_hash_table_lookup (task->results, DEFAULT_METRIC);
  2146. if (mres) {
  2147. found = g_hash_table_lookup (mres->symbols, symbol) != NULL;
  2148. }
  2149. lua_pushboolean (L, found);
  2150. }
  2151. else {
  2152. return luaL_error (L, "invalid arguments");
  2153. }
  2154. return 1;
  2155. }
  2156. static gint
  2157. lua_task_get_symbols (lua_State *L)
  2158. {
  2159. struct rspamd_task *task = lua_check_task (L, 1);
  2160. struct metric_result *mres;
  2161. gint i = 1;
  2162. GHashTableIter it;
  2163. gpointer k, v;
  2164. struct symbol *s;
  2165. if (task) {
  2166. mres = g_hash_table_lookup (task->results, DEFAULT_METRIC);
  2167. if (mres) {
  2168. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2169. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2170. g_hash_table_iter_init (&it, mres->symbols);
  2171. while (g_hash_table_iter_next (&it, &k, &v)) {
  2172. s = v;
  2173. lua_pushstring (L, k);
  2174. lua_rawseti (L, -3, i);
  2175. lua_pushnumber (L, s->score);
  2176. lua_rawseti (L, -2, i);
  2177. i ++;
  2178. }
  2179. }
  2180. else {
  2181. lua_createtable (L, 0, 0);
  2182. lua_createtable (L, 0, 0);
  2183. }
  2184. }
  2185. else {
  2186. return luaL_error (L, "invalid arguments");
  2187. }
  2188. return 2;
  2189. }
  2190. static gint
  2191. lua_task_get_symbols_numeric (lua_State *L)
  2192. {
  2193. struct rspamd_task *task = lua_check_task (L, 1);
  2194. struct metric_result *mres;
  2195. gint i = 1, id;
  2196. GHashTableIter it;
  2197. gpointer k, v;
  2198. struct symbol *s;
  2199. if (task) {
  2200. mres = g_hash_table_lookup (task->results, DEFAULT_METRIC);
  2201. if (mres) {
  2202. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2203. lua_createtable (L, g_hash_table_size (mres->symbols), 0);
  2204. g_hash_table_iter_init (&it, mres->symbols);
  2205. while (g_hash_table_iter_next (&it, &k, &v)) {
  2206. id = rspamd_symbols_cache_find_symbol (task->cfg->cache,
  2207. k);
  2208. s = v;
  2209. lua_pushnumber (L, id);
  2210. lua_rawseti (L, -3, i);
  2211. lua_pushnumber (L, s->score);
  2212. lua_rawseti (L, -2, i);
  2213. i ++;
  2214. }
  2215. }
  2216. else {
  2217. lua_createtable (L, 0, 0);
  2218. lua_createtable (L, 0, 0);
  2219. }
  2220. }
  2221. else {
  2222. return luaL_error (L, "invalid arguments");
  2223. }
  2224. return 2;
  2225. }
  2226. enum lua_date_type {
  2227. DATE_CONNECT = 0,
  2228. DATE_MESSAGE,
  2229. DATE_CONNECT_STRING,
  2230. DATE_MESSAGE_STRING
  2231. };
  2232. static enum lua_date_type
  2233. lua_task_detect_date_type (lua_State *L, gint idx, gboolean *gmt)
  2234. {
  2235. enum lua_date_type type = DATE_CONNECT;
  2236. if (lua_type (L, idx) == LUA_TNUMBER) {
  2237. gint num = lua_tonumber (L, idx);
  2238. if (num >= DATE_CONNECT && num <= DATE_MESSAGE_STRING) {
  2239. return num;
  2240. }
  2241. }
  2242. else if (lua_type (L, idx) == LUA_TTABLE) {
  2243. const gchar *str;
  2244. lua_pushvalue (L, idx);
  2245. lua_pushstring (L, "format");
  2246. lua_gettable (L, -2);
  2247. str = lua_tostring (L, -1);
  2248. if (g_ascii_strcasecmp (str, "message") == 0) {
  2249. type = DATE_MESSAGE;
  2250. }
  2251. else if (g_ascii_strcasecmp (str, "connect_str") == 0) {
  2252. type = DATE_CONNECT_STRING;
  2253. }
  2254. else if (g_ascii_strcasecmp (str, "message_str") == 0) {
  2255. type = DATE_MESSAGE_STRING;
  2256. }
  2257. lua_pop (L, 1);
  2258. lua_pushstring (L, "gmt");
  2259. lua_gettable (L, -2);
  2260. if (lua_type (L, -1) == LUA_TBOOLEAN) {
  2261. *gmt = lua_toboolean (L, -1);
  2262. }
  2263. /* Value and table */
  2264. lua_pop (L, 2);
  2265. }
  2266. return type;
  2267. }
  2268. static gint
  2269. lua_task_get_date (lua_State *L)
  2270. {
  2271. struct rspamd_task *task = lua_check_task (L, 1);
  2272. gdouble tim;
  2273. enum lua_date_type type = DATE_CONNECT;
  2274. gboolean gmt = TRUE;
  2275. if (task != NULL) {
  2276. if (lua_gettop (L) > 1) {
  2277. type = lua_task_detect_date_type (L, 2, &gmt);
  2278. }
  2279. /* Get GMT date and store it to time_t */
  2280. if (type == DATE_CONNECT || type == DATE_CONNECT_STRING) {
  2281. tim = (tv_to_msec (&task->tv)) / 1000.;
  2282. if (!gmt) {
  2283. struct tm t;
  2284. time_t tt;
  2285. tt = tim;
  2286. localtime_r (&tt, &t);
  2287. #if !defined(__sun)
  2288. t.tm_gmtoff = 0;
  2289. #endif
  2290. t.tm_isdst = 0;
  2291. tim = mktime (&t);
  2292. }
  2293. }
  2294. else {
  2295. if (task->message) {
  2296. time_t tt;
  2297. gint offset;
  2298. g_mime_message_get_date (task->message, &tt, &offset);
  2299. if (!gmt) {
  2300. tt += (offset * 60 * 60) / 100 + (offset * 60 * 60) % 100;
  2301. }
  2302. tim = tt;
  2303. }
  2304. else {
  2305. tim = 0.0;
  2306. }
  2307. }
  2308. if (type == DATE_CONNECT || type == DATE_MESSAGE) {
  2309. lua_pushnumber (L, tim);
  2310. }
  2311. else {
  2312. GTimeVal tv;
  2313. gchar *out;
  2314. double_to_tv (tim, &tv);
  2315. out = g_time_val_to_iso8601 (&tv);
  2316. lua_pushstring (L, out);
  2317. g_free (out);
  2318. }
  2319. }
  2320. else {
  2321. return luaL_error (L, "invalid arguments");
  2322. }
  2323. return 1;
  2324. }
  2325. static gint
  2326. lua_task_get_message_id (lua_State *L)
  2327. {
  2328. struct rspamd_task *task = lua_check_task (L, 1);
  2329. if (task != NULL) {
  2330. if (task->message_id != NULL) {
  2331. lua_pushstring (L, task->message_id);
  2332. }
  2333. else {
  2334. lua_pushnil (L);
  2335. }
  2336. }
  2337. else {
  2338. return luaL_error (L, "invalid arguments");
  2339. }
  2340. return 1;
  2341. }
  2342. static gint
  2343. lua_task_get_timeval (lua_State *L)
  2344. {
  2345. struct rspamd_task *task = lua_check_task (L, 1);
  2346. if (task != NULL) {
  2347. lua_createtable (L, 0, 2);
  2348. lua_pushstring (L, "tv_sec");
  2349. lua_pushnumber (L, (lua_Number)task->tv.tv_sec);
  2350. lua_settable (L, -3);
  2351. lua_pushstring (L, "tv_usec");
  2352. lua_pushnumber (L, (lua_Number)task->tv.tv_usec);
  2353. lua_settable (L, -3);
  2354. }
  2355. else {
  2356. return luaL_error (L, "invalid arguments");
  2357. }
  2358. return 1;
  2359. }
  2360. static gint
  2361. lua_task_get_size (lua_State *L)
  2362. {
  2363. struct rspamd_task *task = lua_check_task (L, 1);
  2364. if (task != NULL) {
  2365. lua_pushnumber (L, task->msg.len);
  2366. }
  2367. else {
  2368. return luaL_error (L, "invalid arguments");
  2369. }
  2370. return 1;
  2371. }
  2372. /**
  2373. * - `no_log`: do not log task summary
  2374. * - `no_stat`: do not include task into scanned stats
  2375. * - `pass_all`: check all filters for task
  2376. * - `extended_urls`: output extended info about urls
  2377. * - `skip`: skip task processing
  2378. */
  2379. #define LUA_TASK_FLAG_WRITE(flag, set) do { \
  2380. task->flags = (set) ? (task->flags | (flag)) : (task->flags & ~(flag)); \
  2381. } while(0)
  2382. #define LUA_TASK_SET_FLAG(flag, strname, macro, set) do { \
  2383. if (!found && strcmp ((flag), strname) == 0) { \
  2384. LUA_TASK_FLAG_WRITE((macro), set); \
  2385. found = TRUE; \
  2386. } \
  2387. } while(0)
  2388. #define LUA_TASK_FLAG_READ(flag) do { \
  2389. lua_pushboolean(L, !!(task->flags & (flag))); \
  2390. } while(0)
  2391. #define LUA_TASK_GET_FLAG(flag, strname, macro) do { \
  2392. if (!found && strcmp ((flag), strname) == 0) { \
  2393. LUA_TASK_FLAG_READ((macro)); \
  2394. found = TRUE; \
  2395. } \
  2396. } while(0)
  2397. static gint
  2398. lua_task_set_flag (lua_State *L)
  2399. {
  2400. struct rspamd_task *task = lua_check_task (L, 1);
  2401. const gchar *flag = luaL_checkstring (L, 2);
  2402. gboolean set = TRUE, found = FALSE;
  2403. if (lua_gettop (L) >= 3) {
  2404. set = lua_toboolean (L, 3);
  2405. }
  2406. if (task != NULL && flag != NULL) {
  2407. LUA_TASK_SET_FLAG (flag, "pass_all", RSPAMD_TASK_FLAG_PASS_ALL, set);
  2408. LUA_TASK_SET_FLAG (flag, "no_log", RSPAMD_TASK_FLAG_NO_LOG, set);
  2409. LUA_TASK_SET_FLAG (flag, "no_stat", RSPAMD_TASK_FLAG_NO_STAT, set);
  2410. LUA_TASK_SET_FLAG (flag, "skip", RSPAMD_TASK_FLAG_SKIP, set);
  2411. LUA_TASK_SET_FLAG (flag, "extended_urls", RSPAMD_TASK_FLAG_EXT_URLS, set);
  2412. LUA_TASK_SET_FLAG (flag, "learn_spam", RSPAMD_TASK_FLAG_LEARN_SPAM, set);
  2413. LUA_TASK_SET_FLAG (flag, "learn_ham", RSPAMD_TASK_FLAG_LEARN_HAM, set);
  2414. LUA_TASK_SET_FLAG (flag, "broken_headers",
  2415. RSPAMD_TASK_FLAG_BROKEN_HEADERS, set);
  2416. if (!found) {
  2417. msg_warn_task ("unknown flag requested: %s", flag);
  2418. }
  2419. }
  2420. else {
  2421. return luaL_error (L, "invalid arguments");
  2422. }
  2423. return 0;
  2424. }
  2425. static gint
  2426. lua_task_has_flag (lua_State *L)
  2427. {
  2428. struct rspamd_task *task = lua_check_task (L, 1);
  2429. const gchar *flag = luaL_checkstring (L, 2);
  2430. gboolean found = FALSE;
  2431. if (task != NULL && flag != NULL) {
  2432. LUA_TASK_GET_FLAG (flag, "pass_all", RSPAMD_TASK_FLAG_PASS_ALL);
  2433. LUA_TASK_GET_FLAG (flag, "no_log", RSPAMD_TASK_FLAG_NO_LOG);
  2434. LUA_TASK_GET_FLAG (flag, "no_stat", RSPAMD_TASK_FLAG_NO_STAT);
  2435. LUA_TASK_GET_FLAG (flag, "skip", RSPAMD_TASK_FLAG_SKIP);
  2436. LUA_TASK_GET_FLAG (flag, "extended_urls", RSPAMD_TASK_FLAG_EXT_URLS);
  2437. LUA_TASK_GET_FLAG (flag, "learn_spam", RSPAMD_TASK_FLAG_LEARN_SPAM);
  2438. LUA_TASK_GET_FLAG (flag, "learn_ham", RSPAMD_TASK_FLAG_LEARN_HAM);
  2439. LUA_TASK_GET_FLAG (flag, "broken_headers",
  2440. RSPAMD_TASK_FLAG_BROKEN_HEADERS);
  2441. if (!found) {
  2442. msg_warn_task ("unknown flag requested: %s", flag);
  2443. lua_pushboolean (L, 0);
  2444. }
  2445. }
  2446. else {
  2447. return luaL_error (L, "invalid arguments");
  2448. }
  2449. return 1;
  2450. }
  2451. static gint
  2452. lua_task_get_flags (lua_State *L)
  2453. {
  2454. struct rspamd_task *task = lua_check_task (L, 1);
  2455. gint idx = 1;
  2456. guint flags, bit, i;
  2457. if (task) {
  2458. lua_createtable (L, 8, 0);
  2459. flags = task->flags;
  2460. for (i = 0; i < sizeof (task->flags) * NBBY; i ++) {
  2461. bit = (1U << i);
  2462. if (flags & bit) {
  2463. switch (bit) {
  2464. case RSPAMD_TASK_FLAG_PASS_ALL:
  2465. lua_pushstring (L, "pass_all");
  2466. lua_rawseti (L, -2, idx ++);
  2467. break;
  2468. case RSPAMD_TASK_FLAG_NO_LOG:
  2469. lua_pushstring (L, "no_log");
  2470. lua_rawseti (L, -2, idx++);
  2471. break;
  2472. case RSPAMD_TASK_FLAG_NO_STAT:
  2473. lua_pushstring (L, "no_stat");
  2474. lua_rawseti (L, -2, idx++);
  2475. break;
  2476. case RSPAMD_TASK_FLAG_SKIP:
  2477. lua_pushstring (L, "skip");
  2478. lua_rawseti (L, -2, idx++);
  2479. break;
  2480. case RSPAMD_TASK_FLAG_EXT_URLS:
  2481. lua_pushstring (L, "extended_urls");
  2482. lua_rawseti (L, -2, idx++);
  2483. break;
  2484. case RSPAMD_TASK_FLAG_BROKEN_HEADERS:
  2485. lua_pushstring (L, "broken_headers");
  2486. lua_rawseti (L, -2, idx++);
  2487. break;
  2488. case RSPAMD_TASK_FLAG_LEARN_SPAM:
  2489. lua_pushstring (L, "learn_spam");
  2490. lua_rawseti (L, -2, idx++);
  2491. break;
  2492. case RSPAMD_TASK_FLAG_LEARN_HAM:
  2493. lua_pushstring (L, "learn_ham");
  2494. lua_rawseti (L, -2, idx++);
  2495. break;
  2496. default:
  2497. break;
  2498. }
  2499. }
  2500. }
  2501. }
  2502. else {
  2503. return luaL_error (L, "invalid arguments");
  2504. }
  2505. return 1;
  2506. }
  2507. static gint
  2508. lua_task_get_digest (lua_State *L)
  2509. {
  2510. struct rspamd_task *task = lua_check_task (L, 1);
  2511. gchar hexbuf[33];
  2512. gint r;
  2513. if (task) {
  2514. r = rspamd_encode_hex_buf (task->digest, sizeof (task->digest),
  2515. hexbuf, sizeof (hexbuf) - 1);
  2516. if (r > 0) {
  2517. hexbuf[r] = '\0';
  2518. lua_pushstring (L, hexbuf);
  2519. }
  2520. else {
  2521. lua_pushnil (L);
  2522. }
  2523. }
  2524. else {
  2525. return luaL_error (L, "invalid arguments");
  2526. }
  2527. return 1;
  2528. }
  2529. static gint
  2530. lua_task_learn (lua_State *L)
  2531. {
  2532. struct rspamd_task *task = lua_check_task (L, 1);
  2533. gboolean is_spam = FALSE;
  2534. const gchar *clname = NULL;
  2535. GError *err = NULL;
  2536. int ret = 1;
  2537. if (task == NULL) {
  2538. return luaL_error (L, "invalid arguments");
  2539. }
  2540. is_spam = lua_toboolean(L, 2);
  2541. if (lua_gettop (L) > 2) {
  2542. clname = luaL_checkstring (L, 3);
  2543. }
  2544. if (!rspamd_learn_task_spam (task, is_spam, clname, &err)) {
  2545. lua_pushboolean (L, FALSE);
  2546. if (err != NULL) {
  2547. lua_pushstring (L, err->message);
  2548. ret = 2;
  2549. }
  2550. }
  2551. else {
  2552. lua_pushboolean (L, TRUE);
  2553. }
  2554. return ret;
  2555. }
  2556. static gint
  2557. lua_task_set_settings (lua_State *L)
  2558. {
  2559. struct rspamd_task *task = lua_check_task (L, 1);
  2560. ucl_object_t *settings;
  2561. const ucl_object_t *act, *elt, *metric_elt;
  2562. struct metric_result *mres;
  2563. guint i;
  2564. settings = ucl_object_lua_import (L, 2);
  2565. if (settings != NULL && task != NULL) {
  2566. metric_elt = ucl_object_lookup (settings, DEFAULT_METRIC);
  2567. if (metric_elt) {
  2568. task->settings = ucl_object_ref (metric_elt);
  2569. ucl_object_unref (settings);
  2570. }
  2571. else {
  2572. task->settings = settings;
  2573. }
  2574. act = ucl_object_lookup (task->settings, "actions");
  2575. if (act) {
  2576. /* Adjust desired actions */
  2577. mres = g_hash_table_lookup (task->results, DEFAULT_METRIC);
  2578. if (mres == NULL) {
  2579. mres = rspamd_create_metric_result (task, DEFAULT_METRIC);
  2580. }
  2581. for (i = 0; i < METRIC_ACTION_MAX; i++) {
  2582. elt = ucl_object_lookup_any (act, rspamd_action_to_str (i),
  2583. rspamd_action_to_str_alt (i), NULL);
  2584. if (elt) {
  2585. mres->actions_limits[i] = ucl_object_todouble (elt);
  2586. msg_debug_task ("adjusted action %s to %.2f",
  2587. ucl_object_key (elt), mres->actions_limits[i]);
  2588. }
  2589. }
  2590. }
  2591. rspamd_symbols_cache_process_settings (task, task->cfg->cache);
  2592. }
  2593. else {
  2594. return luaL_error (L, "invalid arguments");
  2595. }
  2596. return 0;
  2597. }
  2598. static gint
  2599. lua_task_set_rmilter_reply (lua_State *L)
  2600. {
  2601. struct rspamd_task *task = lua_check_task (L, 1);
  2602. ucl_object_t *reply;
  2603. reply = ucl_object_lua_import (L, 2);
  2604. if (reply != NULL && task != NULL) {
  2605. rspamd_mempool_set_variable (task->task_pool, "rmilter-reply",
  2606. reply, (rspamd_mempool_destruct_t)ucl_object_unref);
  2607. }
  2608. else {
  2609. return luaL_error (L, "invalid arguments");
  2610. }
  2611. return 0;
  2612. }
  2613. static gint
  2614. lua_task_get_settings (lua_State *L)
  2615. {
  2616. struct rspamd_task *task = lua_check_task (L, 1);
  2617. if (task != NULL) {
  2618. if (task->settings) {
  2619. return ucl_object_push_lua (L, task->settings, true);
  2620. }
  2621. else {
  2622. lua_pushnil (L);
  2623. }
  2624. }
  2625. else {
  2626. return luaL_error (L, "invalid arguments");
  2627. }
  2628. return 1;
  2629. }
  2630. static gint
  2631. lua_task_lookup_settings (lua_State *L)
  2632. {
  2633. struct rspamd_task *task = lua_check_task (L, 1);
  2634. const gchar *key = NULL;
  2635. const ucl_object_t *elt;
  2636. if (task != NULL) {
  2637. if (lua_isstring (L, 2)) {
  2638. key = lua_tostring (L, 2);
  2639. }
  2640. if (task->settings) {
  2641. if (key == NULL) {
  2642. return ucl_object_push_lua (L, task->settings, true);
  2643. }
  2644. else {
  2645. elt = ucl_object_lookup (task->settings, key);
  2646. if (elt) {
  2647. return ucl_object_push_lua (L, elt, true);
  2648. }
  2649. else {
  2650. lua_pushnil (L);
  2651. }
  2652. }
  2653. }
  2654. else {
  2655. lua_pushnil (L);
  2656. }
  2657. }
  2658. else {
  2659. return luaL_error (L, "invalid arguments");
  2660. }
  2661. return 1;
  2662. }
  2663. static gint
  2664. lua_task_get_settings_id (lua_State *L)
  2665. {
  2666. struct rspamd_task *task = lua_check_task (L, 1);
  2667. guint32 *hp;
  2668. if (task != NULL) {
  2669. hp = rspamd_mempool_get_variable (task->task_pool, "settings_hash");
  2670. if (hp) {
  2671. lua_pushnumber (L, *hp);
  2672. }
  2673. else {
  2674. lua_pushnil (L);
  2675. }
  2676. }
  2677. else {
  2678. return luaL_error (L, "invalid arguments");
  2679. }
  2680. return 1;
  2681. }
  2682. static gint
  2683. lua_task_cache_get (lua_State *L)
  2684. {
  2685. struct rspamd_task *task = lua_check_task (L, 1);
  2686. if (task) {
  2687. msg_err_task ("this function is deprecated and will return nothing");
  2688. }
  2689. lua_pushnumber (L, -1);
  2690. return 1;
  2691. }
  2692. static gint
  2693. lua_task_cache_set (lua_State *L)
  2694. {
  2695. struct rspamd_task *task = lua_check_task (L, 1);
  2696. if (task) {
  2697. msg_err_task ("this function is deprecated and will return nothing");
  2698. }
  2699. lua_pushnumber (L, 0);
  2700. return 1;
  2701. }
  2702. static gint
  2703. lua_task_process_regexp (lua_State *L)
  2704. {
  2705. struct rspamd_task *task = lua_check_task (L, 1);
  2706. struct rspamd_lua_regexp *re = NULL;
  2707. gboolean strong = FALSE;
  2708. const gchar *type_str = NULL, *header_str = NULL;
  2709. gsize header_len = 0;
  2710. GError *err = NULL;
  2711. gint ret = 0;
  2712. enum rspamd_re_type type = RSPAMD_RE_BODY;
  2713. /*
  2714. * - `re`* : regular expression object
  2715. * - `type`*: type of regular expression:
  2716. * + `mime`: mime regexp
  2717. * + `rawmime`: raw mime regexp
  2718. * + `header`: header regexp
  2719. * + `rawheader`: raw header expression
  2720. * + `body`: raw body regexp
  2721. * + `url`: url regexp
  2722. * - `header`: for header and rawheader regexp means the name of header
  2723. * - `strong`: case sensitive match for headers
  2724. */
  2725. if (task != NULL) {
  2726. if (!rspamd_lua_parse_table_arguments (L, 2, &err,
  2727. "*re=U{regexp};*type=S;header=V;strong=B",
  2728. &re, &type_str, &header_len, &header_str,
  2729. &strong)) {
  2730. msg_err_task ("cannot get parameters list: %e", err);
  2731. if (err) {
  2732. g_error_free (err);
  2733. }
  2734. }
  2735. else {
  2736. type = rspamd_re_cache_type_from_string (type_str);
  2737. if ((type == RSPAMD_RE_HEADER || type == RSPAMD_RE_RAWHEADER)
  2738. && header_str == NULL) {
  2739. msg_err_task (
  2740. "header argument is mandatory for header/rawheader regexps");
  2741. }
  2742. else {
  2743. ret = rspamd_re_cache_process (task, re->re, type,
  2744. (gpointer) header_str, header_len, strong);
  2745. }
  2746. }
  2747. }
  2748. else {
  2749. return luaL_error (L, "invalid arguments");
  2750. }
  2751. lua_pushnumber (L, ret);
  2752. return 1;
  2753. }
  2754. static gint
  2755. lua_task_get_metric_score (lua_State *L)
  2756. {
  2757. struct rspamd_task *task = lua_check_task (L, 1);
  2758. const gchar *metric_name;
  2759. gdouble rs;
  2760. struct metric_result *metric_res;
  2761. metric_name = luaL_checkstring (L, 2);
  2762. if (task && metric_name) {
  2763. if ((metric_res =
  2764. g_hash_table_lookup (task->results, metric_name)) != NULL) {
  2765. lua_createtable (L, 2, 0);
  2766. lua_pushnumber (L, metric_res->score);
  2767. rs = rspamd_task_get_required_score (task, metric_res);
  2768. lua_rawseti (L, -2, 1);
  2769. lua_pushnumber (L, rs);
  2770. lua_rawseti (L, -2, 2);
  2771. }
  2772. else {
  2773. lua_pushnil (L);
  2774. }
  2775. }
  2776. else {
  2777. return luaL_error (L, "invalid arguments");
  2778. }
  2779. return 1;
  2780. }
  2781. static gint
  2782. lua_task_get_metric_action (lua_State *L)
  2783. {
  2784. struct rspamd_task *task = lua_check_task (L, 1);
  2785. const gchar *metric_name;
  2786. struct metric_result *metric_res;
  2787. enum rspamd_metric_action action;
  2788. metric_name = luaL_checkstring (L, 2);
  2789. if (metric_name == NULL) {
  2790. metric_name = DEFAULT_METRIC;
  2791. }
  2792. if (task && metric_name) {
  2793. if ((metric_res =
  2794. g_hash_table_lookup (task->results, metric_name)) != NULL) {
  2795. action = rspamd_check_action_metric (task, metric_res);
  2796. lua_pushstring (L, rspamd_action_to_str (action));
  2797. }
  2798. else {
  2799. lua_pushnil (L);
  2800. }
  2801. }
  2802. else {
  2803. return luaL_error (L, "invalid arguments");
  2804. }
  2805. return 1;
  2806. }
  2807. static gint
  2808. lua_task_set_metric_score (lua_State *L)
  2809. {
  2810. struct rspamd_task *task = lua_check_task (L, 1);
  2811. const gchar *metric_name;
  2812. struct metric_result *metric_res;
  2813. gdouble nscore;
  2814. metric_name = luaL_checkstring (L, 2);
  2815. nscore = luaL_checknumber (L, 3);
  2816. if (metric_name == NULL) {
  2817. metric_name = DEFAULT_METRIC;
  2818. }
  2819. if (task && metric_name) {
  2820. if ((metric_res =
  2821. g_hash_table_lookup (task->results, metric_name)) != NULL) {
  2822. metric_res->score = nscore;
  2823. lua_pushboolean (L, true);
  2824. }
  2825. else {
  2826. lua_pushboolean (L, false);
  2827. }
  2828. }
  2829. else {
  2830. return luaL_error (L, "invalid arguments");
  2831. }
  2832. return 1;
  2833. }
  2834. static gint
  2835. lua_task_set_metric_action (lua_State *L)
  2836. {
  2837. struct rspamd_task *task = lua_check_task (L, 1);
  2838. const gchar *metric_name, *action_name;
  2839. struct metric_result *metric_res;
  2840. gint action;
  2841. metric_name = luaL_checkstring (L, 2);
  2842. if (metric_name == NULL) {
  2843. metric_name = DEFAULT_METRIC;
  2844. }
  2845. action_name = luaL_checkstring (L, 3);
  2846. if (task && metric_name && action_name) {
  2847. if ((metric_res =
  2848. g_hash_table_lookup (task->results, metric_name)) != NULL) {
  2849. if (rspamd_action_from_str (action_name, &action)) {
  2850. metric_res->action = action;
  2851. lua_pushboolean (L, true);
  2852. }
  2853. else {
  2854. lua_pushboolean (L, false);
  2855. }
  2856. }
  2857. else {
  2858. lua_pushboolean (L, false);
  2859. }
  2860. }
  2861. else {
  2862. return luaL_error (L, "invalid arguments");
  2863. }
  2864. return 1;
  2865. }
  2866. /* Image functions */
  2867. static gint
  2868. lua_image_get_width (lua_State *L)
  2869. {
  2870. struct rspamd_image *img = lua_check_image (L);
  2871. if (img != NULL) {
  2872. lua_pushnumber (L, img->width);
  2873. }
  2874. else {
  2875. return luaL_error (L, "invalid arguments");
  2876. }
  2877. return 1;
  2878. }
  2879. static gint
  2880. lua_image_get_height (lua_State *L)
  2881. {
  2882. struct rspamd_image *img = lua_check_image (L);
  2883. if (img != NULL) {
  2884. lua_pushnumber (L, img->height);
  2885. }
  2886. else {
  2887. return luaL_error (L, "invalid arguments");
  2888. }
  2889. return 1;
  2890. }
  2891. static gint
  2892. lua_image_get_type (lua_State *L)
  2893. {
  2894. struct rspamd_image *img = lua_check_image (L);
  2895. if (img != NULL) {
  2896. lua_pushstring (L, rspamd_image_type_str (img->type));
  2897. }
  2898. else {
  2899. return luaL_error (L, "invalid arguments");
  2900. }
  2901. return 1;
  2902. }
  2903. static gint
  2904. lua_image_get_size (lua_State *L)
  2905. {
  2906. struct rspamd_image *img = lua_check_image (L);
  2907. if (img != NULL) {
  2908. lua_pushinteger (L, img->data->len);
  2909. }
  2910. else {
  2911. return luaL_error (L, "invalid arguments");
  2912. }
  2913. return 1;
  2914. }
  2915. static gint
  2916. lua_image_get_filename (lua_State *L)
  2917. {
  2918. struct rspamd_image *img = lua_check_image (L);
  2919. if (img != NULL && img->filename != NULL) {
  2920. lua_pushstring (L, img->filename);
  2921. }
  2922. else {
  2923. return luaL_error (L, "invalid arguments");
  2924. }
  2925. return 1;
  2926. }
  2927. /* Arvhive methods */
  2928. static gint
  2929. lua_archive_get_type (lua_State *L)
  2930. {
  2931. struct rspamd_archive *arch = lua_check_archive (L);
  2932. if (arch != NULL) {
  2933. lua_pushstring (L, rspamd_archive_type_str (arch->type));
  2934. }
  2935. else {
  2936. return luaL_error (L, "invalid arguments");
  2937. }
  2938. return 1;
  2939. }
  2940. static gint
  2941. lua_archive_get_files (lua_State *L)
  2942. {
  2943. struct rspamd_archive *arch = lua_check_archive (L);
  2944. guint i;
  2945. struct rspamd_archive_file *f;
  2946. if (arch != NULL) {
  2947. lua_createtable (L, arch->files->len, 0);
  2948. for (i = 0; i < arch->files->len; i ++) {
  2949. f = g_ptr_array_index (arch->files, i);
  2950. lua_pushlstring (L, f->fname->str, f->fname->len);
  2951. lua_rawseti (L, -2, i + 1);
  2952. }
  2953. }
  2954. else {
  2955. return luaL_error (L, "invalid arguments");
  2956. }
  2957. return 1;
  2958. }
  2959. static gint
  2960. lua_archive_get_files_full (lua_State *L)
  2961. {
  2962. struct rspamd_archive *arch = lua_check_archive (L);
  2963. guint i;
  2964. struct rspamd_archive_file *f;
  2965. if (arch != NULL) {
  2966. lua_createtable (L, arch->files->len, 0);
  2967. for (i = 0; i < arch->files->len; i ++) {
  2968. f = g_ptr_array_index (arch->files, i);
  2969. lua_createtable (L, 0, 4);
  2970. lua_pushstring (L, "name");
  2971. lua_pushlstring (L, f->fname->str, f->fname->len);
  2972. lua_settable (L, -3);
  2973. lua_pushstring (L, "compressed_size");
  2974. lua_pushnumber (L, f->compressed_size);
  2975. lua_settable (L, -3);
  2976. lua_pushstring (L, "uncompressed_size");
  2977. lua_pushnumber (L, f->uncompressed_size);
  2978. lua_settable (L, -3);
  2979. lua_pushstring (L, "encrypted");
  2980. lua_pushboolean (L, (f->flags & RSPAMD_ARCHIVE_FILE_ENCRYPTED) ? true : false);
  2981. lua_settable (L, -3);
  2982. lua_rawseti (L, -2, i + 1);
  2983. }
  2984. }
  2985. else {
  2986. return luaL_error (L, "invalid arguments");
  2987. }
  2988. return 1;
  2989. }
  2990. static gint
  2991. lua_archive_is_encrypted (lua_State *L)
  2992. {
  2993. struct rspamd_archive *arch = lua_check_archive (L);
  2994. if (arch != NULL) {
  2995. lua_pushboolean (L, (arch->flags & RSPAMD_ARCHIVE_ENCRYPTED) ? true : false);
  2996. }
  2997. else {
  2998. return luaL_error (L, "invalid arguments");
  2999. }
  3000. return 1;
  3001. }
  3002. static gint
  3003. lua_archive_get_size (lua_State *L)
  3004. {
  3005. struct rspamd_archive *arch = lua_check_archive (L);
  3006. if (arch != NULL) {
  3007. lua_pushinteger (L, arch->size);
  3008. }
  3009. else {
  3010. return luaL_error (L, "invalid arguments");
  3011. }
  3012. return 1;
  3013. }
  3014. static gint
  3015. lua_archive_get_filename (lua_State *L)
  3016. {
  3017. struct rspamd_archive *arch = lua_check_archive (L);
  3018. if (arch != NULL) {
  3019. lua_pushstring (L, arch->archive_name);
  3020. }
  3021. else {
  3022. return luaL_error (L, "invalid arguments");
  3023. }
  3024. return 1;
  3025. }
  3026. /* Text methods */
  3027. static gint
  3028. lua_text_len (lua_State *L)
  3029. {
  3030. struct rspamd_lua_text *t = lua_check_text (L, 1);
  3031. gsize l = 0;
  3032. if (t != NULL) {
  3033. l = t->len;
  3034. }
  3035. else {
  3036. return luaL_error (L, "invalid arguments");
  3037. }
  3038. lua_pushnumber (L, l);
  3039. return 1;
  3040. }
  3041. static gint
  3042. lua_text_str (lua_State *L)
  3043. {
  3044. struct rspamd_lua_text *t = lua_check_text (L, 1);
  3045. if (t != NULL) {
  3046. lua_pushlstring (L, t->start, t->len);
  3047. }
  3048. else {
  3049. return luaL_error (L, "invalid arguments");
  3050. }
  3051. return 1;
  3052. }
  3053. static gint
  3054. lua_text_ptr (lua_State *L)
  3055. {
  3056. struct rspamd_lua_text *t = lua_check_text (L, 1);
  3057. if (t != NULL) {
  3058. lua_pushlightuserdata (L, (gpointer)t->start);
  3059. }
  3060. else {
  3061. return luaL_error (L, "invalid arguments");
  3062. }
  3063. return 1;
  3064. }
  3065. static gint
  3066. lua_text_gc (lua_State *L)
  3067. {
  3068. struct rspamd_lua_text *t = lua_check_text (L, 1);
  3069. if (t != NULL) {
  3070. if (t->flags & RSPAMD_TEXT_FLAG_OWN) {
  3071. if (t->flags & RSPAMD_TEXT_FLAG_MMAPED) {
  3072. munmap ((gpointer)t->start, t->len);
  3073. }
  3074. else {
  3075. g_free ((gpointer)t->start);
  3076. }
  3077. }
  3078. }
  3079. return 0;
  3080. }
  3081. /* Init part */
  3082. static gint
  3083. lua_load_task (lua_State * L)
  3084. {
  3085. lua_newtable (L);
  3086. luaL_register (L, NULL, tasklib_f);
  3087. return 1;
  3088. }
  3089. static void
  3090. luaopen_archive (lua_State * L)
  3091. {
  3092. rspamd_lua_new_class (L, "rspamd{archive}", archivelib_m);
  3093. lua_pop (L, 1);
  3094. }
  3095. void
  3096. luaopen_task (lua_State * L)
  3097. {
  3098. rspamd_lua_new_class (L, "rspamd{task}", tasklib_m);
  3099. lua_pop (L, 1);
  3100. rspamd_lua_add_preload (L, "rspamd_task", lua_load_task);
  3101. luaopen_archive (L);
  3102. }
  3103. void
  3104. luaopen_image (lua_State * L)
  3105. {
  3106. rspamd_lua_new_class (L, "rspamd{image}", imagelib_m);
  3107. lua_pop (L, 1);
  3108. }
  3109. void
  3110. luaopen_text (lua_State *L)
  3111. {
  3112. rspamd_lua_new_class (L, "rspamd{text}", textlib_m);
  3113. lua_pop (L, 1);
  3114. }
  3115. void
  3116. rspamd_lua_task_push (lua_State *L, struct rspamd_task *task)
  3117. {
  3118. struct rspamd_task **ptask;
  3119. ptask = lua_newuserdata (L, sizeof (gpointer));
  3120. rspamd_lua_setclass (L, "rspamd{task}", -1);
  3121. *ptask = task;
  3122. }