PHP interface to DH Control Panel

software development

#1

Has anyone here created an interface to - for example - automatically add an email address or subdomain from a PHP script using the DreamHost control panels?

I would like to be able to automatically add a subdomain when I require one and have it mirror the main domain. Currently I have to do this by hand each time, but I would like to be able to automate it. I sent an enquiry as to whether this was possible to Support and they said “Yes its doable, but no we can’t give you any help with it, not even any form of documentation or guidance - you need a programmer!” Well gee thanks, I am a programmer, but I’m not psychic!

So do you reckon this is going to involve creating a web browser simulator to feed the correct commands into their control panels? Or is there a more direct way to do this?

Your opinions/advice would be welcomed…


#2

Okay so I found some details and started to develop a program, but I’m having problems getting the script to log into the DH control panel.

So I worked out, from refering to the Dynamic DNS shell script example in the wiki (http://wiki.dreamhost.com/index.php/DNS) that you have to capture the initial cookie that gets sent when you first visit the control panel, and use that when you submit the login request, otherwise DH complains that your cookies don’t work.

So step 1 is to send a request for the basic https://panel.dreamhost.com/ and you capture the cookies. I’m using cURL and the COOKIEJAR option to do that.

Step 2 is to send the login request, incorporating the cookies using COOKIEFILE and capturing the NEW cookies sent back to a seperate COOKIEJAR (just to make sure it is all nice and clean). The Username and Password are sent via POST to https://panel.dreamhost.com/index.cgi along with “Nscmd=Nlogin” which tells it you are logging in.

Sadly the response from this request is blank - nothing. No HTTP header, no error code, just a totally blank response from the server.

So what is going wrong?

Here is the code I’m using:

$cookie_jar1 = tempnam($_SERVER[‘DOCUMENT_ROOT’],‘cookie1’);
$cookie_jar2 = tempnam($_SERVER[‘DOCUMENT_ROOT’],‘cookie2’);

$url = “https://panel.dreamhost.com/”;
$ref_url = “http://www.yahoo.com/”;

$c = curl_init($url);
curl_setopt($c, CURLOPT_VERBOSE, 1);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_COOKIEJAR, $cookie_jar1);
curl_setopt($c, CURLOPT_REFERER, $ref_url);
curl_setopt($c, CURLOPT_USERAGENT,“Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”);

$page = curl_exec($c);
print “Last CURL error : |”.curl_errno($c)."|\n";
curl_close($c);

$ref_url = $url;
$url = “https://panel.dreamhost.com/index.cgi”;
$param_string = “Nscmd=Nlogin&username=$USER&password=$PASS”;

$c = curl_init($url);
curl_setopt($c, CURLOPT_VERBOSE, 1);
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar1);
curl_setopt($c, CURLOPT_COOKIEJAR, $cookie_jar2);
curl_setopt($c, CURLOPT_REFERER, $ref_url);
curl_setopt($c, CURLOPT_USERAGENT,“Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)”);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $param_string);
$page = curl_exec($c);
print “Last cURL error : |”.curl_error($c)."|\n";
print “Last cURL error : |”.curl_errno($c)."|\n";
curl_close($c);

print “\n\nLogged in Page\n\n”;
print “|”; print_r ($page); print “|”;

As you can see I am trying to make the session appear like a normal browser as much as possible, just in case this has any effect.

Any idea what is wrong - or is it DH deliberately blocking me?


#3

The short answer is yes. Don’t take it personally though, they’re trying to block anyone who doesn’t properly authenticate. :slight_smile:

I was trying to do something similar, and never pulled it off, but think something I found might be useful. It doesn’t look to me like you’re specifying the authentication type with the “CURLOPT_HTTPAUTH” argument of “curl_setopt”

Curl uses basic authentication by default. Perhaps Dreamhost is using a different auth type? Again, it never worked for me, but I was experimenting with this curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);http://curl.planetmirror.com/docs/httpscripting.html
http://rexxcurl.sourceforge.net/doc/index.html
http://curl.rtin.bz/docs/manpage.html

http://benconley.net
http://teamshocker.com


#4

Thanks for the response.

I’ve gone further with trying to make the script appear more browser like. From one of the links you posted I was able to get the FF plugin LiveHTTPHeaders, which showed me EXACTLY how my browser communicates with DH and I noticed an error where I had not urlencoded the username!

Now I’ve also realised that sometimes the DH control panels actually return a blank page in real life - to which I simply force a GET of the index page by clicking in the address bar and pressing RETURN (refresh doesn’t work). This then usually forces the browser to GET the logged in DH page. So I duplicated this in my script and VOILA!! I get a logged in page!!!

