The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Dynamic display of nameserver - ajaxnslist() ?

Discussion in 'cPanel Developers' started by bmett, Aug 31, 2010.

  1. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    Hi folks,

    I'm currently adding cPanel API functions to our CMS so that the employees can create new accounts without loggin into cPanel itself. No problems so far. If you do that in cPanel though, the DNS Settings box has nice feature that shows the nameservers for the typed in domain name. It would like to have something like that in our CMS too :D The function the cPanel site calls is called ajaxnslist().
    Anyone has an idea where to find this function or maybe a different idea how to do that?
    Thanks for any help.
    Cheers,
    Bjorn
     
  2. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Hi Bjorn,

    This type of functionality does have an API methods, unfortunately. "ajaxnslist()" performs an AJAX request against a WHM page.

    You can retrieve this information from
    1) /etc/wwwacct.conf (for general/deault nameservers)

    2) if you need to fetch nameservers relative to a reseller, you can grep out specific reseller nameserves from /var/cpanel/resellers-nameserver

    Regards,
    -David
     
  3. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    Hi David,

    Thanks for the reply.

    So is there an API method or not? From your post its not 100% clear for me.

    I don't only need the default nameserver or reseller-nameserver. I actually want a script that dynamically shows me the nameserver of any domain. Even if i put in google.com or yahoo.com.

    The script on cPanels 'create an account' page does exactly that.

    Cheers,
    Bjorn
     
  4. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Hi Bjorn,

    This functionality is not implemented as an API or XML-API call.

    There's a hack-ish way to get this information by making your own API2 call. The custom API call would wrap around the cPanel Perl module that is (ultimately) called to provide the dynamic lookup in the current, shipped product.

    I cover the technical details of implementing a custom API2 call in this post: http://forums.cpanel.net/f42/help-cant-make-postwwwacct-work-cpaddon-161586.html#post677297

    You will need to do the same things itemized setup steps 1a and 1b of that post. But instead of use that custom module, you use this:
    Code:
    package Cpanel::DnsRootsCustom;
    
    BEGIN { unshift @INC, '/usr/local/cpanel', '/usr/local/cpanel/cpaddons', '/usr/local/cpanel/perl'; }
    
    use Cpanel::DnsRoots;
    use IO::Scalar;
    
    sub api2_fetchnameservers {
            my %OPTS = @_;
            my $out;
            my ($nameserver, $nameserver2, $nameserver3, $nameserver4);
    
            tie *VAROUT, 'IO::Scalar', \$out;
            select(VAROUT);
            my @DNSROOTS = Cpanel::DnsRoots::fetchnameservers(%OPTS->{'domain'});
            select(STDOUT);
    
            if ( $DNSROOTS[0] eq '1' ) {
                my %NAMES   = %{ $DNSROOTS[2] };
                my $nscount = 1;
                foreach my $tnameserver ( keys %NAMES ) {
                    my $nsip  = $NAMES{$tnameserver};
                    my $nsvar = $nscount;
                    if ( $nsvar == 1 ) { $nsvar = ''; }
                    eval '$nameserver' . $nsvar . q{ = '} . $tnameserver . q{';};
                    $nscount++;
                }
            }
    
            my $return_str = "$nameserver:$nameserver2:$nameserver3:$nameserver4";
            return {'result' => $return_str };
    }
    
    sub api2 {
            my $func = shift;
            my %API  = (
                    'fetchnameservers' => {
                            'func' => 'api2_fetchnameservers',
                            'engine' => 'hasharray'
                    }
            );
    
    
            return \%{ $API{$func} };
    }
    
    Save that code as /usr/local/cpanel/Cpanel/DnsRootsCustom.pm

    Then you could either place a cPanel API2 tag in you custom cPanel page or you could use the xml-api like so:
    Code:
    <?php
    include("xmlapi.php");
    
    $ip = "10.1.1.1";
    $root_pass = "r00tS3cr3t!";
    
    $xmlapi = new xmlapi($ip);
    $xmlapi->password_auth("root",$root_pass);
    
    $cP_acct = 'dave';
    
    $args = array(
    	'domain'	=>	'google.com',
    	'useregns'	=>	1,
    	);
    	
    $xmlapi->api2_query($cP_acct, 'DnsRootsCustom', 'fetchnameservers', $args);
    
    The results from an xml-api call would look like:
    Code:
    URL: https://10.1.1.1:2087/xml-api/cpanel
    DATA: domain=google.com&useregns=1&cpanel_xmlapi_user=dave&cpanel_xmlapi_module=DnsRootsCustom&cpanel_xmlapi_func=fetchnameservers&cpanel_xmlapi_apiversion=2
    
    
    RESPONSE:
       <cpanelresult>
        <apiversion>2</apiversion>
        <data>
          <result>ns2.google.com:ns4.google.com:ns3.google.com:ns1.google.com</result>
        </data>
        <event>
          <result>1</result>
        </event>
        <func>fetchnameservers</func>
        <module>DnsRootsCustom</module>
      </cpanelresult>
    
    The problem with this implementation is that API2 calls made via xml-api require a cpanel user name (in my example, 'dave'). So, you have to have at least some cpanel or reseller account that you know will always exist on the box. There's just no way around that. We do not have a mechanism to make 'native' xml-api functions; only the ability to make custom API1/API2 module/functions...that can be invoked on behalf of a cPanel user. [ in the case of this particular functionality, the user is irrelevant and discarded once the code determines it's a valid account on the system; there's no user specific info being gathered ]

    If that doesn't work for you purposes, you'd have to reimplement the code found in the Cpanel::DnsRoots.pm module as a CGI script that you hit direct (which is essentially what the JS ajaxnslist() function is doing).

    Regards,
    -DavidN
     
  5. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    David, you are just amazing! :D

    Thanks again for your support. Your solution works absolutely perfect and does exactly what I want!

    Thanks again, have a great weekend!
    Bjorn
     
  6. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Glad I could help!

    Best Regards,
    -DavidN
     
  7. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    Hey David,

    Unfortunately my last reply was a bit premature (haha).

    The custom API call works fine and it's nothing wrong with it, but I can't get it to work dynamically in my form. What I want is, that the display of the name-server dynamically changes when the user edits the input field for the domain URL.
    The API call only works at the initial loading of the page. Since I do the API call via PHP it makes perfectly sense why its not working. PHP is server-side and my javascript doing the dynamic call is client-side.

    So here is my question, is it possible to do a API call via Javascript or any other via, so I can get the wanted functionality to work?

    Cheers,
    Bjorn
     
  8. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Hi Bjorn,

    If your custom page is on a cPanel server, you could have something like the code below in an theme directory (ie, /usr/local/cpanel/base/frontend/x3/$this_sample_code) and it will make an ajax call, requesting the nameservers after the domain name is typed.
    HTML:
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <script>
    
    function fetchandfill(domain){
    
            if (window.XMLHttpRequest)
            {// code for IE7+, Firefox, Chrome, Opera, Safari
                    xmlhttp=new XMLHttpRequest();
            }
            else
            {// code for IE6, IE5
                    xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
            }
    
            xmlhttp.onreadystatechange=function()
            {
                    if (xmlhttp.readyState==4 && xmlhttp.status==200)
                    {
                            results = eval('(' + xmlhttp.responseText + ')');
                            raw = results.cpanelresult.data[0].result;
                            names = raw.split(':');
                            document.getElementById("nameserver").value = names[0];
                            document.getElementById("nameserver2").value = names[1];
                            document.getElementById("nameserver3").value = names[2];
                            document.getElementById("nameserver4").value = names[3];
                    }
            }
    
            // send ajax request to our server
            xmlhttp.open("POST","/json-api/cpanel",true);
            xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
            data = "domain="+ domain + "&useregns=1&cpanel_jsonapi_user=<cpanel print="$user">&cpanel_jsonapi_module=DnsRootsCustom&cpanel_jsonapi_func=fetchnameservers&cpanel_jsonapi_apiversion=2";
            xmlhttp.send(data);
    
    }
    
    function updatenameservers(){
            fetchandfill(document.getElementById("domain").value);
    }
    
    </script>
    
    
    <body>
     <form id="myform" name="myform">
            <input id="domain" name="domain" type="text" onblur="updatenameservers()" />
    
            <input id="nameserver" name="nameserver" type="text" />
            <input id="nameserver2" name="nameserver2" type="text" />
            <input id="nameserver3" name="nameserver3" type="text" />
            <input id="nameserver4" name="nameserver4" type="text" />
     </form>
    </body>
    </html>
    
    Of course, if you're on a different server that the cPanel installation, you'll have to do it differently. In that case, you would have the your JS request a local page and the local page is responsible for making the remote connection and query as an isolated HTTP request and then returning the results back to the JS.

    Cheers,
    -DavidN

    PS. please for give my inelegant JS. I prefer to use a JS framework, but this is really just a simple example. It doesn't have failsafe or error correction. Like I said this is just a quick example.
     
  9. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    Hi David,

    Thanks for your reply.

    Your code makes perfectly sense and I already coded something similar but if I put your code in a file and put that file in an account in /home/myaccount/public_html and open it, it won't work.
    I get the error that
    http://www.mydomain.com.au/json-api/cpanel
    is not found. And again that make sense. So where to I have to point the xmlhttp.open request?
    And yes, the website sits on the same server cpanel does.

    Thanks again for your help,
    Bjorn
     
  10. cPanelDavidN

    cPanelDavidN Integration Developer
    Staff Member

    Joined:
    Dec 17, 2009
    Messages:
    571
    Likes Received:
    1
    Trophy Points:
    18
    Location:
    Houston, TX
    cPanel Access Level:
    Root Administrator
    Hi Bjorn,

    It won't work if you place it in a home directory. The JS request is simply going to '/json/cpanel' which will form a URI based on the current page. So, in your example, that is 'http://www.mydomain.com.au'. And since the user's site, proper, doesn't answer API requests, much less on port 80, the xmlhttp.open will fail. In order for my page to work, it needs to be served within the cPanel UI, so the script needs to live in /usr/local/cpanel/base/frontend/$theme/ (where $theme will be 'x3' or possibly something else). All paged served from there are done so on ports 2082 and 2083, and of course, require that a login cookie/session/token has been established.

    This type of implementation has a few short comings:
    1) you need root to place the script in the proper directory
    2) it only works if you're logged into cPanel; essentially working within the UI
    3) by having it in a 'common' cPanel directory, anyone on the box will/can execute the page from their cPanel UI (at least, as the script exists currently).

    If you need this functionality without all of that baggage, then you'll have to do the other type implementation I mentioned earlier. You have to have your JS poll a page that is a script, or wrapper if you will. The wrapper would work completely independent of cPanel login or location. It would contain all authentication needed and make the request via cURL or fopen or the like and then just print/echo the results back to the client (aka, xmlhttp).

    See my PM for more details...

    -DavidN
     
  11. bmett

    bmett Well-Known Member

    Joined:
    Aug 5, 2010
    Messages:
    63
    Likes Received:
    0
    Trophy Points:
    6
    Location:
    Brisbane, AU
    Just a quick update on this thread.

    I finally managed to implement the need ajax request with jQuery. I simply used $.post() to do the POST request.

    Every time the user changes the domain name in the input field, jQuery does the request which calls the API call 'DnsRootsCustom'.

    Quite easy in the end.

    Thanks again to David for the support.

    Cheers,
    Bjorn
     

Share This Page