Last active
August 29, 2015 14:18
-
-
Save mozeryansky/9bcc2f9c7c34a7c35b53 to your computer and use it in GitHub Desktop.
T-Square Wiki Reporting Tool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
$teamURL = ""; | |
$username = ""; | |
$password = ""; | |
if(empty($teamURL)){ | |
echo "You can hard code your team's main site URL, along with all user inputs at the top of the source file.\n"; | |
echo "To find your team's site, login to t-square, navigate to your team's site, and copy the current url.\n"; | |
echo "It should look something like this: https://t-square.gatech.edu/portal/site/abcd1234-ab12-cd34-ad14-abcd1234a1b2\n"; | |
echo "\n"; | |
fwrite(STDOUT, "Team Site URL: "); | |
$teamURL = trim(fgets(STDIN)); | |
} | |
if(empty($username)){ | |
fwrite(STDOUT, "Username: "); | |
$username = trim(fgets(STDIN)); | |
} | |
if(empty($password)){ | |
fwrite(STDOUT, "Password: "); | |
$password = preg_replace('/\r?\n$/', '', `stty -echo; head -n1 ; stty echo`); | |
echo "\n"; | |
} | |
$ckfile = tempnam("/tmp", "CURLCOOKIE"); | |
$headers = array( | |
'User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13', | |
'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', | |
'Accept-Language: en-us,en;q=0.5', | |
'Accept-Encoding: gzip,deflate', | |
'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7', | |
'Keep-Alive: 115', | |
'Connection: keep-alive' | |
); | |
function createCurlHandle($url) | |
{ | |
global $headers, $ckfile; | |
$ch = curl_init(); | |
curl_setopt($ch, CURLOPT_URL, $url); | |
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); | |
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); | |
curl_setopt($ch, CURLOPT_COOKIEFILE, $ckfile); | |
curl_setopt($ch, CURLOPT_COOKIEJAR, $ckfile); | |
curl_setopt($ch, CURLOPT_HEADER, true); | |
//curl_setopt($ch, CURLOPT_VERBOSE, true); | |
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | |
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); | |
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); | |
return $ch; | |
} | |
function executeCurl($ch) | |
{ | |
$output = curl_exec($ch); | |
if(curl_errno(($ch))){ | |
echo 'Curl error: ' . curl_error($ch); | |
exit(); | |
} | |
curl_close($ch); | |
return $output; | |
} | |
function say($message) | |
{ | |
echo $message."\n"; | |
} | |
/************ Get Login Page *****************/ | |
say('Aquiring Login Page'); | |
$tsquareLoginURL = 'https://t-square.gatech.edu/portal/login'; | |
$output = executeCurl(createCurlHandle($tsquareLoginURL)); | |
$doc = new DOMDocument(); | |
@$doc->loadHTML($output); | |
$form = $doc->getElementById('fm1'); | |
// get unique login url | |
$loginurl = 'https://login.gatech.edu'.$form->getAttribute('action'); | |
// get the lt code. This is new and completely useless... | |
// probably just prevents non-targeted brute force logins | |
$inputs = $doc->getElementsByTagName('input'); | |
foreach($inputs as $input){ | |
if(trim($input->getAttribute('name')) == "lt"){ | |
$lt = $input->getAttribute('value'); | |
break; | |
} | |
} | |
/*************** Login ********************/ | |
say('Loggin In'); | |
$post = array( | |
'username' => $username, | |
'password' => $password, | |
'execution' => 'e1s1', | |
'lt' => $lt, | |
'_eventId' => 'submit', | |
'submit' => 'LOGIN' | |
); | |
$ch = createCurlHandle($loginurl); | |
curl_setopt($ch, CURLOPT_POST, true); | |
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post)); | |
$output = executeCurl($ch); | |
/*************** Goto Team Page ********************/ | |
say('Navigating to Team Site'); | |
// Our Tsquare Site | |
$output = executeCurl(createCurlHandle($teamURL)); | |
$doc = new DOMDocument(); | |
@$doc->loadHTML($output); | |
$toolMenuLinks = $doc->getElementById('toolMenu')->getElementsByTagName('a'); | |
foreach($toolMenuLinks as $link){ | |
if(trim($link->getAttribute('class')) == "icon-sakai-rwiki"){ | |
$wikiURL = $link->getAttribute('href'); | |
break; | |
} | |
} | |
/*************** Select Wiki ********************/ | |
say('Opening Wiki Page'); | |
$output = executeCurl(createCurlHandle($wikiURL)); | |
$doc = new DOMDocument(); | |
@$doc->loadHTML($output); | |
$iframes = $doc->getElementsByTagName('iframe'); | |
foreach($iframes as $iframe){ | |
if(trim($iframe->getAttribute('title')) == "Wiki"){ | |
$wikiIframeURL = $iframe->getAttribute('src'); | |
break; | |
} | |
} | |
list($wikiBaseURL) = explode('?', $wikiIframeURL);// cheap method | |
/*************** Explore our Wiki ********************/ | |
say('Begin exploring the Wiki'); | |
$sayExploring = true; | |
function makeDoc($output) | |
{ | |
$doc = new DOMDocument(); | |
@$doc->loadHTML($output); | |
return $doc; | |
} | |
function getBody($doc) | |
{ | |
$contentDivs = $doc->getElementById('rwiki_content')->getElementsByTagName('div'); | |
$body = false; | |
foreach($contentDivs as $div){ | |
if(strtolower(trim($div->getAttribute('class'))) == "rwikirenderedcontent"){ | |
$body = $div; | |
break; | |
} | |
} | |
if($body === false){ | |
echo "Could not find wiki body!"; | |
exit; | |
} | |
return $body; | |
} | |
function getLinks($element) | |
{ | |
global $wikiBaseURL; | |
$linksArr = array(); | |
$links = $element->getElementsByTagName('a'); | |
foreach($links as $link){ | |
// skip anchors | |
if($link->getAttribute('class') == "anchorpoint"){ | |
continue; | |
} | |
$url = $link->getAttribute('href'); | |
$newLink = array( | |
'url' => $wikiBaseURL.$url, | |
'name' => $link->nodeValue, | |
'external' => false | |
); | |
// mark external links | |
if($url[0] != '?'){ | |
$newLink['external'] = true; | |
} | |
$linksArr[] = $newLink; | |
} | |
return $linksArr; | |
} | |
function recursively_find_text_nodes($dom_element, $depth=1) | |
{ | |
$return = array(); | |
foreach ($dom_element->childNodes as $dom_child) { | |
switch ($dom_child->nodeType) { | |
case XML_TEXT_NODE: | |
if (trim($dom_child->nodeValue) !== '') { | |
$return[] = array ( | |
'depth' => $depth, | |
'value' => $dom_child->nodeValue | |
); | |
} | |
break; | |
case XML_ELEMENT_NODE: | |
/*$return[] = array ( | |
'depth' => $depth, | |
'value' => $dom_child | |
);*/ | |
$return = array_merge($return, recursively_find_text_nodes($dom_child, $depth+1)); | |
break; | |
} | |
} | |
return $return; | |
} | |
function getPageHistory($doc) | |
{ | |
global $wikiBaseURL; | |
$historyURL = $wikiBaseURL.$doc->getElementById('historyLink')->getAttribute('href'); | |
$output = executeCurl(createCurlHandle($historyURL)); | |
$body = getBody(makeDoc($output)); | |
$edits = array(); | |
$rows = $body->getElementsByTagName('tr'); | |
$rowsArr = array(); | |
foreach($rows as $row){ | |
$cells = $row->getElementsByTagName('td'); | |
$cellArr = array(); | |
foreach($cells as $cell){ | |
$cellArr[] = trim($cell->textContent); | |
} | |
if(empty($cellArr)){ | |
continue; | |
} | |
$name = $cellArr[1]; | |
$rowsArr[] = $name; | |
$creator = $name; | |
if(!isset($edits[$name])){ | |
$edits[$name] = 0; | |
} | |
$edits[$name]++; | |
} | |
$lastModifier = $rowsArr[0]; | |
arsort($edits); | |
reset($edits); | |
$majority = key($edits); | |
$history = array( | |
'editors' => $rowsArr, | |
'edits' => count($rowsArr), | |
'creator' => $creator, | |
'lastModifier' => $lastModifier, | |
'majority' => $majority | |
); | |
return $history; | |
} | |
$pagesVisited = array(); | |
function exploreWiki(&$wiki, $level) | |
{ | |
global $pagesVisited, $sayExploring; | |
$tabs = str_repeat("\t", $level); | |
if($wiki['external']){ | |
if($sayExploring){ | |
say($tabs."External: ".$wiki['name']); | |
} | |
$wiki['explored'] = false; | |
return; | |
} | |
if(substr($wiki['name'], -1, 1) == '?'){ | |
if($sayExploring){ | |
say($tabs."Empty: ".$wiki['name']); | |
} | |
$wiki['emptyPage'] = true; | |
$wiki['explored'] = false; | |
return; | |
} | |
$wiki['emptyPage'] = false; | |
$url = $wiki['url']; | |
if(in_array($wiki['name'], $pagesVisited)){ | |
$wiki['explored'] = false; | |
//say($tabs."Recursion: ".$wiki['name']); | |
return;// don't allow recursive links | |
} | |
$wiki['explored'] = true; | |
$pagesVisited[] = $wiki['name']; | |
if($sayExploring){ | |
say($tabs."Exploring: ".$wiki['name']); | |
} | |
$output = executeCurl(createCurlHandle($url)); | |
$doc = makeDoc($output); | |
$history = getPageHistory($doc); | |
$wiki['history'] = $history; | |
$body = getBody($doc); | |
// counts | |
$textnodes = recursively_find_text_nodes($body); | |
$words = 0; | |
$characters = 0; | |
foreach($textnodes as $node){ | |
$words += substr_count($node['value'], " ")+1; | |
$characters += strlen($node['value']); | |
} | |
$wiki['lineCount'] = count($textnodes); | |
$wiki['wordCount'] = $words; | |
$wiki['characterCount'] = $characters; | |
// links | |
$newlinks = getLinks($body); | |
foreach($newlinks as $link){ | |
// add to wiki structure | |
$name = $link['name']; | |
$url = $link['url']; | |
// build newWiki array | |
$newWiki = $link; | |
$newWiki['links'] = array(); | |
// add reference | |
$wiki['links'][] = &$newWiki; | |
// explore | |
exploreWiki($newWiki, $level+1); | |
// unset the reference, to reuse this variable in the next loop | |
// silly php you're so advanced | |
unset($newWiki); | |
} | |
} | |
// create wiki strarting structure | |
$wiki = array( | |
array( | |
'name' => 'Home', | |
'url' => $wikiIframeURL, | |
'external' => false, | |
'links' => array() | |
) | |
); | |
// being exploring | |
exploreWiki($wiki[0], 0); | |
say('Finished exploring the Wiki'); | |
// all raw data! Including SSN and passwords. | |
// print_r($wiki); | |
// create the final report | |
function reportOverview($wiki, &$info) | |
{ | |
if(!$wiki['explored']){ | |
return; | |
} | |
$info['pages']++; | |
$info['lines'] += $wiki['lineCount']; | |
$info['words'] += $wiki['wordCount']; | |
$info['characters'] += $wiki['characterCount']; | |
$info['edits'] += $wiki['history']['edits']; | |
$links = $wiki['links']; | |
foreach($links as $wiki){ | |
reportOverview($wiki, $info); | |
} | |
} | |
function reportContentShare($wiki, &$share) | |
{ | |
if(!$wiki['explored']){ | |
return; | |
} | |
$shareArray = array( | |
'creator' => array(), | |
'lastModifier' => array(), | |
'majority' => array(), | |
'edits' => 0 | |
); | |
$creator = $wiki['history']['creator']; | |
if(!isset($share[$creator])){ | |
$share[$creator] = $shareArray; | |
} | |
$share[$creator]['creator'][] = $wiki['name']; | |
$lastModifier = $wiki['history']['lastModifier']; | |
if(!isset($share[$lastModifier])){ | |
$share[$lastModifier] = $shareArray; | |
} | |
$share[$lastModifier]['lastModifier'][] = $wiki['name']; | |
$majority = $wiki['history']['majority']; | |
if(!isset($share[$majority])){ | |
$share[$majority] = $shareArray; | |
} | |
$share[$majority]['majority'][] = $wiki['name']; | |
foreach($wiki['history']['editors'] as $editor){ | |
if(!isset($share[$editor])){ | |
$share[$editor] = $shareArray; | |
} | |
$share[$editor]['edits']++; | |
} | |
$links = $wiki['links']; | |
foreach($links as $wiki){ | |
reportContentShare($wiki, $share); | |
} | |
} | |
function reportWikiStructure($wiki, $level) | |
{ | |
if(!$wiki['explored'] && !$wiki['external']){ | |
return; | |
} | |
$name = $wiki['name']; | |
$links = $wiki['links']; | |
$external = $wiki['external']; | |
$tabs = str_repeat("\t", $level); | |
$externalTxt = ''; | |
if($external){ | |
$externalTxt = 'External: '; | |
} | |
say($tabs.$externalTxt.$name); | |
foreach($links as $wiki){ | |
reportWikiStructure($wiki, $level+1); | |
} | |
} | |
function reporDetailedStructure($wiki, $level) | |
{ | |
if(!$wiki['explored'] && !$wiki['external']){ | |
return; | |
} | |
$name = $wiki['name']; | |
$links = $wiki['links']; | |
$external = $wiki['external']; | |
$tabs = str_repeat("\t", $level); | |
$externalTxt = ''; | |
if($external){ | |
$externalTxt = 'External: '; | |
} | |
// title | |
say($tabs.$externalTxt.$name); | |
// details | |
if(isset($wiki['history'])){ | |
say($tabs.' - Creator: '.$wiki['history']['creator']); | |
say($tabs.' - Last Editor: '.$wiki['history']['lastModifier']); | |
say($tabs.' - Majority Editor: '.$wiki['history']['majority']); | |
say($tabs.' - Edits: '.$wiki['history']['edits']); | |
} | |
if(isset($wiki['lineCount'])){ | |
say($tabs.' - Lines: '.$wiki['lineCount']); | |
} | |
if(isset($wiki['wordCount'])){ | |
say($tabs.' - Words: '.$wiki['wordCount']); | |
} | |
foreach($links as $wiki){ | |
reporDetailedStructure($wiki, $level+1); | |
} | |
} | |
say('Creating report'); | |
// create overview | |
say('Generating overview'); | |
$info = array( | |
'pages' => 0, | |
'lines' => 0, | |
'words' => 0, | |
'characters' => 0, | |
'edits' => 0 | |
); | |
reportOverview($wiki[0], $info); | |
say('Generating content share'); | |
$share = array(); | |
reportContentShare($wiki[0], $share); | |
ob_start(); | |
foreach($share as $person=>$details){ | |
say($person); | |
say('Total Edits: '.$details['edits']); | |
say('Creator'); | |
foreach($details['creator'] as $page){ | |
say("\t".$page); | |
} | |
say('Last Modifier'); | |
foreach($details['lastModifier'] as $page){ | |
say("\t".$page); | |
} | |
say('Majority Editor'); | |
foreach($details['majority'] as $page){ | |
say("\t".$page); | |
} | |
say(''); | |
} | |
$detailedShare = ob_get_contents(); | |
ob_end_clean(); | |
ob_start(); | |
say('Total Pages: '.$info['pages']); | |
say('Total Lines: '.$info['lines']); | |
say('Total Words: '.$info['words']); | |
say('Total Characters: '.$info['characters']); | |
say('Total Edits: '.$info['edits']); | |
say(''); | |
say('=== Content Share ==='); | |
say(''); | |
foreach($share as $name=>$details){ | |
say($name); | |
say("\t".'Total Edits: '.$details['edits']); | |
say("\t".'Created Pages: '.count($details['creator'])); | |
say("\t".'Last To Modify Pages: '.count($details['lastModifier'])); | |
say("\t".'Majority Editor Pages: '.count($details['majority'])); | |
} | |
$overview = ob_get_contents(); | |
ob_end_clean(); | |
// general structure | |
say('Generating structure'); | |
ob_start(); | |
reportWikiStructure($wiki[0], 0); | |
$wikiStructure = ob_get_contents(); | |
ob_end_clean(); | |
// structure with details | |
say('Generating detailed structure'); | |
ob_start(); | |
reporDetailedStructure($wiki[0], 0); | |
$detailedStructure = ob_get_contents(); | |
ob_end_clean(); | |
// compile reports together | |
$filename = 'wiki_'.date('F_d_Y_h_i_a').'.txt'; | |
say('Saving report: '.$filename); | |
$report = "=== Wiki Report ===\n\n"; | |
$report .= date('F d, Y g:ia')."\n\n"; | |
$report .= $overview."\n\n"; | |
$report .= "=== Wiki Structure ===\n\n"; | |
$report .= $wikiStructure."\n\n"; | |
$report .= "=== Detailed Share Info ===\n\n"; | |
$report .= $detailedShare."\n\n"; | |
$report .= "=== Detailed Structure ===\n\n"; | |
$report .= $detailedStructure; | |
// save report | |
@mkdir('reports'); | |
file_put_contents('reports/'.$filename, $report); | |
say('Done'); | |
?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment