/** * Clean a value and try to prevent XSS attacks * * @param mixed $varValue A string or array * @param boolean $blnStrictMode If true, the function removes also JavaScript event handlers * * @return mixed The cleaned string or array */ public static function xssClean($varValue, $blnStrictMode = false) { if ($varValue === null || $varValue == '') { return $varValue; } // Recursively clean arrays if (is_array($varValue)) { foreach ($varValue as $k => $v) { $varValue[$k] = static::xssClean($v); } return $varValue; } // Return if the value is not a string if (is_bool($varValue) || $varValue === null || is_numeric($varValue)) { return $varValue; } // Validate standard character entites and UTF16 two byte encoding $varValue = preg_replace('/(&#*\\w+)[\\x00-\\x20]+;/i', '$1;', $varValue); $varValue = preg_replace('/(&#x*)([0-9a-f]+);/i', '$1$2;', $varValue); // Remove carriage returns $varValue = preg_replace('/\\r+/', '', $varValue); // Replace unicode entities $varValue = utf8_decode_entities($varValue); // Remove null bytes $varValue = str_replace(chr(0), '', $varValue); // Remove encoded null bytes while (strpos($varValue, '\\0') !== false) { $varValue = str_replace('\\0', '', $varValue); } // Define a list of keywords $arrKeywords = array('/\\bj\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\b/is', '/\\bv\\s*b\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t\\b/is', '/\\bv\\s*b\\s*s\\s*c\\s*r\\s*p\\s*t\\b/is', '/\\bs\\s*c\\s*r\\s*i\\s*p\\s*t\\b/is', '/\\ba\\s*p\\s*p\\s*l\\s*e\\s*t\\b/is', '/\\ba\\s*l\\s*e\\s*r\\s*t\\b/is', '/\\bd\\s*o\\s*c\\s*u\\s*m\\s*e\\s*n\\s*t\\b/is', '/\\bw\\s*r\\s*i\\s*t\\s*e\\b/is', '/\\bc\\s*o\\s*o\\s*k\\s*i\\s*e\\b/is', '/\\bw\\s*i\\s*n\\s*d\\s*o\\s*w\\b/is'); // Compact exploded keywords like "j a v a s c r i p t" foreach ($arrKeywords as $strKeyword) { $arrMatches = array(); preg_match_all($strKeyword, $varValue, $arrMatches); foreach ($arrMatches[0] as $strMatch) { $varValue = str_replace($strMatch, preg_replace('/\\s*/', '', $strMatch), $varValue); } } $arrRegexp[] = '/<(a|img)[^>]*[^a-z](<script|<xss)[^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]document\\.cookie[^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]vbscri?pt\\s*:[^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]expression\\s*\\([^>]*>/is'; // Also remove event handlers and JavaScript in strict mode if ($blnStrictMode) { $arrRegexp[] = '/vbscri?pt\\s*:/is'; $arrRegexp[] = '/javascript\\s*:/is'; $arrRegexp[] = '/<\\s*embed.*swf/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]alert\\s*\\([^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]javascript\\s*:[^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]window\\.[^>]*>/is'; $arrRegexp[] = '/<(a|img)[^>]*[^a-z]document\\.[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onabort\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onblur\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onchange\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onclick\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onerror\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onfocus\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onkeypress\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onkeydown\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onkeyup\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onload\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onmouseover\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onmouseup\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onmousedown\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onmouseout\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onreset\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onselect\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onsubmit\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onunload\\s*=[^>]*>/is'; $arrRegexp[] = '/<[^>]*[^a-z]onresize\\s*=[^>]*>/is'; } $varValue = preg_replace($arrRegexp, '', $varValue); // Recheck for encoded null bytes while (strpos($varValue, '\\0') !== false) { $varValue = str_replace('\\0', '', $varValue); } return $varValue; }
/** * Generate the image and stylesheet * @param string $outputFileName * @param int $themeId * @param bool $useInAssetsFolderToo * @param bool $directionX * @param bool $outputWidth */ public function generateImage($outputFileName, $themeId = 0, $useInAssetsFolderToo = false, $directionX = true, $outputWidth = true) { $output = $this->outputFolder . $outputFileName; $bgImage = TL_FILES_URL . str_replace(TL_ROOT . '/', '', $output); $neededWidth = 0; $neededHeight = 0; // Walk each line and set size of new image foreach ($this->arrFolders as $folder) { if (!is_dir($folder)) { $this->strStylesheet .= "/**\n * Source Folder is not valid!!!\n */"; $this->saveCss(); return; } if ($handle = opendir($folder)) { while (false !== ($file = readdir($handle))) { if ($file == '.' || $file == '..' || is_dir($folder . $file)) { continue; } try { $size = getimagesize($folder . $file); } catch (Exception $ex) { continue; } if ($directionX) { $neededWidth += $size[0]; if ($size[1] > $neededHeight) { $neededHeight = $size[1]; } } else { $neededHeight += $size[1]; if ($size[0] > $neededWidth) { $neededWidth = $size[0]; } } } closedir($handle); } } if ($neededWidth <= 0) { $this->strStylesheet .= "/**\n * Error while reading images, or no image found in directory!!!\n */"; $this->saveCss(); return; } // Create image $image = imagecreatetruecolor($neededWidth, $neededHeight); imagesavealpha($image, true); $white = imagecolorallocate($image, 255, 255, 255); $grey = imagecolorallocate($image, 128, 128, 128); $black = imagecolorallocate($image, 0, 0, 0); imagefilledrectangle($image, 0, 0, 150, 25, $black); $trans_colour = imagecolorallocatealpha($image, 0, 0, 0, 127); imagefill($image, 0, 0, $trans_colour); $this->strStylesheet .= '/* CSS sprite generator, generated ' . date('Y-m-d H:i') . " */\n"; $currentX = 0; $currentY = 0; // Walk each line and create image as well as css chunks foreach ($this->arrFolders as $folder) { if ($handle = opendir($folder)) { for ($i = 0; false !== ($file = readdir($handle)); $i++) { $filePath = $folder . $file; if ($file == '.' || $file == '..' || is_dir($filePath)) { $i--; continue; } if (strtoupper(substr($filePath, -3)) == 'PNG') { $source = imagecreatefrompng($filePath); } elseif (strtoupper(substr($filePath, -3)) == 'JPG') { $source = imagecreatefromjpeg($filePath); } elseif (strtoupper(substr($filePath, -3)) == 'GIF') { $source = imagecreatefromgif($filePath); } else { $i--; continue; } $size = getimagesize($filePath); // Import CSS selecotrs or write new if ($this->databaseBlob[$i] !== null) { $cssSelector = utf8_decode_entities($this->databaseBlob[$i][$this->blobSelectorIndex]); } else { $cssSelector = '.' . str_replace(array('.', ' '), array('_', '_'), substr($file, 0, -4)); $databaseBlob[$i][$this->blobSelectorIndex] = $cssSelector; } //imageAlphaBlending($source, false); //imageSaveAlpha($source, true); //imagecopymerge($image, $source, $currentX, 0, 0,0, $size[0], $size[1], 100); imagecopy($image, $source, $currentX, $currentY, 0, 0, $size[0], $size[1]); // Write CSS if ($outputWidth) { $this->strStylesheet .= $cssSelector . "\n{\n\tbackground: url(" . $bgImage . ") no-repeat;\n\tbackground-position: -" . $currentX . "px " . $currentY . "px;\n\twidth: " . $size[0] . "px;\n\theight: " . $size[1] . "px;\n}\n"; $databaseBlob[$i][$this->blobSelectorIndex] = $cssSelector; $databaseBlob[$i][$this->blobImageIndex] = str_replace(TL_ROOT . '/', '', $filePath); } else { $this->strStylesheet .= $cssSelector . "\n{\n\tbackground: url(" . $bgImage . ") no-repeat;\n\tbackground-position: -" . $currentX . "px -" . $currentY . "px;\n}\n"; $databaseBlob[$i][$this->blobSelectorIndex] = $cssSelector; $databaseBlob[$i][$this->blobImageIndex] = str_replace(TL_ROOT . '/', '', $filePath); } // Update current background position if ($directionX) { $currentX += $size[0]; } else { $currentY += $size[1]; } } closedir($handle); } } imagepng($image, $output); imagedestroy($image); if ($this->updateDatabase && $themeId > 0) { $this->updateDatabaseBlob($themeId, $databaseBlob); } $this->saveCss(); if ($useInAssetsFolderToo) { $this->strStylesheet = str_replace(array('files/', "\n\t", "\n", ': ', ' */'), array('../../files/', '', '', ':', " */\n"), $this->strStylesheet); $this->cssFilename = str_replace('.css', '.assets.css', $this->cssFilename); $this->saveCss(); } }