Is it possible to get EXTERNAL_LINKS using the GWT API? - php

I am trying to use the code from #eyecatchup (https://github.com/eyecatchup/php-webmaster-tools-downloads) to get data via the Google Webmaster Tools API. I am able to get "TOP_PAGES" and "TOP QUERIES" but that is it. What I really want is "EXTERNAL_LINKS" or even "LATEST_LINKS".
Here is the gwtdata.php code:
<pre>
<?php
/**
* PHP class for downloading CSV files from Google Webmaster Tools.
*
* This class does NOT require the Zend gdata package be installed
* in order to run.
*
* Copyright 2012 eyecatchUp UG. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* #author: Stephan Schmitz <eyecatchup#gmail.com>
* #link: https://code.google.com/p/php-webmaster-tools-downloads/
*/
class GWTdata
{
const HOST = "https://www.google.com";
const SERVICEURI = "/webmasters/tools/";
public $_language, $_tables, $_daterange, $_downloaded, $_skipped;
private $_auth, $_logged_in;
public function __construct()
{
$this->_auth = false;
$this->_logged_in = false;
$this->_language = "en";
$this->_daterange = array("","");
$this->_tables = array("TOP_PAGES", "TOP_QUERIES",
"CRAWL_ERRORS", "CONTENT_ERRORS", "CONTENT_KEYWORDS",
"INTERNAL_LINKS", "EXTERNAL_LINKS", "SOCIAL_ACTIVITY"
);
$this->_errTablesSort = array(0 => "http",
1 => "not-found", 2 => "restricted-by-robotsTxt",
3 => "unreachable", 4 => "timeout", 5 => "not-followed",
"kAppErrorSoft-404s" => "soft404", "sitemap" => "in-sitemaps"
);
$this->_errTablesType = array(0 => "web-crawl-errors",
1 => "mobile-wml-xhtml-errors", 2 => "mobile-chtml-errors",
3 => "mobile-operator-errors", 4 => "news-crawl-errors"
);
$this->_downloaded = array();
$this->_skipped = array();
}
/**
* Sets content language.
*
* #param $str String Valid ISO 639-1 language code, supported by Google.
*/
public function SetLanguage($str)
{
$this->_language = $str;
}
/**
* Sets features that should be downloaded.
*
* #param $arr Array Valid array values are:
* "TOP_PAGES", "TOP_QUERIES", "CRAWL_ERRORS", "CONTENT_ERRORS",
* "CONTENT_KEYWORDS", "INTERNAL_LINKS", "EXTERNAL_LINKS",
* "SOCIAL_ACTIVITY".
*/
public function SetTables($arr)
{
if(is_array($arr) && !empty($arr) && sizeof($arr) <= 2) {
$valid = array("TOP_PAGES","TOP_QUERIES","CRAWL_ERRORS","CONTENT_ERRORS",
"CONTENT_KEYWORDS","INTERNAL_LINKS","EXTERNAL_LINKS","SOCIAL_ACTIVITY");
$this->_tables = array();
for($i=0; $i < sizeof($arr); $i++) {
if(in_array($arr[$i], $valid)) {
array_push($this->_tables, $arr[$i]);
} else { throw new Exception("Invalid argument given."); }
}
} else { throw new Exception("Invalid argument given."); }
}
/**
* Sets daterange for download data.
*
* #param $arr Array Array containing two ISO 8601 formatted date strings.
*/
public function SetDaterange($arr)
{
if(is_array($arr) && !empty($arr) && sizeof($arr) == 2) {
if(self::IsISO8601($arr[0]) === true &&
self::IsISO8601($arr[1]) === true) {
$this->_daterange = array(str_replace("-", "", $arr[0]),
str_replace("-", "", $arr[1]));
return true;
} else { throw new Exception("Invalid argument given."); }
} else { throw new Exception("Invalid argument given."); }
}
/**
* Returns array of downloaded filenames.
*
* #return Array Array of filenames that have been written to disk.
*/
public function GetDownloadedFiles()
{
return $this->_downloaded;
}
/**
* Returns array of downloaded filenames.
*
* #return Array Array of filenames that have been written to disk.
*/
public function GetSkippedFiles()
{
return $this->_skipped;
}
/**
* Checks if client has logged into their Google account yet.
*
* #return Boolean Returns true if logged in, or false if not.
*/
private function IsLoggedIn()
{
return $this->_logged_in;
}
/**
* Attempts to log into the specified Google account.
*
* #param $email String User's Google email address.
* #param $pwd String Password for Google account.
* #return Boolean Returns true when Authentication was successful,
* else false.
*/
public function LogIn($email, $pwd)
{
$url = self::HOST . "/accounts/ClientLogin";
$postRequest = array(
'accountType' => 'HOSTED_OR_GOOGLE',
'Email' => $email,
'Passwd' => $pwd,
'service' => "sitemaps",
'source' => "Google-WMTdownloadscript-0.1-php"
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postRequest);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if($info['http_code'] == 200) {
preg_match('/Auth=(.*)/', $output, $match);
if(isset($match[1])) {
$this->_auth = $match[1];
$this->_logged_in = true;
return true;
} else { return false; }
} else { return false; }
}
/**
* Attempts authenticated GET Request.
*
* #param $url String URL for the GET request.
* #return Mixed Curl result as String,
* or false (Boolean) when Authentication fails.
*/
public function GetData($url)
{
if(self::IsLoggedIn() === true) {
$url = self::HOST . $url;
$head = array("Authorization: GoogleLogin auth=".$this->_auth,
"GData-Version: 2");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $head);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return ($info['http_code']!=200) ? false : $result;
} else { return false; }
}
/**
* Gets all available sites from Google Webmaster Tools account.
*
* #return Mixed Array with all site URLs registered in GWT account,
* or false (Boolean) if request failed.
*/
public function GetSites()
{
if(self::IsLoggedIn() === true) {
$feed = self::GetData(self::SERVICEURI."feeds/sites/");
if($feed !== false) {
$sites = array();
$doc = new DOMDocument();
$doc->loadXML($feed);
foreach ($doc->getElementsByTagName('entry') as $node) {
array_push($sites,
$node->getElementsByTagName('title')->item(0)->nodeValue);
}
return $sites;
} else { return false; }
} else { return false; }
}
/**
* Gets the download links for an available site
* from the Google Webmaster Tools account.
*
* #param $url String Site URL registered in GWT.
* #return Mixed Array with keys TOP_PAGES and TOP_QUERIES,
* or false (Boolean) when Authentication fails.
*/
public function GetDownloadUrls($url)
{
if(self::IsLoggedIn() === true) {
$_url = sprintf(self::SERVICEURI."downloads-list?hl=%s&siteUrl=%s",
$this->_language,
urlencode($url));
$downloadList = self::GetData($_url);
return json_decode($downloadList, true);
} else { return false; }
}
/**
* Downloads the file based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional path to save CSV to (no trailing slash!).
*/
public function DownloadCSV($site, $savepath=".")
{
if(self::IsLoggedIn() === true) {
$downloadUrls = self::GetDownloadUrls($site);
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
$tables = $this->_tables;
foreach($tables as $table) {
if($table=="CRAWL_ERRORS") {
self::DownloadCSV_CrawlErrors($site, $savepath);
}
elseif($table=="CONTENT_ERRORS") {
self::DownloadCSV_XTRA($site, $savepath,
"html-suggestions", "\)", "CONTENT_ERRORS", "content-problems-dl");
}
elseif($table=="CONTENT_KEYWORDS") {
self::DownloadCSV_XTRA($site, $savepath,
"keywords", "\)", "CONTENT_KEYWORDS", "content-words-dl");
}
elseif($table=="INTERNAL_LINKS") {
self::DownloadCSV_XTRA($site, $savepath,
"internal-links", "\)", "INTERNAL_LINKS", "internal-links-dl");
}
elseif($table=="EXTERNAL_LINKS") {
self::DownloadCSV_XTRA($site, $savepath,
"external-links-domain", "\)", "EXTERNAL_LINKS", "external-links-domain-dl");
}
elseif($table=="SOCIAL_ACTIVITY") {
self::DownloadCSV_XTRA($site, $savepath,
"social-activity", "x26", "SOCIAL_ACTIVITY", "social-activity-dl");
}
else {
$finalName = "$savepath/$table-$filename.csv";
$finalUrl = $downloadUrls[$table] ."&prop=ALL&db=%s&de=%s&more=true";
$finalUrl = sprintf($finalUrl, $this->_daterange[0], $this->_daterange[1]);
self::SaveData($finalUrl,$finalName);
}
}
} else { return false; }
}
/**
* Downloads "unofficial" downloads based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional path to save CSV to (no trailing slash!).
*/
public function DownloadCSV_XTRA($site, $savepath=".", $tokenUri, $tokenDelimiter, $filenamePrefix, $dlUri)
{
if(self::IsLoggedIn() === true) {
$uri = self::SERVICEURI . $tokenUri . "?hl=%s&siteUrl=%s";
$_uri = sprintf($uri, $this->_language, $site);
$token = self::GetToken($_uri, $tokenDelimiter);
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
$finalName = "$savepath/$filenamePrefix-$filename.csv";
$url = self::SERVICEURI . $dlUri . "?hl=%s&siteUrl=%s&security_token=%s&prop=ALL&db=%s&de=%s&more=true";
$_url = sprintf($url, $this->_language, $site, $token, $this->_daterange[0], $this->_daterange[1]);
self::SaveData($_url,$finalName);
} else { return false; }
}
/**
* Downloads the Crawl Errors file based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional: Path to save CSV to (no trailing slash!).
* #param $separated Boolean Optional: If true, the method saves separated CSV files
* for each error type. Default: Merge errors in one file.
*/
public function DownloadCSV_CrawlErrors($site, $savepath=".", $separated=false)
{
if(self::IsLoggedIn() === true) {
$type_param = "we";
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
if($separated) {
foreach($this->_errTablesSort as $sortid => $sortname) {
foreach($this->_errTablesType as $typeid => $typename) {
if($typeid == 1) {
$type_param = "mx";
} else if($typeid == 2) {
$type_param = "mc";
} else {
$type_param = "we";
}
$uri = self::SERVICEURI."crawl-errors?hl=en&siteUrl=$site&tid=$type_param";
$token = self::GetToken($uri,"x26");
$finalName = "$savepath/CRAWL_ERRORS-$typename-$sortname-$filename.csv";
$url = self::SERVICEURI."crawl-errors-dl?hl=%s&siteUrl=%s&security_token=%s&type=%s&sort=%s";
$_url = sprintf($url, $this->_language, $site, $token, $typeid, $sortid);
self::SaveData($_url,$finalName);
}
}
}
else {
$uri = self::SERVICEURI."crawl-errors?hl=en&siteUrl=$site&tid=$type_param";
$token = self::GetToken($uri,"x26");
$finalName = "$savepath/CRAWL_ERRORS-$filename.csv";
$url = self::SERVICEURI."crawl-errors-dl?hl=%s&siteUrl=%s&security_token=%s&type=0";
$_url = sprintf($url, $this->_language, $site, $token);
self::SaveData($_url,$finalName);
}
} else { return false; }
}
/**
* Saves data to a CSV file based on the given URL.
*
* #param $finalUrl String CSV Download URI.
* #param $finalName String Filepointer to save location.
*/
private function SaveData($finalUrl, $finalName)
{
$data = self::GetData($finalUrl);
if(strlen($data) > 1 && file_put_contents($finalName, utf8_decode($data))) {
array_push($this->_downloaded, realpath($finalName));
return true;
} else {
array_push($this->_skipped, $finalName);
return false;
}
}
/**
* Regular Expression to find the Security Token for a download file.
*
* #param $uri String A Webmaster Tools Desktop Service URI.
* #param $delimiter String Trailing delimiter for the regex.
* #return String Returns a security token.
*/
private function GetToken($uri, $delimiter)
{
$matches = array(); $tmp = self::get_data($uri); preg_match_all("#46security_token(.?)$delimiter#si", $tmp, $matches); return #substr($matches[1][0],3,-1);
}
/**
* Validates ISO 8601 date format.
*
* #param $str String Valid ISO 8601 date string (eg. 2012-01-01).
* #return Boolean Returns true if string has valid format, else false.
*/
private function IsISO8601($str)
{
$stamp = strtotime($str);
return (is_numeric($stamp) && checkdate(date('m', $stamp),
date('d', $stamp), date('Y', $stamp))) ? true : false;
}
}
?>
</pre>
And here is the code I am using to try to extract external links:
<pre>
<?php
include 'gwtdata.php';
try {
$email = "***#gmail.com";
$password = "***";
# If hardcoded, don't forget trailing slash!
$website = "***";
# Valid values are "TOP_PAGES", "TOP_QUERIES", "CRAWL_ERRORS",
# "CONTENT_ERRORS", "CONTENT_KEYWORDS", "INTERNAL_LINKS",
# "EXTERNAL_LINKS" and "SOCIAL_ACTIVITY".
$tables = array("EXTERNAL_LINKS");
$gdata = new GWTdata();
if($gdata->LogIn($email, $password) === true)
{
$gdata->SetTables($tables);
$gdata->DownloadCSV($website, "./csv");
}
$files = $gdata->GetDownloadedFiles();
foreach($files as $file)
{
print "Saved $file\n</a>";
}
} catch (Exception $e) {
die($e->getMessage());
}
?>
</pre>

