FrenchYeti/dexcalibur

View on GitHub
inspectors/ApplicationTopography/web/service.html

Summary

Maintainability
Test Coverage
<!DOCTYPE html>
<html lang="en">

<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <title>Dexcalibur - Service</title>

    <!-- styles -->
    <!--## pages/inc/tpl_css.html ##-->




    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
    <!--[if lt IE 9]>
        <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
        <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->

</head>

<body class="dxc-dark">


        <!-- Navigation -->
        <!--## pages/inc/menu.html ##-->

        <div id="page-wrapper" class="dxc-dark">
            

            <div class="row">
                <div class="col-lg-12">
                    <h1 class="page-header"><span class="text-info">Service&nbsp;:&nbsp;</span><span id="service-name"></span></h1>
                </div>
                <!-- /.col-lg-12 -->
            </div>
            
            <div class="row"><div class="col-lg-12" id="alertcontainer"></div></div>

            <div class="row">
                <div class="col-lg-5  dxc-detail-body-sm">
                    <div class="card">
                        <div class="btn-group">
                            <a class="btn btn-primary seeClass" href="" id="dxc-detail-impl"><span class="fa fa-eye"></span>&nbsp;Class</a>
                            <!--<a class="btn btn-danger startActivity" href=""><span class="fa fa-play"></span>&nbsp;Send intent</a>--> 
                        </div>
                        <div class="card-body" style="padding:0px" id="dxc-detail-attr-tab">
                        </div>
                    </div>
                    <div class="card">
                        <h5 class="card-header"> Intent Filters
                            </h5>
                            <div class="card-body" style="padding:0px">
                                <table width="100%" class="table table-striped table-bordered overflow-auto" style="margin-bottom:0px;overflow:scroll" id="dxc-detail-intent-tab">
                                    <thead>
                                        <th width="50%">Categories</th>
                                        <th width="50%">Action</th>
                                    </thead>
                                    <tbody></tbody>
                                </table>
                            </div>
                    </div>
                </div>
                <div class="col-lg-7">
                        <div class="card">
                            <div class="card-header" style="font-size:1.2em">
                                Android internals methods called
                            </div>
                            <div class="card-body" style="padding:0px">
                                <p></p>
                                <table width="100%" class="table table-striped table-bordered" style="margin-bottom: 0px" id="dxc-detail-intern-tab">
                                    <thead>
                                        <th>Class</th>
                                        <th>Method</th>
                                    </thead>
                                    <tbody><!--
                                        <tr><td class="col-lg-8" >DexClassLoader.load</td><td class="col-lg-4 col-threat-score" style="color:orange">3/5</td></tr>
                                        <tr><td class="col-lg-8" >Runtime.exec</td><td class="col-lg-4 col-threat-score" style="color: orangered">5/5</td></tr>
                                    --></tbody>
                                </table>
                            </div>
                        </div>
                </div>
            </div>
            


            
            <div class="modal fade" id="confIntentModal" tabindex="-1" role="dialog" aria-labelledby="confIntentModalLabel" aria-hidden="true">
                    <div class="modal-dialog" role="document">
                      <div class="modal-content">
                            <div class="modal-header">
                              <h3 class="modal-title">Intent configuration</h3>
                            </div>
                        <div class="modal-body">
                            <p>This intent filter has multiple categories and/or actions. So, please select intent parameters.</p>

                            <div class="input-group mb-3" id="confCatListSection">
                                <div class="input-group-prepend">
                                    <span class="input-group-text" id="confCatIntentLabel">Categories</span>
                                </div>
                                <select id="confCatList" class="form-control" aria-label="Small" aria-describedby="confCatIntentLabel"></select>
                            </div>


                            <div class="input-group mb-3" id="confActListSection">
                                <div class="input-group-prepend">
                                    <span class="input-group-text" id="confActIntentLabel">Actions</span>
                                </div>
                                <select id="confActList" class="form-control" aria-label="Small" aria-describedby="confActIntentLabel"></select>
                            </div>

                            <p>
                                You can specify extra options passed "as is" to 'am' command, such as start activity options or intent arguments. 
                            </p>

                            <div class="input-group input-group mb-3">
                                <div class="input-group-prepend">
                                    <span class="input-group-text" id="confEOIntentLabel">Extra Options</span>
                                </div>
                                <input type="text" value="" id="confExtraOpts" class="form-control" aria-label="Small" aria-describedby="confEOIntentLabel">
                            </div>


                            <input type="hidden" id="confIntentId" value="">
                            <input type="hidden" id="confDataUri" value="">
                            <input type="hidden" id="confMime" value="">
                      </div>
                        <div class="modal-footer">
                          <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>&nbsp;
                          <button type="button" class="btn btn-primary" id="sendIntentCustom">Send</button>
                        </div>
                      </div>
                    </div>
                  </div>
           


        </div>
        <!-- /#page-wrapper -->
    


    <!--## pages/inc/tpl_js_end.html ##-->

   <!--<script src="/js/wexcalibur.js"></script> -->
    <script>