This isn’t them blocking scripting access as such, just the usual DH control panel flakiness maninfesting itself. I’ve added a routine now so that if the server sends back a zero length page, it automatically does a GET of the page. This simulates actual real useage.


#5

Great job figuring it out. As you know, the solution eluded me. If you would possibly entertain the idea of sharing the correct answer, that would be awesome. If you’d prefer to keep from sharing with everyone, PM or contact info in my profile would work too.

Thanks either way.

http://benconley.net
http://teamshocker.com


#6

I also would like to know how this is done! I’ve looked into this for hours using putty to test. But wow I never even thought of a php version.

Can you also by any chance send me a copy?

Thanks.


Use “DCOUNTME” promo code when registering and recieve up to $85 off! (referer: saygoodbye)


#7

Okay here is the PHP script I developed to be able to do this. The first two variables are your username and password.

This is not a terribly elegant script - I’m still workign to convert it into something more elegant, but this works and you can use it as the basis of your own scripts…

<? $USER = ""; $PASS = ""; function show_curl_errors ($chan) { # # Displays cURL error messages when needed. # if (curl_errno($chan) != 0) { print "Last cURL error : ".curl_errno($chan)." \n"; print "Last cURL error : ".curl_error($chan)." \n"; } } # initialise standard variable and the cookie files # Note: I am using this script to create an new email address that is forwarded to an existing address $redirect_address = "name@whatever.com"; # exiting email address (note: replace @ with "percent"40) $email_alias = "newname"; # email alias - ie what comes before the @ $email_domain = "newdomain.com"; # domain name of the new email addresss # I'm using two cookie jars, one for before the login, one for after. Not sure if this is neccessary however $cookie_jar1 = tempnam($_SERVER['DOCUMENT_ROOT']."/admin",'cookie1'); $cookie_jar2 = tempnam($_SERVER['DOCUMENT_ROOT']."/admin",'cookie2'); # standard browser header $header_array['Host'] = "panel.dreamhost.com"; $header_array['Accept'] = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; $header_array['Accept-Language'] = "en-us,en;q=0.5"; $header_array['Accept-Encoding'] = "gzip,deflate"; $header_array['Accept-Charset'] = "ISO-8859-1,utf-8;q=0.7,*;q=0.7"; $header_array['Keep-Alive'] = "300"; $header_array['Connection'] = "keep-alive"; $user_agent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7"; # start session on index/login page $url = "https://panel.dreamhost.com/"; $ref_url = ""; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEJAR, $cookie_jar1); $page = curl_exec($c); show_curl_errors ($c); curl_close($c); # Submit login request $ref_url = $url; $url = "https://panel.dreamhost.com/index.cgi"; $param_string = "Nscmd=Nlogin&username=$USER&password=$PASS"; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_REFERER, $ref_url); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar1); curl_setopt($c, CURLOPT_COOKIEJAR, $cookie_jar2); curl_setopt($c, CURLOPT_POST, 1); curl_setopt($c, CURLOPT_POSTFIELDS, $param_string); $page = curl_exec($c); #show_curl_errors ($c); curl_close($c); #print "Login Page\n"; unlink($cookie_jar1); # Resubmit the index page request - often get a blank response from the login page. This makes sure the session is legit $ref_url = $url; $url = "https://panel.dreamhost.com/index.cgi"; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_REFERER, $ref_url); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar2); curl_setopt($c, CURLOPT_POST, 0); $page = curl_exec($c); #show_curl_errors ($c); curl_close($c); #print "ReGet Login Page\n"; # ask for the "Create New Email" page. #$ref_url = $url; $url = "https://panel.dreamhost.com/index.cgi?tree=mail.addresses&domain=$account_domain&current_step=Index&next_step=New"; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_REFERER, $ref_url); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar2); curl_setopt($c, CURLOPT_POST, 0); $page = curl_exec($c); #show_curl_errors ($c); curl_close($c); #print "New Email Page\n"; # submit the New Email page using the variables we have previously set up. # Note: I'm only setting up addresses that are forwarded to an existing address. $ref_url = $url; $url = "https://panel.dreamhost.com/index.cgi?"; $param_string = "tree=mail.addresses&current_step=New&next_step=NewFinal&alias=$email_alias&domain=$email_domain&dest=forward&addresses=$redirect_address"; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_REFERER, $ref_url); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar2); curl_setopt($c, CURLOPT_POST, 1); curl_setopt($c, CURLOPT_POSTFIELDS, $param_string); $page = curl_exec($c); #show_curl_errors ($c); curl_close($c); # Now to verify, ask to edit bulk emails, then extract the list of forwarded emails and display them. $ref_url = $url; $url = "https://panel.dreamhost.com/index.cgi?tree=mail.addresses&current_step=Index&next_step=Bulk"; $param_string = ""; $c = curl_init($url); curl_setopt($c, CURLOPT_VERBOSE, 1); curl_setopt($c, CURLOPT_RETURNTRANSFER, 1); curl_setopt($c, CURLOPT_HEADER, 1); curl_setopt($c, CURLOPT_REFERER, $ref_url); curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY); curl_setopt($c, CURLOPT_HTTPHEADER, $header_array); curl_setopt($c, CURLOPT_USERAGENT,$user_agent); curl_setopt($c, CURLOPT_COOKIEFILE, $cookie_jar2); curl_setopt($c, CURLOPT_POST, false); $page = curl_exec($c); #show_curl_errors ($c); curl_close($c); $start_string = "<textarea name=text"; $end_string = ""; $page_lines = split("/n",$page); foreach ($page_lines as $p) { if (ereg($start_string,$p)) {$found = true;} if ($found) {$outp = $p;} if (ereg($end_string,$p)) {$found = false;} } $n = strpos($outp,"")+1; $outp3 = substr($outp2,$n); $n = strpos($outp3,"<"); $outp4 = substr($outp3,0,$n); print "If the email was set up correctly, it will appear in this list of currently active addresses:"; print "
$outp4
"; unlink($cookie_jar2); exit; ?>

#8

having checked the script (bah for loosing the indentation) the only gotcha is the @ sign in the $redirect_address variable. this must be represented as

% 40

(space added after the % to stop the browser converting it back into @)


#9

Thanks for your script, I’m working (very, very, very slowly) on a resellerscript, so that you can make your own panel and let your costumers (customers?) change it by themselfs.
It will run with php/mysql.

Yes, it’s being lazy and yes, I know it’s a kind of script that has been created over and over again and almost never seen a decent “final release”

Some of the problems that can rise here is that when I change something through panel.dreamhost.com, it has to be read by my panelscript.

But that’s all for in a near future, first examining the panel and which fields are required and when not.

And I’m gonna dream on in this post by saying that it would be sooooo nice and “ego stroking” if dreamhost used my script to enhance their panel which would probably be … never :smiley:


#10

That is very cool, boldmanuk! It certainly helps “show the way” for some of us. Thank You! :slight_smile:

–rlparker


#11

Hello,

I have been trying to develop scripts like yours too.

But i was wondering… if dh change their panel (not entirely, just some lines) i would probaly loose my work and have to rewrite all the strpos and substr stuff. Did you find anyway to solve this problem?

Does dh usually change their panel?


#12

I’ve been looking for something like this, so I just wanted to say thanks!
Have any issues come up since this was posted that I should know about?


#13

Shouldn’t $account_domain be $email_domain?


#14

This works for me:

// I have to do this twice for some reason. for ($i = 1; $i <= 2; $i++) { $ch = curl_init('https://panel.dreamhost.com/index.cgi?tree=' . $tree); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_COOKIEFILE, '~/sites/dhcookies.txt'); curl_setopt($ch, CURLOPT_COOKIEJAR, '~/sites/dhcookies.txt'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, array( 'username' => 'username', 'password' => 'password', 'Nscmd' => 'Nlogin', )); if ($i == 2) { $lines = explode("\n", curl_exec($ch)); } }I haven’t figured out why I have to run it twice, but it’s short and simple. I imagine this could me modified to post panel forms like the one for creating a new sub-domain.

$tree: the page I want to get~: This "alias" doesn't actually work in a PHP script, it's just there for looks.Visit me, please…
www.theraven7.com


#15

Here’s a php function for sending messages from my external server to a dreamhost announcement list. This worked for me:

function announce_test($message)
{
$header_array[‘Host’] = “panel.dreamhost.com”;
$header_array[‘Accept’] = “text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,/;q=0.5”;
$header_array[‘Accept-Language’] = “en-us,en;q=0.5”;
$header_array[‘Accept-Encoding’] = “gzip,deflate”;
$header_array[‘Accept-Charset’] = “ISO-8859-1,utf-8;q=0.7,*;q=0.7”;
$header_array[‘Keep-Alive’] = “300”;
$header_array[‘Connection’] = “keep-alive”;
$user_agent = “Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Firefox/1.5.0.7”;

$curl_pw_str=‘Nscmd=Nlogin&username=’ . urlencode(‘doc@domain.com’) . ‘&password=PASSWORD&submit=’ . urlencode(‘Log In’);
$c=curl_init(“https://panel.dreamhost.com/index.cgi”);
curl_setopt($c, CURLOPT_POST,1);
curl_setopt($c, CURLOPT_VERBOSE,1);
//curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($c, CURLOPT_HTTPHEADER, $header_array);
curl_setopt($c, CURLOPT_USERAGENT,$user_agent);

curl_setopt($c, CURLOPT_HTTP_VERSION, 1.0);
curl_setopt($c, CURLOPT_COOKIEFILE, ‘/Library/WebServer/cookie.php’);
curl_setopt($c, CURLOPT_COOKIEJAR, ‘/Library/WebServer/cookie1.php’);
curl_setopt($c, CURLOPT_POSTFIELDS,$curl_pw_str);
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, TRUE);
//curl_setopt($c, CURLOPT_USERPWD, ‘:bcpa3176’);
$result=curl_exec($c);

$c=curl_init(“https://panel.dreamhost.com/index.cgi?tree=mail.list&current_step=Index&next_step=ShowSend&address=LISTNAME&domain=DOMAIN.com”);
curl_setopt($c, CURLOPT_POST,0);
curl_setopt($c, CURLOPT_VERBOSE,1);
//curl_setopt($c, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($c, CURLOPT_HTTPHEADER, $header_array);
curl_setopt($c, CURLOPT_USERAGENT,$user_agent);

curl_setopt($c, CURLOPT_HTTP_VERSION, 1.0);
curl_setopt($c, CURLOPT_COOKIEFILE, ‘/Library/WebServer/cookie.php’);
curl_setopt($c, CURLOPT_COOKIEJAR, ‘/Library/WebServer/cookie1.php’);
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, TRUE);
//curl_setopt($c, CURLOPT_USERPWD, ‘:bcpa3176’);
$result2=curl_exec($c);

$c=curl_init(“https://panel.dreamhost.com/index.cgi?tree=mail.list&current_step=ShowSend&next_step=SendFinal&address=LISTNAME&domain=DOMAIN.com”);
$thepoststr=‘tree=mail.list&current_step=ShowSend&next_step=SendFinal&name=’ . urlencode("“test” ") . ‘LISTNAME@DOMAIN.com&subject=test announcement&message=’ . urlencode($message) . ‘&charset=iso-8859-1&html=on&stamp=’ . date(“Y-m-d h:i:s”);
curl_setopt($c, CURLOPT_HTTPHEADER, $header_array);
curl_setopt($c, CURLOPT_USERAGENT,$user_agent);
curl_setopt($c, CURLOPT_POSTFIELDS,$thepoststr);
curl_setopt($c, CURLOPT_HTTP_VERSION, 1.0);
curl_setopt($c, CURLOPT_COOKIEFILE, ‘/Library/WebServer/cookie.php’);
curl_setopt($c, CURLOPT_COOKIEJAR, ‘/Library/WebServer/cookie1.php’);
curl_setopt($c, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, TRUE);
$result1=curl_exec($c);
$result1=curl_exec($c);
echo curl_error($c); if($result1)
curl_close($c);
//echo $result;
//echo $result2;
//echo $result1;
return $result1;
}

Took me a few runs at this. Replace your email, password, domain name and list name and you should be good to go. Uncomment the echo lines for troubleshooting.


#16

Sweet! Thanks for sharing this! :slight_smile:

–rlparker


#17

has anyone happened to figure out how you can use a PHP script to create a new mysql database?


#18

You can’t…

…at least not in DH.
There’s a number of restrictions in place at DH (for security’s sake) regarding mySQL. One of those is that you cannot CREATE or DROP a database from PHP, you have to do it through the panel.

You can, however, CREATE and DROP tables via PHP with no trouble

cheers!


#19

It appears so … a general procedure that should work is described in other posts in this thread, where examples are given for automating creating email aliases and posting to announment lists via PHP scripts.

Another example of how to “automate” Panel interaction, based on Bodamunk’s work, is described in this forum post (shows sample code for addding a sub-domain using PHP).

These tasks were not intended to be accomplished from outside the panel, but have been made to work using PHP and cURL. The same process, with different details, should work as well for manipulating other sections of the panel.

That said, development of such a tool is considerably less useful without an established API to work through … DreamHost changes to the structure, or operation, of the panel would likely break much of this kind of code, so I consider such things to be a “one off” job and would not rely upon them to work dependably over time. :wink:

–rlparker