Part of the author's answer here https://stackoverflow.com/a/16002159/624466, is the answer to your question too.
[..] this code is neither released by Google nor makes use of an official
API, but is rather a custom script processing data from the web
interface.
[..] there were some changes to the Google Webmaster Tools web
interface [..]. Thus,
it broke some functionality of the PHP class GWTdata

Related

Function mod_scorm_insert_scorm_tracks "Invalid parameter"

I have problem with a WebService function for moodle callen "mod_scorm_insert_scorm_tracks"
This function is used for inserting track information (i.e. star time) of a user in his SCORM progress.
Part of the estructure of this function is
scoid= int
attempt= int
tracks[0][element]= string
tracks[0][value]= string
NEW
PHP structe has to look like this
[tracks] =>
Array
(
[0] =>
Array
(
[element] => string
[value] => string
)
)
I have used one of the examples they had in his website everything was fine until I got this error
<b>Notice</b>: Array to string conversion in <b>C:\xampp\htdocs\otros\PHP-REST\curl.php</b> on line <b>247</b><br />
<?xml version="1.0" encoding="UTF-8" ?>
<EXCEPTION class="invalid_parameter_exception">
<ERRORCODE>invalidparameter</ERRORCODE>
<MESSAGE>Invalid parameter value detected</MESSAGE>
<DEBUGINFO>tracks => Invalid parameter value detected: Only arrays accepted. The bad value is: 'Array'</DEBUGINFO>
</EXCEPTION>
And the problem seems to be here:
$item1 = new stdClass();
$item1->scoid = '2';
$item1->attempt = '1';
$item1->tracks = array(
array(
array(
'element' => 'x.start.time',
'value' => '1473102672'
),
),
array(
array(
'element' => 'x.start.time',
'value' => '1473102680'
),
),
);
I tried in many ways
$item1 = new stdClass();
$item1->scoid = '2';
$item1->attempt = '1';
$item1->tracks = array('element' => 'x.start.time','value' => '1473102672');
or
$item1 = new stdClass();
$item1->scoid = '2';
$item1->attempt = '1';
$item1->tracks = array(array ('element' => 'x.start.time','value' => '1473102672'));
And still getting the same message, I'm pretty that is problema with my wyntax but I have tried in many ways and still not working I hope yo can help me.
Complete Code:
/// SETUP - NEED TO BE CHANGED
$token = '481bf3d85a7eb539e37eabc88feccb3c';
$domainname = 'http://localhost/moodle';
//$functionname = 'mod_scorm_launch_sco';
$functionname = 'mod_scorm_insert_scorm_tracks';
//$functionname ='mod_scorm_view_scorm';
// REST RETURNED VALUES FORMAT
$restformat = 'xml'; //Also possible in Moodle 2.2 and later: 'json'
//Setting it to 'json' will fail all calls on earlier Moodle version
$item1 = new stdClass();
$item1->scoid = '2';
$item1->attempt = '1';
$item1->tracks = array(
array(
array(
'element' => 'x.start.time',
'value' => 1473102672
),
),
array(
array(
'element' => 'x.start.time',
'value' => 1473102680
),
),
);
$params = $item1;
/// REST CALL
header('Content-Type: text/plain');
$serverurl = $domainname . '/webservice/rest/server.php'. '?wstoken=' . $token . '&wsfunction='.$functionname;
require_once('./curl.php');
$curl = new curl;
//if rest format == 'xml', then we do not add the param for backward compatibility with Moodle < 2.2
$restformat = ($restformat == 'json')?'&moodlewsrestformat=' . $restformat:'';
$resp = $curl->post($serverurl . $restformat, $params);
print_r($resp);
curl.php
<?php
/**
* cURL class
*
* This is a wrapper class for curl, it is quite easy to use:
* <code>
* $c = new curl;
* // enable cache
* $c = new curl(array('cache'=>true));
* // enable cookie
* $c = new curl(array('cookie'=>true));
* // enable proxy
* $c = new curl(array('proxy'=>true));
*
* // HTTP GET Method
* $html = $c->get('http://example.com');
* // HTTP POST Method
* $html = $c->post('http://example.com/', array('q'=>'words', 'name'=>'moodle'));
* // HTTP PUT Method
* $html = $c->put('http://example.com/', array('file'=>'/var/www/test.txt');
* </code>
*
* #author Dongsheng Cai <dongsheng#moodle.com> - https://github.com/dongsheng/cURL
* #license http://www.gnu.org/copyleft/gpl.html GNU Public License
*/
class curl {
/** #var bool */
public $cache = false;
public $proxy = false;
/** #var array */
public $response = array();
public $header = array();
/** #var string */
public $info;
public $error;
/** #var array */
private $options;
/** #var string */
private $proxy_host = '';
private $proxy_auth = '';
private $proxy_type = '';
/** #var bool */
private $debug = false;
private $cookie = false;
private $count = 0;
/**
* #param array $options
*/
public function __construct($options = array()){
if (!function_exists('curl_init')) {
$this->error = 'cURL module must be enabled!';
trigger_error($this->error, E_USER_ERROR);
return false;
}
// the options of curl should be init here.
$this->resetopt();
if (!empty($options['debug'])) {
$this->debug = true;
}
if(!empty($options['cookie'])) {
if($options['cookie'] === true) {
$this->cookie = 'curl_cookie.txt';
} else {
$this->cookie = $options['cookie'];
}
}
if (!empty($options['cache'])) {
if (class_exists('curl_cache')) {
$this->cache = new curl_cache();
}
}
}
/**
* Resets the CURL options that have already been set
*/
public function resetopt(){
$this->options = array();
$this->options['CURLOPT_USERAGENT'] = 'MoodleBot/1.0';
// True to include the header in the output
$this->options['CURLOPT_HEADER'] = 0;
// True to Exclude the body from the output
$this->options['CURLOPT_NOBODY'] = 0;
// TRUE to follow any "Location: " header that the server
// sends as part of the HTTP header (note this is recursive,
// PHP will follow as many "Location: " headers that it is sent,
// unless CURLOPT_MAXREDIRS is set).
//$this->options['CURLOPT_FOLLOWLOCATION'] = 1;
$this->options['CURLOPT_MAXREDIRS'] = 10;
$this->options['CURLOPT_ENCODING'] = '';
// TRUE to return the transfer as a string of the return
// value of curl_exec() instead of outputting it out directly.
$this->options['CURLOPT_RETURNTRANSFER'] = 1;
$this->options['CURLOPT_BINARYTRANSFER'] = 0;
$this->options['CURLOPT_SSL_VERIFYPEER'] = 0;
$this->options['CURLOPT_SSL_VERIFYHOST'] = 2;
$this->options['CURLOPT_CONNECTTIMEOUT'] = 30;
}
/**
* Reset Cookie
*/
public function resetcookie() {
if (!empty($this->cookie)) {
if (is_file($this->cookie)) {
$fp = fopen($this->cookie, 'w');
if (!empty($fp)) {
fwrite($fp, '');
fclose($fp);
}
}
}
}
/**
* Set curl options
*
* #param array $options If array is null, this function will
* reset the options to default value.
*
*/
public function setopt($options = array()) {
if (is_array($options)) {
foreach($options as $name => $val){
if (stripos($name, 'CURLOPT_') === false) {
$name = strtoupper('CURLOPT_'.$name);
}
$this->options[$name] = $val;
}
}
}
/**
* Reset http method
*
*/
public function cleanopt(){
unset($this->options['CURLOPT_HTTPGET']);
unset($this->options['CURLOPT_POST']);
unset($this->options['CURLOPT_POSTFIELDS']);
unset($this->options['CURLOPT_PUT']);
unset($this->options['CURLOPT_INFILE']);
unset($this->options['CURLOPT_INFILESIZE']);
unset($this->options['CURLOPT_CUSTOMREQUEST']);
}
/**
* Set HTTP Request Header
*
* #param array $headers
*
*/
public function setHeader($header) {
if (is_array($header)){
foreach ($header as $v) {
$this->setHeader($v);
}
} else {
$this->header[] = $header;
}
}
/**
* Set HTTP Response Header
*
*/
public function getResponse(){
return $this->response;
}
/**
* private callback function
* Formatting HTTP Response Header
*
* #param mixed $ch Apparently not used
* #param string $header
* #return int The strlen of the header
*/
private function formatHeader($ch, $header)
{
$this->count++;
if (strlen($header) > 2) {
list($key, $value) = explode(" ", rtrim($header, "\r\n"), 2);
$key = rtrim($key, ':');
if (!empty($this->response[$key])) {
if (is_array($this->response[$key])){
$this->response[$key][] = $value;
} else {
$tmp = $this->response[$key];
$this->response[$key] = array();
$this->response[$key][] = $tmp;
$this->response[$key][] = $value;
}
} else {
$this->response[$key] = $value;
}
}
return strlen($header);
}
/**
* Set options for individual curl instance
*
* #param object $curl A curl handle
* #param array $options
* #return object The curl handle
*/
private function apply_opt($curl, $options) {
// Clean up
$this->cleanopt();
// set cookie
if (!empty($this->cookie) || !empty($options['cookie'])) {
$this->setopt(array('cookiejar'=>$this->cookie,
'cookiefile'=>$this->cookie
));
}
// set proxy
if (!empty($this->proxy) || !empty($options['proxy'])) {
$this->setopt($this->proxy);
}
$this->setopt($options);
// reset before set options
curl_setopt($curl, CURLOPT_HEADERFUNCTION, array(&$this,'formatHeader'));
// set headers
if (empty($this->header)){
$this->setHeader(array(
'User-Agent: MoodleBot/1.0',
'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7',
'Connection: keep-alive'
));
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $this->header);
if ($this->debug){
echo '<h1>Options</h1>';
var_dump($this->options);
echo '<h1>Header</h1>';
var_dump($this->header);
}
// set options
foreach($this->options as $name => $val) {
if (is_string($name)) {
$name = constant(strtoupper($name));
}
curl_setopt($curl, $name, $val);
}
return $curl;
}
/**
* Download multiple files in parallel
*
* Calls {#link multi()} with specific download headers
*
* <code>
* $c = new curl;
* $c->download(array(
* array('url'=>'http://localhost/', 'file'=>fopen('a', 'wb')),
* array('url'=>'http://localhost/20/', 'file'=>fopen('b', 'wb'))
* ));
* </code>
*
* #param array $requests An array of files to request
* #param array $options An array of options to set
* #return array An array of results
*/
public function download($requests, $options = array()) {
$options['CURLOPT_BINARYTRANSFER'] = 1;
$options['RETURNTRANSFER'] = false;
return $this->multi($requests, $options);
}
/*
* Mulit HTTP Requests
* This function could run multi-requests in parallel.
*
* #param array $requests An array of files to request
* #param array $options An array of options to set
* #return array An array of results
*/
protected function multi($requests, $options = array()) {
$count = count($requests);
$handles = array();
$results = array();
$main = curl_multi_init();
for ($i = 0; $i < $count; $i++) {
$url = $requests[$i];
foreach($url as $n=>$v){
$options[$n] = $url[$n];
}
$handles[$i] = curl_init($url['url']);
$this->apply_opt($handles[$i], $options);
curl_multi_add_handle($main, $handles[$i]);
}
$running = 0;
do {
curl_multi_exec($main, $running);
} while($running > 0);
for ($i = 0; $i < $count; $i++) {
if (!empty($options['CURLOPT_RETURNTRANSFER'])) {
$results[] = true;
} else {
$results[] = curl_multi_getcontent($handles[$i]);
}
curl_multi_remove_handle($main, $handles[$i]);
}
curl_multi_close($main);
return $results;
}
/**
* Single HTTP Request
*
* #param string $url The URL to request
* #param array $options
* #return bool
*/
protected function request($url, $options = array()){
// create curl instance
$curl = curl_init($url);
$options['url'] = $url;
$this->apply_opt($curl, $options);
if ($this->cache && $ret = $this->cache->get($this->options)) {
return $ret;
} else {
$ret = curl_exec($curl);
if ($this->cache) {
$this->cache->set($this->options, $ret);
}
}
$this->info = curl_getinfo($curl);
$this->error = curl_error($curl);
if ($this->debug){
echo '<h1>Return Data</h1>';
var_dump($ret);
echo '<h1>Info</h1>';
var_dump($this->info);
echo '<h1>Error</h1>';
var_dump($this->error);
}
curl_close($curl);
if (empty($this->error)){
return $ret;
} else {
return $this->error;
// exception is not ajax friendly
//throw new moodle_exception($this->error, 'curl');
}
}
/**
* HTTP HEAD method
*
* #see request()
*
* #param string $url
* #param array $options
* #return bool
*/
public function head($url, $options = array()){
$options['CURLOPT_HTTPGET'] = 0;
$options['CURLOPT_HEADER'] = 1;
$options['CURLOPT_NOBODY'] = 1;
return $this->request($url, $options);
}
/**
* Recursive function formating an array in POST parameter
* #param array $arraydata - the array that we are going to format and add into &$data array
* #param string $currentdata - a row of the final postdata array at instant T
* when finish, it's assign to $data under this format: name[keyname][][]...[]='value'
* #param array $data - the final data array containing all POST parameters : 1 row = 1 parameter
*/
function format_array_postdata_for_curlcall($arraydata, $currentdata, &$data) {
foreach ($arraydata as $k=>$v) {
$newcurrentdata = $currentdata;
if (is_object($v)) {
$v = (array) $v;
}
if (is_array($v)) { //the value is an array, call the function recursively
$newcurrentdata = $newcurrentdata.'['.urlencode($k).']';
$this->format_array_postdata_for_curlcall($v, $newcurrentdata, $data);
} else { //add the POST parameter to the $data array
$data[] = $newcurrentdata.'['.urlencode($k).']='.urlencode($v);
}
}
}
/**
* Transform a PHP array into POST parameter
* (see the recursive function format_array_postdata_for_curlcall)
* #param array $postdata
* #return array containing all POST parameters (1 row = 1 POST parameter)
*/
function format_postdata_for_curlcall($postdata) {
if (is_object($postdata)) {
$postdata = (array) $postdata;
}
$data = array();
foreach ($postdata as $k=>$v) {
if (is_object($v)) {
$v = (array) $v;
}
if (is_array($v)) {
$currentdata = urlencode($k);
$this->format_array_postdata_for_curlcall($v, $currentdata, $data);
} else {
$data[] = urlencode($k).'='.urlencode($v);
}
}
$convertedpostdata = implode('&', $data);
return $convertedpostdata;
}
/**
* HTTP POST method
*
* #param string $url
* #param array|string $params
* #param array $options
* #return bool
*/
public function post($url, $params = '', $options = array()){
$options['CURLOPT_POST'] = 1;
if (is_array($params)) {
$params = $this->format_postdata_for_curlcall($params);
}
$options['CURLOPT_POSTFIELDS'] = $params;
return $this->request($url, $options);
}
/**
* HTTP GET method
*
* #param string $url
* #param array $params
* #param array $options
* #return bool
*/
public function get($url, $params = array(), $options = array()){
$options['CURLOPT_HTTPGET'] = 1;
if (!empty($params)){
$url .= (stripos($url, '?') !== false) ? '&' : '?';
$url .= http_build_query($params, '', '&');
}
return $this->request($url, $options);
}
/**
* HTTP PUT method
*
* #param string $url
* #param array $params
* #param array $options
* #return bool
*/
public function put($url, $params = array(), $options = array()){
$file = $params['file'];
if (!is_file($file)){
return null;
}
$fp = fopen($file, 'r');
$size = filesize($file);
$options['CURLOPT_PUT'] = 1;
$options['CURLOPT_INFILESIZE'] = $size;
$options['CURLOPT_INFILE'] = $fp;
if (!isset($this->options['CURLOPT_USERPWD'])){
$this->setopt(array('CURLOPT_USERPWD'=>'anonymous: noreply#moodle.org'));
}
$ret = $this->request($url, $options);
fclose($fp);
return $ret;
}
/**
* HTTP DELETE method
*
* #param string $url
* #param array $params
* #param array $options
* #return bool
*/
public function delete($url, $param = array(), $options = array()){
$options['CURLOPT_CUSTOMREQUEST'] = 'DELETE';
if (!isset($options['CURLOPT_USERPWD'])) {
$options['CURLOPT_USERPWD'] = 'anonymous: noreply#moodle.org';
}
$ret = $this->request($url, $options);
return $ret;
}
/**
* HTTP TRACE method
*
* #param string $url
* #param array $options
* #return bool
*/
public function trace($url, $options = array()){
$options['CURLOPT_CUSTOMREQUEST'] = 'TRACE';
$ret = $this->request($url, $options);
return $ret;
}
/**
* HTTP OPTIONS method
*
* #param string $url
* #param array $options
* #return bool
*/
public function options($url, $options = array()){
$options['CURLOPT_CUSTOMREQUEST'] = 'OPTIONS';
$ret = $this->request($url, $options);
return $ret;
}
public function get_info() {
return $this->info;
}
}
/**
* This class is used by cURL class, use case:
*
* <code>
*
* $c = new curl(array('cache'=>true), 'module_cache'=>'repository');
* $ret = $c->get('http://www.google.com');
* </code>
*
* #package core
* #subpackage file
* #copyright 1999 onwards Martin Dougiamas {#link http://moodle.com}
* #license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class curl_cache {
/** #var string */
public $dir = '';
/**
*
* #param string #module which module is using curl_cache
*
*/
function __construct() {
$this->dir = '/tmp/';
if (!file_exists($this->dir)) {
mkdir($this->dir, 0700, true);
}
$this->ttl = 1200;
}
/**
* Get cached value
*
* #param mixed $param
* #return bool|string
*/
public function get($param){
$this->cleanup($this->ttl);
$filename = 'u_'.md5(serialize($param));
if(file_exists($this->dir.$filename)) {
$lasttime = filemtime($this->dir.$filename);
if(time()-$lasttime > $this->ttl)
{
return false;
} else {
$fp = fopen($this->dir.$filename, 'r');
$size = filesize($this->dir.$filename);
$content = fread($fp, $size);
return unserialize($content);
}
}
return false;
}
/**
* Set cache value
*
* #param mixed $param
* #param mixed $val
*/
public function set($param, $val){
$filename = 'u_'.md5(serialize($param));
$fp = fopen($this->dir.$filename, 'w');
fwrite($fp, serialize($val));
fclose($fp);
}
/**
* Remove cache files
*
* #param int $expire The number os seconds before expiry
*/
public function cleanup($expire){
if($dir = opendir($this->dir)){
while (false !== ($file = readdir($dir))) {
if(!is_dir($file) && $file != '.' && $file != '..') {
$lasttime = #filemtime($this->dir.$file);
if(time() - $lasttime > $expire){
#unlink($this->dir.$file);
}
}
}
}
}
/**
* delete current user's cache file
*
*/
public function refresh(){
if($dir = opendir($this->dir)){
while (false !== ($file = readdir($dir))) {
if(!is_dir($file) && $file != '.' && $file != '..') {
if(strpos($file, 'u_')!==false){
#unlink($this->dir.$file);
}
}
}
}
}
}
Thanks!
Well after some research I finally took plan B
I wrote tracks in a different variable:
$tracks = array();
$tracks[] = array(
'element' => 'cmi.core.lesson_status',
'value' => 'completed'
);
And I followed curl.php array set option:
$arrayName = array('' => , );
Then when I inserted scoid and attemps as single variables in the array:
$params = array('scoid' => '2', 'attempt' => '1', 'tracks' => $tracks);
and boala!the record is on my table:

