diff --git a/LZCompressor/LZContext.php b/LZCompressor/LZContext.php new file mode 100644 index 0000000..0e41a3e --- /dev/null +++ b/LZCompressor/LZContext.php @@ -0,0 +1,91 @@ +data = new LZData; + } + + // Helper + + /** + * @param string $val + * @return bool + */ + public function dictionaryContains($val) { + return array_key_exists($val, $this->dictionary); + } + + /** + * @param $val + */ + public function addToDictionary($val) { + $this->dictionary[$val] = $this->dictSize++; + } + + /** + * @param string $val + * @return bool + */ + public function dictionaryToCreateContains($val) { + return array_key_exists($val, $this->dictionaryToCreate); + } + + /** + * decrements enlargeIn and extends numbits in case enlargeIn drops to 0 + */ + public function enlargeIn() { + $this->enlargeIn--; + if($this->enlargeIn==0) { + $this->enlargeIn = pow(2, $this->numBits); + $this->numBits++; + } + } +} diff --git a/LZCompressor/LZData.php b/LZCompressor/LZData.php new file mode 100644 index 0000000..b536ce1 --- /dev/null +++ b/LZCompressor/LZData.php @@ -0,0 +1,29 @@ +str .= $str; + } +} diff --git a/LZCompressor/LZReverseDictionary.php b/LZCompressor/LZReverseDictionary.php new file mode 100644 index 0000000..264caa4 --- /dev/null +++ b/LZCompressor/LZReverseDictionary.php @@ -0,0 +1,33 @@ +entries); + } + + public function hasEntry($index) { + return array_key_exists($index, $this->entries); + } + + public function getEntry($index) { + return $this->entries[$index]; + } + + public function addEntry($char) { + $this->entries[] = $char; + } + +} \ No newline at end of file diff --git a/LZCompressor/LZString.php b/LZCompressor/LZString.php new file mode 100644 index 0000000..75791fa --- /dev/null +++ b/LZCompressor/LZString.php @@ -0,0 +1,286 @@ +c = LZUtil::utf8_charAt($uncompressed, $ii); + if(!$context->dictionaryContains($context->c)) { + $context->addToDictionary($context->c); + $context->dictionaryToCreate[$context->c] = true; + } + $context->wc = $context->w . $context->c; + if($context->dictionaryContains($context->wc)) { + $context->w = $context->wc; + } else { + self::produceW($context, $bitsPerChar, $getCharFromInt); + } + } + if($context->w !== '') { + self::produceW($context, $bitsPerChar, $getCharFromInt); + } + + $value = 2; + for($i=0; $i<$context->numBits; $i++) { + self::writeBit($value&1, $context->data, $bitsPerChar, $getCharFromInt); + $value = $value >> 1; + } + + while (true) { + $context->data->val = $context->data->val << 1; + if ($context->data->position == ($bitsPerChar-1)) { + $context->data->append($getCharFromInt($context->data->val)); + break; + } + $context->data->position++; + } + + return $context->data->str; + } + + /** + * @param LZContext $context + * @param integer $bitsPerChar + * @param callable $getCharFromInt + * + * @return LZContext + */ + private static function produceW(LZContext $context, $bitsPerChar, $getCharFromInt) + { + if($context->dictionaryToCreateContains($context->w)) { + if(LZUtil::charCodeAt($context->w)<256) { + for ($i=0; $i<$context->numBits; $i++) { + self::writeBit(null, $context->data, $bitsPerChar, $getCharFromInt); + } + $value = LZUtil::charCodeAt($context->w); + for ($i=0; $i<8; $i++) { + self::writeBit($value&1, $context->data, $bitsPerChar, $getCharFromInt); + $value = $value >> 1; + } + } else { + $value = 1; + for ($i=0; $i<$context->numBits; $i++) { + self::writeBit($value, $context->data, $bitsPerChar, $getCharFromInt); + $value = 0; + } + $value = LZUtil::charCodeAt($context->w); + for ($i=0; $i<16; $i++) { + self::writeBit($value&1, $context->data, $bitsPerChar, $getCharFromInt); + $value = $value >> 1; + } + } + $context->enlargeIn(); + unset($context->dictionaryToCreate[$context->w]); + } else { + $value = $context->dictionary[$context->w]; + for ($i=0; $i<$context->numBits; $i++) { + self::writeBit($value&1, $context->data, $bitsPerChar, $getCharFromInt); + $value = $value >> 1; + } + } + $context->enlargeIn(); + $context->addToDictionary($context->wc); + $context->w = $context->c.''; + } + + /** + * @param string $value + * @param LZData $data + * @param integer $bitsPerChar + * @param callable $getCharFromInt + */ + private static function writeBit($value, LZData $data, $bitsPerChar, $getCharFromInt) + { + if(null !== $value) { + $data->val = ($data->val << 1) | $value; + } else { + $data->val = ($data->val << 1); + } + if ($data->position == ($bitsPerChar-1)) { + $data->position = 0; + $data->append($getCharFromInt($data->val)); + $data->val = 0; + } else { + $data->position++; + } + } + + /** + * @param LZData $data + * @param integer $resetValue + * @param callable $getNextValue + * @param integer $exponent + * @param string $feed + * @return integer + */ + private static function readBits(LZData $data, $resetValue, $getNextValue, $feed, $exponent) + { + $bits = 0; + $maxPower = pow(2, $exponent); + $power=1; + while($power != $maxPower) { + $resb = $data->val & $data->position; + $data->position >>= 1; + if ($data->position == 0) { + $data->position = $resetValue; + $data->val = $getNextValue($feed, $data->index++); + } + $bits |= (($resb>0 ? 1 : 0) * $power); + $power <<= 1; + } + return $bits; + } + + /** + * @param string $compressed + * @param integer $resetValue + * @param callable $getNextValue + * @return string + */ + private static function _decompress($compressed, $resetValue, $getNextValue) + { + if(!is_string($compressed) || strlen($compressed) === 0) { + return ''; + } + + $length = LZUtil::utf8_strlen($compressed); + $entry = null; + $enlargeIn = 4; + $numBits = 3; + $result = ''; + + $dictionary = new LZReverseDictionary(); + + $data = new LZData(); + $data->str = $compressed; + $data->val = $getNextValue($compressed, 0); + $data->position = $resetValue; + $data->index = 1; + + $next = self::readBits($data, $resetValue, $getNextValue, $compressed, 2); + + if($next < 0 || $next > 1) { + return ''; + } + + $exponent = ($next == 0) ? 8 : 16; + $bits = self::readBits($data, $resetValue, $getNextValue, $compressed, $exponent); + + $c = LZUtil::fromCharCode($bits); + $dictionary->addEntry($c); + $w = $c; + + $result .= $c; + + while(true) { + if($data->index > $length) { + return ''; + } + $bits = self::readBits($data, $resetValue, $getNextValue, $compressed, $numBits); + + $c = $bits; + + switch($c) { + case 0: + $bits = self::readBits($data, $resetValue, $getNextValue, $compressed, 8); + $c = $dictionary->size(); + $dictionary->addEntry(LZUtil::fromCharCode($bits)); + $enlargeIn--; + break; + case 1: + $bits = self::readBits($data, $resetValue, $getNextValue, $compressed, 16); + $c = $dictionary->size(); + $dictionary->addEntry(LZUtil::fromCharCode($bits)); + $enlargeIn--; + break; + case 2: + return $result; + break; + } + + if($enlargeIn == 0) { + $enlargeIn = pow(2, $numBits); + $numBits++; + } + + if($dictionary->hasEntry($c)) { + $entry = $dictionary->getEntry($c); + } + else { + if ($c == $dictionary->size()) { + $entry = $w . $w{0}; + } else { + return null; + } + } + + $result .= $entry; + $dictionary->addEntry($w . $entry{0}); + $w = $entry; + + $enlargeIn--; + if($enlargeIn == 0) { + $enlargeIn = pow(2, $numBits); + $numBits++; + } + } + } +} diff --git a/LZCompressor/LZUtil.php b/LZCompressor/LZUtil.php new file mode 100644 index 0000000..4b27a1e --- /dev/null +++ b/LZCompressor/LZUtil.php @@ -0,0 +1,112 @@ + 1) return ($h & 0x1F) << 6 | (ord($ch{1}) & 0x3F); + if ($h <= 0xEF && $len > 2) return ($h & 0x0F) << 12 | (ord($ch{1}) & 0x3F) << 6 | (ord($ch{2}) & 0x3F); + if ($h <= 0xF4 && $len > 3) + return ($h & 0x0F) << 18 | (ord($ch{1}) & 0x3F) << 12 | (ord($ch{2}) & 0x3F) << 6 | (ord($ch{3}) & 0x3F); + return -2; + } + + /** + * @param string $str + * @param integer $num + * + * @return string + */ + public static function utf8_charAt($str, $num) + { + return mb_substr($str, $num, 1, 'UTF-8'); + } + + /** + * @param string $str + * @return integer + */ + public static function utf8_strlen($str) { + return mb_strlen($str, 'UTF-8'); + } + + +} \ No newline at end of file diff --git a/editor.php b/editor.php index 2b3f680..4e13ff2 100644 --- a/editor.php +++ b/editor.php @@ -5,7 +5,7 @@ $t = $text['editor']; ?> - + ICEcoder v <?php echo $ICEcoder["versionNo"];?> editor @@ -287,6 +287,14 @@ function createNewCMInstance(num) { window['cM'+num] .on("inputRead", function(thisCM) {top.ICEcoder.cMonInputRead(thisCM,'cM'+num)}); window['cM'+num+'diff'] .on("inputRead", function(thisCM) {top.ICEcoder.cMonInputRead(thisCM,'cM'+num+'diff')}); + // Gutter Click + window['cM'+num] .on("gutterClick", function(thisCM,line,gutter,evt) {top.ICEcoder.cMonGutterClick(thisCM,line,gutter,evt,'cM'+num)}); + window['cM'+num+'diff'] .on("gutterClick", function(thisCM,line,gutter,evt) {top.ICEcoder.cMonGutterClick(thisCM,line,gutter,evt,'cM'+num+'diff')}); + + // Mouse Down + window['cM'+num] .on("mousedown", function(thisCM) {top.ICEcoder.cMonMouseDown(thisCM,'cM'+num)}); + window['cM'+num+'diff'] .on("mousedown", function(thisCM) {top.ICEcoder.cMonMouseDown(thisCM,'cM'+num+'diff')}); + // Render line window['cM'+num] .on("renderLine", function(thisCM, line, element) {top.ICEcoder.cMonRenderLine(thisCM,'cM'+num,line,element)}); window['cM'+num+'diff'] .on("renderLine", function(thisCM, line, element) {top.ICEcoder.cMonRenderLine(thisCM,'cM'+num+'diff',line,element)}); diff --git a/files.php b/files.php index a6e1ef9..8b88150 100644 --- a/files.php +++ b/files.php @@ -8,7 +8,7 @@ $isGitHubRepoDir = in_array($ICEcoder["root"],$ICEcoder['githubLocalPaths']); ?> - + ICEcoder v <?php echo $ICEcoder["versionNo"];?> file manager diff --git a/index.php b/index.php index 516dcf6..1e0f052 100644 --- a/index.php +++ b/index.php @@ -37,7 +37,7 @@ if ($ICEcoder["checkUpdates"]) { $isMac = strpos($_SERVER['HTTP_USER_AGENT'], "Macintosh")>-1 ? true : false; ?> - + ICEcoder v <?php echo $ICEcoder["versionNo"];?> @@ -80,6 +80,7 @@ $t = $text['index']; + @@ -252,7 +253,7 @@ $t = $text['index']; - +
diff --git a/lib/file-control-xhr.php b/lib/file-control-xhr.php index f6d4daa..a5e2383 100644 --- a/lib/file-control-xhr.php +++ b/lib/file-control-xhr.php @@ -4,6 +4,14 @@ include("settings.php"); include("ftp-control.php"); $t = $text['file-control']; +// Load the LZ String PHP libs and define using LZString +include(dirname(__FILE__)."/../LZCompressor/LZContext.php"); +include(dirname(__FILE__)."/../LZCompressor/LZData.php"); +include(dirname(__FILE__)."/../LZCompressor/LZReverseDictionary.php"); +include(dirname(__FILE__)."/../LZCompressor/LZString.php"); +include(dirname(__FILE__)."/../LZCompressor/LZUtil.php"); +use LZCompressor\LZString as LZString; + // =============================== // SET OUR ERROR INFO TO A DEFAULT // =============================== @@ -21,11 +29,11 @@ $saveType = isset($_GET['saveType']) ? strClean($_GET['saveType']) : ""; // Establish the filename/new filename if (isset($_POST['newFileName']) && $_POST['newFileName']!="") { - $file = $_POST['newFileName']; // New file + $file = strClean($_POST['newFileName']); // New file } elseif (isset($_REQUEST['file'])) { - $file = $_REQUEST['file']; // Existing file + $file = strClean($_REQUEST['file']); // Existing file } else { - $file = ""; // Error + $file = ""; // Error $finalAction = "nothing"; $doNext = ""; $error = true; @@ -33,6 +41,14 @@ if (isset($_POST['newFileName']) && $_POST['newFileName']!="") { $errorMsg = $t['Sorry, bad filename...']; }; +// If we have changes or whole content, we need to LZ decompress them +if (isset($_POST['changes'])) { + $_POST['changes'] = LZString::decompressFromBase64($_POST['changes']); +} +if (isset($_POST['contents'])) { + $_POST['contents'] = LZString::decompressFromBase64($_POST['contents']); +} + // If we have file(s) to work with... if (!$error) { // Replace pipes with slashes, after cleaning the chars @@ -148,7 +164,7 @@ function stitchChanges($fileLines) { $fileLines[$j] = ""; // If the last line, clear line returns from it if ($j == count($fileLines)-1) { - $fileLines[$changes[$i][1]-1] = rtrim(rtrim(rtrim($fileLines[$changes[$i][1]-1],"\n"),"\r"),"\r\n"); + $fileLines[$changes[$i][1]-1] = rtrim(rtrim($fileLines[$changes[$i][1]-1],"\r"),"\n"); } } } @@ -228,7 +244,7 @@ if (!$error && $_GET['action']=="save") { /* console.log(\'Calling \'+saveURL+\' via XHR\'); */ xhr.open("POST",saveURL,true); xhr.setRequestHeader(\'Content-type\', \'application/x-www-form-urlencoded\'); - xhr.send(\'timeStart='.$_POST["timeStart"].'&file='.$fileURL.'&newFileName=\'+newFileName.replace(/\\\+/g,"%2B")+\'&contents=\'+top.ICEcoder.saveAsContent); + xhr.send(\'timeStart='.$_POST["timeStart"].'&file='.$fileURL.'&newFileName=\'+newFileName.replace(/\\\+/g,"%2B")+\'&contents=\'+encodeURIComponent(top.LZString.compressToBase64(top.ICEcoder.saveAsContent))); top.ICEcoder.serverMessage("'.$t['Saving'].'
" + "'.($finalAction == "Save" ? "newFileName" : "'".$fileName."'").'"); } } @@ -266,11 +282,25 @@ if (!$error && $_GET['action']=="save") { if (isset($ftpSite)) { $ftpFilepath = ltrim($fileLoc."/".$fileName,"/"); if (isset($_POST['changes'])) { - // Get existing file contents as lines and stitch changes onto it - $contents = toUTF8noBOM(ftpGetContents($ftpConn, $ftpRoot.$ftpFilepath, $ftpMode)); - $contents = explode("\n",$contents); - $fileLines = file($file); + // Get existing file contents as lines + $loadedFile = toUTF8noBOM(ftpGetContents($ftpConn, $ftpRoot.$fileLoc."/".$fileName, $ftpMode)); + $fileLines = explode("\n",$loadedFile); + // Need to add a new line at the end of each because explode will lose them, + // want want to end up with same array that 'file($file)' produces for a local file + // - it keeps the line endings at the end of each array item + for ($i=0; $i 0) || ($windowsNewLines > 0)){ + if ($unixNewLines > $windowsNewLines){ + $contents = str_replace($ICEcoder["lineEnding"], "\n", $contents); + } elseif ($windowsNewLines > $unixNewLines){ + $contents = str_replace($ICEcoder["lineEnding"], "\r\n", $contents); + } + } // Write our file contents if (!ftpWriteFile($ftpConn, $ftpFilepath, $contents, $ftpMode)) { $doNext .= 'top.ICEcoder.message("Sorry, could not write '.$ftpFilepath.' at '.$ftpHost.'");'; @@ -291,25 +328,26 @@ if (!$error && $_GET['action']=="save") { // Get existing file contents as lines and stitch changes onto it $fileLines = file($file); $contents = stitchChanges($fileLines); + + // get old file contents, and count stats on usage \n and \r there + // in this case we can keep line endings, which file had before, without + // making code version control systems going crazy about line endings change in whole file. + $oldContents = file_exists($file)?file_get_contents($file):''; + $unixNewLines = preg_match_all('/[^\r][\n]/u', $oldContents); + $windowsNewLines = preg_match_all('/[\r][\n]/u', $oldContents); } else { $contents = $_POST['contents']; } // Newly created files have the perms set too $setPerms = (!file_exists($file)) ? true : false; - // get old file contents, if file exists, and count stats on usage \n and \r there - // in this case we can keep line endings, which file had before, without - // making code version control systems going crazy about line endings change in whole file. - $oldContents = file_exists($file)?file_get_contents($file):''; - $unixNewLines = preg_match_all('/[^\r][\n]/u', $oldContents); - $windowsNewLines = preg_match_all('/[\r][\n]/u', $oldContents); $fh = fopen($file, 'w') or die($t['Sorry, cannot save']); // replace \r\n (Windows), \r (old Mac) and \n (Linux) line endings with whatever we chose to be lineEnding $contents = str_replace("\r\n", $ICEcoder["lineEnding"], $contents); $contents = str_replace("\r", $ICEcoder["lineEnding"], $contents); $contents = str_replace("\n", $ICEcoder["lineEnding"], $contents); - if (($unixNewLines > 0) || ($windowsNewLines > 0)){ + if (isset($_POST['changes']) && ($unixNewLines > 0) || ($windowsNewLines > 0)){ if ($unixNewLines > $windowsNewLines){ $contents = str_replace($ICEcoder["lineEnding"], "\n", $contents); } elseif ($windowsNewLines > $unixNewLines){ @@ -512,7 +550,7 @@ if (!$error && $_GET['action']=="save") { // ========== if (!$error && $_GET['action']=="newFolder") { - if (!$demoMode && ($ftpSite || is_writable($docRoot.$fileLoc))) { + if (!$demoMode && (isset($ftpSite) || is_writable($docRoot.$fileLoc))) { $updateFM = false; // FTP if (isset($ftpSite)) { @@ -555,7 +593,7 @@ if (!$error && $_GET['action']=="move") { $tgtDir = $docRoot.$fileLoc."/".$fileName; } if ($srcDir != $tgtDir && $fileLoc != "") { - if (!$demoMode && ($ftpSite || is_writable($srcDir))) { + if (!$demoMode && (isset($ftpSite) || is_writable($srcDir))) { $updateFM = false; // FTP if (isset($ftpSite)) { @@ -576,7 +614,7 @@ if (!$error && $_GET['action']=="move") { } // Update file manager on success if ($updateFM) { - $doNext .= 'top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'move\',\''.$fileLoc.'\',\''.$fileName.'\',\'\',\''.str_replace($iceRoot,"",strClean(str_replace("|","/",$_GET['oldFileName']))).'\',false,$fileOrFolder);'; + $doNext .= 'top.ICEcoder.selectedFiles=[];top.ICEcoder.updateFileManagerList(\'move\',\''.$fileLoc.'\',\''.$fileName.'\',\'\',\''.str_replace($iceRoot,"",strClean(str_replace("|","/",$_GET['oldFileName']))).'\',false,\''.$fileOrFolder.'\');'; } $finalAction = "move"; // Run our custom processes @@ -597,7 +635,7 @@ if (!$error && $_GET['action']=="move") { // ================== if (!$error && $_GET['action']=="rename") { - if (!$demoMode && ($ftpSite || is_writable($docRoot.$iceRoot.str_replace("|","/",strClean($_GET['oldFileName']))))) { + if (!$demoMode && (isset($ftpSite) || is_writable($docRoot.$iceRoot.str_replace("|","/",strClean($_GET['oldFileName']))))) { $updateFM = false; // FTP if (isset($ftpSite)) { @@ -871,7 +909,7 @@ if (!isset($ftpSite) && !$error && $_GET['action']=="getRemoteFile") { // ======================= if (!$error && $_GET['action']=="perms") { - if (!$demoMode && ($ftpSite || is_writable($file))) { + if (!$demoMode && (isset($ftpSite) || is_writable($file))) { $updateFM = false; // FTP if (isset($ftpSite)) { @@ -917,7 +955,7 @@ if (!isset($ftpSite) && !$error && $_GET['action']=="checkExists") { // =================== // No $filemtime yet? Get it now! -if (!isset($filemtime)) { +if (!isset($filemtime) && !is_dir($file)) { $filemtime = $serverType=="Linux" ? filemtime($file) : "1000000"; } // Set $timeStart, use 0 if not available @@ -937,7 +975,7 @@ if (isset($ftpSite)) { } else { $itemAbsPath = $file; $itemPath = dirname($file); - $itemBytes = filesize($file); + $itemBytes = is_dir($file) ? null : filesize($file); $itemType = (file_exists($file) ? (is_dir($file) ? "dir" : "file") : "unknown"); $itemExists = (file_exists($file) ? "true" : "false"); } diff --git a/lib/file-control.php b/lib/file-control.php index f1fcd37..9d2946b 100644 --- a/lib/file-control.php +++ b/lib/file-control.php @@ -3,6 +3,14 @@ include("headers.php"); include("settings.php"); include("ftp-control.php"); $t = $text['file-control']; + +// Load the LZ String PHP libs and define using LZString +include(dirname(__FILE__)."/../LZCompressor/LZContext.php"); +include(dirname(__FILE__)."/../LZCompressor/LZData.php"); +include(dirname(__FILE__)."/../LZCompressor/LZReverseDictionary.php"); +include(dirname(__FILE__)."/../LZCompressor/LZString.php"); +include(dirname(__FILE__)."/../LZCompressor/LZUtil.php"); +use LZCompressor\LZString as LZString; ?> @@ -102,7 +110,7 @@ if ($_GET['action']=="load") { $encoding=ini_get("default_charset"); if($encoding=="") $encoding="UTF-8"; - echo '