/** * Used to get the published patches of a given server and a given pushfeed * (and optionnaly a page title) * @param <string> $server url of the server * @param <string> $pushName pushfeed name * @param <string> $title article title * @return <array> array of patchIDs */ static function getPublishedPatchs($server, $pushName, $title = null) { //global $wgScriptExtension; $published = array(); $pushName = str_replace(' ', '_', $pushName); $title = str_replace(' ', '_', $title); if (isset($title)) { $patchXML = utils::file_get_contents_curl(utils::lcfirst($server) . "/api.php?action=query&meta=patchPushed&pppushName=" . $pushName . '&pppageName=' . $title . '&format=xml'); /*test if it is a xml file. If not, the server is not reachable via the url * Then we try to reach it with the .php5 extension */ if (strpos($patchXML, "<?xml version=\"1.0\"?>") === false) { $patchXML = utils::file_get_contents_curl(utils::lcfirst($server) . "/api.php5?action=query&meta=patchPushed&pppushName=" . $pushName . '&pppageName=' . $title . '&format=xml'); } if (strpos($patchXML, "<?xml version=\"1.0\"?>") === false) { $patchXML = false; } } else { $patchXML = utils::file_get_contents_curl(utils::lcfirst($server) . "/api.php?action=query&meta=patchPushed&pppushName=" . $pushName . '&format=xml'); /*test if it is a xml file. If not, the server is not reachable via the url * Then we try to reach it with the .php5 extension */ if (strpos($patchXML, "<?xml version=\"1.0\"?>") === false) { $patchXML = utils::file_get_contents_curl(utils::lcfirst($server) . "/api.php5?action=query&meta=patchPushed&pppushName=" . $pushName . '&format=xml'); } if (strpos($patchXML, "<?xml version=\"1.0\"?>") === false) { $patchXML = false; } } if ($patchXML === false) { return false; } $patchXML = trim($patchXML); $dom = new DOMDocument(); $dom->loadXML($patchXML); $patchPublished = $dom->getElementsByTagName('patch'); $published = array(); foreach ($patchPublished as $p) { $published[] = $p->firstChild->nodeValue; } return $published; }
/** * MW Hook used to redirect to page creation (pushfeed, pullfeed, changeset), * to forms or to push/pull action testing the action param * * @since 1.1 * * @param string $action * @param Article $article * * @return true */ public function onUnknownAction($action, Article $article) { global $wgOut, $wgServerName, $wgScriptPath, $wgUser, $wgScriptExtension, $wgDSMWIP; $urlServer = 'http://' . $wgServerName . $wgScriptPath . "/index{$wgScriptExtension}"; $urlAjax = 'http://' . $wgServerName . $wgScriptPath; ///////// / pull form page//////// if (isset($_GET['action']) && $_GET['action'] == 'addpullpage') { wfDebugLog('p2p', 'addPullPage '); $newtext = "Add a new site:\n\t<div id='dsmw' style=\"color:green;\"></div>\n\n\t{{#form:action=" . $urlServer . "?action=pullpage|method=POST|\n\t\tPushFeed Url: {{#input:type=button|value=Url test|onClick=\n\t\tvar url = document.getElementsByName('url')[0].value;\n\t\tif(url.indexOf('PushFeed')==-1){\n\t\t\talert('No valid PushFeed syntax, see example.');\n\t\t}else{\n\t\t\tvar urlTmp = url.substring( 0, url.indexOf( 'PushFeed' ) );\n\t\t\t//alert(urlTmp);\n\n\t\t\tvar pos1 = urlTmp.indexOf( 'index.php' );\n\t\t\t//alert( pos1 );\n\t\t\tvar pushUrl='';\n\t\t\tif( pos1 != -1 ){\n\t\t\t\tpushUrl = urlTmp.substring(0,pos1);\n\t\t\t\t//alert('if');\n\t\t\t} else {\n\t\t\t\tpushUrl = urlTmp;\n\t\t\t\t//alert('else');\n\t\t\t}\n\t\t\t//alert(pushUrl);\n\n\t\t\t//alert(pushUrl+'api.php?action=query&meta=patch&papatchId=1&format=xml');\n\t\t\tvar xhr_object = null;\n\n\t\t\tif( window.XMLHttpRequest ) { // Firefox\n\t\t\t\txhr_object = new XMLHttpRequest();\n\t\t\t}else if( window.ActiveXObject ) { // Internet Explorer\n\t\t\t\txhr_object = new ActiveXObject('Microsoft.XMLHTTP');\n\t\t\t} else {\n\t\t\t\talert('Votre navigateur ne supporte pas les objets XMLHTTPRequest...');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\ttry {\n\t\t\t\txhr_object.open('GET', '" . $urlAjax . "/extensions/DSMW/files/ajax.php?url='+escape(pushUrl+'api.php?action=query&meta=patch&papatchId=1&format=xml'), true);\n\t\t\t} catch( e ) {\n\t\t\t\t//alert('There is no DSMW Server responding at this URL');\n\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t}\n\t\t\txhr_object.onreadystatechange = function() {\n\n\t\t\tif( xhr_object.readyState == 4 ) {\n\t\t\t\tif( xhr_object.statusText=='OK' ){\n\t\t\t\t\tif( xhr_object.responseText == 'true' ){\n\t\t\t\t\t\t//alert('URL valid, there is a DSMW Server responding');\n\t\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'URL valid, there is a DSMW Server responding!';\n\t\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'green';\n\t\t\t\t\t} else{ //alert('There is no DSMW Server responding at this URL');\n\t\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t\t\t}\n\t\t\t\t} else{\n\t\t\t\t\t//alert('There is no DSMW Server responding at this URL');\n\t\t\t\t\tdocument.getElementById('dsmw').innerHTML = 'There is no DSMW Server responding at this URL!';\n\t\t\t\t\tdocument.getElementById('dsmw').style.color = 'red';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\txhr_object.send(null);\n\t}\n\t}}<br> {{#input:type=text|name=url|size=50}} <b>e.g. http://server/path/index.php?title=PushFeed:PushName</b><br>\n\tPullFeed Name: <br> {{#input:type=text|name=pullname}}<br>\n\t{{#input:type=submit|value=ADD}}\n\t}}"; $article->doEdit($newtext, $summary = ""); $wgOut->redirect($article->getTitle()->getFullURL()); return false; } elseif (isset($_GET['action']) && $_GET['action'] == 'addpushpage') { wfDebugLog('p2p', 'addPushPage'); $specialAsk = $urlServer . '?title=Special:Ask'; $newtext = "Add a new pushfeed:\n\n\t{{#form:action=" . $urlServer . "?action=pushpage|method=POST|\n\tPushFeed Name: <br> {{#input:class=test|name=name|type=text|onKeyUp=test('{$urlServer}');}}<div style=\"display:inline; \" id=\"state\" ></div><br />\n\tRequest: {{#input:type=button|value=Test your query|title=click here to test your query results|onClick=\n\tvar query = document.getElementsByName('keyword')[0].value;\n\tvar query1 = encodeURI(query);\n\twindow.open('" . $specialAsk . "&q='+query1+'&eq=yes&p%5Bformat%5D=broadtable','querywindow','menubar=no, status=no, scrollbars=yes, menubar=no, width=1000, height=900');}}\n\t <br>{{#input:type=textarea|cols=30 | style=width:auto |rows=2|name=keyword}} <b>e.g. [[Category:city]][[locatedIn::France]]</b><br>\n\t{{#input:type=submit|value=ADD}}\n\t}}"; $article->doEdit($newtext, $summary = ""); $wgOut->redirect($article->getTitle()->getFullURL()); return false; } elseif (isset($_GET['action']) && $_GET['action'] == 'pushpage') { // $url = $_POST['url'];//pas url mais changesetId wfDebugLog('p2p', 'Create new push ' . $_POST['name'] . ' with ' . $_POST['keyword']); $name = $_POST['name']; $request = $_POST['keyword']; $stringReq = utils::encodeRequest($request); // avoid "semantic injection" :)) // addPushSite($url, $name, $request); $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n[[name::PushFeed:" . $name . "| ]]\n'''Semantic query:''' [[hasSemanticQuery::" . $stringReq . "| ]]<nowiki>" . $request . "</nowiki>\n\n'''Pages concerned:'''\n{{#ask: " . $request . "}}\n[[deleted::false| ]]\n\n==Actions==\n\n{{#input:type=ajax|value=PUSH|onClick=pushpull('" . $urlServer . "','PushFeed:" . $name . "', 'onpush');}}\nThe \"PUSH\" action publishes the (unpublished) modifications of the articles listed above.\n\n== PUSH Progress : ==\n<div id=\"state\" ></div><br />\n"; wfDebugLog('p2p', ' -> push page contains : ' . $newtext); $title = Title::newFromText($_POST['name'], PUSHFEED); $article = new Article($title); $edit = $article->doEdit($newtext, $summary = ""); $wgOut->redirect($title->getFullURL()); return false; } elseif (isset($_POST['action']) && $_POST['action'] == 'onpush') { /* In case we push directly from an article page */ if (isset($_POST['page']) && isset($_POST['request'])) { $articlename = Title::newFromText($_POST['name']); if (!$articlename->exists()) { $result = utils::createPushFeed($_POST['name'], $_POST['request']); utils::writeAndFlush("Create push <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title=" . $_POST['name'] . ">" . $_POST['name'] . "</a>"); if ($result == false) { throw new MWException(__METHOD__ . ': no Pushfeed created in utils:: createPushFeed: ' . 'name: ' . $_POST['name'] . ' request' . $_POST['request']); } } } wfDebugLog('p2p', 'push on '); $patches = array(); $tmpPatches = array(); if (isset($_POST['name'])) { $name1 = $_POST['name']; if (!is_array($name1)) { $name1 = array($name1); } foreach ($name1 as $push) { wfDebugLog('p2p', ' - ' . $push); } } else { $name1 = ''; } if ($name1 == '') { utils::writeAndFlush('<p><b>No pushfeed selected!</b></p>'); $title = Title::newFromText('Special:ArticleAdminPage'); $wgOut->redirect($title->getFullURL()); return false; } // $name = $name1[0]; utils::writeAndFlush('<p><b>Start push </b></p>'); foreach ($name1 as $name) { utils::writeAndFlush("<span style=\"margin-left:30px;\">begin push: <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title={$name}>" . $name . "</a></span> <br/>"); $patches = array(); // / / for each pushfeed name==> push wfDebugLog('p2p', ' -> pushname ' . $name); // $name = $_GET['name'];//PushFeed name $request = getPushFeedRequest($name); // $previousCSID = getPreviousCSID($name); $previousCSID = getHasPushHead($name); if ($previousCSID == false) { $previousCSID = "none"; // $CSID = $name."_0"; } // else{ // $count = explode(" ", $previousCSID); // $cnt = $count[1] + 1; // $CSID = $name."_".$cnt; // } wfDebugLog('p2p', ' ->pushrequest ' . $request); wfDebugLog('p2p', ' ->pushHead : ' . $previousCSID); $CSID = utils::generateID(); // changesetID if ($request == false) { $outtext = '<p><b>No semantic request found!</b></p> <a href="' . $_SERVER['HTTP_REFERER'] . '">back</a>'; $wgOut->addHTML($outtext); return false; } $pages = getRequestedPages($request); // ce sont des pages et non des patches foreach ($pages as $page) { wfDebugLog('p2p', ' ->requested page ' . $page); $page = str_replace('"', '', $page); $request1 = '[[Patch:+]][[onPage::' . $page . ']]'; $tmpPatches = utils::orderPatchByPrevious($page); if (!is_array($tmpPatches)) { throw new MWException(__METHOD__ . ': $tmpPatches is not an array'); } $patches = array_merge($patches, $tmpPatches); wfDebugLog('p2p', ' -> ' . count($tmpPatches) . 'patchs were found for the page ' . $page); } wfDebugLog('p2p', ' -> ' . count($patches) . ' patchs were found for the pushfeed ' . $name); $published = getPublishedPatches($name); $unpublished = array_diff($patches, $published); /* unpublished = patches-published */ wfDebugLog('p2p', ' -> ' . count($published) . ' patchs were published for the pushfeed ' . $name . ' and ' . count($unpublished) . ' unpublished patchs'); if (empty($unpublished)) { wfDebugLog('p2p', ' -> no unpublished patch'); utils::writeAndFlush("<span style=\"margin-left:60px;\">no unpublished patch</span><br/>"); // return false; //If there is no unpublished patch } else { utils::writeAndFlush("<span style=\"margin-left:60px;\">" . count($unpublished) . " unpublished patch</span><br/>"); $pos = strrpos($CSID, ":"); // NS removing if ($pos === false) { // not found... $articleName = $CSID; $CSID = "ChangeSet:" . $articleName; } else { $articleName = substr($CSID, 0, $pos + 1); $CSID = "ChangeSet:" . $articleName; } $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n[[changeSetID::" . $CSID . "| ]]\n\n'''Date:''' " . date(DATE_RFC822) . "\n\n'''User:''' " . $wgUser->getName() . "\n\nThis ChangeSet is in : [[inPushFeed::" . $name . "]]<br>\n==Published patches==\n\n{| class=\"wikitable\" border=\"1\" style=\"text-align:left; width:30%;\"\n|-\n!bgcolor=#c0e8f0 scope=col | Patch\n|-\n"; // wfDebugLog('p2p',' -> count unpublished patch '.count($unpublished)); foreach ($unpublished as $patch) { wfDebugLog('p2p', ' -> unpublished patch ' . $patch); $newtext .= "|[[hasPatch::" . $patch . "]]\n\t|-\n\t"; } $newtext .= "\n\t|}"; $newtext .= "\n==Previous ChangeSet==\n[[previousChangeSet::" . $previousCSID . "]]\n"; $update = updatePushFeed($name, $CSID); if ($update == true) { // update the "hasPushHead" value successful $title = Title::newFromText($articleName, CHANGESET); $article = new Article($title); $article->doEdit($newtext, $summary = ""); } else { $outtext = '<p><b>PushFeed has not been updated!</b></p>'; $wgOut->addHTML($outtext); } } } // end foreach pushfeed list utils::writeAndFlush('<p><b>End push</b></p>'); $title = Title::newFromText('Special:ArticleAdminPage'); $wgOut->redirect($title->getFullURL()); return false; } elseif (isset($_GET['action']) && $_GET['action'] == 'pullpage') { // wfDebugLog('p2p','Create pull '.$_POST['pullname'].' with pushName '.$_POST['pushname'].' on '.$_POST['url']); // $url = rtrim($_POST['url'], "/"); //removes the final "/" if there is one $urlTmp = $_POST['url']; if (utils::isValidURL($urlTmp) == false) { // throws an exception if $url is invalid throw new MWException(__METHOD__ . ': ' . $urlTmp . ' seems not to be an url'); } $res = utils::parsePushURL($urlTmp); if ($res === false || empty($res)) { throw new MWException(__METHOD__ . ': URL format problem'); } $pushname = $res[0]; $url = $res[1]; // $pushname = $_POST['pushname']; $pullname = $_POST['pullname']; $newtext = "\n[[Special:ArticleAdminPage|DSMW Admin functions]]\n\n==Features==\n\n[[name::PullFeed:" . $pullname . "| ]]\n'''URL of the DSMW PushServer:''' [[pushFeedServer::" . $url . "]]<br>\n'''PushFeed name:''' [[pushFeedName::PushFeed:" . $pushname . "]]\n[[deleted::false| ]]\n\n==Actions==\n\n{{#input:type=ajax|value=PULL|onClick=pushpull('" . $urlServer . "','PullFeed:" . $pullname . "','onpull');}}\n\nThe \"PULL\" action gets the modifications published in the PushFeed of the PushFeedServer above.\n\n== PULL Progress : ==\n<div id=\"state\" ></div><br />\n"; $title = Title::newFromText($pullname, PULLFEED); $article = new Article($title); $article->doEdit($newtext, $summary = ""); $wgOut->redirect($title->getFullURL()); return false; } elseif (isset($_POST['action']) && $_POST['action'] == 'onpull') { if (isset($_POST['name'])) { $name1 = $_POST['name']; wfDebugLog('p2p', 'pull on '); if (!is_array($name1)) { $name1 = array($name1); } } else { $name1 = ''; } if ($name1 == '') { utils::writeAndFlush('<p><b>No pullfeed selected!</b></p> '); $title = Title::newFromText('Special:ArticleAdminPage'); $article = new Article($title); $article->doEdit('', $summary = ""); $wgOut->redirect($title->getFullURL()); return false; } // $name = $name1[0];//with NS utils::writeAndFlush('<p><b>Start pull</b></p>'); foreach ($name1 as $name) { // for each pullfeed name==> pull utils::writeAndFlush("<span style=\"margin-left:30px;\">begin pull: <A HREF=" . 'http://' . $wgServerName . $wgScriptPath . "/index.php?title={$name}>" . $name . "</a></span> <br/>"); wfDebugLog('p2p', ' -> pull : ' . $name); // $previousCSID = getPreviousPulledCSID($name); // if($previousCSID==false) { // $previousCSID = "none"; // } $previousCSID = getHasPullHead($name); if ($previousCSID == false) { $previousCSID = "none"; } wfDebugLog('p2p', ' -> pullHead : ' . $previousCSID); $relatedPushServer = getPushURL($name); if (is_null($relatedPushServer)) { throw new MWException(__METHOD__ . ': no relatedPushServer url'); } $namePush = getPushName($name); $namePush = str_replace(' ', '_', $namePush); wfDebugLog('p2p', ' -> pushServer : ' . $relatedPushServer); wfDebugLog('p2p', ' -> pushName : ' . $namePush); if (is_null($namePush)) { throw new MWException(__METHOD__ . ': no PushName'); } // split NS and name preg_match("/^(.+?)_*:_*(.*)\$/S", $namePush, $m); $nameWithoutNS = $m[2]; // $url = $relatedPushServer.'/api.php?action=query&meta=changeSet&cspushName='.$nameWithoutNS.'&cschangeSet='.$previousCSID.'&format=xml'; // $url = $relatedPushServer."/api{$wgScriptExtension}?action=query&meta=changeSet&cspushName=".$nameWithoutNS.'&cschangeSet='.$previousCSID.'&format=xml'; wfDebugLog('testlog', ' -> request ChangeSet : ' . $relatedPushServer . '/api.php?action=query&meta=changeSet&cspushName=' . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); /* test if it is a xml file. If not, the server is not reachable via the url * Then we try to reach it with the .php5 extension */ if (strpos($cs, "<?xml version=\"1.0\"?>") === false) { $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php5?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); } if (strpos($cs, "<?xml version=\"1.0\"?>") === false) { $cs = false; } if ($cs === false) { throw new MWException(__METHOD__ . ': Cannot connect to Push Server (ChangeSet API)'); } $cs = trim($cs); $dom = new DOMDocument(); $dom->loadXML($cs); $changeSet = $dom->getElementsByTagName('changeSet'); $CSID = null; foreach ($changeSet as $cs) { if ($cs->hasAttribute("id")) { $CSID = $cs->getAttribute('id'); $csName = $CSID; } } wfDebugLog('p2p', ' -> changeSet found ' . $CSID); while ($CSID != null) { // if(!utils::pageExist($CSID)) { $listPatch = null; $patchs = $dom->getElementsByTagName('patch'); foreach ($patchs as $p) { wfDebugLog('p2p', ' -> patch ' . $p->firstChild->nodeValue); $listPatch[] = $p->firstChild->nodeValue; } // $CSID = substr($CSID,strlen('changeSet:')); utils::createChangeSetPull($CSID, $name, $previousCSID, $listPatch); integrate($CSID, $listPatch, $relatedPushServer, $csName); updatePullFeed($name, $CSID); // } $previousCSID = $CSID; wfDebugLog('p2p', ' -> request ChangeSet : ' . $relatedPushServer . '/api.php?action=query&meta=changeSet&cspushName=' . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); /* test if it is a xml file. If not, the server is not reachable via the url * Then we try to reach it with the .php5 extension */ if (strpos($cs, "<?xml version=\"1.0\"?>") === false) { $cs = utils::file_get_contents_curl(utils::lcfirst($relatedPushServer) . "/api.php5?action=query&meta=changeSet&cspushName=" . $nameWithoutNS . '&cschangeSet=' . $previousCSID . '&format=xml'); } if (strpos($cs, "<?xml version=\"1.0\"?>") === false) { $cs = false; } if ($cs === false) { throw new MWException(__METHOD__ . ': Cannot connect to Push Server (ChangeSet API)'); } $cs = trim($cs); $dom = new DOMDocument(); $dom->loadXML($cs); $changeSet = $dom->getElementsByTagName('changeSet'); $CSID = null; foreach ($changeSet as $cs) { if ($cs->hasAttribute("id")) { $CSID = $cs->getAttribute('id'); } } wfDebugLog('p2p', ' -> changeSet found ' . $CSID); } if (is_null($csName)) { wfDebugLog('p2p', ' - redirect to Special:ArticleAdminPage'); utils::writeAndFlush("<span style=\"margin-left:60px;\">no new patch</span><br/>"); } else { wfDebugLog('p2p', ' - redirect to ChangeSet:' . $csName); } } // end foreach list pullfeed utils::writeAndFlush('<p><b>End pull</b></p>'); $title = Title::newFromText('Special:ArticleAdminPage'); $wgOut->redirect($title->getFullURL()); return false; } else { return true; } }
function downloadFile($url) { global $wgServerName, $wgServer, $wgContLang, $wgAuth, $wgScriptPath, $wgScriptExtension, $wgMemc, $wgRequest; $apiUrl = $wgServer . $wgScriptPath . "/api" . $wgScriptExtension; $edittoken = $apiUrl . "?action=query&prop=info&intoken=edit&titles=Foo&format=xml"; $edittoken = utils::file_get_contents_curl($edittoken); $dom = new DOMDocument(); $dom->loadXML($edittoken); $edittoken = $dom->getElementsByTagName('page'); foreach ($edittoken as $p) { if ($p->hasAttribute("edittoken")) { $token = $p->getAttribute('edittoken'); } } $token = str_replace("+", "%2B", $token); // $url = $patch->getUrl(); $onPage = preg_split("/^.*\\//", $url); $onPage = $onPage[1]; $onPage = str_replace(array(' '), array('_'), $onPage); $url = str_replace(array(':', 'Http', ' '), array('%3A', 'http', '_'), $url); $download = $apiUrl . "?action=upload&filename=" . $onPage . "&url=" . $url . "&token=" . $token . "&ignorewarnings=1"; $resp = Http::post($download); libxml_use_internal_errors(true); $sxe = simplexml_load_string($resp); }