Infinite loop when using cURL to access a REST API, what is causing it?

I am trying to write a connector using cURL to connect to a REST API.
The first step the user have to do is creates a session using createSession(). This will send a POST call to the API with a username and a password. The API will respond with a sessionId, a cookie value and couple of custom header.
The session is only valid for 3 minutes after each valid request. If I make a request after the session has expired I will get http error code 401 which indicates that the user is unauthorized to make the request because the sessionId is invalid or timed out.
Instead of asking the user to login again manually, I would like to automatically reconnect by calling the createSession() method when I get error 401. The reason why I need to do this because the sessionId is save in the client cookies and so the client does not know if the session is expired or active. My code will try to call methods using the sessionId that is saved in the cookies weather it is active or expired.
The API will renew the session 3 minutes each time a request is made as long as the session is still active. The only time I will need to reconnect is only when the user have not made a request for 3 minutes.
The issue that I am running into is when I try to reconnnect, I go into an infinite loop that I can't figure out how to stop it.
Here is my code
<?php namespace API;
/**
* ICWS API
*
* #package ICWS
*/
class ICWS {
private $_myAppName = 'ICWS API connector';
private $_authenticationType = 'Basic'; //Not used yet
private $_languageID = 'en-US';
private $_protocol = 'http';
private $_sessionIdKey = 'sessionId';
private $_interactionIdKey = 'interactionIdKey';
private $_maxLoginAttempts = 3;
private $_loginAttempts = 0;
private $_debug = false;
//No need to edit beyond this line
private $_isSubscribledToQueue = false;
private $_alternateHostList = array();
private $_interactionId = 0;
private $_queueType = 1;
private $_userID;
private $_password;
private $_workstation;
private $_queueName;
private $_cainfo;
private $_baseURL;
private $_csrfToken;
private $_sessionId;
private $_ININ_ICWS_CSRF_Token;
private $_Location;
private $_subscriptionId;
private $_curlHeader;
private $_requestFile;
public function __construct($config)
{
//Make sure cURL is enabled on the server
if(!is_callable('curl_init')){
throw new ApiException('cURL is disabled on this server. Before making API calls cURL extension must be enabled.');
}
//Make sure all required config are set
if( !isset($config['host']) || empty($config['host'])
|| !isset($config['port']) || empty($config['port'])
|| !isset($config['userID']) || empty($config['userID'])
|| !isset($config['password']) || empty($config['password'])
|| !isset($config['workstation']) || empty($config['workstation'])
){
throw new ApiException('Host, Port, userID, password, workstation are required!');
}
$this->_userID = $config['userID'];
$this->_password = $config['password'];
$this->_workstation = $config['workstation'];
//override the default queueType
if( isset($config['queueType']) && !empty($config['queueType']) ){
$this->_queueType = $config['queueType'];
}
//override the default queueName
if( isset($config['queueName']) && !empty($config['queueName']) ){
$this->_queueName = $config['queueName'];
}
//override the default appName
if( isset($config['appName']) && !empty($config['appName']) ){
$this->_myAppName = $config['appName'];
}
//override the default session Key
if( isset($config['sessionKey']) && !empty($config['sessionKey']) ){
$this->_sessionKey = $config['sessionKey'];
}
//override the default protocol
if( isset($config['isSecured']) && $config['isSecured'] == true){
if(!isset($config['cainfo']) || empty($config['cainfo'])){
throw new ApiException('To enable SSL you must provide CA Info file (.cert)');
} else {
$this->_protocol = 'https';
$this->cainfo = $config['cainfo'];
}
}
//override the default server Language
if( isset($config['languageID']) && !empty($config['languageID']) ){
$this->_languageID = $config['languageID'];
}
//override the default debug mode
if( isset($config['debug']) && !empty($config['debug']) ){
$this->_debug = $config['debug'];
}
//override the default authentication type
if( isset($config['authenticationType']) && !empty($config['authenticationType']) ){
$this->_authenticationType = $config['authenticationType'];
}
//set the sessionId if it already exists
if( isset( $_COOKIE[$this->_sessionIdKey] ) && !empty( $_COOKIE[$this->_sessionIdKey] )){
$this->_sessionId = $_COOKIE[$this->_sessionIdKey];
}
//set the _interactionIdKey if it already exists
if( isset( $_COOKIE[$this->_interactionIdKey] ) && !empty( $_COOKIE[$this->_interactionIdKey] )){
$this->_interactionId = $this->_bigint($_COOKIE[$this->_interactionIdKey]);
}
if(isset($_COOKIE['ININ-ICWS-CSRF-Token']) && !empty($_COOKIE['ININ-ICWS-CSRF-Token'])){
$this->_ININ_ICWS_CSRF_Token = $_COOKIE['ININ-ICWS-CSRF-Token'];
}
$this->_baseURL = $this->_protocol . '://' . $config['host'] . ':' . $config['port'] . '/icws/';
$this->_subscriptionId = $this->_userID;
}
/**
* Authentication the user and generated a sessionId
*
* #param string $userID
* #param string $password
* #param boolean $forceNewSession
* #catch exception
* #return void
*/
public function createSession($forceNewSession = false){
if( !empty($this->_sessionId) && ! $forceNewSession ){
return;
}
if($forceNewSession){
$this->destroySession();
}
$this->_requestFile = 'connection';
$type = 'urn:inin.com:connection:icAuthConnectionRequestSettings';
$data = array('__type' => $type,
'applicationName' => $this->_myAppName,
'userID' => $this->_userID,
'password' => $this->_password);
$this->_curlHeader = array('Accept-Language: ' . $this->_languageID,
'Content-Type: application/json');
$httpCode = 0;
try {
$data = $this->_processRequest('POST', 'connection', $data, $httpCode, false);
if($this->_debug){
new showVar($data, false, 'HTTP Code: ' . $httpCode);
}
$this->_csrfToken = $data['csrfToken'];
$this->_sessionId = $data['sessionId'];
$this->_alternateHostList = $data['alternateHostList'];
if(!empty($this->_sessionId)){
setCookie($this->_sessionIdKey, $this->_sessionId);
$this->_loginAttempts = 0;
}
} catch (\Exception $e){
$this->_displayError($e);
}
}
/**
* Destroy the IC session
*
* #return void
*/
public function destroySession(){
//destroy the sessionId
$this->_sessionId = NULL;
$this->_destroy($this->_sessionIdKey);
//destroy the sessionId
$this->_interactionIdKey = 0;
$this->_destroy($this->_interactionIdKey);
//destroy the CSRF-Token
$this->_ININ_ICWS_CSRF_Token = NULL;
$this->_destroy('ININ-ICWS-CSRF-Token');
}
/**
* Calls any Method after a session is created
*
* #param string $method GET/POST/PUT
* #param string $uri
* #param array $data
* #catch exception
* #return array or false
*/
private function _sendRequest($method, $uri, $data = false, &$httpCode = 0){
if( !$this->_sessionId ){
return false;
}
$uri = $this->_sessionId . '/' . $uri;
$return = false;
//,'Cookie: ' . $this->_ININ_ICWS_Cookie
$this->_curlHeader = array('ININ-ICWS-CSRF-Token: ' . $this->_ININ_ICWS_CSRF_Token,
'ININ-ICWS-Session-ID: ' . $this->_sessionId,
'Content-Type: application/json');
try {
$return = $this->_processRequest($method, $uri, $data, $httpCode);
} catch (\Exception $e){
$this->_displayError($e);
} finally {
return $return;
}
}
/**
* Handle the cURL call to the API
*
* #throws ApiException
* #param string $method GET/POST/PUT
* #param string $uri
* #param array $data
* #param array &$httpCode
* #return array
*/
private function _processRequest($method, $uri, $data = false, &$httpCode = NULL, $allowReconnect = true)
{
$ch = curl_init();
$url = $this->_baseURL . $uri;
if(
($method == 'POST' || $method == 'PUT')
&& $data
){
$jsonString = json_encode($data);
curl_setopt( $ch, CURLOPT_POSTFIELDS, $jsonString );
}
if($method == 'POST'){
curl_setopt($ch, CURLOPT_POST, true);
} elseif( $method == 'PUT'){
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
} else {
if ($data){
$url = sprintf("%s?%s", $url, http_build_query($data));
}
}
//set the URL
curl_setopt($ch, CURLOPT_URL, $url);
//disable the use of cached connection
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
//return the respond from the API
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//return the HEADER respond from the API
curl_setopt($ch, CURLOPT_HEADER, true);
//add custom headers
if(!empty($this->_curlHeader)){
curl_setopt($ch, CURLOPT_HTTPHEADER, $this->_curlHeader);
}
//add the cookie value
$cookiesFile = 'icwsCookies';
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookiesFile); // write
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookiesFile); // read
//enable SSL
if( $this->_protocol == 'https' ){
curl_setopt($ch, CURLOPT_CAINFO, $this->_cainfo);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, true);
}
//send the request to the API
$respond = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//throw cURL exception
if($respond === false){
$errorNo = curl_errno($ch);
$errorMessage = curl_error($ch);
throw new ApiException($errorMessage, $errorNo);
}
list($header, $body) = explode("\r\n\r\n", $respond, 2);
if($uri == 'connection'){
$this->_handleReceivedHeaders($header);
}
//if user gets unauthorized error attempt to login as long as the attempt are under 3
if($httpCode == 401 && $allowReconnect){
if( $this->_loginAttempts > $this->_maxLoginAttempts){
throw new ApiException('All Attempts to create a session have been used! Please check your credentials and try again');
} else {
$this->_reconnect($method, $uri, $data);
}
}
//convert respond to an array
return json_decode($body, true);
}
/**
* Reconnect to the Api and generate a new sessionId
*
* #return boolean
*/
private function _reconnect($method, $uri, $data){
$this->createSession(true);
$httpCode = 0;
$this->_processRequest($method, $uri, $data, $httpCode);
if($httpCode == 200 || $httpCode == 201){
return true;
}
return false;
}
/**
* Get the cookie HTTP headers and set them as cookie
*
* #param array $httpRespond
* #return void
*/
private function _handleReceivedHeaders($httpRespond){
$header = $this->_http_parse_headers($httpRespond);
//set the ININ-ICWS-CSRF-Token value
if( isset($header['ININ-ICWS-CSRF-Token']) ){
$this->_ININ_ICWS_CSRF_Token = $header['ININ-ICWS-CSRF-Token'];
setCookie('ININ-ICWS-CSRF-Token', $this->_ININ_ICWS_CSRF_Token);
}
}
/**
* Checks if the API return an error
*
* #param array $result
* #return boolean
*/
private function _hasAPIError($result){
if( isset($result['errorId']) && !empty($result['errorId'])
&& isset($result['message']) && !empty($result['message'])
){
return true;
}
return false;
}
/**
* Displays the exception details
*
* #param ApiException $e
*/
private function _displayError(ApiException $e){
echo 'Error Number: ' . $e->getCode() . "<br>";
echo $e->getMessage() . "<br><br>";
}
/**
* convert cURL header into an array
*
* #param string $raw_headers
* #return array
*/
private function _http_parse_headers($raw_headers)
{
$headers = array();
$key = '';
foreach(explode("\n", $raw_headers) as $i => $h)
{
$h = explode(':', $h, 2);
if (isset($h[1])){
if (!isset($headers[$h[0]])){
$headers[$h[0]] = trim($h[1]);
} elseif (is_array($headers[$h[0]])){
$headers[$h[0]] = array_merge($headers[$h[0]], array(trim($h[1]))); // [+]
} else {
$headers[$h[0]] = array_merge(array($headers[$h[0]]), array(trim($h[1]))); // [+]
}
$key = $h[0];
} else {
if (substr($h[0], 0, 1) == "\t"){
$headers[$key] .= "\r\n\t".trim($h[0]);
} elseif (!$key){
$headers[0] = trim($h[0]);trim($h[0]);
}
}
}
return $headers;
}
/**
* return a valid numeric value
*
* #param string $val
* #return big integer
*/
private function _bigint($val){
$val = filter_var($val, FILTER_SANITIZE_NUMBER_INT);
if(empty($val)){
$val = 0;
}
return $val;
}
/**
* Destroy a cookie
* #return void
*/
private function _destroy($name){
setcookie($name, null);
unset($_COOKIE[$name]);
}
}
?>
This snipit below is where I am trying reconnect to the API. which is causing the loop for some reason.
if($httpCode == 401 && $allowReconnect){
if( $this->_loginAttempts > $this->_maxLoginAttempts){
throw new ApiException('All Attempts to create a session have been used! Please check your credentials and try again');
} else {
$this->_reconnect($method, $uri, $data);
}
}
Here is a summary of my code.
a session is created via $this->createSession(true);
then multiple _processRequests() methods are called at different time. If a the _processRequests() method return 401 then $this->createSession(true); is called until it return code 201 or 200 or the $this->createSession(true); is called more than 3 times then I will need to quite. the problem is even when $this->createSession(true); return code 200 or 201 it keeps looping and it does not stop
The cause of the loop is that _processRequests() calls itself infinite when error 401 is reached. It does not recognize that the second calls returns 201.
In _reconnect method:
$this->createSession(true);
In createSession method:
$data = $this->_processRequest('POST', 'connection', $data, $httpCode, false);
In _processRequest method:
//if user gets unauthorized error attempt to login as long as the attempt are under 3
if($httpCode == 401 && $allowReconnect){
if( $this->_loginAttempts > $this->_maxLoginAttempts){
throw new ApiException('All Attempts to create a session have been used! Please check your credentials and try again');
} else {
$this->_reconnect($method, $uri, $data);
}
}
My guess is that you got an unauthorized error, and since you're never incrementing $this->_loginAttempts anywhere in the code, it can't never be greater than $this->_maxLoginAttempts, so the code will call again the _reconnect mehtod, causing it to enter in an infinite loop.

