Upgrade 3CX to v18 and get it hosted free!

PHP Code for provisioning and rebooting Grandstreams

Author image

Based on the current examples with Bash scripts, Perl and LUA code on the site, I decided to contribute some PHP snippets which provide various functions:

Update: According to my research, the reboot and provisioning methods used for the GXP2120 and GXP2140 should also apply to the GXP2100 and GXP1200 phones.

Reboot for GXP2120 and GXP2140:


	$pass = "admin";
	// generate URLs
	$login_url = "http://" . $ip . "/cgi-bin/dologin";
	$reboot_url = "http://" . $ip . "/cgi-bin/api-sys_operation";

	// curl object
	$ch = curl_init();
		
	// set curl to use cookie file
	$ckfile = tempnam("/tmp", "CURLCOOKIE");
	curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
		
	//set the url, number of POST vars, POST data
	curl_setopt($ch, CURLOPT_URL, $login_url);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, "&password=" . $pass);
	curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
		
	// get 'sid' as a string
	$response = curl_exec($ch);
	preg_match('/sid" : "([A-z0-9]*)/', $response, $sid);
	$sid = $sid[1];
		
	// now that we have the sid, send the reboot command
	curl_setopt($ch, CURLOPT_URL, $reboot_url);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, "&request=REBOOT&sid=" . $sid);
	$response = curl_exec($ch);
	curl_close($ch);

UPDATE 2017/03: as of recent firmware builds, the following GET request appears to be enough


		$pass = "admin";
		// generate URLs
		$login_url = "http://" . $ip . "/cgi-bin/dologin";
		$reboot_url = "http://" . $ip . "/cgi-bin/api-sys_operation";

		// http://xx.xx.xx.xx/cgi-bin/api-sys_operation?password=XXXXX&request=REBOOT
		$reboot_url = "http://" . $ip . "/cgi-bin/api-sys_operation?password=$pass&request=REBOOT";

		// curl object
		$ch = curl_init();

		// Set some options - we are passing in a useragent too here
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_URL, $reboot_url);
		curl_setopt($ch, CURLOPT_USERAGENT, 'GSProv cURL');

		// send GET request
		$response = curl_exec($ch);		
		curl_close($ch);

Reboot for the GXP2000:


	$pass = "admin";
	// generate URLs
	$login_url = "http://" . $ip . "/dologin.htm";
	$reboot_url = "http://" . $ip . "/rs.htm";

	// curl object
	$ch = curl_init();
	
	// set curl to use cookie file
	$ckfile = tempnam("/tmp", "CURLCOOKIE");
	curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile);
	//set the URL, number of POST vars, POST data
	curl_setopt($ch, CURLOPT_URL, $login_url);
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS, "P2=" . $pass . "&Login=Login&gnkey=0b82");
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
	curl_setopt($ch, CURLOPT_REFERER, str_replace('dologin', 'login', $login_url));
	curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13 ( .NET CLR 3.5.30729)");

	// get 'sid' cookie by logging in
	$response = curl_exec($ch);
	// now that we have the sid cookie, send the reboot command
	curl_setopt($ch, CURLOPT_URL, $reboot_url);
	curl_setopt($ch, CURLOPT_POST, false);
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);
	curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
	curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
	$response = curl_exec($ch);
	curl_close($ch);

Provisioning (plain XML) for GXP2120 and GXP2140:

— This example assumes you have a database with tables named after the configuration parameters. If not, substitute the database part with reading a textfile of params instead or get creative…


	// clear any previous output
	ob_end_clean();

	// set headers for filetype
	header("Content-type: text/xml");
	header("Content-Disposition: \"inline; filename=cfg" . $mac . ".xml");
	// print XML header gxp21xx
	print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n";
	print "<gs_provision version=\"1\">\r\n";
	print "\t<mac>" . $mac . "</mac>\r\n";
	print "\t<config version=\"1\">\r\n";

	$offset = 7;
	$total_column = ($sth->columnCount() -1);
	$data = $sth->fetch();

	for ($counter = $offset; $counter <= $total_column; $counter ++) {
		$meta = $sth->getColumnMeta($counter);
		// only print configured parameters
		if (strlen($data[$counter]) > 0) {
			$value = str_replace('\r', '', $data[$counter]);
			$value = str_replace('\n', '', $value);
			print "\t\t<" . $meta['name'] . ">" . $value . "</" . $meta['name'] . ">\r\n";
		}
	}
	
	// XML end tags
	print "\t</config>\r\n";
	print "</gs_provision>\r\n";

Provisioning GXP2000:

