require_once("common.php");
require_once("loggedinuser.php");
class ContentHandler {
public static $CONTENT_POSTED = 1;
public static $CONTENT_QUEUED = 2;
public static $QUEUE_ENTRY_NEW = 0;
public static $QUEUE_ENTRY_EDIT = 1;
public static $CONTENT_NO_CHANGE = 3;
public static $CONTENT_FAILURE = 4;
public static $CONTENT_SUCCESS = 5;
public static function submitNew($loggedInUser, $ip, $title, $lid, $content){
global $ACL_ACCESS_NOBODY;
global $ACL_ACCESS_NOBODY_VERIFIED;
global $ACL_ACCESS_ADMIN_LOW;
global $ACL_ACCESS_ADMIN_HIGH;
global $CMS_CONTENT_PATH;
$retVal = -1;
$accessLevel = $ACL_ACCESS_NOBODY;
if (isset($loggedInUser) && ($loggedInUser != null)) {
$accessLevel = $loggedInUser->getAccessLevel($lid);
}
if ($accessLevel == $ACL_ACCESS_ADMIN_HIGH) {
if (ContentHandler::writeNewFile($loggedInUser,$lid,$title,$content) &&
ContentHandler::addHistory(Language::lookupName($lid) . "/" . $title,
$loggedInUser->getUID(), $lid,
$content,ContentHandler::$QUEUE_ENTRY_NEW,
$loggedInUser)) {
$retVal = ContentHandler::$CONTENT_POSTED;
} else
$retVal = ContentHandler::$CONTENT_FAILURE;
} else {
if (ContentHandler::addQueue($lid, $title, $content,
ContentHandler::$QUEUE_ENTRY_NEW,
$loggedInUser, $ip))
$retVal = ContentHandler::$CONTENT_QUEUED;
else
$retVal = ContentHandler::$CONTENT_FAILURE;
}
return $retVal;
}
public static function submitEdit($loggedInUser, $ip, $file, $content) {
require_once("languages.php");
global $ACL_ACCESS_NOBODY;
global $ACL_ACCESS_NOBODY_VERIFIED;
global $ACL_ACCESS_ADMIN_LOW;
global $ACL_ACCESS_ADMIN_HIGH;
$retVal = -1;
if (substr($content, strlen($content) - 1, 1) != "\n")
$content .= "\n";
$diff = ContentHandler::makeDiff($file, $content);
if ($diff == null)
return ContentHandler::$CONTENT_NO_CHANGE;
$langName = substr($file, 0, strpos($file, "/"));
$lid = Language::lookupLID($langName);
$accessLevel = $ACL_ACCESS_NOBODY;
if (isset($loggedInUser) && ($loggedInUser != null)) {
$accessLevel = $loggedInUser->getAccessLevel($lid);
}
echo "Access level: $accessLevel
langid: $lid
";
if (($accessLevel == $ACL_ACCESS_ADMIN_LOW) ||
($accessLevel == $ACL_ACCESS_ADMIN_HIGH)) {
if (ContentHandler::applyDiff($file, $diff)) {
if (ContentHandler::addHistory($file, $loggedInUser->getUID(), $lid,
$diff,
ContentHandler::$QUEUE_ENTRY_EDIT,
$loggedInUser)) {
$retVal = ContentHandler::$CONTENT_POSTED;
} else {
$retVal = ContentHandler::$CONTENT_FAILURE;
}
} else
$retVal = ContentHandler::$CONTENT_FAILURE;
} else {
if (ContentHandler::addQueue($lid, $file, $diff,
ContentHandler::$QUEUE_ENTRY_EDIT,
$loggedInUser, $ip))
$retVal = ContentHandler::$CONTENT_QUEUED;
else
$retVal = ContentHandler::$CONTENT_FAILURE;
}
return $retVal;
}
public static function approveQueueEntry($pid, $loggedInUser){
global $CMS_CONTENT_PATH;
settype($pid, "integer");
$retVal = ContentHandler::$CONTENT_FAILURE;
$db = getDBConnection();
$result = mysql_query("SELECT UID,LID,path,type,data FROM PendingQueue WHERE PID=" . $pid, $db);
if (!$result)
die("Error while approving queue entry!");
$row = mysql_fetch_row($result);
$uid = $row[ 0 ];
$lid = $row[ 1 ];
$path = $row[ 2 ];
$type = $row[ 3 ];
$data = addslashes($row[ 4 ]);
settype($uid, "integer");
settype($lid, "integer");
settype($type, "integer");
$accessLevel = $loggedInUser->getAccessLevel($lid);
if ($type == 0) {
if ($accessLevel != ACLs::$ACL_ACCESS_ADMIN_HIGH)
die("Error: You have insufficient privileges to approve new submissions!");
if (ContentHandler::writeNewFile($loggedInUser, $lid, $path, $data) &&
ContentHandler::addHistory($path,$uid,$lid,$data,$type,$loggedInUser) &&
ContentHandler::delQueue($pid)) {
$retVal = ContentHandler::$CONTENT_POSTED;
} else
$retVal = ContentHandler::$CONTENT_FAILURE;
} else if ($type == 1) {
if ($accessLevel < ACLs::$ACL_ACCESS_ADMIN_LOW)
die("Error: You have insufficient privileges to approve new submissions!");
$db = getDBConnection();
$result = mysql_query("SELECT path,data FROM PendingQueue WHERE PID=" . $pid, $db);
if (!$result)
die("Error while retrieving from pending queue!: " . $pid);
$row = mysql_fetch_row($result);
$path = $row[ 0 ];
$diff = $row[ 1 ];
mysql_close($db);
if (ContentHandler::applyDiff($path, $diff) &&
ContentHandler::addHistory($path, $loggedInUser->getUID(), $lid,
$diff,
ContentHandler::$QUEUE_ENTRY_EDIT,
$loggedInUser) &&
ContentHandler::delQueue($pid)) {
$retVal = ContentHandler::$CONTENT_POSTED;
} else
$retVal = ContentHandler::$CONTENT_FAILURE;
} else
die("Internal error!");
return $retVal;
}
public static function rejectQueueEntry($pid) {
if (ContentHandler::delQueue($pid))
return ContentHandler::$CONTENT_SUCCESS;
else
return ContentHandler::$CONTENT_FAILURE;
}
private static function getUnusedPID($db) {
$needToClose = false;
if ($db == null) {
$db = getDBConnection();
$needToClose = true;
}
$result = mysql_query("SELECT MAX(PID) FROM PendingQueue", $db);
if (!$result) {
die('Error getting unused PID: ' . mysql_error());
}
$retVal = mysql_result($result, 0);
settype($retVal, "integer");
$retVal++;
mysql_free_result($result);
if ($needToClose)
mysql_close($db);
return $retVal;
}
private static function getUnusedHID($db) {
$needToClose = false;
if ($db == null) {
$db = getDBConnection();
$needToClose = true;
}
$result = mysql_query("SELECT MAX(HID) FROM History", $db);
if (!$result) {
die('Error getting unused HID: ' . mysql_error());
}
$retVal = mysql_result($result, 0);
settype($retVal, "integer");
$retVal++;
mysql_free_result($result);
if ($needToClose)
mysql_close($db);
return $retVal;
}
private static function writeNewFile($loggedInUser, $lid, $title, $data) {
global $CMS_CONTENT_FS_PATH;
global $FILE_MODE;
global $CONTENT_HEADER;
global $CONTENT_FOOTER;
$title = normalizeString($title);
$langName = normalizeString(Language::lookupName($lid));
$relativePath = $langName . '/' . $title . '.html';
$filename = $CMS_CONTENT_FS_PATH . $relativePath;
if (!($hFile = fopen($filename, "w+")))
die("Error while creating new file " . $filename);
$footer = str_replace("%EDIT_URL%", $relativePath, $CONTENT_FOOTER);
if (fwrite($hFile, $CONTENT_HEADER . $data . "\n" . $footer) === FALSE)
die("Error while writing to file " . $filename);
fclose($hFile);
$oldumask = umask(0000);
if (!chmod($filename, $FILE_MODE))
die("Error while chmod'ing file " . $filename);
umask($oldumask);
return true;
}
private static function makeDiff($originalFileName, $newContent) {
global $CMS_CONTENT_FS_PATH;
global $DIFF_PATH;
$retVal = null;
$tempFileOld = ContentHandler::extractContent($originalFileName);
$tempFileNew = ContentHandler::tempFile($newContent);
$command = $DIFF_PATH . ' -u ' . $tempFileOld. ' ' . $tempFileNew;
$diff = array();
$diffRetVal = null;
echo "Executing: " . $command . "
";
exec($command, $diff, $diffRetVal);
if ($diffRetVal == 1) {
$retVal = '';
for($i = 0; $i < count($diff); $i++) {
$retVal .= ($diff[ $i ] . "\n");
}
}
if (unlink($tempFileOld) === false)
die("Error while deleting temporary file: " . $tempFileOld);
if (unlink($tempFileNew) === false)
die("Error while deleting temporary file: " . $tempFileNew);
echo 'Diff:
' . $retVal . '
';
return $retVal;
}
private static function tempFile($data) {
global $TEMP_DIR;
$oldumask = umask(0077);
$randString = mt_rand();
settype($randString, "string");
$filename = $TEMP_DIR . "litcms" . $randString;
if (!($hFile = fopen($filename, "w+")))
die("Error while creating temporary file!");
fwrite($hFile, $data);
fclose($hFile);
umask($oldumask);
return $filename;
}
private static function applyDiff($originalFileName, $diff) {
global $PATCH_PATH;
global $CMS_CONTENT_FS_PATH;
global $CONTENT_HEADER;
global $CONTENT_FOOTER;
// TODO: make backup of file before overwriting!
$contentTempFile = ContentHandler::extractContent($originalFileName);
$diffTempFile = ContentHandler::tempFile($diff);
$command = $PATCH_PATH . ' -p0 ' .
$contentTempFile . ' < ' . $diffTempFile;
$patchResult = array();
$patchRetVal = -1;
exec($command, $patchResult, $patchRetVal);
if (unlink($diffTempFile) === false)
my_log("Error while deleting temporary file: " . $diffTempFile);
if ($patchRetVal == 0) {
$hFile = null;
if (!($hFile = fopen($contentTempFile, "r")))
die("Error while reading temporary content file: " . $contentTempFile);
$newContent = fread($hFile, filesize($contentTempFile));
fclose($hFile);
if (unlink($contentTempFile) === false)
my_log("Error while deleting temporary file: " . $contentTempFile);
if (!($hFile = fopen($CMS_CONTENT_FS_PATH . $originalFileName, "w+"))) {
my_log("Error while applying the following diff file to $originalFileName:\n\n$diff\n\n");
} else {
$newContent = $CONTENT_HEADER . $newContent .
str_replace("%EDIT_URL%", $originalFileName, $CONTENT_FOOTER);
fwrite($hFile, $newContent);
fclose($hFile);
$retVal = true;
}
} else {
my_log("Error while applying the following diff file to $originalFileName:\n\n$diff\n\n");
if (unlink($contentTempFile) === false)
my_log("Error while deleting temporary file: " . $contentTempFile);
$retVal = false;
}
return $retVal;
}
private static function extractContent($file) {
global $CMS_CONTENT_FS_PATH;
$hFile = fopen($CMS_CONTENT_FS_PATH . $file, "r");
$content = fread($hFile, filesize($CMS_CONTENT_FS_PATH . $file));
fclose($hFile);
$beginPos = strpos($content, "");
$endPos = strpos($content, "");
if (($beginPos === false) || ($endPos === false)) {
die("Cannot read file " . $file);
} else
$beginPos += 19;
$contentLen = $endPos - $beginPos;
$content = substr($content, $beginPos, $contentLen);
$tempFileName = ContentHandler::tempFile($content);
return $tempFileName;
}
private static function addHistory($path, $uid, $lid, $data, $type,
$loggedInUser) {
$retVal = false;
$db = getDBConnection();
$unusedHID = ContentHandler::getUnusedHID($db);
$approvedbyUID = $loggedInUser->getUID();
$query = "INSERT INTO History VALUES($unusedHID,'$path',NOW(),$uid,$lid,'$data',$type,$approvedbyUID)";
$result = mysql_query($query, $db);
if ($result)
$retVal = true;
else
my_log("Error while executing: " . $query);
mysql_close($db);
return $retVal;
}
private static function addQueue($lid, $title, $content, $type,
$loggedInUser, $ip) {
$retVal = false;
$db = getDBConnection();
$uid = -1;
if ($loggedInUser != null)
$uid = $loggedInUser->getUID();
$path = Language::lookupName($lid) . '/' . $title . '.html';
$query = "INSERT INTO PendingQueue VALUES(" . ContentHandler::getUnusedPID($db) . "," . $uid . "," . $lid . ",NOW(),'" . $ip . "','" . $path . "',$type,'" . $content . "')";
$result = mysql_query($query, $db);
if ($result)
$retVal = true;
else
my_log("Error while executing: " . $query);
mysql_close($db);
return $retVal;
}
private static function delQueue($pid) {
settype($pid, "integer");
$retVal = false;
$db = getDBConnection();
$result = mysql_query("DELETE FROM PendingQueue WHERE PID=" . $pid, $db);
if (!$result || (mysql_affected_rows($db) != 1)) {
$retVal = false;
my_log("Error while deleting from pending queue!: " . $pid);
} else
$retVal = true;
mysql_close($db);
return $retVal;
}
}
?>