API for dropbox login, access,upload ,delete using cakephp

I have created application in dropbox developer account.
I am using this component class for dropbox .when i trying to login i am getting this error "Please create your dropbox_token and dropbox_token_secret fields in your user model."
<?php
/**
* CAKEPHP DROPBOX COMPONENT v0.4
* Connects Cakephp to Dropbox using cURL.
*
* Copyright (C) 2010 Kyle Robinson Young
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* #author Kyle Robinson Young <kyle at kyletyoung.com>
* #copyright 2010 Kyle Robinson Young
* #license http://www.opensource.org/licenses/mit-license.php The MIT License
* #version 0.4
* #link http://www.kyletyoung.com/code/cakephp_dropbox_component
*
* SETTINGS:
* email/password: To your dropbox account
* cache: Set to name of cache config or false for no cache
*
* When in doubt, clear the cache.
*
* TODO:
* Make sync function smarter (use modified).
*
*/
class DropboxComponent extends Object
{
var $email, $password;
var $loggedin = false;
var $post, $cookie = array();
var $cache = 'default';
var $_wcache = array();
/**
* INITIALIZE
* #param class $controller
* #param array $settings
*/
function initialize(&$controller, $settings=array())
{
if (!extension_loaded('curl'))
{
trigger_error('Dropbox Component: I require the cURL extension to work.');
} // no curl
if (empty($settings['email']) || empty($settings['password']))
{
trigger_error('Dropbox Component: I need your dropbox email and password to login.');
} // email|pass empty
else
{
$this->email = $settings['email'];
$this->password = $settings['password'];
if (isset($settings['cache'])) $this->cache = $settings['cache'];
$this->login();
} // else
} // initialize
/**
* UPLOAD
* Upload a local file to a remote folder.
*
* #param $file
* #param $dir
* #return bool
*/
function upload($from=null, $to='/')
{
if (!file_exists($from)) return false;
$data = $this->request('https://www.dropbox.com/home');
$token = $this->findOnDropbox('token_upload', $data);
if ($token === false) return false;
$this->post = array(
'plain' => 'yes',
'file' => '#'.$from,
'dest' => $to,
't' => $token
);
$data = $this->request('https://dl-web.dropbox.com/upload');
if (strpos($data, 'HTTP/1.1 302 FOUND') === false) return false;
return true;
} // upload
/**
* DOWNLOAD
* Download a remote file to a local folder.
* Both from and to must be a path to a file name.
*
* #param str $from
* #param str $to
* #param str $w
* #return bool
*/
function download($from=null, $to=null, $w=null)
{
$data = $this->file($from, $w);
if (empty($data['data'])) return false;
if (!is_writable(dirname($to))) return false;
if (!$fp = fopen($to, 'w')) return false;
if (fwrite($fp, $data['data']) === false) return false;
fclose($fp);
return true;
} // download
/**
* SYNC
* Compares files from the local and remote folders
* then syncs them.
* Both local and remote must be folders.
*
* TODO:
* Currently only checks if files exists. Doesn't
* check if they are up to date which it should.
*
* #param str $local
* #param str $remote
* #return bool
*/
function sync($local=null, $remote=null)
{
if (!is_dir($local)) return false;
// GET REMOTE FILES
$remote_files = $this->files($remote);
// GET LOCAL FILES
$local_files = array();
$d = dir($local);
while (false !== ($entry = $d->read()))
{
if (substr($entry, 0, 1) == '.') continue;
if (is_dir($local.DS.$entry)) continue;
$local_files[] = $entry;
} // while
$d->close();
// DOWNLOAD FILES
$tmp = array();
foreach ($remote_files as $file)
{
if (empty($file['w'])) continue;
$tmp[] = $file['name'];
if (in_array($file['name'], $local_files)) continue;
$this->download($file['path'].$file['name'], $local.$file['name'], $file['w']);
} // foreach
// UPLOAD FILES
foreach ($local_files as $file)
{
if (in_array($file, $tmp)) continue;
$this->upload($local.$file, $remote);
} // foreach
return true;
} // sync
/**
* FILES
* Returns an array of remote files/folders
* within the given dir param.
*
* #param str $dir
* #return array
*/
function files($dir='/')
{
$dir = $this->escape($dir);
if ($this->cache === false) Cache::delete('dropbox_files_'.$dir, $this->cache);
if (($files = Cache::read('dropbox_files_'.$dir, $this->cache)) === false)
{
$files = array();
$data = $this->request('https://www.dropbox.com/browse_plain/'.$dir.'?no_js=true');
// GET FILES
$matches = $this->findOnDropbox('files', $data);
if ($matches === false) return false;
// GET TYPES
$types = $this->findOnDropbox('file_types', $data);
// GET SIZES
$sizes = $this->findOnDropbox('file_sizes', $data);
// GET MODS
$mods = $this->findOnDropbox('file_modified_dates', $data);
$i = 0;
foreach ($matches as $key => $file)
{
// IF PARENT
if (strpos($file, "Parent folder") !== false) continue;
// GET FILENAME
$found = $this->findOnDropbox('filename', $file);
if ($found === false) continue;
$found = parse_url($found);
$filename = pathinfo($found['path']);
$filename = $filename['basename'];
if (empty($filename)) continue;
// SET DEFAULTS
$path = $dir.$filename;
$type = 'unknown';
$size = 0;
$modified = 0;
// GET TYPE
if (!empty($types[$key])) $type = trim($types[$key]);
// GET SIZE
if (!empty($sizes[$key])) $size = trim($sizes[$key]);
// GET MODIFIED
if (!empty($mods[$key])) $modified = trim($mods[$key]);
// ADD TO FILES
$files[$i] = array(
'path' => urldecode($dir),
'name' => $filename,
'type' => $type,
'size' => $size,
'modified' => $modified
);
// IF FILE OR FOLDER - FILES HAVE W
$w = $this->findOnDropbox('w', $file);
if ($w !== false)
{
$files[$i]['w'] = $w;
// SAVE W FOR LATER
$this->_wcache[$dir.'/'.$filename] = $w;
} // !empty
$i++;
} // foreach
} // Cache::read
if ($this->cache !== false)
{
Cache::write('dropbox_files_'.$dir, $files, $this->cache);
} // if cache
return $files;
} // files
/**
* FILE
* Returns a remote file as an array.
*
* #param str $file
* #param str $w
* #return array
*/
function file($file=null, $w=null)
{
$file = $this->escape($file);
if ($this->cache === false) Cache::delete('dropbox_file_'.$file, $this->cache);
if (($out = Cache::read('dropbox_file_'.$file, $this->cache)) === false)
{
if (empty($w))
{
if (!empty($this->_wcache[$file])) $w = $this->_wcache[$file];
else return false;
} // empty w
$data = $this->request('https://dl-web.dropbox.com/get/'.$file.'?w='.$w);
$type = $this->findOnDropbox('content_type', $data);
$data = substr(stristr($data, "\r\n\r\n"), 4);
if (!empty($type[0])) $type = $type[0];
$out = array(
'path' => $file,
'w' => $w,
'data' => $data,
'content_type' => $type
);
if ($this->cache !== false)
{
Cache::write('dropbox_file_'.$file, $out, $this->cache);
} // if cache
} // Cache::read
return $out;
} // file
/**
* LOGIN
* to dropbox
*
* #return bool
*/
function login()
{
if (!$this->loggedin)
{
if (empty($this->email) || empty($this->password)) return false;
$data = $this->request('https://www.dropbox.com/login');
// GET TOKEN
$token = $this->findOnDropbox('token_login', $data);
if ($token === false) return false;
// LOGIN TO DROPBOX
$this->post = array(
'login_email' => $this->email,
'login_password' => $this->password,
't' => $token
);
$data = $this->request('https://www.dropbox.com/login');
// IF WERE HOME
if (stripos($data, 'location: /home') === false) return false;
$this->loggedin = true;
} // if loggedin
return true;
} // login
/**
* REQUEST
* Returns data from given url and
* saves cookies. Use $this->post and
* $this->cookie to submit params.
*
* #param str $url
* #return str
*/
function request($url=null)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// IF POST
if (!empty($this->post))
{
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $this->post);
$this->post = array();
} // !empty
// IF COOKIES
if (!empty($this->cookie))
{
$cookies = array();
foreach ($this->cookie as $key => $val)
{
$cookies[] = "$key=$val";
} // foreach
$cookies = implode(';', $cookies);
curl_setopt($ch, CURLOPT_COOKIE, $cookies);
} // !empty
// GET DATA
$data = curl_exec($ch);
// SAVE COOKIES
$cookies = $this->findOnDropbox('cookies', $data);
if ($cookies !== false)
{
$this->cookie = array_merge($this->cookie, $cookies);
} // if cookies
curl_close($ch);
return $data;
} // request
/**
* ESCAPE
* Returns a dropbox friendly str
* for a url
*
* #param str $str
* #return str
*/
function escape($str=null)
{
return str_replace(
array('+','_','%2E','-','%2F','%3A'),
array('%20','%5F','.','%2D','/',':'),
urlencode($str)
);
} // escape
/**
* FIND ON DROPBOX
* A single function for parsing data from
* Dropbox. For easy update when/if Dropbox
* updates their html.
*
* #param str $key
* #param str $data
* #return mixed
*/
function findOnDropbox($key=null, $data=null)
{
switch (strtolower($key))
{
// FIND FILES & NAMES
case 'files':
preg_match_all('/<div.*details-filename.*>(.*?)<\/div>/i', $data, $matches);
if (!empty($matches[0])) return $matches[0];
break;
// FIND FILE TYPES
case 'file_types':
preg_match_all('/<div.*details-icon.*>(<img.*class="sprite s_(.*)".*>)<\/div>/i', $data, $matches);
if (!empty($matches[2])) return $matches[2];
break;
// FIND FILE SIZES
case 'file_sizes':
preg_match_all('/<div.*details-size.*>(.*)<\/div>/i', $data, $matches);
if (!empty($matches[1])) return $matches[1];
break;
// FIND FILE MODIFIED DATES
case 'file_modified_dates':
preg_match_all('/<div.*details-modified.*>(.*)<\/div>/i', $data, $matches);
if (!empty($matches[1])) return $matches[1];
break;
// FIND FILE NAME
case 'filename':
preg_match('/href=[("|\')]([^("|\')]+)/i', $data, $match);
if (!empty($match[1])) return $match[1];
break;
// FIND W
case 'w':
preg_match('/\?w=(.[^"]*)/i', $data, $match);
if (!empty($match[1])) return $match[1];
break;
// FIND CONTENT TYPE
case 'content_type':
preg_match('/Content-Type: .+\/.+/i', $data, $type);
if (!empty($type)) return $type;
break;
// FIND COOKIES
case 'cookies':
preg_match_all('/Set-Cookie: ([^=]+)=(.*?);/i', $data, $matches);
$return = array();
foreach ($matches[1] as $key => $val)
{
$return[(string)$val] = $matches[2][$key];
} // foreach
if (!empty($return)) return $return;
break;
// FIND LOGIN FORM TOKEN
case 'token_login':
preg_match('/<form [^>]*\/login[^>]*>.*?<\/form>/si', $data, $match);
if (!empty($match[0]))
{
preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
if (!empty($match[1])) return $match[1];
} // !empty
break;
// FIND UPLOAD FORM TOKEN
case 'token_upload':
preg_match('/<form [^>]*https\:\/\/dl-web\.dropbox\.com\/upload[^>]*>.*?<\/form>/si', $data, $match);
if (!empty($match[0]))
{
preg_match('/<input [^>]*name="t" [^>]*value="(.*?)"[^>]*>/si', $match[0], $match);
if (!empty($match[1])) return $match[1];
} // !empty
break;
} // switch
return false;
} // findOnDropbox
} // DropboxComponent
?>
Controller code
class DropboxWebserverController extends AppController
{
var $name = 'DropboxWebserver';
var $uses = array();
var $autoRender = false;
var $components = array('Dropbox' => array(
'email' => 'email#gmail.com',
'password' => 'password',
//'cache' => false
));
var $root_folder = '/';
var $default_home = array('index.html', 'index.htm', 'index.php');
/**
* INDEX
*/
function index()
{
$args = func_get_args();
$args = implode('/', $args);
$path = pathinfo($args);
if ($path['dirname'] == ".")
{
$folder = $path['basename'];
$file = '';
} // dirname == .
else
{
$folder = $path['dirname'];
$file = $path['basename'];
} // else
$files = $this->Dropbox->files($this->root_folder.$folder);
//debug($files);
// FIND FILE
foreach ($files as $f)
{
if (strpos($f['type'], 'folder') !== false) continue;
if (empty($f['name'])) continue;
if ($f['name'] == $file)
{
$file = $this->Dropbox->file($this->root_folder.$folder.'/'.$file, $f['w']);
$output = $file['data'];
$content_type = $file['content_type'];
break;
} // name == file
// FIND DEFAULT HOME
if (in_array($f['name'], $this->default_home))
{
$default = $f;
} // in_array
} // foreach
if (!empty($output))
{
header('Content-Type: '.$content_type);
echo $output;
} // !empty
elseif (!empty($default))
{
$file = $this->Dropbox->file($this->root_folder.$folder.'/'.$default['name'], $default['w']);
header('Content-Type: '.$file['content_type']);
echo $file['data'];
} // !empty default
else
{
echo 'Error 404: File Not Found';
} // else
} // index
}
How to login and access drop box account using cakephp