— This example assumes you have a database with tables named after the configuration parameters. If not, substitute the database part with reading a textfile of params instead or get creative…


	// clear previous output
	ob_end_clean();
	// set headers for filetype
	header("Content-type: text/plain");
	header("Content-Disposition: \"inline; filename=cfg$mac");
	
	$h_crlf = '0d0a';
	$h_mac = $mac;
	$b_mac  = pack("H12", $h_mac);
	$b_crlf = pack("H4", $h_crlf);

	// huge string of parameters...
	$paramstring = "";

	// get data from db
	$total_column = ($sth->columnCount() -1);
	$data = $sth->fetch();
	for ($counter = 0; $counter <= $total_column; $counter ++) {
		$meta = $sth->getColumnMeta($counter);
		if ($data[$counter]) {
			$paramstring .= $meta['name'] . "=" . trim($data[$counter]) . "&";
		}
	}
	
	// sort of "URLencode" the string
	$paramstring = str_replace(' ','%20',$paramstring);
	$paramstring = str_replace('-','%2D',$paramstring); 
	$paramstring = str_replace('*','%2A',$paramstring); 
	$paramstring = str_replace(',','%2C',$paramstring); 
	$paramstring = str_replace(';','%3B',$paramstring); 

	$paramstring .= 'gnkey=0b82';

	// add an extra byte to make the body even (bytewise)
	if ((strlen($paramstring) % 2) != 0) {
		$paramstring .= "\0";
	}
	// add an extra word ( = two bytes) to make the body even (wordwise)
	if ((strlen($paramstring) % 4) != 0) {
		$paramstring .= "\0\0";
	}

	$d_length = 8 + (strlen($paramstring) / 2);
	
	$b_length = pack("N", $d_length);
	
	$d_checksum = array_sum(unpack("n2", $b_length));
	$d_checksum += array_sum(unpack("n*", $b_mac));
	$d_checksum %= pow(2,16);
	$d_checksum += (6676); // (3338 * 2)
	$d_checksum += array_sum(unpack("n*", $paramstring));
	$d_checksum %= pow(2,16);

	$d_checksum = (65536 - $d_checksum);
	
	$b_checksum = pack("n", $d_checksum);
	
	// output data
	print $b_length;
	print $b_checksum;
	print $b_mac;
	print $b_crlf;
	print $b_crlf;
	print $paramstring;

XML Phonebook (Applies to all models that support the feature):


	ob_end_clean();
	header("Content-type: text/xml");
	header("Content-Disposition: \"inline; filename=phonebook.xml");
	print "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n" .
			"<AddressBook>\r\n";
	foreach ($db->runQuery($query) as $row) {
		$fname = $row['fname'];
		$lname = $row['lname'];
		$pattern = array("'é'", "'è'", "'à«'", "'àª'", "'É'", "'È'", "'Ë'", "'Ê'", 
						"'à¡'", "'à '", "'ä'", "'à¢'", "'à¥'", "'à'", "'À'", "'Ä'", "'Â'", "'Ã…'", 
						"'ó'", "'à²'", "'ö'", "'à´'", "'Ó'", "'Ã’'", "'Ö'", "'Ô'", 
						"'à­'", "'à¬'", "'à¯'", "'à®'", "'à'", "'ÃŒ'", "'à'", "'ÃŽ'", 
						"'àº'", "'à¹'", "'à¼'", "'à»'", "'Ú'", "'Ù'", "'Ü'", "'Û'", 
						"'à½'", "'à¿'", "'à'", "'à¸'", "'Ø'", "'Å“'", "'Å’'", "'Æ'", "'à§'", "'Ç'");
		$replace = array('e', 'e', 'e', 'e', 'E', 'E', 'E', 'E', 
						'a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A', 'A', 
						'o', 'o', 'o', 'o', 'O', 'O', 'O', 'O', 
						'i', 'i', 'i', 'I', 'I', 'I', 'I', 'I', 
						'u', 'u', 'u', 'u', 'U', 'U', 'U', 'U', 
						'y', 'y', 'Y', 'o', 'O', 'a', 'A', 'A', 'c', 'C');
		$fname = preg_replace($pattern, $replace, $fname);
		$lname = preg_replace($pattern, $replace, $lname);
		print "\t  <Contact>\n" .
			  "\t   <LastName>" . $lname . "</LastName>\r\n" . 
			  "\t   <FirstName>" . $fname . "</FirstName>\r\n" . 
			  "\t   <Phone>\n" . 
			  "\t    <phonenumber>" . $row['pnumber'] . "</phonenumber>\r\n" . 
			  "\t    <accountindex>" . $row['accindex'] . "</accountindex>\r\n" . 
			  "\t   </Phone>\r\n" . 
			  "\t  </Contact>\r\n";
	}
	print "</AddressBook>\r\n";


Article Reviews

Write a Review

Your email address will not be published. Required fields are marked *

Required Field. Minimum 5 characters.

Required Field. Minimum 5 characters, maximum 50.

Required field.There is an error with this field.

Required Field.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

There are no reviews for this article. Be the first one to write a review.

Related Posts:

Get 3CX - Absolutely Free!
Link up your team and customers Phone System Live Chat Video Conferencing

Hosted or Self-managed. Up to 10 users free forever. No credit card. Try risk free.

3CX
A 3CX Account with that email already exists. You will be redirected to the Customer Portal to sign in or reset your password if you've forgotten it.