User:Jim Carter/Bot

Classes (JimmyBot.classes.php)
&lt;?PHP /**	 * @author Jim Carter **/	/**	 * This class is designed to provide a simplified interface to cURL which maintains cookies. * @author Jim **/	class http { private $ch; private $uid; public $postfollowredirs; public $getfollowredirs;

/**		 * Our constructor function. This just does basic cURL initialization. * @return void **/		function __construct { global $proxyhost, $proxyport, $proxytype; $this-&gt;ch = curl_init; $this-&gt;uid = dechex(rand(0,99999999)); curl_setopt($this-&gt;ch,CURLOPT_COOKIEJAR,'/tmp/cluewikibot.cookies.'.$this-&gt;uid.'.dat'); curl_setopt($this-&gt;ch,CURLOPT_COOKIEFILE,'/tmp/cluewikibot.cookies.'.$this-&gt;uid.'.dat'); curl_setopt($this-&gt;ch,CURLOPT_MAXCONNECTS,100); curl_setopt($this-&gt;ch,CURLOPT_CLOSEPOLICY,CURLCLOSEPOLICY_LEAST_RECENTLY_USED); curl_setopt($this-&gt;ch,CURLOPT_USERAGENT,'ClueBot/1.1'); if (isset($proxyhost) and isset($proxyport) and ($proxyport != null) and ($proxyhost != null)) { curl_setopt($this-&gt;ch,CURLOPT_PROXYTYPE,isset( $proxytype ) ? $proxytype : CURLPROXY_HTTP); curl_setopt($this-&gt;ch,CURLOPT_PROXY,$proxyhost); curl_setopt($this-&gt;ch,CURLOPT_PROXYPORT,$proxyport); }			$this-&gt;postfollowredirs = 0; $this-&gt;getfollowredirs = 1; }

/**		 * Post to a URL. * @param $url The URL to post to. * @param $data The post-data to post, should be an array of key =&gt; value pairs. * @return Data retrieved from the POST request. **/		function post ($url,$data) { $time = microtime(1); curl_setopt($this-&gt;ch,CURLOPT_URL,$url); curl_setopt($this-&gt;ch,CURLOPT_FOLLOWLOCATION,$this-&gt;postfollowredirs); curl_setopt($this-&gt;ch,CURLOPT_MAXREDIRS,10); curl_setopt($this-&gt;ch,CURLOPT_HEADER,0); curl_setopt($this-&gt;ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($this-&gt;ch,CURLOPT_TIMEOUT,30); curl_setopt($this-&gt;ch,CURLOPT_CONNECTTIMEOUT,10); curl_setopt($this-&gt;ch,CURLOPT_POST,1); curl_setopt($this-&gt;ch,CURLOPT_POSTFIELDS, $data); curl_setopt($this-&gt;ch,CURLOPT_HTTPHEADER, array('Expect:')); $data = curl_exec($this-&gt;ch); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'POST: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data).&quot; b)\n&quot;); return $data; }

/**		 * Get a URL. * @param $url The URL to get. * @return Data retrieved from the GET request. **/		function get ($url) { $time = microtime(1); curl_setopt($this-&gt;ch,CURLOPT_URL,$url); curl_setopt($this-&gt;ch,CURLOPT_FOLLOWLOCATION,$this-&gt;getfollowredirs); curl_setopt($this-&gt;ch,CURLOPT_MAXREDIRS,10); curl_setopt($this-&gt;ch,CURLOPT_HEADER,0); curl_setopt($this-&gt;ch,CURLOPT_RETURNTRANSFER,1); curl_setopt($this-&gt;ch,CURLOPT_TIMEOUT,30); curl_setopt($this-&gt;ch,CURLOPT_CONNECTTIMEOUT,10); curl_setopt($this-&gt;ch,CURLOPT_HTTPGET,1); $data = curl_exec($this-&gt;ch); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'GET: '.$url.' ('.(microtime(1) - $time).' s) ('.strlen($data).&quot; b)\n&quot;); return $data; }

/**		 * Our destructor. Cleans up cURL and unlinks temporary files. **/		function __destruct { curl_close($this-&gt;ch); @unlink('/tmp/cluewikibot.cookies.'.$this-&gt;uid.'.dat'); }	}

/**	 * This class is a deprecated wrapper class which allows legacy code written for Wikipedia's query.php API to still work with wikipediaapi::. **/	class wikipediaquery { private $http; private $api; public $queryurl = 'http://en.wikipedia.org/w/query.php'; //Obsolete, but kept for compatibility purposes.

/**		 * This is our constructor. * @return void **/		function __construct { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; }			$this-&gt;http = &amp;$__wp__http; $this-&gt;api = new wikipediaapi; }

/**		 * Reinitializes the queryurl. * @private * @return void **/		private function checkurl { $this-&gt;api-&gt;apiurl = str_replace('query.php','api.php',$this-&gt;queryurl); }