Is there any possible to get Google Webmaster Tool (GWT) datas using PHP?

I'm trying to get some datas from Google Webmaster Tool (GWT), I have searched some of the API Documents and Implements, But they are returning few of the datas only from the GWT.
My Needs :
Needs to get the datas of the following from GWT,
(1). TOP_PAGES
(2). TOP_QUERIES
(3). CRAWL_ERRORS
(4). CONTENT_ERRORS
(5). CONTENT_KEYWORDS
(6). INTERNAL_LINKS
(7). EXTERNAL_LINKS
(8). SOCIAL_ACTIVITY
After getting these datas, i need to generate the Excel file for each of them.
Achieved :
I have got few datas from the above and generated into the Excel file.such as,
(1). TOP_PAGES
(2). TOP_QUERIES
(3). INTERNAL_LINKS
(4). EXTERNAL_LINKS
(5). CONTENT_KEYWORDS
Not Achieved :
Still I'm not getting the major parts / datas like,
(1). CRAWL_ERRORS
(2). CONTENT_ERRORS
(3). SOCIAL_ACTIVITY
Code Samples For Your Reference :
I have used two files in PHP for this GWT API,
File #1 : ( gwdata.php )
<?php
/**
* PHP class for downloading CSV files from Google Webmaster Tools.
*
* This class does NOT require the Zend gdata package be installed
* in order to run.
*
* Copyright 2012 eyecatchUp UG. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* #author: Stephan Schmitz <eyecatchup#gmail.com>
* #link: https://code.google.com/p/php-webmaster-tools-downloads/
*/
class GWTdata
{
const HOST = "https://www.google.com";
const SERVICEURI = "/webmasters/tools/";
public $_language, $_tables, $_daterange, $_downloaded, $_skipped;
private $_auth, $_logged_in;
public function __construct()
{
$this->_auth = false;
$this->_logged_in = false;
$this->_language = "en";
$this->_daterange = array("","");
$this->_tables = array("TOP_PAGES", "TOP_QUERIES",
"CRAWL_ERRORS", "CONTENT_ERRORS", "CONTENT_KEYWORDS",
"INTERNAL_LINKS", "EXTERNAL_LINKS", "SOCIAL_ACTIVITY"
);
$this->_errTablesSort = array(0 => "http",
1 => "not-found", 2 => "restricted-by-robotsTxt",
3 => "unreachable", 4 => "timeout", 5 => "not-followed",
"kAppErrorSoft-404s" => "soft404", "sitemap" => "in-sitemaps"
);
$this->_errTablesType = array(0 => "web-crawl-errors",
1 => "mobile-wml-xhtml-errors", 2 => "mobile-chtml-errors",
3 => "mobile-operator-errors", 4 => "news-crawl-errors"
);
$this->_downloaded = array();
$this->_skipped = array();
}
/**
* Sets content language.
*
* #param $str String Valid ISO 639-1 language code, supported by Google.
*/
public function SetLanguage($str)
{
$this->_language = $str;
}
/**
* Sets features that should be downloaded.
*
* #param $arr Array Valid array values are:
* "TOP_PAGES", "TOP_QUERIES", "CRAWL_ERRORS", "CONTENT_ERRORS",
* "CONTENT_KEYWORDS", "INTERNAL_LINKS", "EXTERNAL_LINKS",
* "SOCIAL_ACTIVITY".
*/
public function SetTables($arr)
{
if(is_array($arr) && !empty($arr) && sizeof($arr) <= 2) {
$valid = array("TOP_PAGES","TOP_QUERIES","CRAWL_ERRORS","CONTENT_ERRORS",
"CONTENT_KEYWORDS","INTERNAL_LINKS","EXTERNAL_LINKS","SOCIAL_ACTIVITY");
$this->_tables = array();
for($i=0; $i < sizeof($arr); $i++) {
if(in_array($arr[$i], $valid)) {
array_push($this->_tables, $arr[$i]);
} else { throw new Exception("Invalid argument given."); }
}
} else { throw new Exception("Invalid argument given."); }
}
/**
* Sets daterange for download data.
*
* #param $arr Array Array containing two ISO 8601 formatted date strings.
*/
public function SetDaterange($arr)
{
if(is_array($arr) && !empty($arr) && sizeof($arr) == 2) {
if(self::IsISO8601($arr[0]) === true &&
self::IsISO8601($arr[1]) === true) {
$this->_daterange = array(str_replace("-", "", $arr[0]),
str_replace("-", "", $arr[1]));
return true;
} else { throw new Exception("Invalid argument given."); }
} else { throw new Exception("Invalid argument given."); }
}
/**
* Returns array of downloaded filenames.
*
* #return Array Array of filenames that have been written to disk.
*/
public function GetDownloadedFiles()
{
return $this->_downloaded;
}
/**
* Returns array of downloaded filenames.
*
* #return Array Array of filenames that have been written to disk.
*/
public function GetSkippedFiles()
{
return $this->_skipped;
}
/**
* Checks if client has logged into their Google account yet.
*
* #return Boolean Returns true if logged in, or false if not.
*/
private function IsLoggedIn()
{
return $this->_logged_in;
}
/**
* Attempts to log into the specified Google account.
*
* #param $email String User's Google email address.
* #param $pwd String Password for Google account.
* #return Boolean Returns true when Authentication was successful,
* else false.
*/
public function LogIn($email, $pwd)
{
$url = self::HOST . "/accounts/ClientLogin";
$postRequest = array(
'accountType' => 'HOSTED_OR_GOOGLE',
'Email' => $email,
'Passwd' => $pwd,
'service' => "sitemaps",
'source' => "Google-WMTdownloadscript-0.1-php"
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postRequest);
$output = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
if($info['http_code'] == 200) {
preg_match('/Auth=(.*)/', $output, $match);
if(isset($match[1])) {
$this->_auth = $match[1];
$this->_logged_in = true;
return true;
} else { return false; }
} else { return false; }
}
/**
* Attempts authenticated GET Request.
*
* #param $url String URL for the GET request.
* #return Mixed Curl result as String,
* or false (Boolean) when Authentication fails.
*/
public function GetData($url)
{
if(self::IsLoggedIn() === true) {
$url = self::HOST . $url;
$head = array("Authorization: GoogleLogin auth=".$this->_auth,
"GData-Version: 2");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $head);
$result = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
return ($info['http_code']!=200) ? false : $result;
} else { return false; }
}
/**
* Gets all available sites from Google Webmaster Tools account.
*
* #return Mixed Array with all site URLs registered in GWT account,
* or false (Boolean) if request failed.
*/
public function GetSites()
{
if(self::IsLoggedIn() === true) {
$feed = self::GetData(self::SERVICEURI."feeds/sites/");
if($feed !== false) {
$sites = array();
$doc = new DOMDocument();
$doc->loadXML($feed);
foreach ($doc->getElementsByTagName('entry') as $node) {
array_push($sites,
$node->getElementsByTagName('title')->item(0)->nodeValue);
}
return $sites;
} else { return false; }
} else { return false; }
}
/**
* Gets the download links for an available site
* from the Google Webmaster Tools account.
*
* #param $url String Site URL registered in GWT.
* #return Mixed Array with keys TOP_PAGES and TOP_QUERIES,
* or false (Boolean) when Authentication fails.
*/
public function GetDownloadUrls($url)
{
if(self::IsLoggedIn() === true) {
$_url = sprintf(self::SERVICEURI."downloads-list?hl=%s&siteUrl=%s",
$this->_language,
urlencode($url));
$downloadList = self::GetData($_url);
return json_decode($downloadList, true);
} else { return false; }
}
/**
* Downloads the file based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional path to save CSV to (no trailing slash!).
*/
public function DownloadCSV($site, $savepath=".")
{
if(self::IsLoggedIn() === true) {
$downloadUrls = self::GetDownloadUrls($site);
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
$tables = $this->_tables;
foreach($tables as $table) {
if($table=="CRAWL_ERRORS") {
self::DownloadCSV_CrawlErrors($site, $savepath);
}
elseif($table=="CONTENT_ERRORS") {
self::DownloadCSV_XTRA($site, $savepath,
"html-suggestions", "\)", "CONTENT_ERRORS", "content-problems-dl");
}
elseif($table=="CONTENT_KEYWORDS") {
self::DownloadCSV_XTRA($site, $savepath,
"keywords", "\)", "CONTENT_KEYWORDS", "content-words-dl");
}
elseif($table=="INTERNAL_LINKS") {
self::DownloadCSV_XTRA($site, $savepath,
"internal-links", "\)", "INTERNAL_LINKS", "internal-links-dl");
}
elseif($table=="EXTERNAL_LINKS") {
self::DownloadCSV_XTRA($site, $savepath,
"external-links-domain", "\)", "EXTERNAL_LINKS", "external-links-domain-dl");
}
elseif($table=="SOCIAL_ACTIVITY") {
self::DownloadCSV_XTRA($site, $savepath,
"social-activity", "x26", "SOCIAL_ACTIVITY", "social-activity-dl");
}
else {
$finalName = "$savepath/$table-$filename.csv";
$finalUrl = $downloadUrls[$table] ."&prop=ALL&db=%s&de=%s&more=true";
$finalUrl = sprintf($finalUrl, $this->_daterange[0], $this->_daterange[1]);
self::SaveData($finalUrl,$finalName);
}
}
} else { return false; }
}
/**
* Downloads "unofficial" downloads based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional path to save CSV to (no trailing slash!).
*/
public function DownloadCSV_XTRA($site, $savepath=".", $tokenUri, $tokenDelimiter, $filenamePrefix, $dlUri)
{
if(self::IsLoggedIn() === true) {
$uri = self::SERVICEURI . $tokenUri . "?hl=%s&siteUrl=%s";
$_uri = sprintf($uri, $this->_language, $site);
$token = self::GetToken($_uri, $tokenDelimiter);
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
$finalName = "$savepath/$filenamePrefix-$filename.csv";
$url = self::SERVICEURI . $dlUri . "?hl=%s&siteUrl=%s&security_token=%s&prop=ALL&db=%s&de=%s&more=true";
$_url = sprintf($url, $this->_language, $site, $token, $this->_daterange[0], $this->_daterange[1]);
self::SaveData($_url,$finalName);
} else { return false; }
}
/**
* Downloads the Crawl Errors file based on the given URL.
*
* #param $site String Site URL available in GWT Account.
* #param $savepath String Optional: Path to save CSV to (no trailing slash!).
* #param $separated Boolean Optional: If true, the method saves separated CSV files
* for each error type. Default: Merge errors in one file.
*/
public function DownloadCSV_CrawlErrors($site, $savepath=".", $separated=false)
{
if(self::IsLoggedIn() === true) {
$type_param = "we";
$filename = parse_url($site, PHP_URL_HOST) ."-". date("Ymd-His");
if($separated) {
foreach($this->_errTablesSort as $sortid => $sortname) {
foreach($this->_errTablesType as $typeid => $typename) {
if($typeid == 1) {
$type_param = "mx";
} else if($typeid == 2) {
$type_param = "mc";
} else {
$type_param = "we";
}
$uri = self::SERVICEURI."crawl-errors?hl=en&siteUrl=$site&tid=$type_param";
$token = self::GetToken($uri,"x26");
$finalName = "$savepath/CRAWL_ERRORS-$typename-$sortname-$filename.csv";
$url = self::SERVICEURI."crawl-errors-dl?hl=%s&siteUrl=%s&security_token=%s&type=%s&sort=%s";
$_url = sprintf($url, $this->_language, $site, $token, $typeid, $sortid);
self::SaveData($_url,$finalName);
}
}
}
else {
$uri = self::SERVICEURI."crawl-errors?hl=en&siteUrl=$site&tid=$type_param";
$token = self::GetToken($uri,"x26");
$finalName = "$savepath/CRAWL_ERRORS-$filename.csv";
$url = self::SERVICEURI."crawl-errors-dl?hl=%s&siteUrl=%s&security_token=%s&type=0";
$_url = sprintf($url, $this->_language, $site, $token);
self::SaveData($_url,$finalName);
}
} else { return false; }
}
/**
* Saves data to a CSV file based on the given URL.
*
* #param $finalUrl String CSV Download URI.
* #param $finalName String Filepointer to save location.
*/
private function SaveData($finalUrl, $finalName)
{
$data = self::GetData($finalUrl);
if(strlen($data) > 1 && file_put_contents($finalName, utf8_decode($data))) {
array_push($this->_downloaded, realpath($finalName));
return true;
} else {
array_push($this->_skipped, $finalName);
return false;
}
}
/**
* Regular Expression to find the Security Token for a download file.
*
* #param $uri String A Webmaster Tools Desktop Service URI.
* #param $delimiter String Trailing delimiter for the regex.
* #return String Returns a security token.
*/
private function GetToken($uri, $delimiter)
{
$matches = array();
$tmp = self::GetData($uri);
//preg_match_all("#x26security_token(.*?)$delimiter#si", $tmp, $matches);
preg_match_all("#46security_token(.*?)$delimiter#si", $tmp, $matches);
//return substr($matches[1][0],4,-1);
return substr($matches[1][0],3,-1);
}
/**
* Validates ISO 8601 date format.
*
* #param $str String Valid ISO 8601 date string (eg. 2012-01-01).
* #return Boolean Returns true if string has valid format, else false.
*/
private function IsISO8601($str)
{
$stamp = strtotime($str);
return (is_numeric($stamp) && checkdate(date('m', $stamp),
date('d', $stamp), date('Y', $stamp))) ? true : false;
}
}
?>
File #2: ( index.php )
<?php
include 'gwtdata.php';
include 'credentials.php';
try {
$website = "http://www.yourdomain.com/"; /* Add Your Website Url */
$gdata = new GWTdata();
if($gdata->LogIn($email, $password) === true)
{
$gdata->DownloadCSV($website,"Here Add Your Folder Path To Save CSV File With GWT Data");
echo "Datas Are Successfully Downloaded";
}
} catch (Exception $e) {
die($e->getMessage());
}
?>
Can anyone help me in this, to achieve all those datas and make it as excel file to generate using PHP.
[..] I have searched some of the API Documents and Implements, [..]
[..] I have used two files in PHP for this GWT API, [..]
I am the author of the code that you quote (GWTdata PHP class) and first off want to make clear that this code is neither released by Google nor makes use of an official API, but is rather a custom script processing data from the web interface.
[..] returning few of the datas only from the GWT. [..]
A couple of weeks ago, there were some changes to the Google Webmaster Tools web interface (which, again, was/is used to process data requests). Thus, it broke some functionality of the PHP class GWTdata - such as downloading the crawl errors.
[..] Can anyone help me in this, to achieve all those datas and make it as excel file to generate using PHP. [..]
Unfortunately, for the most data there is nothing I/we can do about it (since the data is just not accessable any longer).
[..] Still I'm not getting the major parts / datas like,
1. Crawl errors [..]
Anyway, you can use this followup project to get the crawl errors.
GwtCrawlErrors (Download website crawl errors from Google Webmaster Tools as CSV):
https://github.com/eyecatchup/GWT_CrawlErrors-php
The Google API Client for PHP now supports the Webmasters API. Documentation is (as per usual) scarce for the PHP library, but it maps reasonably cleanly on to the methods described in the Webmasters API reference and there are some examples in the code so it's not too hard to get a hold on.

