<?php
/**
references:
- "GMail RSS feed in PHP" by thimal
- "GMail as an online backup system" by Ilia Alshanetsky
- "Gmail Agent API" by Johnvey Hwang
homepages:
http://gmail-lite.sourceforge.net/
http://sourceforge.net/projects/gmail-lite/
**/
/** library libgmailer **/
/** some constants **/
define("GM_LNK_GMAIL", "https://gmail.google.com/gmail");
define("GM_LNK_LOGIN", "https://www.google.com/accounts/ServiceLoginBoxAuth");
define("GM_LNK_LOGOUT", "https://gmail.google.com/gmail?logout");
define("GM_LNK_REFER", "https://www.google.com/accounts/ServiceLoginBox?service=mail&continue=https%3A%2F%2Fgmail.google.com%2Fgmail");
define("GM_LNK_CONTACT", "https://gmail.google.com/gmail?view=page&name=address");
define("GM_LNK_ATTACHMENT", "https://gmail.google.com/gmail?view=att&disp=att");
define("GM_USER_AGENT", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.4b) Gecko/20040612 Mozilla Firebird/0.9");
define("GM_VER", "0.6.4");
define("GM_COOKIE_KEY", "LIBGMAILER");
define("GM_USE_COOKIE", 0x001);
define("GM_USE_PHPSESSION", 0x002);
define("GM_STANDARD", 0x001);
define("GM_LABEL", 0x002);
define("GM_CONVERSATION", 0x004);
define("GM_QUERY", 0x008);
define("GM_CONTACT", 0x010);
define("GM_ACT_APPLYLABEL", 1);
define("GM_ACT_REMOVELABEL", 2);
define("GM_ACT_STAR", 3);
define("GM_ACT_UNSTAR", 4);
define("GM_ACT_SPAM", 5);
define("GM_ACT_UNSPAM", 6);
define("GM_ACT_READ", 7);
define("GM_ACT_UNREAD", 8);
define("GM_ACT_TRASH", 9);
define("GM_ACT_DELFOREVER", 10);
define("GM_ACT_ARCHIVE", 11);
define("GM_ACT_INBOX", 12);
define("GM_ACT_UNTRASH", 13);
/** for debugger **/
define(D_FILE, "debug.php"); // the debugging data file is in PHP for security reason
define(D_ON, 0);
class GMailer {
var $cookie_str;
var $login;
var $pwd;
var $raw; // raw packets
var $contact_raw; // raw packets for address book
var $timezone;
var $created;
var $use_session;
/** proxy-related **/
var $proxy_host;
var $proxy_auth;
/** methods list *************************
setLoginInfo(login, pass, timezone)
connect()
connectNoCookie()
isConnected()
fetch(query)
fetchBox(type, box, position)
fetchContact()
getAttachmentsOf(Snapshot->conversation, path_to_store_files)
getAttachment(attachment_id, message_containing, filename)
send(to, subject, body, cc, bcc, message_replying, thread_replying, attached_files)
getCookieFromBrowser()
saveCookieToBrowser()
removeCookieFromBrowser()
disconnect()
dump(query)
getSnapshot(type)
getStandardBox()
******************************************/
function GMailer() {
// GMailer needs "curl" extension to work
Debugger::say("Constructing GMailer...");
$this->created = true;
if (!extension_loaded('curl')) {
if (!dl('php_curl.dll') && !dl('curl.so')) {
Debugger::say("Constructing failed: unable to load curl extension.");
$this->created = false;
}
}
if (!function_exists("curl_setopt")) {
Debugger::say("Constructing failed: No curl.");
$this->created = false;
}
$this->proxy_host = "";
$this->proxy_auth = "";
$this->use_session = 2;
Debugger::say("Constructing completed.");
}
function setLoginInfo($my_login, $my_pwd, $my_tz) {
$this->login = $my_login;
$this->pwd = $my_pwd;
$this->timezone = strval($my_tz*-60);
Debugger::say("LoginInfo set.");
}
function setProxy($host, $username, $pwd) {
$this->proxy_host = $host;
if (strlen($username) > 0 || strlen($pwd) > 0) {
$this->proxy_auth = $username.":".$pwd;
}
}
function setSessionMethod($met) {
if ($met & GM_USE_PHPSESSION) {
if (!extension_loaded('session')) {
if (!dl('php_session.dll') && !dl('session.so')) {
Debugger::say("Session: unable to load PHP session extension.");
$this->setSessionMethod(GM_USE_COOKIE | !GM_USE_PHPSESSION); // forced to use custom cookie
return;
}
}
if (!($met & GM_USE_COOKIE)) {
@ini_set("session.use_cookies", 0);
@ini_set("session.use_trans_sid", 1);
Debugger::say("Session: do not using cookie.");
} else {
@ini_set("session.use_cookies", 1);
@ini_set("session.use_trans_sid", 0);
Debugger::say("Session: using cookie.");
}
@ini_set("session.name", "sess");
session_start();
Debugger::say("Session: using PHP session.");
$this->use_session = true;
} else {
Debugger::say("Session: using cookie.");
$this->use_session = false;
}
}
function connectNoCookie() {
Debugger::say("Start connecting without cookie...");
$postdata = "service=mail&Email=".urlencode($this->login)."&Passwd=".urlencode($this->pwd)."&null=Sign%20in&continue=https%3A%2F%2Fgmail.google.com%2Fgmail";
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_URL, GM_LNK_LOGIN);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$result = curl_exec($c);
curl_close($c);
if (strpos($result, "errormsg") > 0) {
$this->cookie_str = "";
Debugger::say("Connect failed: ".$result);
return 0;
}
/** from here we have to perform "cookie-handshaking"... **/
Debugger::say("Start cookie-handshaking...");
$cookies = GMailer::get_cookies($result);
Debugger::say("1st phase cookie obtained: ".$cookie);
// js forward path
$a = strpos($result, "top.location = \"");
$b = strpos($result, ";", $a);
$forward = substr($result, $a+16, $b-($a+16)-1);
Debugger::say("Redirecting: ".$forward);
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_URL, "https://gmail.google.com/accounts/".$forward);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_HEADER, 1);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_COOKIE, $cookies);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$ret = curl_exec($c);
curl_close($c);
$data = GMailer::get_cookies($ret);
$d = ($data)? $data.$gv : $cookies;
$d = $d.";TZ=".$this->timezone;
Debugger::say("2nd phase cookie obtained: ".$d);
$this->cookie_str = $d; // the cookie string obtained from gmail
Debugger::say("Finished connecting without cookie.");
return 1;
}
function connect() {
if ($this->use_session == 2)
$this->setSessionMethod(GM_USE_COOKIE | GM_USE_PHPSESSION); // by default
if (!$this->getSessionFromBrowser()) {
return $this->connectNoCookie() && $this->saveSessionToBrowser();
} else {
Debugger::say("Connect completed by getting cookie from browser.");
return 1;
}
}
function isConnected() {
return (strlen($this->cookie_str) > 0);
}
function fetch($query) {
if ($this->isConnected() == true) {
Debugger::say("Start fetching query: ".$query);
$query .= "&zv=".round(rand(0,1999)*2147483.648); // to fool proxy
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_URL, GM_LNK_GMAIL."?".$query);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$inbox = curl_exec($c);
curl_close($c);
$inbox = str_replace("\n", "", $inbox);
$inbox = str_replace("D([", "\nD([", $inbox);
$inbox = str_replace("]);", "]);\n", $inbox);
$regexp = "|D\(\[(.*)\]\);|U";
preg_match_all($regexp, $inbox, $matches, PREG_SET_ORDER);
$packets = array();
for ($i = 0; $i < count($matches); $i++) {
$off = 0;
$tmp = GMailer::parse_data_packet("[".$matches[$i][1]."]", $off);
if (array_key_exists($tmp[0], $packets) || ($tmp[0]=="mi"||$tmp[0]=="mb")) {
if ($tmp[0]=="t"||$tmp[0]=="ts")
$packets[$tmp[0]] = array_merge($packets[$tmp[0]], array_slice($tmp, 1));
if ($tmp[0]=="mi"||$tmp[0]=="mb") {
if (array_key_exists("mg", $packets))
array_push($packets["mg"],$tmp);
else
$packets["mg"] = array($tmp);
}
} else {
$packets[$tmp[0]] = $tmp;
}
}
$this->raw = $packets;
Debugger::say("Fetch completed.");
return 1;
} else { // not logged in yet
Debugger::say("Fetch failed: not connected.");
return 0;
}
}
function fetchBox($type, $box, $pos) {
if ($this->isConnected() == true) {
switch ($type) {
case GM_STANDARD:
$q = "search=".$box."&view=tl&start=".$pos;
break;
case GM_LABEL:
$q = "search=cat&cat=".$box."&view=tl&start=".$pos;
break;
case GM_CONVERSATION:
$q = "search=inbox&view=cv";
if (is_array($box)) {
$q .= "&th=".$box[0];
for ($i = 1; $i < count($box); $i++)
$q .= "&msgs=".$box[$i];
} else {
$q .= "&th=".$box;
}
break;
case GM_QUERY:
$q = "search=query&q=".urlencode($box)."&view=tl&start=".$pos;
break;
default:
$q = "search=inbox&view=tl&start=0&init=1";
break;
}
$this->fetch($q);
return 1;
} else {
return 0;
}
}
function fetchContact() {
if ($this->isConnected() == true) {
Debugger::say("Fetching contact list...");
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_URL, GM_LNK_CONTACT);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$inbox = curl_exec($c);
curl_close($c);
$inbox = str_replace("\n", "", $inbox);
$inbox = str_replace("\r", "", $inbox);
$regexp = "|\[\[(.*)\]\];|U";
preg_match_all($regexp, $inbox, $matches, PREG_SET_ORDER);
$packets = array();
$off = 0;
$tmp = GMailer::parse_data_packet("[[".$matches[0][1]."]]", $off);
$packets = array("co"=>$tmp);
$this->contact_raw = $packets;
Debugger::say("Fetched entried: ".count($this->contact_raw));
Debugger::say("Completed fetching contact list.");
return 1;
} else { // not logged in yet
Debugger::say("Failed to fetch contact list: not connected.");
return 0;
}
}
function getAttachmentsOf($convs, $path) {
if ($this->isConnected() == true) {
if (!is_array($convs)) {
$convs = array($convs); // array wrapper
}
$final = array();
foreach ($convs as $v) {
if (count($v["attachment"]) > 0) {
foreach ($v["attachment"] as $vv) {
$f = $path."/".$vv["filename"];
while (file_exists($f)) {
$f = $path."/".$vv["filename"].".".round(rand(0,1999));
}
if ($this->getAttachment($vv["id"],$v["id"],$f)) {
array_push($final, $f);
}
}
}
}
return $final;
} else {
return 0;
}
}
function getAttachment($attid, $msgid, $filename) {
if ($this->isConnected() == true) {
Debugger::say("Start getting attachment...");
$query = "&attid=".urlencode($attid)."&th=".urlencode($msgid);
$fp = fopen($filename, "wb");
if ($fp) {
$c = curl_init();
curl_setopt($c, CURLOPT_FILE, $fp);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
curl_setopt($c, CURLOPT_URL, GM_LNK_ATTACHMENT.$query);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
curl_exec($c);
curl_close($c);
fclose($fp);
} else {
Debugger::say("Failed to get attachment: cannot fopen the file.");
return 0;
}
Debugger::say("Completed getting attachment.");
return 1;
} else {
Debugger::say("Failed to get attachment: not connected.");
return 0;
}
}
function dump($query) {
if ($this->isConnected() == true) {
Debugger::say("Dumping...");
$query .= "&zv=".round(rand(0,1999)*2147483.648); // to fool proxy
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_URL, GM_LNK_GMAIL."?".$query);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$page = curl_exec($c);
curl_close($c);
return $page;
Debugger::say("Finished dumping ".strlen($page)." bytes.");
} else { // not logged in yet
Debugger::say("Failed to dump: not connected.");
return 0;
}
}
function send($to, $subj, $body, $cc, $bcc, $mid, $tid, $files) {
if ($this->isConnected()) {
Debugger::say("Starting to send mail...");
$postdata = array();
$postdata["view"] = "sm";
$postdata["msgbody"] = stripslashes($body);
$postdata["to"] = stripslashes($to);
$postdata["subject"] = stripslashes($subj);
$postdata["cc"] = stripslashes($cc);
$postdata["bcc"] = stripslashes($bcc);
$postdata["rm"] = $mid;
$postdata["th"] = $tid;
$postdata["draft"] = "";
$postdata["cmid"] = 1;
//echo $this->cookie_str;
$cc = split(";", $this->cookie_str);
foreach ($cc as $cc_part) {
//echo "***".$cc_part."****<br>";
$cc_parts = split("=", $cc_part);
//echo "***".$cc_parts[0]."******".$cc_parts[1]."****<br>";
if (trim($cc_parts[0]) == "GMAIL_AT") {
$postdata["at"] = $cc_parts[1];
break;
}
}
if (is_array($files)) {
for ($i = 0; $i < count($files); $i++) {
$postdata["file".$i] = "@".realpath($files[$i]);
}
}
//echo $postdata;
set_time_limit(150);
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_URL, "https://gmail.google.com/gmail");
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
curl_setopt($c, CURLOPT_POST, 1);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$result = curl_exec($c);
curl_close($c);
Debugger::say("Finished sending email.");
return 1;
} else {
Debugger::say("Failed to send email: not connected.");
return 0;
}
}
function performAction($act, $id, $para) {
if ($this->isConnected()) {
Debugger::say("Start performing action...");
if ($act == GM_ACT_DELFOREVER)
$this->performAction(GM_ACT_TRASH, $id, 0); // trash it before
$postdata = "act=";
$action_codes = array("ib", "ac_", "rc_", "st", "xst", "sp", "us", "rd", "ur", "tr", "dl", "rc_^i", "ib", "ib");
$postdata .= isset($action_codes[$act]) ? $action_codes[$act] : $action_codes[GM_ACT_INBOX];
if ($act == GM_ACT_APPLYLABEL || $act == GM_ACT_REMOVELABEL) {
$postdata .= $para;
}
$cc = split(";", $this->cookie_str);
foreach ($cc as $cc_part) {
$cc_parts = split("=", $cc_part);
if (trim($cc_parts[0]) == "GMAIL_AT") {
$postdata .= "&at=".$cc_parts[1];
break;
}
}
if (is_array($id)) {
foreach ($id as $t) {
$postdata .= "&t=".$t;
}
} else {
$postdata .= "&t=".$id;
}
$postdata .= "&vp=";
if ($act == GM_ACT_UNTRASH || $act == GM_ACT_DELFOREVER)
$link = "https://gmail.google.com/gmail?search=trash&view=tl&start=0";
else
$link = "https://gmail.google.com/gmail?search=query&q=&view=tl&start=0";
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_URL, $link);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, $postdata);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
$result = curl_exec($c);
curl_close($c);
Debugger::say("Finished performing action.");
return 1;
} else {
Debugger::say("Failed to perform action: not connected.");
return 0;
}
}
function getSessionFromBrowser() {
Debugger::say("Start getting session from browser...");
if (!$this->use_session) {
return $this->getCookieFromBrowser();
}
if (isset($_SESSION[GM_COOKIE_KEY])) {
$this->cookie_str = base64_decode($_SESSION[GM_COOKIE_KEY]);
Debugger::say("completed getting session from browser: ".$this->cookie_str);
return 1;
} else {
Debugger::say("Failed to read session ".GM_COOKIE_KEY." from browser.");
return 0;
}
}
function getCookieFromBrowser() {
Debugger::say("Start getting cookie from browser...");
if (!isset($_COOKIE)) {
Debugger::say("Failed to get any cookie from browser.");
return 0;
}
if (count($_COOKIE) == 0) {
Debugger::say("Failed to get non-empty cookie array from browser.");
return 0;
}
if (isset($_COOKIE[GM_COOKIE_KEY])) {
$this->cookie_str = base64_decode($_COOKIE[GM_COOKIE_KEY]);
Debugger::say("Completed getting cookie from browser: ".$this->cookie_str);
return 1;
} else {
Debugger::say("Failed to read cookie ".GM_COOKIE_KEY." from browser.");
return 0;
}
}
function saveSessionToBrowser() {
Debugger::say("Start saving session to browser...");
if ($this->isConnected()) {
if (!$this->use_session)
return $this->saveCookieToBrowser();
$_SESSION[GM_COOKIE_KEY] = base64_encode($this->cookie_str);
Debugger::say("Just saved session: ".GM_COOKIE_KEY."=".base64_encode($this->cookie_str));
Debugger::say("Completed saving session to browser.");
return 1;
}
Debugger::say("Failed to save session to browser: not connected.");
return 0;
}
function saveCookieToBrowser() {
Debugger::say("Start saving cookie to browser...");
if ($this->isConnected()) {
if (strpos($_SERVER["HTTP_HOST"],":"))
$domain = substr($_SERVER["HTTP_HOST"],0,strpos($_SERVER["HTTP_HOST"],":"));
else
$domain = $_SERVER["HTTP_HOST"];
Debugger::say("Saving cookies with domain=".$domain);
header("Set-Cookie: ".GM_COOKIE_KEY."=".base64_encode($this->cookie_str)."; Domain=".$domain.";");
Debugger::say("Just saved cookie: ".GM_COOKIE_KEY."=".base64_encode($this->cookie_str));
Debugger::say("Completed saving cookie to browser.");
return 1;
}
Debugger::say("Failed to save cookie to browser: not connected.");
return 0;
}
function removeSessionFromBrowser() {
Debugger::say("Start removing session from browser...");
if (!$this->use_session)
return $this->removeCookieFromBrowser();
if (isset($_SESSION[GM_COOKIE_KEY])) {
unset($_SESSION[GM_COOKIE_KEY]);
Debugger::say("Just removed session: ".GM_COOKIE_KEY);
} else {
Debugger::say("Cannot find libgmailer session: ".GM_COOKIE_KEY);
}
Debugger::say("Finished removing session from browser.");
}
function removeCookieFromBrowser() {
Debugger::say("Start removing cookie from browser...");
if (isset($_COOKIE)) {
if (isset($_COOKIE[GM_COOKIE_KEY])) {
// libgmailer cookie exists
if (strpos($_SERVER["HTTP_HOST"],":"))
$domain = substr($_SERVER["HTTP_HOST"],0,strpos($_SERVER["HTTP_HOST"],":"));
else
$domain = $_SERVER["HTTP_HOST"];
Debugger::say("Removing cookies with domain=".$domain);
header("Set-Cookie: ".GM_COOKIE_KEY."=1; Discard; Max-Age=0; Domain=".$domain.";");
Debugger::say("Just removed cookie: ".GM_COOKIE_KEY);
} else {
Debugger::say("Cannot find libgmailer cookie: ".GM_COOKIE_KEY);
}
} else {
Debugger::say("Cannot find any cookie from browser.");
}
Debugger::say("Finished removing cookie from browser.");
}
function disconnect() {
Debugger::say("Start disconnecting...");
/** logout from gamil.google.com too **/
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($c, CURLOPT_URL, GM_LNK_LOGOUT);
curl_setopt($c, CURLOPT_SSL_VERIFYHOST, 2);
$this->CURL_PROXY($c);
curl_setopt($c, CURLOPT_USERAGENT, GM_USER_AGENT);
curl_setopt($c, CURLOPT_COOKIE, $this->cookie_str);
curl_setopt($c, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($c, CURLOPT_REFERER, GM_LNK_REFER);
curl_exec($c);
curl_close($c);
Debugger::say("Logged-out from GMail.");
$this->removeSessionFromBrowser();
$this->cookie_str = "";
Debugger::say("Completed disconnecting.");
}
function getSnapshot($type) {
if ($type & (GM_STANDARD|GM_LABEL|GM_CONVERSATION|GM_QUERY))
return new GMailSnapshot($type, $this->raw);
elseif ($type & GM_CONTACT)
return new GMailSnapshot($type, $this->contact_raw);
else
return new GMailSnapshot(GM_STANDARD, $this->raw); // assuming normal by default
}
function getStandardBox() {
return array("Inbox","Starred","Sent","All","Spam","Trash");
}
/** some helper (static/private) functions **/
function CURL_PROXY($cc) {
if (strlen($this->proxy_host) > 0) {
curl_setopt($cc, CURLOPT_PROXY, $this->proxy_host);
if (strlen($this->proxy_auth) > 0)
curl_setopt($cc, CURLOPT_PROXYUSERPWD, $this->proxy_auth);
}
}
function get_cookies($header) {
preg_match_all('!Set-Cookie: ([^;\s]+)($|;)!', $header, $match);
$cookie = "";
foreach ($match[1] as $val) {
if ($val{0} == '=') {
continue;
}
$cookie .= $val . ";";
}
return substr($cookie, 0, -1);
}
function parse_data_packet($input, &$offset) {
$output = array();
// state variables
$isQuoted = false; // track when we are inside quotes
$dataHold = ""; // temporary data container
$lastCharacter = " ";
// walk through the entire string
for($i=1; $i < strlen($input); $i++) {
switch($input[$i]) {
case "[": // handle start of array marker
if(!$isQuoted) {
// recurse any nested arrays
array_push($output, GMailer::parse_data_packet(substr($input,$i), $offset));
// the returning recursive function write out the total length of the characters consumed
$i += $offset;
// assume that the last character is a closing bracket
$lastCharacter = "]";
} else {
$dataHold .= "[";
}
break;
case "]": // handle end of array marker
if(!$isQuoted) {
if($dataHold != "") {
array_push($output, $dataHold);
}
// determine total number of characters consumed (write to reference)
$offset = $i;
return $output;
} else {
$dataHold .= "]";
break;
}
case '"': // toggle quoted state
if($isQuoted) {
$isQuoted = false;
} else {
$isQuoted = true;
$lastCharacter = '"';
}
break;
case ',': // find end of element marker and add to array
if(!$isQuoted) {
if($dataHold != "") { // this is to filter out adding extra elements after an empty array
array_push($output, $dataHold);
$dataHold = "";
} else if($lastCharacter == '"') { // this is to catch empty strings
array_push($output, "");
}
} else {
$dataHold .= ",";
}
break;
case '\\':
if ($i < strlen($input) - 1) {
switch($input[$i+1]) {
case "\\": /* for the case \\ */
$dataHold .= '\\';
$lastCharacter = '\\';
break;
case '"': /* for the case \" */
$dataHold .= '"';
$lastCharacter = '\"';
$i += 1;
break;
case "'": /* for the case \' */
$dataHold .= "'";
$lastCharacter = "\'";
$i += 1;
break;
case "n": /* for the case \n */
$dataHold .= "\n";
$lastCharacter = "\n";
$i += 1;
break;
case "r": /* for the case \r */
$dataHold .= "\r";
$lastCharacter = "\r";
$i += 1;
break;
default:
}
}
break;
default: // regular characters are added to the data container
$dataHold .= $input[$i];
break;
}
}
return $output;
}
}
class GMailSnapshot {
function GMailSnapshot($type, $raw) {
// input: raw packet generated by GMailer
if (!is_array($raw))
return null;
if (count($raw) == 0)
return null;
if ($type & (GM_STANDARD|GM_LABEL|GM_CONVERSATION|GM_QUERY)) {
$this->gmail_ver = $raw["v"][1];
$this->quota_mb = $raw["qu"][1];
$this->quota_per = $raw["qu"][3];
$this->std_box_new = array_slice($raw["ds"],1);
if (isset($raw["p"])) {
$this->owner = $raw["p"][5][1];
$this->owner_email = $raw["p"][6][1];
}
$this->have_invit = $raw["i"][1];
$this->label_list = array();
$this->label_new = array();
foreach ($raw["ct"][1] as $v) {
array_push($this->label_list, $v[0]);
array_push($this->label_new, $v[1]);
}
if (isset($raw["ts"])) {
$this->view = (GM_STANDARD|GM_LABEL|GM_QUERY);
$this->box_name = $raw["ts"][5];
$this->box_total = $raw["ts"][3];
$this->box_pos = $raw["ts"][1];
}
if (isset($raw["t"])) {
$this->box = array();
foreach ($raw["t"] as $t) {
if ($t == "t") continue;
$b = array(
"id"=>$t[0],
"is_read"=>($t[1]==1?1:0),
"is_starred"=>($t[2]==1?1:0),
"date"=>strip_tags($t[3]),
"sender"=>strip_tags($t[4],"<b>"),
"flag"=>$t[5],
"subj"=>strip_tags($t[6],"<b>"),
"snippet"=>$t[7],
"labels"=>(count($t[8])==0?0:$t[8]),
"attachment"=>strlen($t[9])==0?array():explode(",",$t[9]),
"msgid"=>$t[10]
);
array_push($this->box, $b);
}
}
if (isset($raw["cs"])) {
$this->view = GM_CONVERSATION;
$this->conv_title = $raw["cs"][2];
$this->conv_total = $raw["cs"][8];
$this->conv_id = $raw["cs"][1];
$this->conv_labels = count($raw["cs"][5])==0?0:$raw["cs"][5];
$ij = array_search("^i", $this->conv_labels);
if (!($ij === false)) {
$this->conv_labels[$ij] = "Inbox";
}
$this->conv_starred = false;
$this->conv = array();
for ($i = 0; $i < count($raw["mg"]); $i++) {
if ($raw["mg"][$i][0] == "mb" && $i > 0) {
$b["body"] .= $raw["mg"][$i][1];
if ($raw["mg"][$i][2] == 0) {
array_push($this->conv, $b);
unset($b);
}
} elseif ($raw["mg"][$i][0] == "mi") {
if (isset($b)) {
array_push($this->conv, $b);
unset($b);
}
$b = array();
$b["index"] = $raw["mg"][$i][2];
$b["id"] = $raw["mg"][$i][3];
$b["is_star"] = $raw["mg"][$i][4];
if ($b["is_star"] == 1)
$this->conv_starred = true;
$b["sender"] = $raw["mg"][$i][6];
$b["sender_email"] = str_replace("\"", "", $raw["mg"][$i][7]); // remove annoying d-quotes in address
$b["recv"] = $raw["mg"][$i][8];
$b["recv_email"] = str_replace("\"", "", $raw["mg"][$i][10]);
$b["reply_email"] = str_replace("\"", "", $raw["mg"][$i][13]);
$b["dt_easy"] = $raw["mg"][$i][9];
$b["dt"] = $raw["mg"][$i][14];
$b["subj"] = $raw["mg"][$i][15];
$b["snippet"] = $raw["mg"][$i][16];
$b["attachment"] = array();
foreach ($raw["mg"][$i][17] as $bb) {
array_push($b["attachment"], array("id"=>$bb[0],"filename"=>$bb[1],"type"=>$bb[2],"size"=>$bb[3]));
}
//$b["attachment"] = count($raw["mg"][$i][17])==0 ? 0 : 1;
$b["body"] = "";
}
}
if (isset($b)) array_push($this->conv, $b);
}
} elseif ($type & GM_CONTACT) {
$this->contacts = array();
$this->contacts_freq = array();
foreach ($raw["co"] as $a) {
$b = array(
"name"=>$a[2],
"email"=>str_replace("\"", "", $a[1]),
"notes"=>$a[3],
"is_freq"=>$a[4]
);
array_push($this->contacts, $b);
if ($a[4] == 1)
array_push($this->contacts_freq, $b);
}
$this->view = GM_CONTACT;
} else {
return null;
}
}
}
class Debugger {
function say($str) {
if (D_ON) {
$fd = fopen(D_FILE, "a+");
fwrite($fd, "<?php ".$str." ?>\n");
fclose($fd);
}
}
}
Debugger::say("======== ".date("j M Y H:i:s")." libgmailer STARTED! ===============================");
?>