"; echo ""; $fp = fopen("diagrams/graphmodel.xml", "r"); fpassthru($fp); fclose($fp); echo ""; echo ""; if (is_file($delta)) { $fp = fopen($delta, "r+"); fpassthru($fp); fclose($fp); } echo ""; echo ""; // Deletes existing buffer if (is_file($filename)) { unlink($filename); } touch($filename); chmod($filename, 0777); } else { // Gets the XML parameter from the POST request and converts all linefeeds // into a HTML entity. This is required for correct handling of the XML on // the client side. if (isset($_POST["xml"])) { $xml = str_replace("\n", " ", stripslashes($_POST["xml"])); // TODO: Take only the edits from the XML $edits = ""; $doc = mxUtils::parseXml($xml); $child = $doc->documentElement; if ($child->nodeName == "message") { $child = $child->firstChild; while ($child != null) { if ($child->nodeName == "delta") { $edit = $child->firstChild; while ($edit != null) { if ($edit->nodeName == "edit") { $edits .= $doc->saveXML($edit); } $edit = $edit->nextSibling; } } $child = $child->nextSibling; } } // Appends the change to all connected sessions except the incoming // session and the global delta file if (strlen($edits) > 0) { mxLog::debug("received changes from ".session_id(). ": ".strlen($edits)." bytes"); // Makes sure the global delta file exists so that the change is // appended below if (!is_file($delta)) { touch($delta); chmod($delta, 0777); } // Clears out the delta file if this change contains a mxRootChange // in which case the previous changes will no longer be visible and // just waste bandwidth. if (strpos($edits, "mxRootChange") > 0) { $fp = fopen($delta, "r+"); fpassthru($fp); ftruncate($fp, 0); fflush($fp); fclose($fp); } // Dispatches the XML to all sessions except the incoming session // TODO: Remove dead sessions $fp = opendir($document); while($filename = readdir($fp)) { if ($filename!= "." && $filename != ".." && !is_dir("$document/$filename") && $filename != session_id()) { mxLog::debug("dispatch changes to $filename"); $tmp = fopen("$document/$filename", "a"); fwrite($tmp, $edits); fflush($tmp); fclose($tmp); } } flush(); } } else { // Makes sure to cancel existing pending requests before they consume the // change data after a refresh, where the request must be served instead. $requestid = md5(uniqid(rand(), true)); $_SESSION['requestid'] = $requestid; session_commit(); mxLog::debug("request $requestid enters"); if (!is_file($filename)) { touch($filename); chmod($filename, 0777); } else { // Keeps the request for 10 secs and asks for changes each second $timeout = 10; $count = 0; while (is_file($filename) && filesize($filename) == 0 && $count < $timeout && $_SESSION['requestid'] == $requestid) { sleep(1); clearstatcache(); $count++; // Sync the session state session_start(); session_commit(); } // Sync the session state session_start(); session_commit(); if ($_SESSION['requestid'] != $requestid) { mxLog::debug("request $requestid has died"); } else if (filesize($filename) > 0) { mxLog::debug("request $requestid leaves: ".filesize($filename)." bytes"); header("Pragma: public"); header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Content-Type: application/xhtml+xml"); // Sends the changes to the client echo ""; echo ""; $fp = fopen($filename, "r+"); fpassthru($fp); ftruncate($fp, 0); fflush($fp); fclose($fp); echo ""; echo ""; } else { touch($filename); } } } } mxLog::leave(); mxLog::close(); ?>