let TAGS_COLOR = {
        MAIN: "success",
        BROWSABLE: "danger",
        EXPOSED: "danger",
        BOOT_COMPLETED: "purple",
        SMS: "info",
        PHONE: "info"
    };

    function htmlEncode(txt){
        return $('<div />').text(txt).html();
    }
  function renderIntentModal(pIntentConfig, pDataUri, pMime){

        //$("#confIntentModal")

        tpl = {cat:'', action:'', browser:null, data:'', uri:''};

        console.log(pIntentConfig);

        // init
        $("#confCatList").empty();
        $("#confActList").empty();
        $("#confDataUri").empty();
        $("#confMime").empty();
        $("#confIntentId").attr('value',pIntentConfig.__id);

        // fill
        if(pIntentConfig.category.length > 1){
            $("#confCatListSection").css('visibility','visible');
            pIntentConfig.category.map((x,i) => {
                $("#confCatList").append(`<option value="${x.name}">${DexcaliburAPI.ui.htmlEncode(x.name)}</option>`);
            });
        }else{
            $("#confCatListSection").css("visibility",'hidden');
        }

        if(pIntentConfig.action.length > 1){
            $("#confActListSection").css('visibility','visible');
            pIntentConfig.action.map((x,i) => {
                $("#confActList").append(`<option value="${x.name}">${DexcaliburAPI.ui.htmlEncode(x.name)}</option>`);
            });
        }else{
            $("#confActListSection").css("visibility",'hidden');
        }

        console.log(pDataUri,pMime);
        if(pDataUri != null){
            $("#confDataUri").attr('value',pDataUri);
        }
        if(pMime != null){
            $("#confMime").attr('value',pMime);
        }

        $("#confIntentModal").modal();
    }

    function render(data){
        // act-detail-tag
        let tpl = {};

        $("#service-name").html(
            data.name
        );


        $("#dxc-detail-title").html(
            DexcaliburAPI.ui.htmlEncode(data.name)
        );

        // tags
        let tags = "";
        if((data.__tag instanceof Array) && (data.__tag.length > 0)){
           data.__tag.map(t => {
                if(TAGS_COLOR[t] != null)
                    tags += DexcaliburAPI.ui.badge.make(TAGS_COLOR[t],t);
                else
                    tags += DexcaliburAPI.ui.badge.make('info',t);
            });
        }

        // impl
        $("#dxc-detail-impl").attr(
            "href",
            "/pages/finder.html?class="+btoa(encodeURIComponent(data.__impl))
        );

       

        // attributes
        $("#dxc-detail-attr-tab").empty();
        $("#dxc-detail-attr-tab").append("<div class='row'><div class='col-lg-4'>Tags</div><div class='col-lg-8'>"+DexcaliburAPI.ui.htmlEncode(tags)+"</div></div>");
        
        for(let i in data.attr){
            $("#dxc-detail-attr-tab").append("<div class='row'><div class='col-lg-4'>"
                +DexcaliburAPI.ui.htmlEncode(i)+"</div><div class='col-lg-8'>"+DexcaliburAPI.ui.htmlEncode(data.attr[i])+"</div></div>");
        }

        // intent
        $("#dxc-detail-intent-tab > tbody").empty();
        
        if(data.intentFilters.length > 0){
            for(let i=0; i<data.intentFilters.length; i++){
                
                intent = data.intentFilters[i];
                tpl = {cat:'', action:'', browser:null, data:'', uri:''};

                intent.category.map((x,i) => {
                    if(i>0) tpl.cat += "<br>";
                    if(x.name.endsWith(".BROWSABLE")){
                        tpl.browser = 'test';
                    }
                    tpl.cat += DexcaliburAPI.ui.htmlEncode(x.name);
                });
                intent.action.map((x,i) => {
                    if(i>0) tpl.action += "<br>";
                    tpl.action += DexcaliburAPI.ui.htmlEncode(x.name);
                });
                intent.data.map((x,i) => {
                    let dat="", url="", mime="";

                    for(let k in x){
                        if(x[k]!==null){
                            if(i>0) dat += "<br>";
                            dat += '<li><b>'+k+' : </b>'+DexcaliburAPI.ui.htmlEncode(x[k])+'</li>';
                        }
                    }

                    url = ''+x.scheme+'://';
                    if(x.host != null)
                        url += x.host;
                    if(x.port != null)
                        url += ':'+x.port;
                    if(x.path != null){
                        url += '/'+x.path;
                    }                


                    tpl.data += `
                        <div class="row">
                            <div class='col-lg-12' style='font-size:1.2em'>
                                <ul>${dat}</ul>
                                <div class="input-group input-group-sm mb-3">
                                    <div class="input-group-prepend">
                                        <span class="input-group-text" id="inputGroup-sizing-sm">Data URI</span>
                                    </div>
                                    <input type="text" value="${url}" id="${intent.__id}-${i}-data"class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm">
                                    <div class="input-group-append">
                                        <button class="btn btn-success sendIntent" id="${intent.__id}-${i}-custom"  type="button">Send intent</button>
                                    </div>
                                    <input type="hidden" value="${(x.mimeType!==null?x.mimeType:'')}" id="${intent.__id}-${i}-data-mime" class="form-control" aria-label="Small" aria-describedby="inputGroup-sizing-sm">
                                </div>
                            </div>
                        </div>
                    `;

                });

                if(tpl.data == ''){
                    tpl.data = `
                    <br>
                        <div class="row">
                            <div class="col-lg-12 text-right">

                                    <div class="input-group input-group-sm mb-3">
                                        <!--<div class="input-group-prepend">
                                            <span class="input-group-text" id="inputGroup-sizing-sm">This has not data</span>
                                        </div>-->
                                        <div class="input-group-append">
                                            <button class="btn btn-success btn-sm sendIntent" id="${intent.__id}"  type="button">Send intent</button>
                                        </div>
                                    </div>
                            </div>
                        </div>`;
                }

                body_tr = `
                <tr>
                    <td colspan="2">
                        <div class="row">
                            <div class="col-lg-6">
                                <b style='font-size:1.2em'>${tpl.cat}</b>
                            </div>
                            <div class="col-lg-6">
                                <i>${tpl.action}</i>
                            </div>
                        </div>`;

                if(tpl.data !== null){
                    body_tr += tpl.data;
                }

                body_tr += `
                    </td>
                </tr>`;

                $("#dxc-detail-intent-tab > tbody").append(body_tr);
            }
        }else{
            $("#dxc-detail-intent-tab > tbody").append("<tr><td colspan='3' style='font-size:1.2em'>No intent filters</td></tr>");
        }

        /*
        if(data.intentFilters.length > 0){
            for(let i=0; i<data.intentFilters.length; i++){
                intent = data.intentFilters[i];
                body_tr = "<tr><td><span class='badge badge-danger'><span class='fa fa-play'></span>&nbsp;send</span></td><td>";
                intent.category.map((x,i) => {
                    if(i>0) body_tr += "<br>";
                    body_tr += DexcaliburAPI.ui.htmlEncode(x.name);
                });
                body_tr += "</td><td>";
                intent.action.map((x,i) => {
                    if(i>0) body_tr += "<br>";
                    body_tr += DexcaliburAPI.ui.htmlEncode(x.name);
                });
                body_tr += "</td></tr>";

                $("#dxc-detail-intent-tab > tbody").append(body_tr);
            }
        }else{
            $("#dxc-detail-intent-tab > tbody").append("<tr><td colspan='3' style='font-size:1.2em'>No intent filters</td></tr>");
        }*/

        // interns 
        $("#dxc-detail-intern-tab > tbody").empty();
        let m = "";
        for(let i in data.__ppts["internals"]){

            m = Object.keys(data.__ppts["internals"][i]).map(
                x => "<a target='blank' href='/pages/finder.html?method="
                + btoa(encodeURIComponent(i+'.'+x)) + "'>"+DexcaliburAPI.ui.htmlEncode(x)+"</a>")
                .join("<br>");

            $("#dxc-detail-intern-tab > tbody").append(
                "<tr><td class='col-lg-3'>"+DexcaliburAPI.ui.htmlEncode(i)+"</td><td class='col-lg-9'>"+m+"</td></tr>"       
            );
        }

    }

    $(document).ready(function() {
        //let id=
        var currentObject = null;

        DexcaliburAPI.util.onLocation(
            location,
            {
                "id": function(value){
                    DexcaliburAPI.manifest.services.get(
                        value, {
                        200: function(data){

                            let act = JSON.parse(data);
                            currentObject = act.data;
                            render(act.data);
                        }
                    });
                }
            }
        );

        $("#sendIntentCustom").click(function(el){


            let id = $("#confIntentId").attr('value');

            let opt = {
                uid: id,
                type: 'start_service',
                name: currentObject.name,
                category: null,
                action:  null,
                data_uri: null,
                mime_type: null,
                extra_opts: null,
                app: null
            };

            let filt = null, data = null;

            for(let i=0; i<currentObject.intentFilters.length; i++){
                if(currentObject.intentFilters[i].__id == id)
                    filt = currentObject.intentFilters[i];
            }

            if(filt == null){
                console.log("IntentFilter not found");
                return ;
            }

            if($("#confDataUri")[0].value.length > 0){
                opt.data_uri = $("#confDataUri")[0].value;
            }

            if($("#confMime")[0].value.length > 0){
               opt.mime_type = $("#confMime")[0].value;
            }

            if($("#confExtraOpts")[0].value.length > 0){
               opt.extra_opts = $("#confExtraOpts")[0].value;
            }

            if(filt.action.length > 1)
                opt.action = $("#confActList").val();
            else if(filt.action.length == 1)
                opt.action = filt.action[0].name;
            

            if(filt.category.length > 1)
                opt.category = $("#confCatList").val();
            else if(filt.category.length == 1)
                opt.category = filt.category[0].name;
            

            DexcaliburAPI.manifest.intent.send(
                opt, {
                    200: function(data){
                        console.log(data);

                        $("#confIntentModal").modal('hide');
                        DexcaliburAPI.ui.alert.success(
                            `The intent has been emitted.<br>
                            <code>${data.data}</code>`,
                            false
                        );

                    },
                    404: function(data){
                        data = data.responseJSON;

                        $("#confIntentModal").modal('hide');
                        if(data.err != null){
                            DexcaliburAPI.ui.alert.error(
                                `${data.err.err} :<br>
                                <code>${data.err.stderr}</code>`,
                                false
                            );
                        }else{
                            DexcaliburAPI.ui.alert.error(
                                data.responseJSON.err
                            );
                        }
                    }
                } 
            );
        });

        $('#dxc-detail-intent-tab').on('click','.sendIntent',function(e){
                let data = null, curr=null, elId = e.target.id, intentUid=null, mime=null, ids=null;


                if(elId.endsWith("-custom")){ 

                    intentUid = elId.substring(0, elId.length-"-custom".length);


                    if($("#"+intentUid+"-data").length > 0)
                        data = $("#"+intentUid+"-data")[0].value;


                    if($("#"+intentUid+"-data-mime").length > 0)
                        mime = $("#"+intentUid+"-data-mime")[0].value;

                    intentUid = intentUid.split('-')[0]+'-'+intentUid.split('-')[1];
                }else{
                    intentUid = elId;
                    data = null;
                }

                
                for(let i=0; i<currentObject.intentFilters.length; i++){
                    console.log(currentObject.intentFilters[i]);
                    if(currentObject.intentFilters[i].__id==intentUid)
                        curr = currentObject.intentFilters[i];
                }

                if(curr.action.length > 1 || curr.category.length > 1){
                    renderIntentModal(curr, data, mime);
                    return;
                }


                let opt = {
                    uid: intentUid,
                    type: 'start_service',
                    name: currentObject.name,
                    category:  ((curr.category.length > 0) ? curr.category[0].name : null),
                    action:  ((curr.action.length > 0)? curr.action[0].name : null),
                    data_uri: ((data!=null && data.length > 0)? data : null),
                    mime_type: (mime != null? mime : null),
                    extra_opts: null,
                    app: "self"
                };

                DexcaliburAPI.manifest.intent.send(
                    opt, {
                        200: function(data){

                            DexcaliburAPI.ui.alert.success(
                                `The intent has been emitted.<br>
                                <code>${data.data}</code>`,
                                false
                            );
                        },
                        404: function(data){
                            data = data.responseJSON;
                            if(data.err != null){
                                DexcaliburAPI.ui.alert.error(
                                    `${data.err.err} :<br>
                                    <code>${data.err.stderr}</code>`,
                                    false
                                );
                            }else{
                                DexcaliburAPI.ui.alert.error(
                                    data.responseJSON.err
                                );
                            }
                        }
                    } 
                );
            });
        });

    </script>

</body>

</html>