Finally! Google Plus status updater is here :) It is written in PHP, so it should be cross platform, which is a plus ;) It needs the curl extension to work though. Well, the bot can log into your Google account and update your Google Plus status, but I’m sure you can extend it to other Google products. All this is done without Google API, OAuth, tokens or any other annoying products. Post your comments, improvements and feature request below.
Download: gplus-bot
<?php
/**
* Google+ (plus.google.com) PHP Curl bot
* @since Sep 29 2011
* @version 15.12.2011
* @link http://360percents.com/
* @author Luka Pušić <luka@pusic.si>
*/
/**
* REQUIRED PARAMETERS
*/
$status = 'testzzz';
$email = 'your@email.com';
$pass = 'yourpassw0rd';
/**
* OPTIONAL PARAMETERS
* sleeptime is an optional timeout parameter which makes us look less suspicious to Google
* Enter pageid if you want to post to a page.
*/
$pageid = false;
$cookies = 'cookie.txt';
$sleeptime = 0;
$uagent = 'Mozilla/4.0 (compatible; MSIE 5.0; S60/3.0 NokiaN73-1/2.0(2.0617.0.0.7) Profile/MIDP-2.0 Configuration/CLDC-1.1)';
$pc_uagent = 'Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1';
$debug = FALSE;
function tidy($str) {
return rtrim($str, "&");
}
/**
* Handle cookie file
*/
@unlink($cookies); //delete previous cookie file if exists
touch($cookies); //create a cookie file
/**
* MAIN BLOCK
* login_data() just collects login form info
* login($postdata) logs you in and you can do pretty much anything you want from here on
*/
login(login_data());
sleep($sleeptime);
if ($pageid) {
update_page_status();
} else {
update_profile_status();
} //update status with $GLOBAL['status'];
sleep($sleeptime);
logout(); //optional - log out
/**
* 1. GET: http://plus.google.com/
* Parse the webpage and collect form data
* @return array (string postdata, string postaction)
*/
function login_data() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['uagent']);
curl_setopt($ch, CURLOPT_URL, "https://plus.google.com/app/basic/login");
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$buf = utf8_decode(html_entity_decode(curl_exec($ch)));
$buf = str_replace( '&', '&', $buf ); // just in case any correctly encoded
$buf = str_replace( '&', '&', $buf ); // now encode them all again
curl_close($ch);
echo "\n[+] Sending GET request to: https://plus.google.com/app/basic/login\n\n";
$toreturn = '';
$doc = new DOMDocument;
$doc->loadxml($buf);
$inputs = $doc->getElementsByTagName('input');
foreach ($inputs as $input) {
switch ($input->getAttribute('name')) {
case 'Email':
$toreturn .= 'Email=' . urlencode($GLOBALS['email']) . '&';
break;
case 'Passwd':
$toreturn .= 'Passwd=' . urlencode($GLOBALS['pass']) . '&';
break;
default:
$toreturn .= $input->getAttribute('name') . '=' . urlencode($input->getAttribute('value')) . '&';
}
}
return array(tidy($toreturn), $doc->getElementsByTagName('form')->item(0)->getAttribute('action'));
}
/**
* 2. POST login: https://accounts.google.com/ServiceLoginAuth
*/
function login($postdata) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['uagent']);
curl_setopt($ch, CURLOPT_URL, $postdata[1]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postdata[0]);
$buf = curl_exec($ch); #this is not the g+ home page, because the b**** doesn't redirect properly
curl_close($ch);
if ($GLOBALS['debug']) {
echo $buf;
}
echo "\n[+] Sending POST request to: " . $postdata[1] . "\n\n";
}
/**
* 3. GET status update form:
* Parse the webpage and collect form data
*/
function update_profile_status() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['uagent']);
curl_setopt($ch, CURLOPT_URL, 'https://m.google.com/app/plus/?v=compose&group=m1c&hideloc=1');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$buf = utf8_decode(html_entity_decode(str_replace('&', '', curl_exec($ch))));
$header = curl_getinfo($ch);
curl_close($ch);
if ($GLOBALS['debug']) {
echo $buf;
}
$params = '';
$doc = new DOMDocument;
$doc->loadxml($buf);
$inputs = $doc->getElementsByTagName('input');
foreach ($inputs as $input) {
if (($input->getAttribute('name') != 'editcircles')) {
$params .= $input->getAttribute('name') . '=' . urlencode($input->getAttribute('value')) . '&';
}
}
$params .= 'newcontent=' . urlencode($GLOBALS['status']);
//$baseurl = $doc->getElementsByTagName('base')->item(0)->getAttribute('href');
$baseurl = 'https://m.google.com' . parse_url($header['url'], PHP_URL_PATH);
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['uagent']);
//delete group=b0& in the line below, to post just to your circles, not to public
curl_setopt($ch, CURLOPT_URL, $baseurl . '?v=compose&group=m1c&group=b0&hideloc=1&a=post');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_REFERER, $baseurl . '?v=compose&group=m1c&group=b0&hideloc=1');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
$buf = curl_exec($ch);
$header = curl_getinfo($ch);
curl_close($ch);
if ($GLOBALS['debug']) {
echo $buf;
}
echo "\n[+] POST Updating status on: " . $baseurl . "\n\n";
}
/**
* Not implemented yet!
* just ignore this function for now
*/
function update_page_status() {
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['pc_uagent']);
curl_setopt($ch, CURLOPT_URL, 'https://plus.google.com/u/0/b/' . $GLOBALS['pageid'] . '/');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
$buf = utf8_decode(html_entity_decode(str_replace('&', '', curl_exec($ch))));
curl_close($ch);
if ($GLOBALS['debug']) {
echo $buf;
}
}
/**
* 3. GET logout:
* Just logout to look more human like and reset cookie :)
*/
function logout() {
echo "\n[+] GET Logging out: \n\n";
$ch = curl_init();
curl_setopt($ch, CURLOPT_COOKIEJAR, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_COOKIEFILE, $GLOBALS['cookies']);
curl_setopt($ch, CURLOPT_USERAGENT, $GLOBALS['uagent']);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/m/logout');
$buf = curl_exec($ch);
curl_close($ch);
if ($GLOBALS['debug']) {
echo $buf;
}
}
?>
Sweet! Testing it.
The script needs some modification, I’m working on it.
[+] Sending GET request to: https://plus.google.com/
[+] Sending POST request to: https://accounts.google.com/ServiceLoginAuth
PHP Fatal error: Call to a member function getAttribute() on a non-object in /home/******/****/gplus/gplus.php on line 126
Sorry for lots of text… My $buf, $doc don’t have TagName(‘base’) and Attribute(‘href’)
echo $buf:
===================%<===================
Google Accounts
Account
Email:
Password:
Remember me
copy;2011 Google
===================%<===================
Oops.. All html was cut out by WP.
Here’s my $buf: http://pastie.org/2798063
Very good script, it works perfect after some modifications ! Thanks a lot
Can you please submit the modifications? It would save me some time. Thank you
I would also like to hear about modifications.
Still doesn’t work for me.
I did some modifications, but the script is still in early alpha stages :) It works for me now though…
There are currently two issues:
-Mobile phone security confirmation must be disabled
-Mobile Google+ location terms of agreement must be accepted, which can be done once manually by visiting G+ on a phone (or fake the useragent in a browser)
PHP Fatal error: Call to a member function getAttribute() on a non-object in /home/****/tmp/gplus/gplus2.php on line 145
Still doesn’t work for me.. Tried both turning on and off 2-step auth, tried both touch/basic mobile versions of the site. Anyway, can’t pass this authentication.
Thanks for commiting to git this script )
How do you use it? What links do you visit before launching the PHP? Do you have 2-step authorization? Does it work only for regular accounts (*@gmail.com) or for GoogleAps accounts too (*@mydomain.com)? What rows do you have in your cookie?
1.) Two step verification must be turned off, of course :)
2.) It also works for GoogleApps.
Fixed for now… I was getting the same error!
Google removed “base href=…” element recently so I had to fix the script. $baseurl is now determined via curl_info(). It works for me again. I pushed the new version to GitHub and you can download it here too.
Google+ is going through a lot of changes daily, so it might take a while before this code becomes stable. But i would be really happy to see someone join me on this project :)
At last! Works for me )
But still it’s a great security breach in turning off the 2-step auth.
Promoted the GIT src to several people on stackoverflow.
Doesn’t work for me any more
https://m.google.com/app/plus/?v=compose&group=m1c&hideloc=1 is now gone, its now being pasted to https://m.google.com/app/plus/mp/165/data with plain POST. And although I manage to post fake data and accept result with weird “while” cycles in there.. it doesn’t show up.
Also, on my hosting CURLOPT_FOLLOWLOCATION was disabled because of safe mode.
Thanks, I will look into it!
Works quite good! Thanks a lot!
Only the visibility of the post is set to “limited”, which means, that it is only visible of members following me. Is it possible to set the visibility to “public”?
Yes, I changed the visibility to public now. All I had to do is add group=b0 parameter near group=m1c when posting the new status.
have you found a solution for update_page_status this time?
Not yet, it’s not as easy as profile updating at all. But i’ll be working on it.
is there an API to post the status update?
Not yet. I don’t know what’s taking Google so long…
The script is giving
parse error, expecting `’)” on line 90
What is needed to fix that or can you put up a new script?
Hi, can you help me please, I have this error:
Warning: DOMDocument::loadXML() [domdocument.loadxml]: EntityRef: expecting ‘;’ in Entity, line: 60 in /***/index.php on line 76
Fatal error: Call to a member function getAttribute() on a non-object in /***/index.php on line 90
That is the error I’m getting also.
Pauly fixed the script. You can download the new version now.
@Vahe and anyone else having trouble, it’s down to & encoding on the google plus page that is first fetched, the & are not encoded right so DOMDocument can’t do it’s stuff. If you edit the code and change
$buf = utf8_decode(html_entity_decode(curl_exec($ch)));
curl_close($ch);
to
$buf = utf8_decode(html_entity_decode(curl_exec($ch)));
$buf = str_replace( ‘&’, ‘&’, $buf ); // just in case any correctly encoded
$buf = str_replace( ‘&’, ‘&’, $buf ); // now encode them all again
curl_close($ch);
That’ll do it… just in case wordpress messes with what I have entered the code is up here on github too https://github.com/pauly/gplus-bot/tree/patch-1
@Luka thanks for this code it’s great.
Thanks Pauly, the script is now merged.
Yeah wordpress messed with my code above and changed all the & amp ; to just & again so follow the github link…
Hi guys.
Pauly’s script is not working for me without adding
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
otherwise
Curl-Error: SSL certificate problem, verify that the CA cert is OK.
not sure whether more problems might come up
HI,I don’t understand what this script do, can it add people in my circles automatically.
Thanks in advance
Thanks a lot ,,
But please help me, I have this problem:
Fatal error: Call to a member function getAttribute() on a non-object in /home/a4763597/public_html/gplus.php on line 92
Please reply to me as fast as possible ..
Sorry,, I was change the URL from “https://plus.google.com/” to “https://accounts.google.com/ServiceLoginAuth?service=oz”
becuse the first one is not work and give me this error:
Fatal error: Call to a member function getAttribute() on a non-object in /home/a4763597/public_html/gplus.php on line 92
So,, when I’m change it to the second one, it’s give me this error:
Fatal error: Call to a member function getAttribute() on a non-object in /home/a4763597/public_html/gplus.php on line 92
Please help me,, what can I do to make this script work for me?
I was getting all the errors described above when trying to test on my Localhost Dev server, as soon as I uploaded to my live server, everything worked! Can’t wait for Post to Page to be fixed as well, thanks guys for the great contribution
Is it possible to add a URL and Photo? On G+ I generally post a Link to my blog articles which then automatically show the Title, description and thumbnail image from my articles meta data. Using this script, if I simply pass in he URL of an article, it just post a text link to the article with no other data. Could someone possibly show how to enhance this to show image and data with Link? I am able to pass in a URL, Title, Description, and Image URL, I just do not know the format to pass them in?
I’m having one problem, google says that i’m logging from a location unsual and asking my secondary email.
It’s seems its because i’m not german, can you please tell me how to change the locale.
Please ignore the first comment, but now i have this error
Warning: DOMDocument::loadXML() [domdocument.loadxml]: Input is not proper UTF-8, indicate encoding ! Bytes: 0xED 0×72 0×63 0×75 in Entity, line: 1 in gplus.php on line 140
I’ve replaced with Paulys code but does’t post status, I can log in no problems there
Change loadXML to loadhtml to get rid of XML-errors.
I have uploaded in our server and run the gplus.php file but then showing [+] Sending GET request to: https://plus.google.com/app/basic/login . How I will solve this please help me.
Looks like the script is broken….. it looks like the DOMDocument is empty… nothing to iterate through..
Thoughts?
nice peace of code, it save my much time, thanks a lot.
Hello,
If there is any idea to include the html message to g+ via this script…Its very urgent.. This script shows only the text content..Plz help .. Waiting for a solution…
no one………….reply the above query……..
Hi, I wish for to subscribe for this webpage to obtain latest updates, thus where can i do
it please help out.