/**		 * Gets the content of a page. * @param $page The wikipedia page to fetch. * @return The wikitext for the page. **/		function getpage ($page) { $this-&gt;checkurl; $ret = $this-&gt;api-&gt;revisions($page,1,'older',true,null,true,false,false,false); return $ret[0]['*']; }

/**		 * Gets the page id for a page. * @param $page The wikipedia page to get the id for. * @return The page id of the page. **/		function getpageid ($page) { $this-&gt;checkurl; $ret = $this-&gt;api-&gt;revisions($page,1,'older',false,null,true,false,false,false); return $ret['pageid']; }

/**		 * Gets the number of contributions a user has. * @param $user The username for which to get the edit count. * @return The number of contributions the user has. **/		function contribcount ($user) { $this-&gt;checkurl; $ret = $this-&gt;api-&gt;users($user,1,null,true); if ($ret !== false) return $ret[0]['editcount']; return false; }	}

/**	 * This class is for interacting with Wikipedia's api.php API. **/	class wikipediaapi { private $http; private $edittoken; private $tokencache; private $user, $pass; public $apiurl = 'http://en.wikipedia.org/w/api.php';

/**		 * This is our constructor. * @return void **/		function __construct { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; }			$this-&gt;http = &amp;$__wp__http; }

/**		 * This function takes a username and password and logs you into wikipedia. * @param $user Username to login as. * @param $pass Password that corrisponds to the username. * @return void **/		function login ($user,$pass) { $this-&gt;user = $user; $this-&gt;pass = $pass; $x = unserialize($this-&gt;http-&gt;post($this-&gt;apiurl.'?action=login&amp;format=php',array('lgname' =&gt; $user, 'lgpassword' =&gt; $pass))); if($x['login']['result'] == 'Success') return true; if($x['login']['result'] == 'NeedToken') { $x = unserialize($this-&gt;http-&gt;post($this-&gt;apiurl.'?action=login&amp;format=php',array('lgname' =&gt; $user, 'lgpassword' =&gt; $pass, 'lgtoken' =&gt; $x['login']['token']))); if($x['login']['result'] == 'Success') return true; }			return false; }

/**		 * This function returns the edit token. * @return Edit token. **/		function getedittoken { $tokens = $this-&gt;gettokens('Main Page'); if ($tokens['edittoken'] == '') $tokens = $this-&gt;gettokens('Main Page',true); $this-&gt;edittoken = $tokens['edittoken']; return $tokens['edittoken']; }

/**		 * This function returns the various tokens for a certain page. * @param $title Page to get the tokens for. * @param $flush Optional - internal use only. Flushes the token cache. * @return An associative array of tokens for the page. **/		function gettokens ($title,$flush = false) { if (!is_array($this-&gt;tokencache)) $this-&gt;tokencache = array; foreach ($this-&gt;tokencache as $t =&gt; $data) if (time - $data['timestamp'] &gt; 6*60*60) unset($this-&gt;tokencache[$t]); if (isset($this-&gt;tokencache[$title]) &amp;&amp; (!$flush)) { return $this-&gt;tokencache[$title]['tokens']; } else { $tokens = array; $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;format=php&amp;prop=info&amp;intoken=edit|delete|protect|move|block|unblock|email&amp;titles='.urlencode($title)); $x = unserialize($x); foreach ($x['query']['pages'] as $y) { $tokens['edittoken'] = $y['edittoken']; $tokens['deletetoken'] = $y['deletetoken']; $tokens['protecttoken'] = $y['protecttoken']; $tokens['movetoken'] = $y['movetoken']; $tokens['blocktoken'] = $y['blocktoken']; $tokens['unblocktoken'] = $y['unblocktoken']; $tokens['emailtoken'] = $y['emailtoken']; $this-&gt;tokencache[$title] = array(							'timestamp' =&gt; time,							'tokens' =&gt; $tokens									 ); return $tokens; }			}		}		/**		 * This function returns the recent changes for the wiki. * @param $count The number of items to return. (Default 10) * @param $namespace The namespace ID to filter items on. Null for no filtering. (Default null) * @param $dir The direction to pull items. &quot;older&quot; or &quot;newer&quot;. (Default 'older') * @param $ts The timestamp to start at. Null for the beginning/end (depending on direction). (Default null) * @return Associative array of recent changes metadata. **/		function recentchanges ($count = 10,$namespace = null,$dir = 'older',$ts = null) { $append = ''; if ($ts !== null) { $append .= '&amp;rcstart='.urlencode($ts); } $append .= '&amp;rcdir='.urlencode($dir); if ($namespace !== null) { $append .= '&amp;rcnamespace='.urlencode($namespace); } $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=recentchanges&amp;rcprop=user|comment|flags|timestamp|title|ids|sizes&amp;format=php&amp;rclimit='.$count.$append); $x = unserialize($x); return $x['query']['recentchanges']; }