OAuth - Error on Twitter (could not authenticate)

I have written a class (so I could learn how OAuth works). It is working fine; I can retrieve the access token with the class. But when I try to post an update, it says that I'm not authenticated! What am I doing wrong here?
// By Kevin Jacobs
class OAuth {
private $url = null;
private $debug = false;
private $method = 'POST';
private $oauthData = array();
private $data = array();
private $token = array('key' => '', 'secret' => '');
private $consumer = array('key' => '', 'secret' => '');
/**
* Encode a string in such a way you can use it for OAuth.
* #param string $oauthData Data to encode
* #return string $encData Encoded data
*/
public static function encode($oauthData) {
if (is_string($oauthData)) {
return str_ireplace(
array('+', '%7E'),
array(' ', '~'),
rawurlencode($oauthData)
);
} else {
return '';
}
}
/**
* Generates a relative unique random string of a certain length.
* #param int $length Length of the string
* #return string $strRand A random string
*/
public static function generateString($length = 40) {
// Only strong cryptographic strings are allowed
while (!isset($bStrong) || $bStrong === false) {
$bytes = openssl_random_pseudo_bytes(floor($length / 2), $bStrong);
}
$strRand = bin2hex($bytes);
return sha1($strRand);
}
/**
* Generate a token pair (key and secret).
* #return array $tokenPair
*/
public static function generateTokenPair() {
$tokenPair = array();
$tokenPair['key'] = self::generateString();
$tokenPair['secret'] = self::generateString();
return $tokenPair;
}
/**
* Set the callback URL.
* #param string $callbackURL
*/
public function setCallback($callback = null) {
if ($callback === null) {
$callback = 'http';
if ($_SERVER['SERVER_PORT'] == 443) $callback .= 's';
$callback .= '://' . $_SERVER['SERVER_NAME'];
if ($_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
$callback .= ':' . $_SERVER['SERVER_PORT'];
}
$callback .= $_SERVER['REQUEST_URI'];
}
$this->oauthData['oauth_callback'] = $callback;
}
/**
* Get the callback URL.
* #return string $callbackURL
*/
public function getCallback() {
return $this->oauthData['oauth_callback'];
}
/**
* Generate the nonce.
* #return string $nonce
*/
public function setNonce() {
$this->oauthData['oauth_nonce'] = md5(self::generateString(20) . mktime());
return $this->oauthData['oauth_nonce'];
}
/**
* Set the timestamp.
* #return int $timestamp
*/
public function setTimestamp() {
$this->oauthData['oauth_timestamp'] = mktime();
return $this->oauthData['oauth_timestamp'];
}
/**
* Set the OAuth version.
* #param string Version
*/
public function setVersion($version = '1.0') {
$this->oauthData['oauth_version'] = $version;
}
/**
* Set the HTTP method.
* #param string Method
*/
public function setMethod($method = 'POST') {
$this->method = trim(strtoupper($method));
}
/**
* Get the HTTP method.
* #return string Method
*/
public function getMethod() {
return $this->method;
}
/**
* Get the URL to call.
* #return string URL
*/
public function getURL() {
return $this->url;
}
/**
* Set the URL to call.
* #param string URL
*/
public function setURL($URL) {
$this->url = $URL;
}
/**
* Get the token key and secret
* #return array $token Containing token key and secret
*/
public function getToken() {
return $this->token;
}
/**
* Set the token
* #param string $tokenKey Token key
* #param string $tokenSecret Token secret
*/
public function setToken($tokenKey, $tokenSecret = null) {
$this->token['key'] = $tokenKey;
$this->token['secret'] = $tokenSecret;
$this->oauthData['oauth_token'] = $tokenKey;
$this->oauthData['oauth_token_secret'] = $tokenSecret;
}
/**
* Get the consumer
* #return array $consumer Containing consumer key and secret
*/
public function getConsumer() {
return $this->consumer;
}
/**
* Set the consumer
* #param string $consumerKey Consumer key
* #param string $consumerSecret Consumer secret
*/
public function setConsumer($consumerKey, $consumerSecret) {
$this->oauthData['oauth_consumer_key'] = $consumerKey;
$this->consumer['key'] = $consumerKey;
$this->consumer['secret'] = $consumerSecret;
}
/**
* Generate the signature.
* #return array Signature properties
*/
public function setSignature() {
// Set the signature method
$this->oauthData['oauth_signature_method'] = 'HMAC-SHA1';
// First, sort the OAuth data
$oauthData = $this->oauthData;
ksort($oauthData);
// Now combine them in a string
$query = http_build_query($oauthData);
// Make it URL proof
$query = rawurlencode($query);
// Fetch the method and URL
$method = $this->getMethod();
$url = $this->getURL();
// Make the URL URL proof
$url = rawurlencode($url);
// Now bind everything together
$baseString = $method . '&' . $url . '&' . $query;
// Retrieve the key
$consumer = $this->getConsumer();
$token = $this->getToken();
$key = self::encode($consumer['secret']) . '&' . self::encode($token['secret']);
// Encrypt the base string
$signature = hash_hmac('SHA1', $baseString, $key, true);
// And make it URL proof using base64_encode
$signature = base64_encode($signature);
$this->oauthData['oauth_signature'] = $signature;
}
public function setVerifier($verifier) {
$this->oauthData['oauth_verifier'] = $verifier;
}
public function debugOn() {
$this->debug = true;
}
public function debugOff() {
$this->debug = false;
}
public function setData($data) {
$this->data = $data;
}
public function call($url) {
$method = $this->getMethod();
$this->setURL($url);
$this->setNonce();
$this->setTimestamp();
$this->setSignature();
$oauthData = $this->oauthData;
$data = $this->data;
$data = array_merge($data, $oauthData);
if ($method == 'GET') {
$url = explode('#', $url);
$url = reset($url);
if (strpos($url, '?') !== false) {
$binder = '&';
} else {
$binder = '?';
}
$url .= $binder . http_build_query($oauthData);
}
$ch = curl_init();
if (!empty($headers)) {
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
if ($method == 'POST') {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $oauthData);
}
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_FAILONERROR, false);
curl_setopt($ch, CURLOPT_MAXREDIRS, 10);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_ENCODING, '');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Expect:'));
$result = curl_exec($ch);
curl_close($ch);
return $result;
}
}
$x = new OAuth();
$x->debugOn();
$x->setVersion('1.0');
$x->setConsumer('consumerToken', 'consumerSecret');
$x->setToken('accessToken', 'accessSecret');
$x->setMethod('POST');
$x->setData(array('status' => 'Hello World!'));
echo $x->call('http://api.twitter.com/1/statuses/update.json', true);
The following code is working (retrieving the access token):
$x = new OAuth();
$x->debugOn();
$x->setVersion('1.0');
$x->setConsumer('consumerToken', 'consumerSecret');
$x->setToken('accessToken', 'accessSecret');
$x->setMethod('POST');
if (isset($_GET['oauth_verifier']) && isset($_GET['oauth_token'])) {
// Request token -> Access token
$verifier = $_GET['oauth_verifier'];
$token = $_GET['oauth_token'];
$x->setVerifier($verifier);
$x->setToken($token);
$x->setMethod('GET');
$result = $x->call('https://api.twitter.com/oauth/access_token', true);
parse_str($result);
echo 'Access token: ' . $oauth_token . '<br />';
echo 'Access token secret: ' . $oauth_token_secret;
} else {
// Request token
$x->setCallback();
$x->setMethod('GET');
$result = $x->call('https://api.twitter.com/oauth/request_token');
parse_str($result);
header('Location: http://api.twitter.com/oauth/authorize?oauth_token=' . $oauth_token);
}
I'm kind of guessing here, but since you only speak of "retrieving the access token with the class", I suspect you aren't actually following through the entire Twitter OAuth authorization flow. The initial token you get back is just your starting point toward getting the real token you'll be able to use to post updates; you have to jump through a bunch of hoops.
If I'm mistaken and you have actually gone through those hoops, never mind. :)

Categories