"Fossies" - the Fresh Open Source Software Archive

Member "imapfilter-2.8.2/src/common.lua" (26 Dec 2023, 11430 Bytes) of package /linux/privat/imapfilter-2.8.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Lua source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 -- Common functions for all classes and compatibility workarounds
    2 
    3 if _VERSION == 'Lua 5.1' then
    4     table.unpack = unpack
    5 else
    6     unpack = table.unpack
    7 end
    8 
    9 
   10 function _check_required(arg, argtype)
   11     if type(arg) == 'nil' then
   12         error('required argument left out', 3)
   13     else
   14         _check_optional(arg, argtype)
   15     end
   16 end
   17 
   18 function _check_optional(arg, argtype)
   19     if type(arg) ~= 'nil' then
   20         if type(argtype) == 'string' then
   21             if type(arg) ~= argtype then
   22                 error(argtype .. ' argument expected, got ' .. type(arg), 4)
   23             end
   24         elseif type(argtype) == 'table' then
   25             local b = false
   26             for _, t in ipairs(argtype) do
   27                 if type(arg) == t then b = true end
   28             end
   29             if b == false then
   30                 error(argtype .. ' argument expected, got ' .. type(arg), 4)
   31             end
   32         end
   33     end
   34 end
   35 
   36 
   37 function _extract_mailboxes(messages)
   38     local t = {}
   39     for _, v in ipairs(messages) do
   40         b, _ = table.unpack(v)
   41         t[b] = true
   42     end
   43     return t
   44 end
   45 
   46 function _extract_messages(mailbox, messages)
   47     local t = {}
   48     for _, v in ipairs(messages) do
   49         b, m = table.unpack(v)
   50         if mailbox == b then table.insert(t, m) end
   51     end
   52     return t
   53 end
   54 
   55 
   56 function _make_range(messages)
   57     for _, m in ipairs(messages) do
   58         if type(m) ~= 'number' then return messages end
   59     end
   60 
   61     table.sort(messages)
   62 
   63     local t = {}
   64     local a, z
   65     for _, m in ipairs(messages) do
   66         if a == nil or z == nil then
   67             a = m
   68             z = m
   69         else
   70             if m == z + 1 and m - a <= options.range then
   71                 z = m
   72             else
   73                 if a == z then
   74                     table.insert(t, tostring(a))
   75                 else
   76                     table.insert(t, a .. ':' .. z)
   77                 end
   78                 a = m
   79                 z = m
   80             end
   81         end
   82     end
   83 
   84     if a == z then
   85         table.insert(t, tostring(a))
   86     else
   87         table.insert(t, a .. ':' .. z)
   88     end
   89 
   90     return t
   91 end
   92 
   93 
   94 function _make_query(criteria, messages)
   95     local s = messages .. ' '
   96 
   97     if criteria.invert ~= true then
   98         for ka, va in ipairs(criteria) do
   99             if type(va) == 'string' then
  100                 s = s .. '' .. '(' .. va .. ')' .. ' '
  101             elseif type(va) == 'table' then
  102                 for i = 1, #va - 1 do s = s .. 'OR ' end
  103                 for ko, vo in ipairs(va) do
  104                     if type(vo) ~= 'string' then
  105                         error('filter rule not a string', 2)
  106                     end
  107                     s = s .. '(' .. vo .. ') '
  108                 end
  109             else
  110                 error('filter element not a string or table', 2)
  111             end
  112         end
  113     else
  114         for i = 1, #criteria - 1 do s = s .. 'OR ' end
  115         for ko, vo in ipairs(criteria) do
  116             if type(vo) == 'string' then
  117                 s = s .. '' .. '(' .. vo .. ')' .. ' '
  118             elseif type(vo) == 'table' then
  119                 s = s .. '('
  120                 for ka, va in ipairs(vo) do
  121                     if type(va) ~= 'string' then
  122                         error('filter rule not a string', 2)
  123                     end
  124                     s = s .. va .. ' '
  125                 end
  126                 s = string.gsub(s, '(.+) ', '%1')
  127                 s = s .. ') '
  128             else
  129                 error('filter rule not a string or table', 2)
  130             end
  131         end
  132     end
  133 
  134     s = string.gsub(s, '(.+) ', '%1')
  135 
  136     return s
  137 end
  138 
  139 
  140 function _parse_structure(b)
  141     local bs = _parse_body(b)
  142     if not bs then error(b.i .. ':' .. b.s) end
  143     return _parse_normalize(bs)
  144 end
  145 
  146 function _parse_normalize(bs, key, val)
  147     if not key or not val then
  148         if #bs == 0 then
  149             return { ['1'] = bs }
  150         else
  151             for k, v in pairs(bs) do
  152                 if type(k) ~= 'number' then bs[k] = nil end
  153             end
  154             for k, v in ipairs(bs) do
  155                 _parse_normalize(bs, k, v)
  156                 bs[tostring(k)] = v
  157                 bs[k] = nil
  158             end
  159         end
  160         return bs
  161     else
  162         for k, v in ipairs(val) do
  163             local new = tostring(key) .. '.' .. tostring(k)
  164             bs[new] = v
  165             _parse_normalize(bs, new, v)
  166             val[k] = nil
  167         end
  168     end
  169 end
  170 
  171 function _parse_body(b)
  172     if not _parse_lpar(b) then return end
  173 
  174     local bp
  175     if _parse_lpar(b, true) then
  176         bp = _parse_mpart(b)
  177     else
  178         bp = _parse_1part(b)
  179     end
  180 
  181     if not _parse_rpar(b) then return end
  182 
  183     return bp
  184 end
  185 
  186 function _parse_1part(b)
  187     local i = b.i
  188     local t = _parse_string(b)
  189     _parse_space(b)
  190     local s = _parse_string(b)
  191     if t and t:lower() == 'message' and s and s:lower() == 'rfc822' then
  192         return _parse_message(b)
  193     else
  194         b.i = i
  195         return _parse_basic(b)
  196     end
  197 end
  198 
  199 function _parse_basic(b)
  200     local bp = {}
  201     local s
  202 
  203     s = _parse_string(b)
  204     if not s then return end
  205     bp['type'] = s
  206 
  207     _parse_space(b)
  208 
  209     s = _parse_string(b)
  210     if not s then return end
  211     bp['type'] = bp['type'] .. '/' .. s
  212 
  213     _parse_space(b)
  214 
  215     s = _parse_param(b, 'name')
  216     if s then bp['name'] = s end
  217 
  218     _parse_space(b)
  219     _parse_nstring(b)
  220     _parse_space(b)
  221     _parse_nstring(b)
  222     _parse_space(b)
  223     _parse_string(b)
  224     _parse_space(b)
  225     bp['size'] = _parse_number(b)
  226     if bp['type']:sub(1, 5):lower() == 'text/' then
  227         _parse_space(b)
  228         _parse_number(b)
  229     end
  230     if _parse_space(b) then _parse_nstring(b) end
  231     if _parse_space(b) then
  232         s = _parse_dsp(b)
  233         if s then bp['name'] = s end
  234     end
  235     if _parse_space(b) then _parse_lang(b) end
  236     if _parse_space(b) then _parse_nstring(b) end
  237     while _parse_space(b) and b.i <= #b.s do _parse_extension(b) end
  238 
  239     return bp
  240 end
  241 
  242 function _parse_mpart(b)
  243     local bp = {}
  244     local i = 1
  245     local s
  246 
  247     bp['type'] = 'multipart'
  248 
  249     while _parse_lpar(b, true) and b.i <= #b.s do
  250         bp[i] = _parse_body(b)
  251         i = i + 1
  252     end
  253 
  254     _parse_space(b)
  255 
  256     s = _parse_string(b)
  257     if not s then return end
  258     bp['type'] = bp['type'] .. '/' .. s
  259 
  260     if _parse_space(b) then
  261         s = _parse_param(b, 'name')
  262         if s then bp['name'] = s end
  263     end
  264     if _parse_space(b) then
  265         s = _parse_dsp(b)
  266         if s then bp['name'] = s end
  267     end
  268     if _parse_space(b) then _parse_lang(b) end
  269     if _parse_space(b) then _parse_nstring(b) end
  270     while _parse_space(b) and b.i < #b.s do _parse_extension(b) end
  271 
  272     return bp
  273 end
  274 
  275 function _parse_message(b)
  276     local bp = {}
  277     local s
  278 
  279     bp['type'] = 'message/rfc822'
  280 
  281     _parse_space(b)
  282 
  283     s = _parse_param(b, 'name')
  284     if s then bp['name'] = s end
  285 
  286     _parse_space(b)
  287     _parse_nstring(b)
  288     _parse_space(b)
  289     _parse_nstring(b)
  290     _parse_space(b)
  291     _parse_string(b)
  292     _parse_space(b)
  293     bp['size'] = _parse_number(b)
  294 
  295     _parse_space(b)
  296     _parse_envelope(b)
  297 
  298     _parse_space(b)
  299     local p = _parse_body(b)
  300     if not p then return end
  301     if #p == 0 then
  302         bp[1] = p
  303     else
  304         for k, v in pairs(p) do
  305             if type(k) == 'number' then
  306                 bp[k] = v
  307             end
  308         end
  309     end
  310 
  311     _parse_space(b)
  312     _parse_number(b)
  313 
  314     if _parse_space(b) then _parse_nstring(b) end
  315     if _parse_space(b) then
  316         s = _parse_dsp(b)
  317         if s then bp['name'] = s end
  318     end
  319     if _parse_space(b) then _parse_lang(b) end
  320     if _parse_space(b) then _parse_nstring(b) end
  321     while _parse_space(b) and b.i <= #b.s do _parse_extension(b) end
  322 
  323     return bp
  324 end
  325 
  326 function _parse_envelope(b)
  327     _parse_lpar(b)
  328     _parse_nstring(b)
  329     _parse_space(b)
  330     _parse_nstring(b)
  331     _parse_space(b)
  332     _parse_address(b)
  333     _parse_space(b)
  334     _parse_address(b)
  335     _parse_space(b)
  336     _parse_address(b)
  337     _parse_space(b)
  338     _parse_address(b)
  339     _parse_space(b)
  340     _parse_address(b)
  341     _parse_space(b)
  342     _parse_address(b)
  343     _parse_space(b)
  344     _parse_nstring(b)
  345     _parse_space(b)
  346     _parse_nstring(b)
  347     _parse_rpar(b)
  348 end
  349 
  350 function _parse_address(b)
  351     if _parse_lpar(b) then
  352         while _parse_lpar(b) and b.i <= #b.s do
  353             _parse_nstring(b)
  354             _parse_space(b)
  355             _parse_nstring(b)
  356             _parse_space(b)
  357             _parse_nstring(b)
  358             _parse_space(b)
  359             _parse_nstring(b)
  360             _parse_rpar(b)
  361         end
  362         _parse_rpar(b)
  363     elseif _parse_nil(b) then
  364     end
  365 end
  366 
  367 function _parse_lang(b)
  368     if _parse_lpar(b) then
  369         local lang = {}
  370         repeat
  371             table.insert(lang, _parse_string(b))
  372         until not _parse_space(b) or b.i > #b.s
  373         _parse_rpar(b)
  374         return lang
  375     else
  376         return _parse_nstring(b)
  377     end
  378 end
  379 
  380 function _parse_dsp(b)
  381     local r
  382     if _parse_lpar(b) then
  383         _parse_string(b)
  384         _parse_space(b)
  385         r = _parse_param(b, 'filename')
  386         _parse_rpar(b)
  387     elseif _parse_nil(b) then
  388     end
  389     return r
  390 end
  391 
  392 function _parse_param(b, key)
  393     local r
  394     if _parse_lpar(b) then
  395         repeat
  396             local s = _parse_string(b)
  397             _parse_space(b)
  398             if s and s:lower() == key then
  399                 r = _parse_string(b)
  400             else
  401                 _parse_string(b)
  402             end
  403         until not _parse_space(b) or b.i > #b.s
  404         _parse_rpar(b)
  405     elseif _parse_nil(b) then
  406     end
  407     return r
  408 end
  409 
  410 function _parse_extension(b)
  411     if _parse_nstring(b) then
  412     elseif _parse_number(b) then
  413     elseif _parse_lpar(b) then
  414         _parse_extension(b)
  415         while _parse_space(b) and b.i <= #b.s do
  416             _parse_extension(b)
  417         end
  418         _parse_rpar(b)
  419     else
  420     end
  421 end
  422 
  423 function _parse_space(b, peek)
  424     if b.s:sub(b.i, b.i) == ' ' then
  425         if not peek then b.i = b.i + 1 end
  426         return true
  427     else
  428         return false
  429     end
  430 end
  431 
  432 function _parse_lpar(b, peek)
  433     if b.s:sub(b.i, b.i) == '(' then
  434         if not peek then b.i = b.i + 1 end
  435         return true
  436     else
  437         return false
  438     end
  439 end
  440 
  441 function _parse_rpar(b, peek)
  442     if b.s:sub(b.i, b.i) == ')' then
  443         if not peek then b.i = b.i + 1 end
  444         return true
  445     else
  446         return false
  447     end
  448 end
  449 
  450 function _parse_nil(b)
  451     if b.s:sub(b.i, b.i + 2):upper() == 'NIL' then
  452         b.i = b.i + 3
  453         return true
  454     else
  455         return false
  456     end
  457 end
  458 
  459 function _parse_string(b)
  460     local i = b.i
  461 
  462     if b.s:sub(i, i) == '"' then
  463         i = i + 1
  464     else return end
  465 
  466     local j = i
  467     local n = 0
  468     while true do
  469         n = b.s:find('"', i + n)
  470         if not n then return end
  471         if b.s:sub(n - 1, n - 1) ~= '\\' then
  472             i = n + 1
  473             b.i = i
  474             return b.s:sub(j, n - 1)
  475         else return end
  476     end
  477 end
  478 
  479 function _parse_nstring(b)
  480     local i = b.i
  481 
  482     if b.s:sub(i, i) == '"' then
  483         i = i + 1
  484     elseif _parse_nil(b) then
  485         return 'NIL'
  486     else return end
  487 
  488     local j = i
  489     local n = 0
  490     while true do
  491         n = b.s:find('"', i + n)
  492         if not n then return end
  493         if b.s:sub(n - 1, n - 1) ~= '\\' then
  494             i = n + 1
  495             b.i = i
  496             return b.s:sub(j, n - 1)
  497         else return end
  498     end
  499 end
  500 
  501 function _parse_number(b)
  502     local j = b.i
  503     local n = b.s:find('[^0-9]', b.i)
  504     if not n then return end
  505     b.i = n
  506     return tonumber(b.s:sub(j, n - 1))
  507 end