/**		 * This function returns search results from Wikipedia's internal search engine. * @param $search The query string to search for. * @param $limit The number of results to return. (Default 10) * @param $offset The number to start at. (Default 0) * @param $namespace The namespace ID to filter by. Null means no filtering. (Default 0) * @param $what What to search, 'text' or 'title'. (Default 'text') * @param $redirs Whether or not to list redirects. (Default false) * @return Associative array of search result metadata. **/		function search ($search,$limit = 10,$offset = 0,$namespace = 0,$what = 'text',$redirs = false) { $append = ''; if ($limit != null) $append .= '&amp;srlimit='.urlencode($limit); if ($offset != null) $append .= '&amp;sroffset='.urlencode($offset); if ($namespace != null) $append .= '&amp;srnamespace='.urlencode($namespace); if ($what != null) $append .= '&amp;srwhat='.urlencode($what); if ($redirs == true) $append .= '&amp;srredirects=1'; else $append .= '&amp;srredirects=0'; $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=search&amp;format=php&amp;srsearch='.urlencode($search).$append); $x = unserialize($x); return $x['query']['search']; }

/**		 * Retrieve entries from the WikiLog. * @param $user Username who caused the entry. Null means anyone. (Default null) * @param $title Object to which the entry refers. Null means anything. (Default null) * @param $limit Number of entries to return. (Default 50) * @param $type Type of logs. Null means any type. (Default null) * @param $start Date to start enumerating logs. Null means beginning/end depending on $dir. (Default null) * @param $end Where to stop enumerating logs. Null means whenever limit is satisfied or there are no more logs. (Default null) * @param $dir Direction to enumerate logs. &quot;older&quot; or &quot;newer&quot;. (Default 'older') * @return Associative array of logs metadata. **/		function logs ($user = null,$title = null,$limit = 50,$type = null,$start = null,$end = null,$dir = 'older') { $append = ''; if ($user != null) $append.= '&amp;leuser='.urlencode($user); if ($title != null) $append.= '&amp;letitle='.urlencode($title); if ($limit != null) $append.= '&amp;lelimit='.urlencode($limit); if ($type != null) $append.= '&amp;letype='.urlencode($type); if ($start != null) $append.= '&amp;lestart='.urlencode($start); if ($end != null) $append.= '&amp;leend='.urlencode($end); if ($dir != null) $append.= '&amp;ledir='.urlencode($dir); $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;format=php&amp;list=logevents&amp;leprop=ids|title|type|user|timestamp|comment|details'.$append); $x = unserialize($x); return $x['query']['logevents']; }

/**		 * Retrieves metadata about a user's contributions. * @param $user Username whose contributions we want to retrieve. * @param $count Number of entries to return. (Default 50) * @param[in,out] $continue Where to continue enumerating if part of a larger, split request. This is filled with the next logical continuation value. (Default null) * @param $dir Which direction to enumerate from, &quot;older&quot; or &quot;newer&quot;. (Default 'older') * @return Associative array of contributions metadata. **/		function usercontribs ($user,$count = 50,&amp;$continue = null,$dir = 'older') { if ($continue != null) { $append = '&amp;ucstart='.urlencode($continue); } else { $append = ''; }			$x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;format=php&amp;list=usercontribs&amp;ucuser='.urlencode($user).'&amp;uclimit='.urlencode($count).'&amp;ucdir='.urlencode($dir).$append); $x = unserialize($x); $continue = $x['query-continue']['usercontribs']['ucstart']; return $x['query']['usercontribs']; }

/**		 * Returns revision data (meta and/or actual). * @param $page Page for which to return revision data for. * @param $count Number of revisions to return. (Default 1) * @param $dir Direction to start enumerating multiple revisions from, &quot;older&quot; or &quot;newer&quot;. (Default 'older') * @param $content Whether to return actual revision content, true or false. (Default false) * @param $revid Revision ID to start at. (Default null) * @param $wait Whether or not to wait a few seconds for the specific revision to become available. (Default true) * @param $getrbtok Whether or not to retrieve a rollback token for the revision. (Default false) * @param $dieonerror Whether or not to kill the process with an error if an error occurs. (Default false) * @param $redirects Whether or not to follow redirects. (Default false) * @return Associative array of revision data. **/		function revisions ($page,$count = 1,$dir = 'older',$content = false,$revid = null,$wait = true,$getrbtok = false,$dieonerror = true,$redirects = false) { $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;prop=revisions&amp;titles='.urlencode($page).'&amp;rvlimit='.urlencode($count).'&amp;rvprop=timestamp|ids|user|comment'.(($content)?'|content':).'&amp;format=php&amp;meta=userinfo&amp;rvdir='.urlencode($dir).(($revid !== null)?'&amp;rvstartid='.urlencode($revid):).(($getrbtok == true)?'&amp;rvtoken=rollback':).(($redirects == true)?'&amp;redirects':)); $x = unserialize($x); if ($revid !== null) { $found = false; if (!isset($x['query']['pages']) or !is_array($x['query']['pages'])) { if ($dieonerror == true) die('No such page.'.&quot;\n&quot;); else return false; }				foreach ($x['query']['pages'] as $data) { if (!isset($data['revisions']) or !is_array($data['revisions'])) { if ($dieonerror == true) die('No such page.'.&quot;\n&quot;); else return false; }					foreach ($data['revisions'] as $data2) if ($data2['revid'] == $revid) $found = true; unset($data,$data2); break; }

if ($found == false) { if ($wait == true) { sleep(1); return $this-&gt;revisions($page,$count,$dir,$content,$revid,false,$getrbtok,$dieonerror); } else { if ($dieonerror == true) die('Revision error.'.&quot;\n&quot;); }				}			}			foreach ($x['query']['pages'] as $key =&gt; $data) { $data['revisions']['ns'] = $data['ns']; $data['revisions']['title'] = $data['title']; $data['revisions']['currentuser'] = $x['query']['userinfo']['name']; //				$data['revisions']['currentuser'] = $x['query']['userinfo']['currentuser']['name']; $data['revisions']['continue'] = $x['query-continue']['revisions']['rvstartid']; $data['revisions']['pageid'] = $key; return $data['revisions']; }		}

/**		 * Enumerates user metadata. * @param $start The username to start enumerating from. Null means from the beginning. (Default null) * @param $limit The number of users to enumerate. (Default 1) * @param $group The usergroup to filter by. Null means no filtering. (Default null) * @param $requirestart Whether or not to require that $start be a valid username. (Default false) * @param[out] $continue This is filled with the name to continue from next query. (Default null) * @return Associative array of user metadata. **/		function users ($start = null,$limit = 1,$group = null,$requirestart = false,&amp;$continue = null) { $append = ''; if ($start != null) $append .= '&amp;aufrom='.urlencode($start); if ($group != null) $append .= '&amp;augroup='.urlencode($group); $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=allusers&amp;format=php&amp;auprop=blockinfo|editcount|registration|groups&amp;aulimit='.urlencode($limit).$append); $x = unserialize($x); $continue = $x['query-continue']['allusers']['aufrom']; if (($requirestart == true) and ($x['query']['allusers'][0]['name'] != $start)) return false; return $x['query']['allusers']; }

/**		 * Get members of a category. * @param $category Category to enumerate from. * @param $count Number of members to enumerate. (Default 500) * @param[in,out] $continue Where to continue enumerating from. This is automatically filled in when run. (Default null) * @return Associative array of category member metadata. **/		function categorymembers ($category,$count = 500,&amp;$continue = null) { if ($continue != null) { $append = '&amp;cmcontinue='.urlencode($continue); } else { $append = ''; }			$category = 'Category:'.str_ireplace('category:','',$category); $x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=categorymembers&amp;cmtitle='.urlencode($category).'&amp;format=php&amp;cmlimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['categorymembers']['cmcontinue']; return $x['query']['categorymembers']; }

/**		 * Enumerate all categories. * @param[in,out] $start Where to start enumerating. This is updated automatically with the value to continue from. (Default null) * @param $limit Number of categories to enumerate. (Default 50) * @param $dir Direction to enumerate in. 'ascending' or 'descending'. (Default 'ascending') * @param $prefix Only enumerate categories with this prefix. (Default null) * @return Associative array of category list metadata. **/		function listcategories (&amp;$start = null,$limit = 50,$dir = 'ascending',$prefix = null) { $append = ''; if ($start != null) $append .= '&amp;acfrom='.urlencode($start); if ($limit != null) $append .= '&amp;aclimit='.urlencode($limit); if ($dir != null) $append .= '&amp;acdir='.urlencode($dir); if ($prefix != null) $append .= '&amp;acprefix='.urlencode($prefix);

$x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=allcategories&amp;acprop=size&amp;format=php'.$append); $x = unserialize($x);

$start = $x['query-continue']['allcategories']['acfrom'];

return $x['query']['allcategories']; } 		/**		 * Enumerate all backlinks to a page. * @param $page Page to search for backlinks to. * @param $count Number of backlinks to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @param $filter Whether or not to include redirects. Acceptible values are 'all', 'redirects', and 'nonredirects'. (Default null) * @return Associative array of backlink metadata. **/		function backlinks ($page,$count = 500,&amp;$continue = null,$filter = null) { if ($continue != null) { $append = '&amp;blcontinue='.urlencode($continue); } else { $append = ''; }			if ($filter != null) { $append .= '&amp;blfilterredir='.urlencode($filter); }

$x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=backlinks&amp;bltitle='.urlencode($page).'&amp;format=php&amp;bllimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['backlinks']['blcontinue']; return $x['query']['backlinks']; }

/**		 * Gets a list of transcludes embedded in a page. * @param $page Page to look for transcludes in. * @param $count Number of transcludes to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @return Associative array of transclude metadata. **/		function embeddedin ($page,$count = 500,&amp;$continue = null) { if ($continue != null) { $append = '&amp;eicontinue='.urlencode($continue); } else { $append = ''; }			$x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=embeddedin&amp;eititle='.urlencode($page).'&amp;format=php&amp;eilimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['embeddedin']['eicontinue']; return $x['query']['embeddedin']; }

/**		 * Gets a list of pages with a common prefix. * @param $prefix Common prefix to search for. * @param $namespace Numeric namespace to filter on. (Default 0) * @param $count Number of pages to list. (Default 500) * @param[in,out] $continue Where to start enumerating from. This is automatically filled in. (Default null) * @return Associative array of page metadata. **/		function listprefix ($prefix,$namespace = 0,$count = 500,&amp;$continue = null) { $append = '&amp;apnamespace='.urlencode($namespace); if ($continue != null) { $append .= '&amp;apfrom='.urlencode($continue); }			$x = $this-&gt;http-&gt;get($this-&gt;apiurl.'?action=query&amp;list=allpages&amp;apprefix='.urlencode($prefix).'&amp;format=php&amp;aplimit='.$count.$append); $x = unserialize($x); $continue = $x['query-continue']['allpages']['apfrom']; return $x['query']['allpages']; }

/**		 * Edits a page. * @param $page Page name to edit. * @param $data Data to post to page. * @param $summary Edit summary to use. * @param $minor Whether or not to mark edit as minor. (Default false) * @param $bot Whether or not to mark edit as a bot edit. (Default true) * @param $wpStarttime Time in MW TS format of beginning of edit. (Default now) * @param $wpEdittime Time in MW TS format of last edit to that page. (Default correct) * @return boolean True on success, false on failure. **/		function edit ($page,$data,$summary = '',$minor = false,$bot = true,$wpStarttime = null,$wpEdittime = null,$checkrun = true) { global $run, $user;

$wpq = new wikipediaquery; $wpq-&gt;queryurl = str_replace('api.php','query.php',$this-&gt;apiurl);

if ($checkrun == true) if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq-&gt;getpage('User:'.$user.'/Run')))) return false; /* Check /Run page */

$params = Array(				'action' =&gt; 'edit',				'format' =&gt; 'php',				'assert' =&gt; 'bot',				'title' =&gt; $page,				'text' =&gt; $data,				'token' =&gt; $this-&gt;getedittoken,				'summary' =&gt; $summary,				($minor?'minor':'notminor') =&gt; '1',				($bot?'bot':'notbot') =&gt; '1'			);

if ($wpStarttime !== null) $params['starttimestamp'] = $wpStarttime; if ($wpEdittime !== null) $params['basetimestamp'] = $wpEdittime;

$x = $this-&gt;http-&gt;post($this-&gt;apiurl,$params); $x = unserialize($x); var_export($x); if ($x['edit']['result'] == 'Success') return true; if ($x['error']['code'] == 'badtoken') { if($this-&gt;login($this-&gt;user,$this-&gt;pass)) { $this-&gt;gettokens('Main Page',true); return $this-&gt;edit($page,$data,$summary,$minor,$bot,$wpStarttime,$wpEdittime,$checkrun); } else return false; }			else return false; } 		/**		 * Moves a page. * @param $old Name of page to move. * @param $new New page title. * @param $reason Move summary to use. * @return void **/		function move ($old,$new,$reason) { $tokens = $this-&gt;gettokens($old); $params = array(				'action' =&gt; 'move',				'format' =&gt; 'php',				'from' =&gt; $old,				'to' =&gt; $new,				'token' =&gt; $tokens['movetoken'],				'reason' =&gt; $reason			);

$x = $this-&gt;http-&gt;post($this-&gt;apiurl,$params); $x = unserialize($x); var_export($x); }

/**		 * Rollback an edit. * @param $title Title of page to rollback. * @param $user Username of last edit to the page to rollback. * @param $reason Edit summary to use for rollback. * @param $token Rollback token. If not given, it will be fetched. (Default null) * @return void **/		function rollback ($title,$user,$reason,$token = null) { if (($token == null) or ($token == '')) { $token = $this-&gt;revisions($title,1,'older',false,null,true,true); print_r($token); if ($token[0]['user'] == $user) { $token = $token[0]['rollbacktoken']; } else { return false; }			}			$params = array(				'action' =&gt; 'rollback',				'format' =&gt; 'php',				'title' =&gt; $title,				'user' =&gt; $user,				'summary' =&gt; $reason,				'token' =&gt; $token,				'markbot' =&gt; 0			);

echo 'Posting to API: '; var_export($params); $x = $this-&gt;http-&gt;post($this-&gt;apiurl,$params); $x = unserialize($x); var_export($x); return ( isset($x['rollback']['summary']) and isset( $x[ 'rollback' ][ 'revid' ] ) and $x[ 'rollback' ][ 'revid' ] ) ? true : false; }	}

/**	 * This class is for interacting with Wikipedia's browser interface, index.php. * Many of these functions are deprecated. **/	class wikipediaindex { private $http; public $indexurl = 'http://en.wikipedia.org/w/index.php'; private $postinterval = 0; private $lastpost; private $edittoken;

/**		 * This is our constructor. * @return void **/		function __construct { global $__wp__http; if (!isset($__wp__http)) { $__wp__http = new http; }			$this-&gt;http = &amp;$__wp__http; }

/**		 * Post data to a page, nicely. * @param $page Page title. * @param $data Data to post to page. * @param $summery Edit summary. (Default '') * @param $minor Whether to mark edit as minor. (Default false) * @param $rv Revision data. If not given, it will be fetched. (Default null) * @param $bot Whether to mark edit as bot. (Default true) * @return HTML data from the page. * @deprecated * @see wikipediaapi::edit **/		function post ($page,$data,$summery = '',$minor = false,$rv = null,$bot = true) { global $user; global $maxlag; global $irc; global $irctechchannel; global $run; global $maxlagkeepgoing;

$wpq = new wikipediaquery; $wpq-&gt;queryurl = str_replace('index.php','query.php',$this-&gt;indexurl); $wpapi = new wikipediaapi; $wpapi-&gt;apiurl = str_replace('index.php','api.php',$this-&gt;indexurl);

if ((!$this-&gt;edittoken) or ($this-&gt;edittoken == '')) $this-&gt;edittoken = $wpapi-&gt;getedittoken; if ($rv == null) $rv = $wpapi-&gt;revisions($page,1,'older',true); if (!$rv[0]['*']) $rv[0]['*'] = $wpq-&gt;getpage($page);

//Fake the edit form. $now = gmdate('YmdHis', time); $token = htmlspecialchars($this-&gt;edittoken); $tmp = date_parse($rv[0]['timestamp']); $edittime = gmdate('YmdHis', gmmktime($tmp['hour'],$tmp['minute'],$tmp['second'],$tmp['month'],$tmp['day'],$tmp['year'])); $html = &quot;&lt;input type='hidden' value=\&quot;{$now}\&quot; name=\&quot;wpStarttime\&quot; /&gt;\n&quot;; $html.= &quot;&lt;input type='hidden' value=\&quot;{$edittime}\&quot; name=\&quot;wpEdittime\&quot; /&gt;\n&quot;; $html.= &quot;&lt;input type='hidden' value=\&quot;{$token}\&quot; name=\&quot;wpEditToken\&quot; /&gt;\n&quot;; $html.= '&lt;input name=&quot;wpAutoSummary&quot; type=&quot;hidden&quot; value=&quot;'.md5('').'&quot; /&gt;'.&quot;\n&quot;;

if (preg_match('/'.preg_quote('','/').'/iS',$rv[0]['*'])) { return false; }		/* Honor the bots flags */ if (preg_match('/'.preg_quote('','/').'/iS',$rv[0]['*'])) { return false; } if (preg_match('/'.preg_quote('','/').'/iS',$rv[0]['*'])) { return false; } if (preg_match('/'.preg_quote('','/').'/iS',$rv[0]['*'],$m)) { if (in_array(explode(',',$m[1]),$user)) { return false; } } /* /Honor the bots flags */ if (!preg_match('/'.preg_quote($user,'/').'/iS',$rv['currentuser'])) { return false; } /* We need to be logged in */ //			if (preg_match('/'.preg_quote('You have new messages','/').'/iS',$rv[0]['*'])) { return false; } /* Check talk page */ if (!preg_match('/(yes|enable|true)/iS',((isset($run))?$run:$wpq-&gt;getpage('User:'.$user.'/Run')))) { return false; } /* Check /Run page */

$x = $this-&gt;forcepost($page,$data,$summery,$minor,$html,$maxlag,$maxlagkeepgoing,$bot); /* Go ahead and post. */			$this-&gt;lastpost = time; return $x; }

/**		 * Post data to a page. * @param $page Page title. * @param $data Data to post to page. * @param $summery Edit summary. (Default '') * @param $minor Whether to mark edit as minor. (Default false) * @param $edithtml HTML from the edit form. If not given, it will be fetched. (Default null) * @param $maxlag Maxlag for posting. (Default null) * @param $mlkg Whether to keep going after encountering a maxlag error and sleeping or not. (Default null) * @param $bot Whether to mark edit as bot. (Default true) * @return HTML data from the page. * @deprecated * @see wikipediaapi::edit **/		function forcepost ($page,$data,$summery = '',$minor = false,$edithtml = null,$maxlag = null,$mlkg = null,$bot = true) { $post['wpSection'] = ''; $post['wpScrolltop'] = ''; if ($minor == true) { $post['wpMinoredit'] = 1; } $post['wpTextbox1'] = $data; $post['wpSummary'] = $summery; if ($edithtml == null) { $html = $this-&gt;http-&gt;get($this-&gt;indexurl.'?title='.urlencode($page).'&amp;action=edit'); } else { $html = $edithtml; }			preg_match('|\&lt;input type\=\\\'hidden\\\' value\=\&quot;(.*)\&quot; name\=\&quot;wpStarttime\&quot; /\&gt;|U',$html,$m); $post['wpStarttime'] = $m[1]; preg_match('|\&lt;input type\=\\\'hidden\\\' value\=\&quot;(.*)\&quot; name\=\&quot;wpEdittime\&quot; /\&gt;|U',$html,$m); $post['wpEdittime'] = $m[1]; preg_match('|\&lt;input type\=\\\'hidden\\\' value\=\&quot;(.*)\&quot; name\=\&quot;wpEditToken\&quot; /\&gt;|U',$html,$m); $post['wpEditToken'] = $m[1]; preg_match('|\&lt;input name\=\&quot;wpAutoSummary\&quot; type\=\&quot;hidden\&quot; value\=\&quot;(.*)\&quot; /\&gt;|U',$html,$m); $post['wpAutoSummary'] = $m[1]; if ($maxlag != null) { $x = $this-&gt;http-&gt;post($this-&gt;indexurl.'?title='.urlencode($page).'&amp;action=submit&amp;maxlag='.urlencode($maxlag).'&amp;bot='.(($bot == true)?'1':'0'),$post); if (preg_match('/Waiting for ([^ ]*): ([0-9.-]+) seconds lagged/S',$x,$lagged)) { global $irc; if (is_resource($irc)) { global $irctechchannel; foreach(explode(',',$irctechchannel) as $y) { fwrite($irc,'PRIVMSG '.$y.' :'.$lagged[1].' is lagged out by '.$lagged[2].' seconds. ('.$lagged[0].')'.&quot;\n&quot;); }					}					sleep(10); if ($mlkg != true) { return false; } else { $x = $this-&gt;http-&gt;post($this-&gt;indexurl.'?title='.urlencode($page).'&amp;action=submit&amp;bot='.(($bot == true)?'1':'0'),$post); } }				return $x; } else { return $this-&gt;http-&gt;post($this-&gt;indexurl.'?title='.urlencode($page).'&amp;action=submit&amp;bot='.(($bot == true)?'1':'0'),$post); }		} 		/**		 * Get a diff. * @param $title Page title to get the diff of. * @param $oldid Old revision ID. * @param $id New revision ID. * @param $wait Whether or not to wait for the diff to become available. (Default true) * @return Array of added data, removed data, and a rollback token if one was fetchable. **/		function diff ($title,$oldid,$id,$wait = true) { $deleted = ''; $added = '';

$html = $this-&gt;http-&gt;get($this-&gt;indexurl.'?title='.urlencode($title).'&amp;action=render&amp;diff='.urlencode($id).'&amp;oldid='.urlencode($oldid).'&amp;diffonly=1');

if (preg_match_all('/\&amp;amp\;(oldid\=)(\d*)\\\'\&gt;(Revision as of|Current revision as of)/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); if ((($oldid != $m[0][2]) and (is_numeric($oldid))) or (($id != $m[1][2]) and (is_numeric($id)))) { if ($wait == true) { sleep(1); return $this-&gt;diff($title,$oldid,$id,false); } else { echo 'OLDID as detected: '.$m[0][2].' Wanted: '.$oldid.&quot;\n&quot;; echo 'NEWID as detected: '.$m[1][2].' Wanted: '.$id.&quot;\n&quot;; echo $html; die('Revision error.'.&quot;\n&quot;); }				}			}			if (preg_match_all('/\&lt;td class\=(\&quot;|\\\')diff-addedline\1\&gt;\&lt;div\&gt;(.*)\&lt;\/div\&gt;\&lt;\/td\&gt;/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); foreach ($m as $x) { $added .= htmlspecialchars_decode(strip_tags($x[2])).&quot;\n&quot;; }			}

if (preg_match_all('/\&lt;td class\=(\&quot;|\\\')diff-deletedline\1\&gt;\&lt;div\&gt;(.*)\&lt;\/div\&gt;\&lt;\/td\&gt;/USs', $html, $m, PREG_SET_ORDER)) { //print_r($m); foreach ($m as $x) { $deleted .= htmlspecialchars_decode(strip_tags($x[2])).&quot;\n&quot;; }			}

//echo $added.&quot;\n&quot;.$deleted.&quot;\n&quot;;

if (preg_match('/action\=rollback\&amp;amp\;from\=.*\&amp;amp\;token\=(.*)\&quot;/US', $html, $m)) { $rbtoken = $m[1]; $rbtoken = urldecode($rbtoken); //				echo 'rbtoken: '.$rbtoken.' -- '; print_r($m); echo &quot;\n\n&quot;; return array($added,$deleted,$rbtoken); }

return array($added,$deleted); }

/**		 * Rollback an edit. * @param $title Page title to rollback. * @param $user Username of last edit to the page to rollback. * @param $reason Reason to rollback. If null, default is generated. (Default null) * @param $token Rollback token to use. If null, it is fetched. (Default null) * @param $bot Whether or not to mark as bot. (Default true) * @return HTML or false if failure. * @deprecated * @see wikipediaapi::rollback **/		function rollback ($title,$user,$reason = null,$token = null,$bot = true) { if (($token == null) or (!$token)) { $wpapi = new wikipediaapi; $wpapi-&gt;apiurl = str_replace('index.php','api.php',$this-&gt;indexurl); $token = $wpapi-&gt;revisions($title,1,'older',false,null,true,true); if ($token[0]['user'] == $user) { //					echo 'Token: '; print_r($token); echo &quot;\n\n&quot;; $token = $token[0]['rollbacktoken']; } else { return false; }			}			$x = $this-&gt;http-&gt;get($this-&gt;indexurl.'?title='.urlencode($title).'&amp;action=rollback&amp;from='.urlencode($user).'&amp;token='.urlencode($token).(($reason != null)?'&amp;summary='.urlencode($reason):'').'&amp;bot='.(($bot == true)?'1':'0')); global $logfd; if (!is_resource($logfd)) $logfd = fopen('php://stderr','w'); fwrite($logfd,'Rollback return: '.$x.&quot;\n&quot;); if (!preg_match('/action complete/iS',$x)) return false; return $x; } 		/**		 * Move a page. * @param $old Page title to move. * @param $new New title to move to. * @param $reason Move page summary. * @return HTML page. * @deprecated * @see wikipediaapi::move **/		function move ($old,$new,$reason) { $wpapi = new wikipediaapi; $wpapi-&gt;apiurl = str_replace('index.php','api.php',$this-&gt;indexurl); if ((!$this-&gt;edittoken) or ($this-&gt;edittoken == '')) $this-&gt;edittoken = $wpapi-&gt;getedittoken;

$token = htmlspecialchars($this-&gt;edittoken);

$post = array (					'wpOldTitle'	=&gt; $old,					'wpNewTitle'	=&gt; $new,					'wpReason'	=&gt; $reason,					'wpWatch'	=&gt; '0',					'wpEditToken'	=&gt; $token,					'wpMove'	=&gt; 'Move page'				); return $this-&gt;http-&gt;post($this-&gt;indexurl.'?title=Special:Movepage&amp;action=submit',$post); }

/**		 * Uploads a file. * @param $page Name of page on the wiki to upload as. * @param $file Name of local file to upload. * @param $desc Content of the file description page. * @return HTML content. **/		function upload ($page,$file,$desc) { $post = array (					'wpUploadFile'		=&gt; '@'.$file,					'wpSourceType'		=&gt; 'file',					'wpDestFile'		=&gt; $page,					'wpUploadDescription'	=&gt; $desc,					'wpLicense'		=&gt; '',					'wpWatchthis'		=&gt; '0',					'wpIgnoreWarning'	=&gt; '1',					'wpUpload'		=&gt; 'Upload file'				); return $this-&gt;http-&gt;post($this-&gt;indexurl.'?title=Special:Upload&amp;action=submit',$post); }

/**		 * Check if a user has email enabled. * @param $user Username to check whether or not the user has email enabled. * @return True or false depending on whether or not the user has email enabled. **/		function hasemail ($user) { $tmp = $this-&gt;http-&gt;get($this-&gt;indexurl.'?title=Special:EmailUser&amp;target='.urlencode($user)); if (stripos($tmp,&quot;No e-mail address&quot;) !== false) return false; return true; }

/**		 * Sends an email to a user. * @param $user Username to send email to. * @param $subject Subject of email to send. * @param $body Body of email to send. * @return HTML content. **/		function email ($user,$subject,$body) { $wpapi = new wikipediaapi; $wpapi-&gt;apiurl = str_replace('index.php','api.php',$this-&gt;indexurl); if ((!$this-&gt;edittoken) or ($this-&gt;edittoken == '')) $this-&gt;edittoken = $wpapi-&gt;getedittoken;

$post = array (					'wpSubject'	=&gt; $subject,					'wpText'	=&gt; $body,					'wpCCMe'	=&gt; 0,					'wpSend'	=&gt; 'Send',					'wpEditToken'	=&gt; $this-&gt;edittoken				);

return $this-&gt;http-&gt;post($this-&gt;indexurl.'?title=Special:EmailUser&amp;target='.urlencode($user).'&amp;action=submit',$post); }	} ?&gt;