summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcss.js9
-rwxr-xr-xlive_css.module85
2 files changed, 75 insertions, 19 deletions
diff --git a/css.js b/css.js
index e94fbf5..d63ca8e 100755
--- a/css.js
+++ b/css.js
@@ -362,12 +362,15 @@ window.style = function(href, complete){
try {
window.style.lessParser.parse(css, function(e, tree) {
css = tree.toCSS();
+ self.link.html(self.fullUri(css));
});
}
- catch (e) {}
+ catch (e) {
+ console.log('invalid less code');
+ }
}
-
- self.link.html(self.fullUri(css));
+ else
+ self.link.html(self.fullUri(css));
};
self.getStyle = function(){
if (this.href.match(/\.less$/i) && this.less != undefined)
diff --git a/live_css.module b/live_css.module
index 5c72791..922b81d 100755
--- a/live_css.module
+++ b/live_css.module
@@ -164,27 +164,80 @@ function live_css_save(){
if (!user_access('edit css')) return;
$css = $_POST['css'];
$href = $_POST['href'];
+
+ // The URL may contain cache data. In that case, we need to strip them.
+ // i.e. http://.../css/my_file.css?m1unhm
+ $sanitized_url = _live_css_sanitize_css_url($href);
- //calculate the file path relative to the base drupal folder
- $parts = split('/', $href);
- $path = '';
- for($i = 3; $i < count($parts); $i++){
- $path .= $parts[$i] . '/';
+ if (substr($sanitized_url, -4) != '.css' && substr($sanitized_url, -5) != '.less') {
+ echo json_encode(array(
+ 'result' => 'failure',
+ 'filename' => $path,
+ 'msg' => 'Can\'t save to files without a \'less\' or \'css\' extension!'
+ ));
+ return;
+ }
+
+ if (file_munge_filename($sanitized_url) != $sanitized_url) {
+ echo json_encode(array(
+ 'result' => 'failure',
+ 'filename' => $path,
+ 'msg' => 'The url used contains a sub-filextension which poses a security threat. Saving not allowed.'
+ ));
+ return;
}
- if(strpos($path, '?') > 0)
- $path = substr($path, 0, strpos($path, '?'));
- else
- $path = substr($path, 0, -1);
- $path = $_SERVER['DOCUMENT_ROOT'] . '/' . $path;
+ // File path relative to Drupal installation folder.
+ global $base_url;
+ $stripped_url = drupal_substr($sanitized_url, drupal_strlen($base_url) , drupal_strlen($sanitized_url));
+ $relative_file_path = _live_css_document_root() . $stripped_url;
- //save file back
- $fh = fopen($path, 'w') or die("Can't open file " . $path . " at " . $href);
- fwrite($fh, $css);
- fclose($fh);
+
+ // Save file back.
+ $msg = '';
+ $fh = fopen($relative_file_path, 'w');
+ if ($fh !== FALSE) {
+ fwrite($fh, $css);
+ fclose($fh);
+ $result = 'success';
+ }
+ else {
+ $result = 'failure';
+ $msg = 'Can\'t open file ' . $relative_file_path . ' from ' . $href . '. Ensure that you have full write access and that the path is correct.';
+ }
echo json_encode(array(
- 'result' => 'success',
- 'filename' => $path
+ 'result' => $result,
+ 'filename' => $path,
+ 'msg' => $msg
));
}
+
+/**
+ * Helper function to sanitize a URL.
+ * Removes cache information from url of CSS files.
+ */
+function _live_css_sanitize_css_url($url){
+ $result = $url;
+ $pos = strpos($url, '.css?');
+ if ($pos !== FALSE) {
+ $result = substr($url, 0, $pos + 4);
+ }
+ $pos = strpos($url, '.less?');
+ if ($pos !== FALSE) {
+ $result = substr($url, 0, $pos + 5);
+ }
+ return $result;
+}
+
+
+/**
+ * Helper function to get the document root for the current Drupal installation.
+ * $_SERVER['DOCUMENT_ROOT'] is not reliable across all systems, so we need a
+ * way to get the correct value.
+ */
+function _live_css_document_root() {
+ $absolute_dir = dirname(__FILE__);
+ $relative_dir = drupal_get_path('module', 'live_css');
+ return drupal_substr($absolute_dir, 0, -1 * (1 + drupal_strlen($relative_dir)));
+}