Changeset 4353

Show
Ignore:
Timestamp:
03/21/09 05:36:08 (4 years ago)
Author:
jow
Message:

applications/luci-asterisk: rework dialplan management

Location:
luci/trunk/applications/luci-asterisk
Files:
1 added
5 modified

Legend:

Unmodified
Added
Removed
  • luci/trunk/applications/luci-asterisk/luasrc/asterisk.lua

    r4319 r4353  
    2525AST_FLAGS = "-r -x" 
    2626 
     27 
     28--- LuCI Asterisk - Resync uci context 
     29function uci_resync() 
     30    uci = luci.model.uci.cursor() 
     31end 
    2732 
    2833--- LuCI Asterisk io interface 
     
    319324    return hash 
    320325end 
     326 
     327 
     328--- LuCI Asterisk - Dialplan 
     329-- @type    module 
     330dialplan = luci.util.class() 
     331 
     332--- Parse a dialplan section 
     333-- @param plan  Table containing the plan info 
     334-- @return      Table with parsed information 
     335function dialplan.parse(z) 
     336    if z['.name'] then 
     337        local plan = { 
     338            zones       = { }, 
     339            name        = z['.name'], 
     340            description = z.description or z['.name'] 
     341        } 
     342 
     343        for _, name in ipairs(tools.parse_list(z.include)) do 
     344            local zone = dialzone.zone(name) 
     345            if zone then 
     346                plan.zones[#plan.zones+1] = zone 
     347            end 
     348        end 
     349 
     350        return plan 
     351    end 
     352end 
     353 
     354--- Get a list of known dial plans 
     355-- @return      Associative table of plans and table of plan names 
     356function dialplan.plans() 
     357    local plans  = { } 
     358    local pnames = { } 
     359    uci:foreach("asterisk", "dialplan", 
     360        function(p) 
     361            plans[p['.name']] = dialplan.parse(p) 
     362            pnames[#pnames+1] = p['.name'] 
     363        end) 
     364    return plans, pnames 
     365end 
     366 
     367--- Get a specific dial plan 
     368-- @param name  Name of the dial plan 
     369-- @return      Table containing plan information 
     370function dialplan.plan(n) 
     371    local plan 
     372    uci:foreach("asterisk", "dialplan", 
     373        function(p) 
     374            if p['.name'] == n then 
     375                plan = dialplan.parse(p) 
     376            end 
     377        end) 
     378    return plan 
     379end 
  • luci/trunk/applications/luci-asterisk/luasrc/controller/asterisk.lua

    r4319 r4353  
    4141 
    4242 
    43     entry({"admin", "asterisk"},                        cbi("asterisk/main"),        "Asterisk",  99).i18n = "asterisk" 
     43    entry({"admin", "asterisk"},                        cbi("asterisk/main"),           "Asterisk",  99).i18n = "asterisk" 
    4444 
    45     entry({"admin", "asterisk", "phones"},              cbi("asterisk/phones"),      "Phones",       1) 
    46     entry({"admin", "asterisk", "phones", "sip"},       cbi("asterisk/phone_sip"),   nil,            1).leaf = true 
    47     --entry({"admin", "asterisk", "phones", "exten"},   cbi("asterisk/phone_exten"), "Extensions",   2).leaf = true 
     45    entry({"admin", "asterisk", "phones"},              cbi("asterisk/phones"),         "Phones",       1) 
     46    entry({"admin", "asterisk", "phones", "sip"},       cbi("asterisk/phone_sip"),      nil,            1).leaf = true 
     47    --entry({"admin", "asterisk", "phones", "exten"},   cbi("asterisk/phone_exten"),    "Extensions",   2).leaf = true 
    4848 
    49     entry({"admin", "asterisk", "trunks"},              cbi("asterisk/trunks"),      "Trunks",       2) 
    50     entry({"admin", "asterisk", "trunks", "sip"},       cbi("asterisk/trunk_sip"),   nil,            1).leaf = true 
     49    entry({"admin", "asterisk", "trunks"},              cbi("asterisk/trunks"),         "Trunks",       2) 
     50    entry({"admin", "asterisk", "trunks", "sip"},       cbi("asterisk/trunk_sip"),      nil,            1).leaf = true 
    5151 
    52     --entry({"admin", "asterisk", "dialplans"},         cbi("asterisk/dialplans"),   "Call Routing", 3) 
    53     entry({"admin", "asterisk", "dialplans"},           call("handle_dialplan"),     "Call Routing", 3) 
    54     entry({"admin", "asterisk", "dialplans", "out"},    cbi("asterisk/dialplan_out"),     nil,            1).leaf = true 
    55     entry({"admin", "asterisk", "dialplans", "zones"},  cbi("asterisk/dialzones"),      "Dial Zones",   2).leaf = true 
     52    --entry({"admin", "asterisk", "dialplans"},         cbi("asterisk/dialplans"),      "Call Routing", 3) 
     53    entry({"admin", "asterisk", "dialplans"},           call("handle_dialplan"),        "Call Routing", 3) 
     54    entry({"admin", "asterisk", "dialplans", "out"},    cbi("asterisk/dialplan_out"),   nil,            1).leaf = true 
     55    entry({"admin", "asterisk", "dialplans", "zones"},  call("handle_dialzones"),       "Dial Zones",   2).leaf = true 
    5656 
    5757end 
     
    6060function handle_dialplan() 
    6161    local uci = luci.model.uci.cursor() 
     62    local ast = require "luci.asterisk" 
     63    local err = false 
    6264 
    63     if luci.http.formvalue("delete") then 
    64         local del = luci.http.formvalue("delete") 
    65         if #del > 0 and not del:match("[^a-zA-Z0-9_]") then 
    66             uci:delete("asterisk", del) 
    67             uci:foreach("asterisk", "dialplan", 
    68                 function(s) 
    69                     if s.include then 
    70                         local inc = type(s.include) == "table" and s.include or 
    71                             luci.util.split(s.include, "%s+", nil, true) 
     65    for k, v in pairs(luci.http.formvaluetable("delzone")) do 
     66        local plan = ast.dialplan.plan(k) 
     67        if #v > 0 and plan then 
     68            local newinc = { } 
    7269 
    73                         local inc2 = { } 
    74                         for _, v in ipairs(inc) do 
    75                             if v ~= del then 
    76                                 inc2[#inc2+1] = v 
    77                             end 
    78                         end 
     70            for _, z in ipairs(plan.zones) do 
     71                if z.name ~= v then 
     72                    newinc[#newinc+1] = z.name 
     73                end 
     74            end 
    7975 
    80                         uci:set("asterisk", s['.name'], "include", inc2) 
    81                     end 
    82                 end) 
     76            uci:delete("asterisk", plan.name, "include") 
     77 
     78            if #newinc > 0 then 
     79                uci:set("asterisk", plan.name, "include", newinc) 
     80            end 
    8381 
    8482            uci:save("asterisk") 
    85             uci:commit("asterisk") 
    8683        end 
    8784    end 
    8885 
    89     for k, v in pairs(luci.http.formvaluetable("create_entry")) do 
    90         if #v > 0 and not v:match("[^a-zA-Z0-9_]") then 
    91             uci:section("asterisk", "dialzone", v, { 
    92                 context = k 
    93             } ) 
     86    for k, v in pairs(luci.http.formvaluetable("addzone")) do 
     87        local plan = ast.dialplan.plan(k) 
     88        local zone = ast.dialzone.zone(v) 
     89        if #v > 0 and plan and zone then 
     90            local newinc = { zone.name } 
    9491 
    95             local inc = uci:get("asterisk", k, "include") 
    96             inc = type(inc) == "table" and inc or 
    97                 type(inc) == "string" and #inc > 0 and 
    98                     luci.util.split(inc, "%s+", nil, true) or { } 
     92            for _, z in ipairs(plan.zones) do 
     93                newinc[#newinc+1] = z.name 
     94            end 
    9995 
    100             inc[#inc+1] = v 
     96            uci:delete("asterisk", plan.name, "include") 
    10197 
    102             uci:set("asterisk", k, "include", inc) 
     98            if #newinc > 0 then 
     99                uci:set("asterisk", plan.name, "include", newinc) 
     100            end 
     101 
    103102            uci:save("asterisk") 
    104             uci:commit("asterisk") 
    105  
    106             luci.http.redirect(luci.dispatcher.build_url( 
    107                 "asterisk", "dialplans", "out", v 
    108             )) 
    109  
    110             return 
    111103        end 
    112104    end 
    113105 
    114     luci.template.render("asterisk/dialplans") 
     106    local aname = luci.http.formvalue("addplan") 
     107    if aname and #aname > 0 then 
     108        if aname:match("^[a-zA-Z0-9_]+$") then 
     109            uci:section("asterisk", "dialplan", aname, { }) 
     110            uci:save("asterisk") 
     111        else 
     112            err = true 
     113        end 
     114    end 
     115 
     116    local dname = luci.http.formvalue("delplan") 
     117    if dname and #dname > 0 then 
     118        if uci:get("asterisk", dname) == "dialplan" then 
     119            uci:delete("asterisk", dname) 
     120            uci:save("asterisk") 
     121        end 
     122    end 
     123 
     124    ast.uci_resync() 
     125    luci.template.render("asterisk/dialplans", { create_error = err }) 
    115126end 
     127 
     128function handle_dialzones() 
     129    local ast = require "luci.asterisk" 
     130    local uci = luci.model.uci.cursor() 
     131    local err = false 
     132 
     133    if luci.http.formvalue("newzone") then 
     134        local name = luci.http.formvalue("newzone_name") 
     135        if name and name:match("^[a-zA-Z0-9_]+$") then 
     136            uci:section("asterisk", "dialzone", name, { 
     137                uses  = ast.tools.parse_list(luci.http.formvalue("newzone_uses") or {}), 
     138                match = ast.tools.parse_list(luci.http.formvalue("newzone_match") or {}) 
     139            }) 
     140            uci:save("asterisk") 
     141        else 
     142            err = true 
     143        end 
     144    end 
     145 
     146    if luci.http.formvalue("delzone") then 
     147        local name = luci.http.formvalue("delzone") 
     148        if uci:get("asterisk", name) == "dialzone" then 
     149            uci:delete("asterisk", name) 
     150            uci:save("asterisk") 
     151        end 
     152    end 
     153 
     154    luci.template.render("asterisk/dialzones", { create_error = err }) 
     155end 
  • luci/trunk/applications/luci-asterisk/luasrc/model/cbi/asterisk/dialplan_out.lua

    r4274 r4353  
    115115    intl = entry:option(DynamicList, "international", "Intl. prefix matches (optional)") 
    116116 
    117     trunk = entry:option(ListValue, "uses", "Used trunk") 
     117    trunk = entry:option(MultiValue, "uses", "Used trunk") 
    118118    for _, v in ipairs(find_trunks(cbimap.uci)) do 
    119119        trunk:value(unpack(v)) 
  • luci/trunk/applications/luci-asterisk/luasrc/view/asterisk/dialplans.htm

    r4274 r4353  
    1818<% 
    1919    local uci = luci.model.uci.cursor_state() 
     20    local ast = require "luci.asterisk" 
    2021 
    21     function find_rules(plan) 
    22         local r = { } 
    23         if plan and plan.include then 
    24             local i = luci.util.split(plan.include, "%s+", nil, true) 
    25             for _, i in ipairs(i) do 
    26                 i = uci:get("asterisk", "dialzone", i) 
    27                 if i then 
    28                     r[#r+1] = i 
    29                 end 
    30             end 
    31         end 
    32         return r 
    33     end 
    34  
    35     dp_lookup_table = { } 
    36  
    37     function dialplan_lookup(s) 
    38         if not dp_lookup_table[s['.name']] then 
    39             s.childs  = { } 
    40             s.matches = type(s.match) == "table" and s.match or { s.match } 
    41             s.name, s.type = s['.name'], s['.type'] 
    42             s['.name'], s['.type'] = nil, nil 
    43             dp_lookup_table[s.name] = s 
    44         end 
    45     end 
    46  
    47     uci:foreach("asterisk", "dialplan", dialplan_lookup) 
    48     uci:foreach("asterisk", "dialzone", dialplan_lookup) 
    49  
    50     for k, p in pairs(dp_lookup_table) do 
    51         if p.include then 
    52             local i = type(p.include) == "string" 
    53                 and luci.util.split(p.include, "%s+", nil, true) or p.include 
    54  
    55             for _, i in ipairs(i) do 
    56                 i = dp_lookup_table[i] 
    57                 if i then 
    58                     p.childs[#p.childs+1] = i 
    59                     i.parent = p 
    60                 end 
    61             end 
    62         end 
    63     end 
    64  
    65     function digit_pattern(s) 
    66         return "<code style='padding: 2px; border:1px solid #CCCCCC; background-color: #FFFFFF'>%s</code>" % s 
     22    function digit_pattern(s,t) 
     23        return "<code style='padding: 2px; border:1px solid #CCCCCC; background-color: #FFFFFF'%s>%s</code>" 
     24            %{ t and " title='" .. t .. "'" or "", s } 
    6725    end 
    6826 
     
    7331    end 
    7432 
    75     function link_trunks(s) 
    76         local l = { } 
    77         for s in s:gmatch("(%S+)") do 
    78             if s:match("^[sS][iI][pP]/") then 
    79                 l[#l+1] = '<a href="%s">%s</a>' %{ 
    80                     luci.dispatcher.build_url("admin", "asterisk", "trunks", 
    81                         "sip", (s:gsub("^.+/",""))), 
    82                     (s:gsub("^.+/","SIP: ")) 
    83                 } 
     33    function format_matches(z) 
     34        local html = { } 
     35 
     36        if z.localprefix then 
     37            for _, m in ipairs(z.matches) do 
     38                html[#html+1] = 
     39                    digit_pattern(z.localprefix, "local prefix") .. " " .. 
     40                    digit_pattern(m) 
    8441            end 
    8542        end 
    86         return '<small>%s</small>' % table.concat(l, ", ") 
     43 
     44        if #z.intlmatches > 0 then 
     45            for _, i in ipairs(z.intlmatches) do 
     46                for _, m in ipairs(z.matches) do 
     47                    html[#html+1] = "%s %s" %{ 
     48                        digit_pattern("(%s)" % i, "intl. prefix"), 
     49                        digit_pattern(m) 
     50                    } 
     51                end 
     52            end 
     53        else 
     54            for _, m in ipairs(z.matches) do 
     55                html[#html+1] = digit_pattern(m) 
     56            end 
     57        end 
     58 
     59        return table.concat(html, "; ") 
    8760    end 
    8861%> 
     
    10174<fieldset class="cbi-section" id="cbi-asterisk-sip"> 
    10275    <!--<legend>Dialplans</legend>--> 
    103     <div class="cbi-section-descr"></div> 
     76    <div class="cbi-section-descr"> 
     77        Here you can manage your dial plans which are used to route outgoing calls from your local extensions. 
     78    </div> 
    10479 
    105  
    106  
    107  
    108  
    109     <% for name, plan in luci.util.kspairs(dp_lookup_table) do 
    110         if plan.type == "dialplan" then %> 
     80    <% for i, plan in pairs(ast.dialplan.plans()) do %> 
    11181    <div class="cbi-section-node"> 
    11282        <table class="cbi-section-table"> 
    11383            <tr class="cbi-section-table-titles"> 
    114                 <th style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="5"> 
    115                     <big>&nbsp;Dialplan <em><%=name%></em></big> 
     84                <th style="text-align: left; padding: 3px" class="cbi-section-table-cell"> 
     85                    <big>Dialplan <em><%=plan.name%></em></big> 
    11686                </th> 
    117             </tr> 
    118  
    119             <tr class="cbi-section-table-descr"> 
    120                 <th style="width: 5%; text-align:right" class="cbi-section-table-cell">Prepend</th> 
    121                 <th style="width: 20%; text-align:left" class="cbi-section-table-cell">- Match</th> 
    122                 <th style="text-align:left" class="cbi-section-table-cell">Trunk</th> 
    123                 <th style="width: 40%; text-align:left" class="cbi-section-table-cell">Description</th> 
    124                 <th style="width: 4%; text-align:left" class="cbi-section-table-cell"></th> 
    125             </tr> 
    126  
    127             <% for i, rule in pairs(plan.childs) do 
    128                 if rule.type == "dialzone" then %> 
    129             <tr class="cbi-section-table-row <%=rowstyle(i)%>"> 
    130                 <td style="text-align:right" class="cbi-value-field"> 
    131                     <% for _ in ipairs(rule.matches) do %> 
    132                         <%=rule.addprefix and digit_pattern(rule.addprefix)%>&nbsp;<br /> 
    133                     <% end %> 
    134                 </td> 
    135                 <td style="text-align:left" class="cbi-value-field"> 
    136                     <% for _, m in ipairs(rule.matches) do %> 
    137                         <%=rule.localprefix and "%s " % digit_pattern(rule.localprefix)%> 
    138                         <%=digit_pattern(m)%><br /> 
    139                     <% end %> 
    140                 </td> 
    141                 <td style="text-align:left" class="cbi-value-field"> 
    142                     <%=rule.uses and link_trunks(rule.uses)%> 
    143                 </td> 
    144                 <td style="text-align:left" class="cbi-value-field"> 
    145                     <%=rule.description or rule.name%> 
    146                 </td> 
    147                 <td style="text-align:left" class="cbi-value-field"> 
    148                     <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans', 'out', rule.name)%>"> 
    149                         <img style="border:none" alt="Edit entry" title="Edit entry" src="/luci-static/resources/cbi/edit.gif" /> 
    150                     </a> 
    151                     <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delete=<%=rule.name%>"> 
    152                         <img style="border:none" alt="Delete entry" title="Delete entry" src="/luci-static/resources/cbi/remove.gif" /> 
     87                <td> 
     88                    <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delplan=<%=plan.name%>"> 
     89                        <img style="border:none" alt="Remove this dialplan" title="Remove this dialplan" src="/luci-static/resources/cbi/remove.gif" /> 
    15390                    </a> 
    15491                </td> 
    15592            </tr> 
    156             <% end end %> 
     93 
     94            <!-- dialzones --> 
     95            <% local zones_used = { } %> 
     96            <% for i, zone in ipairs(plan.zones) do zones_used[zone.name] = true %> 
     97            <tr class="cbi-section-table-row <%=rowstyle(i)%>"> 
     98                <td style="text-align: left; padding: 3px" class="cbi-section-table-cell"> 
     99                    <strong>&#x2514; Dialzone <em><%=zone.name%></em></strong> 
     100                    <p style="padding-left: 1em; margin-bottom:0"> 
     101                        Description: <%=zone.description%><br /> 
     102                        Lines: 
     103                        <%=ast.tools.hyperlinks( 
     104                            zone.trunks, function(v) 
     105                                return luci.dispatcher.build_url("admin", "asterisk", "trunks", "%s") % v:lower() 
     106                            end 
     107                        )%><br /> 
     108                        Matches: 
     109                        <%=format_matches(zone)%> 
     110                    </p> 
     111                </td> 
     112                <td style="width:5%" class="cbi-value-field"> 
     113                    <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans', 'out', zone.name)%>"> 
     114                        <img style="border:none" alt="Edit dialzone" title="Edit dialzone" src="/luci-static/resources/cbi/edit.gif" /> 
     115                    </a> 
     116                    <a href="<%=luci.dispatcher.build_url('admin', 'asterisk', 'dialplans')%>?delzone.<%=plan.name%>=<%=zone.name%>"> 
     117                        <img style="border:none" alt="Remove from this dialplan" title="Remove from this dialplan" src="/luci-static/resources/cbi/remove.gif" /> 
     118                    </a> 
     119                </td> 
     120            </tr> 
     121            <% end %> 
     122 
     123            <tr class="cbi-section-table-row"> 
     124                <td style="text-align: left; padding: 3px" class="cbi-section-table-cell" colspan="2"> 
     125                    <hr style="margin-bottom:0.5em; border-width:0 0 1px 0" /> 
     126                    <select style="width:30%" name="addzone.<%=plan.name%>"> 
     127                        <option value="">-- Add dialzone --</option> 
     128                        <% for _, zone in pairs(ast.dialzone.zones()) do %> 
     129                            <% if not zones_used[zone.name] then %> 
     130                                <option value="<%=zone.name%>"><%=zone.name%> (<%=zone.description%>)</option> 
     131                            <% end %> 
     132                        <% end %> 
     133                    </select> 
     134                    <input type="submit" class="cbi-button cbi-button-add" value=" &raquo; " title="Add Zone ..."/> 
     135                    &nbsp; &nbsp; 
     136                    <a href="<%=luci.dispatcher.build_url('admin/asterisk/dialplans/zones')%>" class="cbi-title-ref">Manage dialzones</a> 
     137                </td> 
     138            </tr> 
     139            <!-- /dialzones --> 
     140 
    157141        </table> 
    158142 
    159         <div class="cbi-section-create cbi-tblsection-create"> 
    160             <input type="text" class="cbi-section-create-name" name="create_entry.<%=name%>"/> 
    161             <input type="submit" class="cbi-button cbi-button-add" value="Add entry" title="Add entry"/> 
    162         </div> 
     143        <div class="cbi-section-create cbi-tblsection-create"></div> 
    163144    </div> 
    164145    <br /> 
    165     <% end end %> 
     146    <% end %> 
     147 
     148        <div class="cbi-section-node"> 
     149            <div class="cbi-section-create cbi-tblsection-create" style="padding: 3px"> 
     150                <h3>Create a new dialplan</h3> 
     151                The name is required and must be unique. It may only contain the characters A-Z, a-z, 0-9 and _ .<br /> 
     152 
     153                <%- if create_error then %> 
     154                    <br /><span style="color:red">Invalid name given!</span><br /> 
     155                <% end -%> 
     156 
     157                <br /> 
     158                <input type="text" class="cbi-section-create-name" name="addplan" style="width:200px" /> 
     159                <input type="submit" class="cbi-button cbi-button-add" value="Add dialplan" title="Add dialplan"/> 
     160            </div> 
     161        </div> 
    166162 
    167163    </fieldset> 
  • luci/trunk/applications/luci-asterisk/root/etc/config/asterisk

    r3620 r4353  
    7676 
    7777config 'sip' 'providerphone' 
     78    option 'provider' 'yes' 
    7879    option 'type' 'friend' 
    7980    option 'timeout' '55' 
     
    189190 
    190191config 'dialzone' 'mobile' 
    191     option 'uses' 'SIP/iinetphone' 
     192    option 'uses' 'SIP/providerphone' 
    192193    option 'match' '04XXXXXXXX' 
    193194    option 'localprefix' '0'