diff --git a/build.xml b/build.xml index b8d40a01..61fa7ac7 100644 --- a/build.xml +++ b/build.xml @@ -13,7 +13,7 @@ ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ - ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an ``AS IS'' BASIS, @@ -28,291 +28,291 @@ --> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - - - - + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - - - - - - + + + + + + + + + - - - + + + - - - - - - + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + - + - - - - - - - + + + + + + + - - - + + + - - - - - - - + + + + + + + - - - - - - - + + + + + + + - - + + - - - - - - - - - - + + + + + + + + + + - - - - - + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + - - - - + + + + - - - - - - - - - Build aborted by user. - - - - - + + + + + + + + + Build aborted by user. + + + + + - - - - + + + + - - - + + + - - - + + + diff --git a/build/MessageParser.js b/build/MessageParser.js index 4dd7209e..81f31776 100644 --- a/build/MessageParser.js +++ b/build/MessageParser.js @@ -7,7 +7,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -39,10 +39,10 @@ * @constructor */ var Message = function(id, pluralId) { - this.id = id && String(id); - this.pluralId = pluralId && String(pluralId); - this.locations = []; - return this; + this.id = id && String(id); + this.pluralId = pluralId && String(pluralId); + this.locations = []; + return this; }; /** @@ -54,11 +54,11 @@ var Message = function(id, pluralId) { * @type String */ Message.getKey = function(id, pluralId) { - if (id && pluralId) { - return id + pluralId; - } else { - return id; - } + if (id && pluralId) { + return id + pluralId; + } else { + return id; + } }; /** @@ -71,28 +71,28 @@ Message.getKey = function(id, pluralId) { * @type String */ Message.formatId = function(str, wrap) { - var escapeQuotes = function(s) { - return s.replace(/(^|[^\\])"/g, '$1\\"'); - }; + var escapeQuotes = function(s) { + return s.replace(/(^|[^\\])"/g, '$1\\"'); + }; - var len = 80; - var buf = new java.lang.StringBuffer(); - if (wrap == true && str.length > len) { - buf.append('""\n'); - var offset = 0; - while (offset < str.length) { - buf.append('"'); - buf.append(escapeQuotes(str.substring(offset, offset += len))); - buf.append('"'); - buf.append("\n"); - } - return buf.toString(); - } else { + var len = 80; + var buf = new java.lang.StringBuffer(); + if (wrap == true && str.length > len) { + buf.append('""\n'); + var offset = 0; + while (offset < str.length) { buf.append('"'); - buf.append(escapeQuotes(str)); - buf.append('"\n'); - } - return buf.toString(); + buf.append(escapeQuotes(str.substring(offset, offset += len))); + buf.append('"'); + buf.append("\n"); + } + return buf.toString(); + } else { + buf.append('"'); + buf.append(escapeQuotes(str)); + buf.append('"\n'); + } + return buf.toString(); }; /** @@ -103,7 +103,7 @@ Message.formatId = function(str, wrap) { * was found at */ Message.prototype.addLocation = function(filePath, lineNum) { - this.locations.push(filePath + ":" + lineNum); + this.locations.push(filePath + ":" + lineNum); }; /** @@ -113,34 +113,34 @@ Message.prototype.addLocation = function(filePath, lineNum) { * to write into */ Message.prototype.write = function(buf) { - for (var i=0;i -1 - || (this.pluralId != null && this.pluralId.indexOf("{") > -1)) { - buf.append("#, java-format\n"); - } - buf.append('msgid '); - buf.append(Message.formatId(this.id)); - if (this.pluralId != null) { - buf.append('msgid_plural '); - buf.append(Message.formatId(this.pluralId)); - buf.append('msgstr[0] ""\nmsgstr[1] ""\n') - } else { - buf.append('msgstr ""\n') - } - buf.append("\n"); - return; + for (var i=0;i -1 + || (this.pluralId != null && this.pluralId.indexOf("{") > -1)) { + buf.append("#, java-format\n"); + } + buf.append('msgid '); + buf.append(Message.formatId(this.id)); + if (this.pluralId != null) { + buf.append('msgid_plural '); + buf.append(Message.formatId(this.pluralId)); + buf.append('msgstr[0] ""\nmsgstr[1] ""\n') + } else { + buf.append('msgstr ""\n') + } + buf.append("\n"); + return; }; /** * @constructor */ var MessageParser = function() { - this.messages = {}; - return this; + this.messages = {}; + return this; }; /** @@ -150,11 +150,11 @@ var MessageParser = function() { * @type Object */ MessageParser.FUNCTION_NAMES = { - "_": true, - "gettext": true, - "ngettext": true, - "markgettext": true, - "cgettext": true + "_": true, + "gettext": true, + "ngettext": true, + "markgettext": true, + "cgettext": true }; /** @@ -198,7 +198,7 @@ MessageParser.REGEX_PARAM = /([\w]*)\s*=\s*["'](.*?)["']\s*(?=\w+=|$)/gm; * @type Number */ MessageParser.getLineNum = function(str, idx) { - return str.substring(0, idx).split(/.*(?:\r\n|\n\r|\r|\n)/).length; + return str.substring(0, idx).split(/.*(?:\r\n|\n\r|\r|\n)/).length; }; /** @@ -209,36 +209,36 @@ MessageParser.getLineNum = function(str, idx) { * @param {String} encoding The encoding to use */ MessageParser.prototype.parse = function(file, encoding) { - if (file.isDirectory()) { - var list = file.list(); - for (var i=0;i -1) { + switch (String(fName.substring(dotIdx+1))) { + case "skin": + print("Parsing skin file " + file.getCanonicalPath() + "..."); + this.parseSkinFile(file, encoding); + break; + case "hac": + case "js": + print("Parsing function file " + file.getCanonicalPath() + "..."); + this.parseFunctionFile(file, encoding); + break; + default: + break; } - } else { - var fName, dotIdx; - fName = file.getName(); - if ((dotIdx = fName.lastIndexOf(".")) > -1) { - switch (String(fName.substring(dotIdx+1))) { - case "skin": - print("Parsing skin file " + file.getCanonicalPath() + "..."); - this.parseSkinFile(file, encoding); - break; - case "hac": - case "js": - print("Parsing function file " + file.getCanonicalPath() + "..."); - this.parseFunctionFile(file, encoding); - break; - default: - break; - } - } - } - return; + } + } + return; }; /** @ignore */ MessageParser.prototype.toString = function() { - return "[Jala Message Parser]"; + return "[Jala Message Parser]"; }; /** @@ -248,65 +248,65 @@ MessageParser.prototype.toString = function() { * @param {String} encoding The encoding to use */ MessageParser.prototype.parseFunctionFile = function(file, encoding) { - var fis = new java.io.FileInputStream(file); - var isr = new java.io.InputStreamReader(fis, encoding || "UTF-8"); - var reader = new java.io.BufferedReader(isr); - var tokenizer = new java.io.StreamTokenizer(reader); - var messages = [], stack = []; - var c; - while ((c = tokenizer.nextToken()) != java.io.StreamTokenizer.TT_EOF) { - switch (c) { - case java.io.StreamTokenizer.TT_WORD: - if (MessageParser.FUNCTION_NAMES[tokenizer.sval] == true) { - stack.push({name: tokenizer.sval, lineNr: tokenizer.lineno()}); - } else if (stack.length > 0) { - // it's something else than a string argument inside a gettext method call - // so finalize the argument parsing here as we aren't interested in that - messages.push(stack.pop()); - } - break; - case java.io.StreamTokenizer.TT_NUMBER: - break; - default: - if (stack.length > 0) { - if ("\u0028".charCodeAt(0) == c) { - // start of arguments (an opening bracket) - stack[stack.length-1].args = []; - } else if ("\u0029".charCodeAt(0) == c) { - // end of arguments (a closing bracket) - messages.push(stack.pop()); - } else if ("\u0022".charCodeAt(0) == c || "\u0027".charCodeAt(0) == c) { - // a quoted string argument - stack[stack.length-1].args.push(tokenizer.sval); - } - } - break; + var fis = new java.io.FileInputStream(file); + var isr = new java.io.InputStreamReader(fis, encoding || "UTF-8"); + var reader = new java.io.BufferedReader(isr); + var tokenizer = new java.io.StreamTokenizer(reader); + var messages = [], stack = []; + var c; + while ((c = tokenizer.nextToken()) != java.io.StreamTokenizer.TT_EOF) { + switch (c) { + case java.io.StreamTokenizer.TT_WORD: + if (MessageParser.FUNCTION_NAMES[tokenizer.sval] == true) { + stack.push({name: tokenizer.sval, lineNr: tokenizer.lineno()}); + } else if (stack.length > 0) { + // it's something else than a string argument inside a gettext method call + // so finalize the argument parsing here as we aren't interested in that + messages.push(stack.pop()); + } + break; + case java.io.StreamTokenizer.TT_NUMBER: + break; + default: + if (stack.length > 0) { + if ("\u0028".charCodeAt(0) == c) { + // start of arguments (an opening bracket) + stack[stack.length-1].args = []; + } else if ("\u0029".charCodeAt(0) == c) { + // end of arguments (a closing bracket) + messages.push(stack.pop()); + } else if ("\u0022".charCodeAt(0) == c || "\u0027".charCodeAt(0) == c) { + // a quoted string argument + stack[stack.length-1].args.push(tokenizer.sval); + } + } + break; + } + } + if (messages.length > 0) { + var msgParam, key, msg; + for (var i=0;i 0) { + if (msgParam.name === "cgettext" || msgParam.name === "markgettext") { + msgParam.args[0] = cgettext.getKey(msgParam.args[0], msgParam.args[1]); + delete msgParam.args[1]; + } + key = Message.getKey(msgParam.args[0]); + if (!(msg = this.messages[key])) { + this.messages[key] = msg = new Message(msgParam.args[0], msgParam.args[1]); + } + if (!msg.pluralId && msgParam.args.length > 1) { + msg.pluralId = msgParam.args[1]; + } + msg.addLocation(file.getCanonicalPath(), msgParam.lineNr); } - } - if (messages.length > 0) { - var msgParam, key, msg; - for (var i=0;i 0) { - if (msgParam.name === "cgettext" || msgParam.name === "markgettext") { - msgParam.args[0] = cgettext.getKey(msgParam.args[0], msgParam.args[1]); - delete msgParam.args[1]; - } - key = Message.getKey(msgParam.args[0]); - if (!(msg = this.messages[key])) { - this.messages[key] = msg = new Message(msgParam.args[0], msgParam.args[1]); - } - if (!msg.pluralId && msgParam.args.length > 1) { - msg.pluralId = msgParam.args[1]; - } - msg.addLocation(file.getCanonicalPath(), msgParam.lineNr); - } - } - } - fis.close(); - isr.close(); - reader.close(); - return; + } + } + fis.close(); + isr.close(); + reader.close(); + return; }; /** @@ -324,72 +324,72 @@ MessageParser.prototype.parseFunctionFile = function(file, encoding) { * @param {String} encoding The encoding to use */ MessageParser.prototype.parseSkinFile = function(file, encoding) { - var self = this; - var source = readFile(file.getAbsolutePath(), encoding || "UTF-8"); + var self = this; + var source = readFile(file.getAbsolutePath(), encoding || "UTF-8"); - var checkNestedMacros = function(iterator) { - var macros = []; - while (iterator.hasNext()) { - macro = iterator.next(); - if (macro && macro.constructor !== String) { - macros.push(macro); - } + var checkNestedMacros = function(iterator) { + var macros = []; + while (iterator.hasNext()) { + macro = iterator.next(); + if (macro && macro.constructor !== String) { + macros.push(macro); } - processMacros(macros); - } + } + processMacros(macros); + } - var processMacros = function(macros) { - var re = gettext_macro.REGEX; - var id, pluralId, name, args, param, key, msg; - for each (var macro in macros) { - id = pluralId = null; - name = macro.getName(); - param = macro.getNamedParams(); - if (param) { - checkNestedMacros(param.values().iterator()); - if (name === MessageParser.MACRO_NAME) { - id = param.get("text"); - pluralId = param.get("plural"); - } else if (param.containsKey("message") === MessageParser.ATTRIBUTE_NAME) { - id = param.get("message"); - pluralId = param.get("plural"); - } - } - args = macro.getPositionalParams(); - if (args) { - checkNestedMacros(args.iterator()); - if (name === "gettext" || name === "markgettext") { - id = cgettext.getKey(args.get(0), param && param.get("context")); - } else if (name === "ngettext") { - id = args.get(0); - pluralId = args.get(1); - } - } - if (id != null) { - if (id.constructor !== String) { - continue; - } - // create new Message instance or update the existing one - id = id.replace(re, String.SPACE); - pluralId && (pluralId = pluralId.replace(re, String.SPACE)); - key = Message.getKey(id); - if (!(msg = self.messages[key])) { - self.messages[key] = msg = new Message(id, pluralId, file.getCanonicalPath()); - } - msg.addLocation(file.getCanonicalPath(), MessageParser.getLineNum(source, macro.start)); - } + var processMacros = function(macros) { + var re = gettext_macro.REGEX; + var id, pluralId, name, args, param, key, msg; + for each (var macro in macros) { + id = pluralId = null; + name = macro.getName(); + param = macro.getNamedParams(); + if (param) { + checkNestedMacros(param.values().iterator()); + if (name === MessageParser.MACRO_NAME) { + id = param.get("text"); + pluralId = param.get("plural"); + } else if (param.containsKey("message") === MessageParser.ATTRIBUTE_NAME) { + id = param.get("message"); + pluralId = param.get("plural"); + } } - } + args = macro.getPositionalParams(); + if (args) { + checkNestedMacros(args.iterator()); + if (name === "gettext" || name === "markgettext") { + id = cgettext.getKey(args.get(0), param && param.get("context")); + } else if (name === "ngettext") { + id = args.get(0); + pluralId = args.get(1); + } + } + if (id != null) { + if (id.constructor !== String) { + continue; + } + // create new Message instance or update the existing one + id = id.replace(re, String.SPACE); + pluralId && (pluralId = pluralId.replace(re, String.SPACE)); + key = Message.getKey(id); + if (!(msg = self.messages[key])) { + self.messages[key] = msg = new Message(id, pluralId, file.getCanonicalPath()); + } + msg.addLocation(file.getCanonicalPath(), MessageParser.getLineNum(source, macro.start)); + } + } + } - var skin = createSkin(source); - if (skin.hasMainskin()) { - processMacros(skin.getMacros()); - } - for each (var name in skin.getSubskinNames()) { - var subskin = skin.getSubskin(name); - processMacros(subskin.getMacros()); - } - return; + var skin = createSkin(source); + if (skin.hasMainskin()) { + processMacros(skin.getMacros()); + } + for each (var name in skin.getSubskinNames()) { + var subskin = skin.getSubskin(name); + processMacros(subskin.getMacros()); + } + return; } /** @@ -399,58 +399,58 @@ MessageParser.prototype.parseSkinFile = function(file, encoding) { * @see http://drupal.org/node/17564 */ MessageParser.prototype.getPotString = function() { - var date = new Date; - var buf = new java.lang.StringBuffer(); - buf.append('#\n'); - buf.append('# The Antville Project\n'); - buf.append('# http://code.google.com/p/antville\n'); - buf.append('#\n'); - buf.append('# Copyright 2001-' + date.getFullYear() + ' by The Antville People\n'); - buf.append('#\n'); - buf.append("# Licensed under the Apache License, Version 2.0 (the ``License''\n"); - buf.append('# you may not use this file except in compliance with the License.\n'); - buf.append('# You may obtain a copy of the License at\n'); - buf.append('#\n'); - buf.append('# http://www.apache.org/licenses/LICENSE-2.0\n'); - buf.append('#\n'); - buf.append('# Unless required by applicable law or agreed to in writing, software\n'); - buf.append("# distributed under the License is distributed on an ``AS IS'' BASIS,\n"); - buf.append('# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'); - buf.append('# See the License for the specific language governing permissions and\n'); - buf.append('# limitations under the License.\n'); - buf.append('#\n'); - buf.append('# $Revision$\n'); - buf.append('# $Author$\n'); - buf.append('# $Date$\n'); - buf.append('# $URL$\n'); - buf.append('#\n'); - buf.append('#, fuzzy\n'); - buf.append('msgid ""\n'); - buf.append('msgstr ""\n'); - buf.append('"Project-Id-Version: Antville-' + Root.VERSION + '\\n"\n'); - buf.append('"Report-Msgid-Bugs-To: mail@antville.org\\n"\n'); - var sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mmZ"); - buf.append('"POT-Creation-Date: ' + sdf.format(new java.util.Date()) + '\\n"\n'); - buf.append('"PO-Revision-Date: ' + sdf.format(new java.util.Date()) + '\\n"\n'); - //buf.append('"Last-Translator: FULL NAME \\n"\n'); - buf.append('"Language-Team: The Antville People \\n"\n'); - buf.append('"MIME-Version: 1.0\\n"\n'); - buf.append('"Content-Type: text/plain; charset=utf-8\\n"\n'); - buf.append('"Content-Transfer-Encoding: 8bit\\n"\n'); - buf.append('"Plural-Forms: nplurals=2; plural=(n != 1);\\n"\n'); - buf.append('\n'); + var date = new Date; + var buf = new java.lang.StringBuffer(); + buf.append('#\n'); + buf.append('# The Antville Project\n'); + buf.append('# http://code.google.com/p/antville\n'); + buf.append('#\n'); + buf.append('# Copyright 2001-' + date.getFullYear() + ' by The Antville People\n'); + buf.append('#\n'); + buf.append("# Licensed under the Apache License, Version 2.0 (the ``License''\n"); + buf.append('# you may not use this file except in compliance with the License.\n'); + buf.append('# You may obtain a copy of the License at\n'); + buf.append('#\n'); + buf.append('# http://www.apache.org/licenses/LICENSE-2.0\n'); + buf.append('#\n'); + buf.append('# Unless required by applicable law or agreed to in writing, software\n'); + buf.append("# distributed under the License is distributed on an ``AS IS'' BASIS,\n"); + buf.append('# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'); + buf.append('# See the License for the specific language governing permissions and\n'); + buf.append('# limitations under the License.\n'); + buf.append('#\n'); + buf.append('# $Revision$\n'); + buf.append('# $Author$\n'); + buf.append('# $Date$\n'); + buf.append('# $URL$\n'); + buf.append('#\n'); + buf.append('#, fuzzy\n'); + buf.append('msgid ""\n'); + buf.append('msgstr ""\n'); + buf.append('"Project-Id-Version: Antville-' + Root.VERSION + '\\n"\n'); + buf.append('"Report-Msgid-Bugs-To: mail@antville.org\\n"\n'); + var sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mmZ"); + buf.append('"POT-Creation-Date: ' + sdf.format(new java.util.Date()) + '\\n"\n'); + buf.append('"PO-Revision-Date: ' + sdf.format(new java.util.Date()) + '\\n"\n'); + //buf.append('"Last-Translator: FULL NAME \\n"\n'); + buf.append('"Language-Team: The Antville People \\n"\n'); + buf.append('"MIME-Version: 1.0\\n"\n'); + buf.append('"Content-Type: text/plain; charset=utf-8\\n"\n'); + buf.append('"Content-Transfer-Encoding: 8bit\\n"\n'); + buf.append('"Plural-Forms: nplurals=2; plural=(n != 1);\\n"\n'); + buf.append('\n'); - // sort all messages by their singular key - var keys = []; - for (var i in this.messages) { - keys[keys.length] = this.messages[i].id; - } - keys.sort(); - // add all the messages - for (var i=0;i -1) { - read += r; - if (read == buffer.length) { - // grow input buffer - var newBuffer = new java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, buffer.length * 2); - java.lang.System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); - buffer = newBuffer; - } - } - inStream.close(); - return new java.lang.String(buffer, 0, read); + var inStream = new java.io.InputStreamReader(new java.io.FileInputStream(file), "UTF-8"); + var buffer = new java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, 2048); + var read = 0; + var r = 0; + while ((r = inStream.read(buffer, read, buffer.length - read)) > -1) { + read += r; + if (read == buffer.length) { + // grow input buffer + var newBuffer = new java.lang.reflect.Array.newInstance(java.lang.Character.TYPE, buffer.length * 2); + java.lang.System.arraycopy(buffer, 0, newBuffer, 0, buffer.length); + buffer = newBuffer; + } + } + inStream.close(); + return new java.lang.String(buffer, 0, read); } /** @@ -141,63 +141,63 @@ PoParser.readFile = function(file) { * @param {java.io.File} file The .po file to parse */ PoParser.prototype.parse = function(file) { - // parse the locale key out of the file name - var fileName = file.getName(); - if (!(this.localeKey = fileName.substring(0, fileName.indexOf(".")))) { - throw "Invalid PO file name: " + fileName; - } + // parse the locale key out of the file name + var fileName = file.getName(); + if (!(this.localeKey = fileName.substring(0, fileName.indexOf(".")))) { + throw "Invalid PO file name: " + fileName; + } - // read the PO file content and parse it into messages - var content = PoParser.readFile(file); - var start = new Date(); - var lines = content.split(PoParser.REGEX_LINES); - var idx = -1; - var line = null; - var m, value, nr; - var msg; + // read the PO file content and parse it into messages + var content = PoParser.readFile(file); + var start = new Date(); + var lines = content.split(PoParser.REGEX_LINES); + var idx = -1; + var line = null; + var m, value, nr; + var msg; - var hasMoreLines = function() { - return idx < lines.length - 1; - }; + var hasMoreLines = function() { + return idx < lines.length - 1; + }; - var nextLine = function() { - return (line = lines[idx += 1]) != null; - }; + var nextLine = function() { + return (line = lines[idx += 1]) != null; + }; - var getContinuation = function(str) { - var nLine; - while ((nLine = lines[idx + 1]) != null) { - if ((m = nLine.match(PoParser.REGEX_MSG_CONT)) != null) { - str += m[1]; - nextLine(); - } else { - break; - } + var getContinuation = function(str) { + var nLine; + while ((nLine = lines[idx + 1]) != null) { + if ((m = nLine.match(PoParser.REGEX_MSG_CONT)) != null) { + str += m[1]; + nextLine(); + } else { + break; } - return str; - } + } + return str; + } - while (nextLine()) { - if ((m = line.match(PoParser.REGEX_MSGID)) != null) { - value = getContinuation(m[1]); - if (value) { - msg = this.messages[this.messages.length] = new Message(value); - } - } else if ((m = line.match(PoParser.REGEX_MSGID_PLURAL)) != null) { - value = getContinuation(m[1]); - if (value && msg != null) { - msg.pluralKey = value; - } - } else if ((m = line.match(PoParser.REGEX_MSGSTR)) != null) { - nr = m[1]; - value = getContinuation(m[2]); - if (value && msg != null) { - nr = parseInt(nr, 10); - msg.translations[nr || 0] = value; - } + while (nextLine()) { + if ((m = line.match(PoParser.REGEX_MSGID)) != null) { + value = getContinuation(m[1]); + if (value) { + msg = this.messages[this.messages.length] = new Message(value); } - } - return; + } else if ((m = line.match(PoParser.REGEX_MSGID_PLURAL)) != null) { + value = getContinuation(m[1]); + if (value && msg != null) { + msg.pluralKey = value; + } + } else if ((m = line.match(PoParser.REGEX_MSGSTR)) != null) { + nr = m[1]; + value = getContinuation(m[2]); + if (value && msg != null) { + nr = parseInt(nr, 10); + msg.translations[nr || 0] = value; + } + } + } + return; }; /** @@ -207,44 +207,44 @@ PoParser.prototype.parse = function(file) { * file should be saved */ PoParser.prototype.writeToFile = function(output) { - var buf = new java.lang.StringBuffer(); - // write header - buf.append('/**\n'); - buf.append(' * Instantiate the messages namespace if it\'s not already existing\n'); - buf.append(' */\n'); + var buf = new java.lang.StringBuffer(); + // write header + buf.append('/**\n'); + buf.append(' * Instantiate the messages namespace if it\'s not already existing\n'); + buf.append(' */\n'); var objPath = ""; - if (this.namespace) { - objPath += this.namespace; - buf.append('if (!global.' + objPath + ') {\n'); - buf.append(' global.' + objPath + ' = {};\n'); - buf.append('}\n'); - objPath += "."; - } - objPath += "messages"; - buf.append('if (!global.' + objPath + ') {\n'); - buf.append(' global.' + objPath + ' = {};\n'); - buf.append('}\n\n'); + if (this.namespace) { + objPath += this.namespace; + buf.append('if (!global.' + objPath + ') {\n'); + buf.append(' global.' + objPath + ' = {};\n'); + buf.append('}\n'); + objPath += "."; + } + objPath += "messages"; + buf.append('if (!global.' + objPath + ') {\n'); + buf.append(' global.' + objPath + ' = {};\n'); + buf.append('}\n\n'); - buf.append('/**\n'); - buf.append(' * Messages for locale "' + this.localeKey + '"\n'); - buf.append(' */\n'); - var fname = objPath + "." + this.localeKey + ".js"; - objPath += "['" + this.localeKey + "']"; - buf.append('global.' + objPath + ' = {\n'); - // write messages - for (var i=0;i [namespace]"); - print(": Either a single .po file or a directory containing .po files"); - print(": The directory where the generated messages files should be stored"); - print("[namespace]: An optional global namespace where the messages should be"); - print(" stored (eg. a namespace like 'jala' will lead to messages"); - print(" stored in global.jala.messages by their locale."); - quit(); + print("Usage:"); + print("PoParser.js [namespace]"); + print(": Either a single .po file or a directory containing .po files"); + print(": The directory where the generated messages files should be stored"); + print("[namespace]: An optional global namespace where the messages should be"); + print(" stored (eg. a namespace like 'jala' will lead to messages"); + print(" stored in global.jala.messages by their locale."); + quit(); } var input = new java.io.File(arguments[0]); @@ -306,31 +306,31 @@ var namespace = arguments[2]; // check if the output destination is a directory if (output.isFile()) { - print("Invalid arguments: the output destination must be a directory."); - quit(); + print("Invalid arguments: the output destination must be a directory."); + quit(); } if (namespace && namespace.indexOf(".") != -1) { - print("Invalid arguments: Please don't specify complex object paths, as this"); - print("would corrupt the messages file."); - quit(); + print("Invalid arguments: Please don't specify complex object paths, as this"); + print("would corrupt the messages file."); + quit(); } // parse the PO file(s) and create the message catalog files var parser; if (input.isDirectory()) { - var files = input.listFiles(); - var file; - for (var i=0;i/i; + macroEndRegex = parserConfig.macroEndRegex || /^%>/i; //inner modes var htmlMixedMode; var macroMode = { - startState: function() { - return {} - }, - token: function(stream, state) { - var c = stream.next(); - return 'helma-macro'; - } - } + startState: function() { + return {} + }, + token: function(stream, state) { + var c = stream.next(); + return 'helma-macro'; + } + } //tokenizer when in html mode function htmlDispatch(stream, state) { - if (stream.match(macroStartRegex, false)) { - state.token=macroDispatch; - return macroMode.token(stream, state.macroState); - } - else - return htmlMixedMode.token(stream, state.htmlState); - } + if (stream.match(macroStartRegex, false)) { + state.token=macroDispatch; + return macroMode.token(stream, state.macroState); + } + else + return htmlMixedMode.token(stream, state.htmlState); + } //tokenizer when in macro mode function macroDispatch(stream, state) { - if (stream.match(macroEndRegex, false)) { - state.token=htmlDispatch; - return htmlMixedMode.token(stream, state.htmlState); - } - else{ - var style = macroMode.token(stream, state.macroState); - return style; - } + if (stream.match(macroEndRegex, false)) { + state.token=htmlDispatch; + return htmlMixedMode.token(stream, state.htmlState); } + else{ + var style = macroMode.token(stream, state.macroState); + return style; + } + } return { - startState: function() { - htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed"); - return { - token : parserConfig.startOpen ? macroDispatch : htmlDispatch, - htmlState : htmlMixedMode.startState(), - macroState : macroMode.startState() - } - }, - - token: function(stream, state) { - return state.token(stream, state); - }, - - indent: function(state, textAfter) { - if (state.token == htmlDispatch) - return htmlMixedMode.indent(state.htmlState, textAfter); - else - return macroMode.indent(state.macroState, textAfter); - }, - - copyState: function(state) { - return { - token : state.token, - htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState), - macroState : CodeMirror.copyState(macroMode, state.macroState) + startState: function() { + htmlMixedMode = htmlMixedMode || CodeMirror.getMode(config, "htmlmixed"); + return { + token : parserConfig.startOpen ? macroDispatch : htmlDispatch, + htmlState : htmlMixedMode.startState(), + macroState : macroMode.startState() } - }, + }, + + token: function(stream, state) { + return state.token(stream, state); + }, + + indent: function(state, textAfter) { + if (state.token == htmlDispatch) + return htmlMixedMode.indent(state.htmlState, textAfter); + else + return macroMode.indent(state.macroState, textAfter); + }, + + copyState: function(state) { + return { + token : state.token, + htmlState : CodeMirror.copyState(htmlMixedMode, state.htmlState), + macroState : CodeMirror.copyState(macroMode, state.macroState) + } + }, - electricChars: "/{}:" + electricChars: "/{}:" } }, "htmlmixed"); diff --git a/build/jsdoc/templates/codeview/publish.js b/build/jsdoc/templates/codeview/publish.js index 1081d745..be3a4e1b 100755 --- a/build/jsdoc/templates/codeview/publish.js +++ b/build/jsdoc/templates/codeview/publish.js @@ -1,33 +1,33 @@ /** Called automatically by JsDoc Toolkit. */ function publish(symbolSet) { publish.conf = { // trailing slash expected for dirs - ext: ".html", - outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", + ext: ".html", + outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/", - staticDir: "static/", + staticDir: "static/", symbolsDir: "symbols/", - srcDir: "symbols/src/", - cssDir: "css/", - fontsDir: "css/fonts/", - jsDir: "javascript/", + srcDir: "symbols/src/", + cssDir: "css/", + fontsDir: "css/fonts/", + jsDir: "javascript/", templateName: "Codeview", templateVersion: "1.2", templateLink: "http://www.thebrightlines.com/2010/05/06/new-template-for-jsdoctoolkit-codeview/" }; - + // is source output is suppressed, just display the links to the source file if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) { Link.prototype._makeSrcLink = function(srcFilePath) { return "<"+srcFilePath+">"; } } - + // create the folders and subfolders to hold the output IO.mkPath((publish.conf.outDir+publish.conf.cssDir)); IO.mkPath((publish.conf.outDir+publish.conf.fontsDir)); IO.mkPath((publish.conf.outDir+publish.conf.jsDir)); IO.mkPath((publish.conf.outDir+"symbols/src").split("/")); - + // used to allow Link to check the details of things being linked to Link.symbolSet = symbolSet; @@ -39,15 +39,15 @@ function publish(symbolSet) { print("Couldn't create the required templates: "+e); quit(); } - + // some utility filters function hasNoParent($) {return ($.memberOf == "")} function isaFile($) {return ($.is("FILE"))} function isaClass($) {return (($.is("CONSTRUCTOR") || $.isNamespace) && ($.alias != "_global_" || !JSDOC.opt.D.noGlobal))} - + // get an array version of the symbolset, useful for filtering var symbols = symbolSet.toArray(); - + // create the hilited source code files var files = JSDOC.opt.srcFiles; for (var i = 0, l = files.length; i < l; i++) { @@ -55,74 +55,74 @@ function publish(symbolSet) { var srcDir = publish.conf.outDir + publish.conf.srcDir; makeSrcFile(file, srcDir); } - + // get a list of all the classes in the symbolset publish.classes = symbols.filter(isaClass).sort(makeSortby("alias")); - + // create a filemap in which outfiles must be to be named uniquely, ignoring case if (JSDOC.opt.u) { var filemapCounts = {}; Link.filemap = {}; for (var i = 0, l = publish.classes.length; i < l; i++) { var lcAlias = publish.classes[i].alias.toLowerCase(); - + if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1; else filemapCounts[lcAlias]++; - - Link.filemap[publish.classes[i].alias] = + + Link.filemap[publish.classes[i].alias] = (filemapCounts[lcAlias] > 1)? lcAlias+"_"+filemapCounts[lcAlias] : lcAlias; } } - + // create each of the class pages for (var i = 0, l = publish.classes.length; i < l; i++) { var symbol = publish.classes[i]; - - symbol.events = symbol.getEvents(); // 1 order matters + + symbol.events = symbol.getEvents(); // 1 order matters symbol.methods = symbol.getMethods(); // 2 - + var output = ""; output = classTemplate.process(symbol); - + IO.saveFile(publish.conf.outDir+publish.conf.symbolsDir, ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output); } - + // create the class index page try { var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allclasses.tmpl"); } catch(e) { print(e.message); quit(); } - + var classesIndex = classesindexTemplate.process(publish.classes); IO.saveFile(publish.conf.outDir, (JSDOC.opt.D.index=="files"?"allclasses":"index")+publish.conf.ext, classesIndex); classesindexTemplate = classesIndex = classes = null; - + // create the file index page try { var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl"); } catch(e) { print(e.message); quit(); } - + var documentedFiles = symbols.filter(isaFile); // files that have file-level docs var allFiles = []; // not all files have file-level docs, but we need to list every one - + for (var i = 0; i < files.length; i++) { allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */"))); } - + for (var i = 0; i < documentedFiles.length; i++) { var offset = files.indexOf(documentedFiles[i].alias); allFiles[offset] = documentedFiles[i]; } - + allFiles = allFiles.sort(makeSortby("name")); // output the file index page var filesIndex = fileindexTemplate.process(allFiles); IO.saveFile(publish.conf.outDir, (JSDOC.opt.D.index=="files"?"index":"files")+publish.conf.ext, filesIndex); fileindexTemplate = filesIndex = files = null; - + // copy static files IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.cssDir+"all.css", publish.conf.outDir+"/"+publish.conf.cssDir); IO.copyFile(publish.conf.templatesDir+"/"+publish.conf.cssDir+"screen.css", publish.conf.outDir+"/"+publish.conf.cssDir); @@ -181,14 +181,14 @@ function include(path) { /** Turn a raw source file into a code-hilited page in the docs. */ function makeSrcFile(path, srcDir, name) { if (JSDOC.opt.s) return; - + if (!name) { name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_"); name = name.replace(/\:/g, "_"); } - + var src = {path: path, name:name, charset: IO.encoding, hilited: ""}; - + if (defined(JSDOC.PluginManager)) { JSDOC.PluginManager.run("onPublishSrc", src); } @@ -219,18 +219,18 @@ function makeSignature(params) { /** Find symbol {@link ...} strings in text and turn into html links */ function resolveLinks(str, from) { - str = str.replace(/\{@link ([^}]+)\}/gi, - function(match, symbolName) { + str = str.replace(/\{@link ([^}]+)\}/gi, + function(match, symbolName) { symbolName = symbolName.trim(); var index = symbolName.indexOf(' '); if (index > 0) { - var label = symbolName.substring(index + 1); - symbolName = symbolName.substring(0, index); - return new Link().toSymbol(symbolName).withText(label); + var label = symbolName.substring(index + 1); + symbolName = symbolName.substring(0, index); + return new Link().toSymbol(symbolName).withText(label); } else { - return new Link().toSymbol(symbolName); + return new Link().toSymbol(symbolName); } - } - ); - return str; + } + ); + return str; } \ No newline at end of file diff --git a/build/jsdoc/templates/default/publish.js b/build/jsdoc/templates/default/publish.js index 42300f4b..084a3f6a 100644 --- a/build/jsdoc/templates/default/publish.js +++ b/build/jsdoc/templates/default/publish.js @@ -1,23 +1,23 @@ /** Called automatically by JsDoc Toolkit. */ function publish(symbolSet) { publish.conf = { // trailing slash expected for dirs - ext: ".html", - outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", + ext: ".html", + outDir: JSDOC.opt.d || SYS.pwd+"../out/jsdoc/", templatesDir: JSDOC.opt.t || SYS.pwd+"../templates/jsdoc/", symbolsDir: "symbols/", - srcDir: "symbols/src/" + srcDir: "symbols/src/" }; - + // is source output is suppressed, just display the links to the source file if (JSDOC.opt.s && defined(Link) && Link.prototype._makeSrcLink) { Link.prototype._makeSrcLink = function(srcFilePath) { return "<"+srcFilePath+">"; } } - + // create the folders and subfolders to hold the output IO.mkPath((publish.conf.outDir+"symbols/src").split("/")); - + // used to allow Link to check the details of things being linked to Link.symbolSet = symbolSet; @@ -30,15 +30,15 @@ function publish(symbolSet) { print("Couldn't create the required templates: "+e); quit(); } - + // some ustility filters function hasNoParent($) {return ($.memberOf == "")} function isaFile($) {return ($.is("FILE"))} function isaClass($) {return ($.is("CONSTRUCTOR") || $.isNamespace)} - + // get an array version of the symbolset, useful for filtering var symbols = symbolSet.toArray(); - + // create the hilited source code files var files = JSDOC.opt.srcFiles; for (var i = 0, l = files.length; i < l; i++) { @@ -46,76 +46,76 @@ function publish(symbolSet) { var srcDir = publish.conf.outDir + "symbols/src/"; makeSrcFile(file, srcDir); } - + // get a list of all the classes in the symbolset var classes = symbols.filter(isaClass).sort(makeSortby("alias")); - + // create a filemap in which outfiles must be to be named uniquely, ignoring case if (JSDOC.opt.u) { var filemapCounts = {}; Link.filemap = {}; for (var i = 0, l = classes.length; i < l; i++) { var lcAlias = classes[i].alias.toLowerCase(); - + if (!filemapCounts[lcAlias]) filemapCounts[lcAlias] = 1; else filemapCounts[lcAlias]++; - - Link.filemap[classes[i].alias] = + + Link.filemap[classes[i].alias] = (filemapCounts[lcAlias] > 1)? lcAlias+"_"+filemapCounts[lcAlias] : lcAlias; } } - + // create a class index, displayed in the left-hand column of every class page Link.base = "../"; publish.classesIndex = classesTemplate.process(classes); // kept in memory - + // create each of the class pages for (var i = 0, l = classes.length; i < l; i++) { var symbol = classes[i]; - - symbol.events = symbol.getEvents(); // 1 order matters + + symbol.events = symbol.getEvents(); // 1 order matters symbol.methods = symbol.getMethods(); // 2 - + Link.currentSymbol= symbol; var output = ""; output = classTemplate.process(symbol); - + IO.saveFile(publish.conf.outDir+"symbols/", ((JSDOC.opt.u)? Link.filemap[symbol.alias] : symbol.alias) + publish.conf.ext, output); } - + // regenerate the index with different relative links, used in the index pages Link.base = ""; publish.classesIndex = classesTemplate.process(classes); - + // create the class index page try { var classesindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"index.tmpl"); } catch(e) { print(e.message); quit(); } - + var classesIndex = classesindexTemplate.process(classes); IO.saveFile(publish.conf.outDir, "index"+publish.conf.ext, classesIndex); classesindexTemplate = classesIndex = classes = null; - + // create the file index page try { var fileindexTemplate = new JSDOC.JsPlate(publish.conf.templatesDir+"allfiles.tmpl"); } catch(e) { print(e.message); quit(); } - + var documentedFiles = symbols.filter(isaFile); // files that have file-level docs var allFiles = []; // not all files have file-level docs, but we need to list every one - + for (var i = 0; i < files.length; i++) { allFiles.push(new JSDOC.Symbol(files[i], [], "FILE", new JSDOC.DocComment("/** */"))); } - + for (var i = 0; i < documentedFiles.length; i++) { var offset = files.indexOf(documentedFiles[i].alias); allFiles[offset] = documentedFiles[i]; } - + allFiles = allFiles.sort(makeSortby("name")); // output the file index page @@ -153,14 +153,14 @@ function include(path) { /** Turn a raw source file into a code-hilited page in the docs. */ function makeSrcFile(path, srcDir, name) { if (JSDOC.opt.s) return; - + if (!name) { name = path.replace(/\.\.?[\\\/]/g, "").replace(/[\\\/]/g, "_"); name = name.replace(/\:/g, "_"); } - + var src = {path: path, name:name, charset: IO.encoding, hilited: ""}; - + if (defined(JSDOC.PluginManager)) { JSDOC.PluginManager.run("onPublishSrc", src); } @@ -196,6 +196,6 @@ function resolveLinks(str, from) { return new Link().toSymbol(symbolName); } ); - + return str; } diff --git a/code/Admin/Admin.js b/code/Admin/Admin.js index 493f515b..2cb77b5e 100644 --- a/code/Admin/Admin.js +++ b/code/Admin/Admin.js @@ -8,7 +8,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -36,49 +36,49 @@ Admin.SITEREMOVALGRACEPERIOD = 14; // days * @constructor */ Admin.Job = function(target, method, user) { - var file; - user || (user = session.user); + var file; + user || (user = session.user); - this.__defineGetter__("target", function() { - return target; - }); + this.__defineGetter__("target", function() { + return target; + }); - this.__defineGetter__("method", function() { - return method; - }); + this.__defineGetter__("method", function() { + return method; + }); - this.__defineGetter__("user", function() { - return user; - }); + this.__defineGetter__("user", function() { + return user; + }); - this.__defineGetter__("name", function() { - return file.getName(); - }); + this.__defineGetter__("name", function() { + return file.getName(); + }); - this.remove = function() { - return file["delete"](); - } + this.remove = function() { + return file["delete"](); + } - if (target && method && user) { - file = new java.io.File.createTempFile("job-", String.EMPTY, Admin.queue.dir); - serialize({type: target._prototype, id: target._id, method: method, user: user._id}, file); - } else if (target) { - file = new java.io.File(Admin.queue.dir, target); - if (file.exists()) { - var data = deserialize(file); - target = global[data.type].getById(data.id); - method = data.method; - user = User.getById(data.user); - } - } else { - throw Error("Insufficient arguments"); - } + if (target && method && user) { + file = new java.io.File.createTempFile("job-", String.EMPTY, Admin.queue.dir); + serialize({type: target._prototype, id: target._id, method: method, user: user._id}, file); + } else if (target) { + file = new java.io.File(Admin.queue.dir, target); + if (file.exists()) { + var data = deserialize(file); + target = global[data.type].getById(data.id); + method = data.method; + user = User.getById(data.user); + } + } else { + throw Error("Insufficient arguments"); + } - this.toString = function() { - return ["[Job: ", method, " ", target, " by ", user, "]"].join(String.EMPTY); - } + this.toString = function() { + return ["[Job: ", method, " ", target, " by ", user, "]"].join(String.EMPTY); + } - return this; + return this; } /** @@ -87,7 +87,7 @@ Admin.Job = function(target, method, user) { * @see defineConstants */ Admin.getNotificationScopes = defineConstants(Admin, markgettext("None"), - markgettext("Trusted"), markgettext("Regular")); + markgettext("Trusted"), markgettext("Regular")); /** * @function @@ -95,8 +95,8 @@ Admin.getNotificationScopes = defineConstants(Admin, markgettext("None"), * @see defineConstants */ Admin.getPhaseOutModes = defineConstants(Admin, markgettext("Disabled"), - markgettext("Restricted"), markgettext("Abandoned"), - markgettext("Both")); + markgettext("Restricted"), markgettext("Abandoned"), + markgettext("Both")); /** * @function @@ -104,7 +104,7 @@ Admin.getPhaseOutModes = defineConstants(Admin, markgettext("Disabled"), * @see defineConstants */ Admin.getCreationScopes = defineConstants(Admin, markgettext("Privileged"), - markgettext("Trusted"), markgettext("Regular")); + markgettext("Trusted"), markgettext("Regular")); /** * Convenience method for easily queueing jobs. @@ -115,8 +115,8 @@ Admin.getCreationScopes = defineConstants(Admin, markgettext("Privileged"), * @see Admin.Job */ Admin.queue = function(target, method, user) { - var job = new Admin.Job(target, method, user || session.user); - return job.name; + var job = new Admin.Job(target, method, user || session.user); + return job.name; } /** @@ -129,251 +129,251 @@ Admin.queue.dir.exists() || Admin.queue.dir.mkdirs(); * */ Admin.dequeue = function() { - var jobs = Admin.queue.dir.list(); - var max = Math.min(jobs.length, 10); - for (let i=0; i Date.ONEDAY * Admin.SITEREMOVALGRACEPERIOD) { - if (this.job) { - return; // Site is already scheduled for deletion - } - let job = new Admin.Job(this, "remove", User.getById(1)); - this.job = job.name; + root.admin.deletedSites.forEach(function() { + if (now - this.deleted > Date.ONEDAY * Admin.SITEREMOVALGRACEPERIOD) { + if (this.job) { + return; // Site is already scheduled for deletion } - }); + let job = new Admin.Job(this, "remove", User.getById(1)); + this.job = job.name; + } + }); - var notificationPeriod = root.phaseOutNotificationPeriod * Date.ONEDAY; - var gracePeriod = root.phaseOutGracePeriod * Date.ONEDAY; + var notificationPeriod = root.phaseOutNotificationPeriod * Date.ONEDAY; + var gracePeriod = root.phaseOutGracePeriod * Date.ONEDAY; - var phaseOutAbandonedSites = function() { - root.forEach(function() { - if (this.status === Site.TRUSTED) { - return; - } - var age = now - (this.stories.size() > 0 ? - this.stories.get(0).modified : this.created); - if (age - notificationPeriod > 0) { - if (!this.notified) { - var site = res.handlers.site = this; - this.members.owners.forEach(function() { - res.handlers.membership = this; - sendMail(this.creator.email, - gettext("[{0}] Warning: Site will be deleted"), - site.renderSkinAsString("$Site#notify_delete")); - }); - this.notified = now; - } else if (now - this.notified > gracePeriod) { - this.mode = Site.DELETED; - this.deleted = now; - this.notified = null; - } - } - }); - return; - } + var phaseOutAbandonedSites = function() { + root.forEach(function() { + if (this.status === Site.TRUSTED) { + return; + } + var age = now - (this.stories.size() > 0 ? + this.stories.get(0).modified : this.created); + if (age - notificationPeriod > 0) { + if (!this.notified) { + var site = res.handlers.site = this; + this.members.owners.forEach(function() { + res.handlers.membership = this; + sendMail(this.creator.email, + gettext("[{0}] Warning: Site will be deleted"), + site.renderSkinAsString("$Site#notify_delete")); + }); + this.notified = now; + } else if (now - this.notified > gracePeriod) { + this.mode = Site.DELETED; + this.deleted = now; + this.notified = null; + } + } + }); + return; + } - var phaseOutRestrictedSites = function() { - root.admin.restrictedSites.forEach(function() { - if (this.status === Site.TRUSTED) { - return; - } - var age = now - this.created; - if (age - notificationPeriod > 0) { - if (!this.notified) { - var site = res.handlers.site = this; - this.members.owners.forEach(function() { - res.handlers.membership = this; - sendMail(this.creator.email, - gettext("[{0}] Warning: Site will be blocked"), - site.renderSkinAsString("$Site#notify_block")); - }); - this.notified = now; - } else if (now - this.notified > gracePeriod) { - this.status = Site.BLOCKED; - this.notified = null; - } - } - }); - return; - } + var phaseOutRestrictedSites = function() { + root.admin.restrictedSites.forEach(function() { + if (this.status === Site.TRUSTED) { + return; + } + var age = now - this.created; + if (age - notificationPeriod > 0) { + if (!this.notified) { + var site = res.handlers.site = this; + this.members.owners.forEach(function() { + res.handlers.membership = this; + sendMail(this.creator.email, + gettext("[{0}] Warning: Site will be blocked"), + site.renderSkinAsString("$Site#notify_block")); + }); + this.notified = now; + } else if (now - this.notified > gracePeriod) { + this.status = Site.BLOCKED; + this.notified = null; + } + } + }); + return; + } - switch (root.phaseOutMode) { - case Admin.ABANDONED: - return phaseOutAbandonedSites(); - case Admin.RESTRICTED: - return phaseOutRestrictedSites(); - case Admin.BOTH: - phaseOutAbandonedSites(); - return phaseOutRestrictedSites(); - } - return; + switch (root.phaseOutMode) { + case Admin.ABANDONED: + return phaseOutAbandonedSites(); + case Admin.RESTRICTED: + return phaseOutRestrictedSites(); + case Admin.BOTH: + phaseOutAbandonedSites(); + return phaseOutRestrictedSites(); + } + return; } /** * */ Admin.purgeReferrers = function() { - var sql = new Sql; - var result = sql.execute(Sql.PURGEREFERRERS); - return result; + var sql = new Sql; + var result = sql.execute(Sql.PURGEREFERRERS); + return result; } /** * */ Admin.commitRequests = function() { - var requests = app.data.requests; - app.data.requests = {}; - for each (var item in requests) { - switch (item.type) { - case Story: - var story = Story.getById(item.id); - story && (story.requests = item.requests); - break; - } - } - res.commit(); - return; + var requests = app.data.requests; + app.data.requests = {}; + for each (var item in requests) { + switch (item.type) { + case Story: + var story = Story.getById(item.id); + story && (story.requests = item.requests); + break; + } + } + res.commit(); + return; } /** * */ Admin.commitEntries = function() { - var entries = app.data.entries; - app.data.entries = []; - var history = []; + var entries = app.data.entries; + app.data.entries = []; + var history = []; - for each (var item in entries) { - var referrer = helma.Http.evalUrl(item.referrer); - if (!referrer) { - continue; + for each (var item in entries) { + var referrer = helma.Http.evalUrl(item.referrer); + if (!referrer) { + continue; + } + + // Only log unique combinations of context, ip and referrer + referrer = String(referrer); + var key = item.context._prototype + "-" + item.context._id + ":" + + item.ip + ":" + referrer; + if (history.indexOf(key) > -1) { + continue; + } + history.push(key); + + // Exclude requests coming from the same site + if (item.site) { + var href = item.site.href().toLowerCase(); + if (href.startsWith("http") && + referrer.toLowerCase().contains(href.substr(0, href.length-1))) { + continue; } + } + item.persist(); + } - // Only log unique combinations of context, ip and referrer - referrer = String(referrer); - var key = item.context._prototype + "-" + item.context._id + ":" + - item.ip + ":" + referrer; - if (history.indexOf(key) > -1) { - continue; - } - history.push(key); - - // Exclude requests coming from the same site - if (item.site) { - var href = item.site.href().toLowerCase(); - if (href.startsWith("http") && - referrer.toLowerCase().contains(href.substr(0, href.length-1))) { - continue; - } - } - item.persist(); - } - - res.commit(); - return; + res.commit(); + return; } /** * */ Admin.invokeCallbacks = function() { - var http = helma.Http(); - http.setTimeout(200); - http.setReadTimeout(300); - http.setMethod("POST"); + var http = helma.Http(); + http.setTimeout(200); + http.setReadTimeout(300); + http.setMethod("POST"); - var ref, site, item; - while (ref = app.data.callbacks.pop()) { - site = Site.getById(ref.site); - item = ref.handler && ref.handler.getById(ref.id); - if (!site || !item) { - continue; - } - app.log("Invoking callback URL " + site.callbackUrl + " for " + item); - try { - http.setContent({ - type: item.constructor.name, - id: item.name || item._id, - url: item.href(), - date: item.modified.valueOf(), - user: item.modifier.name, - site: site.title || site.name, - origin: site.href() - }); - http.getUrl(site.callbackUrl); - } catch (ex) { - app.debug("Invoking callback URL " + site.callbackUrl + " failed: " + ex); - } - } - return; + var ref, site, item; + while (ref = app.data.callbacks.pop()) { + site = Site.getById(ref.site); + item = ref.handler && ref.handler.getById(ref.id); + if (!site || !item) { + continue; + } + app.log("Invoking callback URL " + site.callbackUrl + " for " + item); + try { + http.setContent({ + type: item.constructor.name, + id: item.name || item._id, + url: item.href(), + date: item.modified.valueOf(), + user: item.modifier.name, + site: site.title || site.name, + origin: site.href() + }); + http.getUrl(site.callbackUrl); + } catch (ex) { + app.debug("Invoking callback URL " + site.callbackUrl + " failed: " + ex); + } + } + return; } /** * */ Admin.updateHealth = function() { - var health = Admin.health || {}; - if (!health.modified || new Date - health.modified > 5 * Date.ONEMINUTE) { - health.modified = new Date; - health.requestsPerUnit = app.requestCount - - (health.currentRequestCount || 0); - health.currentRequestCount = app.requestCount; - health.errorsPerUnit = app.errorCount - (health.currentErrorCount || 0); - health.currentErrorCount = app.errorCount; - Admin.health = health; - } - return; + var health = Admin.health || {}; + if (!health.modified || new Date - health.modified > 5 * Date.ONEMINUTE) { + health.modified = new Date; + health.requestsPerUnit = app.requestCount - + (health.currentRequestCount || 0); + health.currentRequestCount = app.requestCount; + health.errorsPerUnit = app.errorCount - (health.currentErrorCount || 0); + health.currentErrorCount = app.errorCount; + Admin.health = health; + } + return; } /** * */ Admin.updateDomains = function() { - res.push(); - for (var key in app.properties) { - if (key.startsWith("domain.") && !key.endsWith("*")) { - res.writeln(getProperty(key) + "\t\t" + key.substr(7)); - } - } - var map = res.pop(); - var file = new java.io.File(app.dir, "domains.map"); - var out = new java.io.BufferedWriter(new java.io.OutputStreamWriter( - new java.io.FileOutputStream(file), "UTF-8")); - out.write(map); - out.close(); - return; + res.push(); + for (var key in app.properties) { + if (key.startsWith("domain.") && !key.endsWith("*")) { + res.writeln(getProperty(key) + "\t\t" + key.substr(7)); + } + } + var map = res.pop(); + var file = new java.io.File(app.dir, "domains.map"); + var out = new java.io.BufferedWriter(new java.io.OutputStreamWriter( + new java.io.FileOutputStream(file), "UTF-8")); + out.write(map); + out.close(); + return; } /** @@ -390,10 +390,10 @@ Admin.updateDomains = function() { * @extends HopObject */ Admin.prototype.constructor = function() { - this.filterSites(); - this.filterUsers(); - this.filterLog(); - return this; + this.filterSites(); + this.filterUsers(); + this.filterLog(); + return this; } /** @@ -402,28 +402,28 @@ Admin.prototype.constructor = function() { * @returns {Boolean} */ Admin.prototype.getPermission = function(action) { - if (!session.user) { + if (!session.user) { + return false; + } + switch (action) { + case "users": + if (req.queryParams.id === session.user._id) { return false; - } - switch (action) { - case "users": - if (req.queryParams.id === session.user._id) { - return false; - } - break; - } - return User.require(User.PRIVILEGED); + } + break; + } + return User.require(User.PRIVILEGED); } /** * */ Admin.prototype.onRequest = function() { - HopObject.prototype.onRequest.apply(this); - if (!session.data.admin) { - session.data.admin = new Admin(); - } - return; + HopObject.prototype.onRequest.apply(this); + if (!session.data.admin) { + session.data.admin = new Admin(); + } + return; } /** @@ -431,32 +431,32 @@ Admin.prototype.onRequest = function() { * @param {String} name */ Admin.prototype.onUnhandledMacro = function(name) { - res.debug("Add " + name + "_macro to Admin!"); - return null; + res.debug("Add " + name + "_macro to Admin!"); + return null; } Admin.prototype.main_action = function() { - return res.redirect(this.href("log")); + return res.redirect(this.href("log")); } Admin.prototype.setup_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - this.log(root, "setup"); - res.message = gettext("Successfully updated the setup."); - res.redirect(this.href(req.action)); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.save) { + try { + this.update(req.postParams); + this.log(root, "setup"); + res.message = gettext("Successfully updated the setup."); + res.redirect(this.href(req.action)); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } - res.data.title = gettext("Setup"); - res.data.action = this.href(req.action); - res.data.body = this.renderSkinAsString("$Admin#setup"); - root.renderSkin("Site#page"); - return; + res.data.title = gettext("Setup"); + res.data.action = this.href(req.action); + res.data.body = this.renderSkinAsString("$Admin#setup"); + root.renderSkin("Site#page"); + return; } /** @@ -464,112 +464,112 @@ Admin.prototype.setup_action = function() { * @param {Object} data */ Admin.prototype.update = function(data) { - root.map({ - creationScope: data.creationScope, - creationDelay: data.creationDelay, - replyTo: data.replyTo, - notificationScope: data.notificationScope, - phaseOutGracePeriod: data.phaseOutGracePeriod, - phaseOutMode: data.phaseOutMode, - phaseOutNotificationPeriod: data.phaseOutNotificationPeriod, - probationPeriod: data.probationPeriod, - quota: data.quota - }); - return; + root.map({ + creationScope: data.creationScope, + creationDelay: data.creationDelay, + replyTo: data.replyTo, + notificationScope: data.notificationScope, + phaseOutGracePeriod: data.phaseOutGracePeriod, + phaseOutMode: data.phaseOutMode, + phaseOutNotificationPeriod: data.phaseOutNotificationPeriod, + probationPeriod: data.probationPeriod, + quota: data.quota + }); + return; } Admin.prototype.jobs_action = function() { - var files = Admin.queue.dir.listFiles(); - for each (var file in files) { - var job = deserialize(file); - res.debug(job.toSource() + " – " + file); - } - return; + var files = Admin.queue.dir.listFiles(); + for each (var file in files) { + var job = deserialize(file); + res.debug(job.toSource() + " – " + file); + } + return; } Admin.prototype.log_action = function() { - if (req.postParams.search || req.postParams.filter) { - session.data.admin.filterLog(req.postParams); - } - res.data.list = renderList(session.data.admin.entries, - this.renderItem, 10, req.queryParams.page); - res.data.pager = renderPager(session.data.admin.entries, - this.href(req.action), 10, req.queryParams.page); + if (req.postParams.search || req.postParams.filter) { + session.data.admin.filterLog(req.postParams); + } + res.data.list = renderList(session.data.admin.entries, + this.renderItem, 10, req.queryParams.page); + res.data.pager = renderPager(session.data.admin.entries, + this.href(req.action), 10, req.queryParams.page); - res.data.title = gettext("Administration Log"); - res.data.action = this.href(req.action); - res.data.body = this.renderSkinAsString("$Admin#log"); - res.data.body += this.renderSkinAsString("$Admin#main"); - root.renderSkin("Site#page"); - return; + res.data.title = gettext("Administration Log"); + res.data.action = this.href(req.action); + res.data.body = this.renderSkinAsString("$Admin#log"); + res.data.body += this.renderSkinAsString("$Admin#main"); + root.renderSkin("Site#page"); + return; } Admin.prototype.sites_action = function() { - if (req.postParams.id) { - if (req.postParams.remove === "1") { - var site = Site.getById(req.postParams.id); - if (site.stories.size() < 1) { - Site.remove.call(site); - res.message = gettext("The site {0} was successfully removed.", site.name); - } else { - site.deleted = new Date; - site.status = Site.BLOCKED; - site.mode = Site.DELETED; - res.message = gettext("The site {0} is queued for removal.", site.name); - } - this.log(root, "Deleted site " + site.name); - res.redirect(this.href(req.action) + "?page=" + req.postParams.page); - } else if (req.postParams.save === "1") { - this.updateSite(req.postParams); - res.message = gettext("The changes were saved successfully."); + if (req.postParams.id) { + if (req.postParams.remove === "1") { + var site = Site.getById(req.postParams.id); + if (site.stories.size() < 1) { + Site.remove.call(site); + res.message = gettext("The site {0} was successfully removed.", site.name); + } else { + site.deleted = new Date; + site.status = Site.BLOCKED; + site.mode = Site.DELETED; + res.message = gettext("The site {0} is queued for removal.", site.name); } - res.redirect(this.href(req.action) + "?page=" + req.postParams.page + - "#" + req.postParams.id); - return; - } + this.log(root, "Deleted site " + site.name); + res.redirect(this.href(req.action) + "?page=" + req.postParams.page); + } else if (req.postParams.save === "1") { + this.updateSite(req.postParams); + res.message = gettext("The changes were saved successfully."); + } + res.redirect(this.href(req.action) + "?page=" + req.postParams.page + + "#" + req.postParams.id); + return; + } - if (req.postParams.search || req.postParams.filter) { - session.data.admin.filterSites(req.postParams); - } else if (req.queryParams.id) { - res.meta.item = Site.getById(req.queryParams.id); - } + if (req.postParams.search || req.postParams.filter) { + session.data.admin.filterSites(req.postParams); + } else if (req.queryParams.id) { + res.meta.item = Site.getById(req.queryParams.id); + } - res.data.list = renderList(session.data.admin.sites, - this.renderItem, 10, req.queryParams.page); - res.data.pager = renderPager(session.data.admin.sites, - this.href(req.action), 10, req.data.page); + res.data.list = renderList(session.data.admin.sites, + this.renderItem, 10, req.queryParams.page); + res.data.pager = renderPager(session.data.admin.sites, + this.href(req.action), 10, req.data.page); - res.data.title = gettext("Site Administration"); - res.data.action = this.href(req.action); - res.data.body = this.renderSkinAsString("$Admin#sites"); - res.data.body += this.renderSkinAsString("$Admin#main"); - root.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Administration"); + res.data.action = this.href(req.action); + res.data.body = this.renderSkinAsString("$Admin#sites"); + res.data.body += this.renderSkinAsString("$Admin#main"); + root.renderSkin("Site#page"); + return; } Admin.prototype.users_action = function() { - if (req.postParams.search || req.postParams.filter) { - session.data.admin.filterUsers(req.postParams); - } else if (req.postParams.save) { - this.updateUser(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this.href(req.action) + "?page=" + req.postParams.page + - "#" + req.postParams.id); - } else if (req.queryParams.id) { - res.meta.item = User.getById(req.queryParams.id); - } + if (req.postParams.search || req.postParams.filter) { + session.data.admin.filterUsers(req.postParams); + } else if (req.postParams.save) { + this.updateUser(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this.href(req.action) + "?page=" + req.postParams.page + + "#" + req.postParams.id); + } else if (req.queryParams.id) { + res.meta.item = User.getById(req.queryParams.id); + } - res.data.list = renderList(session.data.admin.users, - this.renderItem, 10, req.data.page); - res.data.pager = renderPager(session.data.admin.users, - this.href(req.action), 10, req.data.page); + res.data.list = renderList(session.data.admin.users, + this.renderItem, 10, req.data.page); + res.data.pager = renderPager(session.data.admin.users, + this.href(req.action), 10, req.data.page); - res.data.title = gettext("User Administration"); - res.data.action = this.href(req.action); - res.data.body = this.renderSkinAsString("$Admin#users"); - res.data.body += this.renderSkinAsString("$Admin#main"); - root.renderSkin("Site#page"); - return; + res.data.title = gettext("User Administration"); + res.data.action = this.href(req.action); + res.data.body = this.renderSkinAsString("$Admin#users"); + res.data.body += this.renderSkinAsString("$Admin#main"); + root.renderSkin("Site#page"); + return; } /** @@ -577,37 +577,37 @@ Admin.prototype.users_action = function() { * @param {Object} data */ Admin.prototype.filterLog = function(data) { - data || (data = {}); - var sql = ""; - if (data.filter > 0) { - sql += "where context_type = '"; - switch (data.filter) { - case "1": - sql += "Root"; break; - case "2": - sql += "Site"; break; - case "3": - sql += "User"; break; - } - sql += "' and "; - } else { - sql += "where " - } - sql += "action <> 'main' "; - if (data.query) { - var parts = stripTags(data.query).split(" "); - var keyword, like; - for (var i in parts) { - sql += i < 1 ? "and " : "or "; - keyword = parts[i].replace(/\*/g, "%"); - like = keyword.contains("%") ? "like" : "="; - sql += "action " + like + " '" + keyword + "' "; - } - } - sql += "order by created "; - (data.dir == 1) || (sql += "desc"); - this.entries.subnodeRelation = sql; - return; + data || (data = {}); + var sql = ""; + if (data.filter > 0) { + sql += "where context_type = '"; + switch (data.filter) { + case "1": + sql += "Root"; break; + case "2": + sql += "Site"; break; + case "3": + sql += "User"; break; + } + sql += "' and "; + } else { + sql += "where " + } + sql += "action <> 'main' "; + if (data.query) { + var parts = stripTags(data.query).split(" "); + var keyword, like; + for (var i in parts) { + sql += i < 1 ? "and " : "or "; + keyword = parts[i].replace(/\*/g, "%"); + like = keyword.contains("%") ? "like" : "="; + sql += "action " + like + " '" + keyword + "' "; + } + } + sql += "order by created "; + (data.dir == 1) || (sql += "desc"); + this.entries.subnodeRelation = sql; + return; } /** @@ -615,48 +615,48 @@ Admin.prototype.filterLog = function(data) { * @param {Object} data */ Admin.prototype.filterSites = function(data) { - data || (data = {}); - var sql; - switch (data.filter) { - case "1": - sql = "where status = 'blocked' "; break; - case "2": - sql = "where status = 'trusted' "; break; - case "3": - sql = "where mode = 'open' "; break; - case "4": - sql = "where mode = 'restricted' "; break; - case "5": - sql = "where mode = 'public' "; break; - case "6": - sql = "where mode = 'closed' "; break; - case "7": - sql = "where mode = 'deleted' "; break; - case "0": - default: - sql = "where true "; - } - if (data.query) { - var parts = stripTags(data.query).split(" "); - var keyword, like; - for (var i in parts) { - sql += i < 1 ? "and " : "or "; - keyword = parts[i].replace(/\*/g, "%"); - like = keyword.contains("%") ? "like" : "="; - sql += "(name " + like + " '" + keyword + "') "; - } - } - switch (data.order) { - case "1": - sql += "group by created, id order by created "; break; - case "2": - sql += "group by name, id order by name "; break; - default: - sql += "group by modified, id order by modified "; break; - } - (data.dir == 1) || (sql += "desc"); - this.sites.subnodeRelation = sql; - return; + data || (data = {}); + var sql; + switch (data.filter) { + case "1": + sql = "where status = 'blocked' "; break; + case "2": + sql = "where status = 'trusted' "; break; + case "3": + sql = "where mode = 'open' "; break; + case "4": + sql = "where mode = 'restricted' "; break; + case "5": + sql = "where mode = 'public' "; break; + case "6": + sql = "where mode = 'closed' "; break; + case "7": + sql = "where mode = 'deleted' "; break; + case "0": + default: + sql = "where true "; + } + if (data.query) { + var parts = stripTags(data.query).split(" "); + var keyword, like; + for (var i in parts) { + sql += i < 1 ? "and " : "or "; + keyword = parts[i].replace(/\*/g, "%"); + like = keyword.contains("%") ? "like" : "="; + sql += "(name " + like + " '" + keyword + "') "; + } + } + switch (data.order) { + case "1": + sql += "group by created, id order by created "; break; + case "2": + sql += "group by name, id order by name "; break; + default: + sql += "group by modified, id order by modified "; break; + } + (data.dir == 1) || (sql += "desc"); + this.sites.subnodeRelation = sql; + return; } /** @@ -664,44 +664,44 @@ Admin.prototype.filterSites = function(data) { * @param {Object} data */ Admin.prototype.filterUsers = function(data) { - data || (data = {}); - var sql; - switch (data.filter) { - case "1": - sql = "where status = 'blocked' "; break; - case "2": - sql = "where status = 'trusted' "; break; - case "3": - sql = "where status = 'privileged' "; break; - default: - sql = "where true "; break; - } - if (data.query) { - var parts = stripTags(data.query).split(" "); - var keyword, like; - for (var i in parts) { - sql += i < 1 ? "and " : "or "; - keyword = parts[i].replace(/\*/g, "%"); - like = keyword.contains("%") ? "like" : "="; - if (keyword.contains("@")) { - sql += "email " + like + " '" + keyword.replace(/@/g, "") + "' "; - } else { - sql += "name " + like + " '" + keyword + "' "; - } + data || (data = {}); + var sql; + switch (data.filter) { + case "1": + sql = "where status = 'blocked' "; break; + case "2": + sql = "where status = 'trusted' "; break; + case "3": + sql = "where status = 'privileged' "; break; + default: + sql = "where true "; break; + } + if (data.query) { + var parts = stripTags(data.query).split(" "); + var keyword, like; + for (var i in parts) { + sql += i < 1 ? "and " : "or "; + keyword = parts[i].replace(/\*/g, "%"); + like = keyword.contains("%") ? "like" : "="; + if (keyword.contains("@")) { + sql += "email " + like + " '" + keyword.replace(/@/g, "") + "' "; + } else { + sql += "name " + like + " '" + keyword + "' "; } - } - switch (data.order) { - case "0": - default: - sql += "group by created, id order by created "; break; - case "1": - sql += "group by modified, id order by modified "; break; - case "2": - sql += "group by name, id order by name "; break; - } - (data.dir == 1) || (sql += "desc"); - this.users.subnodeRelation = sql; - return; + } + } + switch (data.order) { + case "0": + default: + sql += "group by created, id order by created "; break; + case "1": + sql += "group by modified, id order by modified "; break; + case "2": + sql += "group by name, id order by name "; break; + } + (data.dir == 1) || (sql += "desc"); + this.users.subnodeRelation = sql; + return; } /** @@ -709,16 +709,16 @@ Admin.prototype.filterUsers = function(data) { * @param {Object} data */ Admin.prototype.updateSite = function(data) { - var site = Site.getById(data.id); - if (!site) { - throw Error(gettext("Please choose a site you want to edit.")); - } - if (site.status !== data.status) { - var current = site.status; - site.status = data.status; - this.log(site, "Changed status from " + current + " to " + site.status); - } - return; + var site = Site.getById(data.id); + if (!site) { + throw Error(gettext("Please choose a site you want to edit.")); + } + if (site.status !== data.status) { + var current = site.status; + site.status = data.status; + this.log(site, "Changed status from " + current + " to " + site.status); + } + return; } /** @@ -726,19 +726,19 @@ Admin.prototype.updateSite = function(data) { * @param {Object} data */ Admin.prototype.updateUser = function(data) { - var user = User.getById(data.id); - if (!user) { - throw Error(gettext("Please choose a user you want to edit.")); - } - if (user === session.user) { - throw Error(gettext("Sorry, you are not allowed to modify your own account.")); - } - if (data.status !== user.status) { - var current = user.status; - user.status = data.status; - this.log(user, "Changed status from " + current + " to " + data.status); - } - return; + var user = User.getById(data.id); + if (!user) { + throw Error(gettext("Please choose a user you want to edit.")); + } + if (user === session.user) { + throw Error(gettext("Sorry, you are not allowed to modify your own account.")); + } + if (data.status !== user.status) { + var current = user.status; + user.status = data.status; + this.log(user, "Changed status from " + current + " to " + data.status); + } + return; } /** @@ -746,15 +746,15 @@ Admin.prototype.updateUser = function(data) { * @param {HopObject} item */ Admin.prototype.renderItem = function(item) { - res.handlers.item = item; - var name = item._prototype; - (name === "Root") && (name = "Site"); - Admin.prototype.renderSkin("$Admin#" + name); - if (item === res.meta.item) { - Admin.prototype.renderSkin((req.data.action === "delete" ? - "$Admin#delete" : "$Admin#edit") + name); - } - return; + res.handlers.item = item; + var name = item._prototype; + (name === "Root") && (name = "Site"); + Admin.prototype.renderSkin("$Admin#" + name); + if (item === res.meta.item) { + Admin.prototype.renderSkin((req.data.action === "delete" ? + "$Admin#delete" : "$Admin#edit") + name); + } + return; } /** @@ -763,9 +763,9 @@ Admin.prototype.renderItem = function(item) { * @param {String} action */ Admin.prototype.log = function(context, action) { - var entry = new LogEntry(context, action); - this.entries.add(entry); - return; + var entry = new LogEntry(context, action); + this.entries.add(entry); + return; } /** @@ -776,27 +776,27 @@ Admin.prototype.log = function(context, action) { * @param {String} text */ Admin.prototype.link_macro = function(param, action, text, id) { - switch (action) { - case "main": - action = "."; - case "delete": - case "edit": - if (id) { - if (req.action === "users" && (id === session.user._id)) { - return; - } - if (req.action === "sites" && (id === root._id)) { - return; - } - action = req.action + "?action=" + action + "&id=" + id; - if (req.queryParams.page) { - action += "&page=" + req.queryParams.page; - } - action += "#" + id; + switch (action) { + case "main": + action = "."; + case "delete": + case "edit": + if (id) { + if (req.action === "users" && (id === session.user._id)) { + return; } - break; - } - return HopObject.prototype.link_macro.call(this, param, action, text); + if (req.action === "sites" && (id === root._id)) { + return; + } + action = req.action + "?action=" + action + "&id=" + id; + if (req.queryParams.page) { + action += "&page=" + req.queryParams.page; + } + action += "#" + id; + } + break; + } + return HopObject.prototype.link_macro.call(this, param, action, text); } /** @@ -805,10 +805,10 @@ Admin.prototype.link_macro = function(param, action, text, id) { * @param {HopObject} object */ Admin.prototype.count_macro = function(param, object) { - if (object && object.size) { - res.write(object.size()); - } - return; + if (object && object.size) { + res.write(object.size()); + } + return; } /** @@ -817,10 +817,10 @@ Admin.prototype.count_macro = function(param, object) { * @param {String} name */ Admin.prototype.skin_macro = function(param, name) { - if (this.getPermission("main")) { - return HopObject.prototype.skin_macro.apply(this, arguments); - } - return; + if (this.getPermission("main")) { + return HopObject.prototype.skin_macro.apply(this, arguments); + } + return; } /** @@ -830,14 +830,14 @@ Admin.prototype.skin_macro = function(param, name) { * @param {String} name */ Admin.prototype.items_macro = function(param, object, name) { - if (!object || !object.size) { - return; - } - var max = Math.min(object.size(), parseInt(param.limit) || 10); - for (var i=0; i")) { + content && (content = content.trim()); + content || (content = String.EMPTY); + var result = {}; + if (!content.startsWith("")) { + result.text = content; + } else { + var pos = content.lastIndexOf(""); + if (pos > 0) { + result.title = content.substring(7, pos); + result.text = content.substring (pos + 8); + } else { result.text = content; - } else { - var pos = content.lastIndexOf(""); - if (pos > 0) { - result.title = content.substring(7, pos); - result.text = content.substring (pos + 8); - } else { - result.text = content; - } - } - return result; + } + } + return result; } /** @@ -63,15 +63,15 @@ Api.blogger._getContentParts = function(content) { * @returns {Object} Properties: userid, nickname and url */ Api.blogger.getUserInfo = function(appKey, name, password) { - var user = User.getByName(name); - if (!user) { - throw Error("User " + name + " does not exist on this server"); - } - return { - userid: name, - nickname: name, - url: user.url - } + var user = User.getByName(name); + if (!user) { + throw Error("User " + name + " does not exist on this server"); + } + return { + userid: name, + nickname: name, + url: user.url + } } /** @@ -83,20 +83,20 @@ Api.blogger.getUserInfo = function(appKey, name, password) { * url */ Api.blogger.getUsersBlogs = function(appKey, name, password) { - var user = Api.getUser(name, password); - var result = []; - user.forEach(function() { - Api.constrain(this.site, user); - if (this.site.stories.getPermission("create")) { - result.push({ - blogid: this.site.name, - blogName: this.site.title, - url: this.site.href() - }); - } - return; - }); - return result; + var user = Api.getUser(name, password); + var result = []; + user.forEach(function() { + Api.constrain(this.site, user); + if (this.site.stories.getPermission("create")) { + result.push({ + blogid: this.site.name, + blogName: this.site.title, + url: this.site.href() + }); + } + return; + }); + return result; } /** @@ -111,28 +111,28 @@ Api.blogger.getUsersBlogs = function(appKey, name, password) { * dateCreated and content */ Api.blogger.getRecentPosts = function(appKey, id, name, password, limit) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("main")) { - throw Error("Permission denied for user " + user.name + - " to get recent posts of site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("main")) { + throw Error("Permission denied for user " + user.name + + " to get recent posts of site " + site.name); + } - var result = []; - var stories = res.handlers.membership.stories; - var max = Math.min(stories.size(), Number(limit) || Infinity, 20); - for each (var story in stories.list(0, max)) { - result.push({ - postid: story._id, - userid: story.creator.name, - dateCreated: story.created, - content: story.title ? "" + story.title + - "" + story.text : story.text - }); - } - return result; + var result = []; + var stories = res.handlers.membership.stories; + var max = Math.min(stories.size(), Number(limit) || Infinity, 20); + for each (var story in stories.list(0, max)) { + result.push({ + postid: story._id, + userid: story.creator.name, + dateCreated: story.created, + content: story.title ? "" + story.title + + "" + story.text : story.text + }); + } + return result; } /** @@ -145,22 +145,22 @@ Api.blogger.getRecentPosts = function(appKey, id, name, password, limit) { * @returns {Object} Properties: content, userid, postid, dateCreated */ Api.blogger.getPost = function(appKey, id, name, password) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("main")) { - throw Error("Permission denied for user " + name + - " to get post #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("main")) { + throw Error("Permission denied for user " + name + + " to get post #" + id); + } - return { - content: story.title ? html.elementAsString("title", story.title) + - story.text : story.text, - userid: story.creator.name, - postid: story._id, - dateCreated: story.created - } + return { + content: story.title ? html.elementAsString("title", story.title) + + story.text : story.text, + userid: story.creator.name, + postid: story._id, + dateCreated: story.created + } } /** @@ -175,25 +175,25 @@ Api.blogger.getPost = function(appKey, id, name, password) { * @returns {Number} The ID of the new story */ Api.blogger.newPost = function(appKey, id, name, password, content, publish) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("create")) { - throw Error("Permission denied for user " + user.name + - " to add a post to site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("create")) { + throw Error("Permission denied for user " + user.name + + " to add a post to site " + site.name); + } - var parts = Api.blogger._getContentParts(content); + var parts = Api.blogger._getContentParts(content); - var story = Story.add({ - title: parts.title, - text: parts.text, - status: publish ? Story.PUBLIC : Story.CLOSED, - mode: Story.FEATURED - }, site, user); + var story = Story.add({ + title: parts.title, + text: parts.text, + status: publish ? Story.PUBLIC : Story.CLOSED, + mode: Story.FEATURED + }, site, user); - return story._id; + return story._id; } /** @@ -208,24 +208,24 @@ Api.blogger.newPost = function(appKey, id, name, password, content, publish) { * @returns {Boolean} Always true */ Api.blogger.editPost = function(appkey, id, name, password, content, publish) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("edit")) { - throw Error("Permission denied for user " + name + - " to edit post #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("edit")) { + throw Error("Permission denied for user " + name + + " to edit post #" + id); + } - var parts = Api.blogger._getContentParts(content); - story.update({ - title: parts.title, - text: parts.text, - status: publish ? Story.PUBLIC : Story.CLOSED, - modifier: user, - modified: new Date - }); - return true; + var parts = Api.blogger._getContentParts(content); + story.update({ + title: parts.title, + text: parts.text, + status: publish ? Story.PUBLIC : Story.CLOSED, + modifier: user, + modified: new Date + }); + return true; } /** @@ -238,15 +238,15 @@ Api.blogger.editPost = function(appkey, id, name, password, content, publish) { * @returns {Boolean} Always true */ Api.blogger.deletePost = function(appKey, id, name, password) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("delete")) { - throw Error("Permission denied for user " + name + - " to delete story #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("delete")) { + throw Error("Permission denied for user " + name + + " to delete story #" + id); + } - Story.remove.call(story); - return true; + Story.remove.call(story); + return true; } diff --git a/code/Api/Api.js b/code/Api/Api.js index 4c501dd4..cafd081c 100644 --- a/code/Api/Api.js +++ b/code/Api/Api.js @@ -8,7 +8,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -32,9 +32,9 @@ * @param {User} user */ Api.constrain = function(site, user) { - res.handlers.site = site; - res.handlers.membership = Membership.getByName(user.name); - return; + res.handlers.site = site; + res.handlers.membership = Membership.getByName(user.name); + return; } /** @ignore */ @@ -49,16 +49,16 @@ Api.dispatch = function() { * @returns {User} */ Api.getUser = function(name, password) { - var user = User.getByName(name); - if (!user) { - throw Error("User " + name + " does not exist on this server"); - } else if (user.hash !== String(password + user.salt).md5()) { - throw Error("Authentication failed for user " + name); - } else if (user.status === User.BLOCKED) { - throw Error("The user account " + name + " is currently blocked"); - } - session.login(user); - return user; + var user = User.getByName(name); + if (!user) { + throw Error("User " + name + " does not exist on this server"); + } else if (user.hash !== String(password + user.salt).md5()) { + throw Error("Authentication failed for user " + name); + } else if (user.status === User.BLOCKED) { + throw Error("The user account " + name + " is currently blocked"); + } + session.login(user); + return user; } /** @@ -68,13 +68,13 @@ Api.getUser = function(name, password) { * @returns {Site} */ Api.getSite = function(name) { - var site = Site.getByName(String(name)); - if (!site) { - throw Error("Site " + name + " does not exist on this server"); - } else if (site.status === Site.BLOCKED) { - throw Error("The site " + name + " is blocked"); - } - return site; + var site = Site.getByName(String(name)); + if (!site) { + throw Error("Site " + name + " does not exist on this server"); + } else if (site.status === Site.BLOCKED) { + throw Error("The site " + name + " is blocked"); + } + return site; } /** @@ -84,11 +84,11 @@ Api.getSite = function(name) { * @returns {Story} */ Api.getStory = function(id) { - var story = Story.getById(id); - if (!story) { - throw Error("Story #" + id + " does not exist on this server"); - } - return story; + var story = Story.getById(id); + if (!story) { + throw Error("Story #" + id + " does not exist on this server"); + } + return story; } /** @@ -101,42 +101,42 @@ Api.getStory = function(id) { * @returns {Boolean} */ Api.prototype.getPermission = function(){ - return true; + return true; } Api.prototype.main_action = function() { - res.data.title = gettext("Application Programming Interfaces"); - res.data.body = this.renderSkinAsString("$Api#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Application Programming Interfaces"); + res.data.body = this.renderSkinAsString("$Api#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Api.prototype.callback_action = function() { - var ping = function(data) { - if (data.type !== "Story" && data.type !== "Comment") { - return; - } - var remote = new Remote("http://rpc.weblogs.com/RPC2"); - var call = remote.weblogUpdates.ping(data.site, data.origin); - if (call.error || call.result.flerror) { - app.debug("Error invoking weblogs.com ping() method for " + - data.site + ": " + call.error || call.result.message); - } else { - app.debug(call.result); - } + var ping = function(data) { + if (data.type !== "Story" && data.type !== "Comment") { return; - }; + } + var remote = new Remote("http://rpc.weblogs.com/RPC2"); + var call = remote.weblogUpdates.ping(data.site, data.origin); + if (call.error || call.result.flerror) { + app.debug("Error invoking weblogs.com ping() method for " + + data.site + ": " + call.error || call.result.message); + } else { + app.debug(call.result); + } + return; + }; - if (req.isGet()) { - res.data.title = gettext("Default Callback Url"); - res.data.body = this.renderSkinAsString("$Api#callback", - {name: req.action, code: ping.toString()}); - res.handlers.site.renderSkin("Site#page"); - } else if (req.isPost()) { - app.debug("Invoked default callback with POST params: " + req.postParams); - app.invokeAsync(this, ping, [req.postParams], 1000); - } - return; + if (req.isGet()) { + res.data.title = gettext("Default Callback Url"); + res.data.body = this.renderSkinAsString("$Api#callback", + {name: req.action, code: ping.toString()}); + res.handlers.site.renderSkin("Site#page"); + } else if (req.isPost()) { + app.debug("Invoked default callback with POST params: " + req.postParams); + app.invokeAsync(this, ping, [req.postParams], 1000); + } + return; } /** @@ -145,18 +145,18 @@ Api.prototype.callback_action = function() { * @throws {Error} */ Api.prototype.main_action_xmlrpc = function(methodName) { - if (!methodName) { - return false; - } - var parts = methodName.split("."); - var method = parts[1]; - if (method && !method.startsWith("_")) { - var handler = Api[parts[0]]; - if (handler && handler[method]) { - var args = Array.prototype.splice.call(arguments, 1); - return handler[method].apply(null, args); - } - } - throw Error("Method " + methodName + "() is not implemented"); - return; + if (!methodName) { + return false; + } + var parts = methodName.split("."); + var method = parts[1]; + if (method && !method.startsWith("_")) { + var handler = Api[parts[0]]; + if (handler && handler[method]) { + var args = Array.prototype.splice.call(arguments, 1); + return handler[method].apply(null, args); + } + } + throw Error("Method " + methodName + "() is not implemented"); + return; } diff --git a/code/Api/Api.metaWeblog.js b/code/Api/Api.metaWeblog.js index 648e1c2e..fc1e98ed 100644 --- a/code/Api/Api.metaWeblog.js +++ b/code/Api/Api.metaWeblog.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -36,24 +36,24 @@ Api.metaWeblog = {} * @returns {Object} */ Api.metaWeblog._getStruct = function(story) { - return { - userid: story.creator.name, - postid: story._id, - dateCreated: story.created, - title: story.getTitle(), - description: story.text, - categories: story.getTags(), - flNotOnHomePage: story.mode === Story.HIDDEN ? true : false, - link: story.href(), - permaLink: story.href(), - mt_excerpt: null, // FIXME: What are these "mt_" prefixed properties? - mt_text_more: null, - mt_allow_comments: story.commentMode === Story.OPEN ? 1 : 0, - mt_allow_pings: 0, - mt_convert_breaks: null, - mt_keywords: null, - postSource: story.getMetadata('postSource') - } + return { + userid: story.creator.name, + postid: story._id, + dateCreated: story.created, + title: story.getTitle(), + description: story.text, + categories: story.getTags(), + flNotOnHomePage: story.mode === Story.HIDDEN ? true : false, + link: story.href(), + permaLink: story.href(), + mt_excerpt: null, // FIXME: What are these "mt_" prefixed properties? + mt_text_more: null, + mt_allow_comments: story.commentMode === Story.OPEN ? 1 : 0, + mt_allow_pings: 0, + mt_convert_breaks: null, + mt_keywords: null, + postSource: story.getMetadata('postSource') + } } /** @@ -66,22 +66,22 @@ Api.metaWeblog._getStruct = function(story) { * @returns {Object[]} */ Api.metaWeblog.getRecentPosts = function(id, name, password, limit) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("main")) { - throw Error("Permission denied for user " + user.name + - " to get recent posts from site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("main")) { + throw Error("Permission denied for user " + user.name + + " to get recent posts from site " + site.name); + } - var result = []; - var stories = res.handlers.membership.stories; - var max = Math.min(stories.size(), Number(limit) || Infinity, 20); - for each (var story in stories.list(0, max)) { - result.push(Api.metaWeblog._getStruct(story)); - } - return result; + var result = []; + var stories = res.handlers.membership.stories; + var max = Math.min(stories.size(), Number(limit) || Infinity, 20); + for each (var story in stories.list(0, max)) { + result.push(Api.metaWeblog._getStruct(story)); + } + return result; } /** @@ -93,14 +93,14 @@ Api.metaWeblog.getRecentPosts = function(id, name, password, limit) { * @returns {Object} */ Api.metaWeblog.getPost = function(id, name, password) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("main")) { - throw Error("Permission denied for user " + name + - " to get post #" + id); - } - return Api.metaWeblog._getStruct(story); + var story = Api.getStory(id); + var user = Api.getUser(name, password); + Api.constrain(story.site, user); + if (!story.getPermission("main")) { + throw Error("Permission denied for user " + name + + " to get post #" + id); + } + return Api.metaWeblog._getStruct(story); } /** @@ -114,26 +114,26 @@ Api.metaWeblog.getPost = function(id, name, password) { * @returns {Number} */ Api.metaWeblog.newPost = function(id, name, password, content, publish) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("create")) { - throw Error("Permission denied for user " + user.name + - " to add a post to site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("create")) { + throw Error("Permission denied for user " + user.name + + " to add a post to site " + site.name); + } - var story = Story.add({ - title: content.title, - text: content.description, - status: publish ? Story.PUBLIC : Story.CLOSED, - mode: content.flNotOnHomePage ? Story.HIDDEN : Story.FEATURED, - commentMode: content.discussions === 0 ? Story.CLOSED : Story.OPEN, - tags: content.categories - }, site, user); + var story = Story.add({ + title: content.title, + text: content.description, + status: publish ? Story.PUBLIC : Story.CLOSED, + mode: content.flNotOnHomePage ? Story.HIDDEN : Story.FEATURED, + commentMode: content.discussions === 0 ? Story.CLOSED : Story.OPEN, + tags: content.categories + }, site, user); - story.setMetadata('postSource', content.postSource); - return story._id; + story.setMetadata('postSource', content.postSource); + return story._id; } /** @@ -147,27 +147,27 @@ Api.metaWeblog.newPost = function(id, name, password, content, publish) { * @returns {Boolean} */ Api.metaWeblog.editPost = function(id, name, password, content, publish) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("edit")) { - throw Error("Permission denied for user " + name + - " to edit post #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("edit")) { + throw Error("Permission denied for user " + name + + " to edit post #" + id); + } - story.update({ - title: content.title, - text: content.description, - status: publish ? Story.PUBLIC : Story.CLOSED, - mode: content.flNotOnHomePage ? Story.HIDDEN : Story.FEATURED, - commentMode: content.discussions || content.mt_allow_comments ? - Story.OPEN : Story.CLOSED, - tags: content.categories - }); + story.update({ + title: content.title, + text: content.description, + status: publish ? Story.PUBLIC : Story.CLOSED, + mode: content.flNotOnHomePage ? Story.HIDDEN : Story.FEATURED, + commentMode: content.discussions || content.mt_allow_comments ? + Story.OPEN : Story.CLOSED, + tags: content.categories + }); - story.setMetadata('postSource', content.postSource); - return true; + story.setMetadata('postSource', content.postSource); + return true; } /** @@ -179,25 +179,25 @@ Api.metaWeblog.editPost = function(id, name, password, content, publish) { * @returns {Object[]} */ Api.metaWeblog.getCategories = function(id, name, password) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("main")) { - throw Error("Permission denied for user " + user.name + - " to get categories from site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("main")) { + throw Error("Permission denied for user " + user.name + + " to get categories from site " + site.name); + } - var result = []; - var tags = site.getTags("tags", Tags.ALL).list(); - for each (var tag in tags) { - result.push({ - description: tag.name, - htmlUrl: tag.href(), - rssUrl: tag.href("rss") - }); - } - return result; + var result = []; + var tags = site.getTags("tags", Tags.ALL).list(); + for each (var tag in tags) { + result.push({ + description: tag.name, + htmlUrl: tag.href(), + rssUrl: tag.href("rss") + }); + } + return result; } /** @@ -210,40 +210,40 @@ Api.metaWeblog.getCategories = function(id, name, password) { * @returns {Object} */ Api.metaWeblog.newMediaObject = function(id, name, password, media) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); + Api.constrain(site, user); - var result = {}; - var data = {}; - if (media.type && media.type.toLowerCase().startsWith("image/")) { - if (!site.images.getPermission("create")) { - throw Error("Permission denied for user " + user.name + - " to add a media object to site " + site.name); - } - data.file = new Packages.helma.util.MimePart(media.name, - media.bits, media.type); - data.file_origin = media.name; - data.description = media.description; - if (media.maxWidth) { - data.maxWidth = media.maxWidth; - } - if (media.maxHeight) { - data.maxHeight = media.maxHeight; - } - result.url = Image.add(data, site, user).getUrl(); - } else { - if (!site.files.getPermission("create")) { - throw Error("Permission denied for user " + user.name + - " to add a media object to site " + site.name); - } - data.file = new Packages.helma.util.MimePart(media.name, - media.bits, media.type); - data.file_origin = media.name; - data.description = media.description; - result.url = File.add(data, site, user).getUrl(); - } + var result = {}; + var data = {}; + if (media.type && media.type.toLowerCase().startsWith("image/")) { + if (!site.images.getPermission("create")) { + throw Error("Permission denied for user " + user.name + + " to add a media object to site " + site.name); + } + data.file = new Packages.helma.util.MimePart(media.name, + media.bits, media.type); + data.file_origin = media.name; + data.description = media.description; + if (media.maxWidth) { + data.maxWidth = media.maxWidth; + } + if (media.maxHeight) { + data.maxHeight = media.maxHeight; + } + result.url = Image.add(data, site, user).getUrl(); + } else { + if (!site.files.getPermission("create")) { + throw Error("Permission denied for user " + user.name + + " to add a media object to site " + site.name); + } + data.file = new Packages.helma.util.MimePart(media.name, + media.bits, media.type); + data.file_origin = media.name; + data.description = media.description; + result.url = File.add(data, site, user).getUrl(); + } - return result; + return result; } diff --git a/code/Api/Api.mt.js b/code/Api/Api.mt.js index ed45bf97..ed4a4355 100644 --- a/code/Api/Api.mt.js +++ b/code/Api/Api.mt.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -41,27 +41,27 @@ Api.mt = {}; * @returns {Object[]} */ Api.mt.getRecentPostTitles = function(id, name, password, limit) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("main")) { - throw Error("Permission denied for user " + user.name + - " to get recent post titles from site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("main")) { + throw Error("Permission denied for user " + user.name + + " to get recent post titles from site " + site.name); + } - var result = []; - var stories = res.handlers.membership.stories; - var max = Math.min(stories.size(), Number(limit) || Infinity, 20); - for each (var story in stories.list(0, max)) { - result.push({ - postid: story._id, - username: story.creator.name, - dateCreated: story.created, - title: story.getTitle() - }); - } - return result; + var result = []; + var stories = res.handlers.membership.stories; + var max = Math.min(stories.size(), Number(limit) || Infinity, 20); + for each (var story in stories.list(0, max)) { + result.push({ + postid: story._id, + username: story.creator.name, + dateCreated: story.created, + title: story.getTitle() + }); + } + return result; } /** @@ -73,24 +73,24 @@ Api.mt.getRecentPostTitles = function(id, name, password, limit) { * @returns {Object[]} */ Api.mt.getCategoryList = function(id, name, password) { - var site = Api.getSite(id); - var user = Api.getUser(name, password); + var site = Api.getSite(id); + var user = Api.getUser(name, password); - Api.constrain(site, user); - if (!site.stories.getPermission("main")) { - throw Error("Permission denied for user " + user.name + - " to access site " + site.name); - } + Api.constrain(site, user); + if (!site.stories.getPermission("main")) { + throw Error("Permission denied for user " + user.name + + " to access site " + site.name); + } - var result = []; - var tags = site.getTags("tags", Tags.ALL).list(); - for each (var tag in tags) { - result.push({ - categoryId: tag.name, // FIXME: tag._id, - categoryName: tag.name - }); - } - return result; + var result = []; + var tags = site.getTags("tags", Tags.ALL).list(); + for each (var tag in tags) { + result.push({ + categoryId: tag.name, // FIXME: tag._id, + categoryName: tag.name + }); + } + return result; } /** @@ -102,24 +102,24 @@ Api.mt.getCategoryList = function(id, name, password) { * @returns {Object[]} */ Api.mt.getPostCategories = function(id, name, password) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("main")) { - throw Error("Permission denied for user " + name + - " to access story #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("main")) { + throw Error("Permission denied for user " + name + + " to access story #" + id); + } - var result = []; - for each (var tag in story.getTags()) { - result.push({ - categoryId: tag, - categoryName: tag, - isPrimary: true - }); - } - return result; + var result = []; + for each (var tag in story.getTags()) { + result.push({ + categoryId: tag, + categoryName: tag, + isPrimary: true + }); + } + return result; } // FIXME: How do I post a new story? @@ -132,17 +132,17 @@ Api.mt.getPostCategories = function(id, name, password) { * @returns {Boolean} */ Api.mt.publishPost = function(id, name, password) { - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("edit")) { - throw Error("Permission denied for user " + name + - " to edit story #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("edit")) { + throw Error("Permission denied for user " + name + + " to edit story #" + id); + } - story.mode = Story.FEATURED; - return true; + story.mode = Story.FEATURED; + return true; } /** @@ -155,21 +155,21 @@ Api.mt.publishPost = function(id, name, password) { * @returns {Boolean} */ Api.mt.setPostCategories = function(id, name, password, categories) { - if (!categories || !categories.length) { - return; - } + if (!categories || !categories.length) { + return; + } - var story = Api.getStory(id); - var user = Api.getUser(name, password); + var story = Api.getStory(id); + var user = Api.getUser(name, password); - Api.constrain(story.site, user); - if (!story.getPermission("edit")) { - throw Error("Permission denied for user " + name + - " to edit story #" + id); - } + Api.constrain(story.site, user); + if (!story.getPermission("edit")) { + throw Error("Permission denied for user " + name + + " to edit story #" + id); + } - story.setTags(categories); - return true; + story.setTags(categories); + return true; } /** @@ -177,7 +177,7 @@ Api.mt.setPostCategories = function(id, name, password, categories) { * @returns {Array} */ Api.mt.supportedTextFilters = function() { - return []; + return []; } /** @@ -185,7 +185,7 @@ Api.mt.supportedTextFilters = function() { * @returns {Array} */ Api.mt.getTrackbackPings = function() { - return []; + return []; } /** @@ -193,9 +193,9 @@ Api.mt.getTrackbackPings = function() { * @returns {String[]} */ Api.mt.supportedMethods = function() { - var result = []; - for (var method in Api.mt) { - result.push(method); - } - return result.sort(); + var result = []; + for (var method in Api.mt) { + result.push(method); + } + return result.sort(); } diff --git a/code/Archive/Archive.js b/code/Archive/Archive.js index ea8e14b4..2884e17b 100644 --- a/code/Archive/Archive.js +++ b/code/Archive/Archive.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -43,10 +43,10 @@ Archive.COLLECTION = "collection"; * @extends HopObject */ Archive.prototype.constructor = function(name, type, parent) { - this.name = name; - this.type = type; - this.parent = parent; - return this; + this.name = name; + this.type = type; + this.parent = parent; + return this; } /** @@ -55,12 +55,12 @@ Archive.prototype.constructor = function(name, type, parent) { * @returns {HopObject} */ Archive.prototype.getChildElement = function(name) { - if (name.startsWith(Archive.PAGER)) { - return new Archive(name, Archive.PAGER, this); - } else if (!isNaN(name)) { - return new Archive(name, Archive.COLLECTION, this); - } - return this.get(name); + if (name.startsWith(Archive.PAGER)) { + return new Archive(name, Archive.PAGER, this); + } else if (!isNaN(name)) { + return new Archive(name, Archive.COLLECTION, this); + } + return this.get(name); } /** @@ -69,50 +69,50 @@ Archive.prototype.getChildElement = function(name) { * @returns {Boolean} */ Archive.prototype.getPermission = function(action) { - var site = res.handlers.site; - if (!site.getPermission("main") || site.archiveMode !== Site.PUBLIC) { - return false; - } - switch (action) { - case "main": - case "page1": - return true; - case "previous": - return this.getPage() > 1 - case "next": - return this.getPage() < this.getSize() / this.getPageSize(); - } - return false; + var site = res.handlers.site; + if (!site.getPermission("main") || site.archiveMode !== Site.PUBLIC) { + return false; + } + switch (action) { + case "main": + case "page1": + return true; + case "previous": + return this.getPage() > 1 + case "next": + return this.getPage() < this.getSize() / this.getPageSize(); + } + return false; } Archive.prototype.main_action = function() { - var date = this.getDate(); - var dateString = String.EMPTY; - switch (path.length - (this.type === Archive.PAGER ? 4 : 3)) { - case 1: - dateString = formatDate(date, "yyyy"); - break; - case 2: - dateString = formatDate(date, "MMM yyyy"); - break; - case 3: - var type = java.text.DateFormat.LONG; - var locale = res.handlers.site.getLocale(); - var pattern = java.text.DateFormat.getDateInstance(type, locale).toPattern() - dateString = formatDate(date, pattern); - break; - } - var page = gettext("Page {0} of {1}", this.getPage(), - Math.ceil(this.getSize() / this.getPageSize())); - res.data.title = gettext("Story Archive {0} ({1})", dateString, page); - res.data.body = this.renderSkinAsString("Archive#main"); - res.handlers.site.renderSkin("Site#page"); - res.handlers.site.log(); - return; + var date = this.getDate(); + var dateString = String.EMPTY; + switch (path.length - (this.type === Archive.PAGER ? 4 : 3)) { + case 1: + dateString = formatDate(date, "yyyy"); + break; + case 2: + dateString = formatDate(date, "MMM yyyy"); + break; + case 3: + var type = java.text.DateFormat.LONG; + var locale = res.handlers.site.getLocale(); + var pattern = java.text.DateFormat.getDateInstance(type, locale).toPattern() + dateString = formatDate(date, pattern); + break; + } + var page = gettext("Page {0} of {1}", this.getPage(), + Math.ceil(this.getSize() / this.getPageSize())); + res.data.title = gettext("Story Archive {0} ({1})", dateString, page); + res.data.body = this.renderSkinAsString("Archive#main"); + res.handlers.site.renderSkin("Site#page"); + res.handlers.site.log(); + return; } Archive.prototype.page1_action = function() { - return res.redirect(this.href()); + return res.redirect(this.href()); } /** @@ -121,21 +121,21 @@ Archive.prototype.page1_action = function() { * @returns {String} */ Archive.prototype.href = function(action) { - var buffer = []; - var archive = this; - while (archive.parent) { - buffer.push(archive.name); - archive = archive.parent; - } - buffer.push(res.handlers.site.href("archive")); - buffer.reverse(); - if (action) { - if (this.type === Archive.PAGER) { - buffer.pop(); - } - buffer.push(action); - } - return buffer.join("/"); + var buffer = []; + var archive = this; + while (archive.parent) { + buffer.push(archive.name); + archive = archive.parent; + } + buffer.push(res.handlers.site.href("archive")); + buffer.reverse(); + if (action) { + if (this.type === Archive.PAGER) { + buffer.pop(); + } + buffer.push(action); + } + return buffer.join("/"); } /** @@ -146,76 +146,76 @@ Archive.prototype.href = function(action) { * @see renderLink */ Archive.prototype.link_macro = function(param, action, text) { - if (!this.getPermission(action)) { - return; - } - switch (action) { - case "previous": - var page = this.getPage() - 1; break; - case "next": - var page = this.getPage() + 1; break; - } - var action = "page" + page; - return renderLink.call(global, param, action, text, this); + if (!this.getPermission(action)) { + return; + } + switch (action) { + case "previous": + var page = this.getPage() - 1; break; + case "next": + var page = this.getPage() + 1; break; + } + var action = "page" + page; + return renderLink.call(global, param, action, text, this); } /** * */ Archive.prototype.stories_macro = function() { - var day, storyDay; - var page = this.getPage(); - var pageSize = this.getPageSize(); + var day, storyDay; + var page = this.getPage(); + var pageSize = this.getPageSize(); - var renderStory = function(story) { - storyDay = formatDate(story.created, 'yyyy-MM-dd'); - if (day !== storyDay) { - story.renderSkin("Story#date"); - day = storyDay; - } - story.renderSkin("Story#preview"); - return; - } + var renderStory = function(story) { + storyDay = formatDate(story.created, 'yyyy-MM-dd'); + if (day !== storyDay) { + story.renderSkin("Story#date"); + day = storyDay; + } + story.renderSkin("Story#preview"); + return; + } - // FIXME: This is a little bit inconsistent and thus needs special care - var archive = this.type === Archive.PAGER ? this.parent : this; - if (!archive.parent) { - var site = res.handlers.site; - var offset = (page - 1) * pageSize; - var stories = site.stories.featured.list(offset, pageSize); - for each (var story in stories) { - renderStory(story); - }; - return; - } - - var sql = new Sql; - sql.retrieve(Sql.ARCHIVE, res.handlers.site._id, this.getFilter(), - Sql.ARCHIVEORDER, pageSize, (page - 1) * pageSize); - sql.traverse(function() { - var story = Story.getById(this.id); + // FIXME: This is a little bit inconsistent and thus needs special care + var archive = this.type === Archive.PAGER ? this.parent : this; + if (!archive.parent) { + var site = res.handlers.site; + var offset = (page - 1) * pageSize; + var stories = site.stories.featured.list(offset, pageSize); + for each (var story in stories) { renderStory(story); - }); - return; + }; + return; + } + + var sql = new Sql; + sql.retrieve(Sql.ARCHIVE, res.handlers.site._id, this.getFilter(), + Sql.ARCHIVEORDER, pageSize, (page - 1) * pageSize); + sql.traverse(function() { + var story = Story.getById(this.id); + renderStory(story); + }); + return; } /** * @returns {Number} */ Archive.prototype.getSize = function() { - // FIXME: This is a little bit inconsistent and thus needs special care - var archive = this.type === Archive.PAGER ? this.parent : this; - if (!archive.parent) { - return res.handlers.site.stories.featured.size(); - } - var size; - var sql = new Sql; - sql.retrieve(Sql.ARCHIVESIZE, res.handlers.site._id, this.getFilter()); - sql.traverse(function() { - size = this.count; - return; - }); - return size; + // FIXME: This is a little bit inconsistent and thus needs special care + var archive = this.type === Archive.PAGER ? this.parent : this; + if (!archive.parent) { + return res.handlers.site.stories.featured.size(); + } + var size; + var sql = new Sql; + sql.retrieve(Sql.ARCHIVESIZE, res.handlers.site._id, this.getFilter()); + sql.traverse(function() { + size = this.count; + return; + }); + return size; } /** @@ -223,66 +223,66 @@ Archive.prototype.getSize = function() { * @returns {String} */ Archive.prototype.getFilter = function() { - var buffer = []; - var archive = this; - do { - if (archive.type === Archive.COLLECTION) { - buffer.unshift(Number(archive.name)); - } - } while (archive = archive.parent); + var buffer = []; + var archive = this; + do { + if (archive.type === Archive.COLLECTION) { + buffer.unshift(Number(archive.name)); + } + } while (archive = archive.parent); - if (buffer.length < 0) { - var now = new Date; - buffer.push(now.getDate()); - buffer.push(now.getMonth() + 1); - buffer.push(now.getFullYear()); - } + if (buffer.length < 0) { + var now = new Date; + buffer.push(now.getDate()); + buffer.push(now.getMonth() + 1); + buffer.push(now.getFullYear()); + } - res.push(); - var sql = new Sql; - var keys = ["year", "month", "day"]; - for (var i in buffer) { - sql.retrieve(Sql.ARCHIVEPART, keys[i], buffer[i]); - res.write(sql); - } - return res.pop(); + res.push(); + var sql = new Sql; + var keys = ["year", "month", "day"]; + for (var i in buffer) { + sql.retrieve(Sql.ARCHIVEPART, keys[i], buffer[i]); + res.write(sql); + } + return res.pop(); } /** * @returns {Number} */ Archive.prototype.getPage = function() { - if (this.type === Archive.PAGER) { - return Number(this.name.substr(4)); - } - return 1; + if (this.type === Archive.PAGER) { + return Number(this.name.substr(4)); + } + return 1; } /** * @returns {Number} */ Archive.prototype.getPageSize = function() { - return res.handlers.site.pageSize; + return res.handlers.site.pageSize; } /** * @returns {Date} */ Archive.prototype.getDate = function() { - var date = new Date; - var offset = path.contains(res.handlers.site.archive) + 1; - if (offset > -1) { - var archive; - var buffer = []; - for (var i=offset; i -1) { + var archive; + var buffer = []; + for (var i=offset; i max) { - max = n; - } - return; - }); - votes = Math.round(this.size() / max * variant); - } - } else { - votes = this.size(); - } - if (!votes && param["default"]) { - return param["default"]; - } - return votes; + var votes = 0; + if (variant) { + if (variant.endsWith("%")) { + variant = parseInt(variant) || 1; + var max = this._parent.votes.size(); + votes = this.size() / max * variant; + } else { + var max = 1; + this._parent.forEach(function() { + var n = this.size(); + if (n > max) { + max = n; + } + return; + }); + votes = Math.round(this.size() / max * variant); + } + } else { + votes = this.size(); + } + if (!votes && param["default"]) { + return param["default"]; + } + return votes; } diff --git a/code/Comment/Comment.js b/code/Comment/Comment.js index 6a718cbc..166703ed 100644 --- a/code/Comment/Comment.js +++ b/code/Comment/Comment.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -33,8 +33,8 @@ markgettext("comment"); /** * @see defineConstants */ -Comment.getStatus = defineConstants(Comment, markgettext("deleted"), - markgettext("pending"), markgettext("readonly"), markgettext("public")); +Comment.getStatus = defineConstants(Comment, markgettext("deleted"), + markgettext("pending"), markgettext("readonly"), markgettext("public")); /** * Convenience method for easily adding a new comment to an existing story or comment. @@ -43,56 +43,56 @@ Comment.getStatus = defineConstants(Comment, markgettext("deleted"), * @returns {Comment} */ Comment.add = function(data, parent) { - HopObject.confirmConstructor(Comment); - var story = parent.story || parent; - var comment = new Comment; - comment.name = String.EMPTY; - comment.site = parent.site; - comment.story = story; - comment.parent = parent; - comment.parent_type = parent._prototype; // FIXME: Set correct parent_type (Helma bug?) - comment.status = Story.PUBLIC; - comment.creator = comment.modifier = session.user; - comment.created = comment.modified = new Date; - comment.update(data); - story.comments.add(comment); // Force addition to aggressively cached collection - parent.add(comment); - return comment; + HopObject.confirmConstructor(Comment); + var story = parent.story || parent; + var comment = new Comment; + comment.name = String.EMPTY; + comment.site = parent.site; + comment.story = story; + comment.parent = parent; + comment.parent_type = parent._prototype; // FIXME: Set correct parent_type (Helma bug?) + comment.status = Story.PUBLIC; + comment.creator = comment.modifier = session.user; + comment.created = comment.modified = new Date; + comment.update(data); + story.comments.add(comment); // Force addition to aggressively cached collection + parent.add(comment); + return comment; } /** * @returns {String} */ Comment.remove = function(options) { - if (this.constructor !== Comment) { - return; - } - // Remove all comments of this comment’s creator if corresponding option is set - if (options && options.mode === "user" && options.confirm === "1") { - var membership = Membership.getByName(this.creator.name, this.site); - // Not using HopObject.remove() because it will comepletely remove all comments - membership.comments.forEach(function() { - Comment.remove.call(this); - }) - } else { - // Mark comment as deleted if not already done so or if there are child comments - if (this.size() > 0 && this.status !== Comment.DELETED) { - this.status = Comment.DELETED; - this.deleteMetadata(); - this.touch(); - return this.href(); - } - // Completely remove comment and its children otherwise - while (this.size() > 0) { - Comment.remove.call(this.get(0)); - } - // Explicitely remove comment from aggressively cached collections: - (this.parent || this).removeChild(this); - this.story.comments.removeChild(this); + if (this.constructor !== Comment) { + return; + } + // Remove all comments of this comment’s creator if corresponding option is set + if (options && options.mode === "user" && options.confirm === "1") { + var membership = Membership.getByName(this.creator.name, this.site); + // Not using HopObject.remove() because it will comepletely remove all comments + membership.comments.forEach(function() { + Comment.remove.call(this); + }) + } else { + // Mark comment as deleted if not already done so or if there are child comments + if (this.size() > 0 && this.status !== Comment.DELETED) { + this.status = Comment.DELETED; this.deleteMetadata(); - this.remove(); - } - return this.parent.href(); + this.touch(); + return this.href(); + } + // Completely remove comment and its children otherwise + while (this.size() > 0) { + Comment.remove.call(this.get(0)); + } + // Explicitely remove comment from aggressively cached collections: + (this.parent || this).removeChild(this); + this.story.comments.removeChild(this); + this.deleteMetadata(); + this.remove(); + } + return this.parent.href(); } /** @@ -105,176 +105,176 @@ Comment.remove = function(options) { * @extends Story */ Comment.prototype.constructor = function() { - HopObject.confirmConstructor.call(this); - return this; + HopObject.confirmConstructor.call(this); + return this; } /** - * + * * @param {Object} action * @returns {Boolean} */ Comment.prototype.getPermission = function(action) { - switch (action) { - case ".": - case "main": - if (this.status === Comment.DELETED) { - return false; - } - // Break statement missing here by purpose! - case "comment": - return this.site.commentMode === Site.ENABLED && - this.story.getPermission(action) && - this.status !== Comment.PENDING; - case "delete": - return this.story.getPermission.call(this, "delete"); - case "edit": - return this.status !== Comment.DELETED && - this.story.getPermission.call(this, "delete"); - } - return false; + switch (action) { + case ".": + case "main": + if (this.status === Comment.DELETED) { + return false; + } + // Break statement missing here by purpose! + case "comment": + return this.site.commentMode === Site.ENABLED && + this.story.getPermission(action) && + this.status !== Comment.PENDING; + case "delete": + return this.story.getPermission.call(this, "delete"); + case "edit": + return this.status !== Comment.DELETED && + this.story.getPermission.call(this, "delete"); + } + return false; } /** - * + * * @param {Object} action * @returns {String} */ Comment.prototype.href = function(action) { - var buffer = []; - switch (action) { - case null: - case undefined: - case "": - case ".": - case "main": - buffer.push(this.story.href(), "#", this._id); - break; - default: - buffer.push(this.story.comments.href(), this._id, "/", action); - } - return buffer.join(String.EMPTY); + var buffer = []; + switch (action) { + case null: + case undefined: + case "": + case ".": + case "main": + buffer.push(this.story.href(), "#", this._id); + break; + default: + buffer.push(this.story.comments.href(), this._id, "/", action); + } + return buffer.join(String.EMPTY); } Comment.prototype.edit_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - delete session.data.backup; - res.message = gettext("The comment was successfully updated.");; - res.redirect(this.story.href() + "#" + this._id); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - - res.handlers.parent = this.parent; - res.data.action = this.href(req.action); - res.data.title = gettext("Edit Comment"); - res.data.body = this.renderSkinAsString("Comment#edit"); - this.site.renderSkin("Site#page"); - return; + if (req.postParams.save) { + try { + this.update(req.postParams); + delete session.data.backup; + res.message = gettext("The comment was successfully updated.");; + res.redirect(this.story.href() + "#" + this._id); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + + res.handlers.parent = this.parent; + res.data.action = this.href(req.action); + res.data.title = gettext("Edit Comment"); + res.data.body = this.renderSkinAsString("Comment#edit"); + this.site.renderSkin("Site#page"); + return; } /** - * + * * @param {Object} data */ Comment.prototype.update = function(data) { - if (!data.title && !data.text) { - throw Error(gettext("Please enter at least something into the “title” or “text” field.")); - } - // Get difference to current content before applying changes - var delta = this.getDelta(data); - this.title = data.title; - this.text = data.text; - this.setMetadata(data); + if (!data.title && !data.text) { + throw Error(gettext("Please enter at least something into the “title” or “text” field.")); + } + // Get difference to current content before applying changes + var delta = this.getDelta(data); + this.title = data.title; + this.text = data.text; + this.setMetadata(data); - if (this.story.commentMode === Story.MODERATED) { - this.status = Comment.PENDING; - } else if (delta > 50) { - this.modified = new Date; - if (this.story.status !== Story.CLOSED) { - this.site.modified = this.modified; - } - // We need persistence for adding the callback - this.isTransient() && this.persist(); - res.handlers.site.callback(this); - // Notification is sent in Story.comment_action() - } - this.clearCache(); - this.modifier = session.user; - return; + if (this.story.commentMode === Story.MODERATED) { + this.status = Comment.PENDING; + } else if (delta > 50) { + this.modified = new Date; + if (this.story.status !== Story.CLOSED) { + this.site.modified = this.modified; + } + // We need persistence for adding the callback + this.isTransient() && this.persist(); + res.handlers.site.callback(this); + // Notification is sent in Story.comment_action() + } + this.clearCache(); + this.modifier = session.user; + return; } /** * @returns {String} */ Comment.prototype.getConfirmText = function() { - var size = this.size() + 1; - if (this.status === Comment.DELETED && size > 1) { - return gettext("You are about to delete a comment thread consisting of {0} postings.", - size); - } - return gettext("You are about to delete a comment by user {0}.", - this.creator.name); + var size = this.size() + 1; + if (this.status === Comment.DELETED && size > 1) { + return gettext("You are about to delete a comment thread consisting of {0} postings.", + size); + } + return gettext("You are about to delete a comment by user {0}.", + this.creator.name); } /** - * + * * @param {String} name - * @returns {HopObject} + * @returns {HopObject} */ Comment.prototype.getMacroHandler = function(name) { - if (name === "related") { - var membership = Membership.getByName(this.creator.name, this.site); - if (!membership || membership.comments.size() < 2 || this.status === Comment.DELETED) { - return {}; // Work-around for issue 88 - } - return membership.comments; - } - return null; + if (name === "related") { + var membership = Membership.getByName(this.creator.name, this.site); + if (!membership || membership.comments.size() < 2 || this.status === Comment.DELETED) { + return {}; // Work-around for issue 88 + } + return membership.comments; + } + return null; } /** - * + * */ Comment.prototype.text_macro = function() { - if (this.status === Comment.DELETED) { - res.write(""); - res.write(this.modifier === this.creator ? - gettext("This comment was removed by the author.") : - gettext("This comment was removed.")); - res.writeln(""); - } else { - res.write(this.text); - } - return; + if (this.status === Comment.DELETED) { + res.write(""); + res.write(this.modifier === this.creator ? + gettext("This comment was removed by the author.") : + gettext("This comment was removed.")); + res.writeln(""); + } else { + res.write(this.text); + } + return; } /** * */ Comment.prototype.creator_macro = function() { - return this.status === Comment.DELETED ? null : - HopObject.prototype.creator_macro.apply(this, arguments); + return this.status === Comment.DELETED ? null : + HopObject.prototype.creator_macro.apply(this, arguments); } /** - * + * */ Comment.prototype.modifier_macro = function() { - return this.status === Comment.DELETED ? null : - HopObject.prototype.modifier_macro.apply(this, arguments); + return this.status === Comment.DELETED ? null : + HopObject.prototype.modifier_macro.apply(this, arguments); } /** - * + * * @param {Object} param * @param {Object} action * @param {Object} text */ Comment.prototype.link_macro = function(param, action, text) { - return HopObject.prototype.link_macro.call(this, param, action, text); + return HopObject.prototype.link_macro.call(this, param, action, text); } diff --git a/code/File/File.js b/code/File/File.js index b1e87afb..a2680233 100644 --- a/code/File/File.js +++ b/code/File/File.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -43,40 +43,40 @@ this.handleMetadata("fileName"); * @returns {File} */ File.add = function(data, site, user) { - site || (site = res.handlers.site); - user || (user = session.user); - var file = new File; - file.site = site; - file.requests = 0; - file.creator = file.modifier = user; - file.created = file.modified = new Date; - file.update(data); - site.files.add(file); - return file; + site || (site = res.handlers.site); + user || (user = session.user); + var file = new File; + file.site = site; + file.requests = 0; + file.creator = file.modifier = user; + file.created = file.modified = new Date; + file.update(data); + site.files.add(file); + return file; } /** - * + * */ File.remove = function() { - if (this.constructor === File) { - this.getFile().remove(); - this.deleteMetadata(); - this.remove(); - } - return; + if (this.constructor === File) { + this.getFile().remove(); + this.deleteMetadata(); + this.remove(); + } + return; } /** - * + * * @param {String} name */ File.getName = function(name) { - if (name) { - //return name.replace(/[^\w\d\s._-]/g, String.EMPTY); - return String(name).trim().replace(/[\/\\:;?+\[\]{}|#"`<>^]/g, String.EMPTY); - } - return null; + if (name) { + //return name.replace(/[^\w\d\s._-]/g, String.EMPTY); + return String(name).trim().replace(/[\/\\:;?+\[\]{}|#"`<>^]/g, String.EMPTY); + } + return null; } /** @@ -84,12 +84,12 @@ File.getName = function(name) { * @param {String } url */ File.redirectOnUploadError = function(url) { - if (req.data.helma_upload_error) { - res.message = gettext("Sorry, the file exceeds the maximum upload limit of {0} kB.", - formatNumber(app.appsProperties.uploadLimit)); - res.redirect(url); - } - return; + if (req.data.helma_upload_error) { + res.message = gettext("Sorry, the file exceeds the maximum upload limit of {0} kB.", + formatNumber(app.appsProperties.uploadLimit)); + res.redirect(url); + } + return; } /** @@ -97,11 +97,11 @@ File.redirectOnUploadError = function(url) { * @param {String} url */ File.redirectOnExceededQuota = function(url) { - if (res.handlers.site.getDiskSpace() < 0) { - res.message = gettext("Sorry, there is no disk space left. Please try to delete some files or images first."); - res.redirect(url); - } - return; + if (res.handlers.site.getDiskSpace() < 0) { + res.message = gettext("Sorry, there is no disk space left. Please try to delete some files or images first."); + res.redirect(url); + } + return; } /** @@ -121,177 +121,177 @@ File.redirectOnExceededQuota = function(url) { * @extends HopObject */ File.prototype.constructor = function() { - return this; + return this; } /** - * + * * @param {String} action * @return {Boolean} */ File.prototype.getPermission = function(action) { - switch (action) { - case ".": - case "main": - return true; - case "delete": - case "edit": - return this._parent.getPermission("main") && - this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - } - return false; + switch (action) { + case ".": + case "main": + return true; + case "delete": + case "edit": + return this._parent.getPermission("main") && + this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + } + return false; } File.prototype.main_action = function() { - if (Membership.require(Membership.SUBSCRIBER) && - User.require(User.REGULAR)) { - this.requests += 1; - } - return res.redirect(this.getUrl()); + if (Membership.require(Membership.SUBSCRIBER) && + User.require(User.REGULAR)) { + this.requests += 1; + } + return res.redirect(this.getUrl()); } File.prototype.edit_action = function() { - File.redirectOnUploadError(this.href(req.action)); + File.redirectOnUploadError(this.href(req.action)); - if (req.postParams.save) { - try { - File.redirectOnExceededQuota(this.href(req.action)); - this.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this._parent.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - - res.data.action = this.href(req.action); - res.data.title = gettext("Edit File"); - res.data.body = this.renderSkinAsString("$File#edit"); - return this.site.renderSkin("Site#page"); + if (req.postParams.save) { + try { + File.redirectOnExceededQuota(this.href(req.action)); + this.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this._parent.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + + res.data.action = this.href(req.action); + res.data.title = gettext("Edit File"); + res.data.body = this.renderSkinAsString("$File#edit"); + return this.site.renderSkin("Site#page"); } /** - * + * * @param {String} name * @returns {Object} */ File.prototype.getFormValue = function(name) { - var self = this; - - var getOrigin = function(str) { - var origin = req.postParams.file_origin || self.origin; - if (origin && origin.contains("://")) { - return origin; - } - return null; - } - - if (req.isPost()) { - if (name === "file") { - return getOrigin(); - } - return req.postParams[name]; - } - switch (name) { - case "file": + var self = this; + + var getOrigin = function(str) { + var origin = req.postParams.file_origin || self.origin; + if (origin && origin.contains("://")) { + return origin; + } + return null; + } + + if (req.isPost()) { + if (name === "file") { return getOrigin(); - } - return this[name]; + } + return req.postParams[name]; + } + switch (name) { + case "file": + return getOrigin(); + } + return this[name]; } /** - * + * * @param {Object} data */ File.prototype.update = function(data) { - if (data.uploadError) { - app.log(data.uploadError); - // Looks like the file uploaded has exceeded the upload limit ... - throw Error(gettext("File size is exceeding the upload limit.")); - } - - if (!data.file_origin) { - if (this.isTransient()) { - throw Error(gettext("There was nothing to upload. Please be sure to choose a file.")); - } - } else if (data.file_origin !== this.origin) { - var mime = data.file; - if (mime.contentLength < 1) { - mime = getURL(data.file_origin); - if (!mime) { - throw Error(gettext("Could not fetch the file from the given URL.")); - } - } + if (data.uploadError) { + app.log(data.uploadError); + // Looks like the file uploaded has exceeded the upload limit ... + throw Error(gettext("File size is exceeding the upload limit.")); + } - this.origin = data.file_origin; - var mimeName = mime.normalizeFilename(mime.name); - this.contentLength = mime.contentLength; - this.contentType = mime.contentType; - - if (!this.name) { - var name = File.getName(data.name) || mimeName.split(".")[0]; - this.name = this.site.files.getAccessName(name); + if (!data.file_origin) { + if (this.isTransient()) { + throw Error(gettext("There was nothing to upload. Please be sure to choose a file.")); + } + } else if (data.file_origin !== this.origin) { + var mime = data.file; + if (mime.contentLength < 1) { + mime = getURL(data.file_origin); + if (!mime) { + throw Error(gettext("Could not fetch the file from the given URL.")); } + } - // Make the file persistent before proceeding with writing - // it to disk (also see Helma bug #607) - this.isTransient() && this.persist(); + this.origin = data.file_origin; + var mimeName = mime.normalizeFilename(mime.name); + this.contentLength = mime.contentLength; + this.contentType = mime.contentType; - var extension = mimeName.substr(mimeName.lastIndexOf(".")) || String.EMPTY; - var fileName = this.name + extension; - if (fileName !== this.fileName) { - // Remove existing file if the file name has changed - this.getFile().remove(); - } - this.fileName = fileName; - var file = this.getFile(); - mime.writeToFile(file.getParent(), file.getName()); - } - - // FIXME: one day? - //this.setTags(data.tags || data.tag_array); - this.description = data.description; - this.touch(); - return; + if (!this.name) { + var name = File.getName(data.name) || mimeName.split(".")[0]; + this.name = this.site.files.getAccessName(name); + } + + // Make the file persistent before proceeding with writing + // it to disk (also see Helma bug #607) + this.isTransient() && this.persist(); + + var extension = mimeName.substr(mimeName.lastIndexOf(".")) || String.EMPTY; + var fileName = this.name + extension; + if (fileName !== this.fileName) { + // Remove existing file if the file name has changed + this.getFile().remove(); + } + this.fileName = fileName; + var file = this.getFile(); + mime.writeToFile(file.getParent(), file.getName()); + } + + // FIXME: one day? + //this.setTags(data.tags || data.tag_array); + this.description = data.description; + this.touch(); + return; } /** - * + * */ File.prototype.url_macro = function() { - return res.write(this.url || this.getUrl()); + return res.write(this.url || this.getUrl()); } /** - * + * * @param {Object} param */ File.prototype.contentLength_macro = function(param) { - return res.write((this.contentLength / 1024).format("###,###") + " KB"); + return res.write((this.contentLength / 1024).format("###,###") + " KB"); } /** - * + * */ File.prototype.getFile = function() { - var site = this.site || res.handlers.site; - return site.getStaticFile("files/" + this.fileName); + var site = this.site || res.handlers.site; + return site.getStaticFile("files/" + this.fileName); } /** - * + * */ File.prototype.getUrl = function() { - var site = this.site || res.handlers.site; - return site.getStaticUrl("files/" + this.fileName); + var site = this.site || res.handlers.site; + return site.getStaticUrl("files/" + this.fileName); } /** * @returns {String} */ File.prototype.getConfirmText = function() { - return gettext("You are about to delete the file {0}.", this.name); + return gettext("You are about to delete the file {0}.", this.name); } diff --git a/code/Files/Files.js b/code/Files/Files.js index 0afad3ef..c3095119 100644 --- a/code/Files/Files.js +++ b/code/Files/Files.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -37,69 +37,69 @@ markgettext("files"); */ /** - * + * * @param {String} action * @returns {Boolean} */ Files.prototype.getPermission = function(action) { - if (!this._parent.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - case "create": - return Site.require(Site.OPEN) && session.user || - Membership.require(Membership.CONTRIBUTOR) || - User.require(User.PRIVILEGED); - case "all": - return Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - } - return false; + if (!this._parent.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + case "create": + return Site.require(Site.OPEN) && session.user || + Membership.require(Membership.CONTRIBUTOR) || + User.require(User.PRIVILEGED); + case "all": + return Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + } + return false; } Files.prototype.create_action = function() { - File.redirectOnUploadError(this.href(req.action)); - File.redirectOnExceededQuota(this.href()); + File.redirectOnUploadError(this.href(req.action)); + File.redirectOnExceededQuota(this.href()); - if (req.postParams.save) { - try { - var file = File.add(req.postParams); - file.notify(req.action); - res.message = gettext('The file was successfully added.'); - res.redirect(this.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - - res.data.action = this.href(req.action); - res.data.title = gettext("Add File"); - HopObject.confirmConstructor(File); - res.data.body = (new File).renderSkinAsString("$File#edit"); - this._parent.renderSkin("Site#page"); - return; + if (req.postParams.save) { + try { + var file = File.add(req.postParams); + file.notify(req.action); + res.message = gettext('The file was successfully added.'); + res.redirect(this.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + + res.data.action = this.href(req.action); + res.data.title = gettext("Add File"); + HopObject.confirmConstructor(File); + res.data.body = (new File).renderSkinAsString("$File#edit"); + this._parent.renderSkin("Site#page"); + return; } Files.prototype.main_action = function() { - var files = User.getMembership().files; - res.data.list = renderList(files, "$File#listItem", 10, req.queryParams.page); - res.data.pager = renderPager(files, this.href(), - 10, req.queryParams.page); - res.data.title = gettext("Member Files"); - res.data.body = this.renderSkinAsString("$Files#main"); - this._parent.renderSkin("Site#page"); - return; + var files = User.getMembership().files; + res.data.list = renderList(files, "$File#listItem", 10, req.queryParams.page); + res.data.pager = renderPager(files, this.href(), + 10, req.queryParams.page); + res.data.title = gettext("Member Files"); + res.data.body = this.renderSkinAsString("$Files#main"); + this._parent.renderSkin("Site#page"); + return; } Files.prototype.all_action = function() { - res.data.list = renderList(this, "$File#listItem", 10, req.queryParams.page); - res.data.pager = renderPager(this, - this.href(req.action), 10, req.queryParams.page); - res.data.title = gettext("All Files"); - res.data.body = this.renderSkinAsString("$Files#main"); - this._parent.renderSkin("Site#page"); - return; + res.data.list = renderList(this, "$File#listItem", 10, req.queryParams.page); + res.data.pager = renderPager(this, + this.href(req.action), 10, req.queryParams.page); + res.data.title = gettext("All Files"); + res.data.body = this.renderSkinAsString("$Files#main"); + this._parent.renderSkin("Site#page"); + return; } diff --git a/code/Global/5.less-helma-1.3.0.js b/code/Global/5.less-helma-1.3.0.js index 54daabcd..7af952cb 100644 --- a/code/Global/5.less-helma-1.3.0.js +++ b/code/Global/5.less-helma-1.3.0.js @@ -3,7 +3,7 @@ // Stub out `require` in rhino // function require(arg) { - return less[arg.split('/')[1]]; + return less[arg.split('/')[1]]; }; @@ -17,1732 +17,1732 @@ function require(arg) { // Array // if (!Array.isArray) { - Array.isArray = function(obj) { - return Object.prototype.toString.call(obj) === "[object Array]" || - (obj instanceof Array); - }; + Array.isArray = function(obj) { + return Object.prototype.toString.call(obj) === "[object Array]" || + (obj instanceof Array); + }; } if (!Array.prototype.forEach) { - Array.prototype.forEach = function(block, thisObject) { - var len = this.length >>> 0; - for (var i = 0; i < len; i++) { - if (i in this) { - block.call(thisObject, this[i], i, this); - } + Array.prototype.forEach = function(block, thisObject) { + var len = this.length >>> 0; + for (var i = 0; i < len; i++) { + if (i in this) { + block.call(thisObject, this[i], i, this); } - }; + } + }; } if (!Array.prototype.map) { - Array.prototype.map = function(fun /*, thisp*/) { - var len = this.length >>> 0; - var res = new Array(len); - var thisp = arguments[1]; + Array.prototype.map = function(fun /*, thisp*/) { + var len = this.length >>> 0; + var res = new Array(len); + var thisp = arguments[1]; - for (var i = 0; i < len; i++) { - if (i in this) { - res[i] = fun.call(thisp, this[i], i, this); - } + for (var i = 0; i < len; i++) { + if (i in this) { + res[i] = fun.call(thisp, this[i], i, this); } - return res; - }; + } + return res; + }; } if (!Array.prototype.filter) { - Array.prototype.filter = function (block /*, thisp */) { - var values = []; - var thisp = arguments[1]; - for (var i = 0; i < this.length; i++) { - if (block.call(thisp, this[i])) { - values.push(this[i]); - } + Array.prototype.filter = function (block /*, thisp */) { + var values = []; + var thisp = arguments[1]; + for (var i = 0; i < this.length; i++) { + if (block.call(thisp, this[i])) { + values.push(this[i]); } - return values; - }; + } + return values; + }; } if (!Array.prototype.reduce) { - Array.prototype.reduce = function(fun /*, initial*/) { - var len = this.length >>> 0; - var i = 0; + Array.prototype.reduce = function(fun /*, initial*/) { + var len = this.length >>> 0; + var i = 0; - // no value to return if no initial value and an empty array - if (len === 0 && arguments.length === 1) throw new TypeError(); + // no value to return if no initial value and an empty array + if (len === 0 && arguments.length === 1) throw new TypeError(); - if (arguments.length >= 2) { - var rv = arguments[1]; - } else { - do { - if (i in this) { - rv = this[i++]; - break; - } - // if array contains no values, no initial value to return - if (++i >= len) throw new TypeError(); - } while (true); + if (arguments.length >= 2) { + var rv = arguments[1]; + } else { + do { + if (i in this) { + rv = this[i++]; + break; + } + // if array contains no values, no initial value to return + if (++i >= len) throw new TypeError(); + } while (true); + } + for (; i < len; i++) { + if (i in this) { + rv = fun.call(null, rv, this[i], i, this); } - for (; i < len; i++) { - if (i in this) { - rv = fun.call(null, rv, this[i], i, this); - } - } - return rv; - }; + } + return rv; + }; } if (!Array.prototype.indexOf) { - Array.prototype.indexOf = function (value /*, fromIndex */ ) { - var length = this.length; - var i = arguments[1] || 0; + Array.prototype.indexOf = function (value /*, fromIndex */ ) { + var length = this.length; + var i = arguments[1] || 0; - if (!length) return -1; - if (i >= length) return -1; - if (i < 0) i += length; + if (!length) return -1; + if (i >= length) return -1; + if (i < 0) i += length; - for (; i < length; i++) { - if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } - if (value === this[i]) return i; - } - return -1; - }; + for (; i < length; i++) { + if (!Object.prototype.hasOwnProperty.call(this, i)) { continue } + if (value === this[i]) return i; + } + return -1; + }; } // // Object // if (!Object.keys) { - Object.keys = function (object) { - var keys = []; - for (var name in object) { - if (Object.prototype.hasOwnProperty.call(object, name)) { - keys.push(name); - } + Object.keys = function (object) { + var keys = []; + for (var name in object) { + if (Object.prototype.hasOwnProperty.call(object, name)) { + keys.push(name); } - return keys; - }; + } + return keys; + }; } // // String // if (!String.prototype.trim) { - String.prototype.trim = function () { - return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - }; + String.prototype.trim = function () { + return String(this).replace(/^\s\s*/, '').replace(/\s\s*$/, ''); + }; } var less, tree; if (typeof HopObject === 'function') { - // Helma - // Fully qualified condition would be helma.main.Server.getServer() === 'string' - less = global.less = {} - tree = less.tree = {} - less.mode = 'rhino'; + // Helma + // Fully qualified condition would be helma.main.Server.getServer() === 'string' + less = global.less = {} + tree = less.tree = {} + less.mode = 'rhino'; } else if (typeof environment === "object" && ({}).toString.call(environment) === "[object Environment]") { - // Rhino - // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 - if (typeof(window) === 'undefined') { less = {} } - else { less = window.less = {} } - tree = less.tree = {}; - less.mode = 'rhino'; + // Rhino + // Details on how to detect Rhino: https://github.com/ringo/ringojs/issues/88 + if (typeof(window) === 'undefined') { less = {} } + else { less = window.less = {} } + tree = less.tree = {}; + less.mode = 'rhino'; } else if (typeof(window) === 'undefined') { - // Node.js - less = exports, - tree = require('./tree'); - less.mode = 'node'; + // Node.js + less = exports, + tree = require('./tree'); + less.mode = 'node'; } else { - // Browser - if (typeof(window.less) === 'undefined') { window.less = {} } - less = window.less, - tree = window.less.tree = {}; - less.mode = 'browser'; + // Browser + if (typeof(window.less) === 'undefined') { window.less = {} } + less = window.less, + tree = window.less.tree = {}; + less.mode = 'browser'; } // // less.js - parser // -// A relatively straight-forward predictive parser. -// There is no tokenization/lexing stage, the input is parsed -// in one sweep. +// A relatively straight-forward predictive parser. +// There is no tokenization/lexing stage, the input is parsed +// in one sweep. // -// To make the parser fast enough to run in the browser, several -// optimization had to be made: +// To make the parser fast enough to run in the browser, several +// optimization had to be made: // -// - Matching and slicing on a huge input is often cause of slowdowns. -// The solution is to chunkify the input into smaller strings. -// The chunks are stored in the `chunks` var, -// `j` holds the current chunk index, and `current` holds -// the index of the current chunk in relation to `input`. -// This gives us an almost 4x speed-up. +// - Matching and slicing on a huge input is often cause of slowdowns. +// The solution is to chunkify the input into smaller strings. +// The chunks are stored in the `chunks` var, +// `j` holds the current chunk index, and `current` holds +// the index of the current chunk in relation to `input`. +// This gives us an almost 4x speed-up. // -// - In many cases, we don't need to match individual tokens; -// for example, if a value doesn't hold any variables, operations -// or dynamic references, the parser can effectively 'skip' it, -// treating it as a literal. -// An example would be '1px solid #000' - which evaluates to itself, -// we don't need to know what the individual components are. -// The drawback, of course is that you don't get the benefits of -// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, -// and a smaller speed-up in the code-gen. +// - In many cases, we don't need to match individual tokens; +// for example, if a value doesn't hold any variables, operations +// or dynamic references, the parser can effectively 'skip' it, +// treating it as a literal. +// An example would be '1px solid #000' - which evaluates to itself, +// we don't need to know what the individual components are. +// The drawback, of course is that you don't get the benefits of +// syntax-checking on the CSS. This gives us a 50% speed-up in the parser, +// and a smaller speed-up in the code-gen. // // -// Token matching is done with the `$` function, which either takes -// a terminal string or regexp, or a non-terminal function to call. -// It also takes care of moving all the indices forwards. +// Token matching is done with the `$` function, which either takes +// a terminal string or regexp, or a non-terminal function to call. +// It also takes care of moving all the indices forwards. // // less.Parser = function Parser(env) { - var input, // LeSS input string - i, // current index in `input` - j, // current chunk - temp, // temporarily holds a chunk's state, for backtracking - memo, // temporarily holds `i`, when backtracking - furthest, // furthest index the parser has gone to - chunks, // chunkified input - current, // index of current chunk, in `input` - parser; + var input, // LeSS input string + i, // current index in `input` + j, // current chunk + temp, // temporarily holds a chunk's state, for backtracking + memo, // temporarily holds `i`, when backtracking + furthest, // furthest index the parser has gone to + chunks, // chunkified input + current, // index of current chunk, in `input` + parser; - var that = this; + var that = this; - // This function is called after all files - // have been imported through `@import`. - var finish = function () {}; + // This function is called after all files + // have been imported through `@import`. + var finish = function () {}; - var imports = this.imports = { - paths: env && env.paths || [], // Search paths, when importing - queue: [], // Files which haven't been imported yet - files: {}, // Holds the imported parse trees - contents: {}, // Holds the imported file contents - mime: env && env.mime, // MIME type of .less files - error: null, // Error in parsing/evaluating an import - push: function (path, callback) { - var that = this; - this.queue.push(path); - - // - // Import a file asynchronously - // - less.Parser.importer(path, this.paths, function (e, root, contents) { - that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue - - var imported = path in that.files; - - that.files[path] = root; // Store the root - that.contents[path] = contents; - - if (e && !that.error) { that.error = e } - - callback(e, root, imported); - - if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing - }, env); - } - }; - - function save() { temp = chunks[j], memo = i, current = i } - function restore() { chunks[j] = temp, i = memo, current = i } - - function sync() { - if (i > current) { - chunks[j] = chunks[j].slice(i - current); - current = i; - } - } - // - // Parse from a token, regexp or string, and move forward if match - // - function $(tok) { - var match, args, length, c, index, endIndex, k, mem; + var imports = this.imports = { + paths: env && env.paths || [], // Search paths, when importing + queue: [], // Files which haven't been imported yet + files: {}, // Holds the imported parse trees + contents: {}, // Holds the imported file contents + mime: env && env.mime, // MIME type of .less files + error: null, // Error in parsing/evaluating an import + push: function (path, callback) { + var that = this; + this.queue.push(path); // - // Non-terminal + // Import a file asynchronously // - if (tok instanceof Function) { - return tok.call(parser.parsers); - // - // Terminal - // - // Either match a single character in the input, - // or match a regexp in the current chunk (chunk[j]). - // - } else if (typeof(tok) === 'string') { - match = input.charAt(i) === tok ? tok : null; - length = 1; - sync (); + less.Parser.importer(path, this.paths, function (e, root, contents) { + that.queue.splice(that.queue.indexOf(path), 1); // Remove the path from the queue + + var imported = path in that.files; + + that.files[path] = root; // Store the root + that.contents[path] = contents; + + if (e && !that.error) { that.error = e } + + callback(e, root, imported); + + if (that.queue.length === 0) { finish() } // Call `finish` if we're done importing + }, env); + } + }; + + function save() { temp = chunks[j], memo = i, current = i } + function restore() { chunks[j] = temp, i = memo, current = i } + + function sync() { + if (i > current) { + chunks[j] = chunks[j].slice(i - current); + current = i; + } + } + // + // Parse from a token, regexp or string, and move forward if match + // + function $(tok) { + var match, args, length, c, index, endIndex, k, mem; + + // + // Non-terminal + // + if (tok instanceof Function) { + return tok.call(parser.parsers); + // + // Terminal + // + // Either match a single character in the input, + // or match a regexp in the current chunk (chunk[j]). + // + } else if (typeof(tok) === 'string') { + match = input.charAt(i) === tok ? tok : null; + length = 1; + sync (); + } else { + sync (); + + if (match = tok.exec(chunks[j])) { + length = match[0].length; } else { - sync (); - - if (match = tok.exec(chunks[j])) { - length = match[0].length; - } else { - return null; - } + return null; } + } - // The match is confirmed, add the match length to `i`, - // and consume any extra white-space characters (' ' || '\n') - // which come after that. The reason for this is that LeSS's - // grammar is mostly white-space insensitive. - // - if (match) { - mem = i += length; - endIndex = i + chunks[j].length - length; + // The match is confirmed, add the match length to `i`, + // and consume any extra white-space characters (' ' || '\n') + // which come after that. The reason for this is that LeSS's + // grammar is mostly white-space insensitive. + // + if (match) { + mem = i += length; + endIndex = i + chunks[j].length - length; - while (i < endIndex) { - c = input.charCodeAt(i); - if (! (c === 32 || c === 10 || c === 9)) { break } - i++; - } - chunks[j] = chunks[j].slice(length + (i - mem)); - current = i; - - if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } - - if(typeof(match) === 'string') { - return match; - } else { - return match.length === 1 ? match[0] : match; - } + while (i < endIndex) { + c = input.charCodeAt(i); + if (! (c === 32 || c === 10 || c === 9)) { break } + i++; } - } + chunks[j] = chunks[j].slice(length + (i - mem)); + current = i; - function expect(arg, msg) { - var result = $(arg); - if (! result) { - error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" - : "unexpected token")); + if (chunks[j].length === 0 && j < chunks.length - 1) { j++ } + + if(typeof(match) === 'string') { + return match; } else { - return result; + return match.length === 1 ? match[0] : match; } - } + } + } - function error(msg, type) { - throw { index: i, type: type || 'Syntax', message: msg }; - } + function expect(arg, msg) { + var result = $(arg); + if (! result) { + error(msg || (typeof(arg) === 'string' ? "expected '" + arg + "' got '" + input.charAt(i) + "'" + : "unexpected token")); + } else { + return result; + } + } - // Same as $(), but don't change the state of the parser, - // just return the match. - function peek(tok) { - if (typeof(tok) === 'string') { - return input.charAt(i) === tok; + function error(msg, type) { + throw { index: i, type: type || 'Syntax', message: msg }; + } + + // Same as $(), but don't change the state of the parser, + // just return the match. + function peek(tok) { + if (typeof(tok) === 'string') { + return input.charAt(i) === tok; + } else { + if (tok.test(chunks[j])) { + return true; } else { - if (tok.test(chunks[j])) { - return true; - } else { - return false; - } + return false; } - } + } + } - function basename(pathname) { - if (less.mode === 'node') { - return require('path').basename(pathname); - } else { - return pathname.match(/[^\/]+$/)[0]; - } - } + function basename(pathname) { + if (less.mode === 'node') { + return require('path').basename(pathname); + } else { + return pathname.match(/[^\/]+$/)[0]; + } + } - function getInput(e, env) { - if (e.filename && env.filename && (e.filename !== env.filename)) { - return parser.imports.contents[basename(e.filename)]; - } else { - return input; - } - } + function getInput(e, env) { + if (e.filename && env.filename && (e.filename !== env.filename)) { + return parser.imports.contents[basename(e.filename)]; + } else { + return input; + } + } - function getLocation(index, input) { - for (var n = index, column = -1; - n >= 0 && input.charAt(n) !== '\n'; - n--) { column++ } + function getLocation(index, input) { + for (var n = index, column = -1; + n >= 0 && input.charAt(n) !== '\n'; + n--) { column++ } - return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, - column: column }; - } + return { line: typeof(index) === 'number' ? (input.slice(0, index).match(/\n/g) || "").length : null, + column: column }; + } - function LessError(e, env) { - var input = getInput(e, env), - loc = getLocation(e.index, input), - line = loc.line, - col = loc.column, - lines = input.split('\n'); + function LessError(e, env) { + var input = getInput(e, env), + loc = getLocation(e.index, input), + line = loc.line, + col = loc.column, + lines = input.split('\n'); - this.type = e.type || 'Syntax'; - this.message = e.message; - this.filename = e.filename || env.filename; - this.index = e.index; - this.line = typeof(line) === 'number' ? line + 1 : null; - this.callLine = e.call && (getLocation(e.call, input).line + 1); - this.callExtract = lines[getLocation(e.call, input).line]; - this.stack = e.stack; - this.column = col; - this.extract = [ - lines[line - 1], - lines[line], - lines[line + 1] - ]; - } + this.type = e.type || 'Syntax'; + this.message = e.message; + this.filename = e.filename || env.filename; + this.index = e.index; + this.line = typeof(line) === 'number' ? line + 1 : null; + this.callLine = e.call && (getLocation(e.call, input).line + 1); + this.callExtract = lines[getLocation(e.call, input).line]; + this.stack = e.stack; + this.column = col; + this.extract = [ + lines[line - 1], + lines[line], + lines[line + 1] + ]; + } - this.env = env = env || {}; + this.env = env = env || {}; - // The optimization level dictates the thoroughness of the parser, - // the lower the number, the less nodes it will create in the tree. - // This could matter for debugging, or if you want to access - // the individual nodes in the tree. - this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; + // The optimization level dictates the thoroughness of the parser, + // the lower the number, the less nodes it will create in the tree. + // This could matter for debugging, or if you want to access + // the individual nodes in the tree. + this.optimization = ('optimization' in this.env) ? this.env.optimization : 1; - this.env.filename = this.env.filename || null; + this.env.filename = this.env.filename || null; - // - // The Parser - // - return parser = { + // + // The Parser + // + return parser = { - imports: imports, - // - // Parse an input string into an abstract syntax tree, - // call `callback` when done. - // - parse: function (str, callback) { - var root, start, end, zone, line, lines, buff = [], c, error = null; + imports: imports, + // + // Parse an input string into an abstract syntax tree, + // call `callback` when done. + // + parse: function (str, callback) { + var root, start, end, zone, line, lines, buff = [], c, error = null; - i = j = current = furthest = 0; - input = str.replace(/\r\n/g, '\n'); + i = j = current = furthest = 0; + input = str.replace(/\r\n/g, '\n'); - // Split the input into chunks. - chunks = (function (chunks) { - var j = 0, - skip = /[^"'`\{\}\/\(\)\\]+/g, - comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, - string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, - level = 0, - match, - chunk = chunks[0], - inParam; + // Split the input into chunks. + chunks = (function (chunks) { + var j = 0, + skip = /[^"'`\{\}\/\(\)\\]+/g, + comment = /\/\*(?:[^*]|\*+[^\/*])*\*+\/|\/\/.*/g, + string = /"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'|`((?:[^`\\\r\n]|\\.)*)`/g, + level = 0, + match, + chunk = chunks[0], + inParam; - for (var i = 0, c, cc; i < input.length; i++) { - skip.lastIndex = i; - if (match = skip.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - } - } - c = input.charAt(i); - comment.lastIndex = string.lastIndex = i; - - if (match = string.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - - if (!inParam && c === '/') { - cc = input.charAt(i + 1); - if (cc === '/' || cc === '*') { - if (match = comment.exec(input)) { - if (match.index === i) { - i += match[0].length; - chunk.push(match[0]); - c = input.charAt(i); - } - } - } - } - - switch (c) { - case '{': if (! inParam) { level ++; chunk.push(c); break } - case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } - case '(': if (! inParam) { inParam = true; chunk.push(c); break } - case ')': if ( inParam) { inParam = false; chunk.push(c); break } - default: chunk.push(c); - } + for (var i = 0, c, cc; i < input.length; i++) { + skip.lastIndex = i; + if (match = skip.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); } - if (level > 0) { - error = new(LessError)({ - index: i, - type: 'Parse', - message: "missing closing `}`", - filename: env.filename - }, env); + } + c = input.charAt(i); + comment.lastIndex = string.lastIndex = i; + + if (match = string.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); } + } - return chunks.map(function (c) { return c.join('') });; - })([[]]); + if (!inParam && c === '/') { + cc = input.charAt(i + 1); + if (cc === '/' || cc === '*') { + if (match = comment.exec(input)) { + if (match.index === i) { + i += match[0].length; + chunk.push(match[0]); + c = input.charAt(i); + } + } + } + } - if (error) { - return callback(error); - } + switch (c) { + case '{': if (! inParam) { level ++; chunk.push(c); break } + case '}': if (! inParam) { level --; chunk.push(c); chunks[++j] = chunk = []; break } + case '(': if (! inParam) { inParam = true; chunk.push(c); break } + case ')': if ( inParam) { inParam = false; chunk.push(c); break } + default: chunk.push(c); + } + } + if (level > 0) { + error = new(LessError)({ + index: i, + type: 'Parse', + message: "missing closing `}`", + filename: env.filename + }, env); + } - // Start with the primary rule. - // The whole syntax tree is held under a Ruleset node, - // with the `root` property set to true, so no `{}` are - // output. The callback is called when the input is parsed. - try { - root = new(tree.Ruleset)([], $(this.parsers.primary)); - root.root = true; - } catch (e) { - return callback(new(LessError)(e, env)); - } + return chunks.map(function (c) { return c.join('') });; + })([[]]); - root.toCSS = (function (evaluate) { - var line, lines, column; + if (error) { + return callback(error); + } - return function (options, variables) { - var frames = [], importError; + // Start with the primary rule. + // The whole syntax tree is held under a Ruleset node, + // with the `root` property set to true, so no `{}` are + // output. The callback is called when the input is parsed. + try { + root = new(tree.Ruleset)([], $(this.parsers.primary)); + root.root = true; + } catch (e) { + return callback(new(LessError)(e, env)); + } - options = options || {}; - // - // Allows setting variables with a hash, so: - // - // `{ color: new(tree.Color)('#f01') }` will become: - // - // new(tree.Rule)('@color', - // new(tree.Value)([ - // new(tree.Expression)([ - // new(tree.Color)('#f01') - // ]) - // ]) - // ) - // - if (typeof(variables) === 'object' && !Array.isArray(variables)) { - variables = Object.keys(variables).map(function (k) { - var value = variables[k]; + root.toCSS = (function (evaluate) { + var line, lines, column; - if (! (value instanceof tree.Value)) { - if (! (value instanceof tree.Expression)) { - value = new(tree.Expression)([value]); - } - value = new(tree.Value)([value]); - } - return new(tree.Rule)('@' + k, value, false, 0); - }); - frames = [new(tree.Ruleset)(null, variables)]; - } + return function (options, variables) { + var frames = [], importError; - try { - var css = evaluate.call(this, { frames: frames }) - .toCSS([], { compress: options.compress || false }); - } catch (e) { - throw new(LessError)(e, env); - } + options = options || {}; + // + // Allows setting variables with a hash, so: + // + // `{ color: new(tree.Color)('#f01') }` will become: + // + // new(tree.Rule)('@color', + // new(tree.Value)([ + // new(tree.Expression)([ + // new(tree.Color)('#f01') + // ]) + // ]) + // ) + // + if (typeof(variables) === 'object' && !Array.isArray(variables)) { + variables = Object.keys(variables).map(function (k) { + var value = variables[k]; - if ((importError = parser.imports.error)) { // Check if there was an error during importing - if (importError instanceof LessError) throw importError; - else throw new(LessError)(importError, env); - } + if (! (value instanceof tree.Value)) { + if (! (value instanceof tree.Expression)) { + value = new(tree.Expression)([value]); + } + value = new(tree.Value)([value]); + } + return new(tree.Rule)('@' + k, value, false, 0); + }); + frames = [new(tree.Ruleset)(null, variables)]; + } - if (options.yuicompress && less.mode === 'node') { - return require('./cssmin').compressor.cssmin(css); - } else if (options.compress) { - return css.replace(/(\s)+/g, "$1"); - } else { - return css; - } - }; - })(root.eval); + try { + var css = evaluate.call(this, { frames: frames }) + .toCSS([], { compress: options.compress || false }); + } catch (e) { + throw new(LessError)(e, env); + } - // If `i` is smaller than the `input.length - 1`, - // it means the parser wasn't able to parse the whole - // string, so we've got a parsing error. - // - // We try to extract a \n delimited string, - // showing the line where the parse error occured. - // We split it up into two parts (the part which parsed, - // and the part which didn't), so we can color them differently. - if (i < input.length - 1) { - i = furthest; - lines = input.split('\n'); - line = (input.slice(0, i).match(/\n/g) || "").length + 1; + if ((importError = parser.imports.error)) { // Check if there was an error during importing + if (importError instanceof LessError) throw importError; + else throw new(LessError)(importError, env); + } - for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + if (options.yuicompress && less.mode === 'node') { + return require('./cssmin').compressor.cssmin(css); + } else if (options.compress) { + return css.replace(/(\s)+/g, "$1"); + } else { + return css; + } + }; + })(root.eval); - error = { - type: "Parse", - message: "Syntax Error on line " + line, - index: i, - filename: env.filename, - line: line, - column: column, - extract: [ - lines[line - 2], - lines[line - 1], - lines[line] - ] - }; - } + // If `i` is smaller than the `input.length - 1`, + // it means the parser wasn't able to parse the whole + // string, so we've got a parsing error. + // + // We try to extract a \n delimited string, + // showing the line where the parse error occured. + // We split it up into two parts (the part which parsed, + // and the part which didn't), so we can color them differently. + if (i < input.length - 1) { + i = furthest; + lines = input.split('\n'); + line = (input.slice(0, i).match(/\n/g) || "").length + 1; - if (this.imports.queue.length > 0) { - finish = function () { callback(error, root) }; - } else { - callback(error, root); - } + for (var n = i, column = -1; n >= 0 && input.charAt(n) !== '\n'; n--) { column++ } + + error = { + type: "Parse", + message: "Syntax Error on line " + line, + index: i, + filename: env.filename, + line: line, + column: column, + extract: [ + lines[line - 2], + lines[line - 1], + lines[line] + ] + }; + } + + if (this.imports.queue.length > 0) { + finish = function () { callback(error, root) }; + } else { + callback(error, root); + } + }, + + // + // Here in, the parsing rules/functions + // + // The basic structure of the syntax tree generated is as follows: + // + // Ruleset -> Rule -> Value -> Expression -> Entity + // + // Here's some LESS code: + // + // .class { + // color: #fff; + // border: 1px solid #000; + // width: @w + 4px; + // > .child {...} + // } + // + // And here's what the parse tree might look like: + // + // Ruleset (Selector '.class', [ + // Rule ("color", Value ([Expression [Color #fff]])) + // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) + // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) + // Ruleset (Selector [Element '>', '.child'], [...]) + // ]) + // + // In general, most rules will try to parse a token with the `$()` function, and if the return + // value is truly, will return a new node, of the relevant type. Sometimes, we need to check + // first, before parsing, that's when we use `peek()`. + // + parsers: { + // + // The `primary` rule is the *entry* and *exit* point of the parser. + // The rules here can appear at any level of the parse tree. + // + // The recursive nature of the grammar is an interplay between the `block` + // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, + // as represented by this simplified grammar: + // + // primary → (ruleset | rule)+ + // ruleset → selector+ block + // block → '{' primary '}' + // + // Only at one point is the primary rule not called from the + // block rule: at the root level. + // + primary: function () { + var node, root = []; + + while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || + $(this.mixin.call) || $(this.comment) || $(this.directive)) + || $(/^[\s\n]+/)) { + node && root.push(node); + } + return root; + }, + + // We create a Comment node for CSS comments `/* */`, + // but keep the LeSS comments `//` silent, by just skipping + // over them. + comment: function () { + var comment; + + if (input.charAt(i) !== '/') return; + + if (input.charAt(i + 1) === '/') { + return new(tree.Comment)($(/^\/\/.*/), true); + } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { + return new(tree.Comment)(comment); + } }, // - // Here in, the parsing rules/functions + // Entities are tokens which can be found inside an Expression // - // The basic structure of the syntax tree generated is as follows: - // - // Ruleset -> Rule -> Value -> Expression -> Entity - // - // Here's some LESS code: - // - // .class { - // color: #fff; - // border: 1px solid #000; - // width: @w + 4px; - // > .child {...} - // } - // - // And here's what the parse tree might look like: - // - // Ruleset (Selector '.class', [ - // Rule ("color", Value ([Expression [Color #fff]])) - // Rule ("border", Value ([Expression [Dimension 1px][Keyword "solid"][Color #000]])) - // Rule ("width", Value ([Expression [Operation "+" [Variable "@w"][Dimension 4px]]])) - // Ruleset (Selector [Element '>', '.child'], [...]) - // ]) - // - // In general, most rules will try to parse a token with the `$()` function, and if the return - // value is truly, will return a new node, of the relevant type. Sometimes, we need to check - // first, before parsing, that's when we use `peek()`. - // - parsers: { - // - // The `primary` rule is the *entry* and *exit* point of the parser. - // The rules here can appear at any level of the parse tree. - // - // The recursive nature of the grammar is an interplay between the `block` - // rule, which represents `{ ... }`, the `ruleset` rule, and this `primary` rule, - // as represented by this simplified grammar: - // - // primary → (ruleset | rule)+ - // ruleset → selector+ block - // block → '{' primary '}' - // - // Only at one point is the primary rule not called from the - // block rule: at the root level. - // - primary: function () { - var node, root = []; - - while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) || - $(this.mixin.call) || $(this.comment) || $(this.directive)) - || $(/^[\s\n]+/)) { - node && root.push(node); - } - return root; - }, - - // We create a Comment node for CSS comments `/* */`, - // but keep the LeSS comments `//` silent, by just skipping - // over them. - comment: function () { - var comment; - - if (input.charAt(i) !== '/') return; - - if (input.charAt(i + 1) === '/') { - return new(tree.Comment)($(/^\/\/.*/), true); - } else if (comment = $(/^\/\*(?:[^*]|\*+[^\/*])*\*+\/\n?/)) { - return new(tree.Comment)(comment); - } - }, - - // - // Entities are tokens which can be found inside an Expression - // - entities: { - // - // A string, which supports escaping " and ' - // - // "milky way" 'he\'s the one!' - // - quoted: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; - - e && $('~'); - - if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { - return new(tree.Quoted)(str[0], str[1] || str[2], e); - } - }, - - // - // A catch-all word, such as: - // - // black border-collapse - // - keyword: function () { - var k; - - if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { - if (tree.colors.hasOwnProperty(k)) { - // detect named color - return new(tree.Color)(tree.colors[k].slice(1)); - } else { - return new(tree.Keyword)(k); - } - } - }, - - // - // A function call - // - // rgb(255, 0, 255) - // - // We also try to catch IE's `alpha()`, but let the `alpha` parser - // deal with the details. - // - // The arguments are parsed with the `entities.arguments` parser. - // - call: function () { - var name, args, alpha_ret, index = i; - - if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; - - name = name[1].toLowerCase(); - - if (name === 'url') { return null } - else { i += name.length } - - if (name === 'alpha') { - alpha_ret = $(this.alpha); - if(typeof alpha_ret !== 'undefined') { - return alpha_ret; - } - } - - $('('); // Parse the '(' and consume whitespace. - - args = $(this.entities.arguments); - - if (! $(')')) return; - - if (name) { return new(tree.Call)(name, args, index, env.filename) } - }, - arguments: function () { - var args = [], arg; - - while (arg = $(this.entities.assignment) || $(this.expression)) { - args.push(arg); - if (! $(',')) { break } - } - return args; - }, - literal: function () { - return $(this.entities.dimension) || - $(this.entities.color) || - $(this.entities.quoted); - }, - - // Assignments are argument entities for calls. - // They are present in ie filter properties as shown below. - // - // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) - // - - assignment: function () { - var key, value; - if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { - return new(tree.Assignment)(key, value); - } - }, - - // - // Parse url() tokens - // - // We use a specific rule for urls, because they don't really behave like - // standard function calls. The difference is that the argument doesn't have - // to be enclosed within a string, so it can't be parsed as an Expression. - // - url: function () { - var value; - - if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; - value = $(this.entities.quoted) || $(this.entities.variable) || - $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; - - expect(')'); - - return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) - ? value : new(tree.Anonymous)(value), imports.paths); - }, - - dataURI: function () { - var obj; - - if ($(/^data:/)) { - obj = {}; - obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; - obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; - obj.base64 = $(/^;\s*base64/) || ''; - obj.data = $(/^,\s*[^)]+/); - - if (obj.data) { return obj } - } - }, - - // - // A Variable entity, such as `@fink`, in - // - // width: @fink + 2px - // - // We use a different parser for variable definitions, - // see `parsers.variable`. - // - variable: function () { - var name, index = i; - - if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { - return new(tree.Variable)(name, index, env.filename); - } - }, - - // - // A Hexadecimal color - // - // #4F3C2F - // - // `rgb` and `hsl` colors are parsed through the `entities.call` parser. - // - color: function () { - var rgb; - - if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { - return new(tree.Color)(rgb[1]); - } - }, - - // - // A Dimension, that is, a number and a unit - // - // 0.5em 95% - // - dimension: function () { - var value, c = input.charCodeAt(i); - if ((c > 57 || c < 45) || c === 47) return; - - if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { - return new(tree.Dimension)(value[1], value[2]); - } - }, - - // - // JavaScript code to be evaluated - // - // `window.location.href` - // - javascript: function () { - var str, j = i, e; - - if (input.charAt(j) === '~') { j++, e = true } // Escaped strings - if (input.charAt(j) !== '`') { return } - - e && $('~'); - - if (str = $(/^`([^`]*)`/)) { - return new(tree.JavaScript)(str[1], i, e); - } - } - }, - - // - // The variable part of a variable definition. Used in the `rule` parser - // - // @fink: - // - variable: function () { - var name; - - if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } - }, - - // - // A font size/line-height shorthand - // - // small/12px - // - // We need to peek first, or we'll match on keywords and dimensions - // - shorthand: function () { - var a, b; - - if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; - - if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { - return new(tree.Shorthand)(a, b); - } - }, - - // - // Mixins - // - mixin: { - // - // A Mixin call, with an optional argument list - // - // #mixins > .square(#fff); - // .rounded(4px, black); - // .button; - // - // The `while` loop is there because mixins can be - // namespaced, but we only support the child and descendant - // selector for now. - // - call: function () { - var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; - - if (s !== '.' && s !== '#') { return } - - while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { - elements.push(new(tree.Element)(c, e, i)); - c = $('>'); - } - if ($('(')) { - while (arg = $(this.expression)) { - value = arg; - name = null; - - // Variable - if (arg.value.length = 1) { - var val = arg.value[0]; - if (val instanceof tree.Variable) { - if ($(':')) { - if (value = $(this.expression)) { - name = val.name; - } else { - throw new(Error)("Expected value"); - } - } - } - } - - args.push({ name: name, value: value }); - - if (! $(',')) { break } - } - if (! $(')')) throw new(Error)("Expected )"); - } - - if ($(this.important)) { - important = true; - } - - if (elements.length > 0 && ($(';') || peek('}'))) { - return new(tree.mixin.Call)(elements, args, index, env.filename, important); - } - }, - - // - // A Mixin definition, with a list of parameters - // - // .rounded (@radius: 2px, @color) { - // ... - // } - // - // Until we have a finer grained state-machine, we have to - // do a look-ahead, to make sure we don't have a mixin call. - // See the `rule` function for more information. - // - // We start by matching `.rounded (`, and then proceed on to - // the argument list, which has optional default values. - // We store the parameters in `params`, with a `value` key, - // if there is a value, such as in the case of `@radius`. - // - // Once we've got our params list, and a closing `)`, we parse - // the `{...}` block. - // - definition: function () { - var name, params = [], match, ruleset, param, value, cond, variadic = false; - if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || - peek(/^[^{]*(;|})/)) return; - - save(); - - if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { - name = match[1]; - - do { - if (input.charAt(i) === '.' && $(/^\.{3}/)) { - variadic = true; - break; - } else if (param = $(this.entities.variable) || $(this.entities.literal) - || $(this.entities.keyword)) { - // Variable - if (param instanceof tree.Variable) { - if ($(':')) { - value = expect(this.expression, 'expected expression'); - params.push({ name: param.name, value: value }); - } else if ($(/^\.{3}/)) { - params.push({ name: param.name, variadic: true }); - variadic = true; - break; - } else { - params.push({ name: param.name }); - } - } else { - params.push({ value: param }); - } - } else { - break; - } - } while ($(',')) - - expect(')'); - - if ($(/^when/)) { // Guard - cond = expect(this.conditions, 'expected condition'); - } - - ruleset = $(this.block); - - if (ruleset) { - return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); - } else { - restore(); - } - } - } - }, - - // - // Entities are the smallest recognized token, - // and can be found inside a rule's value. - // - entity: function () { - return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || - $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || - $(this.comment); - }, - - // - // A Rule terminator. Note that we use `peek()` to check for '}', - // because the `block` rule will be expecting it, but we still need to make sure - // it's there, if ';' was ommitted. - // - end: function () { - return $(';') || peek('}'); - }, - - // - // IE's alpha function - // - // alpha(opacity=88) - // - alpha: function () { - var value; - - if (! $(/^\(opacity=/i)) return; - if (value = $(/^\d+/) || $(this.entities.variable)) { - expect(')'); - return new(tree.Alpha)(value); - } - }, - - // - // A Selector Element - // - // div - // + h1 - // #socks - // input[type="text"] - // - // Elements are the building blocks for Selectors, - // they are made out of a `Combinator` (see combinator rule), - // and an element name, such as a tag a class, or `*`. - // - element: function () { - var e, t, c, v; - - c = $(this.combinator); - e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || - $('*') || $(this.attribute) || $(/^\([^)@]+\)/); - - if (! e) { - $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); - } - - if (e) { return new(tree.Element)(c, e, i) } - - if (c.value && c.value.charAt(0) === '&') { - return new(tree.Element)(c, null, i); - } - }, - - // - // Combinators combine elements together, in a Selector. - // - // Because our parser isn't white-space sensitive, special care - // has to be taken, when parsing the descendant combinator, ` `, - // as it's an empty space. We have to check the previous character - // in the input, to see if it's a ` ` character. More info on how - // we deal with this in *combinator.js*. - // - combinator: function () { - var match, c = input.charAt(i); - - if (c === '>' || c === '+' || c === '~') { - i++; - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(c); - } else if (c === '&') { - match = '&'; - i++; - if(input.charAt(i) === ' ') { - match = '& '; - } - while (input.charAt(i) === ' ') { i++ } - return new(tree.Combinator)(match); - } else if (input.charAt(i - 1) === ' ') { - return new(tree.Combinator)(" "); + entities: { + // + // A string, which supports escaping " and ' + // + // "milky way" 'he\'s the one!' + // + quoted: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '"' && input.charAt(j) !== "'") return; + + e && $('~'); + + if (str = $(/^"((?:[^"\\\r\n]|\\.)*)"|'((?:[^'\\\r\n]|\\.)*)'/)) { + return new(tree.Quoted)(str[0], str[1] || str[2], e); + } + }, + + // + // A catch-all word, such as: + // + // black border-collapse + // + keyword: function () { + var k; + + if (k = $(/^[_A-Za-z-][_A-Za-z0-9-]*/)) { + if (tree.colors.hasOwnProperty(k)) { + // detect named color + return new(tree.Color)(tree.colors[k].slice(1)); } else { - return new(tree.Combinator)(null); + return new(tree.Keyword)(k); } - }, + } + }, - // - // A CSS Selector - // - // .class > div + h1 - // li a:hover - // - // Selectors are made out of one or more Elements, see above. - // - selector: function () { - var sel, e, elements = [], c, match; + // + // A function call + // + // rgb(255, 0, 255) + // + // We also try to catch IE's `alpha()`, but let the `alpha` parser + // deal with the details. + // + // The arguments are parsed with the `entities.arguments` parser. + // + call: function () { + var name, args, alpha_ret, index = i; - if ($('(')) { - sel = $(this.entity); - expect(')'); - return new(tree.Selector)([new(tree.Element)('', sel, i)]); + if (! (name = /^([\w-]+|%|progid:[\w\.]+)\(/.exec(chunks[j]))) return; + + name = name[1].toLowerCase(); + + if (name === 'url') { return null } + else { i += name.length } + + if (name === 'alpha') { + alpha_ret = $(this.alpha); + if(typeof alpha_ret !== 'undefined') { + return alpha_ret; } + } - while (e = $(this.element)) { - c = input.charAt(i); - elements.push(e) - if (c === '{' || c === '}' || c === ';' || c === ',') { break } + $('('); // Parse the '(' and consume whitespace. + + args = $(this.entities.arguments); + + if (! $(')')) return; + + if (name) { return new(tree.Call)(name, args, index, env.filename) } + }, + arguments: function () { + var args = [], arg; + + while (arg = $(this.entities.assignment) || $(this.expression)) { + args.push(arg); + if (! $(',')) { break } + } + return args; + }, + literal: function () { + return $(this.entities.dimension) || + $(this.entities.color) || + $(this.entities.quoted); + }, + + // Assignments are argument entities for calls. + // They are present in ie filter properties as shown below. + // + // filter: progid:DXImageTransform.Microsoft.Alpha( *opacity=50* ) + // + + assignment: function () { + var key, value; + if ((key = $(/^\w+(?=\s?=)/i)) && $('=') && (value = $(this.entity))) { + return new(tree.Assignment)(key, value); + } + }, + + // + // Parse url() tokens + // + // We use a specific rule for urls, because they don't really behave like + // standard function calls. The difference is that the argument doesn't have + // to be enclosed within a string, so it can't be parsed as an Expression. + // + url: function () { + var value; + + if (input.charAt(i) !== 'u' || !$(/^url\(/)) return; + value = $(this.entities.quoted) || $(this.entities.variable) || + $(this.entities.dataURI) || $(/^[-\w%@$\/.&=:;#+?~]+/) || ""; + + expect(')'); + + return new(tree.URL)((value.value || value.data || value instanceof tree.Variable) + ? value : new(tree.Anonymous)(value), imports.paths); + }, + + dataURI: function () { + var obj; + + if ($(/^data:/)) { + obj = {}; + obj.mime = $(/^[^\/]+\/[^,;)]+/) || ''; + obj.charset = $(/^;\s*charset=[^,;)]+/) || ''; + obj.base64 = $(/^;\s*base64/) || ''; + obj.data = $(/^,\s*[^)]+/); + + if (obj.data) { return obj } + } + }, + + // + // A Variable entity, such as `@fink`, in + // + // width: @fink + 2px + // + // We use a different parser for variable definitions, + // see `parsers.variable`. + // + variable: function () { + var name, index = i; + + if (input.charAt(i) === '@' && (name = $(/^@@?[\w-]+/))) { + return new(tree.Variable)(name, index, env.filename); + } + }, + + // + // A Hexadecimal color + // + // #4F3C2F + // + // `rgb` and `hsl` colors are parsed through the `entities.call` parser. + // + color: function () { + var rgb; + + if (input.charAt(i) === '#' && (rgb = $(/^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})/))) { + return new(tree.Color)(rgb[1]); + } + }, + + // + // A Dimension, that is, a number and a unit + // + // 0.5em 95% + // + dimension: function () { + var value, c = input.charCodeAt(i); + if ((c > 57 || c < 45) || c === 47) return; + + if (value = $(/^(-?\d*\.?\d+)(px|%|em|rem|pc|ex|in|deg|s|ms|pt|cm|mm|rad|grad|turn)?/)) { + return new(tree.Dimension)(value[1], value[2]); + } + }, + + // + // JavaScript code to be evaluated + // + // `window.location.href` + // + javascript: function () { + var str, j = i, e; + + if (input.charAt(j) === '~') { j++, e = true } // Escaped strings + if (input.charAt(j) !== '`') { return } + + e && $('~'); + + if (str = $(/^`([^`]*)`/)) { + return new(tree.JavaScript)(str[1], i, e); + } + } + }, + + // + // The variable part of a variable definition. Used in the `rule` parser + // + // @fink: + // + variable: function () { + var name; + + if (input.charAt(i) === '@' && (name = $(/^(@[\w-]+)\s*:/))) { return name[1] } + }, + + // + // A font size/line-height shorthand + // + // small/12px + // + // We need to peek first, or we'll match on keywords and dimensions + // + shorthand: function () { + var a, b; + + if (! peek(/^[@\w.%-]+\/[@\w.-]+/)) return; + + if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) { + return new(tree.Shorthand)(a, b); + } + }, + + // + // Mixins + // + mixin: { + // + // A Mixin call, with an optional argument list + // + // #mixins > .square(#fff); + // .rounded(4px, black); + // .button; + // + // The `while` loop is there because mixins can be + // namespaced, but we only support the child and descendant + // selector for now. + // + call: function () { + var elements = [], e, c, args = [], arg, index = i, s = input.charAt(i), name, value, important = false; + + if (s !== '.' && s !== '#') { return } + + while (e = $(/^[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) { + elements.push(new(tree.Element)(c, e, i)); + c = $('>'); + } + if ($('(')) { + while (arg = $(this.expression)) { + value = arg; + name = null; + + // Variable + if (arg.value.length = 1) { + var val = arg.value[0]; + if (val instanceof tree.Variable) { + if ($(':')) { + if (value = $(this.expression)) { + name = val.name; + } else { + throw new(Error)("Expected value"); + } + } + } + } + + args.push({ name: name, value: value }); + + if (! $(',')) { break } } + if (! $(')')) throw new(Error)("Expected )"); + } - if (elements.length > 0) { return new(tree.Selector)(elements) } - }, - tag: function () { - return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); - }, - attribute: function () { - var attr = '', key, val, op; + if ($(this.important)) { + important = true; + } - if (! $('[')) return; + if (elements.length > 0 && ($(';') || peek('}'))) { + return new(tree.mixin.Call)(elements, args, index, env.filename, important); + } + }, - if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { - if ((op = $(/^[|~*$^]?=/)) && - (val = $(this.entities.quoted) || $(/^[\w-]+/))) { - attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); - } else { attr = key } - } + // + // A Mixin definition, with a list of parameters + // + // .rounded (@radius: 2px, @color) { + // ... + // } + // + // Until we have a finer grained state-machine, we have to + // do a look-ahead, to make sure we don't have a mixin call. + // See the `rule` function for more information. + // + // We start by matching `.rounded (`, and then proceed on to + // the argument list, which has optional default values. + // We store the parameters in `params`, with a `value` key, + // if there is a value, such as in the case of `@radius`. + // + // Once we've got our params list, and a closing `)`, we parse + // the `{...}` block. + // + definition: function () { + var name, params = [], match, ruleset, param, value, cond, variadic = false; + if ((input.charAt(i) !== '.' && input.charAt(i) !== '#') || + peek(/^[^{]*(;|})/)) return; - if (! $(']')) return; + save(); - if (attr) { return "[" + attr + "]" } - }, - - // - // The `block` rule is used by `ruleset` and `mixin.definition`. - // It's a wrapper around the `primary` rule, with added `{}`. - // - block: function () { - var content; - - if ($('{') && (content = $(this.primary)) && $('}')) { - return content; - } - }, - - // - // div, .class, body > p {...} - // - ruleset: function () { - var selectors = [], s, rules, match; - save(); - - while (s = $(this.selector)) { - selectors.push(s); - $(this.comment); - if (! $(',')) { break } - $(this.comment); - } - - if (selectors.length > 0 && (rules = $(this.block))) { - return new(tree.Ruleset)(selectors, rules, env.strictImports); - } else { - // Backtrack - furthest = i; - restore(); - } - }, - rule: function () { - var name, value, c = input.charAt(i), important, match; - save(); - - if (c === '.' || c === '#' || c === '&') { return } - - if (name = $(this.variable) || $(this.property)) { - if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { - i += match[0].length - 1; - value = new(tree.Anonymous)(match[1]); - } else if (name === "font") { - value = $(this.font); - } else { - value = $(this.value); - } - important = $(this.important); - - if (value && $(this.end)) { - return new(tree.Rule)(name, value, important, memo); - } else { - furthest = i; - restore(); - } - } - }, - - // - // An @import directive - // - // @import "lib"; - // - // Depending on our environemnt, importing is done differently: - // In the browser, it's an XHR request, in Node, it would be a - // file-system operation. The function used for importing is - // stored in `import`, which we pass to the Import constructor. - // - "import": function () { - var path, features, index = i; - var dir = $(/^@import(?:-(once))?\s+/); - - if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { - features = $(this.mediaFeatures); - if ($(';')) { - return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); - } - } - }, - - mediaFeature: function () { - var e, p, nodes = []; + if (match = $(/^([#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+)\s*\(/)) { + name = match[1]; do { - if (e = $(this.entities.keyword)) { - nodes.push(e); - } else if ($('(')) { - p = $(this.property); - e = $(this.entity); - if ($(')')) { - if (p && e) { - nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); - } else if (e) { - nodes.push(new(tree.Paren)(e)); - } else { - return null; - } - } else { return null } - } - } while (e); - - if (nodes.length > 0) { - return new(tree.Expression)(nodes); - } - }, - - mediaFeatures: function () { - var e, features = []; - - do { - if (e = $(this.mediaFeature)) { - features.push(e); - if (! $(',')) { break } - } else if (e = $(this.entities.variable)) { - features.push(e); - if (! $(',')) { break } - } - } while (e); - - return features.length > 0 ? features : null; - }, - - media: function () { - var features, rules; - - if ($(/^@media/)) { - features = $(this.mediaFeatures); - - if (rules = $(this.block)) { - return new(tree.Media)(rules, features); - } - } - }, - - // - // A CSS Directive - // - // @charset "utf-8"; - // - directive: function () { - var name, value, rules, types, e, nodes; - - if (input.charAt(i) !== '@') return; - - if (value = $(this['import']) || $(this.media)) { - return value; - } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { - types = ($(/^[^{]+/) || '').trim(); - if (rules = $(this.block)) { - return new(tree.Directive)(name + " " + types, rules); - } - } else if (name = $(/^@[-a-z]+/)) { - if (name === '@font-face') { - if (rules = $(this.block)) { - return new(tree.Directive)(name, rules); - } - } else if ((value = $(this.entity)) && $(';')) { - return new(tree.Directive)(name, value); - } - } - }, - font: function () { - var value = [], expression = [], weight, shorthand, font, e; - - while (e = $(this.shorthand) || $(this.entity)) { - expression.push(e); - } - value.push(new(tree.Expression)(expression)); - - if ($(',')) { - while (e = $(this.expression)) { - value.push(e); - if (! $(',')) { break } - } - } - return new(tree.Value)(value); - }, - - // - // A Value is a comma-delimited list of Expressions - // - // font-family: Baskerville, Georgia, serif; - // - // In a Rule, a Value represents everything after the `:`, - // and before the `;`. - // - value: function () { - var e, expressions = [], important; - - while (e = $(this.expression)) { - expressions.push(e); - if (! $(',')) { break } - } - - if (expressions.length > 0) { - return new(tree.Value)(expressions); - } - }, - important: function () { - if (input.charAt(i) === '!') { - return $(/^! *important/); - } - }, - sub: function () { - var e; - - if ($('(') && (e = $(this.expression)) && $(')')) { - return e; - } - }, - multiplication: function () { - var m, a, op, operation; - if (m = $(this.operand)) { - while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - addition: function () { - var m, a, op, operation; - if (m = $(this.multiplication)) { - while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && - (a = $(this.multiplication))) { - operation = new(tree.Operation)(op, [operation || m, a]); - } - return operation || m; - } - }, - conditions: function () { - var a, b, index = i, condition; - - if (a = $(this.condition)) { - while ($(',') && (b = $(this.condition))) { - condition = new(tree.Condition)('or', condition || a, b, index); - } - return condition || a; - } - }, - condition: function () { - var a, b, c, op, index = i, negate = false; - - if ($(/^not/)) { negate = true } - expect('('); - if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - if (op = $(/^(?:>=|=<|[<=>])/)) { - if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { - c = new(tree.Condition)(op, a, b, index, negate); + if (input.charAt(i) === '.' && $(/^\.{3}/)) { + variadic = true; + break; + } else if (param = $(this.entities.variable) || $(this.entities.literal) + || $(this.entities.keyword)) { + // Variable + if (param instanceof tree.Variable) { + if ($(':')) { + value = expect(this.expression, 'expected expression'); + params.push({ name: param.name, value: value }); + } else if ($(/^\.{3}/)) { + params.push({ name: param.name, variadic: true }); + variadic = true; + break; } else { - error('expected expression'); + params.push({ name: param.name }); } - } else { - c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); - } - expect(')'); - return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } else { + params.push({ value: param }); + } + } else { + break; + } + } while ($(',')) + + expect(')'); + + if ($(/^when/)) { // Guard + cond = expect(this.conditions, 'expected condition'); } - }, - // - // An operand is anything that can be part of an operation, - // such as a Color, or a Variable - // - operand: function () { - var negate, p = input.charAt(i + 1); + ruleset = $(this.block); - if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } - var o = $(this.sub) || $(this.entities.dimension) || - $(this.entities.color) || $(this.entities.variable) || - $(this.entities.call); - return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) - : o; - }, - - // - // Expressions either represent mathematical operations, - // or white-space delimited Entities. - // - // 1px solid black - // @var * 2 - // - expression: function () { - var e, delim, entities = [], d; - - while (e = $(this.addition) || $(this.entity)) { - entities.push(e); + if (ruleset) { + return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic); + } else { + restore(); } - if (entities.length > 0) { - return new(tree.Expression)(entities); - } - }, - property: function () { - var name; + } + } + }, - if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { - return name[1]; - } + // + // Entities are the smallest recognized token, + // and can be found inside a rule's value. + // + entity: function () { + return $(this.entities.literal) || $(this.entities.variable) || $(this.entities.url) || + $(this.entities.call) || $(this.entities.keyword) || $(this.entities.javascript) || + $(this.comment); + }, + + // + // A Rule terminator. Note that we use `peek()` to check for '}', + // because the `block` rule will be expecting it, but we still need to make sure + // it's there, if ';' was ommitted. + // + end: function () { + return $(';') || peek('}'); + }, + + // + // IE's alpha function + // + // alpha(opacity=88) + // + alpha: function () { + var value; + + if (! $(/^\(opacity=/i)) return; + if (value = $(/^\d+/) || $(this.entities.variable)) { + expect(')'); + return new(tree.Alpha)(value); + } + }, + + // + // A Selector Element + // + // div + // + h1 + // #socks + // input[type="text"] + // + // Elements are the building blocks for Selectors, + // they are made out of a `Combinator` (see combinator rule), + // and an element name, such as a tag a class, or `*`. + // + element: function () { + var e, t, c, v; + + c = $(this.combinator); + e = $(/^(?:\d+\.\d+|\d+)%/) || $(/^(?:[.#]?|:*)(?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/) || + $('*') || $(this.attribute) || $(/^\([^)@]+\)/); + + if (! e) { + $('(') && (v = $(this.entities.variable)) && $(')') && (e = new(tree.Paren)(v)); + } + + if (e) { return new(tree.Element)(c, e, i) } + + if (c.value && c.value.charAt(0) === '&') { + return new(tree.Element)(c, null, i); + } + }, + + // + // Combinators combine elements together, in a Selector. + // + // Because our parser isn't white-space sensitive, special care + // has to be taken, when parsing the descendant combinator, ` `, + // as it's an empty space. We have to check the previous character + // in the input, to see if it's a ` ` character. More info on how + // we deal with this in *combinator.js*. + // + combinator: function () { + var match, c = input.charAt(i); + + if (c === '>' || c === '+' || c === '~') { + i++; + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(c); + } else if (c === '&') { + match = '&'; + i++; + if(input.charAt(i) === ' ') { + match = '& '; + } + while (input.charAt(i) === ' ') { i++ } + return new(tree.Combinator)(match); + } else if (input.charAt(i - 1) === ' ') { + return new(tree.Combinator)(" "); + } else { + return new(tree.Combinator)(null); + } + }, + + // + // A CSS Selector + // + // .class > div + h1 + // li a:hover + // + // Selectors are made out of one or more Elements, see above. + // + selector: function () { + var sel, e, elements = [], c, match; + + if ($('(')) { + sel = $(this.entity); + expect(')'); + return new(tree.Selector)([new(tree.Element)('', sel, i)]); + } + + while (e = $(this.element)) { + c = input.charAt(i); + elements.push(e) + if (c === '{' || c === '}' || c === ';' || c === ',') { break } + } + + if (elements.length > 0) { return new(tree.Selector)(elements) } + }, + tag: function () { + return $(/^[a-zA-Z][a-zA-Z-]*[0-9]?/) || $('*'); + }, + attribute: function () { + var attr = '', key, val, op; + + if (! $('[')) return; + + if (key = $(/^[a-zA-Z-]+/) || $(this.entities.quoted)) { + if ((op = $(/^[|~*$^]?=/)) && + (val = $(this.entities.quoted) || $(/^[\w-]+/))) { + attr = [key, op, val.toCSS ? val.toCSS() : val].join(''); + } else { attr = key } + } + + if (! $(']')) return; + + if (attr) { return "[" + attr + "]" } + }, + + // + // The `block` rule is used by `ruleset` and `mixin.definition`. + // It's a wrapper around the `primary` rule, with added `{}`. + // + block: function () { + var content; + + if ($('{') && (content = $(this.primary)) && $('}')) { + return content; + } + }, + + // + // div, .class, body > p {...} + // + ruleset: function () { + var selectors = [], s, rules, match; + save(); + + while (s = $(this.selector)) { + selectors.push(s); + $(this.comment); + if (! $(',')) { break } + $(this.comment); + } + + if (selectors.length > 0 && (rules = $(this.block))) { + return new(tree.Ruleset)(selectors, rules, env.strictImports); + } else { + // Backtrack + furthest = i; + restore(); + } + }, + rule: function () { + var name, value, c = input.charAt(i), important, match; + save(); + + if (c === '.' || c === '#' || c === '&') { return } + + if (name = $(this.variable) || $(this.property)) { + if ((name.charAt(0) != '@') && (match = /^([^@+\/'"*`(;{}-]*);/.exec(chunks[j]))) { + i += match[0].length - 1; + value = new(tree.Anonymous)(match[1]); + } else if (name === "font") { + value = $(this.font); + } else { + value = $(this.value); + } + important = $(this.important); + + if (value && $(this.end)) { + return new(tree.Rule)(name, value, important, memo); + } else { + furthest = i; + restore(); + } + } + }, + + // + // An @import directive + // + // @import "lib"; + // + // Depending on our environemnt, importing is done differently: + // In the browser, it's an XHR request, in Node, it would be a + // file-system operation. The function used for importing is + // stored in `import`, which we pass to the Import constructor. + // + "import": function () { + var path, features, index = i; + var dir = $(/^@import(?:-(once))?\s+/); + + if (dir && (path = $(this.entities.quoted) || $(this.entities.url))) { + features = $(this.mediaFeatures); + if ($(';')) { + return new(tree.Import)(path, imports, features, (dir[1] === 'once'), index); + } + } + }, + + mediaFeature: function () { + var e, p, nodes = []; + + do { + if (e = $(this.entities.keyword)) { + nodes.push(e); + } else if ($('(')) { + p = $(this.property); + e = $(this.entity); + if ($(')')) { + if (p && e) { + nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, true))); + } else if (e) { + nodes.push(new(tree.Paren)(e)); + } else { + return null; + } + } else { return null } + } + } while (e); + + if (nodes.length > 0) { + return new(tree.Expression)(nodes); + } + }, + + mediaFeatures: function () { + var e, features = []; + + do { + if (e = $(this.mediaFeature)) { + features.push(e); + if (! $(',')) { break } + } else if (e = $(this.entities.variable)) { + features.push(e); + if (! $(',')) { break } } + } while (e); + + return features.length > 0 ? features : null; + }, + + media: function () { + var features, rules; + + if ($(/^@media/)) { + features = $(this.mediaFeatures); + + if (rules = $(this.block)) { + return new(tree.Media)(rules, features); + } + } + }, + + // + // A CSS Directive + // + // @charset "utf-8"; + // + directive: function () { + var name, value, rules, types, e, nodes; + + if (input.charAt(i) !== '@') return; + + if (value = $(this['import']) || $(this.media)) { + return value; + } else if (name = $(/^@page|@keyframes/) || $(/^@(?:-webkit-|-moz-|-o-|-ms-)[a-z0-9-]+/)) { + types = ($(/^[^{]+/) || '').trim(); + if (rules = $(this.block)) { + return new(tree.Directive)(name + " " + types, rules); + } + } else if (name = $(/^@[-a-z]+/)) { + if (name === '@font-face') { + if (rules = $(this.block)) { + return new(tree.Directive)(name, rules); + } + } else if ((value = $(this.entity)) && $(';')) { + return new(tree.Directive)(name, value); + } + } + }, + font: function () { + var value = [], expression = [], weight, shorthand, font, e; + + while (e = $(this.shorthand) || $(this.entity)) { + expression.push(e); + } + value.push(new(tree.Expression)(expression)); + + if ($(',')) { + while (e = $(this.expression)) { + value.push(e); + if (! $(',')) { break } + } + } + return new(tree.Value)(value); + }, + + // + // A Value is a comma-delimited list of Expressions + // + // font-family: Baskerville, Georgia, serif; + // + // In a Rule, a Value represents everything after the `:`, + // and before the `;`. + // + value: function () { + var e, expressions = [], important; + + while (e = $(this.expression)) { + expressions.push(e); + if (! $(',')) { break } + } + + if (expressions.length > 0) { + return new(tree.Value)(expressions); + } + }, + important: function () { + if (input.charAt(i) === '!') { + return $(/^! *important/); + } + }, + sub: function () { + var e; + + if ($('(') && (e = $(this.expression)) && $(')')) { + return e; + } + }, + multiplication: function () { + var m, a, op, operation; + if (m = $(this.operand)) { + while (!peek(/^\/\*/) && (op = ($('/') || $('*'))) && (a = $(this.operand))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + addition: function () { + var m, a, op, operation; + if (m = $(this.multiplication)) { + while ((op = $(/^[-+]\s+/) || (input.charAt(i - 1) != ' ' && ($('+') || $('-')))) && + (a = $(this.multiplication))) { + operation = new(tree.Operation)(op, [operation || m, a]); + } + return operation || m; + } + }, + conditions: function () { + var a, b, index = i, condition; + + if (a = $(this.condition)) { + while ($(',') && (b = $(this.condition))) { + condition = new(tree.Condition)('or', condition || a, b, index); + } + return condition || a; + } + }, + condition: function () { + var a, b, c, op, index = i, negate = false; + + if ($(/^not/)) { negate = true } + expect('('); + if (a = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + if (op = $(/^(?:>=|=<|[<=>])/)) { + if (b = $(this.addition) || $(this.entities.keyword) || $(this.entities.quoted)) { + c = new(tree.Condition)(op, a, b, index, negate); + } else { + error('expected expression'); + } + } else { + c = new(tree.Condition)('=', a, new(tree.Keyword)('true'), index, negate); + } + expect(')'); + return $(/^and/) ? new(tree.Condition)('and', c, $(this.condition)) : c; + } + }, + + // + // An operand is anything that can be part of an operation, + // such as a Color, or a Variable + // + operand: function () { + var negate, p = input.charAt(i + 1); + + if (input.charAt(i) === '-' && (p === '@' || p === '(')) { negate = $('-') } + var o = $(this.sub) || $(this.entities.dimension) || + $(this.entities.color) || $(this.entities.variable) || + $(this.entities.call); + return negate ? new(tree.Operation)('*', [new(tree.Dimension)(-1), o]) + : o; + }, + + // + // Expressions either represent mathematical operations, + // or white-space delimited Entities. + // + // 1px solid black + // @var * 2 + // + expression: function () { + var e, delim, entities = [], d; + + while (e = $(this.addition) || $(this.entity)) { + entities.push(e); + } + if (entities.length > 0) { + return new(tree.Expression)(entities); + } + }, + property: function () { + var name; + + if (name = $(/^(\*?-?[-a-z_0-9]+)\s*:/)) { + return name[1]; + } } - }; + } + }; }; if (less.mode === 'browser' || less.mode === 'rhino') { - // - // Used by `@import` directives - // - less.Parser.importer = function (path, paths, callback, env) { - if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { - path = paths[0] + path; + // + // Used by `@import` directives + // + less.Parser.importer = function (path, paths, callback, env) { + if (!/^([a-z]+:)?\//.test(path) && paths.length > 0) { + path = paths[0] + path; + } + // We pass `true` as 3rd argument, to force the reload of the import. + // This is so we can get the syntax tree as opposed to just the CSS output, + // as we need this to evaluate the current stylesheet. + loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { + if (e && typeof(env.errback) === "function") { + env.errback.call(null, path, paths, callback, env); + } else { + callback.apply(null, arguments); } - // We pass `true` as 3rd argument, to force the reload of the import. - // This is so we can get the syntax tree as opposed to just the CSS output, - // as we need this to evaluate the current stylesheet. - loadStyleSheet({ href: path, title: path, type: env.mime }, function (e) { - if (e && typeof(env.errback) === "function") { - env.errback.call(null, path, paths, callback, env); - } else { - callback.apply(null, arguments); - } - }, true); - }; + }, true); + }; } (function (tree) { tree.functions = { - rgb: function (r, g, b) { - return this.rgba(r, g, b, 1.0); - }, - rgba: function (r, g, b, a) { - var rgb = [r, g, b].map(function (c) { return number(c) }), - a = number(a); - return new(tree.Color)(rgb, a); - }, - hsl: function (h, s, l) { - return this.hsla(h, s, l, 1.0); - }, - hsla: function (h, s, l, a) { - h = (number(h) % 360) / 360; - s = number(s); l = number(l); a = number(a); + rgb: function (r, g, b) { + return this.rgba(r, g, b, 1.0); + }, + rgba: function (r, g, b, a) { + var rgb = [r, g, b].map(function (c) { return number(c) }), + a = number(a); + return new(tree.Color)(rgb, a); + }, + hsl: function (h, s, l) { + return this.hsla(h, s, l, 1.0); + }, + hsla: function (h, s, l, a) { + h = (number(h) % 360) / 360; + s = number(s); l = number(l); a = number(a); - var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; - var m1 = l * 2 - m2; + var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s; + var m1 = l * 2 - m2; - return this.rgba(hue(h + 1/3) * 255, - hue(h) * 255, - hue(h - 1/3) * 255, - a); + return this.rgba(hue(h + 1/3) * 255, + hue(h) * 255, + hue(h - 1/3) * 255, + a); - function hue(h) { - h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); - if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; - else if (h * 2 < 1) return m2; - else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; - else return m1; - } - }, - hue: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().h)); - }, - saturation: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); - }, - lightness: function (color) { - return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); - }, - alpha: function (color) { - return new(tree.Dimension)(color.toHSL().a); - }, - saturate: function (color, amount) { - var hsl = color.toHSL(); + function hue(h) { + h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h); + if (h * 6 < 1) return m1 + (m2 - m1) * h * 6; + else if (h * 2 < 1) return m2; + else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6; + else return m1; + } + }, + hue: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().h)); + }, + saturation: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%'); + }, + lightness: function (color) { + return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%'); + }, + alpha: function (color) { + return new(tree.Dimension)(color.toHSL().a); + }, + saturate: function (color, amount) { + var hsl = color.toHSL(); - hsl.s += amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - desaturate: function (color, amount) { - var hsl = color.toHSL(); + hsl.s += amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + desaturate: function (color, amount) { + var hsl = color.toHSL(); - hsl.s -= amount.value / 100; - hsl.s = clamp(hsl.s); - return hsla(hsl); - }, - lighten: function (color, amount) { - var hsl = color.toHSL(); + hsl.s -= amount.value / 100; + hsl.s = clamp(hsl.s); + return hsla(hsl); + }, + lighten: function (color, amount) { + var hsl = color.toHSL(); - hsl.l += amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - darken: function (color, amount) { - var hsl = color.toHSL(); + hsl.l += amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + darken: function (color, amount) { + var hsl = color.toHSL(); - hsl.l -= amount.value / 100; - hsl.l = clamp(hsl.l); - return hsla(hsl); - }, - fadein: function (color, amount) { - var hsl = color.toHSL(); + hsl.l -= amount.value / 100; + hsl.l = clamp(hsl.l); + return hsla(hsl); + }, + fadein: function (color, amount) { + var hsl = color.toHSL(); - hsl.a += amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fadeout: function (color, amount) { - var hsl = color.toHSL(); + hsl.a += amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fadeout: function (color, amount) { + var hsl = color.toHSL(); - hsl.a -= amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - fade: function (color, amount) { - var hsl = color.toHSL(); + hsl.a -= amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + fade: function (color, amount) { + var hsl = color.toHSL(); - hsl.a = amount.value / 100; - hsl.a = clamp(hsl.a); - return hsla(hsl); - }, - spin: function (color, amount) { - var hsl = color.toHSL(); - var hue = (hsl.h + amount.value) % 360; + hsl.a = amount.value / 100; + hsl.a = clamp(hsl.a); + return hsla(hsl); + }, + spin: function (color, amount) { + var hsl = color.toHSL(); + var hue = (hsl.h + amount.value) % 360; - hsl.h = hue < 0 ? 360 + hue : hue; + hsl.h = hue < 0 ? 360 + hue : hue; - return hsla(hsl); - }, - // - // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein - // http://sass-lang.com - // - mix: function (color1, color2, weight) { - var p = weight.value / 100.0; - var w = p * 2 - 1; - var a = color1.toHSL().a - color2.toHSL().a; + return hsla(hsl); + }, + // + // Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein + // http://sass-lang.com + // + mix: function (color1, color2, weight) { + var p = weight.value / 100.0; + var w = p * 2 - 1; + var a = color1.toHSL().a - color2.toHSL().a; - var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; - var w2 = 1 - w1; + var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0; + var w2 = 1 - w1; - var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, - color1.rgb[1] * w1 + color2.rgb[1] * w2, - color1.rgb[2] * w1 + color2.rgb[2] * w2]; + var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2, + color1.rgb[1] * w1 + color2.rgb[1] * w2, + color1.rgb[2] * w1 + color2.rgb[2] * w2]; - var alpha = color1.alpha * p + color2.alpha * (1 - p); + var alpha = color1.alpha * p + color2.alpha * (1 - p); - return new(tree.Color)(rgb, alpha); - }, - greyscale: function (color) { - return this.desaturate(color, new(tree.Dimension)(100)); - }, - e: function (str) { - return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); - }, - escape: function (str) { - return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); - }, - '%': function (quoted /* arg, arg, ...*/) { - var args = Array.prototype.slice.call(arguments, 1), - str = quoted.value; + return new(tree.Color)(rgb, alpha); + }, + greyscale: function (color) { + return this.desaturate(color, new(tree.Dimension)(100)); + }, + e: function (str) { + return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str); + }, + escape: function (str) { + return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29")); + }, + '%': function (quoted /* arg, arg, ...*/) { + var args = Array.prototype.slice.call(arguments, 1), + str = quoted.value; - for (var i = 0; i < args.length; i++) { - str = str.replace(/%[sda]/i, function(token) { - var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); - return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; - }); - } - str = str.replace(/%%/g, '%'); - return new(tree.Quoted)('"' + str + '"', str); - }, - round: function (n) { - return this._math('round', n); - }, - ceil: function (n) { - return this._math('ceil', n); - }, - floor: function (n) { - return this._math('floor', n); - }, - _math: function (fn, n) { - if (n instanceof tree.Dimension) { - return new(tree.Dimension)(Math[fn](number(n)), n.unit); - } else if (typeof(n) === 'number') { - return Math[fn](n); - } else { - throw { type: "Argument", message: "argument must be a number" }; - } - }, - argb: function (color) { - return new(tree.Anonymous)(color.toARGB()); + for (var i = 0; i < args.length; i++) { + str = str.replace(/%[sda]/i, function(token) { + var value = token.match(/s/i) ? args[i].value : args[i].toCSS(); + return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value; + }); + } + str = str.replace(/%%/g, '%'); + return new(tree.Quoted)('"' + str + '"', str); + }, + round: function (n) { + return this._math('round', n); + }, + ceil: function (n) { + return this._math('ceil', n); + }, + floor: function (n) { + return this._math('floor', n); + }, + _math: function (fn, n) { + if (n instanceof tree.Dimension) { + return new(tree.Dimension)(Math[fn](number(n)), n.unit); + } else if (typeof(n) === 'number') { + return Math[fn](n); + } else { + throw { type: "Argument", message: "argument must be a number" }; + } + }, + argb: function (color) { + return new(tree.Anonymous)(color.toARGB()); - }, - percentage: function (n) { - return new(tree.Dimension)(n.value * 100, '%'); - }, - color: function (n) { - if (n instanceof tree.Quoted) { - return new(tree.Color)(n.value.slice(1)); - } else { - throw { type: "Argument", message: "argument must be a string" }; - } - }, - iscolor: function (n) { - return this._isa(n, tree.Color); - }, - isnumber: function (n) { - return this._isa(n, tree.Dimension); - }, - isstring: function (n) { - return this._isa(n, tree.Quoted); - }, - iskeyword: function (n) { - return this._isa(n, tree.Keyword); - }, - isurl: function (n) { - return this._isa(n, tree.URL); - }, - ispixel: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; - }, - ispercentage: function (n) { - return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; - }, - isem: function (n) { - return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; - }, - _isa: function (n, Type) { - return (n instanceof Type) ? tree.True : tree.False; - } + }, + percentage: function (n) { + return new(tree.Dimension)(n.value * 100, '%'); + }, + color: function (n) { + if (n instanceof tree.Quoted) { + return new(tree.Color)(n.value.slice(1)); + } else { + throw { type: "Argument", message: "argument must be a string" }; + } + }, + iscolor: function (n) { + return this._isa(n, tree.Color); + }, + isnumber: function (n) { + return this._isa(n, tree.Dimension); + }, + isstring: function (n) { + return this._isa(n, tree.Quoted); + }, + iskeyword: function (n) { + return this._isa(n, tree.Keyword); + }, + isurl: function (n) { + return this._isa(n, tree.URL); + }, + ispixel: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False; + }, + ispercentage: function (n) { + return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False; + }, + isem: function (n) { + return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False; + }, + _isa: function (n, Type) { + return (n instanceof Type) ? tree.True : tree.False; + } }; function hsla(hsla) { - return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); + return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a); } function number(n) { - if (n instanceof tree.Dimension) { - return parseFloat(n.unit == '%' ? n.value / 100 : n.value); - } else if (typeof(n) === 'number') { - return n; - } else { - throw { - error: "RuntimeError", - message: "color functions take numbers as parameters" - }; - } + if (n instanceof tree.Dimension) { + return parseFloat(n.unit == '%' ? n.value / 100 : n.value); + } else if (typeof(n) === 'number') { + return n; + } else { + throw { + error: "RuntimeError", + message: "color functions take numbers as parameters" + }; + } } function clamp(val) { - return Math.min(1, Math.max(0, val)); + return Math.min(1, Math.max(0, val)); } })(require('./tree')); (function (tree) { tree.Alpha = function (val) { - this.value = val; + this.value = val; }; tree.Alpha.prototype = { - toCSS: function () { - return "alpha(opacity=" + - (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } + toCSS: function () { + return "alpha(opacity=" + + (this.value.toCSS ? this.value.toCSS() : this.value) + ")"; + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } }; })(require('../tree')); (function (tree) { tree.Anonymous = function (string) { - this.value = string.value || string; + this.value = string.value || string; }; tree.Anonymous.prototype = { - toCSS: function () { - return this.value; - }, - eval: function () { return this } + toCSS: function () { + return this.value; + }, + eval: function () { return this } }; })(require('../tree')); (function (tree) { tree.Assignment = function (key, val) { - this.key = key; - this.value = val; + this.key = key; + this.value = val; }; tree.Assignment.prototype = { - toCSS: function () { - return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); - }, - eval: function (env) { - if (this.value.eval) { this.value = this.value.eval(env) } - return this; - } + toCSS: function () { + return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value); + }, + eval: function (env) { + if (this.value.eval) { this.value = this.value.eval(env) } + return this; + } }; })(require('../tree'));(function (tree) { @@ -1751,45 +1751,45 @@ tree.Assignment.prototype = { // A function call node. // tree.Call = function (name, args, index, filename) { - this.name = name; - this.args = args; - this.index = index; - this.filename = filename; + this.name = name; + this.args = args; + this.index = index; + this.filename = filename; }; tree.Call.prototype = { - // - // When evaluating a function call, - // we either find the function in `tree.functions` [1], - // in which case we call it, passing the evaluated arguments, - // or we simply print it out as it appeared originally [2]. - // - // The *functions.js* file contains the built-in functions. - // - // The reason why we evaluate the arguments, is in the case where - // we try to pass a variable to a function, like: `saturate(@color)`. - // The function should receive the value, not the variable. - // - eval: function (env) { - var args = this.args.map(function (a) { return a.eval(env) }); + // + // When evaluating a function call, + // we either find the function in `tree.functions` [1], + // in which case we call it, passing the evaluated arguments, + // or we simply print it out as it appeared originally [2]. + // + // The *functions.js* file contains the built-in functions. + // + // The reason why we evaluate the arguments, is in the case where + // we try to pass a variable to a function, like: `saturate(@color)`. + // The function should receive the value, not the variable. + // + eval: function (env) { + var args = this.args.map(function (a) { return a.eval(env) }); - if (this.name in tree.functions) { // 1. - try { - return tree.functions[this.name].apply(tree.functions, args); - } catch (e) { - throw { type: e.type || "Runtime", - message: "error evaluating function `" + this.name + "`" + - (e.message ? ': ' + e.message : ''), - index: this.index, filename: this.filename }; - } - } else { // 2. - return new(tree.Anonymous)(this.name + - "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + if (this.name in tree.functions) { // 1. + try { + return tree.functions[this.name].apply(tree.functions, args); + } catch (e) { + throw { type: e.type || "Runtime", + message: "error evaluating function `" + this.name + "`" + + (e.message ? ': ' + e.message : ''), + index: this.index, filename: this.filename }; } - }, + } else { // 2. + return new(tree.Anonymous)(this.name + + "(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")"); + } + }, - toCSS: function (env) { - return this.eval(env).toCSS(); - } + toCSS: function (env) { + return this.eval(env).toCSS(); + } }; })(require('../tree')); @@ -1798,98 +1798,98 @@ tree.Call.prototype = { // RGB Colors - #ff0014, #eee // tree.Color = function (rgb, a) { - // - // The end goal here, is to parse the arguments - // into an integer triplet, such as `128, 255, 0` - // - // This facilitates operations and conversions. - // - if (Array.isArray(rgb)) { - this.rgb = rgb; - } else if (rgb.length == 6) { - this.rgb = rgb.match(/.{2}/g).map(function (c) { - return parseInt(c, 16); - }); - } else { - this.rgb = rgb.split('').map(function (c) { - return parseInt(c + c, 16); - }); - } - this.alpha = typeof(a) === 'number' ? a : 1; + // + // The end goal here, is to parse the arguments + // into an integer triplet, such as `128, 255, 0` + // + // This facilitates operations and conversions. + // + if (Array.isArray(rgb)) { + this.rgb = rgb; + } else if (rgb.length == 6) { + this.rgb = rgb.match(/.{2}/g).map(function (c) { + return parseInt(c, 16); + }); + } else { + this.rgb = rgb.split('').map(function (c) { + return parseInt(c + c, 16); + }); + } + this.alpha = typeof(a) === 'number' ? a : 1; }; tree.Color.prototype = { - eval: function () { return this }, + eval: function () { return this }, - // - // If we have some transparency, the only way to represent it - // is via `rgba`. Otherwise, we use the hex representation, - // which has better compatibility with older browsers. - // Values are capped between `0` and `255`, rounded and zero-padded. - // - toCSS: function () { - if (this.alpha < 1.0) { - return "rgba(" + this.rgb.map(function (c) { - return Math.round(c); - }).concat(this.alpha).join(', ') + ")"; - } else { - return '#' + this.rgb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; - }).join(''); - } - }, - - // - // Operations have to be done per-channel, if not, - // channels will spill onto each other. Once we have - // our result, in the form of an integer triplet, - // we create a new Color node to hold the result. - // - operate: function (op, other) { - var result = []; - - if (! (other instanceof tree.Color)) { - other = other.toColor(); - } - - for (var c = 0; c < 3; c++) { - result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); - } - return new(tree.Color)(result, this.alpha + other.alpha); - }, - - toHSL: function () { - var r = this.rgb[0] / 255, - g = this.rgb[1] / 255, - b = this.rgb[2] / 255, - a = this.alpha; - - var max = Math.max(r, g, b), min = Math.min(r, g, b); - var h, s, l = (max + min) / 2, d = max - min; - - if (max === min) { - h = s = 0; - } else { - s = l > 0.5 ? d / (2 - max - min) : d / (max + min); - - switch (max) { - case r: h = (g - b) / d + (g < b ? 6 : 0); break; - case g: h = (b - r) / d + 2; break; - case b: h = (r - g) / d + 4; break; - } - h /= 6; - } - return { h: h * 360, s: s, l: l, a: a }; - }, - toARGB: function () { - var argb = [Math.round(this.alpha * 255)].concat(this.rgb); - return '#' + argb.map(function (i) { - i = Math.round(i); - i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); - return i.length === 1 ? '0' + i : i; + // + // If we have some transparency, the only way to represent it + // is via `rgba`. Otherwise, we use the hex representation, + // which has better compatibility with older browsers. + // Values are capped between `0` and `255`, rounded and zero-padded. + // + toCSS: function () { + if (this.alpha < 1.0) { + return "rgba(" + this.rgb.map(function (c) { + return Math.round(c); + }).concat(this.alpha).join(', ') + ")"; + } else { + return '#' + this.rgb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; }).join(''); - } + } + }, + + // + // Operations have to be done per-channel, if not, + // channels will spill onto each other. Once we have + // our result, in the form of an integer triplet, + // we create a new Color node to hold the result. + // + operate: function (op, other) { + var result = []; + + if (! (other instanceof tree.Color)) { + other = other.toColor(); + } + + for (var c = 0; c < 3; c++) { + result[c] = tree.operate(op, this.rgb[c], other.rgb[c]); + } + return new(tree.Color)(result, this.alpha + other.alpha); + }, + + toHSL: function () { + var r = this.rgb[0] / 255, + g = this.rgb[1] / 255, + b = this.rgb[2] / 255, + a = this.alpha; + + var max = Math.max(r, g, b), min = Math.min(r, g, b); + var h, s, l = (max + min) / 2, d = max - min; + + if (max === min) { + h = s = 0; + } else { + s = l > 0.5 ? d / (2 - max - min) : d / (max + min); + + switch (max) { + case r: h = (g - b) / d + (g < b ? 6 : 0); break; + case g: h = (b - r) / d + 2; break; + case b: h = (r - g) / d + 4; break; + } + h /= 6; + } + return { h: h * 360, s: s, l: l, a: a }; + }, + toARGB: function () { + var argb = [Math.round(this.alpha * 255)].concat(this.rgb); + return '#' + argb.map(function (i) { + i = Math.round(i); + i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16); + return i.length === 1 ? '0' + i : i; + }).join(''); + } }; @@ -1897,56 +1897,56 @@ tree.Color.prototype = { (function (tree) { tree.Comment = function (value, silent) { - this.value = value; - this.silent = !!silent; + this.value = value; + this.silent = !!silent; }; tree.Comment.prototype = { - toCSS: function (env) { - return env.compress ? '' : this.value; - }, - eval: function () { return this } + toCSS: function (env) { + return env.compress ? '' : this.value; + }, + eval: function () { return this } }; })(require('../tree')); (function (tree) { tree.Condition = function (op, l, r, i, negate) { - this.op = op.trim(); - this.lvalue = l; - this.rvalue = r; - this.index = i; - this.negate = negate; + this.op = op.trim(); + this.lvalue = l; + this.rvalue = r; + this.index = i; + this.negate = negate; }; tree.Condition.prototype.eval = function (env) { - var a = this.lvalue.eval(env), - b = this.rvalue.eval(env); + var a = this.lvalue.eval(env), + b = this.rvalue.eval(env); - var i = this.index, result; + var i = this.index, result; - var result = (function (op) { - switch (op) { - case 'and': - return a && b; - case 'or': - return a || b; - default: - if (a.compare) { - result = a.compare(b); - } else if (b.compare) { - result = b.compare(a); - } else { - throw { type: "Type", - message: "Unable to perform comparison", - index: i }; - } - switch (result) { - case -1: return op === '<' || op === '=<'; - case 0: return op === '=' || op === '>=' || op === '=<'; - case 1: return op === '>' || op === '>='; - } - } - })(this.op); - return this.negate ? !result : result; + var result = (function (op) { + switch (op) { + case 'and': + return a && b; + case 'or': + return a || b; + default: + if (a.compare) { + result = a.compare(b); + } else if (b.compare) { + result = b.compare(a); + } else { + throw { type: "Type", + message: "Unable to perform comparison", + index: i }; + } + switch (result) { + case -1: return op === '<' || op === '=<'; + case 0: return op === '=' || op === '>=' || op === '=<'; + case 1: return op === '>' || op === '>='; + } + } + })(this.op); + return this.negate ? !result : result; }; })(require('../tree')); @@ -1956,103 +1956,103 @@ tree.Condition.prototype.eval = function (env) { // A number with a unit // tree.Dimension = function (value, unit) { - this.value = parseFloat(value); - this.unit = unit || null; + this.value = parseFloat(value); + this.unit = unit || null; }; tree.Dimension.prototype = { - eval: function () { return this }, - toColor: function () { - return new(tree.Color)([this.value, this.value, this.value]); - }, - toCSS: function () { - var css = this.value + this.unit; - return css; - }, + eval: function () { return this }, + toColor: function () { + return new(tree.Color)([this.value, this.value, this.value]); + }, + toCSS: function () { + var css = this.value + this.unit; + return css; + }, - // In an operation between two Dimensions, - // we default to the first Dimension's unit, - // so `1px + 2em` will yield `3px`. - // In the future, we could implement some unit - // conversions such that `100cm + 10mm` would yield - // `101cm`. - operate: function (op, other) { - return new(tree.Dimension) - (tree.operate(op, this.value, other.value), - this.unit || other.unit); - }, + // In an operation between two Dimensions, + // we default to the first Dimension's unit, + // so `1px + 2em` will yield `3px`. + // In the future, we could implement some unit + // conversions such that `100cm + 10mm` would yield + // `101cm`. + operate: function (op, other) { + return new(tree.Dimension) + (tree.operate(op, this.value, other.value), + this.unit || other.unit); + }, - // TODO: Perform unit conversion before comparing - compare: function (other) { - if (other instanceof tree.Dimension) { - if (other.value > this.value) { - return -1; - } else if (other.value < this.value) { - return 1; - } else { - return 0; - } + // TODO: Perform unit conversion before comparing + compare: function (other) { + if (other instanceof tree.Dimension) { + if (other.value > this.value) { + return -1; + } else if (other.value < this.value) { + return 1; } else { - return -1; + return 0; } - } + } else { + return -1; + } + } }; })(require('../tree')); (function (tree) { tree.Directive = function (name, value, features) { - this.name = name; + this.name = name; - if (Array.isArray(value)) { - this.ruleset = new(tree.Ruleset)([], value); - this.ruleset.allowImports = true; - } else { - this.value = value; - } + if (Array.isArray(value)) { + this.ruleset = new(tree.Ruleset)([], value); + this.ruleset.allowImports = true; + } else { + this.value = value; + } }; tree.Directive.prototype = { - toCSS: function (ctx, env) { - if (this.ruleset) { - this.ruleset.root = true; - return this.name + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - } else { - return this.name + ' ' + this.value.toCSS() + ';\n'; - } - }, - eval: function (env) { - env.frames.unshift(this); - this.ruleset = this.ruleset && this.ruleset.eval(env); - env.frames.shift(); - return this; - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } + toCSS: function (ctx, env) { + if (this.ruleset) { + this.ruleset.root = true; + return this.name + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + } else { + return this.name + ' ' + this.value.toCSS() + ';\n'; + } + }, + eval: function (env) { + env.frames.unshift(this); + this.ruleset = this.ruleset && this.ruleset.eval(env); + env.frames.shift(); + return this; + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) } }; })(require('../tree')); (function (tree) { tree.Element = function (combinator, value, index) { - this.combinator = combinator instanceof tree.Combinator ? - combinator : new(tree.Combinator)(combinator); + this.combinator = combinator instanceof tree.Combinator ? + combinator : new(tree.Combinator)(combinator); - if (typeof(value) === 'string') { - this.value = value.trim(); - } else if (value) { - this.value = value; - } else { - this.value = ""; - } - this.index = index; + if (typeof(value) === 'string') { + this.value = value.trim(); + } else if (value) { + this.value = value; + } else { + this.value = ""; + } + this.index = index; }; tree.Element.prototype.eval = function (env) { - return new(tree.Element)(this.combinator, - this.value.eval ? this.value.eval(env) : this.value, - this.index); + return new(tree.Element)(this.combinator, + this.value.eval ? this.value.eval(env) : this.value, + this.index); }; tree.Element.prototype.toCSS = function (env) { var value = (this.value.toCSS ? this.value.toCSS(env) : this.value); @@ -2064,25 +2064,25 @@ tree.Element.prototype.toCSS = function (env) { }; tree.Combinator = function (value) { - if (value === ' ') { - this.value = ' '; - } else if (value === '& ') { - this.value = '& '; - } else { - this.value = value ? value.trim() : ""; - } + if (value === ' ') { + this.value = ' '; + } else if (value === '& ') { + this.value = '& '; + } else { + this.value = value ? value.trim() : ""; + } }; tree.Combinator.prototype.toCSS = function (env) { - return { - '' : '', - ' ' : ' ', - '&' : '', - '& ' : ' ', - ':' : ' :', - '+' : env.compress ? '+' : ' + ', - '~' : env.compress ? '~' : ' ~ ', - '>' : env.compress ? '>' : ' > ' - }[this.value]; + return { + '' : '', + ' ' : ' ', + '&' : '', + '& ' : ' ', + ':' : ' :', + '+' : env.compress ? '+' : ' + ', + '~' : env.compress ? '~' : ' ~ ', + '>' : env.compress ? '>' : ' > ' + }[this.value]; }; })(require('../tree')); @@ -2090,22 +2090,22 @@ tree.Combinator.prototype.toCSS = function (env) { tree.Expression = function (value) { this.value = value }; tree.Expression.prototype = { - eval: function (env) { - if (this.value.length > 1) { - return new(tree.Expression)(this.value.map(function (e) { - return e.eval(env); - })); - } else if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return this; - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS ? e.toCSS(env) : ''; - }).join(' '); - } + eval: function (env) { + if (this.value.length > 1) { + return new(tree.Expression)(this.value.map(function (e) { + return e.eval(env); + })); + } else if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return this; + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS ? e.toCSS(env) : ''; + }).join(' '); + } }; })(require('../tree')); @@ -2123,30 +2123,30 @@ tree.Expression.prototype = { // the file has been fetched, and parsed. // tree.Import = function (path, imports, features, once, index) { - var that = this; + var that = this; - this.once = once; - this.index = index; - this._path = path; - this.features = features && new(tree.Value)(features); + this.once = once; + this.index = index; + this._path = path; + this.features = features && new(tree.Value)(features); - // The '.less' extension is optional - if (path instanceof tree.Quoted) { - this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; - } else { - this.path = path.value.value || path.value; - } + // The '.less' extension is optional + if (path instanceof tree.Quoted) { + this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less'; + } else { + this.path = path.value.value || path.value; + } - this.css = /css(\?.*)?$/.test(this.path); + this.css = /css(\?.*)?$/.test(this.path); - // Only pre-compile .less files - if (! this.css) { - imports.push(this.path, function (e, root, imported) { - if (e) { e.index = index } - if (imported && that.once) that.skip = imported; - that.root = root || new(tree.Ruleset)([], []); - }); - } + // Only pre-compile .less files + if (! this.css) { + imports.push(this.path, function (e, root, imported) { + if (e) { e.index = index } + if (imported && that.once) that.skip = imported; + that.root = root || new(tree.Ruleset)([], []); + }); + } }; // @@ -2159,86 +2159,86 @@ tree.Import = function (path, imports, features, once, index) { // ruleset. // tree.Import.prototype = { - toCSS: function (env) { - var features = this.features ? ' ' + this.features.toCSS(env) : ''; + toCSS: function (env) { + var features = this.features ? ' ' + this.features.toCSS(env) : ''; - if (this.css) { - return "@import " + this._path.toCSS() + features + ';\n'; - } else { - return ""; + if (this.css) { + return "@import " + this._path.toCSS() + features + ';\n'; + } else { + return ""; + } + }, + eval: function (env) { + var ruleset, features = this.features && this.features.eval(env); + + if (this.skip) return []; + + if (this.css) { + return this; + } else { + ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); + + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype + .splice + .apply(ruleset.rules, + [i, 1].concat(ruleset.rules[i].eval(env))); + } } - }, - eval: function (env) { - var ruleset, features = this.features && this.features.eval(env); - - if (this.skip) return []; - - if (this.css) { - return this; - } else { - ruleset = new(tree.Ruleset)([], this.root.rules.slice(0)); - - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype - .splice - .apply(ruleset.rules, - [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; - } - } + return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules; + } + } }; })(require('../tree')); (function (tree) { tree.JavaScript = function (string, index, escaped) { - this.escaped = escaped; - this.expression = string; - this.index = index; + this.escaped = escaped; + this.expression = string; + this.index = index; }; tree.JavaScript.prototype = { - eval: function (env) { - var result, - that = this, - context = {}; + eval: function (env) { + var result, + that = this, + context = {}; - var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { - return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); - }); + var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) { + return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env)); + }); - try { - expression = new(Function)('return (' + expression + ')'); - } catch (e) { - throw { message: "JavaScript evaluation error: `" + expression + "`" , - index: this.index }; - } + try { + expression = new(Function)('return (' + expression + ')'); + } catch (e) { + throw { message: "JavaScript evaluation error: `" + expression + "`" , + index: this.index }; + } - for (var k in env.frames[0].variables()) { - context[k.slice(1)] = { - value: env.frames[0].variables()[k].value, - toJS: function () { - return this.value.eval(env).toCSS(); - } - }; - } + for (var k in env.frames[0].variables()) { + context[k.slice(1)] = { + value: env.frames[0].variables()[k].value, + toJS: function () { + return this.value.eval(env).toCSS(); + } + }; + } - try { - result = expression.call(context); - } catch (e) { - throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , - index: this.index }; - } - if (typeof(result) === 'string') { - return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); - } else if (Array.isArray(result)) { - return new(tree.Anonymous)(result.join(', ')); - } else { - return new(tree.Anonymous)(result); - } - } + try { + result = expression.call(context); + } catch (e) { + throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" , + index: this.index }; + } + if (typeof(result) === 'string') { + return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index); + } else if (Array.isArray(result)) { + return new(tree.Anonymous)(result.join(', ')); + } else { + return new(tree.Anonymous)(result); + } + } }; })(require('../tree')); @@ -2247,15 +2247,15 @@ tree.JavaScript.prototype = { tree.Keyword = function (value) { this.value = value }; tree.Keyword.prototype = { - eval: function () { return this }, - toCSS: function () { return this.value }, - compare: function (other) { - if (other instanceof tree.Keyword) { - return other.value === this.value ? 0 : 1; - } else { - return -1; - } - } + eval: function () { return this }, + toCSS: function () { return this.value }, + compare: function (other) { + if (other instanceof tree.Keyword) { + return other.value === this.value ? 0 : 1; + } else { + return -1; + } + } }; tree.True = new(tree.Keyword)('true'); @@ -2265,114 +2265,114 @@ tree.False = new(tree.Keyword)('false'); (function (tree) { tree.Media = function (value, features) { - var el = new(tree.Element)('&', null, 0), - selectors = [new(tree.Selector)([el])]; + var el = new(tree.Element)('&', null, 0), + selectors = [new(tree.Selector)([el])]; - this.features = new(tree.Value)(features); - this.ruleset = new(tree.Ruleset)(selectors, value); - this.ruleset.allowImports = true; + this.features = new(tree.Value)(features); + this.ruleset = new(tree.Ruleset)(selectors, value); + this.ruleset.allowImports = true; }; tree.Media.prototype = { - toCSS: function (ctx, env) { - var features = this.features.toCSS(env); + toCSS: function (ctx, env) { + var features = this.features.toCSS(env); - this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); - return '@media ' + features + (env.compress ? '{' : ' {\n ') + - this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + - (env.compress ? '}': '\n}\n'); - }, - eval: function (env) { - if (!env.mediaBlocks) { - env.mediaBlocks = []; - env.mediaPath = []; - } - - var blockIndex = env.mediaBlocks.length; - env.mediaPath.push(this); - env.mediaBlocks.push(this); - - var media = new(tree.Media)([], []); - media.features = this.features.eval(env); - - env.frames.unshift(this.ruleset); - media.ruleset = this.ruleset.eval(env); - env.frames.shift(); - - env.mediaBlocks[blockIndex] = media; - env.mediaPath.pop(); - - return env.mediaPath.length === 0 ? media.evalTop(env) : - media.evalNested(env) - }, - variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, - find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, - rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, - - evalTop: function (env) { - var result = this; - - // Render all dependent Media blocks. - if (env.mediaBlocks.length > 1) { - var el = new(tree.Element)('&', null, 0); - var selectors = [new(tree.Selector)([el])]; - result = new(tree.Ruleset)(selectors, env.mediaBlocks); - result.multiMedia = true; - } - - delete env.mediaBlocks; - delete env.mediaPath; - - return result; - }, - evalNested: function (env) { - var i, value, - path = env.mediaPath.concat([this]); - - // Extract the media-query conditions separated with `,` (OR). - for (i = 0; i < path.length; i++) { - value = path[i].features instanceof tree.Value ? - path[i].features.value : path[i].features; - path[i] = Array.isArray(value) ? value : [value]; - } - - // Trace all permutations to generate the resulting media-query. - // - // (a, b and c) with nested (d, e) -> - // a and d - // a and e - // b and c and d - // b and c and e - this.features = new(tree.Value)(this.permute(path).map(function (path) { - path = path.map(function (fragment) { - return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); - }); - - for(i = path.length - 1; i > 0; i--) { - path.splice(i, 0, new(tree.Anonymous)("and")); - } - - return new(tree.Expression)(path); - })); - - // Fake a tree-node that doesn't output anything. - return new(tree.Ruleset)([], []); - }, - permute: function (arr) { - if (arr.length === 0) { - return []; - } else if (arr.length === 1) { - return arr[0]; - } else { - var result = []; - var rest = this.permute(arr.slice(1)); - for (var i = 0; i < rest.length; i++) { - for (var j = 0; j < arr[0].length; j++) { - result.push([arr[0][j]].concat(rest[i])); - } - } - return result; + this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia); + return '@media ' + features + (env.compress ? '{' : ' {\n ') + + this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') + + (env.compress ? '}': '\n}\n'); + }, + eval: function (env) { + if (!env.mediaBlocks) { + env.mediaBlocks = []; + env.mediaPath = []; } + + var blockIndex = env.mediaBlocks.length; + env.mediaPath.push(this); + env.mediaBlocks.push(this); + + var media = new(tree.Media)([], []); + media.features = this.features.eval(env); + + env.frames.unshift(this.ruleset); + media.ruleset = this.ruleset.eval(env); + env.frames.shift(); + + env.mediaBlocks[blockIndex] = media; + env.mediaPath.pop(); + + return env.mediaPath.length === 0 ? media.evalTop(env) : + media.evalNested(env) + }, + variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) }, + find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) }, + rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }, + + evalTop: function (env) { + var result = this; + + // Render all dependent Media blocks. + if (env.mediaBlocks.length > 1) { + var el = new(tree.Element)('&', null, 0); + var selectors = [new(tree.Selector)([el])]; + result = new(tree.Ruleset)(selectors, env.mediaBlocks); + result.multiMedia = true; + } + + delete env.mediaBlocks; + delete env.mediaPath; + + return result; + }, + evalNested: function (env) { + var i, value, + path = env.mediaPath.concat([this]); + + // Extract the media-query conditions separated with `,` (OR). + for (i = 0; i < path.length; i++) { + value = path[i].features instanceof tree.Value ? + path[i].features.value : path[i].features; + path[i] = Array.isArray(value) ? value : [value]; + } + + // Trace all permutations to generate the resulting media-query. + // + // (a, b and c) with nested (d, e) -> + // a and d + // a and e + // b and c and d + // b and c and e + this.features = new(tree.Value)(this.permute(path).map(function (path) { + path = path.map(function (fragment) { + return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment); + }); + + for(i = path.length - 1; i > 0; i--) { + path.splice(i, 0, new(tree.Anonymous)("and")); + } + + return new(tree.Expression)(path); + })); + + // Fake a tree-node that doesn't output anything. + return new(tree.Ruleset)([], []); + }, + permute: function (arr) { + if (arr.length === 0) { + return []; + } else if (arr.length === 1) { + return arr[0]; + } else { + var result = []; + var rest = this.permute(arr.slice(1)); + for (var i = 0; i < rest.length; i++) { + for (var j = 0; j < arr[0].length; j++) { + result.push([arr[0][j]].concat(rest[i])); + } + } + return result; } + } }; })(require('../tree')); @@ -2380,177 +2380,177 @@ tree.Media.prototype = { tree.mixin = {}; tree.mixin.Call = function (elements, args, index, filename, important) { - this.selector = new(tree.Selector)(elements); - this.arguments = args; - this.index = index; - this.filename = filename; - this.important = important; + this.selector = new(tree.Selector)(elements); + this.arguments = args; + this.index = index; + this.filename = filename; + this.important = important; }; tree.mixin.Call.prototype = { - eval: function (env) { - var mixins, args, rules = [], match = false; + eval: function (env) { + var mixins, args, rules = [], match = false; - for (var i = 0; i < env.frames.length; i++) { - if ((mixins = env.frames[i].find(this.selector)).length > 0) { - args = this.arguments && this.arguments.map(function (a) { - return { name: a.name, value: a.value.eval(env) }; - }); - for (var m = 0; m < mixins.length; m++) { - if (mixins[m].match(args, env)) { - try { - Array.prototype.push.apply( - rules, mixins[m].eval(env, this.arguments, this.important).rules); - match = true; - } catch (e) { - throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; - } - } + for (var i = 0; i < env.frames.length; i++) { + if ((mixins = env.frames[i].find(this.selector)).length > 0) { + args = this.arguments && this.arguments.map(function (a) { + return { name: a.name, value: a.value.eval(env) }; + }); + for (var m = 0; m < mixins.length; m++) { + if (mixins[m].match(args, env)) { + try { + Array.prototype.push.apply( + rules, mixins[m].eval(env, this.arguments, this.important).rules); + match = true; + } catch (e) { + throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack }; } - if (match) { - return rules; - } else { - throw { type: 'Runtime', - message: 'No matching definition was found for `' + - this.selector.toCSS().trim() + '(' + - this.arguments.map(function (a) { - return a.toCSS(); - }).join(', ') + ")`", - index: this.index, filename: this.filename }; - } - } + } + } + if (match) { + return rules; + } else { + throw { type: 'Runtime', + message: 'No matching definition was found for `' + + this.selector.toCSS().trim() + '(' + + this.arguments.map(function (a) { + return a.toCSS(); + }).join(', ') + ")`", + index: this.index, filename: this.filename }; + } } - throw { type: 'Name', - message: this.selector.toCSS().trim() + " is undefined", - index: this.index, filename: this.filename }; - } + } + throw { type: 'Name', + message: this.selector.toCSS().trim() + " is undefined", + index: this.index, filename: this.filename }; + } }; tree.mixin.Definition = function (name, params, rules, condition, variadic) { - this.name = name; - this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; - this.params = params; - this.condition = condition; - this.variadic = variadic; - this.arity = params.length; - this.rules = rules; - this._lookups = {}; - this.required = params.reduce(function (count, p) { - if (!p.name || (p.name && !p.value)) { return count + 1 } - else { return count } - }, 0); - this.parent = tree.Ruleset.prototype; - this.frames = []; + this.name = name; + this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])]; + this.params = params; + this.condition = condition; + this.variadic = variadic; + this.arity = params.length; + this.rules = rules; + this._lookups = {}; + this.required = params.reduce(function (count, p) { + if (!p.name || (p.name && !p.value)) { return count + 1 } + else { return count } + }, 0); + this.parent = tree.Ruleset.prototype; + this.frames = []; }; tree.mixin.Definition.prototype = { - toCSS: function () { return "" }, - variable: function (name) { return this.parent.variable.call(this, name) }, - variables: function () { return this.parent.variables.call(this) }, - find: function () { return this.parent.find.apply(this, arguments) }, - rulesets: function () { return this.parent.rulesets.apply(this) }, + toCSS: function () { return "" }, + variable: function (name) { return this.parent.variable.call(this, name) }, + variables: function () { return this.parent.variables.call(this) }, + find: function () { return this.parent.find.apply(this, arguments) }, + rulesets: function () { return this.parent.rulesets.apply(this) }, - evalParams: function (env, args) { - var frame = new(tree.Ruleset)(null, []), varargs, arg; + evalParams: function (env, args) { + var frame = new(tree.Ruleset)(null, []), varargs, arg; - for (var i = 0, val, name; i < this.params.length; i++) { - arg = args && args[i] + for (var i = 0, val, name; i < this.params.length; i++) { + arg = args && args[i] - if (arg && arg.name) { - frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); - args.splice(i, 1); - i--; - continue; - } - - if (name = this.params[i].name) { - if (this.params[i].variadic && args) { - varargs = []; - for (var j = i; j < args.length; j++) { - varargs.push(args[j].eval(env)); - } - frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); - } else if (val = (arg && arg.value) || this.params[i].value) { - frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); - } else { - throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + - ' (' + args.length + ' for ' + this.arity + ')' }; - } - } - } - return frame; - }, - eval: function (env, args, important) { - var frame = this.evalParams(env, args), context, _arguments = [], rules, start; - - for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { - _arguments.push((args[i] && args[i].value) || this.params[i].value); - } - frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); - - rules = important ? - this.rules.map(function (r) { - return new(tree.Rule)(r.name, r.value, '!important', r.index); - }) : this.rules.slice(0); - - return new(tree.Ruleset)(null, rules).eval({ - frames: [this, frame].concat(this.frames, env.frames) - }); - }, - match: function (args, env) { - var argsLength = (args && args.length) || 0, len, frame; - - if (! this.variadic) { - if (argsLength < this.required) { return false } - if (argsLength > this.params.length) { return false } - if ((this.required > 0) && (argsLength > this.params.length)) { return false } + if (arg && arg.name) { + frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env))); + args.splice(i, 1); + i--; + continue; } - if (this.condition && !this.condition.eval({ - frames: [this.evalParams(env, args)].concat(env.frames) - })) { return false } - - len = Math.min(argsLength, this.arity); - - for (var i = 0; i < len; i++) { - if (!this.params[i].name) { - if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { - return false; - } - } + if (name = this.params[i].name) { + if (this.params[i].variadic && args) { + varargs = []; + for (var j = i; j < args.length; j++) { + varargs.push(args[j].eval(env)); + } + frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env))); + } else if (val = (arg && arg.value) || this.params[i].value) { + frame.rules.unshift(new(tree.Rule)(name, val.eval(env))); + } else { + throw { type: 'Runtime', message: "wrong number of arguments for " + this.name + + ' (' + args.length + ' for ' + this.arity + ')' }; + } } - return true; - } + } + return frame; + }, + eval: function (env, args, important) { + var frame = this.evalParams(env, args), context, _arguments = [], rules, start; + + for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) { + _arguments.push((args[i] && args[i].value) || this.params[i].value); + } + frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env))); + + rules = important ? + this.rules.map(function (r) { + return new(tree.Rule)(r.name, r.value, '!important', r.index); + }) : this.rules.slice(0); + + return new(tree.Ruleset)(null, rules).eval({ + frames: [this, frame].concat(this.frames, env.frames) + }); + }, + match: function (args, env) { + var argsLength = (args && args.length) || 0, len, frame; + + if (! this.variadic) { + if (argsLength < this.required) { return false } + if (argsLength > this.params.length) { return false } + if ((this.required > 0) && (argsLength > this.params.length)) { return false } + } + + if (this.condition && !this.condition.eval({ + frames: [this.evalParams(env, args)].concat(env.frames) + })) { return false } + + len = Math.min(argsLength, this.arity); + + for (var i = 0; i < len; i++) { + if (!this.params[i].name) { + if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) { + return false; + } + } + } + return true; + } }; })(require('../tree')); (function (tree) { tree.Operation = function (op, operands) { - this.op = op.trim(); - this.operands = operands; + this.op = op.trim(); + this.operands = operands; }; tree.Operation.prototype.eval = function (env) { - var a = this.operands[0].eval(env), - b = this.operands[1].eval(env), - temp; + var a = this.operands[0].eval(env), + b = this.operands[1].eval(env), + temp; - if (a instanceof tree.Dimension && b instanceof tree.Color) { - if (this.op === '*' || this.op === '+') { - temp = b, b = a, a = temp; - } else { - throw { name: "OperationError", - message: "Can't substract or divide a color from a number" }; - } - } - return a.operate(this.op, b); + if (a instanceof tree.Dimension && b instanceof tree.Color) { + if (this.op === '*' || this.op === '+') { + temp = b, b = a, a = temp; + } else { + throw { name: "OperationError", + message: "Can't substract or divide a color from a number" }; + } + } + return a.operate(this.op, b); }; tree.operate = function (op, a, b) { - switch (op) { - case '+': return a + b; - case '-': return a - b; - case '*': return a * b; - case '/': return a / b; - } + switch (op) { + case '+': return a + b; + case '-': return a - b; + case '*': return a * b; + case '/': return a / b; + } }; })(require('../tree')); @@ -2558,402 +2558,402 @@ tree.operate = function (op, a, b) { (function (tree) { tree.Paren = function (node) { - this.value = node; + this.value = node; }; tree.Paren.prototype = { - toCSS: function (env) { - return '(' + this.value.toCSS(env) + ')'; - }, - eval: function (env) { - return new(tree.Paren)(this.value.eval(env)); - } + toCSS: function (env) { + return '(' + this.value.toCSS(env) + ')'; + }, + eval: function (env) { + return new(tree.Paren)(this.value.eval(env)); + } }; })(require('../tree')); (function (tree) { tree.Quoted = function (str, content, escaped, i) { - this.escaped = escaped; - this.value = content || ''; - this.quote = str.charAt(0); - this.index = i; + this.escaped = escaped; + this.value = content || ''; + this.quote = str.charAt(0); + this.index = i; }; tree.Quoted.prototype = { - toCSS: function () { - if (this.escaped) { - return this.value; - } else { - return this.quote + this.value + this.quote; - } - }, - eval: function (env) { - var that = this; - var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { - return new(tree.JavaScript)(exp, that.index, true).eval(env).value; - }).replace(/@\{([\w-]+)\}/g, function (_, name) { - var v = new(tree.Variable)('@' + name, that.index).eval(env); - return ('value' in v) ? v.value : v.toCSS(); - }); - return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); - } + toCSS: function () { + if (this.escaped) { + return this.value; + } else { + return this.quote + this.value + this.quote; + } + }, + eval: function (env) { + var that = this; + var value = this.value.replace(/`([^`]+)`/g, function (_, exp) { + return new(tree.JavaScript)(exp, that.index, true).eval(env).value; + }).replace(/@\{([\w-]+)\}/g, function (_, name) { + var v = new(tree.Variable)('@' + name, that.index).eval(env); + return ('value' in v) ? v.value : v.toCSS(); + }); + return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index); + } }; })(require('../tree')); (function (tree) { tree.Rule = function (name, value, important, index, inline) { - this.name = name; - this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); - this.important = important ? ' ' + important.trim() : ''; - this.index = index; - this.inline = inline || false; + this.name = name; + this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]); + this.important = important ? ' ' + important.trim() : ''; + this.index = index; + this.inline = inline || false; - if (name.charAt(0) === '@') { - this.variable = true; - } else { this.variable = false } + if (name.charAt(0) === '@') { + this.variable = true; + } else { this.variable = false } }; tree.Rule.prototype.toCSS = function (env) { - if (this.variable) { return "" } - else { - return this.name + (env.compress ? ':' : ': ') + - this.value.toCSS(env) + - this.important + (this.inline ? "" : ";"); - } + if (this.variable) { return "" } + else { + return this.name + (env.compress ? ':' : ': ') + + this.value.toCSS(env) + + this.important + (this.inline ? "" : ";"); + } }; tree.Rule.prototype.eval = function (context) { - return new(tree.Rule)(this.name, - this.value.eval(context), - this.important, - this.index, this.inline); + return new(tree.Rule)(this.name, + this.value.eval(context), + this.important, + this.index, this.inline); }; tree.Shorthand = function (a, b) { - this.a = a; - this.b = b; + this.a = a; + this.b = b; }; tree.Shorthand.prototype = { - toCSS: function (env) { - return this.a.toCSS(env) + "/" + this.b.toCSS(env); - }, - eval: function () { return this } + toCSS: function (env) { + return this.a.toCSS(env) + "/" + this.b.toCSS(env); + }, + eval: function () { return this } }; })(require('../tree')); (function (tree) { tree.Ruleset = function (selectors, rules, strictImports) { - this.selectors = selectors; - this.rules = rules; - this._lookups = {}; - this.strictImports = strictImports; + this.selectors = selectors; + this.rules = rules; + this._lookups = {}; + this.strictImports = strictImports; }; tree.Ruleset.prototype = { - eval: function (env) { - var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); - var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); + eval: function (env) { + var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) }); + var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports); - ruleset.root = this.root; - ruleset.allowImports = this.allowImports; + ruleset.root = this.root; + ruleset.allowImports = this.allowImports; - // push the current ruleset to the frames stack - env.frames.unshift(ruleset); + // push the current ruleset to the frames stack + env.frames.unshift(ruleset); - // Evaluate imports - if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.Import) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } - } - } - - // Store the frames around mixin definitions, - // so they can be evaluated like closures when the time comes. + // Evaluate imports + if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) { for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Definition) { - ruleset.rules[i].frames = env.frames.slice(0); - } + if (ruleset.rules[i] instanceof tree.Import) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); + } } + } - // Evaluate mixin calls. - for (var i = 0; i < ruleset.rules.length; i++) { - if (ruleset.rules[i] instanceof tree.mixin.Call) { - Array.prototype.splice - .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); - } + // Store the frames around mixin definitions, + // so they can be evaluated like closures when the time comes. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Definition) { + ruleset.rules[i].frames = env.frames.slice(0); } + } - // Evaluate everything else - for (var i = 0, rule; i < ruleset.rules.length; i++) { - rule = ruleset.rules[i]; - - if (! (rule instanceof tree.mixin.Definition)) { - ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; - } + // Evaluate mixin calls. + for (var i = 0; i < ruleset.rules.length; i++) { + if (ruleset.rules[i] instanceof tree.mixin.Call) { + Array.prototype.splice + .apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env))); } + } - // Pop the stack - env.frames.shift(); + // Evaluate everything else + for (var i = 0, rule; i < ruleset.rules.length; i++) { + rule = ruleset.rules[i]; - return ruleset; - }, - match: function (args) { - return !args || args.length === 0; - }, - variables: function () { - if (this._variables) { return this._variables } - else { - return this._variables = this.rules.reduce(function (hash, r) { - if (r instanceof tree.Rule && r.variable === true) { - hash[r.name] = r; - } - return hash; - }, {}); + if (! (rule instanceof tree.mixin.Definition)) { + ruleset.rules[i] = rule.eval ? rule.eval(env) : rule; } - }, - variable: function (name) { - return this.variables()[name]; - }, - rulesets: function () { - if (this._rulesets) { return this._rulesets } - else { - return this._rulesets = this.rules.filter(function (r) { - return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); - }); - } - }, - find: function (selector, self) { - self = self || this; - var rules = [], rule, match, - key = selector.toCSS(); + } - if (key in this._lookups) { return this._lookups[key] } + // Pop the stack + env.frames.shift(); - this.rulesets().forEach(function (rule) { - if (rule !== self) { - for (var j = 0; j < rule.selectors.length; j++) { - if (match = selector.match(rule.selectors[j])) { - if (selector.elements.length > rule.selectors[j].elements.length) { - Array.prototype.push.apply(rules, rule.find( - new(tree.Selector)(selector.elements.slice(1)), self)); - } else { - rules.push(rule); - } - break; - } - } - } + return ruleset; + }, + match: function (args) { + return !args || args.length === 0; + }, + variables: function () { + if (this._variables) { return this._variables } + else { + return this._variables = this.rules.reduce(function (hash, r) { + if (r instanceof tree.Rule && r.variable === true) { + hash[r.name] = r; + } + return hash; + }, {}); + } + }, + variable: function (name) { + return this.variables()[name]; + }, + rulesets: function () { + if (this._rulesets) { return this._rulesets } + else { + return this._rulesets = this.rules.filter(function (r) { + return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition); }); - return this._lookups[key] = rules; - }, - // - // Entry point for code generation - // - // `context` holds an array of arrays. - // - toCSS: function (context, env) { - var css = [], // The CSS output - rules = [], // node.Rule instances - _rules = [], // - rulesets = [], // node.Ruleset instances - paths = [], // Current selectors - selector, // The fully rendered selector - rule; + } + }, + find: function (selector, self) { + self = self || this; + var rules = [], rule, match, + key = selector.toCSS(); - if (! this.root) { - if (context.length === 0) { - paths = this.selectors.map(function (s) { return [s] }); - } else { - this.joinSelectors(paths, context, this.selectors); - } - } + if (key in this._lookups) { return this._lookups[key] } - // Compile rules and rulesets - for (var i = 0; i < this.rules.length; i++) { - rule = this.rules[i]; - - if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { - rulesets.push(rule.toCSS(paths, env)); - } else if (rule instanceof tree.Comment) { - if (!rule.silent) { - if (this.root) { - rulesets.push(rule.toCSS(env)); - } else { - rules.push(rule.toCSS(env)); - } + this.rulesets().forEach(function (rule) { + if (rule !== self) { + for (var j = 0; j < rule.selectors.length; j++) { + if (match = selector.match(rule.selectors[j])) { + if (selector.elements.length > rule.selectors[j].elements.length) { + Array.prototype.push.apply(rules, rule.find( + new(tree.Selector)(selector.elements.slice(1)), self)); + } else { + rules.push(rule); } - } else { - if (rule.toCSS && !rule.variable) { - rules.push(rule.toCSS(env)); - } else if (rule.value && !rule.variable) { - rules.push(rule.value.toString()); - } - } + break; + } + } } + }); + return this._lookups[key] = rules; + }, + // + // Entry point for code generation + // + // `context` holds an array of arrays. + // + toCSS: function (context, env) { + var css = [], // The CSS output + rules = [], // node.Rule instances + _rules = [], // + rulesets = [], // node.Ruleset instances + paths = [], // Current selectors + selector, // The fully rendered selector + rule; - rulesets = rulesets.join(''); - - // If this is the root node, we don't render - // a selector, or {}. - // Otherwise, only output if this ruleset has rules. - if (this.root) { - css.push(rules.join(env.compress ? '' : '\n')); + if (! this.root) { + if (context.length === 0) { + paths = this.selectors.map(function (s) { return [s] }); } else { - if (rules.length > 0) { - selector = paths.map(function (p) { - return p.map(function (s) { - return s.toCSS(env); - }).join('').trim(); - }).join(env.compress ? ',' : ',\n'); - - // Remove duplicates - for (var i = rules.length - 1; i >= 0; i--) { - if (_rules.indexOf(rules[i]) === -1) { - _rules.unshift(rules[i]); - } - } - rules = _rules; - - css.push(selector, - (env.compress ? '{' : ' {\n ') + - rules.join(env.compress ? '' : '\n ') + - (env.compress ? '}' : '\n}\n')); - } + this.joinSelectors(paths, context, this.selectors); } - css.push(rulesets); + } - return css.join('') + (env.compress ? '\n' : ''); - }, + // Compile rules and rulesets + for (var i = 0; i < this.rules.length; i++) { + rule = this.rules[i]; - joinSelectors: function (paths, context, selectors) { - for (var s = 0; s < selectors.length; s++) { - this.joinSelector(paths, context, selectors[s]); + if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) { + rulesets.push(rule.toCSS(paths, env)); + } else if (rule instanceof tree.Comment) { + if (!rule.silent) { + if (this.root) { + rulesets.push(rule.toCSS(env)); + } else { + rules.push(rule.toCSS(env)); + } + } + } else { + if (rule.toCSS && !rule.variable) { + rules.push(rule.toCSS(env)); + } else if (rule.value && !rule.variable) { + rules.push(rule.value.toString()); + } } - }, + } - joinSelector: function (paths, context, selector) { - var before = [], after = [], beforeElements = [], - afterElements = [], hasParentSelector = false, el; + rulesets = rulesets.join(''); - for (var i = 0; i < selector.elements.length; i++) { - el = selector.elements[i]; - if (el.combinator.value.charAt(0) === '&') { - hasParentSelector = true; - } - if (hasParentSelector) afterElements.push(el); - else beforeElements.push(el); + // If this is the root node, we don't render + // a selector, or {}. + // Otherwise, only output if this ruleset has rules. + if (this.root) { + css.push(rules.join(env.compress ? '' : '\n')); + } else { + if (rules.length > 0) { + selector = paths.map(function (p) { + return p.map(function (s) { + return s.toCSS(env); + }).join('').trim(); + }).join(env.compress ? ',' : ',\n'); + + // Remove duplicates + for (var i = rules.length - 1; i >= 0; i--) { + if (_rules.indexOf(rules[i]) === -1) { + _rules.unshift(rules[i]); + } + } + rules = _rules; + + css.push(selector, + (env.compress ? '{' : ' {\n ') + + rules.join(env.compress ? '' : '\n ') + + (env.compress ? '}' : '\n}\n')); } + } + css.push(rulesets); - if (! hasParentSelector) { - afterElements = beforeElements; - beforeElements = []; - } + return css.join('') + (env.compress ? '\n' : ''); + }, - if (beforeElements.length > 0) { - before.push(new(tree.Selector)(beforeElements)); - } + joinSelectors: function (paths, context, selectors) { + for (var s = 0; s < selectors.length; s++) { + this.joinSelector(paths, context, selectors[s]); + } + }, - if (afterElements.length > 0) { - after.push(new(tree.Selector)(afterElements)); - } + joinSelector: function (paths, context, selector) { + var before = [], after = [], beforeElements = [], + afterElements = [], hasParentSelector = false, el; - for (var c = 0; c < context.length; c++) { - paths.push(before.concat(context[c]).concat(after)); + for (var i = 0; i < selector.elements.length; i++) { + el = selector.elements[i]; + if (el.combinator.value.charAt(0) === '&') { + hasParentSelector = true; } - } + if (hasParentSelector) afterElements.push(el); + else beforeElements.push(el); + } + + if (! hasParentSelector) { + afterElements = beforeElements; + beforeElements = []; + } + + if (beforeElements.length > 0) { + before.push(new(tree.Selector)(beforeElements)); + } + + if (afterElements.length > 0) { + after.push(new(tree.Selector)(afterElements)); + } + + for (var c = 0; c < context.length; c++) { + paths.push(before.concat(context[c]).concat(after)); + } + } }; })(require('../tree')); (function (tree) { tree.Selector = function (elements) { - this.elements = elements; - if (this.elements[0].combinator.value === "") { - this.elements[0].combinator.value = ' '; - } + this.elements = elements; + if (this.elements[0].combinator.value === "") { + this.elements[0].combinator.value = ' '; + } }; tree.Selector.prototype.match = function (other) { - var len = this.elements.length, - olen = other.elements.length, - max = Math.min(len, olen); + var len = this.elements.length, + olen = other.elements.length, + max = Math.min(len, olen); - if (len < olen) { - return false; - } else { - for (var i = 0; i < max; i++) { - if (this.elements[i].value !== other.elements[i].value) { - return false; - } + if (len < olen) { + return false; + } else { + for (var i = 0; i < max; i++) { + if (this.elements[i].value !== other.elements[i].value) { + return false; } - } - return true; + } + } + return true; }; tree.Selector.prototype.eval = function (env) { - return new(tree.Selector)(this.elements.map(function (e) { - return e.eval(env); - })); + return new(tree.Selector)(this.elements.map(function (e) { + return e.eval(env); + })); }; tree.Selector.prototype.toCSS = function (env) { - if (this._css) { return this._css } + if (this._css) { return this._css } - return this._css = this.elements.map(function (e) { - if (typeof(e) === 'string') { - return ' ' + e.trim(); - } else { - return e.toCSS(env); - } - }).join(''); + return this._css = this.elements.map(function (e) { + if (typeof(e) === 'string') { + return ' ' + e.trim(); + } else { + return e.toCSS(env); + } + }).join(''); }; })(require('../tree')); (function (tree) { tree.URL = function (val, paths) { - if (val.data) { - this.attrs = val; - } else { - // Add the base path if the URL is relative and we are in the browser - if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { - val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); - } - this.value = val; - this.paths = paths; - } + if (val.data) { + this.attrs = val; + } else { + // Add the base path if the URL is relative and we are in the browser + if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) { + val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value); + } + this.value = val; + this.paths = paths; + } }; tree.URL.prototype = { - toCSS: function () { - return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data - : this.value.toCSS()) + ")"; - }, - eval: function (ctx) { - return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); - } + toCSS: function () { + return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data + : this.value.toCSS()) + ")"; + }, + eval: function (ctx) { + return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths); + } }; })(require('../tree')); (function (tree) { tree.Value = function (value) { - this.value = value; - this.is = 'value'; + this.value = value; + this.is = 'value'; }; tree.Value.prototype = { - eval: function (env) { - if (this.value.length === 1) { - return this.value[0].eval(env); - } else { - return new(tree.Value)(this.value.map(function (v) { - return v.eval(env); - })); - } - }, - toCSS: function (env) { - return this.value.map(function (e) { - return e.toCSS(env); - }).join(env.compress ? ',' : ', '); - } + eval: function (env) { + if (this.value.length === 1) { + return this.value[0].eval(env); + } else { + return new(tree.Value)(this.value.map(function (v) { + return v.eval(env); + })); + } + }, + toCSS: function (env) { + return this.value.map(function (e) { + return e.toCSS(env); + }).join(env.compress ? ',' : ', '); + } }; })(require('../tree')); @@ -2961,258 +2961,258 @@ tree.Value.prototype = { tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file }; tree.Variable.prototype = { - eval: function (env) { - var variable, v, name = this.name; + eval: function (env) { + var variable, v, name = this.name; - if (name.indexOf('@@') == 0) { - name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; - } + if (name.indexOf('@@') == 0) { + name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value; + } - if (variable = tree.find(env.frames, function (frame) { - if (v = frame.variable(name)) { - return v.value.eval(env); - } - })) { return variable } - else { - throw { type: 'Name', - message: "variable " + name + " is undefined", - filename: this.file, - index: this.index }; + if (variable = tree.find(env.frames, function (frame) { + if (v = frame.variable(name)) { + return v.value.eval(env); } - } + })) { return variable } + else { + throw { type: 'Name', + message: "variable " + name + " is undefined", + filename: this.file, + index: this.index }; + } + } }; })(require('../tree')); (function (tree) { tree.find = function (obj, fun) { - for (var i = 0, r; i < obj.length; i++) { - if (r = fun.call(obj, obj[i])) { return r } - } - return null; + for (var i = 0, r; i < obj.length; i++) { + if (r = fun.call(obj, obj[i])) { return r } + } + return null; }; tree.jsify = function (obj) { - if (Array.isArray(obj.value) && (obj.value.length > 1)) { - return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; - } else { - return obj.toCSS(false); - } + if (Array.isArray(obj.value) && (obj.value.length > 1)) { + return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']'; + } else { + return obj.toCSS(false); + } }; })(require('./tree')); (function (tree) { - tree.colors = { - 'aliceblue':'#f0f8ff', - 'antiquewhite':'#faebd7', - 'aqua':'#00ffff', - 'aquamarine':'#7fffd4', - 'azure':'#f0ffff', - 'beige':'#f5f5dc', - 'bisque':'#ffe4c4', - 'black':'#000000', - 'blanchedalmond':'#ffebcd', - 'blue':'#0000ff', - 'blueviolet':'#8a2be2', - 'brown':'#a52a2a', - 'burlywood':'#deb887', - 'cadetblue':'#5f9ea0', - 'chartreuse':'#7fff00', - 'chocolate':'#d2691e', - 'coral':'#ff7f50', - 'cornflowerblue':'#6495ed', - 'cornsilk':'#fff8dc', - 'crimson':'#dc143c', - 'cyan':'#00ffff', - 'darkblue':'#00008b', - 'darkcyan':'#008b8b', - 'darkgoldenrod':'#b8860b', - 'darkgray':'#a9a9a9', - 'darkgrey':'#a9a9a9', - 'darkgreen':'#006400', - 'darkkhaki':'#bdb76b', - 'darkmagenta':'#8b008b', - 'darkolivegreen':'#556b2f', - 'darkorange':'#ff8c00', - 'darkorchid':'#9932cc', - 'darkred':'#8b0000', - 'darksalmon':'#e9967a', - 'darkseagreen':'#8fbc8f', - 'darkslateblue':'#483d8b', - 'darkslategray':'#2f4f4f', - 'darkslategrey':'#2f4f4f', - 'darkturquoise':'#00ced1', - 'darkviolet':'#9400d3', - 'deeppink':'#ff1493', - 'deepskyblue':'#00bfff', - 'dimgray':'#696969', - 'dimgrey':'#696969', - 'dodgerblue':'#1e90ff', - 'firebrick':'#b22222', - 'floralwhite':'#fffaf0', - 'forestgreen':'#228b22', - 'fuchsia':'#ff00ff', - 'gainsboro':'#dcdcdc', - 'ghostwhite':'#f8f8ff', - 'gold':'#ffd700', - 'goldenrod':'#daa520', - 'gray':'#808080', - 'grey':'#808080', - 'green':'#008000', - 'greenyellow':'#adff2f', - 'honeydew':'#f0fff0', - 'hotpink':'#ff69b4', - 'indianred':'#cd5c5c', - 'indigo':'#4b0082', - 'ivory':'#fffff0', - 'khaki':'#f0e68c', - 'lavender':'#e6e6fa', - 'lavenderblush':'#fff0f5', - 'lawngreen':'#7cfc00', - 'lemonchiffon':'#fffacd', - 'lightblue':'#add8e6', - 'lightcoral':'#f08080', - 'lightcyan':'#e0ffff', - 'lightgoldenrodyellow':'#fafad2', - 'lightgray':'#d3d3d3', - 'lightgrey':'#d3d3d3', - 'lightgreen':'#90ee90', - 'lightpink':'#ffb6c1', - 'lightsalmon':'#ffa07a', - 'lightseagreen':'#20b2aa', - 'lightskyblue':'#87cefa', - 'lightslategray':'#778899', - 'lightslategrey':'#778899', - 'lightsteelblue':'#b0c4de', - 'lightyellow':'#ffffe0', - 'lime':'#00ff00', - 'limegreen':'#32cd32', - 'linen':'#faf0e6', - 'magenta':'#ff00ff', - 'maroon':'#800000', - 'mediumaquamarine':'#66cdaa', - 'mediumblue':'#0000cd', - 'mediumorchid':'#ba55d3', - 'mediumpurple':'#9370d8', - 'mediumseagreen':'#3cb371', - 'mediumslateblue':'#7b68ee', - 'mediumspringgreen':'#00fa9a', - 'mediumturquoise':'#48d1cc', - 'mediumvioletred':'#c71585', - 'midnightblue':'#191970', - 'mintcream':'#f5fffa', - 'mistyrose':'#ffe4e1', - 'moccasin':'#ffe4b5', - 'navajowhite':'#ffdead', - 'navy':'#000080', - 'oldlace':'#fdf5e6', - 'olive':'#808000', - 'olivedrab':'#6b8e23', - 'orange':'#ffa500', - 'orangered':'#ff4500', - 'orchid':'#da70d6', - 'palegoldenrod':'#eee8aa', - 'palegreen':'#98fb98', - 'paleturquoise':'#afeeee', - 'palevioletred':'#d87093', - 'papayawhip':'#ffefd5', - 'peachpuff':'#ffdab9', - 'peru':'#cd853f', - 'pink':'#ffc0cb', - 'plum':'#dda0dd', - 'powderblue':'#b0e0e6', - 'purple':'#800080', - 'red':'#ff0000', - 'rosybrown':'#bc8f8f', - 'royalblue':'#4169e1', - 'saddlebrown':'#8b4513', - 'salmon':'#fa8072', - 'sandybrown':'#f4a460', - 'seagreen':'#2e8b57', - 'seashell':'#fff5ee', - 'sienna':'#a0522d', - 'silver':'#c0c0c0', - 'skyblue':'#87ceeb', - 'slateblue':'#6a5acd', - 'slategray':'#708090', - 'slategrey':'#708090', - 'snow':'#fffafa', - 'springgreen':'#00ff7f', - 'steelblue':'#4682b4', - 'tan':'#d2b48c', - 'teal':'#008080', - 'thistle':'#d8bfd8', - 'tomato':'#ff6347', - 'turquoise':'#40e0d0', - 'violet':'#ee82ee', - 'wheat':'#f5deb3', - 'white':'#ffffff', - 'whitesmoke':'#f5f5f5', - 'yellow':'#ffff00', - 'yellowgreen':'#9acd32' - }; + tree.colors = { + 'aliceblue':'#f0f8ff', + 'antiquewhite':'#faebd7', + 'aqua':'#00ffff', + 'aquamarine':'#7fffd4', + 'azure':'#f0ffff', + 'beige':'#f5f5dc', + 'bisque':'#ffe4c4', + 'black':'#000000', + 'blanchedalmond':'#ffebcd', + 'blue':'#0000ff', + 'blueviolet':'#8a2be2', + 'brown':'#a52a2a', + 'burlywood':'#deb887', + 'cadetblue':'#5f9ea0', + 'chartreuse':'#7fff00', + 'chocolate':'#d2691e', + 'coral':'#ff7f50', + 'cornflowerblue':'#6495ed', + 'cornsilk':'#fff8dc', + 'crimson':'#dc143c', + 'cyan':'#00ffff', + 'darkblue':'#00008b', + 'darkcyan':'#008b8b', + 'darkgoldenrod':'#b8860b', + 'darkgray':'#a9a9a9', + 'darkgrey':'#a9a9a9', + 'darkgreen':'#006400', + 'darkkhaki':'#bdb76b', + 'darkmagenta':'#8b008b', + 'darkolivegreen':'#556b2f', + 'darkorange':'#ff8c00', + 'darkorchid':'#9932cc', + 'darkred':'#8b0000', + 'darksalmon':'#e9967a', + 'darkseagreen':'#8fbc8f', + 'darkslateblue':'#483d8b', + 'darkslategray':'#2f4f4f', + 'darkslategrey':'#2f4f4f', + 'darkturquoise':'#00ced1', + 'darkviolet':'#9400d3', + 'deeppink':'#ff1493', + 'deepskyblue':'#00bfff', + 'dimgray':'#696969', + 'dimgrey':'#696969', + 'dodgerblue':'#1e90ff', + 'firebrick':'#b22222', + 'floralwhite':'#fffaf0', + 'forestgreen':'#228b22', + 'fuchsia':'#ff00ff', + 'gainsboro':'#dcdcdc', + 'ghostwhite':'#f8f8ff', + 'gold':'#ffd700', + 'goldenrod':'#daa520', + 'gray':'#808080', + 'grey':'#808080', + 'green':'#008000', + 'greenyellow':'#adff2f', + 'honeydew':'#f0fff0', + 'hotpink':'#ff69b4', + 'indianred':'#cd5c5c', + 'indigo':'#4b0082', + 'ivory':'#fffff0', + 'khaki':'#f0e68c', + 'lavender':'#e6e6fa', + 'lavenderblush':'#fff0f5', + 'lawngreen':'#7cfc00', + 'lemonchiffon':'#fffacd', + 'lightblue':'#add8e6', + 'lightcoral':'#f08080', + 'lightcyan':'#e0ffff', + 'lightgoldenrodyellow':'#fafad2', + 'lightgray':'#d3d3d3', + 'lightgrey':'#d3d3d3', + 'lightgreen':'#90ee90', + 'lightpink':'#ffb6c1', + 'lightsalmon':'#ffa07a', + 'lightseagreen':'#20b2aa', + 'lightskyblue':'#87cefa', + 'lightslategray':'#778899', + 'lightslategrey':'#778899', + 'lightsteelblue':'#b0c4de', + 'lightyellow':'#ffffe0', + 'lime':'#00ff00', + 'limegreen':'#32cd32', + 'linen':'#faf0e6', + 'magenta':'#ff00ff', + 'maroon':'#800000', + 'mediumaquamarine':'#66cdaa', + 'mediumblue':'#0000cd', + 'mediumorchid':'#ba55d3', + 'mediumpurple':'#9370d8', + 'mediumseagreen':'#3cb371', + 'mediumslateblue':'#7b68ee', + 'mediumspringgreen':'#00fa9a', + 'mediumturquoise':'#48d1cc', + 'mediumvioletred':'#c71585', + 'midnightblue':'#191970', + 'mintcream':'#f5fffa', + 'mistyrose':'#ffe4e1', + 'moccasin':'#ffe4b5', + 'navajowhite':'#ffdead', + 'navy':'#000080', + 'oldlace':'#fdf5e6', + 'olive':'#808000', + 'olivedrab':'#6b8e23', + 'orange':'#ffa500', + 'orangered':'#ff4500', + 'orchid':'#da70d6', + 'palegoldenrod':'#eee8aa', + 'palegreen':'#98fb98', + 'paleturquoise':'#afeeee', + 'palevioletred':'#d87093', + 'papayawhip':'#ffefd5', + 'peachpuff':'#ffdab9', + 'peru':'#cd853f', + 'pink':'#ffc0cb', + 'plum':'#dda0dd', + 'powderblue':'#b0e0e6', + 'purple':'#800080', + 'red':'#ff0000', + 'rosybrown':'#bc8f8f', + 'royalblue':'#4169e1', + 'saddlebrown':'#8b4513', + 'salmon':'#fa8072', + 'sandybrown':'#f4a460', + 'seagreen':'#2e8b57', + 'seashell':'#fff5ee', + 'sienna':'#a0522d', + 'silver':'#c0c0c0', + 'skyblue':'#87ceeb', + 'slateblue':'#6a5acd', + 'slategray':'#708090', + 'slategrey':'#708090', + 'snow':'#fffafa', + 'springgreen':'#00ff7f', + 'steelblue':'#4682b4', + 'tan':'#d2b48c', + 'teal':'#008080', + 'thistle':'#d8bfd8', + 'tomato':'#ff6347', + 'turquoise':'#40e0d0', + 'violet':'#ee82ee', + 'wheat':'#f5deb3', + 'white':'#ffffff', + 'whitesmoke':'#f5f5f5', + 'yellow':'#ffff00', + 'yellowgreen':'#9acd32' + }; })(require('./tree')); var name; function loadStyleSheet(sheet, callback, reload, remaining) { - var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; - var input = readFile(sheetName); - var parser = new less.Parser({ - paths: [sheet.href.replace(/[\w\.-]+$/, '')] - }); - parser.parse(input, function (e, root) { - if (e) { - print("Error: " + e); - quit(1); - } - callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); - }); + var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href; + var input = readFile(sheetName); + var parser = new less.Parser({ + paths: [sheet.href.replace(/[\w\.-]+$/, '')] + }); + parser.parse(input, function (e, root) { + if (e) { + print("Error: " + e); + quit(1); + } + callback(root, sheet, { local: false, lastModified: 0, remaining: remaining }); + }); - // callback({}, sheet, { local: true, remaining: remaining }); + // callback({}, sheet, { local: true, remaining: remaining }); } function writeFile(filename, content) { - var fstream = new java.io.FileWriter(filename); - var out = new java.io.BufferedWriter(fstream); - out.write(content); - out.close(); + var fstream = new java.io.FileWriter(filename); + var out = new java.io.BufferedWriter(fstream); + out.write(content); + out.close(); } // Prevent command line integration with Helma if (typeof HopObject === 'undefined') { - // Command line integration via Rhino - (function (args) { - name = args[0]; - var output = args[1]; + // Command line integration via Rhino + (function (args) { + name = args[0]; + var output = args[1]; - if (!name) { - print('No files present in the fileset; Check your pattern match in build.xml'); - quit(1); + if (!name) { + print('No files present in the fileset; Check your pattern match in build.xml'); + quit(1); + } + path = name.split("/");path.pop();path=path.join("/") + + var input = readFile(name); + + if (!input) { + print('lesscss: couldn\'t open file ' + name); + quit(1); + } + + var result; + var parser = new less.Parser(); + parser.parse(input, function (e, root) { + if (e) { + quit(1); + } else { + result = root.toCSS(); + if (output) { + writeFile(output, result); + print("Written to " + output); + } else { + print(result); + } + quit(0); } - path = name.split("/");path.pop();path=path.join("/") - - var input = readFile(name); - - if (!input) { - print('lesscss: couldn\'t open file ' + name); - quit(1); - } - - var result; - var parser = new less.Parser(); - parser.parse(input, function (e, root) { - if (e) { - quit(1); - } else { - result = root.toCSS(); - if (output) { - writeFile(output, result); - print("Written to " + output); - } else { - print(result); - } - quit(0); - } - }); - print("done"); - }(arguments)); + }); + print("done"); + }(arguments)); }})(); diff --git a/code/Global/Exporter.js b/code/Global/Exporter.js index 1b252474..130f4b01 100644 --- a/code/Global/Exporter.js +++ b/code/Global/Exporter.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -40,77 +40,77 @@ var Exporter = {} * @param {User} user The user whose content will be exported. */ Exporter.run = function(site, user) { - try { - var file; - if (site.export_id && (file = File.getById(site.export_id))) { - File.remove.call(file); - } + try { + var file; + if (site.export_id && (file = File.getById(site.export_id))) { + File.remove.call(file); + } - var rssUrl = site.href("rss.xml"); - var baseDir = site.getStaticFile(); - var member = site.members.get(user.name); + var rssUrl = site.href("rss.xml"); + var baseDir = site.getStaticFile(); + var member = site.members.get(user.name); - var xml = new helma.File(baseDir, "export.xml"); - xml.remove(); - xml.open(); + var xml = new helma.File(baseDir, "export.xml"); + xml.remove(); + xml.open(); - var add = function(s) { - return xml.write(s); - } + var add = function(s) { + return xml.write(s); + } - add(''); - add(''); - add(''); - add('tag:blogger.com,1999:blog-' + site._id + '.archive'); - add('' + site.modified.format(Date.ISOFORMAT) + ''); - add('' + encodeXml(site.title) + ''); - add(''); - add(''); - add(''); - add(''); + add(''); + add(''); + add(''); + add('tag:blogger.com,1999:blog-' + site._id + '.archive'); + add('' + site.modified.format(Date.ISOFORMAT) + ''); + add('' + encodeXml(site.title) + ''); + add(''); + add(''); + add(''); + add(''); + add(''); + add('' + site.creator.name + ''); + add('' + site.creator.email + ''); + add(''); + // Currently, blogger.com does not accept other generators + //add('Antville'); + add('Blogger'); + member.stories.forEach(function() { + add(''); + add('tag:blogger.com,1999:blog-' + site._id + '.post-' + this._id + ''); + add('' + this.created.format(Date.ISOFORMAT) + ''); + add('' + this.modified.format(Date.ISOFORMAT) + ''); + add('' + (this.title ? encodeXml(this.title.stripTags()) : '') + ''); + add('' + encodeXml(this.format_filter(this.text, {})) + ''); + add(''); + add(''); add(''); - add('' + site.creator.name + ''); - add('' + site.creator.email + ''); + add('' + this.creator.name + ''); + this.creator.url && add('' + this.creator.url + ''); + add('' + this.creator.email + ''); add(''); - // Currently, blogger.com does not accept other generators - //add('Antville'); - add('Blogger'); - member.stories.forEach(function() { - add(''); - add('tag:blogger.com,1999:blog-' + site._id + '.post-' + this._id + ''); - add('' + this.created.format(Date.ISOFORMAT) + ''); - add('' + this.modified.format(Date.ISOFORMAT) + ''); - add('' + (this.title ? encodeXml(this.title.stripTags()) : '') + ''); - add('' + encodeXml(this.format_filter(this.text, {})) + ''); - add(''); - add(''); - add(''); - add('' + this.creator.name + ''); - this.creator.url && add('' + this.creator.url + ''); - add('' + this.creator.email + ''); - add(''); - add(''); - }); - add(''); + add(''); + }); + add(''); - xml.close(); - // Provide the exported data as downloadable file - // FIXME: Adding a file to a site could be a little bit simpler :/ - file = new File; - file.site = site; - file.update({file: {contentLength: 0}, file_origin: "file://" + - xml.getPath(), name: site.name + "-export"}); - site.files.add(file); - file.creator = user; - site.export_id = file._id; - } catch (ex) { - app.log(ex); - } finally { - xml.close(); - xml.remove(); - } + xml.close(); + // Provide the exported data as downloadable file + // FIXME: Adding a file to a site could be a little bit simpler :/ + file = new File; + file.site = site; + file.update({file: {contentLength: 0}, file_origin: "file://" + + xml.getPath(), name: site.name + "-export"}); + site.files.add(file); + file.creator = user; + site.export_id = file._id; + } catch (ex) { + app.log(ex); + } finally { + xml.close(); + xml.remove(); + } - // Reset the site’s export status - site.job = null; - return; + // Reset the site’s export status + site.job = null; + return; } diff --git a/code/Global/Feature.js b/code/Global/Feature.js index 43134c47..0fd5f203 100644 --- a/code/Global/Feature.js +++ b/code/Global/Feature.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,11 +34,11 @@ * @param {String} id The identifier of the desired feature. */ global.feature_macro = function(param, id) { - var func, feature = Feature.get(id); - if (feature && (func = feature.main)) { - func.constructor === Function && func(param); - } - return; + var func, feature = Feature.get(id); + if (feature && (func = feature.main)) { + func.constructor === Function && func(param); + } + return; } /** @@ -49,19 +49,19 @@ global.feature_macro = function(param, id) { * @param {Object} feature The initial properties of the feature. */ var Feature = function(id, url, feature) { - var self = this; + var self = this; - this.__defineGetter__("id", function() {return id}); + this.__defineGetter__("id", function() {return id}); - for (let i in feature) { - this[i] = feature[i]; - } + for (let i in feature) { + this[i] = feature[i]; + } - this.toString = function() { - return "[Feature: " + html.linkAsString({href: url}, id) + "]"; - } + this.toString = function() { + return "[Feature: " + html.linkAsString({href: url}, id) + "]"; + } - return this; + return this; } /** @@ -70,18 +70,18 @@ var Feature = function(id, url, feature) { * @returns {Feature} */ Feature.add = function(id, url, feature) { - if (!id || !url) { - throw Error("Insufficient arguments"); - } + if (!id || !url) { + throw Error("Insufficient arguments"); + } - var existingFeature = Feature.get(id); - if (existingFeature) { - app.log("Warning! Overwriting already present feature with ID " + id); - Feature.remove(existingFeature); - } + var existingFeature = Feature.get(id); + if (existingFeature) { + app.log("Warning! Overwriting already present feature with ID " + id); + Feature.remove(existingFeature); + } - Feature.list().push(new Feature(id, url, feature)); - return this; + Feature.list().push(new Feature(id, url, feature)); + return this; } /** @@ -90,14 +90,14 @@ Feature.add = function(id, url, feature) { * @returns {Number} The resulting number of features still in the registry. */ Feature.remove = function(feature) { - var features = Feature.list(); - if (feature === "*") { - features.length = 0; - } else if (feature) { - var index = features.indexOf(feature); - (index > -1) && features.splice(index, 1); - } - return features.length; + var features = Feature.list(); + if (feature === "*") { + features.length = 0; + } else if (feature) { + var index = features.indexOf(feature); + (index > -1) && features.splice(index, 1); + } + return features.length; } /** @@ -105,7 +105,7 @@ Feature.remove = function(feature) { * @returns {Feature[]} */ Feature.list = function() { - return app.data.features; + return app.data.features; } /** @@ -114,12 +114,12 @@ Feature.list = function() { * @returns {Feature} */ Feature.get = function(id) { - for each (let feature in Feature.list()) { - if (feature.id === id) { - return feature; - } - } - return; + for each (let feature in Feature.list()) { + if (feature.id === id) { + return feature; + } + } + return; } /** @@ -129,32 +129,32 @@ Feature.get = function(id) { * @returns {Object} */ Feature.invoke = function(id, callback) { - id || (id = "*"); - if (callback) { - var feature, method, result; - var args = Array.prototype.slice.call(arguments, 2); - if (id === "*") { - for each (feature in Feature.list()) { - method = feature[String(callback)]; - if (method && method.constructor === Function) { - result = method.apply(feature, args); - } - } - } else { - feature = Feature.get(id); - if (feature) { - if (callback.constructor === Function) { - result = callback.apply(feature, args); - } else { - method = feature[callback]; - if (method && method.constructor === Function) { - result = method.apply(feature, args); - } - } - } + id || (id = "*"); + if (callback) { + var feature, method, result; + var args = Array.prototype.slice.call(arguments, 2); + if (id === "*") { + for each (feature in Feature.list()) { + method = feature[String(callback)]; + if (method && method.constructor === Function) { + result = method.apply(feature, args); + } } - } - return result; + } else { + feature = Feature.get(id); + if (feature) { + if (callback.constructor === Function) { + result = callback.apply(feature, args); + } else { + method = feature[callback]; + if (method && method.constructor === Function) { + result = method.apply(feature, args); + } + } + } + } + } + return result; } /** @@ -163,11 +163,11 @@ Feature.invoke = function(id, callback) { * @returns {Boolean} */ Feature.getPermission = function(action) { - for each (let feature in Feature.list()) { - let method = feature._getPermission; - if (method && method.constructor === Function && method.call(this, action)) { - return true; - } - } - return false; + for each (let feature in Feature.list()) { + let method = feature._getPermission; + if (method && method.constructor === Function && method.call(this, action)) { + return true; + } + } + return false; } \ No newline at end of file diff --git a/code/Global/FlexiPath.js b/code/Global/FlexiPath.js index 75c5bda4..d80a2987 100644 --- a/code/Global/FlexiPath.js +++ b/code/Global/FlexiPath.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -28,53 +28,53 @@ */ var FlexiPath = function(name, parent) { - var self = this; + var self = this; - this._id = name; - this._parent = parent; - this._patterns = {}; + this._id = name; + this._parent = parent; + this._patterns = {}; - this.__defineGetter__("patterns", function() { - var ref = this; - while (ref._parent.constructor === FlexiPath) { - ref = ref._parent; - } - return ref._patterns; - }); + this.__defineGetter__("patterns", function() { + var ref = this; + while (ref._parent.constructor === FlexiPath) { + ref = ref._parent; + } + return ref._patterns; + }); - this.addUrlPattern = function(pattern, callback) { - this._patterns[pattern] = callback; - return; - } + this.addUrlPattern = function(pattern, callback) { + this._patterns[pattern] = callback; + return; + } - this.href = function(action) { - var href = []; - var ref = this; - while (ref._parent === this.constructor) { - href.unshift(ref._id); - ref = ref._parent; - } - //href.push("/"); - if (action) { - href.push(action); - } - return root.api.href() + href.join("/"); - } + this.href = function(action) { + var href = []; + var ref = this; + while (ref._parent === this.constructor) { + href.unshift(ref._id); + ref = ref._parent; + } + //href.push("/"); + if (action) { + href.push(action); + } + return root.api.href() + href.join("/"); + } - this.getChildElement = function(name) { - return new this.constructor(name, self); - } + this.getChildElement = function(name) { + return new this.constructor(name, self); + } - return this; + return this; }; FlexiPath.prototype.main_action = function() { - for (let pattern in this.patterns) { - let match; - let re = new RegExp(pattern); - if (match = req.path.match(re)) { - return this.patterns[pattern].apply(this, match); - } - } - return; + for (let pattern in this.patterns) { + let match; + let re = new RegExp(pattern); + if (match = req.path.match(re)) { + return this.patterns[pattern].apply(this, match); + } + } + return; } diff --git a/code/Global/Global.js b/code/Global/Global.js index 0679d397..8bb963fd 100644 --- a/code/Global/Global.js +++ b/code/Global/Global.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -51,10 +51,10 @@ app.addRepository("modules/jala/code/Utilities.js"); // Adding i18n message files as repositories (function() { - var dir = new helma.File(app.dir, "../i18n"); - for each (let fname in dir.list()) { - fname.endsWith(".js") && app.addRepository(app.dir + "/../i18n/" + fname); - } + var dir = new helma.File(app.dir, "../i18n"); + for each (let fname in dir.list()) { + fname.endsWith(".js") && app.addRepository(app.dir + "/../i18n/" + fname); + } })(); // I18n.js needs to be added *after* the message files or the translations get lost app.addRepository("modules/jala/code/I18n.js"); @@ -119,22 +119,22 @@ app.data.requests || (app.data.requests = {}); * @param {helma.File} target */ helma.File.prototype.copyDirectory = function(target) { - /* - // Strange enough, Apache commons is not really faster... - var source = new java.io.File(this.toString()); - target = new java.io.File(target.toString()); - return Packages.org.apache.commons.io.FileUtils.copyDirectory(source, target); - */ - this.list().forEach(function(name) { - var file = new helma.File(this, name); - if (file.isDirectory()) { - file.copyDirectory(new helma.File(target, name)); - } else { - target.makeDirectory(); - file.hardCopy(new helma.File(target, name)); - } - }); - return; + /* + // Strange enough, Apache commons is not really faster... + var source = new java.io.File(this.toString()); + target = new java.io.File(target.toString()); + return Packages.org.apache.commons.io.FileUtils.copyDirectory(source, target); + */ + this.list().forEach(function(name) { + var file = new helma.File(this, name); + if (file.isDirectory()) { + file.copyDirectory(new helma.File(target, name)); + } else { + target.makeDirectory(); + file.hardCopy(new helma.File(target, name)); + } + }); + return; } /** @@ -148,7 +148,7 @@ helma.File.prototype.copyDirectory = function(target) { * @returns {Number} The number of mails waiting in the queue */ helma.Mail.prototype.queue = function() { - return app.data.mails.push(this); + return app.data.mails.push(this); } /** @@ -156,20 +156,20 @@ helma.Mail.prototype.queue = function() { * @see app.data.mails */ helma.Mail.flushQueue = function() { - if (app.data.mails.length > 0) { - app.debug("Flushing mail queue, sending " + - app.data.mails.length + " messages"); - var mail; - while (app.data.mails.length > 0) { - mail = app.data.mails.pop(); - mail.send(); - if (mail.status > 0) { - app.debug("Error while sending e-mail (status " + mail.status + ")"); - mail.writeToFile(getProperty("smtp.dir")); - } + if (app.data.mails.length > 0) { + app.debug("Flushing mail queue, sending " + + app.data.mails.length + " messages"); + var mail; + while (app.data.mails.length > 0) { + mail = app.data.mails.pop(); + mail.send(); + if (mail.status > 0) { + app.debug("Error while sending e-mail (status " + mail.status + ")"); + mail.writeToFile(getProperty("smtp.dir")); } - } - return; + } + } + return; } /** @@ -178,7 +178,7 @@ helma.Mail.flushQueue = function() { * @namespace */ jala.i18n.setLocaleGetter(function() { - return (res.handlers.site || root).getLocale(); + return (res.handlers.site || root).getLocale(); }); /** @@ -220,10 +220,10 @@ var lessParser = new less.Parser(); * @type Object */ var rome = new JavaImporter( - Packages.com.sun.syndication.io, - Packages.com.sun.syndication.feed.synd, - Packages.com.sun.syndication.feed.module.itunes, - Packages.com.sun.syndication.feed.module.itunes.types + Packages.com.sun.syndication.io, + Packages.com.sun.syndication.feed.synd, + Packages.com.sun.syndication.feed.module.itunes, + Packages.com.sun.syndication.feed.module.itunes.types ); /** @@ -231,35 +231,35 @@ var rome = new JavaImporter( * @namespace */ var console = { - /** - * Convenience method for bridging log output from the server to the client. - * @methodOf console - * @param {String} text This text will be displayed in the browser’s console (if available). - */ - log: function(text /*, text, … */) { - if (!res.meta.__console__) { - res.debug(''); - res.meta.__console__ = true; - } - var now = formatDate(new Date, Date.ISOFORMAT); - Array.prototype.unshift.call(arguments, '[Helma]', now, '===>'); - var text = Array.prototype.join.call(arguments, ' '); - text = text.replace(/(?:\n|\r)/g, '\\n').replace(/('|")/g, '\\$1'); - res.debug(''); - } + /** + * Convenience method for bridging log output from the server to the client. + * @methodOf console + * @param {String} text This text will be displayed in the browser’s console (if available). + */ + log: function(text /*, text, … */) { + if (!res.meta.__console__) { + res.debug(''); + res.meta.__console__ = true; + } + var now = formatDate(new Date, Date.ISOFORMAT); + Array.prototype.unshift.call(arguments, '[Helma]', now, '===>'); + var text = Array.prototype.join.call(arguments, ' '); + text = text.replace(/(?:\n|\r)/g, '\\n').replace(/('|")/g, '\\$1'); + res.debug(''); + } } /** * The startup handler Helma is calling automatically shortly after the application has started. */ function onStart() { - if (typeof root === "undefined") { - app.logger.error("Error in database configuration: no root site found."); - return; - } - // This is necessary once to be sure that aspect-oriented code will be applied - HopObject.prototype.onCodeUpdate && HopObject.prototype.onCodeUpdate(); - return; + if (typeof root === "undefined") { + app.logger.error("Error in database configuration: no root site found."); + return; + } + // This is necessary once to be sure that aspect-oriented code will be applied + HopObject.prototype.onCodeUpdate && HopObject.prototype.onCodeUpdate(); + return; } /** @@ -273,20 +273,20 @@ function onStop() { /* Currently empty, just to avoid annoying log message */ } * @returns {Function} */ function defineConstants(ctor /*, arguments */) { - var constants = [], name; - for (var i=1; i URL of the story of site “blog” */ function story_macro(param, id, mode) { - var story = HopObject.getFromPath(id, "stories"); - if (!story || !story.getPermission("main")) { - return; - } + var story = HopObject.getFromPath(id, "stories"); + if (!story || !story.getPermission("main")) { + return; + } - switch (mode) { - case "url": - res.write(story.href()); - break; - case "link": - html.link({href: story.href()}, story.getTitle()); - break; - default: - story.renderSkin("Story#" + (param.skin || "embed")); - } - return; + switch (mode) { + case "url": + res.write(story.href()); + break; + case "link": + html.link({href: story.href()}, story.getTitle()); + break; + default: + story.renderSkin("Story#" + (param.skin || "embed")); + } + return; } /** @@ -464,41 +464,41 @@ function story_macro(param, id, mode) { * <% file /image.raw %> Static file of root site */ function file_macro(param, id, mode) { - if (!id) { - return; - } + if (!id) { + return; + } - var file; - if (id.startsWith("/")) { - name = id.substring(1); - if (mode === "url") { - res.write(root.getStaticUrl(name)); - } else { - file = root.getStaticFile(name); - res.push(); - File.prototype.contentLength_macro.call({ - contentLength: file.getLength() - }); - res.handlers.file = { - href: root.getStaticUrl(name), - name: name, - contentLength: res.pop() - }; - File.prototype.renderSkin("File#main"); - } - return; - } + var file; + if (id.startsWith("/")) { + name = id.substring(1); + if (mode === "url") { + res.write(root.getStaticUrl(name)); + } else { + file = root.getStaticFile(name); + res.push(); + File.prototype.contentLength_macro.call({ + contentLength: file.getLength() + }); + res.handlers.file = { + href: root.getStaticUrl(name), + name: name, + contentLength: res.pop() + }; + File.prototype.renderSkin("File#main"); + } + return; + } - file = HopObject.getFromPath(id, "files"); - if (!file) { - return; - } - if (mode === "url") { - res.write(file.getUrl()); - } else { - file.renderSkin("File#" + (param.skin || "main")); - } - return; + file = HopObject.getFromPath(id, "files"); + if (!file) { + return; + } + if (mode === "url") { + res.write(file.getUrl()); + } else { + file.renderSkin("File#" + (param.skin || "main")); + } + return; } /** @@ -510,44 +510,44 @@ function file_macro(param, id, mode) { * @param {String} [mode] Either of 'url' or 'thumbnail' */ function image_macro(param, id, mode) { - if (!id) { - return; - } + if (!id) { + return; + } - var image; - if (id.startsWith("/")) { - var name = id.substring(1); - image = Images.Default[name] || Images.Default[name + ".gif"]; - } else { - image = HopObject.getFromPath(id, "images"); - // FIXME: Could fallback be replaced with CSS background-image? - if (!image && param.fallback) { - image = HopObject.getFromPath(param.fallback, "images"); - } - } + var image; + if (id.startsWith("/")) { + var name = id.substring(1); + image = Images.Default[name] || Images.Default[name + ".gif"]; + } else { + image = HopObject.getFromPath(id, "images"); + // FIXME: Could fallback be replaced with CSS background-image? + if (!image && param.fallback) { + image = HopObject.getFromPath(param.fallback, "images"); + } + } - if (!image) { - return; - } + if (!image) { + return; + } - switch (mode) { - case "url": - res.write(image.getUrl()); - break; - case "thumbnail": - case "popup": - var url = image.getUrl(); - html.openTag("a", {href: url}); - // FIXME: Bloody popups belong to compatibility layer - (mode === "popup") && (param.onclick = 'javascript:openPopup(\'' + - url + '\', ' + image.width + ', ' + image.height + '); return false;') - image.thumbnail_macro(param); - html.closeTag("a"); - break; - default: - image.render_macro(param); - } - return; + switch (mode) { + case "url": + res.write(image.getUrl()); + break; + case "thumbnail": + case "popup": + var url = image.getUrl(); + html.openTag("a", {href: url}); + // FIXME: Bloody popups belong to compatibility layer + (mode === "popup") && (param.onclick = 'javascript:openPopup(\'' + + url + '\', ' + image.width + ', ' + image.height + '); return false;') + image.thumbnail_macro(param); + html.closeTag("a"); + break; + default: + image.render_macro(param); + } + return; } /** @@ -557,32 +557,32 @@ function image_macro(param, id, mode) { * @param {String} mode Either of 'url' or 'link' */ function poll_macro(param, id, mode) { - if (!id) { - return; - } + if (!id) { + return; + } - var poll = HopObject.getFromPath(id, "polls"); - if (!poll) { - return; - } + var poll = HopObject.getFromPath(id, "polls"); + if (!poll) { + return; + } - switch (mode) { - case "url": - res.write(poll.href()); - break; - case "link": - html.link({ - href: poll.href(poll.status === Poll.CLOSED ? "result" : "") - }, poll.question); - break; - default: - if (poll.status === Poll.CLOSED || mode === "results") - poll.renderSkin("$Poll#results", {}); - else { - poll.renderSkin("$Poll#main", {}); - } - } - return; + switch (mode) { + case "url": + res.write(poll.href()); + break; + case "link": + html.link({ + href: poll.href(poll.status === Poll.CLOSED ? "result" : "") + }, poll.question); + break; + default: + if (poll.status === Poll.CLOSED || mode === "results") + poll.renderSkin("$Poll#results", {}); + else { + poll.renderSkin("$Poll#main", {}); + } + } + return; } /** @@ -602,98 +602,98 @@ function poll_macro(param, id, mode) { * <% list tags %> */ function list_macro(param, id, limit) { - if (!id) { + if (!id) { + return; + } + + var skin, collection; + var max = Math.min(limit || 25, 50); + + if (id === "sites") { + collection = root.sites.list(0, max); + skin = "Site#preview"; + } else if (id === "updates") { + collection = root.updates.list(0, limit); + skin = "Site#preview"; + } else { + var site, type; + var parts = id.split("/"); + if (parts.length > 1) { + type = parts[1]; + site = root.sites.get(parts[0]); + } else { + type = parts[0]; + } + + site || (site = res.handlers.site); + var filter = function(item, index) { + return index < max && item.getPermission("main"); + } + + var commentFilter = function(item) { + if (item.story.status !== Story.CLOSED && + item.site.commentMode !== Site.DISABLED && + item.story.commentMode !== Story.CLOSED) { + return true; + } + return false; + } + + switch (type) { + case "comments": + if (site.commentMode !== Site.DISABLED) { + var comments = site.stories.comments; + collection = comments.list().filter(filter); + skin = "Story#preview"; + } + break; + + case "featured": + collection = site.stories.featured.list(0, max); + skin = "Story#preview"; + break; + + case "images": + collection = site.images.list(0, max); + skin = "Image#preview"; + break; + + case "macros": + res.handlers.site.stories.renderSkin('$Stories#macros'); return; - } - var skin, collection; - var max = Math.min(limit || 25, 50); + case "postings": + var content = site.stories.union; + collection = content.list().filter(filter).filter(function(item) { + if (item.constructor === Comment) { + return commentFilter(item); + } + return true; + }); + skin = "Story#preview"; + break; - if (id === "sites") { - collection = root.sites.list(0, max); - skin = "Site#preview"; - } else if (id === "updates") { - collection = root.updates.list(0, limit); - skin = "Site#preview"; - } else { - var site, type; - var parts = id.split("/"); - if (parts.length > 1) { - type = parts[1]; - site = root.sites.get(parts[0]); - } else { - type = parts[0]; - } + case "stories": + var stories = site.stories.recent; + var counter = 0; + collection = stories.list().filter(function(item, index) { + return item.constructor === Story && filter(item, counter++); + }); + skin = "Story#preview"; + break; - site || (site = res.handlers.site); - var filter = function(item, index) { - return index < max && item.getPermission("main"); - } + case "tags": + return site.tags.list_macro(param, param.skin || "$Tag#preview"); + break; - var commentFilter = function(item) { - if (item.story.status !== Story.CLOSED && - item.site.commentMode !== Site.DISABLED && - item.story.commentMode !== Story.CLOSED) { - return true; - } - return false; - } - - switch (type) { - case "comments": - if (site.commentMode !== Site.DISABLED) { - var comments = site.stories.comments; - collection = comments.list().filter(filter); - skin = "Story#preview"; - } - break; - - case "featured": - collection = site.stories.featured.list(0, max); - skin = "Story#preview"; - break; - - case "images": - collection = site.images.list(0, max); - skin = "Image#preview"; - break; - - case "macros": - res.handlers.site.stories.renderSkin('$Stories#macros'); - return; - - case "postings": - var content = site.stories.union; - collection = content.list().filter(filter).filter(function(item) { - if (item.constructor === Comment) { - return commentFilter(item); - } - return true; - }); - skin = "Story#preview"; - break; - - case "stories": - var stories = site.stories.recent; - var counter = 0; - collection = stories.list().filter(function(item, index) { - return item.constructor === Story && filter(item, counter++); - }); - skin = "Story#preview"; - break; - - case "tags": - return site.tags.list_macro(param, param.skin || "$Tag#preview"); - break; - - default: - break; - } - } - for each (var item in collection) { - item.renderSkin(param.skin || skin); - } - return; + default: + break; + } + } + for each (var item in collection) { + item.renderSkin(param.skin || skin); + } + return; } /** @@ -708,17 +708,17 @@ function list_macro(param, id, limit) { * @example <% value foo %> Renders the value of res.meta.value.foo */ function value_macro(param, name, value) { - if (!name) { - return; - } - name = name.toLowerCase(); - if (!value) { - res.write(res.meta.values[name]); - } else { - //res.write("/* set " + name + " to " + value + " */"); - res.meta.values[name] = value; - } - return; + if (!name) { + return; + } + name = name.toLowerCase(); + if (!value) { + res.write(res.meta.values[name]); + } else { + //res.write("/* set " + name + " to " + value + " */"); + res.meta.values[name] = value; + } + return; } /** @@ -738,57 +738,57 @@ function value_macro(param, name, value) { * <% random foo/image gallery=cat %> Renders the default skin of a random image in the gallery “cat“ of the site “foo”. */ function random_macro(param, type, mode) { - var getRandom = function(n) { - return Math.floor(Math.random() * n); - }; + var getRandom = function(n) { + return Math.floor(Math.random() * n); + }; - var site = res.handlers.site; + var site = res.handlers.site; - if (type === "site") { - site = root.sites.get(getRandom(root.sites.size())); - mode === 'url' ? res.write(site.href()) : - site.renderSkin(param.skin || "Site#preview"); - return; - } + if (type === "site") { + site = root.sites.get(getRandom(root.sites.size())); + mode === 'url' ? res.write(site.href()) : + site.renderSkin(param.skin || "Site#preview"); + return; + } - var parts = type.split("/"); - if (parts.length > 1) { - site = root.sites.get(parts[0] || 'www'); - type = parts[1]; - } else { - type = parts[0]; - } + var parts = type.split("/"); + if (parts.length > 1) { + site = root.sites.get(parts[0] || 'www'); + type = parts[1]; + } else { + type = parts[0]; + } - if (!site) { - return; - } + if (!site) { + return; + } - switch (type) { - case "story": - case "stories": - var stories = param.tag ? site.stories.tags.get(param.tag) : - site.stories.featured; - var story = stories && stories.get(getRandom(stories.size())); - if (story) { - param.tag && (story = story.tagged); - mode === 'url' ? res.write(story.href()) : - story.renderSkin(param.skin || "Story#preview"); - } - break; + switch (type) { + case "story": + case "stories": + var stories = param.tag ? site.stories.tags.get(param.tag) : + site.stories.featured; + var story = stories && stories.get(getRandom(stories.size())); + if (story) { + param.tag && (story = story.tagged); + mode === 'url' ? res.write(story.href()) : + story.renderSkin(param.skin || "Story#preview"); + } + break; - case "image": - case "images": - var images = param.gallery ? site.images.galleries.get(param.gallery) : - site.images; - var image = images && images.get(getRandom(images.size())); - if (image) { - param.gallery && (image = image.tagged); - mode === 'url' ? res.write(image.href()) : - image.renderSkin(param.skin || "Image#preview"); - } - break; - } - return; + case "image": + case "images": + var images = param.gallery ? site.images.galleries.get(param.gallery) : + site.images; + var image = images && images.get(getRandom(images.size())); + if (image) { + param.gallery && (image = image.tagged); + mode === 'url' ? res.write(image.href()) : + image.renderSkin(param.skin || "Image#preview"); + } + break; + } + return; } /** @@ -798,9 +798,9 @@ function random_macro(param, type, mode) { * @see Root.VERSION */ function version_macro(param, type) { - var version = Root.VERSION; - var result = version[type || "default"]; - return result || version; + var version = Root.VERSION; + var result = version[type || "default"]; + return result || version; } /** @@ -809,13 +809,13 @@ function version_macro(param, type) { * @param {String} str The string to be rendered. */ function listItemFlag_macro(param, str) { - res.push(); - for (var i=0; i"); - } - renderSkin("$Global#listItemFlag", {text: res.pop()}); - return; + res.push(); + for (var i=0; i"); + } + renderSkin("$Global#listItemFlag", {text: res.pop()}); + return; } @@ -827,7 +827,7 @@ function listItemFlag_macro(param, str) { * @returns {Object} The value argument if truthy, the defaultValue argument otherwise. */ function default_filter(value, param, defaultValue) { - return value || defaultValue; + return value || defaultValue; } /** @@ -838,10 +838,10 @@ function default_filter(value, param, defaultValue) { * @returns {String} The resulting age string of the original date. */ function age_filter(value, param) { - if (!value || value.constructor !== Date) { - return value; - } - return value.getAge() + if (!value || value.constructor !== Date) { + return value; + } + return value.getAge() } /** @@ -853,13 +853,13 @@ function age_filter(value, param) { * @see renderLink */ function link_filter(text, param, url) { - if (text) { - url || (url = text); - res.push(); - renderLink(param, url, text); - return res.pop(); - } - return; + if (text) { + url || (url = text); + res.push(); + renderLink(param, url, text); + return res.pop(); + } + return; } /** @@ -873,14 +873,14 @@ function link_filter(text, param, url) { * @returns {String} The formatted string. */ function format_filter(value, param, pattern, type) { - if (!value && value !== 0) { - return; - } - var f = global["format" + value.constructor.name]; - if (f && f.constructor === Function) { - return f(value, pattern || param.pattern, type); - } - return value; + if (!value && value !== 0) { + return; + } + var f = global["format" + value.constructor.name]; + if (f && f.constructor === Function) { + return f(value, pattern || param.pattern, type); + } + return value; } /** @@ -893,16 +893,16 @@ function format_filter(value, param, pattern, type) { * @returns {String} The clipped result. */ function clip_filter(input, param, limit, clipping, delimiter) { - var len = 0; - if (input) { - len = input.length; - input = input.stripTags(); - } - input || (input = ngettext("({0} character)", "({0} characters)", len)); - limit || (limit = 20); - clipping || (clipping = "..."); - delimiter || (delimiter = "\\s"); - return String(input || "").head(limit, clipping, delimiter); + var len = 0; + if (input) { + len = input.length; + input = input.stripTags(); + } + input || (input = ngettext("({0} character)", "({0} characters)", len)); + limit || (limit = 20); + clipping || (clipping = "..."); + delimiter || (delimiter = "\\s"); + return String(input || "").head(limit, clipping, delimiter); } /** @@ -916,27 +916,27 @@ function clip_filter(input, param, limit, clipping, delimiter) { * @param {HopObject} handler The HopObject used as base URL. Optional if “url” is specified. */ function renderLink(param, url, text, handler) { - url || (url = param.url || String.EMPTY); - text || (text = param.text || url); - if (!text || (handler && !handler.href)) { - return; - } - if (url === "." || url === "main") { - url = String.EMPTY; - } - delete param.url; - delete param.text; - param.title || (param.title = String.EMPTY); - if (!handler || url.contains(":")) { - param.href = url; - } else if (url.contains("/") || url.contains("?") || url.contains("#")) { - var parts = url.split(/(\/|\?|#)/); - param.href = handler.href(parts[0]) + parts.splice(1).join(String.EMPTY); - } else { - param.href = handler.href(url); - } - html.link(param, text); - return; + url || (url = param.url || String.EMPTY); + text || (text = param.text || url); + if (!text || (handler && !handler.href)) { + return; + } + if (url === "." || url === "main") { + url = String.EMPTY; + } + delete param.url; + delete param.text; + param.title || (param.title = String.EMPTY); + if (!handler || url.contains(":")) { + param.href = url; + } else if (url.contains("/") || url.contains("?") || url.contains("#")) { + var parts = url.split(/(\/|\?|#)/); + param.href = handler.href(parts[0]) + parts.splice(1).join(String.EMPTY); + } else { + param.href = handler.href(url); + } + html.link(param, text); + return; } /** @@ -947,11 +947,11 @@ function renderLink(param, url, text, handler) { */ function validateEmail(str) { if (str) { - if (str.isEmail()) { - return str; - } - } - return null; + if (str.isEmail()) { + return str; + } + } + return null; } /** @@ -960,16 +960,16 @@ function validateEmail(str) { * @returns {String|null} The URL string if valid, null otherwise. */ function validateUrl(str) { - if (str) { - if (str.isUrl()) { - return str; - } else if (str.isEmail()) { - return "mailto:" + str; - } else { - return null; - } - } - return null; + if (str) { + if (str.isUrl()) { + return str; + } else if (str.isEmail()) { + return "mailto:" + str; + } else { + return null; + } + } + return null; } /** @@ -978,10 +978,10 @@ function validateUrl(str) { * @returns {String} The processed string. */ function quote(str) { - if (/[\W\D]/.test(str)) { - str = '"' + str + '"'; - } - return str; + if (/[\W\D]/.test(str)) { + str = '"' + str + '"'; + } + return str; } /** @@ -991,7 +991,7 @@ function quote(str) { * @returns {String} The formatted number string. */ function formatNumber(number, pattern) { - return Number(number).format(pattern, res.handlers.site.getLocale()); + return Number(number).format(pattern, res.handlers.site.getLocale()); } /** @@ -1001,74 +1001,74 @@ function formatNumber(number, pattern) { * @returns {String} The formatted date string. */ function formatDate(date, format) { - if (!date) { - return null; - } + if (!date) { + return null; + } - var pattern, - site = res.handlers.site, - locale = site.getLocale(); + var pattern, + site = res.handlers.site, + locale = site.getLocale(); - switch (format) { - case null: - case undefined: - format = "full"; // Caution! Passing through to next case block! - case "short": - case "medium": - case "long": - case "full": - var type = java.text.DateFormat[format.toUpperCase()]; - pattern = java.text.DateFormat.getDateTimeInstance(type, type, locale).toPattern(); - break; + switch (format) { + case null: + case undefined: + format = "full"; // Caution! Passing through to next case block! + case "short": + case "medium": + case "long": + case "full": + var type = java.text.DateFormat[format.toUpperCase()]; + pattern = java.text.DateFormat.getDateTimeInstance(type, type, locale).toPattern(); + break; - case "date": - var type = java.text.DateFormat.FULL - pattern = java.text.DateFormat.getDateInstance(type, locale).toPattern(); - break; + case "date": + var type = java.text.DateFormat.FULL + pattern = java.text.DateFormat.getDateInstance(type, locale).toPattern(); + break; - case "time": - var type = java.text.DateFormat.SHORT; - pattern = java.text.DateFormat.getTimeInstance(type, locale).toPattern(); - break; + case "time": + var type = java.text.DateFormat.SHORT; + pattern = java.text.DateFormat.getTimeInstance(type, locale).toPattern(); + break; - case "iso": - pattern = Date.ISOFORMAT; - break; + case "iso": + pattern = Date.ISOFORMAT; + break; - case "text": - var text, - now = new Date, - diff = now - date; - if (diff < 0) { - // FIXME: Do something similar for future dates - text = formatDate(date); - } else if (diff < Date.ONEMINUTE) { - text = gettext("Right now"); - } else if (diff < Date.ONEHOUR) { - text = ngettext("{0} minute ago", "{0} minutes ago", - parseInt(diff / Date.ONEMINUTE, 10)); - } else if (diff < Date.ONEDAY) { - text = ngettext("{0} hour ago", "{0} hours ago", - parseInt(diff / Date.ONEHOUR, 10)); - } else if (diff < 2 * Date.ONEDAY) { - text = gettext("Yesterday"); - } else { - text = ngettext("{0} day ago", "{0} days ago", - parseInt(diff / Date.ONEDAY, 10)); - } - return text; + case "text": + var text, + now = new Date, + diff = now - date; + if (diff < 0) { + // FIXME: Do something similar for future dates + text = formatDate(date); + } else if (diff < Date.ONEMINUTE) { + text = gettext("Right now"); + } else if (diff < Date.ONEHOUR) { + text = ngettext("{0} minute ago", "{0} minutes ago", + parseInt(diff / Date.ONEMINUTE, 10)); + } else if (diff < Date.ONEDAY) { + text = ngettext("{0} hour ago", "{0} hours ago", + parseInt(diff / Date.ONEHOUR, 10)); + } else if (diff < 2 * Date.ONEDAY) { + text = gettext("Yesterday"); + } else { + text = ngettext("{0} day ago", "{0} days ago", + parseInt(diff / Date.ONEDAY, 10)); + } + return text; - default: - pattern = format; - } + default: + pattern = format; + } - try { - return date.format(pattern, locale, site.getTimeZone()); - } catch (ex) { - return "[Invalid date format]"; - } + try { + return date.format(pattern, locale, site.getTimeZone()); + } catch (ex) { + return "[Invalid date format]"; + } - return String.EMPTY; + return String.EMPTY; } /** @@ -1077,9 +1077,9 @@ function formatDate(date, format) { * @returns {String} An XML string containing the XSLT stylesheet declaration */ function injectXslDeclaration(xml) { - res.push(); - renderSkin("Global#xslDeclaration"); - return xml.replace(/(\?>\r?\n?)/, "$1" + res.pop()); + res.push(); + renderSkin("Global#xslDeclaration"); + return xml.replace(/(\?>\r?\n?)/, "$1" + res.pop()); } /** @@ -1090,27 +1090,27 @@ function injectXslDeclaration(xml) { * @returns {Number} The status code of the underlying helma.Mail instance */ function sendMail(recipient, subject, body, options) { - options || (options = {}); - if (!recipient || !body) { - throw Error("Insufficient arguments in method sendMail()"); - } - var mail = new helma.Mail(getProperty("smtp", "localhost"), - getProperty("smtp.port", "25")); - mail.setFrom(root.replyTo || "root@localhost"); - if (recipient instanceof Array) { - for (var i in recipient) { - mail.addBCC(recipient[i]); - } - } else { - mail.addTo(recipient); - } - mail.setSubject(subject); - mail.setText(body); - if (options.footer !== false) { // It is the exception to have no footer - mail.addText(renderSkinAsString("$Global#mailFooter")); - } - mail.queue(); - return mail.status; + options || (options = {}); + if (!recipient || !body) { + throw Error("Insufficient arguments in method sendMail()"); + } + var mail = new helma.Mail(getProperty("smtp", "localhost"), + getProperty("smtp.port", "25")); + mail.setFrom(root.replyTo || "root@localhost"); + if (recipient instanceof Array) { + for (var i in recipient) { + mail.addBCC(recipient[i]); + } + } else { + mail.addTo(recipient); + } + mail.setSubject(subject); + mail.setText(body); + if (options.footer !== false) { // It is the exception to have no footer + mail.addText(renderSkinAsString("$Global#mailFooter")); + } + mail.queue(); + return mail.status; } /** @@ -1119,7 +1119,7 @@ function sendMail(recipient, subject, body, options) { * @returns {java.util.Locale} The corresponding locale object. */ function getLocale(language) { - return new java.util.Locale(language || "english"); + return new java.util.Locale(language || "english"); } /** @@ -1128,21 +1128,21 @@ function getLocale(language) { * @returns {Object[]} A sorted array containing the corresponding locales */ function getLocales(language) { - var result = [], locale, localeString; - var locales = java.util.Locale.getAvailableLocales(); - for (var i in locales) { - locale = locales[i]; - localeString = locale.toString(); - if (!localeString.contains("_")) { - result.push({ - value: localeString, - display: locale.getDisplayName(locale), - "class": jala.i18n.getCatalog(jala.i18n.getLocale(localeString)) ? "translated" : "" - }); - } - } - result.sort(new String.Sorter("display")); - return result; + var result = [], locale, localeString; + var locales = java.util.Locale.getAvailableLocales(); + for (var i in locales) { + locale = locales[i]; + localeString = locale.toString(); + if (!localeString.contains("_")) { + result.push({ + value: localeString, + display: locale.getDisplayName(locale), + "class": jala.i18n.getCatalog(jala.i18n.getLocale(localeString)) ? "translated" : "" + }); + } + } + result.sort(new String.Sorter("display")); + return result; } /** @@ -1159,30 +1159,30 @@ function getLocales(language) { * @returns {Object[]} A sorted array containing the corresponding timezones */ function getTimeZones(language) { - var result = [], - timeZones = [], - locale = getLocale(language), - ids = java.util.TimeZone.getAvailableIDs(); + var result = [], + timeZones = [], + locale = getLocale(language), + ids = java.util.TimeZone.getAvailableIDs(); - for each (let id in ids) { - // Exclude confusing time zones - if (id.length < 4 || !id.contains("/") || - id.startsWith("Etc") || id.startsWith("System")) { - continue; - } - let timeZone = java.util.TimeZone.getTimeZone(id); - // Exclude more confusing time zones - if (timeZone.getDisplayName().startsWith("GMT")) { - continue; - } - result.push({ - value: timeZone.getID(), - display: timeZone.getID().replace(/_/g, String.SPACE) - }) - timeZones.push(timeZone); - } + for each (let id in ids) { + // Exclude confusing time zones + if (id.length < 4 || !id.contains("/") || + id.startsWith("Etc") || id.startsWith("System")) { + continue; + } + let timeZone = java.util.TimeZone.getTimeZone(id); + // Exclude more confusing time zones + if (timeZone.getDisplayName().startsWith("GMT")) { + continue; + } + result.push({ + value: timeZone.getID(), + display: timeZone.getID().replace(/_/g, String.SPACE) + }) + timeZones.push(timeZone); + } - return result.sort(new String.Sorter("display")); + return result.sort(new String.Sorter("display")); } // FIXME: /** @@ -1191,9 +1191,9 @@ function getTimeZones(language) { * @returns {String} The transformed RSS output. */ function fixRssText(rss) { - var re = new RegExp("]*?(alt\\s*=\\s*\"?([^\"]+)?\"?[^>]*?)?>", "gi"); - rss = rss.replace(re, "[Image]"); - return rss; + var re = new RegExp("]*?(alt\\s*=\\s*\"?([^\"]+)?\"?[^>]*?)?>", "gi"); + rss = rss.replace(re, "[Image]"); + return rss; } // FIXME: @@ -1202,34 +1202,34 @@ function fixRssText(rss) { * @param {Object} src */ function doWikiStuff (src) { - // robert, disabled: didn't get the reason for this: - // var src= " "+src; - if (src == null || !src.contains("<*")) - return src; + // robert, disabled: didn't get the reason for this: + // var src= " "+src; + if (src == null || !src.contains("<*")) + return src; - // do the Wiki link thing, <*asterisk style*> - var regex = new RegExp ("<[*]([^*]+)[*]>"); - regex.ignoreCase=true; + // do the Wiki link thing, <*asterisk style*> + var regex = new RegExp ("<[*]([^*]+)[*]>"); + regex.ignoreCase=true; - var text = ""; - var start = 0; - while (true) { - var found = regex.exec (src.substring(start)); - var to = found == null ? src.length : start + found.index; - text += src.substring(start, to); - if (found == null) - break; - var name = ""+(new java.lang.String (found[1])).trim(); - var item = res.handlers.site.topics.get (name); - if (item == null && name.lastIndexOf("s") == name.length-1) - item = res.handlers.site.topics.get (name.substring(0, name.length-1)); - if (item == null || !item.size()) - text += format(name)+" [define "+format(name)+"]"; - else - text += ""+name+""; - start += found.index + found[1].length+4; - } - return text; + var text = ""; + var start = 0; + while (true) { + var found = regex.exec (src.substring(start)); + var to = found == null ? src.length : start + found.index; + text += src.substring(start, to); + if (found == null) + break; + var name = ""+(new java.lang.String (found[1])).trim(); + var item = res.handlers.site.topics.get (name); + if (item == null && name.lastIndexOf("s") == name.length-1) + item = res.handlers.site.topics.get (name.substring(0, name.length-1)); + if (item == null || !item.size()) + text += format(name)+" [define "+format(name)+"]"; + else + text += ""+name+""; + start += found.index + found[1].length+4; + } + return text; } // FIXME: Rewrite with jala.ListRenderer? @@ -1242,27 +1242,27 @@ function doWikiStuff (src) { * @returns {String} The rendered list. */ function renderList(collection, funcOrSkin, itemsPerPage, pageIdx) { - var currIdx = 0, item; - var isArray = collection instanceof Array; - var stop = size = isArray ? collection.length : collection.size(); + var currIdx = 0, item; + var isArray = collection instanceof Array; + var stop = size = isArray ? collection.length : collection.size(); - if (itemsPerPage) { - var totalPages = Math.ceil(size/itemsPerPage); - if (isNaN(pageIdx) || pageIdx > totalPages || pageIdx < 0) { - pageIdx = 0; - } - currIdx = pageIdx * itemsPerPage; - stop = Math.min(currIdx + itemsPerPage, size); - } + if (itemsPerPage) { + var totalPages = Math.ceil(size/itemsPerPage); + if (isNaN(pageIdx) || pageIdx > totalPages || pageIdx < 0) { + pageIdx = 0; + } + currIdx = pageIdx * itemsPerPage; + stop = Math.min(currIdx + itemsPerPage, size); + } - var isFunction = (funcOrSkin instanceof Function) ? true : false; - res.push(); - while (currIdx < stop) { - item = isArray ? collection[currIdx] : collection.get(currIdx); - isFunction ? funcOrSkin(item) : item.renderSkin(funcOrSkin); - currIdx += 1; - } - return res.pop(); + var isFunction = (funcOrSkin instanceof Function) ? true : false; + res.push(); + while (currIdx < stop) { + item = isArray ? collection[currIdx] : collection.get(currIdx); + isFunction ? funcOrSkin(item) : item.renderSkin(funcOrSkin); + currIdx += 1; + } + return res.pop(); } // FIXME: Rewrite using jala.ListRenderer or rename (eg. renderIndex) @@ -1275,70 +1275,70 @@ function renderList(collection, funcOrSkin, itemsPerPage, pageIdx) { * @returns {String} The rendered page navigation. */ function renderPager(collectionOrSize, url, itemsPerPage, pageIdx) { - // Render a single item for the navigation bar - var renderItem = function(text, cssClass, url, page) { - var param = {"class": cssClass}; - if (!url) { - param.text = text; - } else { - if (url.contains("?")) - param.text = html.linkAsString({href: url + "&page=" + page}, text); - else - param.text = html.linkAsString({href: url + "?page=" + page}, text); - } - renderSkin("$Global#pagerItem", param); - return; - } + // Render a single item for the navigation bar + var renderItem = function(text, cssClass, url, page) { + var param = {"class": cssClass}; + if (!url) { + param.text = text; + } else { + if (url.contains("?")) + param.text = html.linkAsString({href: url + "&page=" + page}, text); + else + param.text = html.linkAsString({href: url + "?page=" + page}, text); + } + renderSkin("$Global#pagerItem", param); + return; + } - var maxItems = 10; - var size = 0; - if (collectionOrSize instanceof Array) { - size = collectionOrSize.length; - } else if (collectionOrSize instanceof HopObject) { - size = collectionOrSize.size(); - } else if (!isNaN(collectionOrSize)) { - size = parseInt(collectionOrSize, 10); - } - var lastPageIdx = Math.ceil(size/itemsPerPage)-1; - // If there's just one page no navigation will be rendered - if (lastPageIdx <= 0) { - return null; - } + var maxItems = 10; + var size = 0; + if (collectionOrSize instanceof Array) { + size = collectionOrSize.length; + } else if (collectionOrSize instanceof HopObject) { + size = collectionOrSize.size(); + } else if (!isNaN(collectionOrSize)) { + size = parseInt(collectionOrSize, 10); + } + var lastPageIdx = Math.ceil(size/itemsPerPage)-1; + // If there's just one page no navigation will be rendered + if (lastPageIdx <= 0) { + return null; + } - // Initialize the parameter object - var param = {}; - var pageIdx = parseInt(pageIdx, 10); - // Check if the passed index is correct - if (isNaN(pageIdx) || pageIdx > lastPageIdx || pageIdx < 0) { - pageIdx = 0; - } - param.display = ((pageIdx * itemsPerPage) + 1) + "-" + - (Math.min((pageIdx * itemsPerPage) + itemsPerPage, size)); - param.total = size; + // Initialize the parameter object + var param = {}; + var pageIdx = parseInt(pageIdx, 10); + // Check if the passed index is correct + if (isNaN(pageIdx) || pageIdx > lastPageIdx || pageIdx < 0) { + pageIdx = 0; + } + param.display = ((pageIdx * itemsPerPage) + 1) + "-" + + (Math.min((pageIdx * itemsPerPage) + itemsPerPage, size)); + param.total = size; - // Render the navigation-bar - res.push(); - (pageIdx > 0) && renderItem("[–]", "pageNavItem", url, pageIdx-1); - var offset = Math.floor(pageIdx / maxItems) * maxItems; - (offset > 0) && renderItem("[..]", "pageNavItem", url, offset-1); - var currPage = offset; - var stop = Math.min(currPage + maxItems, lastPageIdx+1); - while (currPage < stop) { - if (currPage === pageIdx) { - renderItem("[" + (currPage +1) + "]", "pageNavSelItem"); - } else { - renderItem("[" + (currPage +1) + "]", "pageNavItem", url, currPage); - } - currPage += 1; - } - if (currPage < lastPageIdx) { - renderItem("[..]", "pageNavItem", url, offset + maxItems); - } - if (pageIdx < lastPageIdx) { - renderItem("[+]", "pageNavItem", url, pageIdx +1); - } - param.pager = res.pop(); - return renderSkinAsString("$Global#pager", param); + // Render the navigation-bar + res.push(); + (pageIdx > 0) && renderItem("[–]", "pageNavItem", url, pageIdx-1); + var offset = Math.floor(pageIdx / maxItems) * maxItems; + (offset > 0) && renderItem("[..]", "pageNavItem", url, offset-1); + var currPage = offset; + var stop = Math.min(currPage + maxItems, lastPageIdx+1); + while (currPage < stop) { + if (currPage === pageIdx) { + renderItem("[" + (currPage +1) + "]", "pageNavSelItem"); + } else { + renderItem("[" + (currPage +1) + "]", "pageNavItem", url, currPage); + } + currPage += 1; + } + if (currPage < lastPageIdx) { + renderItem("[..]", "pageNavItem", url, offset + maxItems); + } + if (pageIdx < lastPageIdx) { + renderItem("[+]", "pageNavItem", url, pageIdx +1); + } + param.pager = res.pop(); + return renderSkinAsString("$Global#pager", param); } /** @@ -1347,10 +1347,10 @@ function renderPager(collectionOrSize, url, itemsPerPage, pageIdx) { * @returns {String} The english singular form of the original input. */ function singularize(plural) { - if (plural.endsWith("ies")) { - return plural.substring(0, plural.length-3) + "y"; - } - return plural.substring(0, plural.length-1); + if (plural.endsWith("ies")) { + return plural.substring(0, plural.length-3) + "y"; + } + return plural.substring(0, plural.length-1); } /** @@ -1359,10 +1359,10 @@ function singularize(plural) { * @returns {String} The english plural form of the original input. */ function pluralize(singular) { - if (singular.endsWith("y")) { - return singular.substring(0, singular.length-1) + "ies"; - } - return singular + "s"; + if (singular.endsWith("y")) { + return singular.substring(0, singular.length-1) + "ies"; + } + return singular + "s"; } /** @@ -1371,10 +1371,10 @@ function pluralize(singular) { * @param {Number} millis The amount of milliseconds. */ var wait = function(millis) { - millis || (millis = Date.ONESECOND); - var now = new Date; - while (new Date - now < millis) { - void null; - } - return; + millis || (millis = Date.ONESECOND); + var now = new Date; + while (new Date - now < millis) { + void null; + } + return; } diff --git a/code/Global/Importer.js b/code/Global/Importer.js index 1b7c992b..c22daf24 100644 --- a/code/Global/Importer.js +++ b/code/Global/Importer.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -39,36 +39,36 @@ var Importer = {} * @param {User} user The user who will become the creator of the site’s imported content. */ Importer.run = function(site, user) { - try { - var xml = File.getById(site.import_id); - if (xml) { - var file = new java.io.File(xml.getFile()); - var reader = new rome.XmlReader(file); - var input = new rome.SyndFeedInput(true); - var feed = input.build(reader); - Api.constrain(site, user); - for (var i=0; i 1) { - var values = Array.prototype.splice.call(args, 1); - if (typeof values[0] === "object") { - values = values[0]; - } - sql = sql.replace(/\$(\w*)/g, function() { - return value(values[arguments[1]]); - }); - } - return sql; - } - - /** - * Executes an SQL command. - * @param {String} sql The SQL command. - * @returns {Object} The result of the SQL command. - */ - this.execute = function(sql) { - sql = resolve(arguments); - log.info(sql); - if (options.test) { - return app.log(sql); - } - var error; - var result = db.executeCommand(sql); - if (error = db.getLastError()) { - app.log(error); - } - return result; - } - - /** - * Retrieves an SQL query. - * @example sql.retrieve('select $1 from $2 order by $1', 'date', 'foo') - * ===> 'select date from foo order by date' - * @returns {String} - */ - this.retrieve = function() { - return log.info(query = resolve(arguments)); - } - - /** - * Traverses over the results of an SQL query. - * @param {Function} callback The callback function executed for each record. - */ - this.traverse = function(callback) { - var rows = db.executeRetrieval(query); - if (rows && rows.next()) { - do { - var sql = new SqlData(rows); - sql.next(); - if (!options.test) { - callback.call(sql.values, rows); - } - } while (record = rows.next()); - rows.release(); + this.next = function() { + for each (var key in columns) { + this.values[key] = result.getColumnItem(key); } return; - } + } - /** - * @return {String} - */ - this.toString = function() { - return query; - } + return this; + } - return this; + var quote = function(str) { + if (!options.quote || str === null) { + return str; + } + return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'"); + } + + var value = function(obj) { + if (obj === null) { + return obj; + } + if (obj === undefined) { + obj = String(obj); + } + switch (obj.constructor) { + case Number: + return obj; + case String: + return quote(obj); + case Date: + return "from_unixtime(" + (obj.getTime() / 1000) + ")"; + case HopObject: + case Object: + return quote(obj.toSource()); + } + return quote(String(obj)); + } + + var resolve = function(args) { + var sql = args[0]; + if (args.length > 1) { + var values = Array.prototype.splice.call(args, 1); + if (typeof values[0] === "object") { + values = values[0]; + } + sql = sql.replace(/\$(\w*)/g, function() { + return value(values[arguments[1]]); + }); + } + return sql; + } + + /** + * Executes an SQL command. + * @param {String} sql The SQL command. + * @returns {Object} The result of the SQL command. + */ + this.execute = function(sql) { + sql = resolve(arguments); + log.info(sql); + if (options.test) { + return app.log(sql); + } + var error; + var result = db.executeCommand(sql); + if (error = db.getLastError()) { + app.log(error); + } + return result; + } + + /** + * Retrieves an SQL query. + * @example sql.retrieve('select $1 from $2 order by $1', 'date', 'foo') + * ===> 'select date from foo order by date' + * @returns {String} + */ + this.retrieve = function() { + return log.info(query = resolve(arguments)); + } + + /** + * Traverses over the results of an SQL query. + * @param {Function} callback The callback function executed for each record. + */ + this.traverse = function(callback) { + var rows = db.executeRetrieval(query); + if (rows && rows.next()) { + do { + var sql = new SqlData(rows); + sql.next(); + if (!options.test) { + callback.call(sql.values, rows); + } + } while (record = rows.next()); + rows.release(); + } + return; + } + + /** + * @return {String} + */ + this.toString = function() { + return query; + } + + return this; } /** @@ -169,47 +169,47 @@ Sql.COUNT = "select count(*) as count from $0"; * @constant */ Sql.REFERRERS = "select referrer, count(*) as requests from " + - "log where context_type = '$0' and context_id = $1 and action = " + - "'main' and created > now() - interval '2 days' group " + - "by referrer order by requests desc, referrer asc"; + "log where context_type = '$0' and context_id = $1 and action = " + + "'main' and created > now() - interval '2 days' group " + + "by referrer order by requests desc, referrer asc"; /** * SQL command for deleting all log entries older than 2 days. * @constant */ Sql.PURGEREFERRERS = "delete from log where action = 'main' and " + - "created < now() - interval '2 days'"; + "created < now() - interval '2 days'"; /** * SQL query for searching stories and comments. * @constant */ Sql.SEARCH = "select content.id from content, site, metadata where site.id = $0 and " + - "site.id = content.site_id and content.status in ('public', 'shared', 'open') and " + - "content.id = metadata.parent_id and metadata.name in ('title', 'text') and " + - "lower(metadata.value) like lower('%$1%') group by content.id, content.created " + - "order by content.created desc limit $2"; + "site.id = content.site_id and content.status in ('public', 'shared', 'open') and " + + "content.id = metadata.parent_id and metadata.name in ('title', 'text') and " + + "lower(metadata.value) like lower('%$1%') group by content.id, content.created " + + "order by content.created desc limit $2"; /** * SQL query for searching members. * @constant */ Sql.MEMBERSEARCH = "select name from account where name $0 '$1' " + - "order by name asc limit $2"; + "order by name asc limit $2"; /** * SQL query for retrieving all story IDs in a site’s archive. * @constant */ Sql.ARCHIVE = "select id from content where site_id = $0 and prototype = 'Story' and " + - "status in ('public', 'shared', 'open') $1 $2 limit $3 offset $4"; + "status in ('public', 'shared', 'open') $1 $2 limit $3 offset $4"; /** * SQL command for retrieving the size of a site’s archive. * @constant */ Sql.ARCHIVESIZE = "select count(*) as count from content where site_id = $0 " + - "and prototype = 'Story' and status in ('public', 'shared', 'open') $1"; + "and prototype = 'Story' and status in ('public', 'shared', 'open') $1"; /** * SQL part filtering the archive query. diff --git a/code/Global/aspects.js b/code/Global/aspects.js index 41246e40..ca5e9c4b 100644 --- a/code/Global/aspects.js +++ b/code/Global/aspects.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -27,62 +27,62 @@ app.addRepository("modules/helma/Aspects.js"); (function() { - function skinMayDisplayEditLink(name) { - return req.cookies[User.COOKIE + 'LayoutSandbox'] && - res.handlers.layout.getPermission('main') && - typeof name === 'string' && - !name.startsWith('$') && - res.contentType === 'text/html'; - } + function skinMayDisplayEditLink(name) { + return req.cookies[User.COOKIE + 'LayoutSandbox'] && + res.handlers.layout.getPermission('main') && + typeof name === 'string' && + !name.startsWith('$') && + res.contentType === 'text/html'; + } - function renderSkin(args, func, object) { - res.meta.skins || (res.meta.skins = {}); + function renderSkin(args, func, object) { + res.meta.skins || (res.meta.skins = {}); - var name = args[0]; - if (name.startsWith('#')) { - // Fix names using short form (ie. missing prototype) - name = object.constructor.name + name; + var name = args[0]; + if (name.startsWith('#')) { + // Fix names using short form (ie. missing prototype) + name = object.constructor.name + name; + } + var id = name.replace('#', '-').toLowerCase(); + + if (skinMayDisplayEditLink(name) && !res.meta.skins[name]) { + res.meta.skins[name] = true; + var parts = name.split('#'); + var prototype = parts[0]; + var skinName = parts[1]; + var skin = new Skin(prototype, skinName); + res.writeln(''); + res.writeln('
'); + func.apply(object, args); + res.writeln('
\n'); + } else { + func.apply(object, args); + } + + return; + } + + function renderSkinAsString(args, func, object) { + var name = args[0]; + if (skinMayDisplayEditLink(name)) { + res.push(); + object.renderSkin.apply(object, args); + return res.pop(); + } + return func.apply(object, args); + } + + var prototypes = app.__app__.getPrototypes().toArray(); + for each (var prototype in prototypes) { + if (prototype.name in global) { + global[prototype.name].prototype.onCodeUpdate = function() { + this.__renderSkin__ = this.renderSkin; + this.__renderSkinAsString__ = this.renderSkinAsString; + helma.aspects.addAround(this, 'renderSkin', renderSkin); + helma.aspects.addAround(this, 'renderSkinAsString', renderSkinAsString); } - var id = name.replace('#', '-').toLowerCase(); - - if (skinMayDisplayEditLink(name) && !res.meta.skins[name]) { - res.meta.skins[name] = true; - var parts = name.split('#'); - var prototype = parts[0]; - var skinName = parts[1]; - var skin = new Skin(prototype, skinName); - res.writeln(''); - res.writeln('
'); - func.apply(object, args); - res.writeln('
\n'); - } else { - func.apply(object, args); - } - - return; - } - - function renderSkinAsString(args, func, object) { - var name = args[0]; - if (skinMayDisplayEditLink(name)) { - res.push(); - object.renderSkin.apply(object, args); - return res.pop(); - } - return func.apply(object, args); - } - - var prototypes = app.__app__.getPrototypes().toArray(); - for each (var prototype in prototypes) { - if (prototype.name in global) { - global[prototype.name].prototype.onCodeUpdate = function() { - this.__renderSkin__ = this.renderSkin; - this.__renderSkinAsString__ = this.renderSkinAsString; - helma.aspects.addAround(this, 'renderSkin', renderSkin); - helma.aspects.addAround(this, 'renderSkinAsString', renderSkinAsString); - } - } - } + } + } }()); diff --git a/code/Global/i18n.js b/code/Global/i18n.js index e552a709..bda3fbd2 100644 --- a/code/Global/i18n.js +++ b/code/Global/i18n.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -35,29 +35,29 @@ * @param {String} potFile The filename for the output POT file. */ Root.prototype.extractMessages = function(script, scanDirs, potFile) { - var temp = {print: global.print, readFile: global.readFile}; - global.print = function(str) {app.log(str);} - global.readFile = function(fpath, encoding) { - res.push(); - var file = new helma.File(fpath); - file.open({charset: encoding || "UTF-8"}); - var str; - while ((str = file.readln()) !== null) { - res.writeln(str); - } - file.close(); - return res.pop(); - } - var args = ["-o", potFile, "-e", "utf-8"]; - for each (var dir in scanDirs.split(" ")) { - args.push(app.dir + "/../" + dir); - } - var file = new helma.File(script); - var MessageParser = new Function(file.readAll()); - MessageParser.apply(global, args); - global.print = temp.print; - global.readFile = temp.readFile; - return; + var temp = {print: global.print, readFile: global.readFile}; + global.print = function(str) {app.log(str);} + global.readFile = function(fpath, encoding) { + res.push(); + var file = new helma.File(fpath); + file.open({charset: encoding || "UTF-8"}); + var str; + while ((str = file.readln()) !== null) { + res.writeln(str); + } + file.close(); + return res.pop(); + } + var args = ["-o", potFile, "-e", "utf-8"]; + for each (var dir in scanDirs.split(" ")) { + args.push(app.dir + "/../" + dir); + } + var file = new helma.File(script); + var MessageParser = new Function(file.readAll()); + MessageParser.apply(global, args); + global.print = temp.print; + global.readFile = temp.readFile; + return; } /** @@ -68,9 +68,9 @@ Root.prototype.extractMessages = function(script, scanDirs, potFile) { * @returns {String} */ function cgettext(key, context) { - var msgId = cgettext.getKey(key, context); - var text = jala.i18n.translate(msgId); - return text === msgId ? key : text; + var msgId = cgettext.getKey(key, context); + var text = jala.i18n.translate(msgId); + return text === msgId ? key : text; } /** @@ -81,7 +81,7 @@ function cgettext(key, context) { * @example cgettext.getKey('comment', 'verb') ===> 'comment // verb' */ cgettext.getKey = function(key, context) { - return context ? key + " // " + context : key; + return context ? key + " // " + context : key; } /** @@ -92,18 +92,18 @@ cgettext.getKey = function(key, context) { * @see jala.i18n.gettext */ function gettext_macro(param, text /*, value1, value2, ...*/) { - if (!text) { - return; - } - var re = gettext_macro.REGEX; - var args = [text.toString().replace(re, String.SPACE)]; - for (var i=2; i 0) { - item = this.get(0); - if (item.constructor.remove) { - item.constructor.remove.call(item, options); - } else if (!options) { - item.remove(); - } else { - throw Error("Missing static " + item.constructor.name + - ".remove() method"); - } - } - return; + var item; + while (this.size() > 0) { + item = this.get(0); + if (item.constructor.remove) { + item.constructor.remove.call(item, options); + } else if (!options) { + item.remove(); + } else { + throw Error("Missing static " + item.constructor.name + + ".remove() method"); + } + } + return; } /** @@ -58,20 +58,20 @@ HopObject.remove = function(options) { * @param {HopObject} collection */ HopObject.getFromPath = function(name, collection) { - if (name) { - var site; - if (name.contains("/")) { - var parts = name.split("/"); - site = root.get(parts[0]); - name = parts[1]; - } else { - site = res.handlers.site; - } - if (site && site.getPermission("main")) { - return site[collection].get(name); - } - } - return null; + if (name) { + var site; + if (name.contains("/")) { + var parts = name.split("/"); + site = root.get(parts[0]); + name = parts[1]; + } else { + site = res.handlers.site; + } + if (site && site.getPermission("main")) { + return site[collection].get(name); + } + } + return null; } /** @@ -79,21 +79,21 @@ HopObject.getFromPath = function(name, collection) { * should be replaced with static add() method. */ HopObject.confirmConstructor = function(ref) { - var KEY = '__confirmedConstructors__'; - if (!res.meta[KEY]) { - res.meta[KEY] = {}; - } - var confirmed = res.meta[KEY]; - if (typeof ref === 'function') { - confirmed[ref.name] = true; - } else { - ref = (ref || this).constructor.name; - if (!confirmed[ref]) { - app.logger.warn('Calling unconfirmed constructor for ' + - ref + ' prototype – please check!'); - } - } - return; + var KEY = '__confirmedConstructors__'; + if (!res.meta[KEY]) { + res.meta[KEY] = {}; + } + var confirmed = res.meta[KEY]; + if (typeof ref === 'function') { + confirmed[ref.name] = true; + } else { + ref = (ref || this).constructor.name; + if (!confirmed[ref]) { + app.logger.warn('Calling unconfirmed constructor for ' + + ref + ' prototype – please check!'); + } + } + return; } /** @@ -106,63 +106,63 @@ HopObject.confirmConstructor = function(ref) { * */ HopObject.prototype.onRequest = function() { - // Checking if we are on the correct host to prevent at least some XSS issues - if (req.action !== "notfound" && req.action !== "error" && - this.href().contains("://") && - !this.href().toLowerCase().startsWith(req.servletRequest.scheme + - "://" + req.servletRequest.serverName.toLowerCase())) { - res.redirect(this.href(req.action === "main" ? String.EMPTY : req.action)); - } + // Checking if we are on the correct host to prevent at least some XSS issues + if (req.action !== "notfound" && req.action !== "error" && + this.href().contains("://") && + !this.href().toLowerCase().startsWith(req.servletRequest.scheme + + "://" + req.servletRequest.serverName.toLowerCase())) { + res.redirect(this.href(req.action === "main" ? String.EMPTY : req.action)); + } - User.autoLogin(); - res.handlers.membership = User.getMembership(); + User.autoLogin(); + res.handlers.membership = User.getMembership(); - if (User.getCurrentStatus() === User.BLOCKED) { - session.data.status = 403; - session.data.error = gettext("Your account has been blocked.") + String.SPACE + - gettext("Please contact an administrator for further information."); - User.logout(); - res.redirect(root.href("error")); - } + if (User.getCurrentStatus() === User.BLOCKED) { + session.data.status = 403; + session.data.error = gettext("Your account has been blocked.") + String.SPACE + + gettext("Please contact an administrator for further information."); + User.logout(); + res.redirect(root.href("error")); + } - if (res.handlers.site.status === Site.BLOCKED && - !User.require(User.PRIVILEGED)) { - session.data.status = 403; - session.data.error = gettext("The site you requested has been blocked.") + - String.SPACE + gettext("Please contact an administrator for further information."); - res.redirect(root.href("error")); - } + if (res.handlers.site.status === Site.BLOCKED && + !User.require(User.PRIVILEGED)) { + session.data.status = 403; + session.data.error = gettext("The site you requested has been blocked.") + + String.SPACE + gettext("Please contact an administrator for further information."); + res.redirect(root.href("error")); + } - HopObject.confirmConstructor(Layout); - res.handlers.layout = res.handlers.site.layout || new Layout; - res.skinpath = res.handlers.layout.getSkinPath(); + HopObject.confirmConstructor(Layout); + res.handlers.layout = res.handlers.site.layout || new Layout; + res.skinpath = res.handlers.layout.getSkinPath(); - if (!this.getPermission(req.action)) { - if (!session.user) { - User.setLocation(root.href() + req.path); - res.message = gettext("Please login first."); - res.redirect(res.handlers.site.members.href("login")); - } - User.getLocation(); - res.status = 401; - res.data.title = gettext("{0} 401 Error", root.title); - res.data.body = root.renderSkinAsString("$Root#error", {error: - gettext("You are not allowed to access this part of the site.")}); - res.handlers.site.renderSkin("Site#page"); - session.data.error = null; - res.stop(); - } + if (!this.getPermission(req.action)) { + if (!session.user) { + User.setLocation(root.href() + req.path); + res.message = gettext("Please login first."); + res.redirect(res.handlers.site.members.href("login")); + } + User.getLocation(); + res.status = 401; + res.data.title = gettext("{0} 401 Error", root.title); + res.data.body = root.renderSkinAsString("$Root#error", {error: + gettext("You are not allowed to access this part of the site.")}); + res.handlers.site.renderSkin("Site#page"); + session.data.error = null; + res.stop(); + } - res.meta.values = {}; - res.handlers.site.renderSkinAsString("Site#values"); - return; + res.meta.values = {}; + res.handlers.site.renderSkinAsString("Site#values"); + return; } /** * @returns Boolean */ HopObject.prototype.getPermission = function() { - return true; + return true; } // Marking some prototype names used in res.message of HopObject.delete_action() @@ -174,45 +174,45 @@ markgettext("Poll"); markgettext("Story"); HopObject.prototype.delete_action = function() { - if (req.postParams.proceed) { - try { - var parent = this._parent; - var url = this.constructor.remove.call(this, req.postParams) || - parent.href(); - res.message = gettext("{0} was successfully deleted.", gettext(this._prototype)); - res.redirect(User.getLocation() || url); - } catch(ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.proceed) { + try { + var parent = this._parent; + var url = this.constructor.remove.call(this, req.postParams) || + parent.href(); + res.message = gettext("{0} was successfully deleted.", gettext(this._prototype)); + res.redirect(User.getLocation() || url); + } catch(ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Confirm Deletion"); - res.data.body = this.renderSkinAsString("$HopObject#confirm", { - text: this.getConfirmText() - }); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Confirm Deletion"); + res.data.body = this.renderSkinAsString("$HopObject#confirm", { + text: this.getConfirmText() + }); + res.handlers.site.renderSkin("Site#page"); + return; } /** * @returns {Object} */ HopObject.prototype.touch = function() { - return this.map({ - modified: new Date, - modifier: session.user - }); + return this.map({ + modified: new Date, + modifier: session.user + }); } /** * */ HopObject.prototype.log = function() { - var entry = new LogEntry(this, "main"); - app.data.entries.push(entry); - return; + var entry = new LogEntry(this, "main"); + app.data.entries.push(entry); + return; } /** @@ -220,79 +220,79 @@ HopObject.prototype.log = function() { * @param {String} action */ HopObject.prototype.notify = function(action) { - var self = this; - var site = res.handlers.site; + var self = this; + var site = res.handlers.site; - var getPermission = function(scope, mode, status) { - if (scope === Admin.NONE || mode === Site.NOBODY || - status === Site.BLOCKED) { - return false; - } - var scopes = [Admin.REGULAR, Admin.TRUSTED]; - if (scopes.indexOf(status) < scopes.indexOf(scope)) { - return false; - } - if (!Membership.require(mode)) { - return false; - } - return true; - } + var getPermission = function(scope, mode, status) { + if (scope === Admin.NONE || mode === Site.NOBODY || + status === Site.BLOCKED) { + return false; + } + var scopes = [Admin.REGULAR, Admin.TRUSTED]; + if (scopes.indexOf(status) < scopes.indexOf(scope)) { + return false; + } + if (!Membership.require(mode)) { + return false; + } + return true; + } - // Helper method for debugging - var renderMatrix = function() { - var buf = ['']; - for each (var scope in Admin.getNotificationScopes()) { - for each (var mode in Site.getNotificationModes()) { - for each (var status in Site.getStatus()) { - var perm = getPermission(scope.value, mode.value, status.value); - buf.push(''); - buf.push(''); - buf.push(''); - buf.push(''); - buf.push(''); - buf.push(''); - } - } + // Helper method for debugging + var renderMatrix = function() { + var buf = ['
', scope.value, '', status.value, '', mode.value, '', perm, '
']; + for each (var scope in Admin.getNotificationScopes()) { + for each (var mode in Site.getNotificationModes()) { + for each (var status in Site.getStatus()) { + var perm = getPermission(scope.value, mode.value, status.value); + buf.push(''); + buf.push(''); + buf.push(''); + buf.push(''); + buf.push(''); + buf.push(''); + } } - buf.push('
', scope.value, '', status.value, '', mode.value, '', perm, '
'); - res.write(buf.join("")); - return; - } + } + buf.push(''); + res.write(buf.join("")); + return; + } - switch (action) { - case "comment": - action = "create"; break; - } + switch (action) { + case "comment": + action = "create"; break; + } - var currentMembership = res.handlers.membership; - site.members.forEach(function() { - var membership = res.handlers.membership = this; - if (getPermission(root.notificationScope, site.notificationMode, site.status)) { - sendMail(membership.creator.email, gettext("[{0}] Notification of site changes", - root.title), self.renderSkinAsString("$HopObject#notify_" + action)); - } - }); - res.handlers.membership = currentMembership; - return; + var currentMembership = res.handlers.membership; + site.members.forEach(function() { + var membership = res.handlers.membership = this; + if (getPermission(root.notificationScope, site.notificationMode, site.status)) { + sendMail(membership.creator.email, gettext("[{0}] Notification of site changes", + root.title), self.renderSkinAsString("$HopObject#notify_" + action)); + } + }); + res.handlers.membership = currentMembership; + return; } /** * @returns {Tag[]} */ HopObject.prototype.getTags = function() { - var tags = []; - if (typeof this.tags === "object") { - this.tags.list().forEach(function(item) { - item.tag && tags.push(item.tag.name); - }); - } - return tags; + var tags = []; + if (typeof this.tags === "object") { + this.tags.list().forEach(function(item) { + item.tag && tags.push(item.tag.name); + }); + } + return tags; } /** @@ -300,48 +300,48 @@ HopObject.prototype.getTags = function() { * @param {Tag[]|String} tags */ HopObject.prototype.setTags = function(tags) { - if (typeof this.tags !== "object") { - return String.EMPTY; - } + if (typeof this.tags !== "object") { + return String.EMPTY; + } - if (!tags) { - tags = []; - } else if (tags.constructor === String) { - tags = tags.split(/\s*,\s*/); - } + if (!tags) { + tags = []; + } else if (tags.constructor === String) { + tags = tags.split(/\s*,\s*/); + } - var diff = {}; - var tag; - for (var i in tags) { - // Trim and remove troublesome characters (like ../.. etc.) - // We call getAccessName with a virgin HopObject to allow most names - tag = tags[i] = this.getAccessName.call(new HopObject, File.getName(tags[i])); - if (tag && diff[tag] == null) { - diff[tag] = 1; - } - } - this.tags.forEach(function() { - if (!this.tag) { - return; - } - diff[this.tag.name] = (tags.indexOf(this.tag.name) < 0) ? this : 0; - }); + var diff = {}; + var tag; + for (var i in tags) { + // Trim and remove troublesome characters (like ../.. etc.) + // We call getAccessName with a virgin HopObject to allow most names + tag = tags[i] = this.getAccessName.call(new HopObject, File.getName(tags[i])); + if (tag && diff[tag] == null) { + diff[tag] = 1; + } + } + this.tags.forEach(function() { + if (!this.tag) { + return; + } + diff[this.tag.name] = (tags.indexOf(this.tag.name) < 0) ? this : 0; + }); - for (var tag in diff) { - switch (diff[tag]) { - case 0: - // Do nothing (tag already exists) - break; - case 1: - // Add tag to story - this.addTag(tag); - break; - default: - // Remove tag - this.removeTag(diff[tag]); - } - } - return; + for (var tag in diff) { + switch (diff[tag]) { + case 0: + // Do nothing (tag already exists) + break; + case 1: + // Add tag to story + this.addTag(tag); + break; + default: + // Remove tag + this.removeTag(diff[tag]); + } + } + return; } /** @@ -349,8 +349,8 @@ HopObject.prototype.setTags = function(tags) { * @param {String} name */ HopObject.prototype.addTag = function(name) { - TagHub.add(name, this, session.user); - return; + TagHub.add(name, this, session.user); + return; } /** @@ -358,12 +358,12 @@ HopObject.prototype.addTag = function(name) { * @param {String} tag */ HopObject.prototype.removeTag = function(tag) { - var parent = tag._parent; - if (parent.size() === 1) { - parent.remove(); - } - tag.remove(); - return; + var parent = tag._parent; + if (parent.size() === 1) { + parent.remove(); + } + tag.remove(); + return; } /** @@ -371,10 +371,10 @@ HopObject.prototype.removeTag = function(tag) { * @param {Object} values */ HopObject.prototype.map = function(values) { - for (var i in values) { - this[i] = values[i]; - } - return; + for (var i in values) { + this[i] = values[i]; + } + return; } /** @@ -383,16 +383,16 @@ HopObject.prototype.map = function(values) { * @param {String} name */ HopObject.prototype.skin_macro = function(param, name) { - if (!name) { - return; - } - if (name.contains("#")) { - this.renderSkin(name); - } else { - var prototype = this._prototype || "Global"; - this.renderSkin(prototype + "#" + name); - } - return; + if (!name) { + return; + } + if (name.contains("#")) { + this.renderSkin(name); + } else { + var prototype = this._prototype || "Global"; + this.renderSkin(prototype + "#" + name); + } + return; } /** @@ -401,10 +401,10 @@ HopObject.prototype.skin_macro = function(param, name) { * @param {String} name */ HopObject.prototype.input_macro = function(param, name) { - param.name = name; - param.id = name; - param.value = this.getFormValue(name); - return html.input(param); + param.name = name; + param.id = name; + param.value = this.getFormValue(name); + return html.input(param); } /** @@ -413,10 +413,10 @@ HopObject.prototype.input_macro = function(param, name) { * @param {String} name */ HopObject.prototype.textarea_macro = function(param, name) { - param.name = name; - param.id = name; - param.value = this.getFormValue(name); - return html.textArea(param); + param.name = name; + param.id = name; + param.value = this.getFormValue(name); + return html.textArea(param); } /** @@ -425,13 +425,13 @@ HopObject.prototype.textarea_macro = function(param, name) { * @param {String} name */ HopObject.prototype.select_macro = function(param, name) { - param.name = name; - param.id = name; - var options = this.getFormOptions(name); - if (options.length < 2) { - param.disabled = "disabled"; - } - return html.dropDown(param, options, this.getFormValue(name)); + param.name = name; + param.id = name; + var options = this.getFormOptions(name); + if (options.length < 2) { + param.disabled = "disabled"; + } + return html.dropDown(param, options, this.getFormValue(name)); } /** @@ -440,21 +440,21 @@ HopObject.prototype.select_macro = function(param, name) { * @param {String} name */ HopObject.prototype.checkbox_macro = function(param, name) { - param.name = name; - param.id = name; - var options = this.getFormOptions(name); - if (options.length < 2) { - param.disabled = "disabled"; - } - param.value = String((options[1] || options[0]).value); - param.selectedValue = String(this.getFormValue(name)); - var label = param.label; - delete param.label; - html.checkBox(param); - if (label) { - html.element("label", label, {"for": name}); - } - return; + param.name = name; + param.id = name; + var options = this.getFormOptions(name); + if (options.length < 2) { + param.disabled = "disabled"; + } + param.value = String((options[1] || options[0]).value); + param.selectedValue = String(this.getFormValue(name)); + var label = param.label; + delete param.label; + html.checkBox(param); + if (label) { + html.element("label", label, {"for": name}); + } + return; } /** @@ -463,21 +463,21 @@ HopObject.prototype.checkbox_macro = function(param, name) { * @param {String} name */ HopObject.prototype.radiobutton_macro = function(param, name) { - param.name = name; - param.id = name; - var options = this.getFormOptions(name); - if (options.length < 2) { - param.disabled = "disabled"; - } - param.value = String(options[0].value); - param.selectedValue = String(this.getFormValue(name)); - var label = param.label; - delete param.label; - html.radioButton(param); - if (label) { - html.element("label", label, {"for": name}); - } - return; + param.name = name; + param.id = name; + var options = this.getFormOptions(name); + if (options.length < 2) { + param.disabled = "disabled"; + } + param.value = String(options[0].value); + param.selectedValue = String(this.getFormValue(name)); + var label = param.label; + delete param.label; + html.radioButton(param); + if (label) { + html.element("label", label, {"for": name}); + } + return; } /** @@ -486,11 +486,11 @@ HopObject.prototype.radiobutton_macro = function(param, name) { * @param {String} name */ HopObject.prototype.upload_macro = function(param, name) { - param.name = name; - param.id = name; - param.value = this.getFormValue(name); - renderSkin("$Global#upload", param); - return; + param.name = name; + param.id = name; + param.value = this.getFormValue(name); + renderSkin("$Global#upload", param); + return; } /** @@ -499,30 +499,30 @@ HopObject.prototype.upload_macro = function(param, name) { * @param {HopObject} [handler] */ HopObject.prototype.macro_macro = function(param, handler) { - var ctor = this.constructor; - if ([Story, Image, File, Poll].indexOf(ctor) > -1) { - res.write(''); - res.encode("<% "); - res.write(handler || ctor.name.toLowerCase()); - res.write(String.SPACE); - res.write(quote(this.name || this._id)); - res.encode(" %>"); - res.write(''); - } - return; + var ctor = this.constructor; + if ([Story, Image, File, Poll].indexOf(ctor) > -1) { + res.write(''); + res.encode("<% "); + res.write(handler || ctor.name.toLowerCase()); + res.write(String.SPACE); + res.write(quote(this.name || this._id)); + res.encode(" %>"); + res.write(''); + } + return; } /** * */ HopObject.prototype.kind_macro = function() { - var type = this.constructor.name.toLowerCase(); - switch (type) { - default: - res.write(gettext(type)); - break; - } - return; + var type = this.constructor.name.toLowerCase(); + switch (type) { + default: + res.write(gettext(type)); + break; + } + return; } /** @@ -531,19 +531,19 @@ HopObject.prototype.kind_macro = function() { * @returns {Number|String} */ HopObject.prototype.getFormValue = function(name) { - if (req.isPost()) { - return req.postParams[name]; - } else { - var value = this[name] || req.queryParams[name] || String.EMPTY; - return value instanceof HopObject ? value._id : value; - } + if (req.isPost()) { + return req.postParams[name]; + } else { + var value = this[name] || req.queryParams[name] || String.EMPTY; + return value instanceof HopObject ? value._id : value; + } } /** * @returns {Object[]} */ HopObject.prototype.getFormOptions = function() { - return [{value: true, display: "enabled"}]; + return [{value: true, display: "enabled"}]; } /** @@ -552,14 +552,14 @@ HopObject.prototype.getFormOptions = function() { * @param {String} property */ HopObject.prototype.self_macro = function(param, property) { - return property ? this[property] : this; + return property ? this[property] : this; } /** * */ HopObject.prototype.type_macro = function() { - return res.write(this.constructor.name); + return res.write(this.constructor.name); } /** @@ -569,15 +569,15 @@ HopObject.prototype.type_macro = function() { * @param {String} text */ HopObject.prototype.link_macro = function(param, url, text) { - if (url && text) { - var action = url.split(/#|\?/)[0]; - if (this.getPermission(action)) { - renderLink.call(global, param, url, text, this); - } - } else { - res.write("[Insufficient link parameters]"); - } - return; + if (url && text) { + var action = url.split(/#|\?/)[0]; + if (this.getPermission(action)) { + renderLink.call(global, param, url, text, this); + } + } else { + res.write("[Insufficient link parameters]"); + } + return; } /** @@ -586,11 +586,11 @@ HopObject.prototype.link_macro = function(param, url, text) { * @param {String} format */ HopObject.prototype.created_macro = function(param, format) { - if (this.isPersistent()) { - format || (format = param.format); - res.write(formatDate(this.created, format)); - } - return; + if (this.isPersistent()) { + format || (format = param.format); + res.write(formatDate(this.created, format)); + } + return; } /** @@ -599,11 +599,11 @@ HopObject.prototype.created_macro = function(param, format) { * @param {String} format */ HopObject.prototype.modified_macro = function(param, format) { - if (this.isPersistent()) { - format || (format = param.format); - res.write(formatDate(this.modified, format)); - } - return; + if (this.isPersistent()) { + format || (format = param.format); + res.write(formatDate(this.modified, format)); + } + return; } /** @@ -612,17 +612,17 @@ HopObject.prototype.modified_macro = function(param, format) { * @param {String} mode */ HopObject.prototype.creator_macro = function(param, mode) { - if (!this.creator || this.isTransient()) { - return; - } - mode || (mode = param.as); - if (mode === "link" && this.creator.url) { - html.link({href: this.creator.url}, this.creator.name); - } else if (mode === "url") { - res.write(this.creator.url); - } else { - res.write(this.creator.name); - } return; + if (!this.creator || this.isTransient()) { + return; + } + mode || (mode = param.as); + if (mode === "link" && this.creator.url) { + html.link({href: this.creator.url}, this.creator.name); + } else if (mode === "url") { + res.write(this.creator.url); + } else { + res.write(this.creator.name); + } return; } /** @@ -631,32 +631,32 @@ HopObject.prototype.creator_macro = function(param, mode) { * @param {String} mode */ HopObject.prototype.modifier_macro = function(param, mode) { - if (!this.modifier || this.isTransient()) { - return; - } - mode || (mode = param.as); - if (mode === "link" && this.modifier.url) { - html.link({href: this.modifier.url}, this.modifier.name); - } else if (mode === "url") { - res.write(this.modifier.url); - } else { - res.write(this.modifier.name); - } - return; + if (!this.modifier || this.isTransient()) { + return; + } + mode || (mode = param.as); + if (mode === "link" && this.modifier.url) { + html.link({href: this.modifier.url}, this.modifier.name); + } else if (mode === "url") { + res.write(this.modifier.url); + } else { + res.write(this.modifier.name); + } + return; } /** * @returns {String} */ HopObject.prototype.getTitle = function() { - return this.title || gettext(this.__name__.capitalize()); + return this.title || gettext(this.__name__.capitalize()); } /** * @returns {String} */ HopObject.prototype.toString = function() { - return this.constructor.name + " #" + this._id; + return this.constructor.name + " #" + this._id; } /** @@ -667,8 +667,8 @@ HopObject.prototype.toString = function() { * @returns {String} */ HopObject.prototype.link_filter = function(text, param, action) { - action || (action = "."); - res.push(); - renderLink(param, action, text, this); - return res.pop(); + action || (action = "."); + res.push(); + renderLink(param, action, text, this); + return res.pop(); } diff --git a/code/HopObject/metadata.js b/code/HopObject/metadata.js index 4629ddab..e6e6fa74 100644 --- a/code/HopObject/metadata.js +++ b/code/HopObject/metadata.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -33,20 +33,20 @@ * @param {String} name */ HopObject.prototype.handleMetadata = function(name) { - this.__defineGetter__(name, function() { - return this.getMetadata(name); - }); - this.__defineSetter__(name, function(value) { - return this.setMetadata(name, value); - }); - this[name + "_macro"] = function(param) { - var value; - if (value = this[name]) { - res.write(value); - } - return; - }; - return; + this.__defineGetter__(name, function() { + return this.getMetadata(name); + }); + this.__defineSetter__(name, function(value) { + return this.setMetadata(name, value); + }); + this[name + "_macro"] = function(param) { + var value; + if (value = this[name]) { + res.write(value); + } + return; + }; + return; } /** @@ -55,31 +55,31 @@ HopObject.prototype.handleMetadata = function(name) { * @returns {Object} */ HopObject.prototype.getMetadata = function(name) { - if (!this.metadata) { - throw Error("No metadata collection defined for prototype " + this.constructor.name); - } else { - this.metadata.prefetchChildren(); - } + if (!this.metadata) { + throw Error("No metadata collection defined for prototype " + this.constructor.name); + } else { + this.metadata.prefetchChildren(); + } - var self = this; + var self = this; - if (!name) { - var result = {}; - this.metadata.forEach(function() { - var name = this.name; - if (name) { - result[name] = self.getMetadata(name); - } - }); - return result; - } + if (!name) { + var result = {}; + this.metadata.forEach(function() { + var name = this.name; + if (name) { + result[name] = self.getMetadata(name); + } + }); + return result; + } - var meta = this.metadata.get(name); - if (!meta) { - return null; - } + var meta = this.metadata.get(name); + if (!meta) { + return null; + } - return meta.getValue(); + return meta.getValue(); } /** @@ -88,33 +88,33 @@ HopObject.prototype.getMetadata = function(name) { * @param {Object} value */ HopObject.prototype.setMetadata = function(name, value) { - if (!this.metadata) { - throw Error("No metadata collection defined for prototype " + this.constructor.name); - } + if (!this.metadata) { + throw Error("No metadata collection defined for prototype " + this.constructor.name); + } - if (!name) { - throw Error("Insufficient arguments"); - } + if (!name) { + throw Error("Insufficient arguments"); + } - if (typeof name === "object") { - for (var i in name) { - this.setMetadata(i, name[i]); - } - return; - } + if (typeof name === "object") { + for (var i in name) { + this.setMetadata(i, name[i]); + } + return; + } - var metadata = this.metadata.get(name); + var metadata = this.metadata.get(name); - if (metadata) { - metadata.setValue(value); - } else { - metadata = new Metadata(this, name, value); - if (metadata.value !== null) { - // metadata.persist() is not enough or there will be redundant records! - this.metadata.add(metadata); - } - } - return; + if (metadata) { + metadata.setValue(value); + } else { + metadata = new Metadata(this, name, value); + if (metadata.value !== null) { + // metadata.persist() is not enough or there will be redundant records! + this.metadata.add(metadata); + } + } + return; } /** @@ -122,22 +122,22 @@ HopObject.prototype.setMetadata = function(name, value) { * @param {String} name */ HopObject.prototype.deleteMetadata = function(name) { - if (!this.metadata) { - throw Error("No metadata collection defined for prototype " + this.constructor.name); - } + if (!this.metadata) { + throw Error("No metadata collection defined for prototype " + this.constructor.name); + } - var self = this; + var self = this; - if (arguments.length === 0) { - return HopObject.remove.call(this.metadata); - } + if (arguments.length === 0) { + return HopObject.remove.call(this.metadata); + } - Array.prototype.forEach.call(arguments, function(name) { - var metadata = self.metadata.get(name); - metadata && metadata.remove(); - return; - }); - return; + Array.prototype.forEach.call(arguments, function(name) { + var metadata = self.metadata.get(name); + metadata && metadata.remove(); + return; + }); + return; } /** @@ -146,7 +146,7 @@ HopObject.prototype.deleteMetadata = function(name) { * @param {String} name */ HopObject.prototype.metadata_macro = function(param, name) { - var value = this.getMetadata(name); - value && res.write(value); - return; + var value = this.getMetadata(name); + value && res.write(value); + return; } diff --git a/code/Image/Image.js b/code/Image/Image.js index c29ee1d9..b19b719b 100644 --- a/code/Image/Image.js +++ b/code/Image/Image.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -46,8 +46,8 @@ Image.THUMBNAILWIDTH = 100; /** @constant */ Image.KEYS = ["name", "created", "modified", "origin", "description", - "contentType", "contentLength", "width", "height", "thumbnailName", - "thumbnailWidth", "thumbnailHeight", "fileName", "site"]; + "contentType", "contentLength", "width", "height", "thumbnailName", + "thumbnailWidth", "thumbnailHeight", "fileName", "site"]; /** * @param {Object} data @@ -56,34 +56,34 @@ Image.KEYS = ["name", "created", "modified", "origin", "description", * @returns {Image} */ Image.add = function(data, parent, user) { - HopObject.confirmConstructor(Image); - parent || (parent = res.handlers.site); - user || (user = session.user); - var image = new Image; - if (data) { - for each (var key in Image.KEYS) { - image[key] = data[key]; - } - } - image.parent = parent; - image.created = image.modified = new Date; - image.creator = image.modifier = user; - image.update(data); - parent.images.add(image); - return image; + HopObject.confirmConstructor(Image); + parent || (parent = res.handlers.site); + user || (user = session.user); + var image = new Image; + if (data) { + for each (var key in Image.KEYS) { + image[key] = data[key]; + } + } + image.parent = parent; + image.created = image.modified = new Date; + image.creator = image.modifier = user; + image.update(data); + parent.images.add(image); + return image; } /** * */ Image.remove = function() { - if (this.constructor === Image) { - this.removeFiles(); - this.setTags(null); - this.deleteMetadata(); - this.remove(); - } - return; + if (this.constructor === Image) { + this.removeFiles(); + this.setTags(null); + this.deleteMetadata(); + this.remove(); + } + return; } /** @@ -92,25 +92,25 @@ Image.remove = function() { * @returns {String} */ Image.getFileExtension = function(type) { - type = String(type); - // Sometimes type is like "image/jpeg;charset=ISO-8859-1" - var index = type.lastIndexOf(";"); - if (index > -1) { - type = type.substr(0, index); - } - switch (type) { - //case "image/x-icon": - //return ".ico"; - case "image/gif": - return ".gif"; - case "image/jpeg": - case "image/pjpeg": - return ".jpg"; - case "image/png": - case "image/x-png": - return ".png"; - } - return null; + type = String(type); + // Sometimes type is like "image/jpeg;charset=ISO-8859-1" + var index = type.lastIndexOf(";"); + if (index > -1) { + type = type.substr(0, index); + } + switch (type) { + //case "image/x-icon": + //return ".ico"; + case "image/gif": + return ".gif"; + case "image/jpeg": + case "image/pjpeg": + return ".jpg"; + case "image/png": + case "image/x-png": + return ".png"; + } + return null; } /** @@ -141,8 +141,8 @@ Image.getFileExtension = function(type) { * @extends HopObject */ Image.prototype.constructor = function(data) { - HopObject.confirmConstructor.call(this); - return this; + HopObject.confirmConstructor.call(this); + return this; } /** @@ -151,23 +151,23 @@ Image.prototype.constructor = function(data) { * @return {Boolean} */ Image.prototype.getPermission = function(action) { - var defaultGrant = this._parent.getPermission("main"); - switch (action) { - case ".": - case "main": - return true; - case "delete": - return defaultGrant && this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - case "edit": - return defaultGrant && this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED) && - this.parent_type !== "Layout" || - this.parent === path.layout; - } - return false; + var defaultGrant = this._parent.getPermission("main"); + switch (action) { + case ".": + case "main": + return true; + case "delete": + return defaultGrant && this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + case "edit": + return defaultGrant && this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED) && + this.parent_type !== "Layout" || + this.parent === path.layout; + } + return false; } /** @@ -176,43 +176,43 @@ Image.prototype.getPermission = function(action) { * @returns {String} */ Image.prototype.href = function(action) { - if (action !== "replace") { - if (this.parent_type === "Layout" && this.parent !== path.layout) { - return this.getUrl(); - } - } else { - return res.handlers.images.href("create") + "?name=" + this.name; - } - return HopObject.prototype.href.apply(this, arguments); + if (action !== "replace") { + if (this.parent_type === "Layout" && this.parent !== path.layout) { + return this.getUrl(); + } + } else { + return res.handlers.images.href("create") + "?name=" + this.name; + } + return HopObject.prototype.href.apply(this, arguments); } Image.prototype.main_action = function() { - res.data.title = gettext("Image: {0}", this.getTitle()); - res.data.body = this.renderSkinAsString("Image#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Image: {0}", this.getTitle()); + res.data.body = this.renderSkinAsString("Image#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Image.prototype.edit_action = function() { - File.redirectOnUploadError(this.href(req.action)); + File.redirectOnUploadError(this.href(req.action)); - if (req.postParams.save) { - try { - File.redirectOnExceededQuota(this.href(req.action)); - this.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.save) { + try { + File.redirectOnExceededQuota(this.href(req.action)); + this.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Edit Image"); - res.data.body = this.renderSkinAsString("$Image#edit"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Edit Image"); + res.data.body = this.renderSkinAsString("$Image#edit"); + res.handlers.site.renderSkin("Site#page"); + return; } /** @@ -221,32 +221,32 @@ Image.prototype.edit_action = function() { * @returns {Object} */ Image.prototype.getFormValue = function(name) { - var self = this; + var self = this; - var getOrigin = function(str) { - var origin = req.postParams.file_origin || self.origin; - if (origin && origin.contains("://")) { - return origin; - } - return null; - } + var getOrigin = function(str) { + var origin = req.postParams.file_origin || self.origin; + if (origin && origin.contains("://")) { + return origin; + } + return null; + } - if (req.isPost()) { - if (name === "file") { - return getOrigin(); - } - return req.postParams[name]; - } - switch (name) { - case "file": + if (req.isPost()) { + if (name === "file") { return getOrigin(); - case "maxWidth": - case "maxHeight": - return this[name] || 400; - case "tags": - return this.getTags(); - } - return this[name] || req.queryParams[name]; + } + return req.postParams[name]; + } + switch (name) { + case "file": + return getOrigin(); + case "maxWidth": + case "maxHeight": + return this[name] || 400; + case "tags": + return this.getTags(); + } + return this[name] || req.queryParams[name]; } /** @@ -254,102 +254,102 @@ Image.prototype.getFormValue = function(name) { * @param {Object} data */ Image.prototype.update = function(data) { - var origin = data.file_origin; + var origin = data.file_origin; - if (!origin) { - if (this.isTransient()) { - throw Error(gettext("There was nothing to upload. Please be sure to choose a file.")); - } - } else if (origin !== this.origin) { - var mime = data.file; - // Check if mime is not null to allow post requests with no file upload at all - if (!mime || mime.contentLength < 1) { - mime = getURL(origin); - if (!mime) { - throw Error(gettext("Could not fetch the image from the given URL.")); - } + if (!origin) { + if (this.isTransient()) { + throw Error(gettext("There was nothing to upload. Please be sure to choose a file.")); + } + } else if (origin !== this.origin) { + var mime = data.file; + // Check if mime is not null to allow post requests with no file upload at all + if (!mime || mime.contentLength < 1) { + mime = getURL(origin); + if (!mime) { + throw Error(gettext("Could not fetch the image from the given URL.")); } + } - var extension = Image.getFileExtension(mime.contentType); - if (!extension) { - throw Error(gettext("This does not seem to be a (valid) JPG, PNG or GIF image file.")); - } + var extension = Image.getFileExtension(mime.contentType); + if (!extension) { + throw Error(gettext("This does not seem to be a (valid) JPG, PNG or GIF image file.")); + } - this.origin = origin; - var mimeName = mime.normalizeFilename(mime.name); - this.contentLength = mime.contentLength; - this.contentType = mime.contentType; + this.origin = origin; + var mimeName = mime.normalizeFilename(mime.name); + this.contentLength = mime.contentLength; + this.contentType = mime.contentType; - if (!this.name) { - var name = File.getName(data.name) || mimeName.split(".")[0]; - this.name = this.parent.images.getAccessName(name); - } + if (!this.name) { + var name = File.getName(data.name) || mimeName.split(".")[0]; + this.name = this.parent.images.getAccessName(name); + } - var image = this.getConstraint(mime, data.maxWidth, data.maxHeight); - this.height = image.height; - this.width = image.width; + var image = this.getConstraint(mime, data.maxWidth, data.maxHeight); + this.height = image.height; + this.width = image.width; - var thumbnail; - if (image.width > Image.THUMBNAILWIDTH) { - thumbnail = this.getConstraint(mime, Image.THUMBNAILWIDTH); - this.thumbnailWidth = thumbnail.width; - this.thumbnailHeight = thumbnail.height; - } else if (this.isPersistent()) { - this.getThumbnailFile().remove(); - // NOTE: delete operator won't work here due to getter/setter methods - this.deleteMetadata("thumbnailName", "thumbnailWidth", "thumbnailHeight"); - } + var thumbnail; + if (image.width > Image.THUMBNAILWIDTH) { + thumbnail = this.getConstraint(mime, Image.THUMBNAILWIDTH); + this.thumbnailWidth = thumbnail.width; + this.thumbnailHeight = thumbnail.height; + } else if (this.isPersistent()) { + this.getThumbnailFile().remove(); + // NOTE: delete operator won't work here due to getter/setter methods + this.deleteMetadata("thumbnailName", "thumbnailWidth", "thumbnailHeight"); + } - // Make the image persistent before proceeding with writing files and - // setting tags (also see Helma bug #607) - this.isTransient() && this.persist(); + // Make the image persistent before proceeding with writing files and + // setting tags (also see Helma bug #607) + this.isTransient() && this.persist(); - var fileName = this.name + extension; - if (fileName !== this.fileName) { - // Remove existing image files if the file name has changed - this.removeFiles(); - } - this.fileName = fileName; - thumbnail && (this.thumbnailName = this.name + "_small" + extension); - this.writeFiles(image.resized || mime, thumbnail && thumbnail.resized); - image.resized && (this.contentLength = this.getFile().getLength()); - } + var fileName = this.name + extension; + if (fileName !== this.fileName) { + // Remove existing image files if the file name has changed + this.removeFiles(); + } + this.fileName = fileName; + thumbnail && (this.thumbnailName = this.name + "_small" + extension); + this.writeFiles(image.resized || mime, thumbnail && thumbnail.resized); + image.resized && (this.contentLength = this.getFile().getLength()); + } - if (this.parent_type !== "Layout") { - this.setTags(data.tags || data.tag_array); - } - this.description = data.description; - this.touch(); - return; + if (this.parent_type !== "Layout") { + this.setTags(data.tags || data.tag_array); + } + this.description = data.description; + this.touch(); + return; } /** * */ Image.prototype.tags_macro = function() { - return res.write(this.getFormValue("tags")); + return res.write(this.getFormValue("tags")); } /** * */ Image.prototype.contentLength_macro = function() { - return res.write((this.contentLength / 1024).format("###,###") + " KB"); + return res.write((this.contentLength / 1024).format("###,###") + " KB"); } /** * */ Image.prototype.url_macro = function() { - return res.write(this.getUrl()); + return res.write(this.getUrl()); } /** * */ Image.prototype.macro_macro = function() { - return HopObject.prototype.macro_macro.call(this, null, - this.parent.constructor === Layout ? "layout.image" : "image"); + return HopObject.prototype.macro_macro.call(this, null, + this.parent.constructor === Layout ? "layout.image" : "image"); } /** @@ -357,17 +357,17 @@ Image.prototype.macro_macro = function() { * @param {Object} param */ Image.prototype.thumbnail_macro = function(param) { - if (!this.thumbnailName) { - return this.render_macro(param); - } - param.src = this.getUrl(this.getThumbnailFile().getName()); - param.title || (param.title = encode(this.description)); - param.alt = encode(param.alt || param.title); - param.width = this.thumbnailWidth || String.EMPTY; - param.height = this.thumbnailHeight || String.EMPTY; - param.border = (param.border = 0); - html.tag("img", param); - return; + if (!this.thumbnailName) { + return this.render_macro(param); + } + param.src = this.getUrl(this.getThumbnailFile().getName()); + param.title || (param.title = encode(this.description)); + param.alt = encode(param.alt || param.title); + param.width = this.thumbnailWidth || String.EMPTY; + param.height = this.thumbnailHeight || String.EMPTY; + param.border = (param.border = 0); + html.tag("img", param); + return; } /** @@ -375,14 +375,14 @@ Image.prototype.thumbnail_macro = function(param) { * @param {Object} param */ Image.prototype.render_macro = function(param) { - param.src = this.getUrl(); - param.title || (param.title = encode(this.description)); - param.alt = encode(param.alt || param.title); - param.width || (param.width = this.width); - param.height || (param.height = this.height); - param.border || (param.border = 0); - html.tag("img", param); - return; + param.src = this.getUrl(); + param.title || (param.title = encode(this.description)); + param.alt = encode(param.alt || param.title); + param.width || (param.width = this.width); + param.height || (param.height = this.height); + param.border || (param.border = 0); + html.tag("img", param); + return; } /** @@ -392,13 +392,13 @@ Image.prototype.render_macro = function(param) { * @see Site#getStaticFile */ Image.prototype.getFile = function(name) { - name || (name = this.fileName); - if (this.parent_type === "Layout") { - var layout = this.parent || res.handlers.layout; - return layout.getFile(name); - } - var site = this.parent || res.handlers.site; - return site.getStaticFile("images/" + name); + name || (name = this.fileName); + if (this.parent_type === "Layout") { + var layout = this.parent || res.handlers.layout; + return layout.getFile(name); + } + var site = this.parent || res.handlers.site; + return site.getStaticFile("images/" + name); } /** @@ -408,42 +408,42 @@ Image.prototype.getFile = function(name) { * @see Site#getStaticUrl */ Image.prototype.getUrl = function(name) { - name || (name = this.fileName); - if (this.parent_type === "Layout") { - var layout = this.parent || res.handlers.layout; - return layout.site.getStaticUrl('layout/' + name); - } - var site = this.parent || res.handlers.site; - return site.getStaticUrl("images/" + name); + name || (name = this.fileName); + if (this.parent_type === "Layout") { + var layout = this.parent || res.handlers.layout; + return layout.site.getStaticUrl('layout/' + name); + } + var site = this.parent || res.handlers.site; + return site.getStaticUrl("images/" + name); } /** * @returns {helma.File} */ Image.prototype.getThumbnailFile = function() { - return this.getFile(this.thumbnailName); + return this.getFile(this.thumbnailName); } /** * @returns {String} */ Image.prototype.getJSON = function() { - return { - name: this.name, - origin: this.origin, - description: this.description, - contentType: this.contentType, - contentLength: this.contentLength, - width: this.width, - height: this.height, - thumbnailName: this.thumbnailName, - thumbnailWidth: this.thumbnailWidth, - thumbnailHeight: this.thumbnailHeight, - created: this.created, - creator: this.creator ? this.creator.name : null, - modified: this.modified, - modifier: this.modifier ? this.modifier.name : null, - }.toSource(); + return { + name: this.name, + origin: this.origin, + description: this.description, + contentType: this.contentType, + contentLength: this.contentLength, + width: this.width, + height: this.height, + thumbnailName: this.thumbnailName, + thumbnailWidth: this.thumbnailWidth, + thumbnailHeight: this.thumbnailHeight, + created: this.created, + creator: this.creator ? this.creator.name : null, + modified: this.modified, + modifier: this.modifier ? this.modifier.name : null, + }.toSource(); } /** @@ -455,31 +455,31 @@ Image.prototype.getJSON = function() { * @returns {Object} */ Image.prototype.getConstraint = function(mime, maxWidth, maxHeight) { - try { - var image = new helma.Image(mime.inputStream); - var factorH = 1, factorV = 1; - if (maxWidth && image.width > maxWidth) { - factorH = maxWidth / image.width; + try { + var image = new helma.Image(mime.inputStream); + var factorH = 1, factorV = 1; + if (maxWidth && image.width > maxWidth) { + factorH = maxWidth / image.width; + } + if (maxHeight && image.height > maxHeight) { + factorV = maxHeight / image.height; + } + if (factorH !== 1 || factorV !== 1) { + var width = Math.ceil(image.width * + (factorH < factorV ? factorH : factorV)); + var height = Math.ceil(image.height * + (factorH < factorV ? factorH : factorV)); + image.resize(width, height); + if (mime.contentType.endsWith("gif")) { + image.reduceColors(256); } - if (maxHeight && image.height > maxHeight) { - factorV = maxHeight / image.height; - } - if (factorH !== 1 || factorV !== 1) { - var width = Math.ceil(image.width * - (factorH < factorV ? factorH : factorV)); - var height = Math.ceil(image.height * - (factorH < factorV ? factorH : factorV)); - image.resize(width, height); - if (mime.contentType.endsWith("gif")) { - image.reduceColors(256); - } - return {resized: image, width: image.width, height: image.height}; - } - return {width: image.width, height: image.height}; - } catch (ex) { - app.log(ex); - throw Error(gettext("Could not resize the image.")); - } + return {resized: image, width: image.width, height: image.height}; + } + return {width: image.width, height: image.height}; + } catch (ex) { + app.log(ex); + throw Error(gettext("Could not resize the image.")); + } } /** @@ -489,47 +489,47 @@ Image.prototype.getConstraint = function(mime, maxWidth, maxHeight) { * @throws {Error} */ Image.prototype.writeFiles = function(data, thumbnail) { - if (data) { - try { - // If data is a MimeObject (ie. has the writeToFile method) - // the image was not resized and thus, we directly write it to disk - var file = this.getFile(); - if (data.saveAs) { - data.saveAs(file); - } else if (data.writeToFile) { - data.writeToFile(file.getParent(), file.getName()); - } - if (thumbnail) { - thumbnail.saveAs(this.getThumbnailFile()); - } - } catch (ex) { - app.log(ex); - throw Error(gettext("Could not save the image file on disk.")); + if (data) { + try { + // If data is a MimeObject (ie. has the writeToFile method) + // the image was not resized and thus, we directly write it to disk + var file = this.getFile(); + if (data.saveAs) { + data.saveAs(file); + } else if (data.writeToFile) { + data.writeToFile(file.getParent(), file.getName()); } - } - return; + if (thumbnail) { + thumbnail.saveAs(this.getThumbnailFile()); + } + } catch (ex) { + app.log(ex); + throw Error(gettext("Could not save the image file on disk.")); + } + } + return; } /** * @throws {Error} */ Image.prototype.removeFiles = function() { - try { - this.getFile().remove(); - var thumbnail = this.getThumbnailFile(); - if (thumbnail) { - thumbnail.remove(); - } - } catch (ex) { - app.log(ex); - throw Error(gettext("Could not remove the image file from disk.")); - } - return; + try { + this.getFile().remove(); + var thumbnail = this.getThumbnailFile(); + if (thumbnail) { + thumbnail.remove(); + } + } catch (ex) { + app.log(ex); + throw Error(gettext("Could not remove the image file from disk.")); + } + return; } /** * @returns {String} */ Image.prototype.getConfirmText = function() { - return gettext("You are about to delete the image {0}.", this.name); + return gettext("You are about to delete the image {0}.", this.name); } diff --git a/code/Images/Images.js b/code/Images/Images.js index 6a8a7d41..2f72603e 100644 --- a/code/Images/Images.js +++ b/code/Images/Images.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -46,86 +46,86 @@ markgettext("images"); * @returns {Boolean} */ Images.prototype.getPermission = function(action) { - if (!this._parent.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - case "create": - // FIXME: case "tags": - return Site.require(Site.OPEN) && session.user || - Membership.require(Membership.CONTRIBUTOR) || - User.require(User.PRIVILEGED); - case "all": - return this._parent.constructor !== Layout && - (Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED)); - } - return false; + if (!this._parent.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + case "create": + // FIXME: case "tags": + return Site.require(Site.OPEN) && session.user || + Membership.require(Membership.CONTRIBUTOR) || + User.require(User.PRIVILEGED); + case "all": + return this._parent.constructor !== Layout && + (Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED)); + } + return false; } Images.prototype.main_action = function() { - var images, skin; - switch (this._parent.constructor) { - case Root: - case Site: - images = User.getMembership().images; - skin = "$Images#main"; - res.data.title = gettext("Member Images"); - break; + var images, skin; + switch (this._parent.constructor) { + case Root: + case Site: + images = User.getMembership().images; + skin = "$Images#main"; + res.data.title = gettext("Member Images"); + break; - case Layout: - images = res.handlers.layout.images; - skin = "$Images#layout"; - res.data.title = gettext("Layout Images"); - break; - } - res.data.list = renderList(images, "$Image#listItem", - 10, req.queryParams.page); - res.data.pager = renderPager(images, - this.href(req.action), 10, req.queryParams.page); - res.data.body = this.renderSkinAsString(skin); - res.handlers.site.renderSkin("Site#page"); - return; + case Layout: + images = res.handlers.layout.images; + skin = "$Images#layout"; + res.data.title = gettext("Layout Images"); + break; + } + res.data.list = renderList(images, "$Image#listItem", + 10, req.queryParams.page); + res.data.pager = renderPager(images, + this.href(req.action), 10, req.queryParams.page); + res.data.body = this.renderSkinAsString(skin); + res.handlers.site.renderSkin("Site#page"); + return; } Images.prototype.create_action = function() { - File.redirectOnUploadError(this.href(req.action)); - File.redirectOnExceededQuota(this.href()); + File.redirectOnUploadError(this.href(req.action)); + File.redirectOnExceededQuota(this.href()); - if (req.data.save) { - try { - var image = Image.add(req.params, this._parent); - image.notify(req.action); - JSON.sendPaddedResponse(image._id); - res.message = gettext('The image was successfully added.'); - res.redirect(image.href()); - } catch (ex) { - JSON.sendPaddedResponse(null); - res.status = 400; - res.message = ex.toString(); - app.log(ex); - } - } + if (req.data.save) { + try { + var image = Image.add(req.params, this._parent); + image.notify(req.action); + JSON.sendPaddedResponse(image._id); + res.message = gettext('The image was successfully added.'); + res.redirect(image.href()); + } catch (ex) { + JSON.sendPaddedResponse(null); + res.status = 400; + res.message = ex.toString(); + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Add Image"); - HopObject.confirmConstructor(Image); - res.data.body = (new Image).renderSkinAsString("$Image#edit"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Add Image"); + HopObject.confirmConstructor(Image); + res.data.body = (new Image).renderSkinAsString("$Image#edit"); + res.handlers.site.renderSkin("Site#page"); + return; } Images.prototype.all_action = function() { - res.data.pager = renderPager(this, this.href(req.action), - 10, req.queryParams.page); - res.data.list = renderList(this, "$Image#listItem", - 10, req.queryParams.page); - res.data.title = gettext("All Images"); - res.data.body = this.renderSkinAsString("$Images#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.pager = renderPager(this, this.href(req.action), + 10, req.queryParams.page); + res.data.list = renderList(this, "$Image#listItem", + 10, req.queryParams.page); + res.data.title = gettext("All Images"); + res.data.body = this.renderSkinAsString("$Images#main"); + res.handlers.site.renderSkin("Site#page"); + return; } /** @@ -133,70 +133,70 @@ Images.prototype.all_action = function() { * @field */ Images.Default = new function() { - var Image = function(name, description) { - var dir = new helma.File(app.appsProperties['static'], "www"); - var image = new helma.Image(new helma.File(dir, name)); - this.__defineGetter__('parent', function() {return root}); - this.name = this.fileName = name; - this.description = description; - this.width = image.width; - this.height = image.height; - this.getUrl = function() { - // Cannot use global.Image.getUrl() here because these images are - // located in the top-level of the static directory. - return root.getStaticUrl(name); - } - this.render_macro = global.Image.prototype.render_macro; - this.thumbnail_macro = global.Image.prototype.thumbnail_macro; - return this; - } + var Image = function(name, description) { + var dir = new helma.File(app.appsProperties['static'], "www"); + var image = new helma.Image(new helma.File(dir, name)); + this.__defineGetter__('parent', function() {return root}); + this.name = this.fileName = name; + this.description = description; + this.width = image.width; + this.height = image.height; + this.getUrl = function() { + // Cannot use global.Image.getUrl() here because these images are + // located in the top-level of the static directory. + return root.getStaticUrl(name); + } + this.render_macro = global.Image.prototype.render_macro; + this.thumbnail_macro = global.Image.prototype.thumbnail_macro; + return this; + } - var images = {}; - var add = function(name, description) { - images[name] = new Image(name, description); - return; - } + var images = {}; + var add = function(name, description) { + images[name] = new Image(name, description); + return; + } - add("ant.png", "Ant"); - add("ant-icon.png", "Tiny Ant"); - add("big.gif", String.EMPTY); - add("bullet.gif", "*"); - add("dot.gif", String.EMPTY); - add("headbg.gif", String.EMPTY); - add("helma.png", "Helma Object Publisher"); - add("hop.gif", "Helma Object Publisher"); - add("manage.gif", "manage"); - add("marquee.gif", String.EMPTY); - add("menu.gif", "menu"); - add("pixel.gif", String.EMPTY); - add("recent.gif", "recent"); - add("rss.png", "RSS feed"); - add("smallanim.gif", "Made with Antville"); - add("smallchaos.gif", "Made with Antville"); - add("smallstraight.gif", "Made with Antville"); - add("smalltrans.gif", "Made with Antville"); - add("status.gif", "status"); - add("webloghead.gif", "Antville"); - add("xmlbutton.gif", "XML version of this page"); - return images; + add("ant.png", "Ant"); + add("ant-icon.png", "Tiny Ant"); + add("big.gif", String.EMPTY); + add("bullet.gif", "*"); + add("dot.gif", String.EMPTY); + add("headbg.gif", String.EMPTY); + add("helma.png", "Helma Object Publisher"); + add("hop.gif", "Helma Object Publisher"); + add("manage.gif", "manage"); + add("marquee.gif", String.EMPTY); + add("menu.gif", "menu"); + add("pixel.gif", String.EMPTY); + add("recent.gif", "recent"); + add("rss.png", "RSS feed"); + add("smallanim.gif", "Made with Antville"); + add("smallchaos.gif", "Made with Antville"); + add("smallstraight.gif", "Made with Antville"); + add("smalltrans.gif", "Made with Antville"); + add("status.gif", "status"); + add("webloghead.gif", "Antville"); + add("xmlbutton.gif", "XML version of this page"); + return images; } /** * @returns {Image[]} */ Images.prototype.mergeImages = function() { - var images = []; - var layout = this._parent; - while (layout) { - layout.images.forEach(function() { - if (images.indexOf(this) < 0) { - images.push(this); - } - return; - }); - layout = layout.parent; - } - return images.sort(Number.Sorter("created", Number.Sorter.DESC)); + var images = []; + var layout = this._parent; + while (layout) { + layout.images.forEach(function() { + if (images.indexOf(this) < 0) { + images.push(this); + } + return; + }); + layout = layout.parent; + } + return images.sort(Number.Sorter("created", Number.Sorter.DESC)); } /** @@ -206,5 +206,5 @@ Images.prototype.mergeImages = function() { * @see Site#getTags */ Images.prototype.getTags = function(group) { - return this._parent.getTags("galleries", group); + return this._parent.getTags("galleries", group); } diff --git a/code/Layout/Layout.js b/code/Layout/Layout.js index e44fe0d6..9cc157f7 100644 --- a/code/Layout/Layout.js +++ b/code/Layout/Layout.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -32,19 +32,19 @@ markgettext("layout"); /** @constant */ Layout.VALUES = [ - "background color", - "link color", - "active link color", - "visited link color", - "big font", - "big font size", - "big font color", - "base font", - "base font size", - "base font color", - "small font", - "small font size", - "small font color" + "background color", + "link color", + "active link color", + "visited link color", + "big font", + "big font size", + "big font color", + "base font", + "base font size", + "base font color", + "small font", + "small font size", + "small font color" ]; /** @@ -53,16 +53,16 @@ Layout.VALUES = [ * @returns {Layout} */ Layout.add = function(site, user) { - HopObject.confirmConstructor(Layout); - var layout = new Layout; - layout.site = site; - layout.creator = user || session.user; - layout.created = new Date; - layout.mode = Layout.DEFAULT; - layout.reset(); - layout.touch(); - site.layout = layout; - return layout + HopObject.confirmConstructor(Layout); + var layout = new Layout; + layout.site = site; + layout.creator = user || session.user; + layout.created = new Date; + layout.mode = Layout.DEFAULT; + layout.reset(); + layout.touch(); + site.layout = layout; + return layout } /** @@ -71,26 +71,26 @@ Layout.add = function(site, user) { * @param {Boolean} includeSelf */ Layout.remove = function(options) { - if (this.constructor === Layout) { - // Backup current layout in temporary directory if possible - var dir = this.getFile(); - // FIXME: Evaluate if using res.skinpath is necessary; dir could be fully sufficient. - if (res.skinpath && res.skinpath[0] && res.skinpath[0].equals(dir) && - dir.exists() && dir.list().length > 0) { - var zip = this.getArchive(res.skinpath); - var file = java.io.File.createTempFile(this.site.name + "-layout-", ".zip"); - zip.save(file); - } - HopObject.remove.call(this.skins); - HopObject.remove.call(this.images); - this.getFile().removeDirectory(); - // The “force” flag is set e.g. when a whole site is removed - if (options && options.force) { - this.deleteMetadata(); - this.remove(); - } - } - return; + if (this.constructor === Layout) { + // Backup current layout in temporary directory if possible + var dir = this.getFile(); + // FIXME: Evaluate if using res.skinpath is necessary; dir could be fully sufficient. + if (res.skinpath && res.skinpath[0] && res.skinpath[0].equals(dir) && + dir.exists() && dir.list().length > 0) { + var zip = this.getArchive(res.skinpath); + var file = java.io.File.createTempFile(this.site.name + "-layout-", ".zip"); + zip.save(file); + } + HopObject.remove.call(this.skins); + HopObject.remove.call(this.images); + this.getFile().removeDirectory(); + // The “force” flag is set e.g. when a whole site is removed + if (options && options.force) { + this.deleteMetadata(); + this.remove(); + } + } + return; } /** @@ -99,16 +99,16 @@ Layout.remove = function(options) { * @returns {Boolean} */ Layout.sandbox = function(value) { - var cookie = User.COOKIE + 'LayoutSandbox'; - if (typeof value === 'undefined') { - return req.cookies[cookie] === 'true'; - } - if (value === true) { - res.setCookie(cookie, true); - } else if (value === false) { - res.unsetCookie(cookie); - } - return value; + var cookie = User.COOKIE + 'LayoutSandbox'; + if (typeof value === 'undefined') { + return req.cookies[cookie] === 'true'; + } + if (value === true) { + res.setCookie(cookie, true); + } else if (value === false) { + res.unsetCookie(cookie); + } + return value; } /** @@ -140,8 +140,8 @@ this.handleMetadata("originated"); * @extends HopObject */ Layout.prototype.constructor = function() { - HopObject.confirmConstructor.call(this); - return this; + HopObject.confirmConstructor.call(this); + return this; } /** @@ -150,20 +150,20 @@ Layout.prototype.constructor = function() { * @returns {Boolean} */ Layout.prototype.getPermission = function(action) { - switch (action) { - case ".": - case "main": - case "export": - case "images": - case "import": - case "reset": - case "skins": - case "sandbox": - return res.handlers.site.getPermission("main") && - Membership.require(Membership.OWNER) || - User.require(User.PRIVILEGED); - } - return false; + switch (action) { + case ".": + case "main": + case "export": + case "images": + case "import": + case "reset": + case "skins": + case "sandbox": + return res.handlers.site.getPermission("main") && + Membership.require(Membership.OWNER) || + User.require(User.PRIVILEGED); + } + return false; } // FIXME: The Layout.href method is overwritten to guarantee that @@ -174,28 +174,28 @@ Layout.prototype.getPermission = function(action) { * @returns {String} */ Layout.prototype.href = function(action) { - res.push(); - res.write(res.handlers.site.href()); - res.write("layout/"); - action && res.write(action); - return res.pop(); + res.push(); + res.write(res.handlers.site.href()); + res.write("layout/"); + action && res.write(action); + return res.pop(); } Layout.prototype.main_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - res.message = gettext("Successfully updated the layout."); - res.redirect(this.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - res.data.title = gettext("Layout"); - res.data.body = this.renderSkinAsString("$Layout#main"); - res.handlers.site.renderSkin("Site#page"); - return; + if (req.postParams.save) { + try { + this.update(req.postParams); + res.message = gettext("Successfully updated the layout."); + res.redirect(this.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.data.title = gettext("Layout"); + res.data.body = this.renderSkinAsString("$Layout#main"); + res.handlers.site.renderSkin("Site#page"); + return; } /** @@ -204,12 +204,12 @@ Layout.prototype.main_action = function() { * @returns {Object} */ Layout.prototype.getFormOptions = function(name) { - switch (name) { - case "mode": - return Layout.getModes(); - case "parent": - return this.getParentOptions(); - } + switch (name) { + case "mode": + return Layout.getModes(); + case "parent": + return this.getParentOptions(); + } } /** @@ -217,104 +217,104 @@ Layout.prototype.getFormOptions = function(name) { * @param {Object} data */ Layout.prototype.update = function(data) { - var skin = this.skins.getSkin("Site", "values"); - if (!skin) { - Skin.add("Site", "values", this); - } - res.push(); - for (var key in data) { - if (key.startsWith("value_")) { - var value = data[key]; - key = key.substr(6); - res.write("<% value "); - res.write(quote(key)); - res.write(" "); - res.write(quote(value)); - res.write(" %>\n"); - } - } - res.write("\n"); - skin.setSource(res.pop()); - Layout.sandbox(!!data.sandbox); - this.description = data.description; - this.mode = data.mode; - this.touch(); - return; + var skin = this.skins.getSkin("Site", "values"); + if (!skin) { + Skin.add("Site", "values", this); + } + res.push(); + for (var key in data) { + if (key.startsWith("value_")) { + var value = data[key]; + key = key.substr(6); + res.write("<% value "); + res.write(quote(key)); + res.write(" "); + res.write(quote(value)); + res.write(" %>\n"); + } + } + res.write("\n"); + skin.setSource(res.pop()); + Layout.sandbox(!!data.sandbox); + this.description = data.description; + this.mode = data.mode; + this.touch(); + return; } Layout.prototype.reset_action = function() { - if (req.data.proceed) { - try { - Layout.remove.call(this); - this.reset(); - res.message = gettext("{0} was successfully reset.", gettext("Layout")); - res.redirect(this.href()); - } catch(ex) { - res.message = ex; - app.log(ex); - } - } + if (req.data.proceed) { + try { + Layout.remove.call(this); + this.reset(); + res.message = gettext("{0} was successfully reset.", gettext("Layout")); + res.redirect(this.href()); + } catch(ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Confirm Reset"); - res.data.body = this.renderSkinAsString("$HopObject#confirm", { - text: this.getConfirmText() - }); - res.handlers.site.renderSkin("Site#page"); + res.data.action = this.href(req.action); + res.data.title = gettext("Confirm Reset"); + res.data.body = this.renderSkinAsString("$HopObject#confirm", { + text: this.getConfirmText() + }); + res.handlers.site.renderSkin("Site#page"); } Layout.prototype.export_action = function() { - res.contentType = "application/zip"; - var zip = this.getArchive(res.skinpath); - res.setHeader("Content-Disposition", - "attachment; filename=" + this.site.name + "-layout.zip"); - res.writeBinary(zip.getData()); - return; + res.contentType = "application/zip"; + var zip = this.getArchive(res.skinpath); + res.setHeader("Content-Disposition", + "attachment; filename=" + this.site.name + "-layout.zip"); + res.writeBinary(zip.getData()); + return; } Layout.prototype.import_action = function() { - var self = this; - var data = req.postParams; - if (data.submit) { - try { - if (!data.upload || data.upload.contentLength === 0) { - throw Error(gettext("Please upload a zipped layout archive")); - } - // Extract zipped layout to temporary directory - var dir = this.site.getStaticFile(); - var temp = new helma.File(dir, "import.temp"); - var fname = data.upload.writeToFile(dir); - var zip = new helma.File(dir, fname); - (new helma.Zip(zip)).extractAll(temp); - zip.remove(); - var data = Xml.read(new helma.File(temp, "data.xml")); - if (!data.version) { - throw Error(gettext("Sorry, this layout is not compatible with Antville.")); - } - // Remove current layout and replace it with imported one - Layout.remove.call(this); - temp.renameTo(this.getFile()); - this.origin = data.origin; - this.originator = data.originator; - this.originated = data.originated; - data.images.forEach(function() { - Image.add(this); - }); - this.touch(); - res.message = gettext("The layout was successfully imported."); - } catch (ex) { - res.message = ex; - app.log(ex); - temp && temp.removeDirectory(); - res.redirect(this.href(req.action)); + var self = this; + var data = req.postParams; + if (data.submit) { + try { + if (!data.upload || data.upload.contentLength === 0) { + throw Error(gettext("Please upload a zipped layout archive")); } - res.redirect(this.href()); - return; - } - res.data.title = gettext("Import Layout"); - res.data.body = this.renderSkinAsString("$Layout#import"); - res.handlers.site.renderSkin("Site#page"); - return; + // Extract zipped layout to temporary directory + var dir = this.site.getStaticFile(); + var temp = new helma.File(dir, "import.temp"); + var fname = data.upload.writeToFile(dir); + var zip = new helma.File(dir, fname); + (new helma.Zip(zip)).extractAll(temp); + zip.remove(); + var data = Xml.read(new helma.File(temp, "data.xml")); + if (!data.version) { + throw Error(gettext("Sorry, this layout is not compatible with Antville.")); + } + // Remove current layout and replace it with imported one + Layout.remove.call(this); + temp.renameTo(this.getFile()); + this.origin = data.origin; + this.originator = data.originator; + this.originated = data.originated; + data.images.forEach(function() { + Image.add(this); + }); + this.touch(); + res.message = gettext("The layout was successfully imported."); + } catch (ex) { + res.message = ex; + app.log(ex); + temp && temp.removeDirectory(); + res.redirect(this.href(req.action)); + } + res.redirect(this.href()); + return; + } + res.data.title = gettext("Import Layout"); + res.data.body = this.renderSkinAsString("$Layout#import"); + res.handlers.site.renderSkin("Site#page"); + return; } /** @@ -324,18 +324,18 @@ Layout.prototype.import_action = function() { * @returns {Image} */ Layout.prototype.getImage = function(name, fallback) { - var layout = this; - while (layout) { - layout.images.prefetchChildren(); - if (layout.images.get(name)) { - return layout.images.get(name); - } - if (fallback && layout.images.get(fallback)) { - return layout.images.get(fallback); - } - layout = layout.parent; - } - return null; + var layout = this; + while (layout) { + layout.images.prefetchChildren(); + if (layout.images.get(name)) { + return layout.images.get(name); + } + if (fallback && layout.images.get(fallback)) { + return layout.images.get(fallback); + } + layout = layout.parent; + } + return null; } /** @@ -344,48 +344,48 @@ Layout.prototype.getImage = function(name, fallback) { * @returns {helma.File} */ Layout.prototype.getFile = function(name) { - name || (name = String.EMPTY); - return this.site.getStaticFile("layout/" + name); + name || (name = String.EMPTY); + return this.site.getStaticFile("layout/" + name); } /** * @returns {String[]} */ Layout.prototype.getSkinPath = function() { - if (!this.site) { - return null; - } - var skinPath = [this.getFile().toString()]; - return skinPath; + if (!this.site) { + return null; + } + var skinPath = [this.getFile().toString()]; + return skinPath; } /** * */ Layout.prototype.reset = function() { - var skinFiles = app.getSkinfilesInPath([app.dir]); - var content, dir, file; - for (var name in skinFiles) { - if (content = skinFiles[name][name]) { - dir = this.getFile(name); - file = new helma.File(dir, name + ".skin"); - dir.makeDirectory(); - file.open(); - file.write(content); - file.close(); - } - } + var skinFiles = app.getSkinfilesInPath([app.dir]); + var content, dir, file; + for (var name in skinFiles) { + if (content = skinFiles[name][name]) { + dir = this.getFile(name); + file = new helma.File(dir, name + ".skin"); + dir.makeDirectory(); + file.open(); + file.write(content); + file.close(); + } + } - // FIXME: Reset the Site skin of root separately - content = skinFiles.Root.Site; - file = new helma.File(this.getFile("Root"), "Site.skin"); - dir.makeDirectory(); - file.open(); - file.write(content); - file.close() + // FIXME: Reset the Site skin of root separately + content = skinFiles.Root.Site; + file = new helma.File(this.getFile("Root"), "Site.skin"); + dir.makeDirectory(); + file.open(); + file.write(content); + file.close() - this.touch(); - return; + this.touch(); + return; } /** @@ -394,47 +394,47 @@ Layout.prototype.reset = function() { * @returns {helma.Zip} */ Layout.prototype.getArchive = function(skinPath) { - var zip = new helma.Zip(); - var skinFiles = app.getSkinfilesInPath(skinPath); - for (var name in skinFiles) { - if (skinFiles[name][name]) { - var file = new helma.File(this.getFile(name), name + ".skin"); - if (file.exists()) { - zip.add(file, name); - } + var zip = new helma.Zip(); + var skinFiles = app.getSkinfilesInPath(skinPath); + for (var name in skinFiles) { + if (skinFiles[name][name]) { + var file = new helma.File(this.getFile(name), name + ".skin"); + if (file.exists()) { + zip.add(file, name); } - } + } + } - // FIXME: Add the Site skin of root separately - file = new helma.File(this.getFile("Root"), "Site.skin"); - file.exists() && zip.add(file, "Root"); + // FIXME: Add the Site skin of root separately + file = new helma.File(this.getFile("Root"), "Site.skin"); + file.exists() && zip.add(file, "Root"); - var data = new HopObject; - data.images = new HopObject; - this.images.forEach(function() { - zip.add(this.getFile()); - try { - zip.add(this.getThumbnailFile()); - } catch (ex) { - /* Most likely the thumbnail file is identical to the image */ - } - var image = new HopObject; - for each (var key in Image.KEYS) { - image[key] = this[key]; - data.images.add(image); - } - }); + var data = new HopObject; + data.images = new HopObject; + this.images.forEach(function() { + zip.add(this.getFile()); + try { + zip.add(this.getThumbnailFile()); + } catch (ex) { + /* Most likely the thumbnail file is identical to the image */ + } + var image = new HopObject; + for each (var key in Image.KEYS) { + image[key] = this[key]; + data.images.add(image); + } + }); - data.version = Root.VERSION.toString(); - data.origin = this.origin || this.site.href(); - data.originator = this.originator || session.user.name; - data.originated = this.originated || new Date; + data.version = Root.VERSION.toString(); + data.origin = this.origin || this.site.href(); + data.originator = this.originator || session.user.name; + data.originated = this.originated || new Date; - // FIXME: XML encoder is losing all mixed-case properties :( - var xml = new java.lang.String(Xml.writeToString(data)); - zip.addData(xml.getBytes("UTF-8"), "data.xml"); - zip.close(); - return zip; + // FIXME: XML encoder is losing all mixed-case properties :( + var xml = new java.lang.String(Xml.writeToString(data)); + zip.addData(xml.getBytes("UTF-8"), "data.xml"); + zip.close(); + return zip; } @@ -442,8 +442,8 @@ Layout.prototype.getArchive = function(skinPath) { * @returns {String} */ Layout.prototype.getConfirmText = function() { - return gettext("You are about to reset the layout of site {0}.", - this.site.name); + return gettext("You are about to reset the layout of site {0}.", + this.site.name); } /** * @@ -451,13 +451,13 @@ Layout.prototype.getConfirmText = function() { * @returns {HopObject} */ Layout.prototype.getMacroHandler = function(name) { - switch (name) { - case "skins": - return this[name]; + switch (name) { + case "skins": + return this[name]; - default: - return null; - } + default: + return null; + } } /** @@ -467,56 +467,56 @@ Layout.prototype.getMacroHandler = function(name) { * @param {String} mode */ Layout.prototype.image_macro = function(param, name, mode) { - name || (name = param.name); - if (!name) { - return; - } + name || (name = param.name); + if (!name) { + return; + } - var image = this.getImage(name, param.fallback); - if (!image) { - return; - } + var image = this.getImage(name, param.fallback); + if (!image) { + return; + } - mode || (mode = param.as); - var action = param.linkto; - delete(param.name); - delete(param.as); - delete(param.linkto); + mode || (mode = param.as); + var action = param.linkto; + delete(param.name); + delete(param.as); + delete(param.linkto); - switch (mode) { - case "url" : - return res.write(image.getUrl()); - case "thumbnail" : - action || (action = image.getUrl()); - return image.thumbnail_macro(param); - } - image.render_macro(param); - return; + switch (mode) { + case "url" : + return res.write(image.getUrl()); + case "thumbnail" : + action || (action = image.getUrl()); + return image.thumbnail_macro(param); + } + image.render_macro(param); + return; } /** * */ Layout.prototype.values_macro = function() { - var values = []; - for (var key in res.meta.values) { - values.push({key: key, value: res.meta.values[key]}); - } - values.sort(new String.Sorter("key")); - for each (var pair in values) { - this.renderSkin("$Layout#value", { - key: pair.key.capitalize(), - value: pair.value - }); - } - return; + var values = []; + for (var key in res.meta.values) { + values.push({key: key, value: res.meta.values[key]}); + } + values.sort(new String.Sorter("key")); + for each (var pair in values) { + this.renderSkin("$Layout#value", { + key: pair.key.capitalize(), + value: pair.value + }); + } + return; } /** * */ Layout.prototype.sandbox_macro = function() { - res.write(Layout.sandbox()); - return; + res.write(Layout.sandbox()); + return; } diff --git a/code/LogEntry/LogEntry.js b/code/LogEntry/LogEntry.js index b9d85f3f..87927aa1 100644 --- a/code/LogEntry/LogEntry.js +++ b/code/LogEntry/LogEntry.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -45,23 +45,23 @@ markgettext("log entry"); * @extends HopObject */ LogEntry.prototype.constructor = function(context, action) { - this.context = context; - this.action = action; - this.referrer = req.data.http_referer; - this.creator = session.user; - this.created = new Date; - this.ip = req.data.http_remotehost; // Won't be stored in database - this.site = res.handlers.site; - return this; + this.context = context; + this.action = action; + this.referrer = req.data.http_referer; + this.creator = session.user; + this.created = new Date; + this.ip = req.data.http_remotehost; // Won't be stored in database + this.site = res.handlers.site; + return this; } /** * @returns {String} */ LogEntry.prototype.toString = function() { - return "[LogEntry #" + this._id + ": " + (this.creator || "anonymous") + - " requested " + this.action + " action of " + this.context_type + - " #" + this.context_id + " on " + formatDate(this.created) + "]"; + return "[LogEntry #" + this._id + ": " + (this.creator || "anonymous") + + " requested " + this.action + " action of " + this.context_type + + " #" + this.context_id + " on " + formatDate(this.created) + "]"; } /** @@ -70,11 +70,11 @@ LogEntry.prototype.toString = function() { * @returns {HopObject} */ LogEntry.prototype.getMacroHandler = function(name) { - switch (name) { - case "context": - return this.context || {name: this.context_id}; - } - return null; + switch (name) { + case "context": + return this.context || {name: this.context_id}; + } + return null; } /** @@ -82,18 +82,18 @@ LogEntry.prototype.getMacroHandler = function(name) { * @param {Object} param */ LogEntry.prototype.label_macro = function(param) { - if (!User.require(User.PRIVILEGED)) { - return; - } - switch (this.context_type) { - case "Site" : - res.write("SITE"); - break; - case "User" : - res.write("USER"); - break; - default : - res.write("ROOT"); - } - return; + if (!User.require(User.PRIVILEGED)) { + return; + } + switch (this.context_type) { + case "Site" : + res.write("SITE"); + break; + case "User" : + res.write("USER"); + break; + default : + res.write("ROOT"); + } + return; } diff --git a/code/Members/Members.js b/code/Members/Members.js index 4516e329..3d750bbe 100644 --- a/code/Members/Members.js +++ b/code/Members/Members.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -47,306 +47,306 @@ markgettext("members"); * @returns {Boolean} */ Members.prototype.getPermission = function(action) { - switch (action) { - case "login": - case "logout": - case "register": - case "reset": - case "salt.txt": - return true; - } + switch (action) { + case "login": + case "logout": + case "register": + case "reset": + case "salt.txt": + return true; + } - var sitePermission = this._parent.getPermission("main"); + var sitePermission = this._parent.getPermission("main"); - switch (action) { - case "edit": - case "privileges": - case "subscriptions": - case "updated": - return sitePermission && !!session.user; + switch (action) { + case "edit": + case "privileges": + case "subscriptions": + case "updated": + return sitePermission && !!session.user; - case ".": - case "main": - case "add": - case "owners": - case "managers": - case "contributors": - case "subscribers": - return sitePermission && (Membership.require(Membership.OWNER) || - User.require(User.PRIVILEGED)); - } + case ".": + case "main": + case "add": + case "owners": + case "managers": + case "contributors": + case "subscribers": + return sitePermission && (Membership.require(Membership.OWNER) || + User.require(User.PRIVILEGED)); + } - return Feature.getPermission.apply(this, arguments); + return Feature.getPermission.apply(this, arguments); } Members.prototype.main_action = function() { - res.data.title = gettext("Site Members"); - res.data.list = renderList(this, "$Membership#member", - 10, req.queryParams.page); - res.data.pager = renderPager(this, this.href(req.action), - 10, req.queryParams.page); - res.data.body = this.renderSkinAsString("$Members#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Members"); + res.data.list = renderList(this, "$Membership#member", + 10, req.queryParams.page); + res.data.pager = renderPager(this, this.href(req.action), + 10, req.queryParams.page); + res.data.body = this.renderSkinAsString("$Members#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.register_action = function() { - if (req.postParams.register) { - try { - var title = res.handlers.site.title; - var user = User.register(req.postParams); - var membership = Membership.add(user, Membership.SUBSCRIBER, this._parent); - membership.notify(req.action, user.email, - gettext('[{0}] Welcome to {1}!', root.title, title)); - res.message = gettext('Welcome to “{0}”, {1}. Have fun!', - title, user.name); - res.redirect(User.getLocation() || this._parent.href()); - } catch (ex) { - res.message = ex; - } - } + if (req.postParams.register) { + try { + var title = res.handlers.site.title; + var user = User.register(req.postParams); + var membership = Membership.add(user, Membership.SUBSCRIBER, this._parent); + membership.notify(req.action, user.email, + gettext('[{0}] Welcome to {1}!', root.title, title)); + res.message = gettext('Welcome to “{0}”, {1}. Have fun!', + title, user.name); + res.redirect(User.getLocation() || this._parent.href()); + } catch (ex) { + res.message = ex; + } + } - session.data.token = User.getSalt(); - res.data.action = this.href(req.action); - res.data.title = gettext("Register"); - res.data.body = this.renderSkinAsString("$Members#register"); - this._parent.renderSkin("Site#page"); - return; + session.data.token = User.getSalt(); + res.data.action = this.href(req.action); + res.data.title = gettext("Register"); + res.data.body = this.renderSkinAsString("$Members#register"); + this._parent.renderSkin("Site#page"); + return; } Members.prototype.reset_action = function() { - if (req.postParams.reset) { - try { - if (!req.postParams.name || !req.postParams.email) { - throw Error(gettext("Please enter a user name and e-mail address.")); - } - var user = User.getByName(req.postParams.name); - if (!user || user.email !== req.postParams.email) { - throw Error(gettext("User name and e-mail address do not match.")) - } - var token = User.getSalt(); - user.setMetadata("resetToken", token); - sendMail(user.email, gettext("[{0}] Password reset confirmation", root.title), - user.renderSkinAsString("$User#notify_reset", { - href: this.href("reset"), - token: token - })); - res.message = gettext("A confirmation mail was sent to your e-mail address."); - res.redirect(this._parent.href()); - } catch(ex) { - res.message = ex; + if (req.postParams.reset) { + try { + if (!req.postParams.name || !req.postParams.email) { + throw Error(gettext("Please enter a user name and e-mail address.")); } - } else if (req.data.user && req.data.token) { - var user = User.getById(req.data.user); - if (user) { - var token = user.getMetadata("resetToken"); - if (token && token === req.data.token) { - session.login(user); - if (req.postParams.save) { - var password = req.postParams.password; - if (!password) { - res.message = gettext("Please enter a new password."); - } else if (password !== req.postParams.passwordConfirm) { - res.message = gettext("The passwords do not match."); - } else { - user.hash = (password + user.salt).md5(); - user.setMetadata("resetToken", null); - res.message = gettext("Your password was changed."); - res.redirect(this._parent.href()); - } - } - res.data.title = gettext("Reset Password"); - res.data.body = this.renderSkinAsString("$Members#password"); - this._parent.renderSkin("Site#page"); - return; - } + var user = User.getByName(req.postParams.name); + if (!user || user.email !== req.postParams.email) { + throw Error(gettext("User name and e-mail address do not match.")) } - res.message = gettext("This URL is not valid for resetting your password."); - res.redirect(this.href(req.action)); - } - res.data.action = this.href(req.action); - res.data.title = gettext("Request Password Reset"); - res.data.body = this.renderSkinAsString("$Members#reset"); - this._parent.renderSkin("Site#page"); - return; + var token = User.getSalt(); + user.setMetadata("resetToken", token); + sendMail(user.email, gettext("[{0}] Password reset confirmation", root.title), + user.renderSkinAsString("$User#notify_reset", { + href: this.href("reset"), + token: token + })); + res.message = gettext("A confirmation mail was sent to your e-mail address."); + res.redirect(this._parent.href()); + } catch(ex) { + res.message = ex; + } + } else if (req.data.user && req.data.token) { + var user = User.getById(req.data.user); + if (user) { + var token = user.getMetadata("resetToken"); + if (token && token === req.data.token) { + session.login(user); + if (req.postParams.save) { + var password = req.postParams.password; + if (!password) { + res.message = gettext("Please enter a new password."); + } else if (password !== req.postParams.passwordConfirm) { + res.message = gettext("The passwords do not match."); + } else { + user.hash = (password + user.salt).md5(); + user.setMetadata("resetToken", null); + res.message = gettext("Your password was changed."); + res.redirect(this._parent.href()); + } + } + res.data.title = gettext("Reset Password"); + res.data.body = this.renderSkinAsString("$Members#password"); + this._parent.renderSkin("Site#page"); + return; + } + } + res.message = gettext("This URL is not valid for resetting your password."); + res.redirect(this.href(req.action)); + } + res.data.action = this.href(req.action); + res.data.title = gettext("Request Password Reset"); + res.data.body = this.renderSkinAsString("$Members#reset"); + this._parent.renderSkin("Site#page"); + return; } Members.prototype.login_action = function() { - if (req.postParams.login) { - try { - var user = User.login(req.postParams); - res.message = gettext('Welcome to {0}, {1}. Have fun!', - res.handlers.site.getTitle(), user.name); - res.redirect(User.getLocation() || this._parent.href()); - } catch (ex) { - res.message = ex; - } - } - session.data.token = User.getSalt(); - res.data.action = this.href(req.action); - res.data.title = gettext("Login"); - res.data.body = this.renderSkinAsString("$Members#login"); - this._parent.renderSkin("Site#page"); - return; + if (req.postParams.login) { + try { + var user = User.login(req.postParams); + res.message = gettext('Welcome to {0}, {1}. Have fun!', + res.handlers.site.getTitle(), user.name); + res.redirect(User.getLocation() || this._parent.href()); + } catch (ex) { + res.message = ex; + } + } + session.data.token = User.getSalt(); + res.data.action = this.href(req.action); + res.data.title = gettext("Login"); + res.data.body = this.renderSkinAsString("$Members#login"); + this._parent.renderSkin("Site#page"); + return; } Members.prototype.logout_action = function() { - if (session.user) { - res.message = gettext("Good bye, {0}! Looking forward to seeing you again!", - session.user.name); - User.logout(); - } - res.redirect(this._parent.href()); - return; + if (session.user) { + res.message = gettext("Good bye, {0}! Looking forward to seeing you again!", + session.user.name); + User.logout(); + } + res.redirect(this._parent.href()); + return; } Members.prototype.edit_action = function() { - if (req.postParams.save) { - try { - session.user.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this._parent.href()); - } catch (err) { - res.message = err.toString(); - } - } + if (req.postParams.save) { + try { + session.user.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this._parent.href()); + } catch (err) { + res.message = err.toString(); + } + } - session.data.token = User.getSalt(); - session.data.salt = session.user.salt; // FIXME - res.data.title = gettext("User Profile"); - res.data.body = session.user.renderSkinAsString("$User#edit"); - this._parent.renderSkin("Site#page"); - return; + session.data.token = User.getSalt(); + session.data.salt = session.user.salt; // FIXME + res.data.title = gettext("User Profile"); + res.data.body = session.user.renderSkinAsString("$User#edit"); + this._parent.renderSkin("Site#page"); + return; } Members.prototype.salt_txt_action = function() { - res.contentType = "text/plain"; - var user; - if (user = User.getByName(req.queryParams.user)) { - res.write(user.salt || String.EMPTY); - } - return; + res.contentType = "text/plain"; + var user; + if (user = User.getByName(req.queryParams.user)) { + res.write(user.salt || String.EMPTY); + } + return; } Members.prototype.owners_action = function() { - res.data.title = gettext("Site Owners"); - res.data.list = renderList(this.owners, - "$Membership#member", 10, req.queryParams.page); - res.data.pager = renderPager(this.owners, - this.href(req.action), 10, req.queryParams.page); - res.data.body = this.renderSkinAsString("$Members#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Owners"); + res.data.list = renderList(this.owners, + "$Membership#member", 10, req.queryParams.page); + res.data.pager = renderPager(this.owners, + this.href(req.action), 10, req.queryParams.page); + res.data.body = this.renderSkinAsString("$Members#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.managers_action = function() { - res.data.title = gettext("Site Managers"); - res.data.list = renderList(this.managers, - "$Membership#member", 10, req.queryParams.page); - res.data.pager = renderPager(this.managers, - this.href(req.action), 10, req.queryParams.page); - res.data.body = this.renderSkinAsString("$Members#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Managers"); + res.data.list = renderList(this.managers, + "$Membership#member", 10, req.queryParams.page); + res.data.pager = renderPager(this.managers, + this.href(req.action), 10, req.queryParams.page); + res.data.body = this.renderSkinAsString("$Members#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.contributors_action = function() { - res.data.title = gettext("Site Contributors"); - res.data.list = renderList(this.contributors, - "$Membership#member", 10, req.queryParams.page); - res.data.pager = renderPager(this.contributors, - this.href(req.action), 10, req.data.page); - res.data.body = this.renderSkinAsString("$Members#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Contributors"); + res.data.list = renderList(this.contributors, + "$Membership#member", 10, req.queryParams.page); + res.data.pager = renderPager(this.contributors, + this.href(req.action), 10, req.data.page); + res.data.body = this.renderSkinAsString("$Members#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.subscribers_action = function() { - res.data.title = gettext("Site Subscribers"); - res.data.list = renderList(this.subscribers, - "$Membership#member", 10, req.queryParams.page); - res.data.pager = renderPager(this.subscribers, - this.href(req.action), 10, req.queryParams.page); - res.data.body = this.renderSkinAsString("$Members#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Site Subscribers"); + res.data.list = renderList(this.subscribers, + "$Membership#member", 10, req.queryParams.page); + res.data.pager = renderPager(this.subscribers, + this.href(req.action), 10, req.queryParams.page); + res.data.body = this.renderSkinAsString("$Members#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.updated_action = function() { - res.data.title = gettext("Updates"); - res.data.list = session.user.renderSkinAsString("$User#sites"); - res.data.body = session.user.renderSkinAsString("$User#subscriptions"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Updates"); + res.data.list = session.user.renderSkinAsString("$User#sites"); + res.data.body = session.user.renderSkinAsString("$User#subscriptions"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.privileges_action = function() { - var site = res.handlers.site; - res.data.title = gettext("Privileges"); - res.data.list = renderList(session.user.memberships, function(item) { - res.handlers.subscription = item.site; - item.renderSkin("$Membership#subscription"); - return; - }); - res.handlers.site = site; - res.data.body = session.user.renderSkinAsString("$User#subscriptions"); - res.handlers.site.renderSkin("Site#page"); - return; + var site = res.handlers.site; + res.data.title = gettext("Privileges"); + res.data.list = renderList(session.user.memberships, function(item) { + res.handlers.subscription = item.site; + item.renderSkin("$Membership#subscription"); + return; + }); + res.handlers.site = site; + res.data.body = session.user.renderSkinAsString("$User#subscriptions"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.subscriptions_action = function() { - var site = res.handlers.site; - res.data.title = gettext("Subscriptions"); - res.data.list = renderList(session.user.subscriptions, function(item) { - res.handlers.subscription = item.site; - item.renderSkin("$Membership#subscription"); - return; - }); - res.handlers.site = site; - res.data.body = session.user.renderSkinAsString("$User#subscriptions"); - res.handlers.site.renderSkin("Site#page"); - return; + var site = res.handlers.site; + res.data.title = gettext("Subscriptions"); + res.data.list = renderList(session.user.subscriptions, function(item) { + res.handlers.subscription = item.site; + item.renderSkin("$Membership#subscription"); + return; + }); + res.handlers.site = site; + res.data.body = session.user.renderSkinAsString("$User#subscriptions"); + res.handlers.site.renderSkin("Site#page"); + return; } Members.prototype.add_action = function() { - if (req.postParams.term) { - try { - var result = this.search(req.postParams.term); - if (result.length < 1) { - res.message = gettext("No user found to add as member."); - } else { - if (result.length >= 100) { - res.message = gettext("Too many users found, displaying the first {0} matches only.", - result.length); - } else { - res.message = ngettext("One user found.", "{0} users found.", - result.length); - } - res.data.result = this.renderSkinAsString("$Members#results", result); - } - } catch (ex) { - res.message = ex; - app.log(ex); + if (req.postParams.term) { + try { + var result = this.search(req.postParams.term); + if (result.length < 1) { + res.message = gettext("No user found to add as member."); + } else { + if (result.length >= 100) { + res.message = gettext("Too many users found, displaying the first {0} matches only.", + result.length); + } else { + res.message = ngettext("One user found.", "{0} users found.", + result.length); + } + res.data.result = this.renderSkinAsString("$Members#results", result); } - } else if (req.postParams.add) { - try { - var membership = this.addMembership(req.postParams); - membership.notify(req.action, membership.creator.email, - gettext('[{0}] Notification of membership change', root.title)); - res.message = gettext("Successfully added {0} to the list of members.", - req.postParams.name); - res.redirect(membership.href("edit")); - } catch (ex) { - res.message = ex; - app.log(ex); - } - res.redirect(this.href()); - } - res.data.action = this.href(req.action); - res.data.title = gettext('Add Member'); - res.data.body = this.renderSkinAsString("$Members#add"); - res.handlers.site.renderSkin("Site#page"); - return; + } catch (ex) { + res.message = ex; + app.log(ex); + } + } else if (req.postParams.add) { + try { + var membership = this.addMembership(req.postParams); + membership.notify(req.action, membership.creator.email, + gettext('[{0}] Notification of membership change', root.title)); + res.message = gettext("Successfully added {0} to the list of members.", + req.postParams.name); + res.redirect(membership.href("edit")); + } catch (ex) { + res.message = ex; + app.log(ex); + } + res.redirect(this.href()); + } + res.data.action = this.href(req.action); + res.data.title = gettext('Add Member'); + res.data.body = this.renderSkinAsString("$Members#add"); + res.handlers.site.renderSkin("Site#page"); + return; } /** @@ -355,27 +355,27 @@ Members.prototype.add_action = function() { * @returns {Object} */ Members.prototype.search = function(searchString) { - var self = this; - var mode = "="; - if (searchString.contains("*")) { - searchString = searchString.replace(/\*/g, "%"); - mode = "like"; - } - var sql = new Sql; - sql.retrieve(Sql.MEMBERSEARCH, mode, searchString, 100); - var counter = 0, name; - res.push(); - sql.traverse(function() { - // Check if the user is not already a member - if (!self.get(this.name)) { - self.renderSkin("$Members#result", {name: this.name}); - counter += 1; - } - }); - return { - result: res.pop(), - length: counter - }; + var self = this; + var mode = "="; + if (searchString.contains("*")) { + searchString = searchString.replace(/\*/g, "%"); + mode = "like"; + } + var sql = new Sql; + sql.retrieve(Sql.MEMBERSEARCH, mode, searchString, 100); + var counter = 0, name; + res.push(); + sql.traverse(function() { + // Check if the user is not already a member + if (!self.get(this.name)) { + self.renderSkin("$Members#result", {name: this.name}); + counter += 1; + } + }); + return { + result: res.pop(), + length: counter + }; } /** @@ -384,12 +384,12 @@ Members.prototype.search = function(searchString) { * @returns {Membership} */ Members.prototype.addMembership = function(data) { - var user = root.users.get(data.name); - if (!user) { - throw Error(gettext("Sorry, your input did not match any registered user.")); - } else if (this.get(data.name)) { - throw Error(gettext("This user is already a member of this site.")); - } - var membership = Membership.add(user, Membership.SUBSCRIBER, this._parent); - return membership; + var user = root.users.get(data.name); + if (!user) { + throw Error(gettext("Sorry, your input did not match any registered user.")); + } else if (this.get(data.name)) { + throw Error(gettext("This user is already a member of this site.")); + } + var membership = Membership.add(user, Membership.SUBSCRIBER, this._parent); + return membership; } diff --git a/code/Membership/Membership.js b/code/Membership/Membership.js index 89a974f8..04256056 100644 --- a/code/Membership/Membership.js +++ b/code/Membership/Membership.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -37,7 +37,7 @@ markgettext("membership"); * @returns {Membership} */ Membership.getByName = function(name, site) { - return (site || res.handlers.site).members.get(name); + return (site || res.handlers.site).members.get(name); } /** @@ -46,10 +46,10 @@ Membership.getByName = function(name, site) { * @returns {Boolean} */ Membership.require = function(role) { - if (res.handlers.membership) { - return res.handlers.membership.require(role); - } - return false; + if (res.handlers.membership) { + return res.handlers.membership.require(role); + } + return false; } /** @@ -58,7 +58,7 @@ Membership.require = function(role) { * @see defineConstants */ Membership.getRoles = defineConstants(Membership, markgettext("Subscriber"), - markgettext("Contributor"), markgettext("Manager"), markgettext("Owner")); + markgettext("Contributor"), markgettext("Manager"), markgettext("Owner")); /** @@ -67,13 +67,13 @@ Membership.getRoles = defineConstants(Membership, markgettext("Subscriber"), * @param {Site} site */ Membership.add = function(user, role, site) { - HopObject.confirmConstructor(Membership); - user || (user = session.user); - var membership = new Membership(user, role); - membership.created = new Date; - membership.touch(); - site.members.add(membership); - return membership; + HopObject.confirmConstructor(Membership); + user || (user = session.user); + var membership = new Membership(user, role); + membership.created = new Date; + membership.touch(); + site.members.add(membership); + return membership; } /** * @@ -81,20 +81,20 @@ Membership.add = function(user, role, site) { * @param {Object} options */ Membership.remove = function(options) { - options || (options = {}); - if (this.constructor !== Membership) { - return; - } - if (!options.force && !this.getPermission("delete")) { - throw Error(gettext("Sorry, an owner of a site cannot be removed.")); - } - var recipient = this.creator.email; - this.remove(); - if (!options.force) { - this.notify(req.action, recipient, - gettext("[{0}] Notification of membership cancellation", root.title)); - } - return; + options || (options = {}); + if (this.constructor !== Membership) { + return; + } + if (!options.force && !this.getPermission("delete")) { + throw Error(gettext("Sorry, an owner of a site cannot be removed.")); + } + var recipient = this.creator.email; + this.remove(); + if (!options.force) { + this.notify(req.action, recipient, + gettext("[{0}] Notification of membership cancellation", root.title)); + } + return; } /** @@ -118,16 +118,16 @@ Membership.remove = function(options) { * @extends HopObject */ Membership.prototype.constructor = function(user, role) { - HopObject.confirmConstructor(this); - user || (user = session.user); - if (user) { - this.map({ - creator: user, - name: user.name, - role: role - }); - } - return this; + HopObject.confirmConstructor(this); + user || (user = session.user); + if (user) { + this.map({ + creator: user, + name: user.name, + role: role + }); + } + return this; } /** @@ -136,18 +136,18 @@ Membership.prototype.constructor = function(user, role) { * @return {Boolean} */ Membership.prototype.getPermission = function(action) { - if (!res.handlers.site.getPermission("main")) { - return false; - } - switch (action) { - case "contact": - return true; - case "edit": - case "delete": - return User.require(User.PRIVILEGED) || - this.role !== Membership.OWNER || this.creator !== session.user; - } - return false; + if (!res.handlers.site.getPermission("main")) { + return false; + } + switch (action) { + case "contact": + return true; + case "edit": + case "delete": + return User.require(User.PRIVILEGED) || + this.role !== Membership.OWNER || this.creator !== session.user; + } + return false; } /** @@ -156,30 +156,30 @@ Membership.prototype.getPermission = function(action) { * @returns {Object} */ Membership.prototype.getFormOptions = function(name) { - switch (name) { - case "role": - return Membership.getRoles(); - } - return; + switch (name) { + case "role": + return Membership.getRoles(); + } + return; } Membership.prototype.edit_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this._parent.href()); - } catch(ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.save) { + try { + this.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this._parent.href()); + } catch(ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Edit Membership: {0}", this.name); - res.data.body = this.renderSkinAsString("$Membership#edit"); - this.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Edit Membership: {0}", this.name); + res.data.body = this.renderSkinAsString("$Membership#edit"); + this.site.renderSkin("Site#page"); + return; } /** @@ -187,55 +187,55 @@ Membership.prototype.edit_action = function() { * @param {Object} data */ Membership.prototype.update = function(data) { - if (!data.role) { - throw Error(gettext("Please choose a role for this member.")); - } else if (this.user === session.user) { - throw Error(gettext("Sorry, you are not allowed to edit your own membership.")); - } else if (data.role !== this.role) { - this.role = data.role || Membership.SUBSCRIBER; - this.touch(); - this.notify(req.action, this.creator.email, - gettext("[{0}] Notification of membership change", root.title)); - } - return; + if (!data.role) { + throw Error(gettext("Please choose a role for this member.")); + } else if (this.user === session.user) { + throw Error(gettext("Sorry, you are not allowed to edit your own membership.")); + } else if (data.role !== this.role) { + this.role = data.role || Membership.SUBSCRIBER; + this.touch(); + this.notify(req.action, this.creator.email, + gettext("[{0}] Notification of membership change", root.title)); + } + return; } Membership.prototype.contact_action = function() { - if (req.postParams.send) { - try { - if (!req.postParams.text) { - throw Error(gettext("Please enter the message text.")); - } - Feature.invoke("recaptcha", function() { - return this.verify(req.postParams); - }); - this.notify(req.action, this.creator.email, session.user ? - gettext('[{0}] Message from user {1}', root.title, session.user.name) : - gettext('[{0}] Message from anonymous user', root.title)); - res.message = gettext("Your message was sent successfully."); - res.redirect(this._parent.getPermission() ? - this._parent.href() : this.site.href()); - } catch(ex) { - res.message = ex; - app.log(ex); + if (req.postParams.send) { + try { + if (!req.postParams.text) { + throw Error(gettext("Please enter the message text.")); } - } + Feature.invoke("recaptcha", function() { + return this.verify(req.postParams); + }); + this.notify(req.action, this.creator.email, session.user ? + gettext('[{0}] Message from user {1}', root.title, session.user.name) : + gettext('[{0}] Message from anonymous user', root.title)); + res.message = gettext("Your message was sent successfully."); + res.redirect(this._parent.getPermission() ? + this._parent.href() : this.site.href()); + } catch(ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext('Contact User: {0}', this.name); - res.data.body = this.renderSkinAsString("$Membership#contact"); - this.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext('Contact User: {0}', this.name); + res.data.body = this.renderSkinAsString("$Membership#contact"); + this.site.renderSkin("Site#page"); + return; } Membership.prototype.content_action = function() { - res.data.list = renderList(this.content, "$Story#listItem", - 10, req.queryParams.page); - res.data.pager = renderPager(this.content, - this.href(), 10, req.queryParams.page); - res.data.title = gettext("Content of User: {0}", this.name); - res.data.body = this.renderSkinAsString("$Membership#content"); - this.site.renderSkin("Site#page"); + res.data.list = renderList(this.content, "$Story#listItem", + 10, req.queryParams.page); + res.data.pager = renderPager(this.content, + this.href(), 10, req.queryParams.page); + res.data.title = gettext("Content of User: {0}", this.name); + res.data.body = this.renderSkinAsString("$Membership#content"); + this.site.renderSkin("Site#page"); } /** @@ -244,11 +244,11 @@ Membership.prototype.content_action = function() { * @returns {HopObject} */ Membership.prototype.getMacroHandler = function(name) { - switch (name) { - case "user": - return this.creator; - } - return null; + switch (name) { + case "user": + return this.creator; + } + return null; } /** @@ -257,12 +257,12 @@ Membership.prototype.getMacroHandler = function(name) { * @returns {Boolean} */ Membership.prototype.require = function(role) { - var roles = [Membership.SUBSCRIBER, Membership.CONTRIBUTOR, - Membership.MANAGER, Membership.OWNER]; - if (role) { - return roles.indexOf(this.role) >= roles.indexOf(role); - } - return false; + var roles = [Membership.SUBSCRIBER, Membership.CONTRIBUTOR, + Membership.MANAGER, Membership.OWNER]; + if (role) { + return roles.indexOf(this.role) >= roles.indexOf(role); + } + return false; } /** @@ -272,33 +272,33 @@ Membership.prototype.require = function(role) { * @param {String} subject */ Membership.prototype.notify = function(action, recipient, subject) { - switch (action) { - case "add": - case "contact": - case "delete": - case "edit": - case "register": - res.handlers.sender = User.getMembership(); - sendMail(recipient, subject, this.renderSkinAsString("$Membership#notify_" + action), - {footer: action !== "contact"}); - break; - } - return; + switch (action) { + case "add": + case "contact": + case "delete": + case "edit": + case "register": + res.handlers.sender = User.getMembership(); + sendMail(recipient, subject, this.renderSkinAsString("$Membership#notify_" + action), + {footer: action !== "contact"}); + break; + } + return; } /** * @returns {String} */ Membership.prototype.getConfirmText = function() { - return gettext("You are about to delete the membership of user {0}.", - this.creator.name); + return gettext("You are about to delete the membership of user {0}.", + this.creator.name); } /** * @returns {String} */ Membership.prototype.toString = function() { - return (this.role || "Transient") + " membership of user " + this.name; + return (this.role || "Transient") + " membership of user " + this.name; } /** @@ -311,16 +311,16 @@ Membership.prototype.valueOf = Membership.prototype.toString; * */ Membership.prototype.status_macro = function() { - this.renderSkin(session.user ? "Membership#status" : "Membership#login"); - return; + this.renderSkin(session.user ? "Membership#status" : "Membership#login"); + return; } /** * */ Membership.prototype.role_macro = function() { - this.role && res.write(gettext(this.role.capitalize())); - return; + this.role && res.write(gettext(this.role.capitalize())); + return; } /** @@ -331,9 +331,9 @@ Membership.prototype.role_macro = function() { * @see HopObject#link_filter */ Membership.prototype.link_filter = function(value, param) { - if (!session.user || !session.user.url) { - return value; - } - return HopObject.prototype.link_filter.call(this, value, - param, session.user.url); // || this.href()); + if (!session.user || !session.user.url) { + return value; + } + return HopObject.prototype.link_filter.call(this, value, + param, session.user.url); // || this.href()); } diff --git a/code/Metadata/Metadata.js b/code/Metadata/Metadata.js index f2e78c03..70c1c9e7 100644 --- a/code/Metadata/Metadata.js +++ b/code/Metadata/Metadata.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,14 +34,14 @@ * @see Helma documentation */ Metadata.getTypeProperties = function() { - return { - collection: "Metadata", - "local.1": "$id", - "foreign.1": "parent_id", - "local.2": "$prototype", - "foreign.2": "parent_type", - accessName: "name" - } + return { + collection: "Metadata", + "local.1": "$id", + "foreign.1": "parent_id", + "local.2": "$prototype", + "foreign.2": "parent_type", + accessName: "name" + } } /** @@ -54,30 +54,30 @@ Metadata.getTypeProperties = function() { * the (normalized) metadata value and its type. */ Metadata.normalize = function(value) { - if (value === null || value === undefined) { - return [null, null]; - } + if (value === null || value === undefined) { + return [null, null]; + } - if (!value.constructor) { - value = String(value); - } + if (!value.constructor) { + value = String(value); + } - var Constructor = value.constructor; - switch (Constructor) { - case Boolean: - case String: - case Number: - value = String(value); - break; + var Constructor = value.constructor; + switch (Constructor) { + case Boolean: + case String: + case Number: + value = String(value); + break; - case Date: - value = Number(value); - break; + case Date: + value = Number(value); + break; - default: - value = value.toSource(); - } - return [value, Constructor.name]; + default: + value = value.toSource(); + } + return [value, Constructor.name]; } /** @@ -94,12 +94,12 @@ Metadata.normalize = function(value) { * @property {String} type The type of the metadata object. */ Metadata.prototype.constructor = function(parent, name, value) { - if (parent && name && value) { - this.parent = parent; - this.name = name; - this.setValue(value); - } - return this; + if (parent && name && value) { + this.parent = parent; + this.name = name; + this.setValue(value); + } + return this; } /** @@ -108,11 +108,11 @@ Metadata.prototype.constructor = function(parent, name, value) { * @param {Object} value The desired metadata value. */ Metadata.prototype.setValue = function(value) { - [this.value, this.type] = Metadata.normalize(value); - if (this.value === null) { - this.remove(); - } - return; + [this.value, this.type] = Metadata.normalize(value); + if (this.value === null) { + this.remove(); + } + return; } /** @@ -120,25 +120,25 @@ Metadata.prototype.setValue = function(value) { * @returns {Object} The value of the metadata object. */ Metadata.prototype.getValue = function() { - var Constructor = global[this.type]; - switch (Constructor) { - case null: - case undefined: - return null; + var Constructor = global[this.type]; + switch (Constructor) { + case null: + case undefined: + return null; - case Boolean: - return eval(this.value).valueOf(); + case Boolean: + return eval(this.value).valueOf(); - case Date: - return new Date(Number(this.value)); + case Date: + return new Date(Number(this.value)); - case Number: - case String: - return (new Constructor(this.value)).valueOf(); + case Number: + case String: + return (new Constructor(this.value)).valueOf(); - default: - return eval(this.value); - } + default: + return eval(this.value); + } } /** @@ -146,7 +146,7 @@ Metadata.prototype.getValue = function() { * @returns {String} A textual representation of the metadata object. */ Metadata.prototype.toString = function() { - return "Metadata of " + this.parent + " (" + this.name + " = " + this.value + ")"; + return "Metadata of " + this.parent + " (" + this.name + " = " + this.value + ")"; } /** @@ -156,5 +156,5 @@ Metadata.prototype.toString = function() { */ // FIXME: Is this obsolete? Metadata.prototype.onUnhandledMacro = function(name) { - return this.get(name); + return this.get(name); } diff --git a/code/Poll/Poll.js b/code/Poll/Poll.js index 15f38083..13488c3f 100644 --- a/code/Poll/Poll.js +++ b/code/Poll/Poll.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -42,24 +42,24 @@ Poll.getStatus = defineConstants(Poll, markgettext("closed"), markgettext("open" * @param {String} question */ Poll.add = function(data, site) { - HopObject.confirmConstructor(Poll); - var poll = new Poll; - poll.creator = session.user; - poll.created = new Date; - poll.update(data); - site.polls.add(poll); - return poll; + HopObject.confirmConstructor(Poll); + var poll = new Poll; + poll.creator = session.user; + poll.created = new Date; + poll.update(data); + site.polls.add(poll); + return poll; } /** * */ Poll.remove = function() { - if (this.constructor === Poll) { - HopObject.remove.call(this); - this.remove(); - } - return; + if (this.constructor === Poll) { + HopObject.remove.call(this); + this.remove(); + } + return; } /** @@ -79,8 +79,8 @@ Poll.remove = function() { * @extends HopObject */ Poll.prototype.constructor = function() { - HopObject.confirmConstructor(this); - return this; + HopObject.confirmConstructor(this); + return this; } /** @@ -89,25 +89,25 @@ Poll.prototype.constructor = function() { * @returns {Boolean} */ Poll.prototype.getPermission = function(action) { - if (!this.site.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - return !!session.user; - case "result": - return true; - case "edit": - return Membership.require(Membership.OWNER) || - User.require(User.PRIVILEGED); - case "rotate": - case "delete": - return this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - } - return false; + if (!this.site.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + return !!session.user; + case "result": + return true; + case "edit": + return Membership.require(Membership.OWNER) || + User.require(User.PRIVILEGED); + case "rotate": + case "delete": + return this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + } + return false; } /** @@ -116,33 +116,33 @@ Poll.prototype.getPermission = function(action) { * @returns {Object} */ Poll.prototype.getFormOptions = function(name) { - switch (name) { - case "status": - return Poll.getStatus(); - } - return; + switch (name) { + case "status": + return Poll.getStatus(); + } + return; } Poll.prototype.main_action = function() { - if (this.status !== Poll.OPEN) { + if (this.status !== Poll.OPEN) { + res.redirect(this.href("result")); + return; + } + if (req.postParams.vote) { + try { + this.vote(req.postParams); + res.message = gettext("Thanks, your vote was registered. You can change your mind until the poll is closed."); res.redirect(this.href("result")); - return; - } - if (req.postParams.vote) { - try { - this.vote(req.postParams); - res.message = gettext("Thanks, your vote was registered. You can change your mind until the poll is closed."); - res.redirect(this.href("result")); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - res.data.action = this.href(); - res.data.title = gettext("Poll: {0}", this.question); - res.data.body = this.renderSkinAsString("$Poll#main", {header: true}); - this.site.renderSkin("Site#page"); - return; + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.data.action = this.href(); + res.data.title = gettext("Poll: {0}", this.question); + res.data.body = this.renderSkinAsString("$Poll#main", {header: true}); + this.site.renderSkin("Site#page"); + return; } /** @@ -151,7 +151,7 @@ Poll.prototype.main_action = function() { */ Poll.prototype.vote = function(data) { if (!data.choice) { - throw Error(gettext("You did not vote, yet. You can vote until the poll is closed.")); + throw Error(gettext("You did not vote, yet. You can vote until the poll is closed.")); } var choice = this.get(data.choice); var vote = session.user && this.votes.get(session.user.name); @@ -159,27 +159,27 @@ Poll.prototype.vote = function(data) { vote.choice = choice; vote.modified = new Date; } else { - vote = Vote.add(choice, this); + vote = Vote.add(choice, this); } return vote; } Poll.prototype.edit_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - res.message = gettext("The poll was updated successfully."); - res.redirect(this.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - res.data.action = this.href(req.action); - res.data.title = gettext("Edit Poll: {0}", this.question); - res.data.body = this.renderSkinAsString("$Poll#edit"); - this.site.renderSkin("Site#page"); - return; + if (req.postParams.save) { + try { + this.update(req.postParams); + res.message = gettext("The poll was updated successfully."); + res.redirect(this.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.data.action = this.href(req.action); + res.data.title = gettext("Edit Poll: {0}", this.question); + res.data.body = this.renderSkinAsString("$Poll#edit"); + this.site.renderSkin("Site#page"); + return; } /** @@ -187,66 +187,66 @@ Poll.prototype.edit_action = function() { * @param {Object} data */ Poll.prototype.update = function(data) { - var choices = []; - for each (var title in data.title_array) { - if (title = title.trim()) { - choices.push(title); - } - } - if (choices.length < 2 || !data.question) { - throw Error(gettext("Please fill out the whole form to create a valid poll.")); - } - var size = this.size(); - // Update or remove choices - for (var i=size-1; i>-1; i-=1) { - var choice = this.get(i); - var title = choices[i]; - if (title) { - choice.title = title; - choice.touch(); - } else { - Choice.remove.call(choice); - } - } - // Add new choices - for (var i=size; i-1; i-=1) { + var choice = this.get(i); + var title = choices[i]; + if (title) { + choice.title = title; + choice.touch(); + } else { + Choice.remove.call(choice); + } + } + // Add new choices + for (var i=size; i Date.ONEHOUR)) { - var sites = this.sites.list(); - sites.sort(new String.Sorter("title")); - this.cache.sites = {list: sites, modified: now}; - } - res.data.list = renderList(this.cache.sites.list, - "$Site#listItem", 25, req.queryParams.page); - res.data.pager = renderPager(this.cache.sites.list, - this.href(req.action), 25, req.queryParams.page); - res.data.title = gettext("Public Sites"); - res.data.body = this.renderSkinAsString("$Root#sites"); - root.renderSkin("Site#page"); - return; + var now = new Date; + if (!this.cache.sites || (now - this.cache.sites.modified > Date.ONEHOUR)) { + var sites = this.sites.list(); + sites.sort(new String.Sorter("title")); + this.cache.sites = {list: sites, modified: now}; + } + res.data.list = renderList(this.cache.sites.list, + "$Site#listItem", 25, req.queryParams.page); + res.data.pager = renderPager(this.cache.sites.list, + this.href(req.action), 25, req.queryParams.page); + res.data.title = gettext("Public Sites"); + res.data.body = this.renderSkinAsString("$Root#sites"); + root.renderSkin("Site#page"); + return; } Root.prototype.updates_xml_action = function() { - res.contentType = "application/rss+xml"; - var now = new Date; - var feed = new rome.SyndFeedImpl(); - feed.setFeedType("rss_2.0"); - feed.setLink(root.href()); - feed.setTitle("Recently updated sites at " + root.title); - feed.setDescription(root.tagline || String.EMPTY); - feed.setLanguage(root.locale.replace("_", "-")); - feed.setPublishedDate(now); - var entries = new java.util.ArrayList(); - var entry, description; - var sites = root.updates.list(0, 25).sort(Number.Sorter("modified", - Number.Sorter.DESC)); - for each (var site in sites) { - entry = new rome.SyndEntryImpl(); - entry.setTitle(site.title); - entry.setLink(site.href()); - entry.setAuthor(site.creator.name); - entry.setPublishedDate(site.modified); - description = new rome.SyndContentImpl(); - description.setType("text/plain"); - description.setValue(site.tagline); - entry.setDescription(description); - entries.add(entry); - } - feed.setEntries(entries); - var output = new rome.SyndFeedOutput(); - //output.output(feed, res.servletResponse.writer); return; - var xml = output.outputString(feed); - res.write(xml); //injectXslDeclaration(xml)); - return; + res.contentType = "application/rss+xml"; + var now = new Date; + var feed = new rome.SyndFeedImpl(); + feed.setFeedType("rss_2.0"); + feed.setLink(root.href()); + feed.setTitle("Recently updated sites at " + root.title); + feed.setDescription(root.tagline || String.EMPTY); + feed.setLanguage(root.locale.replace("_", "-")); + feed.setPublishedDate(now); + var entries = new java.util.ArrayList(); + var entry, description; + var sites = root.updates.list(0, 25).sort(Number.Sorter("modified", + Number.Sorter.DESC)); + for each (var site in sites) { + entry = new rome.SyndEntryImpl(); + entry.setTitle(site.title); + entry.setLink(site.href()); + entry.setAuthor(site.creator.name); + entry.setPublishedDate(site.modified); + description = new rome.SyndContentImpl(); + description.setType("text/plain"); + description.setValue(site.tagline); + entry.setDescription(description); + entries.add(entry); + } + feed.setEntries(entries); + var output = new rome.SyndFeedOutput(); + //output.output(feed, res.servletResponse.writer); return; + var xml = output.outputString(feed); + res.write(xml); //injectXslDeclaration(xml)); + return; } // Sitemap for Google Webmaster Tools // (Unfortunately, utterly useless.) Root.prototype.sitemap_xml_action = function() { - res.contentType = "text/xml"; - res.writeln(''); - res.writeln(''); - this.sites.forEach(function() { - res.writeln(''); - res.writeln('' + this.href() + ''); - if (this.modified) { - res.writeln('' + this.modified.format("yyyy-MM-dd") + ''); - } - res.writeln(''); - }); - res.writeln(''); - return; + res.contentType = "text/xml"; + res.writeln(''); + res.writeln(''); + this.sites.forEach(function() { + res.writeln(''); + res.writeln('' + this.href() + ''); + if (this.modified) { + res.writeln('' + this.modified.format("yyyy-MM-dd") + ''); + } + res.writeln(''); + }); + res.writeln(''); + return; } Root.prototype.health_action = function() { - var jvm = java.lang.Runtime.getRuntime(); - var totalMemory = jvm.totalMemory() / 1024 / 1024; - var freeMemory = jvm.freeMemory() / 1024 / 1024; + var jvm = java.lang.Runtime.getRuntime(); + var totalMemory = jvm.totalMemory() / 1024 / 1024; + var freeMemory = jvm.freeMemory() / 1024 / 1024; - var param = { - uptime: formatNumber((new Date - app.upSince.getTime()) / - Date.ONEDAY, "0.##"), - freeMemory: formatNumber(freeMemory), - totalMemory: formatNumber(totalMemory), - usedMemory: formatNumber(totalMemory - freeMemory), - sessions: formatNumber(app.countSessions()), - cacheSize: formatNumber(getProperty("cacheSize")) - }; + var param = { + uptime: formatNumber((new Date - app.upSince.getTime()) / + Date.ONEDAY, "0.##"), + freeMemory: formatNumber(freeMemory), + totalMemory: formatNumber(totalMemory), + usedMemory: formatNumber(totalMemory - freeMemory), + sessions: formatNumber(app.countSessions()), + cacheSize: formatNumber(getProperty("cacheSize")) + }; - for each (key in ["activeThreads", "freeThreads", "requestCount", - "errorCount", "xmlrpcCount", "cacheusage"]) { - param[key] = formatNumber(app[key]); - } + for each (key in ["activeThreads", "freeThreads", "requestCount", + "errorCount", "xmlrpcCount", "cacheusage"]) { + param[key] = formatNumber(app[key]); + } - param.errorRatio = formatNumber(100 * app.errorCount / app.requestCount || 0); - param.errorRatioPerUnit = formatNumber(Admin.health.errorsPerUnit / Admin.health.requestsPerUnit || 0); - if (Admin.health) { - param.requestsPerUnit = formatNumber(Admin.health.requestsPerUnit); - param.errorsPerUnit = formatNumber(Admin.health.errorsPerUnit); - } + param.errorRatio = formatNumber(100 * app.errorCount / app.requestCount || 0); + param.errorRatioPerUnit = formatNumber(Admin.health.errorsPerUnit / Admin.health.requestsPerUnit || 0); + if (Admin.health) { + param.requestsPerUnit = formatNumber(Admin.health.requestsPerUnit); + param.errorsPerUnit = formatNumber(Admin.health.errorsPerUnit); + } - param.entries = app.data.entries.length; - param.mails = app.data.mails.length; - param.requests = 0; - for (var i in app.data.requests) { - param.requests += 1; - } - param.callbacks = app.data.callbacks.length; + param.entries = app.data.entries.length; + param.mails = app.data.mails.length; + param.requests = 0; + for (var i in app.data.requests) { + param.requests += 1; + } + param.callbacks = app.data.callbacks.length; - res.data.title = gettext("{0} Health", root.getTitle()); - res.data.body = this.renderSkinAsString("$Root#health", param); - this.renderSkin("Site#page"); + res.data.title = gettext("{0} Health", root.getTitle()); + res.data.body = this.renderSkinAsString("$Root#health", param); + this.renderSkin("Site#page"); } Root.prototype.mrtg_action = function() { - res.contentType = "text/plain"; - var target = req.queryParams.target; - if (!target) { - return; - } - switch (target) { - case "cache": - res.writeln(0); - res.writeln(app.cacheusage * 100 / getProperty("cacheSize", 100)); - break; - case "threads": - res.writeln(0); - res.writeln(app.activeThreads * 100 / app.freeThreads); - break; - case "requests": - res.writeln(app.errorCount); - res.writeln(app.requestCount); - break; - case "users": - res.writeln(app.countSessions()); - res.writeln(root.users.size()); - break; - case "postings": - res.writeln(0); - var sql = new Sql; - sql.retrieve(Sql.COUNT, "content"); - sql.traverse(function() { - res.writeln(this.count); - }); - break; - case "uploads": - var sql = new Sql; - sql.retrieve(Sql.COUNT, "file"); - sql.traverse(function() { - res.writeln(this.count); - }); - sql.retrieve(Sql.COUNT, "image"); - sql.traverse(function() { - res.writeln(this.count); - }); - break; - } - res.writeln(app.upSince); - res.writeln("mrtg." + target + " of Antville version " + Root.VERSION); - return; + res.contentType = "text/plain"; + var target = req.queryParams.target; + if (!target) { + return; + } + switch (target) { + case "cache": + res.writeln(0); + res.writeln(app.cacheusage * 100 / getProperty("cacheSize", 100)); + break; + case "threads": + res.writeln(0); + res.writeln(app.activeThreads * 100 / app.freeThreads); + break; + case "requests": + res.writeln(app.errorCount); + res.writeln(app.requestCount); + break; + case "users": + res.writeln(app.countSessions()); + res.writeln(root.users.size()); + break; + case "postings": + res.writeln(0); + var sql = new Sql; + sql.retrieve(Sql.COUNT, "content"); + sql.traverse(function() { + res.writeln(this.count); + }); + break; + case "uploads": + var sql = new Sql; + sql.retrieve(Sql.COUNT, "file"); + sql.traverse(function() { + res.writeln(this.count); + }); + sql.retrieve(Sql.COUNT, "image"); + sql.traverse(function() { + res.writeln(this.count); + }); + break; + } + res.writeln(app.upSince); + res.writeln("mrtg." + target + " of Antville version " + Root.VERSION); + return; } /** @@ -338,13 +338,13 @@ Root.prototype.mrtg_action = function() { * @see Site#getMacroHandler */ Root.prototype.getMacroHandler = function(name) { - switch (name) { - case "admin": - case "api": - case "sites": - return this[name]; - } - return Site.prototype.getMacroHandler.apply(this, arguments); + switch (name) { + case "admin": + case "api": + case "sites": + return this[name]; + } + return Site.prototype.getMacroHandler.apply(this, arguments); } /** @@ -354,54 +354,54 @@ Root.prototype.getMacroHandler = function(name) { * @see Site#getFormOptions */ Root.prototype.getFormOptions = function(name) { - switch (name) { - case "creationScope": - return Admin.getCreationScopes(); - case "notificationScope": - return Admin.getNotificationScopes(); - case "phaseOutMode": - return Admin.getPhaseOutModes(); - } - return Site.prototype.getFormOptions.apply(root, arguments); + switch (name) { + case "creationScope": + return Admin.getCreationScopes(); + case "notificationScope": + return Admin.getNotificationScopes(); + case "phaseOutMode": + return Admin.getPhaseOutModes(); + } + return Site.prototype.getFormOptions.apply(root, arguments); } /** * @returns {Boolean} */ Root.prototype.getCreationPermission = function() { - var user; - if (!(user = session.user)) { - return false; - } if (User.require(User.PRIVILEGED)) { - return true; - } + var user; + if (!(user = session.user)) { + return false; + } if (User.require(User.PRIVILEGED)) { + return true; + } - switch (root.creationScope) { - case User.PRIVILEGED: - return false; - case User.TRUSTED: - return User.require(User.TRUSTED); - default: - case User.REGULAR: - var now = new Date, delta; - if (root.probationPeriod) { - delta = root.probationPeriod - Math.floor((now - - user.created) / Date.ONEDAY); - if (delta > 0) { - session.data.error = gettext("You need to wait {0} before you are allowed to create a new site.", - ngettext("{0} day", "{0} days", delta)); - return false; - } + switch (root.creationScope) { + case User.PRIVILEGED: + return false; + case User.TRUSTED: + return User.require(User.TRUSTED); + default: + case User.REGULAR: + var now = new Date, delta; + if (root.probationPeriod) { + delta = root.probationPeriod - Math.floor((now - + user.created) / Date.ONEDAY); + if (delta > 0) { + session.data.error = gettext("You need to wait {0} before you are allowed to create a new site.", + ngettext("{0} day", "{0} days", delta)); + return false; } - if (root.creationDelay && user.sites.count() > 0) { - delta = root.creationDelay - Math.floor((now - - user.sites.get(0).created) / Date.ONEDAY); - if (delta > 0) { - session.data.error = gettext("You need to wait {0} before you are allowed to create a new site.", - ngettext("{0} day", "{0} days", delta)); - return false; - } + } + if (root.creationDelay && user.sites.count() > 0) { + delta = root.creationDelay - Math.floor((now - + user.sites.get(0).created) / Date.ONEDAY); + if (delta > 0) { + session.data.error = gettext("You need to wait {0} before you are allowed to create a new site.", + ngettext("{0} day", "{0} days", delta)); + return false; } - } - return true; + } + } + return true; } diff --git a/code/Site/Site.js b/code/Site/Site.js index 33dd17bb..12509f7a 100644 --- a/code/Site/Site.js +++ b/code/Site/Site.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -56,51 +56,51 @@ this.handleMetadata("title"); * @see defineConstants */ Site.getStatus = defineConstants(Site, markgettext("Blocked"), - markgettext("Regular"), markgettext("Trusted")); + markgettext("Regular"), markgettext("Trusted")); /** * @function * @returns {String[]} * @see defineConstants */ Site.getModes = defineConstants(Site, markgettext("Deleted"), - markgettext("Closed"), markgettext("Restricted"), - markgettext("Public"), markgettext("Open")); + markgettext("Closed"), markgettext("Restricted"), + markgettext("Public"), markgettext("Open")); /** * @function * @returns {String[]} * @see defineConstants */ Site.getPageModes = defineConstants(Site, markgettext("days") /* , - markgettext("stories") */ ); + markgettext("stories") */ ); /** * @function * @returns {String[]} * @see defineConstants */ Site.getCommentModes = defineConstants(Site, markgettext("disabled"), - markgettext("enabled")); + markgettext("enabled")); /** * @function * @returns {String[]} * @see defineConstants */ Site.getArchiveModes = defineConstants(Site, markgettext("closed"), - markgettext("public")); + markgettext("public")); /** * @function * @returns {String[]} * @see defineConstants */ Site.getNotificationModes = defineConstants(Site, markgettext("Nobody"), - markgettext("Owner"), markgettext("Manager"), markgettext("Contributor"), - markgettext("Subscriber")); + markgettext("Owner"), markgettext("Manager"), markgettext("Contributor"), + markgettext("Subscriber")); /** * @function * @returns {String[]} * @see defineConstants */ Site.getCallbackModes = defineConstants(Site, markgettext("disabled"), - markgettext("enabled")); + markgettext("enabled")); /** * @param {String} name A unique identifier also used in the URL of a site @@ -108,48 +108,48 @@ Site.getCallbackModes = defineConstants(Site, markgettext("disabled"), * @param {User} user */ Site.add = function(data, user) { - HopObject.confirmConstructor(Site); + HopObject.confirmConstructor(Site); - var now = new Date; - var user = user || session.user || {}; - var site = new Site; + var now = new Date; + var user = user || session.user || {}; + var site = new Site; - if (!data.name) { - throw Error(gettext("Please enter a name for your new site.")); - } + if (!data.name) { + throw Error(gettext("Please enter a name for your new site.")); + } - if (data.name.length > 30) { - throw Error(gettext("The chosen name is too long. Please enter a shorter one.")); - } + if (data.name.length > 30) { + throw Error(gettext("The chosen name is too long. Please enter a shorter one.")); + } - var name = stripTags(decodeURIComponent(data.name)); - if (name !== data.name || /[^\u00a0-\uffff\w\-]/.test(data.name)) { - // We check if name can be used in vhost environment by allowing all Unicode characters - // but only ASCII letters A—z, digits 0—9, the underscore “_” and the hyphen “-”. - throw Error(gettext("Please avoid special characters or HTML code in the name field.")); - } else if (name !== root.getAccessName(name)) { - throw Error(gettext("There already is a site with this name.")); - } + var name = stripTags(decodeURIComponent(data.name)); + if (name !== data.name || /[^\u00a0-\uffff\w\-]/.test(data.name)) { + // We check if name can be used in vhost environment by allowing all Unicode characters + // but only ASCII letters A—z, digits 0—9, the underscore “_” and the hyphen “-”. + throw Error(gettext("Please avoid special characters or HTML code in the name field.")); + } else if (name !== root.getAccessName(name)) { + throw Error(gettext("There already is a site with this name.")); + } - site.name = java.net.IDN.toASCII.constructor === Function ? - java.net.IDN.toASCII(name, java.net.IDN.ALLOW_UNASSIGNED) : name; - site.title = data.title || name; + site.name = java.net.IDN.toASCII.constructor === Function ? + java.net.IDN.toASCII(name, java.net.IDN.ALLOW_UNASSIGNED) : name; + site.title = data.title || name; - site.map({ - created: now, - creator: user, - modified: now, - modifier: user, - status: user.status === User.PRIVILEGED ? Site.TRUSTED : user.status, - mode: Site.CLOSED, - commentMode: Site.ENABLED, - archiveMode: Site.PUBLIC - }); + site.map({ + created: now, + creator: user, + modified: now, + modifier: user, + status: user.status === User.PRIVILEGED ? Site.TRUSTED : user.status, + mode: Site.CLOSED, + commentMode: Site.ENABLED, + archiveMode: Site.PUBLIC + }); - site.update(site); - Layout.add(site); - root.add(site); - return site; + site.update(site); + Layout.add(site); + root.add(site); + return site; } /** @@ -157,28 +157,28 @@ Site.add = function(data, user) { * @param {Site} site */ Site.remove = function() { - if (this.constructor === Site || this === root) { - HopObject.remove.call(this.stories); - HopObject.remove.call(this.images); - HopObject.remove.call(this.files); - HopObject.remove.call(this.polls); - HopObject.remove.call(this.entries); - HopObject.remove.call(this.members, {force: true}); - // The root site needs some special treatment (it will not be removed) - if (this === root) { - Membership.add(root.users.get(0), Membership.OWNER, this); - Layout.remove.call(this.layout); - this.layout.reset(); - this.getStaticFile("images").removeDirectory(); - this.getStaticFile("files").removeDirectory(); - } else { - Layout.remove.call(this.layout, {force: true}); - this.getStaticFile().removeDirectory(); - this.deleteMetadata(); - this.remove(); - } - } - return; + if (this.constructor === Site || this === root) { + HopObject.remove.call(this.stories); + HopObject.remove.call(this.images); + HopObject.remove.call(this.files); + HopObject.remove.call(this.polls); + HopObject.remove.call(this.entries); + HopObject.remove.call(this.members, {force: true}); + // The root site needs some special treatment (it will not be removed) + if (this === root) { + Membership.add(root.users.get(0), Membership.OWNER, this); + Layout.remove.call(this.layout); + this.layout.reset(); + this.getStaticFile("images").removeDirectory(); + this.getStaticFile("files").removeDirectory(); + } else { + Layout.remove.call(this.layout, {force: true}); + this.getStaticFile().removeDirectory(); + this.deleteMetadata(); + this.remove(); + } + } + return; } /** @@ -187,7 +187,7 @@ Site.remove = function() { * @returns {Site} */ Site.getByName = function(name) { - return root.get(name); + return root.get(name); } /** @@ -196,8 +196,8 @@ Site.getByName = function(name) { * @returns {Boolean} */ Site.require = function(mode) { - var modes = [Site.CLOSED, Site.RESTRICTED, Site.PUBLIC, Site.OPEN]; - return modes.indexOf(res.handlers.site.mode) >= modes.indexOf(mode); + var modes = [Site.CLOSED, Site.RESTRICTED, Site.PUBLIC, Site.OPEN]; + return modes.indexOf(res.handlers.site.mode) >= modes.indexOf(mode); } /** @@ -238,8 +238,8 @@ Site.require = function(mode) { * @extends HopObject */ Site.prototype.constructor = function() { - HopObject.confirmConstructor(this); - return this; + HopObject.confirmConstructor(this); + return this; } /** @@ -248,81 +248,81 @@ Site.prototype.constructor = function() { * @returns {Boolean} */ Site.prototype.getPermission = function(action) { - switch (action) { - case "backup.js": - case "main.js": - case "main.css": - case "error": - case "notfound": - case "robots.txt": - case "search.xml": - case "user.js": - return true; + switch (action) { + case "backup.js": + case "main.js": + case "main.css": + case "error": + case "notfound": + case "robots.txt": + case "search.xml": + case "user.js": + return true; - case ".": - case "main": - case "comments.xml": - case "rss.xml": - case "rss.xsl": - case "search": - case "stories.xml": - return Site.require(Site.PUBLIC) || - (Site.require(Site.RESTRICTED) && - Membership.require(Membership.CONTRIBUTOR)) || - ((Site.require(Site.DELETED) || Site.require(Site.CLOSED)) && - Membership.require(Membership.OWNER)) || - User.require(User.PRIVILEGED); + case ".": + case "main": + case "comments.xml": + case "rss.xml": + case "rss.xsl": + case "search": + case "stories.xml": + return Site.require(Site.PUBLIC) || + (Site.require(Site.RESTRICTED) && + Membership.require(Membership.CONTRIBUTOR)) || + ((Site.require(Site.DELETED) || Site.require(Site.CLOSED)) && + Membership.require(Membership.OWNER)) || + User.require(User.PRIVILEGED); - case "edit": - case "export": - case "referrers": - return Membership.require(Membership.OWNER) || - User.require(User.PRIVILEGED); + case "edit": + case "export": + case "referrers": + return Membership.require(Membership.OWNER) || + User.require(User.PRIVILEGED); - case "subscribe": - return Site.require(Site.PUBLIC) && - User.require(User.REGULAR) && - !Membership.require(Membership.SUBSCRIBER); + case "subscribe": + return Site.require(Site.PUBLIC) && + User.require(User.REGULAR) && + !Membership.require(Membership.SUBSCRIBER); - case "unsubscribe": - if (User.require(User.REGULAR)) { - var membership = Membership.getByName(session.user.name, this); - return membership && !membership.require(Membership.OWNER); - } + case "unsubscribe": + if (User.require(User.REGULAR)) { + var membership = Membership.getByName(session.user.name, this); + return membership && !membership.require(Membership.OWNER); + } - case "import": - return User.require(User.PRIVILEGED); - } + case "import": + return User.require(User.PRIVILEGED); + } - return Feature.getPermission.apply(this, arguments); + return Feature.getPermission.apply(this, arguments); } Site.prototype.main_action = function() { - res.data.body = this.renderSkinAsString(this.mode === Site.DELETED ? - "$Site#deleted" : "Site#main"); - res.data.title = this.getTitle(); - this.renderSkin("Site#page"); - this.log(); - return; + res.data.body = this.renderSkinAsString(this.mode === Site.DELETED ? + "$Site#deleted" : "Site#main"); + res.data.title = this.getTitle(); + this.renderSkin("Site#page"); + this.log(); + return; } Site.prototype.edit_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - res.redirect(this.href(req.action)); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.save) { + try { + this.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + res.redirect(this.href(req.action)); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Site Preferences"); - res.data.body = this.renderSkinAsString("$Site#edit"); - this.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Site Preferences"); + res.data.body = this.renderSkinAsString("$Site#edit"); + this.renderSkin("Site#page"); + return; } /** @@ -331,30 +331,30 @@ Site.prototype.edit_action = function() { * @returns {Object} */ Site.prototype.getFormOptions = function(name) { - switch (name) { - case "archiveMode": - return Site.getArchiveModes(); - case "commentMode": - return Site.getCommentModes(); - case "locale": - return getLocales(this.getLocale()); - case "layout": - return this.getLayouts(); - case "mode": - return Site.getModes(); - case "notificationMode": - return Site.getNotificationModes(); - case "pageMode": - return Site.getPageModes(); - case "status": - return Site.getStatus(); - case "timeZone": - return getTimeZones(this.getLocale()); - case "callbackMode": - return Site.getCallbackModes(); - default: - return HopObject.prototype.getFormOptions.apply(this, arguments); - } + switch (name) { + case "archiveMode": + return Site.getArchiveModes(); + case "commentMode": + return Site.getCommentModes(); + case "locale": + return getLocales(this.getLocale()); + case "layout": + return this.getLayouts(); + case "mode": + return Site.getModes(); + case "notificationMode": + return Site.getNotificationModes(); + case "pageMode": + return Site.getPageModes(); + case "status": + return Site.getStatus(); + case "timeZone": + return getTimeZones(this.getLocale()); + case "callbackMode": + return Site.getCallbackModes(); + default: + return HopObject.prototype.getFormOptions.apply(this, arguments); + } } /** @@ -362,129 +362,129 @@ Site.prototype.getFormOptions = function(name) { * @param {Object} data */ Site.prototype.update = function(data) { - if (this.mode !== Site.DELETED && data.mode === Site.DELETED) { - this.deleted = new Date; - } else if (this.job && this.mode === Site.DELETED && data.mode !== Site.DELETED) { - var job = new Admin.Job(this.job); - job.remove(); - this.job = null; - } + if (this.mode !== Site.DELETED && data.mode === Site.DELETED) { + this.deleted = new Date; + } else if (this.job && this.mode === Site.DELETED && data.mode !== Site.DELETED) { + var job = new Admin.Job(this.job); + job.remove(); + this.job = null; + } - this.map({ - title: stripTags(data.title) || this.name, - tagline: data.tagline || '', - mode: data.mode || Site.CLOSED, - callbackUrl: data.callbackUrl || this.callbackUrl || '', - callbackMode: data.callbackMode || Site.DISABLED, - pageMode: data.pageMode || Site.DAYS, - pageSize: parseInt(data.pageSize, 10) || 3, - commentMode: data.commentMode || Site.DISABLED, - archiveMode: data.archiveMode || Site.CLOSED, - notificationMode: data.notificationMode || Site.NOBODY, - timeZone: data.timeZone || root.getTimeZone().getID(), - locale: data.locale || root.getLocale().toString(), - spamfilter: data.spamfilter || '' - }); + this.map({ + title: stripTags(data.title) || this.name, + tagline: data.tagline || '', + mode: data.mode || Site.CLOSED, + callbackUrl: data.callbackUrl || this.callbackUrl || '', + callbackMode: data.callbackMode || Site.DISABLED, + pageMode: data.pageMode || Site.DAYS, + pageSize: parseInt(data.pageSize, 10) || 3, + commentMode: data.commentMode || Site.DISABLED, + archiveMode: data.archiveMode || Site.CLOSED, + notificationMode: data.notificationMode || Site.NOBODY, + timeZone: data.timeZone || root.getTimeZone().getID(), + locale: data.locale || root.getLocale().toString(), + spamfilter: data.spamfilter || '' + }); - this.configured = new Date; - this.modifier = session.user; - this.clearCache(); - return; + this.configured = new Date; + this.modifier = session.user; + this.clearCache(); + return; } Site.prototype.main_css_action = function() { - res.contentType = "text/css"; - res.dependsOn(String(Root.VERSION)); - res.dependsOn(this.layout.modified); - HopObject.confirmConstructor(Skin); - res.dependsOn((new Skin("Site", "stylesheet")).getStaticFile().lastModified()); - res.digest(); - res.push(); - root.renderSkin("$Root#stylesheet"); - this.renderSkin("Site#stylesheet"); - var lessCss = res.pop(); - try { - lessParser.parse(lessCss, function(error, tree) { - if (error) { - res.writeln('/** '); - res.writeln(error.toSource()) - res.writeln('**/'); - res.writeln(lessCss); - return; - } - res.writeln(tree.toCSS()); - }); - } catch (ex) { - res.writeln('/** '); - res.writeln(ex.toSource()); - res.writeln('**/'); - res.writeln(lessCss); - } - return; + res.contentType = "text/css"; + res.dependsOn(String(Root.VERSION)); + res.dependsOn(this.layout.modified); + HopObject.confirmConstructor(Skin); + res.dependsOn((new Skin("Site", "stylesheet")).getStaticFile().lastModified()); + res.digest(); + res.push(); + root.renderSkin("$Root#stylesheet"); + this.renderSkin("Site#stylesheet"); + var lessCss = res.pop(); + try { + lessParser.parse(lessCss, function(error, tree) { + if (error) { + res.writeln('/** '); + res.writeln(error.toSource()) + res.writeln('**/'); + res.writeln(lessCss); + return; + } + res.writeln(tree.toCSS()); + }); + } catch (ex) { + res.writeln('/** '); + res.writeln(ex.toSource()); + res.writeln('**/'); + res.writeln(lessCss); + } + return; } Site.prototype.main_js_action = function() { - res.contentType = "text/javascript"; - res.dependsOn(String(Root.VERSION)); - res.digest(); - this.renderSkin("$Site#include", {href: "//ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"}); - this.renderSkin("$Site#include", {href: root.getStaticUrl("jquery.cookie.js")}); - this.renderSkin("$Site#include", {href: root.getStaticUrl("antville.js?v=" + Root.VERSION)}); - this.renderSkin("$Site#include", {href: this.href("user.js")}); - return; + res.contentType = "text/javascript"; + res.dependsOn(String(Root.VERSION)); + res.digest(); + this.renderSkin("$Site#include", {href: "//ajax.googleapis.com/ajax/libs/jquery/1.8/jquery.min.js"}); + this.renderSkin("$Site#include", {href: root.getStaticUrl("jquery.cookie.js")}); + this.renderSkin("$Site#include", {href: root.getStaticUrl("antville.js?v=" + Root.VERSION)}); + this.renderSkin("$Site#include", {href: this.href("user.js")}); + return; } Site.prototype.user_js_action = function() { - res.contentType = "text/javascript"; - HopObject.confirmConstructor(Skin); - res.dependsOn((new Skin("Site", "javascript")).getStaticFile().lastModified()); - res.digest(); - this.renderSkin("Site#javascript"); - return; + res.contentType = "text/javascript"; + HopObject.confirmConstructor(Skin); + res.dependsOn((new Skin("Site", "javascript")).getStaticFile().lastModified()); + res.digest(); + this.renderSkin("Site#javascript"); + return; } Site.prototype.backup_js_action = function() { - if (req.isPost()) { - var data = session.data.backup = {}; - for (var key in req.postParams) { - data[key] = req.postParams[key]; - } - } else { - res.contentType = "text/javascript"; - res.write(JSON.stringify(session.data.backup || {})); - session.data.backup = null; - } - return; + if (req.isPost()) { + var data = session.data.backup = {}; + for (var key in req.postParams) { + data[key] = req.postParams[key]; + } + } else { + res.contentType = "text/javascript"; + res.write(JSON.stringify(session.data.backup || {})); + session.data.backup = null; + } + return; } Site.prototype.rss_xml_action = function() { - res.contentType = "application/rss+xml"; - res.dependsOn(this.modified); - res.digest(); - res.write(this.getXml(this.stories.union)); - return; + res.contentType = "application/rss+xml"; + res.dependsOn(this.modified); + res.digest(); + res.write(this.getXml(this.stories.union)); + return; } Site.prototype.stories_xml_action = function() { - res.contentType = "application/rss+xml"; - res.dependsOn(this.modified); - res.digest(); - res.write(this.getXml(this.stories.recent)); - return; + res.contentType = "application/rss+xml"; + res.dependsOn(this.modified); + res.digest(); + res.write(this.getXml(this.stories.recent)); + return; } Site.prototype.comments_xml_action = function() { - res.contentType = "application/rss+xml"; - res.dependsOn(this.modified); - res.digest(); - res.write(this.getXml(this.stories.comments)); - return; + res.contentType = "application/rss+xml"; + res.dependsOn(this.modified); + res.digest(); + res.write(this.getXml(this.stories.comments)); + return; } Site.prototype.search_xml_action = function() { - res.contentType = "application/opensearchdescription+xml"; - this.renderSkin("$Site#opensearchdescription"); - return; + res.contentType = "application/opensearchdescription+xml"; + this.renderSkin("$Site#opensearchdescription"); + return; } /** @@ -492,264 +492,264 @@ Site.prototype.search_xml_action = function() { * @param {Story[]} collection */ Site.prototype.getXml = function(collection) { - collection || (collection = this.stories.recent); - var now = new Date; - var feed = new rome.SyndFeedImpl(); - feed.setFeedType("rss_2.0"); - feed.setLink(this.href()); - feed.setTitle(this.title); - feed.setDescription(this.tagline || String.EMPTY); - feed.setLanguage(this.locale.replace("_", "-")); - feed.setPublishedDate(now); + collection || (collection = this.stories.recent); + var now = new Date; + var feed = new rome.SyndFeedImpl(); + feed.setFeedType("rss_2.0"); + feed.setLink(this.href()); + feed.setTitle(this.title); + feed.setDescription(this.tagline || String.EMPTY); + feed.setLanguage(this.locale.replace("_", "-")); + feed.setPublishedDate(now); - /* - var feedInfo = new rome.FeedInformationImpl(); - var feedModules = new java.util.ArrayList(); - feedModules.add(feedInfo); - feed.setModules(feedModules); - //feedInfo.setImage(new java.net.URL(this.getProperty("imageUrl"))); - feedInfo.setSubtitle(this.tagline); - feedInfo.setSummary(this.description); - feedInfo.setAuthor(this.creator.name); - feedInfo.setOwnerName(this.creator.name); - //feedInfo.setOwnerEmailAddress(this.getProperty("email")); - */ + /* + var feedInfo = new rome.FeedInformationImpl(); + var feedModules = new java.util.ArrayList(); + feedModules.add(feedInfo); + feed.setModules(feedModules); + //feedInfo.setImage(new java.net.URL(this.getProperty("imageUrl"))); + feedInfo.setSubtitle(this.tagline); + feedInfo.setSummary(this.description); + feedInfo.setAuthor(this.creator.name); + feedInfo.setOwnerName(this.creator.name); + //feedInfo.setOwnerEmailAddress(this.getProperty("email")); + */ - var entry, entryInfo, entryModules; - var enclosure, enclosures, keywords; - var entries = new java.util.ArrayList(); - var description; + var entry, entryInfo, entryModules; + var enclosure, enclosures, keywords; + var entries = new java.util.ArrayList(); + var description; - var list = collection.constructor === Array ? - collection : collection.list(0, 25); - for each (var item in list) { - entry = new rome.SyndEntryImpl(); - entry.setTitle(item.title || formatDate(item.created, "date")); - entry.setLink(item.href()); - entry.setAuthor(item.creator.name); - entry.setPublishedDate(item.created); - if (item.text) { - description = new rome.SyndContentImpl(); - //description.setType("text/plain"); - // FIXME: Work-around for org.jdom.IllegalDataException caused by some ASCII control characters - description.setValue(item.renderSkinAsString("Story#rss").replace(/[\x00-\x1f^\x0a^\x0d]/g, function(c) { - return "&#" + c.charCodeAt(0) + ";"; - })); - entry.setDescription(description); - } - entries.add(entry); + var list = collection.constructor === Array ? + collection : collection.list(0, 25); + for each (var item in list) { + entry = new rome.SyndEntryImpl(); + entry.setTitle(item.title || formatDate(item.created, "date")); + entry.setLink(item.href()); + entry.setAuthor(item.creator.name); + entry.setPublishedDate(item.created); + if (item.text) { + description = new rome.SyndContentImpl(); + //description.setType("text/plain"); + // FIXME: Work-around for org.jdom.IllegalDataException caused by some ASCII control characters + description.setValue(item.renderSkinAsString("Story#rss").replace(/[\x00-\x1f^\x0a^\x0d]/g, function(c) { + return "&#" + c.charCodeAt(0) + ";"; + })); + entry.setDescription(description); + } + entries.add(entry); - /* - entryInfo = new rome.EntryInformationImpl(); - entryModules = new java.util.ArrayList(); - entryModules.add(entryInfo); - entry.setModules(entryModules); + /* + entryInfo = new rome.EntryInformationImpl(); + entryModules = new java.util.ArrayList(); + entryModules.add(entryInfo); + entry.setModules(entryModules); - enclosure = new rome.SyndEnclosureImpl(); - enclosure.setUrl(episode.getProperty("fileUrl")); - enclosure.setType(episode.getProperty("contentType")); - enclosure.setLength(episode.getProperty("filesize") || 0); - enclosures = new java.util.ArrayList(); - enclosures.add(enclosure); - entry.setEnclosures(enclosures); + enclosure = new rome.SyndEnclosureImpl(); + enclosure.setUrl(episode.getProperty("fileUrl")); + enclosure.setType(episode.getProperty("contentType")); + enclosure.setLength(episode.getProperty("filesize") || 0); + enclosures = new java.util.ArrayList(); + enclosures.add(enclosure); + entry.setEnclosures(enclosures); - entryInfo.setAuthor(entry.getAuthor()); - entryInfo.setBlock(false); - entryInfo.setDuration(new rome.Duration(episode.getProperty("length") || 0)); - entryInfo.setExplicit(false); - entryInfo.setKeywords(episode.getProperty("keywords")); - entryInfo.setSubtitle(episode.getProperty("subtitle")); - entryInfo.setSummary(episode.getProperty("description")); - */ - } - feed.setEntries(entries); + entryInfo.setAuthor(entry.getAuthor()); + entryInfo.setBlock(false); + entryInfo.setDuration(new rome.Duration(episode.getProperty("length") || 0)); + entryInfo.setExplicit(false); + entryInfo.setKeywords(episode.getProperty("keywords")); + entryInfo.setSubtitle(episode.getProperty("subtitle")); + entryInfo.setSummary(episode.getProperty("description")); + */ + } + feed.setEntries(entries); - var output = new rome.SyndFeedOutput(); - //output.output(feed, res.servletResponse.writer); return; - var xml = output.outputString(feed); - // FIXME: Ugly hack for adding PubSubHubbub and rssCloud elements to XML - xml = xml.replace("", '\n '); - xml = xml.replace("", '\n '); - return xml; //injectXslDeclaration(xml); + var output = new rome.SyndFeedOutput(); + //output.output(feed, res.servletResponse.writer); return; + var xml = output.outputString(feed); + // FIXME: Ugly hack for adding PubSubHubbub and rssCloud elements to XML + xml = xml.replace("", '\n '); + xml = xml.replace("", '\n '); + return xml; //injectXslDeclaration(xml); } Site.prototype.rss_xsl_action = function() { - res.charset = "UTF-8"; - res.contentType = "text/xml"; - renderSkin("Global#xslStylesheet"); - return; + res.charset = "UTF-8"; + res.contentType = "text/xml"; + renderSkin("Global#xslStylesheet"); + return; } Site.prototype.referrers_action = function() { - if (req.data.permanent && this.getPermission("edit")) { - var urls = req.data.permanent_array; - res.push(); - res.write(this.getMetadata("spamfilter")); - for (var i in urls) { - res.write("\n"); - res.write(urls[i].replace(/\?/g, "\\\\?")); - } - this.setMetadata("spamfilter", res.pop()); - res.redirect(this.href(req.action)); - return; - } - res.data.action = this.href(req.action); - res.data.title = gettext("Site Referrers"); - res.data.body = this.renderSkinAsString("$Site#referrers"); - this.renderSkin("Site#page"); - return; + if (req.data.permanent && this.getPermission("edit")) { + var urls = req.data.permanent_array; + res.push(); + res.write(this.getMetadata("spamfilter")); + for (var i in urls) { + res.write("\n"); + res.write(urls[i].replace(/\?/g, "\\\\?")); + } + this.setMetadata("spamfilter", res.pop()); + res.redirect(this.href(req.action)); + return; + } + res.data.action = this.href(req.action); + res.data.title = gettext("Site Referrers"); + res.data.body = this.renderSkinAsString("$Site#referrers"); + this.renderSkin("Site#page"); + return; } Site.prototype.search_action = function() { - var term = req.data.q && stripTags(decodeURIComponent(String(req.data.q))); - if (!term) { - res.message = gettext("Please enter a query in the search form."); - res.data.body = this.renderSkinAsString("Site#search"); - } else { - term = term.replace(/(?:\x22|\x27)/g, String.EMPTY); // Remove single and double ticks (aka false quotes) - var sql = new Sql({quote: false}); - sql.retrieve(Sql.SEARCH, this._id, term, 50); - res.push(); - var counter = 0; - sql.traverse(function() { - var content = Story.getById(this.id); - if (!content.story || (content.story.status !== Story.CLOSED && - content.story.commentMode !== Story.CLOSED)) { - content.renderSkin("Story#result"); - counter += 1; - } - }); - res.message = ngettext("Found {0} result.", "Found {0} results.", counter); - res.data.body = res.pop(); - } + var term = req.data.q && stripTags(decodeURIComponent(String(req.data.q))); + if (!term) { + res.message = gettext("Please enter a query in the search form."); + res.data.body = this.renderSkinAsString("Site#search"); + } else { + term = term.replace(/(?:\x22|\x27)/g, String.EMPTY); // Remove single and double ticks (aka false quotes) + var sql = new Sql({quote: false}); + sql.retrieve(Sql.SEARCH, this._id, term, 50); + res.push(); + var counter = 0; + sql.traverse(function() { + var content = Story.getById(this.id); + if (!content.story || (content.story.status !== Story.CLOSED && + content.story.commentMode !== Story.CLOSED)) { + content.renderSkin("Story#result"); + counter += 1; + } + }); + res.message = ngettext("Found {0} result.", "Found {0} results.", counter); + res.data.body = res.pop(); + } - res.data.title = gettext('Search results'); - this.renderSkin("Site#page"); - return; + res.data.title = gettext('Search results'); + this.renderSkin("Site#page"); + return; } Site.prototype.subscribe_action = function() { - try { - Membership.add(session.user, Membership.SUBSCRIBER, this); - res.message = gettext('Successfully subscribed to site {0}.', - this.title); - } catch (ex) { - app.log(ex); - res.message = ex.toString(); - } - res.redirect(this.href()); - return; + try { + Membership.add(session.user, Membership.SUBSCRIBER, this); + res.message = gettext('Successfully subscribed to site {0}.', + this.title); + } catch (ex) { + app.log(ex); + res.message = ex.toString(); + } + res.redirect(this.href()); + return; } Site.prototype.unsubscribe_action = function() { - if (req.postParams.proceed) { - try { - Membership.remove.call(Membership.getByName(session.user.name)); - res.message = gettext("Successfully unsubscribed from site {0}.", - this.title); - res.redirect(User.getLocation() || this.href()); - } catch (ex) { - app.log(ex) - res.message = ex.toString(); - } - } + if (req.postParams.proceed) { + try { + Membership.remove.call(Membership.getByName(session.user.name)); + res.message = gettext("Successfully unsubscribed from site {0}.", + this.title); + res.redirect(User.getLocation() || this.href()); + } catch (ex) { + app.log(ex) + res.message = ex.toString(); + } + } - User.setLocation(); - res.data.title = gettext("Confirm Unsubscribe"); - res.data.body = this.renderSkinAsString("$HopObject#confirm", { - text: gettext('You are about to unsubscribe from site {0}.', this.title) - }); - this.renderSkin("Site#page"); - return; + User.setLocation(); + res.data.title = gettext("Confirm Unsubscribe"); + res.data.body = this.renderSkinAsString("$HopObject#confirm", { + text: gettext('You are about to unsubscribe from site {0}.', this.title) + }); + this.renderSkin("Site#page"); + return; } Site.prototype.export_action = function() { - var job = this.job && new Admin.Job(this.job); + var job = this.job && new Admin.Job(this.job); - var data = req.postParams; - if (data.submit === "start") { - try { - if (!job) { - this.job = Admin.queue(this, "export"); - res.message = gettext("Site is scheduled for export."); - } else { - if (job.method !== "export") { - throw Error(gettext("There is already another job queued for this site: {0}", - job.method)); - } - } - } catch (ex) { - res.message = ex.toString(); - app.log(res.message); + var data = req.postParams; + if (data.submit === "start") { + try { + if (!job) { + this.job = Admin.queue(this, "export"); + res.message = gettext("Site is scheduled for export."); + } else { + if (job.method !== "export") { + throw Error(gettext("There is already another job queued for this site: {0}", + job.method)); + } } - res.redirect(this.href(req.action)); - } else if (data.submit === "stop") { - job && job.remove(); - this.job = null; - res.redirect(this.href(req.action)); - } + } catch (ex) { + res.message = ex.toString(); + app.log(res.message); + } + res.redirect(this.href(req.action)); + } else if (data.submit === "stop") { + job && job.remove(); + this.job = null; + res.redirect(this.href(req.action)); + } - var param = { - status: (job && job.method === "export") ? - gettext("A Blogger export file (.xml) will be created and available for download from here within 24 hours.") : - null - } - res.handlers.file = File.getById(this.export_id) || {}; - res.data.body = this.renderSkinAsString("$Site#export", param); - this.renderSkin("Site#page"); - return; + var param = { + status: (job && job.method === "export") ? + gettext("A Blogger export file (.xml) will be created and available for download from here within 24 hours.") : + null + } + res.handlers.file = File.getById(this.export_id) || {}; + res.data.body = this.renderSkinAsString("$Site#export", param); + this.renderSkin("Site#page"); + return; } Site.prototype.import_action = function() { - var job = this.job && new Admin.Job(this.job); - var file = this.import_id && File.getById(this.import_id); + var job = this.job && new Admin.Job(this.job); + var file = this.import_id && File.getById(this.import_id); - var data = req.postParams; - if (data.submit === "start") { - try { - if (job) { - if (job.method === "import") { - job.remove(); - this.job = null; - } else if (job.method) { - throw Error(gettext("There is already another job queued for this site: {0}", - job.method)); - } - } - file && File.remove.call(file); - data.file_origin = data.file.name; - file = new File; - file.site = this; - file.update(data); - this.files.add(file); - file.creator = session.user; - this.job = Admin.queue(this, "import"); - this.import_id = file._id; - res.message = gettext("Site is scheduled for import."); - res.redirect(this.href(req.action)); - } catch (ex) { - res.message = ex.toString(); - app.log(res.message); + var data = req.postParams; + if (data.submit === "start") { + try { + if (job) { + if (job.method === "import") { + job.remove(); + this.job = null; + } else if (job.method) { + throw Error(gettext("There is already another job queued for this site: {0}", + job.method)); + } } - } else if (data.submit === "stop") { file && File.remove.call(file); - job && job.remove(); - this.job = null; - this.import_id = null; + data.file_origin = data.file.name; + file = new File; + file.site = this; + file.update(data); + this.files.add(file); + file.creator = session.user; + this.job = Admin.queue(this, "import"); + this.import_id = file._id; + res.message = gettext("Site is scheduled for import."); res.redirect(this.href(req.action)); - } + } catch (ex) { + res.message = ex.toString(); + app.log(res.message); + } + } else if (data.submit === "stop") { + file && File.remove.call(file); + job && job.remove(); + this.job = null; + this.import_id = null; + res.redirect(this.href(req.action)); + } - res.handlers.file = File.getById(this.import_id) || {}; - res.data.body = this.renderSkinAsString("$Site#import"); - this.renderSkin("Site#page"); - return; + res.handlers.file = File.getById(this.import_id) || {}; + res.data.body = this.renderSkinAsString("$Site#import"); + this.renderSkin("Site#page"); + return; } Site.prototype.robots_txt_action = function() { - res.contentType = "text/plain"; - this.renderSkin("Site#robots"); - return; + res.contentType = "text/plain"; + this.renderSkin("Site#robots"); + return; } /** @@ -758,40 +758,40 @@ Site.prototype.robots_txt_action = function() { * @returns {HopObject} */ Site.prototype.getMacroHandler = function(name) { - switch (name) { - case "archive": - case "files": - case "galleries": - case "images": - case "layout": - case "members": - case "polls": - case "stories": - case "tags": - return this[name]; - default: - return null; - } + switch (name) { + case "archive": + case "files": + case "galleries": + case "images": + case "layout": + case "members": + case "polls": + case "stories": + case "tags": + return this[name]; + default: + return null; + } } /** * */ Site.prototype.stories_macro = function() { - if (this.stories.featured.size() < 1) { - this.renderSkin("Site#welcome"); - if (session.user) { - if (session.user === this.creator) { - session.user.renderSkin("$User#welcome"); - } - if (this === root && User.require(User.PRIVILEGED)) { - this.admin.renderSkin("$Admin#welcome"); - } + if (this.stories.featured.size() < 1) { + this.renderSkin("Site#welcome"); + if (session.user) { + if (session.user === this.creator) { + session.user.renderSkin("$User#welcome"); } - } else { - this.archive.renderSkin("Archive#main"); - } - return; + if (this === root && User.require(User.PRIVILEGED)) { + this.admin.renderSkin("$Admin#welcome"); + } + } + } else { + this.archive.renderSkin("Archive#main"); + } + return; } /** @@ -799,16 +799,16 @@ Site.prototype.stories_macro = function() { * @param {Object} param */ Site.prototype.calendar_macro = function(param) { - if (this.archiveMode !== Site.PUBLIC) { - return; - } - var calendar = new jala.Date.Calendar(this.archive); - //calendar.setAccessNameFormat("yyyy/MM/dd"); - calendar.setHrefFormat("/yyyy/MM/dd/"); - calendar.setLocale(this.getLocale()); - calendar.setTimeZone(this.getTimeZone()); - calendar.render(this.archive.getDate()); - return; + if (this.archiveMode !== Site.PUBLIC) { + return; + } + var calendar = new jala.Date.Calendar(this.archive); + //calendar.setAccessNameFormat("yyyy/MM/dd"); + calendar.setHrefFormat("/yyyy/MM/dd/"); + calendar.setLocale(this.getLocale()); + calendar.setTimeZone(this.getTimeZone()); + calendar.render(this.archive.getDate()); + return; } /** @@ -816,8 +816,8 @@ Site.prototype.calendar_macro = function(param) { * @param {Object} param */ Site.prototype.age_macro = function(param) { - res.write(Math.floor((new Date() - this.created) / Date.ONEDAY)); - return; + res.write(Math.floor((new Date() - this.created) / Date.ONEDAY)); + return; } /** @@ -826,104 +826,104 @@ Site.prototype.age_macro = function(param) { * @param {String} name */ Site.prototype.static_macro = function(param, name, mode) { - return this.getStaticUrl(name); + return this.getStaticUrl(name); } /** * */ Site.prototype.deleted_macro = function() { - return new Date(this.deleted.getTime() + Date.ONEDAY * - Admin.SITEREMOVALGRACEPERIOD); + return new Date(this.deleted.getTime() + Date.ONEDAY * + Admin.SITEREMOVALGRACEPERIOD); } /** * */ Site.prototype.referrers_macro = function() { - var self = this; - var sql = new Sql; - sql.retrieve(Sql.REFERRERS, "Site", this._id); - sql.traverse(function() { - if (this.requests && this.referrer) { - this.text = encode(this.referrer.head(50)); - this.referrer = encode(this.referrer); - self.renderSkin("$Site#referrer", this); - } - }); - return; + var self = this; + var sql = new Sql; + sql.retrieve(Sql.REFERRERS, "Site", this._id); + sql.traverse(function() { + if (this.requests && this.referrer) { + this.text = encode(this.referrer.head(50)); + this.referrer = encode(this.referrer); + self.renderSkin("$Site#referrer", this); + } + }); + return; } /** * */ Site.prototype.spamfilter_macro = function() { - var str = this.getMetadata("spamfilter"); - if (!str) { - return; - } - var items = str.replace(/\r/g, "").split("\n"); - for (var i in items) { - res.write('"'); - res.write(items[i]); - res.write('"'); - if (i < items.length-1) { - res.write(","); - } - } - return; + var str = this.getMetadata("spamfilter"); + if (!str) { + return; + } + var items = str.replace(/\r/g, "").split("\n"); + for (var i in items) { + res.write('"'); + res.write(items[i]); + res.write('"'); + if (i < items.length-1) { + res.write(","); + } + } + return; } /** * */ Site.prototype.diskspace_macro = function() { - var quota = this.getQuota(); - var usage = this.getDiskSpace(quota); - res.write(usage > 0 ? formatNumber(usage, "#,###.#") : 0); - res.write(" MB " + (quota ? gettext("free") : gettext("used"))); - return; + var quota = this.getQuota(); + var usage = this.getDiskSpace(quota); + res.write(usage > 0 ? formatNumber(usage, "#,###.#") : 0); + res.write(" MB " + (quota ? gettext("free") : gettext("used"))); + return; } /** * @returns {java.util.Locale} */ Site.prototype.getLocale = function() { - var locale; - if (locale = this.cache.locale) { - return locale; - } else if (this.locale) { - var parts = this.locale.split("_"); - locale = new java.util.Locale(parts[0] || String.EMPTY, - parts[1] || String.EMPTY, parts.splice(2).join("_")); - } else { - locale = java.util.Locale.getDefault(); - } - return this.cache.locale = locale; + var locale; + if (locale = this.cache.locale) { + return locale; + } else if (this.locale) { + var parts = this.locale.split("_"); + locale = new java.util.Locale(parts[0] || String.EMPTY, + parts[1] || String.EMPTY, parts.splice(2).join("_")); + } else { + locale = java.util.Locale.getDefault(); + } + return this.cache.locale = locale; } /** * @returns {java.util.TimeZone} */ Site.prototype.getTimeZone = function() { - var timeZone; - if (timeZone = this.cache.timeZone) { - return timeZone; - } - if (this.timeZone) { - timeZone = java.util.TimeZone.getTimeZone(this.timeZone); - } else { - timeZone = java.util.TimeZone.getDefault(); - } - this.cache.timezone = timeZone; - return timeZone; + var timeZone; + if (timeZone = this.cache.timeZone) { + return timeZone; + } + if (this.timeZone) { + timeZone = java.util.TimeZone.getTimeZone(this.timeZone); + } else { + timeZone = java.util.TimeZone.getDefault(); + } + this.cache.timezone = timeZone; + return timeZone; } /** * @returns {Number} */ Site.prototype.getQuota = function() { - return this.status !== Site.TRUSTED ? root.quota : null; + return this.status !== Site.TRUSTED ? root.quota : null; } /** @@ -931,11 +931,11 @@ Site.prototype.getQuota = function() { * @returns {float} */ Site.prototype.getDiskSpace = function(quota) { - quota || (quota = this.getQuota()); - var dir = new java.io.File(this.getStaticFile()); - var size = Packages.org.apache.commons.io.FileUtils.sizeOfDirectory(dir); - var factor = 1024 * 1024; // MB - return (quota ? quota * factor - size : size) / factor; + quota || (quota = this.getQuota()); + var dir = new java.io.File(this.getStaticFile()); + var size = Packages.org.apache.commons.io.FileUtils.sizeOfDirectory(dir); + var factor = 1024 * 1024; // MB + return (quota ? quota * factor - size : size) / factor; } /** @@ -943,18 +943,18 @@ Site.prototype.getDiskSpace = function(quota) { * @param {String} href */ Site.prototype.processHref = function(href) { - var parts, domain, - scheme = (req.servletRequest ? req.servletRequest.scheme : 'http') + '://'; - if (domain = getProperty('domain.' + this.name)) { - parts = [scheme, domain, href]; - } else if (domain = getProperty('domain.*')) { - parts = [scheme, this.name, '.', domain, href]; - } else { - var mountpoint = app.appsProperties.mountpoint; - (mountpoint === '/') && (mountpoint = ''); // Prevents double slashes - parts = [scheme, req.data.http_host, mountpoint, href]; - } - return parts.join(''); + var parts, domain, + scheme = (req.servletRequest ? req.servletRequest.scheme : 'http') + '://'; + if (domain = getProperty('domain.' + this.name)) { + parts = [scheme, domain, href]; + } else if (domain = getProperty('domain.*')) { + parts = [scheme, this.name, '.', domain, href]; + } else { + var mountpoint = app.appsProperties.mountpoint; + (mountpoint === '/') && (mountpoint = ''); // Prevents double slashes + parts = [scheme, req.data.http_host, mountpoint, href]; + } + return parts.join(''); } /** @@ -964,30 +964,30 @@ Site.prototype.processHref = function(href) { * @returns {Tag[]} */ Site.prototype.getTags = function(type, group) { - var handler; - type = type.toLowerCase(); - switch (type) { - case "story": - case "tags": - handler = this.stories; - type = "tags"; - break; - case "image": - case "galleries": - handler = this.images; - type = "galleries"; - break; - } - switch (group) { - case Tags.ALL: - return handler[type]; - case Tags.OTHER: - case Tags.ALPHABETICAL: - return handler[group + type.titleize()]; - default: - return handler["alphabetical" + type.titleize()].get(group); - } - return null; + var handler; + type = type.toLowerCase(); + switch (type) { + case "story": + case "tags": + handler = this.stories; + type = "tags"; + break; + case "image": + case "galleries": + handler = this.images; + type = "galleries"; + break; + } + switch (group) { + case Tags.ALL: + return handler[type]; + case Tags.OTHER: + case Tags.ALPHABETICAL: + return handler[group + type.titleize()]; + default: + return handler["alphabetical" + type.titleize()].get(group); + } + return null; } /** @@ -996,9 +996,9 @@ Site.prototype.getTags = function(type, group) { * @returns {helma.File} */ Site.prototype.getStaticFile = function(tail) { - var fpath = this.name; - tail && (fpath += "/" + tail); - return new helma.File(app.appsProperties['static'], fpath); + var fpath = this.name; + tail && (fpath += "/" + tail); + return new helma.File(app.appsProperties['static'], fpath); } /** @@ -1007,12 +1007,12 @@ Site.prototype.getStaticFile = function(tail) { * @returns {String} */ Site.prototype.getStaticUrl = function(href) { - href || (href = ''); - var scheme = (req.servletRequest ? req.servletRequest.scheme : 'http') + '://'; - var host = getProperty('domain.' + this.name); - host || (host = getProperty('domain.*')); - host || (host = req.data.http_host); - return [scheme, host, app.appsProperties.staticMountpoint, '/', this.name, '/', href].join(''); + href || (href = ''); + var scheme = (req.servletRequest ? req.servletRequest.scheme : 'http') + '://'; + var host = getProperty('domain.' + this.name); + host || (host = getProperty('domain.*')); + host || (host = req.data.http_host); + return [scheme, host, app.appsProperties.staticMountpoint, '/', this.name, '/', href].join(''); } /** @@ -1020,14 +1020,14 @@ Site.prototype.getStaticUrl = function(href) { * @param {Object} ref */ Site.prototype.callback = function(ref) { - if (this.callbackMode === Site.ENABLED && this.callbackUrl) { - app.data.callbacks.push({ - site: this._id, - handler: ref.constructor, - id: ref._id - }); - } - return; + if (this.callbackMode === Site.ENABLED && this.callbackUrl) { + app.data.callbacks.push({ + site: this._id, + handler: ref.constructor, + id: ref._id + }); + } + return; } /** @@ -1036,10 +1036,10 @@ Site.prototype.callback = function(ref) { * @returns {String[]} */ Site.prototype.getAdminHeader = function(name) { - switch (name) { - case "tags": - case "galleries": - return ["#", "Name", "Items"]; - } - return []; + switch (name) { + case "tags": + case "galleries": + return ["#", "Name", "Items"]; + } + return []; } diff --git a/code/Skin/Skin.js b/code/Skin/Skin.js index 93b2f0bd..e7b900ae 100644 --- a/code/Skin/Skin.js +++ b/code/Skin/Skin.js @@ -7,7 +7,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -35,14 +35,14 @@ markgettext("skin"); * @returns {Skin} */ Skin.getByName = function(group, name) { - var skinSet = (res.handlers.layout || path.layout).skins.get(group); - if (skinSet) { - var skin = skinSet.get(name); - if (skin) { - return skin; - } - } - return null; + var skinSet = (res.handlers.layout || path.layout).skins.get(group); + if (skinSet) { + var skin = skinSet.get(name); + if (skin) { + return skin; + } + } + return null; } /** @@ -51,9 +51,9 @@ Skin.getByName = function(group, name) { * @param {Layout} layout */ Skin.add = function(prototype, name, layout) { - var skin = new Skin(prototype, name); - layout.skins.add(skin); - return skin; + var skin = new Skin(prototype, name); + layout.skins.add(skin); + return skin; } /** @@ -61,31 +61,31 @@ Skin.add = function(prototype, name, layout) { * @param {Skin} skin */ Skin.remove = function() { - if (this.constructor === Skin) { - this.setSource(this.source); - this.source = null; - this.remove(); - } - return; + if (this.constructor === Skin) { + this.setSource(this.source); + this.source = null; + this.remove(); + } + return; } /** * @returns {String[]} */ Skin.getPrototypeOptions = function() { - var prototypes = []; - var content, file; - var skinFiles = app.getSkinfilesInPath(res.skinpath); - for (var name in skinFiles) { - // Include root skins only for root site - if (name === root.constructor.name && res.handlers.site !== root) { - continue; - } - if (skinFiles[name][name]) { - prototypes.push({value: name, display: name}); - } - } - return prototypes.sort(new String.Sorter("display")); + var prototypes = []; + var content, file; + var skinFiles = app.getSkinfilesInPath(res.skinpath); + for (var name in skinFiles) { + // Include root skins only for root site + if (name === root.constructor.name && res.handlers.site !== root) { + continue; + } + if (skinFiles[name][name]) { + prototypes.push({value: name, display: name}); + } + } + return prototypes.sort(new String.Sorter("display")); } /** @@ -103,12 +103,12 @@ Skin.getPrototypeOptions = function() { * @extends HopObject */ Skin.prototype.constructor = function(prototype, name) { - HopObject.confirmConstructor(this); - this.prototype = prototype || String.EMPTY; - this.name = name || String.EMPTY; - this.creator = this.modifier = session.user; - this.created = this.modified = new Date; - return this; + HopObject.confirmConstructor(this); + this.prototype = prototype || String.EMPTY; + this.name = name || String.EMPTY; + this.creator = this.modifier = session.user; + this.created = this.modified = new Date; + return this; } /** @@ -117,12 +117,12 @@ Skin.prototype.constructor = function(prototype, name) { * @returns {Boolean} */ Skin.prototype.getPermission = function(action) { - switch (action) { - case ".": - case "main": - return true; - } - return res.handlers.skins.getPermission("main"); + switch (action) { + case ".": + case "main": + return true; + } + return res.handlers.skins.getPermission("main"); } /** @@ -131,47 +131,47 @@ Skin.prototype.getPermission = function(action) { * @returns {String} */ Skin.prototype.href = function(action) { - res.push(); - res.write(res.handlers.layout.skins.href()); - res.write(this.prototype); - res.write("/"); - res.write(this.name); - res.write("/"); - action && (res.write(action)); - return res.pop(); + res.push(); + res.write(res.handlers.layout.skins.href()); + res.write(this.prototype); + res.write("/"); + res.write(this.name); + res.write("/"); + action && (res.write(action)); + return res.pop(); } Skin.prototype.main_action = function() { - if (res.handlers.site === root) { - res.contentType = "text/plain"; - res.write(this.getSource()); - return; - } - res.redirect(this.href("edit")); - return; + if (res.handlers.site === root) { + res.contentType = "text/plain"; + res.write(this.getSource()); + return; + } + res.redirect(this.href("edit")); + return; } Skin.prototype.edit_action = function() { - if (req.postParams.save) { - try { - var url = this.href(req.action); - this.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - if (req.postParams.save == 1) { - res.redirect(url); - } else { - res.redirect(res.handlers.layout.skins.href("modified")); - } - } catch (ex) { - res.message = ex; - app.log(ex); + if (req.postParams.save) { + try { + var url = this.href(req.action); + this.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + if (req.postParams.save == 1) { + res.redirect(url); + } else { + res.redirect(res.handlers.layout.skins.href("modified")); } - } - res.data.action = this.href(req.action); - res.data.title = gettext('Edit Skin: {0}.{1}', this.prototype, this.name); - res.data.body = this.renderSkinAsString("$Skin#edit"); - res.handlers.skins.renderSkin("$Skins#page"); - return; + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.data.action = this.href(req.action); + res.data.title = gettext('Edit Skin: {0}.{1}', this.prototype, this.name); + res.data.body = this.renderSkinAsString("$Skin#edit"); + res.handlers.skins.renderSkin("$Skins#page"); + return; } /** @@ -179,96 +179,96 @@ Skin.prototype.edit_action = function() { * @param {Object} data */ Skin.prototype.update = function(data) { - if (this.isTransient()) { - res.handlers.layout.skins.add(this); - this.source = this.getSource(); // Copies the skin file source to database - } - if (this.prototype === "Site" && this.name === "page") { - var macro = "response.body"; - if (!createSkin(data.source).containsMacro(macro)) { - var macro = ["<%", macro, "%>"].join(String.EMPTY); - throw Error(gettext("The {0} macro is missing. It is essential for accessing the site and must be present in this skin.", macro)); - } - } - this.setSource(data.source); - this.touch(); - return; + if (this.isTransient()) { + res.handlers.layout.skins.add(this); + this.source = this.getSource(); // Copies the skin file source to database + } + if (this.prototype === "Site" && this.name === "page") { + var macro = "response.body"; + if (!createSkin(data.source).containsMacro(macro)) { + var macro = ["<%", macro, "%>"].join(String.EMPTY); + throw Error(gettext("The {0} macro is missing. It is essential for accessing the site and must be present in this skin.", macro)); + } + } + this.setSource(data.source); + this.touch(); + return; } Skin.prototype.reset_action = function() { - if (req.postParams.proceed) { - try { - Skin.remove.call(this); - res.message = gettext("{0} was successfully reset.", gettext("Skin")); - res.redirect(res.handlers.layout.skins.href("modified")); - } catch(ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.proceed) { + try { + Skin.remove.call(this); + res.message = gettext("{0} was successfully reset.", gettext("Skin")); + res.redirect(res.handlers.layout.skins.href("modified")); + } catch(ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext("Confirm Reset"); - res.data.body = this.renderSkinAsString("$HopObject#confirm", { - text: this.getConfirmText() - }); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext("Confirm Reset"); + res.data.body = this.renderSkinAsString("$HopObject#confirm", { + text: this.getConfirmText() + }); + res.handlers.site.renderSkin("Site#page"); + return; } Skin.prototype.compare_action = function() { - var originalSkin = this.source || String.EMPTY; - var diff = this.getSource().diff(originalSkin); - if (!diff) { - res.message = gettext("No differences were found."); - } else { - res.push(); - var param = {}, leftLineNumber = rightLineNumber = 0; - for each (let line in diff) { - if (line.deleted) { - param.right = encode(line.value); - param.leftStatus = "added"; - param.rightStatus = ''; - for (let i=0; i"); - res.writeln(source.trim().replace(/(<%\s*)#/g, "$1// #")); - } - var subskins = skin.getSubskinNames(); - for (var i in subskins) { - if (subskins[i] !== this.name) { - res.writeln("<% #" + subskins[i] + " %>"); - source = skin.getSubskin(subskins[i]).source; - source && res.writeln(source.trim()); - } - } - source = res.pop(); + res.push(); + if (source != null) { + res.writeln("<% #" + this.name + " %>"); + res.writeln(source.trim().replace(/(<%\s*)#/g, "$1// #")); + } + var subskins = skin.getSubskinNames(); + for (var i in subskins) { + if (subskins[i] !== this.name) { + res.writeln("<% #" + subskins[i] + " %>"); + source = skin.getSubskin(subskins[i]).source; + source && res.writeln(source.trim()); + } + } + source = res.pop(); - var file = this.getStaticFile(); - if (!file.exists()) { - file.getParentFile().mkdirs(); - file.createNewFile(); - } - var fos = new java.io.FileOutputStream(file); - var bos = new java.io.BufferedOutputStream(fos); - var writer = new java.io.OutputStreamWriter(bos, "UTF-8"); - writer.write(source); - writer.close(); - bos.close(); - fos.close(); + var file = this.getStaticFile(); + if (!file.exists()) { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + var fos = new java.io.FileOutputStream(file); + var bos = new java.io.BufferedOutputStream(fos); + var writer = new java.io.OutputStreamWriter(bos, "UTF-8"); + writer.write(source); + writer.close(); + bos.close(); + fos.close(); - this.clearCache(); - return; + this.clearCache(); + return; } /** @@ -367,9 +367,9 @@ Skin.prototype.setSource = function(source) { * @returns {java.io.File} */ Skin.prototype.getStaticFile = function() { - // FIXME: Maintain skin inheritance by checking if we target the Site skin of root - var prototype = (res.handlers.site === root && this.prototype === "Site") ? "Root" : this.prototype; - return new java.io.File(res.skinpath[0], prototype + "/" + this.prototype + ".skin"); + // FIXME: Maintain skin inheritance by checking if we target the Site skin of root + var prototype = (res.handlers.site === root && this.prototype === "Site") ? "Root" : this.prototype; + return new java.io.File(res.skinpath[0], prototype + "/" + this.prototype + ".skin"); } /** @@ -377,14 +377,14 @@ Skin.prototype.getStaticFile = function() { * @returns {Skin} */ Skin.prototype.getMainSkin = function(prototype) { - var source, skinSet = app.getSkinfilesInPath(res.skinpath)[prototype || this.prototype]; - if (skinSet) { - source = skinSet[this.prototype]; - if (source !== null) { - return createSkin(source); - } - } - return null; + var source, skinSet = app.getSkinfilesInPath(res.skinpath)[prototype || this.prototype]; + if (skinSet) { + source = skinSet[this.prototype]; + if (source !== null) { + return createSkin(source); + } + } + return null; } /** @@ -394,18 +394,18 @@ Skin.prototype.getMainSkin = function(prototype) { * @returns {Skin} */ Skin.prototype.getSubskin = function(prototype, name) { - var mainSkin = this.getMainSkin(prototype); - if (mainSkin) { - return mainSkin.getSubskin(name || this.name); - } - return null; + var mainSkin = this.getMainSkin(prototype); + if (mainSkin) { + return mainSkin.getSubskin(name || this.name); + } + return null; } /** * */ Skin.prototype.render = function() { - return renderSkin(createSkin(this.getSource())); + return renderSkin(createSkin(this.getSource())); } /** @@ -414,39 +414,39 @@ Skin.prototype.render = function() { * @returns {Boolean} */ Skin.prototype.equals = function(source) { - // FIXME: The removal of linebreaks is necessary but it's not very nice - var re = /\r|\n/g; - var normalize = function(str) { - return str.replace(re, String.EMPTY); - } - return normalize(source) === normalize(this.getSource()); + // FIXME: The removal of linebreaks is necessary but it's not very nice + var re = /\r|\n/g; + var normalize = function(str) { + return str.replace(re, String.EMPTY); + } + return normalize(source) === normalize(this.getSource()); } /** * @returns {String} */ Skin.prototype.getConfirmText = function() { - return gettext("You are about to reset the skin {0}.{1}.", - this.prototype, this.name); + return gettext("You are about to reset the skin {0}.{1}.", + this.prototype, this.name); } /** * @returns {String} */ Skin.prototype.toString = function() { - return "Skin #" + this._id + ": " + this.prototype + "." + this.name; + return "Skin #" + this._id + ": " + this.prototype + "." + this.name; } /** * */ Skin.prototype.status_macro = function() { - return this.isTransient() ? "inherited" : "modified"; + return this.isTransient() ? "inherited" : "modified"; } /** * */ Skin.prototype.content_macro = function() { - return res.write(this.getSource()); + return res.write(this.getSource()); } diff --git a/code/Skins/Skins.js b/code/Skins/Skins.js index 00acf301..e9850430 100644 --- a/code/Skins/Skins.js +++ b/code/Skins/Skins.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -54,7 +54,7 @@ Skins.prototype.constructor = function(name, parent) { * @returns {Boolean} */ Skins.prototype.getPermission = function(action) { - return res.handlers.layout.getPermission("main"); + return res.handlers.layout.getPermission("main"); } /** @@ -63,99 +63,99 @@ Skins.prototype.getPermission = function(action) { * @returns {Skins|Skin} */ Skins.prototype.getChildElement = function(name) { - if (this.parent) { - var group = path[path.length - 1].name; - var skin = this.getSkin(group, name); - if (skin) { - return skin; - } - if (global[group] || group === "Global") { - return this.getSkin(group, name); - } - } - return new Skins(name, this); + if (this.parent) { + var group = path[path.length - 1].name; + var skin = this.getSkin(group, name); + if (skin) { + return skin; + } + if (global[group] || group === "Global") { + return this.getSkin(group, name); + } + } + return new Skins(name, this); } Skins.prototype.onRequest = function() { - if (this.parent) { - res.redirect(res.handlers.layout.skins.href(req.action)); - } - return HopObject.prototype.onRequest.call(this); + if (this.parent) { + res.redirect(res.handlers.layout.skins.href(req.action)); + } + return HopObject.prototype.onRequest.call(this); } Skins.prototype.main_action = function() { - res.data.title = gettext("Basic Skins"); - res.data.body = this.renderSkinAsString("$Skins#main"); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Basic Skins"); + res.data.body = this.renderSkinAsString("$Skins#main"); + res.handlers.site.renderSkin("Site#page"); + return; } Skins.prototype.create_action = function() { - if (req.postParams.save) { - try { - var prototype = req.postParams.prototype; - var name = stripTags(req.postParams.name); - if (!prototype || !req.postParams.name) { - throw Error(gettext("Please choose a prototype and enter a skin name")); - } else if (name !== req.postParams.name || /\s/.test(name) || NAMEPATTERN.test(name)) { - throw Error(gettext("Please avoid special characters or HTML code in the name field.")); - } else if (Skin.getByName(prototype, name)) { - throw Error("Sorry, there is already a skin with that name. Please enter a different one."); - } - var skin = this.getSkin(prototype, name); - skin.update(req.postParams); - res.message = gettext("The changes were saved successfully."); - if (req.postParams.save == 1) { - res.redirect(skin.href("edit")); - } else { - res.redirect(res.handlers.layout.skins.href("modified")); - } - } catch (ex) { - res.message = ex; - app.log(ex); + if (req.postParams.save) { + try { + var prototype = req.postParams.prototype; + var name = stripTags(req.postParams.name); + if (!prototype || !req.postParams.name) { + throw Error(gettext("Please choose a prototype and enter a skin name")); + } else if (name !== req.postParams.name || /\s/.test(name) || NAMEPATTERN.test(name)) { + throw Error(gettext("Please avoid special characters or HTML code in the name field.")); + } else if (Skin.getByName(prototype, name)) { + throw Error("Sorry, there is already a skin with that name. Please enter a different one."); } - } - res.data.title = gettext('Add Skin'); - res.data.action = this.href(req.action); - HopObject.confirmConstructor(Skin); - res.data.body = (new Skin).renderSkinAsString("$Skin#edit"); - this.renderSkin("$Skins#page"); - return; + var skin = this.getSkin(prototype, name); + skin.update(req.postParams); + res.message = gettext("The changes were saved successfully."); + if (req.postParams.save == 1) { + res.redirect(skin.href("edit")); + } else { + res.redirect(res.handlers.layout.skins.href("modified")); + } + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.data.title = gettext('Add Skin'); + res.data.action = this.href(req.action); + HopObject.confirmConstructor(Skin); + res.data.body = (new Skin).renderSkinAsString("$Skin#edit"); + this.renderSkin("$Skins#page"); + return; } Skins.prototype.modified_action = function() { - res.data.title = gettext("Modified Skins"); - res.push(); - this.renderSkin("$Skins#header"); - this.modified.forEach(function() { - this.renderSkin("$Skin#listItem"); - }); - res.data.body = res.pop(); - res.handlers.site.renderSkin("Site#page"); - return; + res.data.title = gettext("Modified Skins"); + res.push(); + this.renderSkin("$Skins#header"); + this.modified.forEach(function() { + this.renderSkin("$Skin#listItem"); + }); + res.data.body = res.pop(); + res.handlers.site.renderSkin("Site#page"); + return; } Skins.prototype.all_action = function() { - if (this.parent) { - res.redirect(res.handlers.layout.skins.href(req.action)); - } - res.data.list = this.getOutline(); - res.data.title = gettext("All Skins"); - res.data.body = this.renderSkinAsString("$Skins#all"); - res.handlers.site.renderSkin("Site#page"); - return; + if (this.parent) { + res.redirect(res.handlers.layout.skins.href(req.action)); + } + res.data.list = this.getOutline(); + res.data.title = gettext("All Skins"); + res.data.body = this.renderSkinAsString("$Skins#all"); + res.handlers.site.renderSkin("Site#page"); + return; } Skins.prototype.safe_action = function() { - res.data.title = gettext("Modified Skins"); - res.push(); - this.modified.forEach(function() { - this.renderSkin("$Skin#listItem"); - }); - res.data.title = "Modified Skins"; - res.data.body = res.pop(); - this.renderSkin("$Skins#page"); - return; + res.data.title = gettext("Modified Skins"); + res.push(); + this.modified.forEach(function() { + this.renderSkin("$Skin#listItem"); + }); + res.data.title = "Modified Skins"; + res.data.body = res.pop(); + this.renderSkin("$Skins#page"); + return; } /** @@ -165,7 +165,7 @@ Skins.prototype.safe_action = function() { * @returns {Skin} */ Skins.prototype.getSkin = function(group, name) { - return Skin.getByName(group, name) || new Skin(group, name); + return Skin.getByName(group, name) || new Skin(group, name); } /** @@ -173,42 +173,42 @@ Skins.prototype.getSkin = function(group, name) { * @returns {String} */ Skins.prototype.getOutline = function() { - var skinfiles, prototype, skin, subskins, names, skins = []; - var options = Skin.getPrototypeOptions(); + var skinfiles, prototype, skin, subskins, names, skins = []; + var options = Skin.getPrototypeOptions(); - for each (var option in options) { - names = []; - prototype = option.value; - skinfiles = app.getSkinfilesInPath(res.skinpath); - skin = createSkin(skinfiles[prototype][prototype]); - subskins = skin.getSubskinNames(); - for each (var subskin in subskins) { - names.push(subskin); - } - names.sort(); - skins.push([prototype, names]); - } + for each (var option in options) { + names = []; + prototype = option.value; + skinfiles = app.getSkinfilesInPath(res.skinpath); + skin = createSkin(skinfiles[prototype][prototype]); + subskins = skin.getSubskinNames(); + for each (var subskin in subskins) { + names.push(subskin); + } + names.sort(); + skins.push([prototype, names]); + } - res.push(); - for each (var item in skins) { - prototype = item[0]; - skin = item[1]; - if (skin && skin.length > 0) { - html.openTag("li"); - html.openTag("a", {href: "#" + prototype}); - res.write(prototype); - html.closeTag("a"); - html.openTag("ul"); - for each (var name in skin) { - subskin = this.getSkin(prototype, name); - html.openTag("li"); - html.link({href: subskin.href("edit")}, - subskin.prototype + "." + subskin.name); - html.closeTag("li"); - } - html.closeTag("ul"); - html.closeTag("li"); + res.push(); + for each (var item in skins) { + prototype = item[0]; + skin = item[1]; + if (skin && skin.length > 0) { + html.openTag("li"); + html.openTag("a", {href: "#" + prototype}); + res.write(prototype); + html.closeTag("a"); + html.openTag("ul"); + for each (var name in skin) { + subskin = this.getSkin(prototype, name); + html.openTag("li"); + html.link({href: subskin.href("edit")}, + subskin.prototype + "." + subskin.name); + html.closeTag("li"); } - } - return res.pop(); + html.closeTag("ul"); + html.closeTag("li"); + } + } + return res.pop(); } diff --git a/code/Stories/Stories.js b/code/Stories/Stories.js index 6129265e..07ed0b7c 100644 --- a/code/Stories/Stories.js +++ b/code/Stories/Stories.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -52,89 +52,89 @@ markgettext("stories"); * @returns {Boolean} */ Stories.prototype.getPermission = function(action) { - if (!this._parent.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - case "create": - return Site.require(Site.OPEN) && session.user || - Membership.require(Membership.CONTRIBUTOR) || - User.require(User.PRIVILEGED); + if (!this._parent.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + case "create": + return Site.require(Site.OPEN) && session.user || + Membership.require(Membership.CONTRIBUTOR) || + User.require(User.PRIVILEGED); - case "all": - case "top": - case "closed": - return Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - } - return false; + case "all": + case "top": + case "closed": + return Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + } + return false; } Stories.prototype.main_action = function() { - var stories = User.getMembership().stories; - res.data.list = renderList(stories, "$Story#listItem", - 10, req.queryParams.page); - res.data.pager = renderPager(stories, - this.href(), 10, req.queryParams.page); - res.data.title = gettext("Member Stories"); - res.data.body = this.renderSkinAsString("$Stories#main"); - this._parent.renderSkin("Site#page"); - return; + var stories = User.getMembership().stories; + res.data.list = renderList(stories, "$Story#listItem", + 10, req.queryParams.page); + res.data.pager = renderPager(stories, + this.href(), 10, req.queryParams.page); + res.data.title = gettext("Member Stories"); + res.data.body = this.renderSkinAsString("$Stories#main"); + this._parent.renderSkin("Site#page"); + return; } Stories.prototype.create_action = function() { - if (req.data.save) { - try { - story = Story.add(req.params); - story.notify(req.action); - JSON.sendPaddedResponse(story._id); - delete session.data.backup; - res.message = gettext("The story was successfully created."); - res.redirect(story.href()); - } catch (ex) { - JSON.sendPaddedResponse(null); - res.status = 400; - res.message = ex; - app.log(ex); - } - } + if (req.data.save) { + try { + story = Story.add(req.params); + story.notify(req.action); + JSON.sendPaddedResponse(story._id); + delete session.data.backup; + res.message = gettext("The story was successfully created."); + res.redirect(story.href()); + } catch (ex) { + JSON.sendPaddedResponse(null); + res.status = 400; + res.message = ex; + app.log(ex); + } + } - res.data.title = gettext("Add Story"); - res.data.action = this.href(req.action); - HopObject.confirmConstructor(Story); - res.data.body = (new Story).renderSkinAsString("Story#edit"); - this._parent.renderSkin("Site#page"); - return; + res.data.title = gettext("Add Story"); + res.data.action = this.href(req.action); + HopObject.confirmConstructor(Story); + res.data.body = (new Story).renderSkinAsString("Story#edit"); + this._parent.renderSkin("Site#page"); + return; } Stories.prototype.closed_action = function() { - res.data.list = renderList(this.closed, - "$Story#listItem", 10, req.queryParams.page); - res.data.pager = renderPager(this.closed, - this.href(req.action), 10, req.queryParams.page); - res.data.title = gettext("Closed Stories"); - res.data.body = this.renderSkinAsString("$Stories#main"); - this._parent.renderSkin("Site#page"); - return; + res.data.list = renderList(this.closed, + "$Story#listItem", 10, req.queryParams.page); + res.data.pager = renderPager(this.closed, + this.href(req.action), 10, req.queryParams.page); + res.data.title = gettext("Closed Stories"); + res.data.body = this.renderSkinAsString("$Stories#main"); + this._parent.renderSkin("Site#page"); + return; } Stories.prototype.all_action = function() { - res.data.list = renderList(this, "$Story#listItem", 10, req.queryParams.page); - res.data.pager = renderPager(this, - this.href(req.action), 10, req.queryParams.page); - res.data.title = gettext("All Stories"); - res.data.body = this.renderSkinAsString("$Stories#main"); - this._parent.renderSkin("Site#page"); - return; + res.data.list = renderList(this, "$Story#listItem", 10, req.queryParams.page); + res.data.pager = renderPager(this, + this.href(req.action), 10, req.queryParams.page); + res.data.title = gettext("All Stories"); + res.data.body = this.renderSkinAsString("$Stories#main"); + this._parent.renderSkin("Site#page"); + return; } Stories.prototype.top_action = function() { - res.data.title = gettext("Top Stories"); - res.data.body = this.renderSkinAsString("$Stories#top"); - this._parent.renderSkin("Site#page"); - return; + res.data.title = gettext("Top Stories"); + res.data.body = this.renderSkinAsString("$Stories#top"); + this._parent.renderSkin("Site#page"); + return; } /** @@ -143,18 +143,18 @@ Stories.prototype.top_action = function() { * @param {String} type */ Stories.prototype.list_macro = function(param, type) { - switch (type) { - case "top": - var counter = 1; - this.top.forEach(function() { - this.renderSkin("$Story#top", { - position: counter - }); - counter += 1; + switch (type) { + case "top": + var counter = 1; + this.top.forEach(function() { + this.renderSkin("$Story#top", { + position: counter }); - break; - } - return; + counter += 1; + }); + break; + } + return; } /** @@ -164,7 +164,7 @@ Stories.prototype.list_macro = function(param, type) { * @see Site#getTags */ Stories.prototype.getTags = function(group) { - return this._parent.getTags("tags", group); + return this._parent.getTags("tags", group); } /** @@ -173,5 +173,5 @@ Stories.prototype.getTags = function(group) { * @returns {String[]} */ Stories.prototype.getAdminHeader = function(name) { - return ["#", "Tag", "Items"]; + return ["#", "Tag", "Items"]; } diff --git a/code/Story/Story.js b/code/Story/Story.js index 649c2eec..f47e26fb 100644 --- a/code/Story/Story.js +++ b/code/Story/Story.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,11 +34,11 @@ this.handleMetadata("title"); this.handleMetadata("text"); Story.ALLOWED_MACROS = [ - "file", - "image", - "link", - "poll", - "story.link" + "file", + "image", + "link", + "poll", + "story.link" ]; /** @@ -49,31 +49,31 @@ Story.ALLOWED_MACROS = [ * @returns {Story} */ Story.add = function(data, site, user) { - HopObject.confirmConstructor(Story); - site || (site = res.handlers.site); - user || (user = session.user); - var story = new Story; - story.name = String.EMPTY; - story.requests = 0; - story.created = story.modified = new Date; - story.site = site; - story.creator = story.modifier = user; - story.update(data); - site.stories.add(story); - return story; + HopObject.confirmConstructor(Story); + site || (site = res.handlers.site); + user || (user = session.user); + var story = new Story; + story.name = String.EMPTY; + story.requests = 0; + story.created = story.modified = new Date; + story.site = site; + story.creator = story.modifier = user; + story.update(data); + site.stories.add(story); + return story; } /** * @function */ Story.remove = function() { - if (this.constructor === Story) { - HopObject.remove.call(this.comments); - this.setTags(null); - this.deleteMetadata(); - this.remove(); - } - return; + if (this.constructor === Story) { + HopObject.remove.call(this.comments); + this.setTags(null); + this.deleteMetadata(); + this.remove(); + } + return; } /** @@ -82,22 +82,22 @@ Story.remove = function() { * @see defineConstants */ Story.getStatus = defineConstants(Story, markgettext("closed"), - markgettext("public"), markgettext("shared"), markgettext("open")); + markgettext("public"), markgettext("shared"), markgettext("open")); /** * @function * @returns {String[]} * @see defineConstants */ Story.getModes = defineConstants(Story, markgettext("hidden"), - markgettext("featured")); + markgettext("featured")); /** * @function * @returns {String[]} * @see defineConstants */ Story.getCommentModes = defineConstants(Story, markgettext("closed"), - /* markgettext("readonly"), markgettext("moderated"), */ - markgettext("open")); + /* markgettext("readonly"), markgettext("moderated"), */ + markgettext("open")); /** * @name Story @@ -124,8 +124,8 @@ Story.getCommentModes = defineConstants(Story, markgettext("closed"), * @extends HopObject */ Story.prototype.constructor = function() { - HopObject.confirmConstructor(this); - return this; + HopObject.confirmConstructor(this); + return this; } /** @@ -134,45 +134,45 @@ Story.prototype.constructor = function() { * @returns {Boolean} */ Story.prototype.getPermission = function(action) { - if (!this.site.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - return this.status !== Story.CLOSED || - this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - case "comment": - return this.site.commentMode === Site.ENABLED && - (this.commentMode === Story.OPEN || - this.commentMode === Story.MODERATED); - case "delete": - return this.creator === session.user || - Membership.require(Membership.MANAGER) || - User.require(User.PRIVILEGED); - case "edit": - case "rotate": - return this.creator === session.user || - Membership.require(Membership.MANAGER) || - (this.status === Story.SHARED && - Membership.require(Membership.CONTRIBUTOR)) || - (this.status === Story.OPEN && - Membership.require(Membership.SUBSCRIBER)) || - User.require(User.PRIVILEGED); - } - return false; + if (!this.site.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + return this.status !== Story.CLOSED || + this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + case "comment": + return this.site.commentMode === Site.ENABLED && + (this.commentMode === Story.OPEN || + this.commentMode === Story.MODERATED); + case "delete": + return this.creator === session.user || + Membership.require(Membership.MANAGER) || + User.require(User.PRIVILEGED); + case "edit": + case "rotate": + return this.creator === session.user || + Membership.require(Membership.MANAGER) || + (this.status === Story.SHARED && + Membership.require(Membership.CONTRIBUTOR)) || + (this.status === Story.OPEN && + Membership.require(Membership.SUBSCRIBER)) || + User.require(User.PRIVILEGED); + } + return false; } Story.prototype.main_action = function() { - res.data.title = this.getTitle(10); - res.data.body = this.renderSkinAsString("Story#main"); - this.site.renderSkin("Site#page"); - this.site.log(); - this.count(); - this.log(); - return; + res.data.title = this.getTitle(10); + res.data.body = this.renderSkinAsString("Story#main"); + this.site.renderSkin("Site#page"); + this.site.log(); + this.count(); + this.log(); + return; } /** @@ -181,37 +181,37 @@ Story.prototype.main_action = function() { * @returns {String} */ Story.prototype.getTitle = function(limit) { - var key = this + ":title:" + limit; - if (!res.meta[key]) { - if (this.title) { - res.meta[key] = stripTags(this.title).clip(limit, "...", "\\s"); - } else if (this.text) { - var parts = stripTags(this.text).embody(limit, "...", "\\s"); - res.meta[key] = parts.head; - res.meta[this + ":text:" + limit] = parts.tail; - } - } - return String(res.meta[key]) || "..."; + var key = this + ":title:" + limit; + if (!res.meta[key]) { + if (this.title) { + res.meta[key] = stripTags(this.title).clip(limit, "...", "\\s"); + } else if (this.text) { + var parts = stripTags(this.text).embody(limit, "...", "\\s"); + res.meta[key] = parts.head; + res.meta[this + ":text:" + limit] = parts.tail; + } + } + return String(res.meta[key]) || "..."; } Story.prototype.edit_action = function() { - if (req.postParams.save) { - try { - this.update(req.postParams); - delete session.data.backup; - res.message = gettext("The story was successfully updated."); - res.redirect(this.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } + if (req.postParams.save) { + try { + this.update(req.postParams); + delete session.data.backup; + res.message = gettext("The story was successfully updated."); + res.redirect(this.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } - res.data.action = this.href(req.action); - res.data.title = gettext('Edit Story'); - res.data.body = this.renderSkinAsString("Story#edit"); - this.site.renderSkin("Site#page"); - return; + res.data.action = this.href(req.action); + res.data.title = gettext('Edit Story'); + res.data.body = this.renderSkinAsString("Story#edit"); + this.site.renderSkin("Site#page"); + return; } /** @@ -219,88 +219,88 @@ Story.prototype.edit_action = function() { * @param {Object} data */ Story.prototype.update = function(data) { - var site = this.site || res.handlers.site; + var site = this.site || res.handlers.site; - if (!data.title && !data.text) { - throw Error(gettext("Please enter at least something into the “title” or “text” field.")); - } - if (data.created) { - try { - this.created = data.created.toDate("yyyy-MM-dd HH:mm", site.getTimeZone()); - } catch (ex) { - throw Error(gettext("Cannot parse timestamp {0} as a date.", data.created)); - app.log(ex); - } - } + if (!data.title && !data.text) { + throw Error(gettext("Please enter at least something into the “title” or “text” field.")); + } + if (data.created) { + try { + this.created = data.created.toDate("yyyy-MM-dd HH:mm", site.getTimeZone()); + } catch (ex) { + throw Error(gettext("Cannot parse timestamp {0} as a date.", data.created)); + app.log(ex); + } + } - // Get difference to current content before applying changes - var delta = this.getDelta(data); - this.title = data.title ? data.title.trim() : String.EMPTY; - this.text = data.text ? data.text.trim() : String.EMPTY; - this.status = data.status || Story.PUBLIC; - this.mode = data.mode || Story.FEATURED; - this.commentMode = data.commentMode || Story.OPEN; - this.setCustomContent(data); + // Get difference to current content before applying changes + var delta = this.getDelta(data); + this.title = data.title ? data.title.trim() : String.EMPTY; + this.text = data.text ? data.text.trim() : String.EMPTY; + this.status = data.status || Story.PUBLIC; + this.mode = data.mode || Story.FEATURED; + this.commentMode = data.commentMode || Story.OPEN; + this.setCustomContent(data); - // FIXME: To be removed resp. moved to Stories.create_action and - // Story.edit_action if work-around for Helma bug #607 fails - // We need persistence for setting the tags - this.isTransient() && this.persist(); - this.setTags(data.tags || data.tag_array); + // FIXME: To be removed resp. moved to Stories.create_action and + // Story.edit_action if work-around for Helma bug #607 fails + // We need persistence for setting the tags + this.isTransient() && this.persist(); + this.setTags(data.tags || data.tag_array); - if (delta > 50) { - this.modified = new Date; - if (this.status !== Story.CLOSED) { - site.modified = this.modified; - } - site.callback(this); - // Notification is sent in Stories.create_action() - } + if (delta > 50) { + this.modified = new Date; + if (this.status !== Story.CLOSED) { + site.modified = this.modified; + } + site.callback(this); + // Notification is sent in Stories.create_action() + } - this.clearCache(); - this.modifier = session.user; - return; + this.clearCache(); + this.modifier = session.user; + return; } Story.prototype.rotate_action = function() { - if (this.status === Story.CLOSED) { - this.status = this.cache.status || Story.PUBLIC; - } else if (this.mode === Story.FEATURED) { - this.mode = Story.HIDDEN; - } else { - this.cache.status = this.status; - this.mode = Story.FEATURED; - this.status = Story.CLOSED; - } - return res.redirect(req.data.http_referer || this._parent.href()); + if (this.status === Story.CLOSED) { + this.status = this.cache.status || Story.PUBLIC; + } else if (this.mode === Story.FEATURED) { + this.mode = Story.HIDDEN; + } else { + this.cache.status = this.status; + this.mode = Story.FEATURED; + this.status = Story.CLOSED; + } + return res.redirect(req.data.http_referer || this._parent.href()); } Story.prototype.comment_action = function() { - // Check if user is logged in since we allow linking here for any user - if (!User.require(User.REGULAR)) { - User.setLocation(this.href(req.action) + "#form"); - res.message = gettext("Please login first."); - res.redirect(this.site.members.href("login")); - } - if (req.postParams.save) { - try { - var comment = Comment.add(req.postParams, this); - comment.notify(req.action); - delete session.data.backup; - res.message = gettext("The comment was successfully created."); - res.redirect(comment.href()); - } catch (ex) { - res.message = ex; - app.log(ex); - } - } - res.handlers.parent = this; - res.data.action = this.href(req.action); - res.data.title = gettext("Add Comment"); - HopObject.confirmConstructor(Comment); - res.data.body = (new Comment).renderSkinAsString("Comment#edit"); - this.site.renderSkin("Site#page"); - return; + // Check if user is logged in since we allow linking here for any user + if (!User.require(User.REGULAR)) { + User.setLocation(this.href(req.action) + "#form"); + res.message = gettext("Please login first."); + res.redirect(this.site.members.href("login")); + } + if (req.postParams.save) { + try { + var comment = Comment.add(req.postParams, this); + comment.notify(req.action); + delete session.data.backup; + res.message = gettext("The comment was successfully created."); + res.redirect(comment.href()); + } catch (ex) { + res.message = ex; + app.log(ex); + } + } + res.handlers.parent = this; + res.data.action = this.href(req.action); + res.data.title = gettext("Add Comment"); + HopObject.confirmConstructor(Comment); + res.data.body = (new Comment).renderSkinAsString("Comment#edit"); + this.site.renderSkin("Site#page"); + return; } /** @@ -309,20 +309,20 @@ Story.prototype.comment_action = function() { * @returns {Object} */ Story.prototype.getFormValue = function(name) { - if (req.isPost()) { - return req.postParams[name]; - } - switch (name) { - case "commentMode": - return this.commentMode || Story.OPEN; - case "mode": - return this.mode || Story.FEATURED; - case "status": - return this.status || Story.PUBLIC; - case "tags": - return this.getTags().join(Tag.DELIMITER); - } - return this[name] || this.getMetadata(name); + if (req.isPost()) { + return req.postParams[name]; + } + switch (name) { + case "commentMode": + return this.commentMode || Story.OPEN; + case "mode": + return this.mode || Story.FEATURED; + case "status": + return this.status || Story.PUBLIC; + case "tags": + return this.getTags().join(Tag.DELIMITER); + } + return this[name] || this.getMetadata(name); } /** @@ -331,18 +331,18 @@ Story.prototype.getFormValue = function(name) { * @returns {String[]} */ Story.prototype.getFormOptions = function(name) { - switch (name) { - case "commentMode": - return Story.getCommentModes(); - case "mode": - return Story.getModes(); - case "status": - return Story.getStatus(); - case "tags": - // FIXME: This could become a huge select element... - return []; - } - return; + switch (name) { + case "commentMode": + return Story.getCommentModes(); + case "mode": + return Story.getModes(); + case "status": + return Story.getStatus(); + case "tags": + // FIXME: This could become a huge select element... + return []; + } + return; } /** @@ -350,13 +350,13 @@ Story.prototype.getFormOptions = function(name) { * @param {Object} data */ Story.prototype.setCustomContent = function(data) { - var metadata = {}; - for (var key in data) { - if (this.isCustomContent(key)) { - metadata[key] = data[key]; - } - } - return HopObject.prototype.setMetadata.call(this, metadata); + var metadata = {}; + for (var key in data) { + if (this.isCustomContent(key)) { + metadata[key] = data[key]; + } + } + return HopObject.prototype.setMetadata.call(this, metadata); } /** @@ -364,28 +364,28 @@ Story.prototype.setCustomContent = function(data) { * @param {String} name */ Story.prototype.isCustomContent = function(key) { - return this[key] === undefined && key !== 'save'; + return this[key] === undefined && key !== 'save'; } /** * Increment the request counter */ Story.prototype.count = function() { - if (session.user === this.creator) { - return; - } - var story; - var key = "Story#" + this._id; - if (story = app.data.requests[key]) { - story.requests += 1; - } else { - app.data.requests[key] = { - type: this.constructor, - id: this._id, - requests: this.requests + 1 - }; - } - return; + if (session.user === this.creator) { + return; + } + var story; + var key = "Story#" + this._id; + if (story = app.data.requests[key]) { + story.requests += 1; + } else { + app.data.requests[key] = { + type: this.constructor, + id: this._id, + requests: this.requests + 1 + }; + } + return; } /** @@ -394,27 +394,27 @@ Story.prototype.count = function() { * @returns {Number} */ Story.prototype.getDelta = function(data) { - if (this.isTransient()) { - return Infinity; - } + if (this.isTransient()) { + return Infinity; + } - var deltify = function(s1, s2) { - var len1 = s1 ? String(s1).length : 0; - var len2 = s2 ? String(s2).length : 0; - return Math.abs(len1 - len2); - }; + var deltify = function(s1, s2) { + var len1 = s1 ? String(s1).length : 0; + var len2 = s2 ? String(s2).length : 0; + return Math.abs(len1 - len2); + }; - var delta = 0; - delta += deltify(data.title, this.title); - delta += deltify(data.text, this.text); - for (var key in data) { - if (this.isCustomContent(key)) { - delta += deltify(data[key], this.getMetadata(key)) - } - } - // In-between updates (1 hour) get zero delta - var timex = (new Date - this.modified) > Date.ONEHOUR ? 1 : 0; - return delta * timex; + var delta = 0; + delta += deltify(data.title, this.title); + delta += deltify(data.text, this.text); + for (var key in data) { + if (this.isCustomContent(key)) { + delta += deltify(data[key], this.getMetadata(key)) + } + } + // In-between updates (1 hour) get zero delta + var timex = (new Date - this.modified) > Date.ONEHOUR ? 1 : 0; + return delta * timex; } /** @@ -423,10 +423,10 @@ Story.prototype.getDelta = function(data) { * @returns {HopObject} */ Story.prototype.getMacroHandler = function(name) { - if (name === "metadata") { - return this.getMetadata(); - } - return null; + if (name === "metadata") { + return this.getMetadata(); + } + return null; } /** @@ -436,17 +436,17 @@ Story.prototype.getMacroHandler = function(name) { * @param {String} text */ Story.prototype.link_macro = function(param, action, text) { - switch (action) { - case "rotate": - if (this.status === Story.CLOSED) { - text = gettext("Publish"); - } else if (this.mode === Story.FEATURED) { - text = gettext("Hide"); - } else { - text = gettext("Close"); - } - } - return HopObject.prototype.link_macro.call(this, param, action, text); + switch (action) { + case "rotate": + if (this.status === Story.CLOSED) { + text = gettext("Publish"); + } else if (this.mode === Story.FEATURED) { + text = gettext("Hide"); + } else { + text = gettext("Close"); + } + } + return HopObject.prototype.link_macro.call(this, param, action, text); } /** @@ -454,34 +454,34 @@ Story.prototype.link_macro = function(param, action, text) { * @param {Object} param */ Story.prototype.summary_macro = function(param) { - param.limit || (param.limit = 15); - var keys, summary; - if (arguments.length > 1) { - res.push(); - var content; - for (var i=1; i 1) { + res.push(); + var content; + for (var i=1; i|\s+)([\w+-_]+:\/\/[^\s]+?)([\.,;:\)\]\"]?)(?=[\s<]|$)/gim; - var re = /(^|\/>|\s+)([!fhtpsr]+:\/\/[^\s]+?)([\.,;:\)\]\"]?)(?=[\s<]|$)/gim - return value.replace(re, function(str, head, url, tail) { - if (url.startsWith("!")) { - return head + url.substring(1) + tail; + param.limit || (param.limit = 50); + // FIXME: The first RegExp has troubles with |\s+)([\w+-_]+:\/\/[^\s]+?)([\.,;:\)\]\"]?)(?=[\s<]|$)/gim; + var re = /(^|\/>|\s+)([!fhtpsr]+:\/\/[^\s]+?)([\.,;:\)\]\"]?)(?=[\s<]|$)/gim + return value.replace(re, function(str, head, url, tail) { + if (url.startsWith("!")) { + return head + url.substring(1) + tail; + } + res.push(); + res.write(head); + if (mode === "plain") { + res.write(url.clip(param.limit)); + } else { + var text, location = /:\/\/([^\/]*)/.exec(url)[1]; + text = location; + if (mode === "extended") { + text = url.replace(/^.+\/([^\/]*)$/, "$1"); } - res.push(); - res.write(head); - if (mode === "plain") { - res.write(url.clip(param.limit)); - } else { - var text, location = /:\/\/([^\/]*)/.exec(url)[1]; - text = location; - if (mode === "extended") { - text = url.replace(/^.+\/([^\/]*)$/, "$1"); - } - html.link({href: url, title: url}, text.clip(param.limit)); - if (mode === "extended" && text !== location) { - res.write(" (" + location + ")"); - } + html.link({href: url, title: url}, text.clip(param.limit)); + if (mode === "extended" && text !== location) { + res.write(" (" + location + ")"); } - res.write(tail); - return res.pop(); - }); + } + res.write(tail); + return res.pop(); + }); } /** * @returns {String} */ Story.prototype.getConfirmText = function() { - return gettext("You are about to delete a story by user {0}.", - this.creator.name); + return gettext("You are about to delete a story by user {0}.", + this.creator.name); } diff --git a/code/Tag/Tag.js b/code/Tag/Tag.js index 28702a02..6dc35148 100644 --- a/code/Tag/Tag.js +++ b/code/Tag/Tag.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,8 +34,8 @@ markgettext("tag"); * @constant */ Tag.MOUNTPOINTS = { - Story: "tags", - Image: "galleries" + Story: "tags", + Image: "galleries" } /** @@ -49,12 +49,12 @@ Tag.DELIMITER = ", "; * @param {String} type */ Tag.add = function(name, type, site) { - var tag = new Tag; - tag.name = name; - tag.type = type; - tag.site = site; - site.$tags.add(tag); - return tag; + var tag = new Tag; + tag.name = name; + tag.type = type; + tag.site = site; + site.$tags.add(tag); + return tag; } /** @@ -69,8 +69,8 @@ Tag.add = function(name, type, site) { * @extends HopObject */ Tag.prototype.constructor = function() { - HopObject.confirmConstructor(Tag); - return this; + HopObject.confirmConstructor(Tag); + return this; } /** @@ -79,88 +79,88 @@ Tag.prototype.constructor = function() { * @returns {Boolean} */ Tag.prototype.getPermission = function(action) { - if (!res.handlers.site.getPermission("main")) { - return false; - } - switch (action) { - case ".": - case "main": - case "rss.xml": - return true; - case "edit": - case "delete": - case "rename": - return User.require(User.PRIVILEGED) || - Membership.require(Membership.MANAGER); - } - return false; + if (!res.handlers.site.getPermission("main")) { + return false; + } + switch (action) { + case ".": + case "main": + case "rss.xml": + return true; + case "edit": + case "delete": + case "rename": + return User.require(User.PRIVILEGED) || + Membership.require(Membership.MANAGER); + } + return false; } Tag.prototype.main_action = function() { - res.handlers.list = new jala.ListRenderer(this.getTagged()); - res.handlers.list.setPageSize(this.site.pageSize); - res.data.title = gettext("Tag: {0}", this.name); - res.data.body = this.renderSkinAsString("$Tag#main"); - res.handlers.site.renderSkin("Site#page"); - res.handlers.site.log(); - return; + res.handlers.list = new jala.ListRenderer(this.getTagged()); + res.handlers.list.setPageSize(this.site.pageSize); + res.data.title = gettext("Tag: {0}", this.name); + res.data.body = this.renderSkinAsString("$Tag#main"); + res.handlers.site.renderSkin("Site#page"); + res.handlers.site.log(); + return; } Tag.prototype.rss_xml_action = function() { - res.contentType = "text/xml"; - res.dependsOn(this.site.modified); - res.digest(); - var tagHubs = this.getTagged().list(0, this.site.pageSize); - var stories = []; - for (var i in tagHubs) { - stories.push(tagHubs[i].tagged); - } - res.write(this.site.getXml(stories)); - return; + res.contentType = "text/xml"; + res.dependsOn(this.site.modified); + res.digest(); + var tagHubs = this.getTagged().list(0, this.site.pageSize); + var stories = []; + for (var i in tagHubs) { + stories.push(tagHubs[i].tagged); + } + res.write(this.site.getXml(stories)); + return; } Tag.prototype.rename_action = function() { - var tag = this; - if (req.data.name) { - // Trim and remove troublesome characters (like ../.. etc.) - // We call getAccessName with a virgin HopObject to allow most names - var name = this.getAccessName.call(new HopObject, File.getName(req.data.name)); - tag = this.site.getTags(this.type, Tags.ALL).get(name); - if (!tag) { - tag = Tag.add(name, this.site, this.type); - } - if (tag !== this) { - this.forEach(function() { - this.tag_id = tag._id; - }); - this.remove(); - res.commit(); - } - } - res.redirect(tag.href()); - return; + var tag = this; + if (req.data.name) { + // Trim and remove troublesome characters (like ../.. etc.) + // We call getAccessName with a virgin HopObject to allow most names + var name = this.getAccessName.call(new HopObject, File.getName(req.data.name)); + tag = this.site.getTags(this.type, Tags.ALL).get(name); + if (!tag) { + tag = Tag.add(name, this.site, this.type); + } + if (tag !== this) { + this.forEach(function() { + this.tag_id = tag._id; + }); + this.remove(); + res.commit(); + } + } + res.redirect(tag.href()); + return; - // FIXME: Actually, the method should work like this but it caused a mess: - if (req.data.name) { - var name = this.getAccessName.call(new HopObject, File.getName(req.data.name)); - var tag = this.site.getTags(this.type, Tags.ALL).get(name); - if (tag) { - if (tag !== this) { - // move tagged items to tag like above - } - } else { - // rename tag like: this.name = name + // FIXME: Actually, the method should work like this but it caused a mess: + if (req.data.name) { + var name = this.getAccessName.call(new HopObject, File.getName(req.data.name)); + var tag = this.site.getTags(this.type, Tags.ALL).get(name); + if (tag) { + if (tag !== this) { + // move tagged items to tag like above } - } + } else { + // rename tag like: this.name = name + } + } } Tag.prototype.delete_action = function() { - var parent = this._parent; - while (this.size() > 0) { - this.get(0).remove(); - }; - this.remove(); - res.redirect(this.site[Tag.MOUNTPOINTS[this.type]].href()); + var parent = this._parent; + while (this.size() > 0) { + this.get(0).remove(); + }; + this.remove(); + res.redirect(this.site[Tag.MOUNTPOINTS[this.type]].href()); } /** @@ -169,14 +169,14 @@ Tag.prototype.delete_action = function() { * @returns {String} */ Tag.prototype.href = function(action) { - res.push(); - res.write(this.site[Tag.MOUNTPOINTS[this.type]].href()); - res.write(encodeURIComponent(this.name)); - res.write("/"); - if (action) { - res.write(java.net.URLEncoder.encode(action)); - } - return res.pop(); + res.push(); + res.write(this.site[Tag.MOUNTPOINTS[this.type]].href()); + res.write(encodeURIComponent(this.name)); + res.write("/"); + if (action) { + res.write(java.net.URLEncoder.encode(action)); + } + return res.pop(); } /** @@ -185,26 +185,26 @@ Tag.prototype.href = function(action) { * @param {String} type */ Tag.prototype.permission_macro = function(param, type) { - return this.getPermission(type); + return this.getPermission(type); } /** * @returns {Story[]|Image[]} */ Tag.prototype.getTagged = function() { - return this[pluralize(this.type.toLowerCase())]; + return this[pluralize(this.type.toLowerCase())]; } /** * @returns {String} */ Tag.prototype.getTitle = function() { - return this.name; + return this.name; } /** * @returns {String} */ Tag.prototype.toString = function() { - return this.type + " tag " + this.name + " of Site " + this.site.alias; + return this.type + " tag " + this.name + " of Site " + this.site.alias; } diff --git a/code/TagHub/TagHub.js b/code/TagHub/TagHub.js index 3fcf9487..ffb3d4e6 100644 --- a/code/TagHub/TagHub.js +++ b/code/TagHub/TagHub.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,18 +34,18 @@ * @returns {TagHub} */ TagHub.add = function(name, tagged, user) { - HopObject.confirmConstructor(this); - var hub = new TagHub; - var site = tagged.site || res.handlers.site; - var tag = site.getTags(tagged._prototype, Tags.ALL).get(name); - if (!tag) { - tag = Tag.add(name, tagged._prototype, site); - } - hub.tag = tag; - hub.tagged = tagged; - hub.user = user; - tagged.tags.add(hub); - return hub; + HopObject.confirmConstructor(this); + var hub = new TagHub; + var site = tagged.site || res.handlers.site; + var tag = site.getTags(tagged._prototype, Tags.ALL).get(name); + if (!tag) { + tag = Tag.add(name, tagged._prototype, site); + } + hub.tag = tag; + hub.tagged = tagged; + hub.user = user; + tagged.tags.add(hub); + return hub; } /** @@ -60,8 +60,8 @@ TagHub.add = function(name, tagged, user) { * @extends HopObject */ TagHub.prototype.constructor = function() { - HopObject.confirmConstructor(TagHub); - return this; + HopObject.confirmConstructor(TagHub); + return this; } /** @@ -70,18 +70,18 @@ TagHub.prototype.constructor = function() { * @returns {HopObject} */ TagHub.prototype.getMacroHandler = function(name) { - switch (name.toLowerCase()) { - case "tagged": - case "story": - case "image": - return this.tagged; - break; - } + switch (name.toLowerCase()) { + case "tagged": + case "story": + case "image": + return this.tagged; + break; + } } /** * @return {String} */ TagHub.prototype.toString = function() { - return "Tag " + this.tag.name + " of " + this.tagged.toString(); + return "Tag " + this.tag.name + " of " + this.tagged.toString(); } diff --git a/code/Tags/Tags.js b/code/Tags/Tags.js index 731c8e9a..d9e2cb45 100644 --- a/code/Tags/Tags.js +++ b/code/Tags/Tags.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -49,27 +49,27 @@ Tags.ALPHABETICAL = "alphabetical"; * @returns {Boolean} */ Tags.prototype.getPermission = function(action) { - return res.handlers.site.getPermission("main"); + return res.handlers.site.getPermission("main"); } Tags.prototype.main_action = function() { - var action = this.getAction(); - if (req.data.group) { - this.setGroup(req.data.group) - res.redirect(this.href(action)); - } - if (req.data.page) { - this.setPage(req.data.page); - res.redirect(this.href(action)); - } - res.data.title = this.getTitle(); - res.data.body = this.renderSkinAsString("$Tags#" + req.action); - res.handlers.site.renderSkin("Site#page"); - return; + var action = this.getAction(); + if (req.data.group) { + this.setGroup(req.data.group) + res.redirect(this.href(action)); + } + if (req.data.page) { + this.setPage(req.data.page); + res.redirect(this.href(action)); + } + res.data.title = this.getTitle(); + res.data.body = this.renderSkinAsString("$Tags#" + req.action); + res.handlers.site.renderSkin("Site#page"); + return; } Tags.prototype.admin_action = function() { - return this.main_action(); + return this.main_action(); } /** @@ -78,64 +78,64 @@ Tags.prototype.admin_action = function() { * @returns {HopObject} */ Tags.prototype.getChildElement = function(id) { - var child = this[id] || this.get(Tags.ALL).get(id); - return child; + var child = this[id] || this.get(Tags.ALL).get(id); + return child; } /** * */ Tags.prototype.alphabet_macro = function() { - if (this.get(Tags.ALL).size() < 50) { - return; - } + if (this.get(Tags.ALL).size() < 50) { + return; + } - var self = this; - var collection = this.get(Tags.ALPHABETICAL); - var prefix = "?group="; - var group = this.getGroup(); + var self = this; + var collection = this.get(Tags.ALPHABETICAL); + var prefix = "?group="; + var group = this.getGroup(); - var add = function(text, id) { - if (group === id) { - res.write(text); - } else { - html.link({href: self.href(self.getAction()) + prefix + id}, text); - } - res.write(" "); - return; - }; + var add = function(text, id) { + if (group === id) { + res.write(text); + } else { + html.link({href: self.href(self.getAction()) + prefix + id}, text); + } + res.write(" "); + return; + }; - add("*", Tags.ALL); - collection.forEach(function() { - add(this._id, this._id); - }); - if (this.get(Tags.OTHER).size() > 0) { - add("?", Tags.OTHER); - } - return; + add("*", Tags.ALL); + collection.forEach(function() { + add(this._id, this._id); + }); + if (this.get(Tags.OTHER).size() > 0) { + add("?", Tags.OTHER); + } + return; } /** * */ Tags.prototype.pager_macro = function() { - var page = this.getPage(); - var max = this.get(this.getGroup()).size(); - var size = this.getPageSize(); - var total = Math.ceil(max / size); - if (total < 2) { - return; - } - var prefix = "?page="; - for (var i=1; i<=total; i+=1) { - if (i == page) { - res.write(i); - } else { - html.link({href: this.href(this.getAction()) + prefix + i}, i); - } - res.write(" "); - } - return; + var page = this.getPage(); + var max = this.get(this.getGroup()).size(); + var size = this.getPageSize(); + var total = Math.ceil(max / size); + if (total < 2) { + return; + } + var prefix = "?page="; + for (var i=1; i<=total; i+=1) { + if (i == page) { + res.write(i); + } else { + html.link({href: this.href(this.getAction()) + prefix + i}, i); + } + res.write(" "); + } + return; } /** @@ -143,34 +143,34 @@ Tags.prototype.pager_macro = function() { * @param {Object} param */ Tags.prototype.header_macro = function(param) { - var header = this.getHeader(); - for each (var title in header) { - this.renderSkin("Tags#header", {title: title}); - } - return; + var header = this.getHeader(); + for each (var title in header) { + this.renderSkin("Tags#header", {title: title}); + } + return; } /** * */ Tags.prototype.list_macro = function(param, skin) { - var page = this.getPage(); - var size = param.limit ? Math.min(param.limit, 100) : this.getPageSize(); - var start = (page - 1) * size; - var collection = this.get(this.getGroup()).list(start, size); - // FIXME: ListRenderer should do this - //var list = new jala.ListRenderer(collection); - //list.render(skin || mgrlistitem); - var index = start + 1; - for each (var item in collection) { - // FIXME: Is there a more elegant solution? - if (item.constructor !== Tag) { - item = item.get(0); - } - item.renderSkin(skin || "$Tag#listItem", {index: index}); - index += 1; - } - return; + var page = this.getPage(); + var size = param.limit ? Math.min(param.limit, 100) : this.getPageSize(); + var start = (page - 1) * size; + var collection = this.get(this.getGroup()).list(start, size); + // FIXME: ListRenderer should do this + //var list = new jala.ListRenderer(collection); + //list.render(skin || mgrlistitem); + var index = start + 1; + for each (var item in collection) { + // FIXME: Is there a more elegant solution? + if (item.constructor !== Tag) { + item = item.get(0); + } + item.renderSkin(skin || "$Tag#listItem", {index: index}); + index += 1; + } + return; } /** @@ -179,14 +179,14 @@ Tags.prototype.list_macro = function(param, skin) { * @returns {TagHub[]} */ Tags.prototype.get = function(group) { - return this._parent.getTags(this._id, group || this.getGroup()); + return this._parent.getTags(this._id, group || this.getGroup()); } /** * @returns {String} */ Tags.prototype.getGroup = function() { - return decodeURIComponent(session.data[this.href("group")] || Tags.ALL); + return decodeURIComponent(session.data[this.href("group")] || Tags.ALL); } /** @@ -194,16 +194,16 @@ Tags.prototype.getGroup = function() { * @param {String} group */ Tags.prototype.setGroup = function(group) { - session.data[this.href("group")] = encodeURIComponent(group); - this.setPage(1); - return; + session.data[this.href("group")] = encodeURIComponent(group); + this.setPage(1); + return; } /** * @returns {Number} */ Tags.prototype.getPage = function() { - return session.data[this.href("page")] || 1; + return session.data[this.href("page")] || 1; } /** @@ -211,22 +211,22 @@ Tags.prototype.getPage = function() { * @param {Number} page */ Tags.prototype.setPage = function(page) { - session.data[this.href("page")] = page; - return; + session.data[this.href("page")] = page; + return; } /** * @returns {Number} */ Tags.prototype.getPageSize = function() { - return 25; + return 25; } /** * @returns {String} */ Tags.prototype.getAction = function() { - return (req.action === "main" ? String.EMPTY : req.action); + return (req.action === "main" ? String.EMPTY : req.action); } /** @@ -235,8 +235,8 @@ Tags.prototype.getAction = function() { * @see Images#getAdminHeader */ Tags.prototype.getHeader = function() { - if (this._parent.getAdminHeader) { - return this._parent.getAdminHeader(this._id) || []; - } - return []; + if (this._parent.getAdminHeader) { + return this._parent.getAdminHeader(this._id) || []; + } + return []; } diff --git a/code/User/User.js b/code/User/User.js index 0e50e24c..a85926c0 100644 --- a/code/User/User.js +++ b/code/User/User.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -48,37 +48,37 @@ User.HASHCOOKIE = getProperty("hashCookie", "antvilleHash"); * @returns {User} */ User.add = function(data) { - HopObject.confirmConstructor(this); - var user = new User; - var now = new Date; - user.map({ - created: now, - email: data.email, - hash: data.hash, - name: data.name, - salt: session.data.token, - status: User.REGULAR, - url: data.url - }); - root.users.add(user); - return user; + HopObject.confirmConstructor(this); + var user = new User; + var now = new Date; + user.map({ + created: now, + email: data.email, + hash: data.hash, + name: data.name, + salt: session.data.token, + status: User.REGULAR, + url: data.url + }); + root.users.add(user); + return user; } /** * FIXME: Still needs a solution whether and how to remove a user’s sites */ User.remove = function() { - return; // FIXME: Disabled until thoroughly tested - if (this.constructor === User) { - HopObject.remove.call(this.comments); - HopObject.remove.call(this.files); - HopObject.remove.call(this.images); - //HopObject.remove.call(this.sites); - HopObject.remove.call(this.stories); - this.deleteMetadata(); - this.remove(); - } - return; + return; // FIXME: Disabled until thoroughly tested + if (this.constructor === User) { + HopObject.remove.call(this.comments); + HopObject.remove.call(this.files); + HopObject.remove.call(this.images); + //HopObject.remove.call(this.sites); + HopObject.remove.call(this.stories); + this.deleteMetadata(); + this.remove(); + } + return; } /** @@ -87,7 +87,7 @@ User.remove = function() { * @returns {User} */ User.getByName = function(name) { - return root.users.get(name); + return root.users.get(name); } /** @@ -96,17 +96,17 @@ User.getByName = function(name) { * @see defineConstants */ User.getStatus = defineConstants(User, markgettext("Blocked"), - markgettext("Regular"), markgettext("Trusted"), - markgettext("Privileged")); + markgettext("Regular"), markgettext("Trusted"), + markgettext("Privileged")); /** * @returns {String} */ User.getSalt = function() { - var salt = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 8); - var random = java.security.SecureRandom.getInstance("SHA1PRNG"); - random.nextBytes(salt); - return Packages.sun.misc.BASE64Encoder().encode(salt); + var salt = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 8); + var random = java.security.SecureRandom.getInstance("SHA1PRNG"); + random.nextBytes(salt); + return Packages.sun.misc.BASE64Encoder().encode(salt); } /** @@ -116,46 +116,46 @@ User.getSalt = function() { * @returns {User} */ User.register = function(data) { - if (!data.name) { - throw Error(gettext("Please enter a username.")); - } + if (!data.name) { + throw Error(gettext("Please enter a username.")); + } - data.name = data.name.trim(); - if (data.name.length > 30) { - throw Error(gettext("Sorry, the username you entered is too long. Please choose a shorter one.")); - } else if (data.name !== stripTags(data.name) || NAMEPATTERN.test(data.name)) { - throw Error(gettext("Please avoid special characters or HTML code in the name field.")); - } else if (data.name !== root.users.getAccessName(data.name)) { - throw Error(gettext("Sorry, the user name you entered already exists. Please enter a different one.")); - } + data.name = data.name.trim(); + if (data.name.length > 30) { + throw Error(gettext("Sorry, the username you entered is too long. Please choose a shorter one.")); + } else if (data.name !== stripTags(data.name) || NAMEPATTERN.test(data.name)) { + throw Error(gettext("Please avoid special characters or HTML code in the name field.")); + } else if (data.name !== root.users.getAccessName(data.name)) { + throw Error(gettext("Sorry, the user name you entered already exists. Please enter a different one.")); + } - data.email && (data.email = data.email.trim()); - if (!validateEmail(data.email)) { - throw Error(gettext("Please enter a valid e-mail address")); - } + data.email && (data.email = data.email.trim()); + if (!validateEmail(data.email)) { + throw Error(gettext("Please enter a valid e-mail address")); + } - if (User.isBlacklisted(data)) { - throw Error("Sequere pecuniam ad meliora."); - } + if (User.isBlacklisted(data)) { + throw Error("Sequere pecuniam ad meliora."); + } - // Create hash from password for JavaScript-disabled browsers - if (!data.hash) { - // Check if passwords match - if (!data.password || !data.passwordConfirm) { - throw Error(gettext("Could not verify your password. Please repeat your input.")) - } else if (data.password !== data.passwordConfirm) { - throw Error(gettext("Unfortunately, your passwords did not match. Please repeat your input.")); - } - data.hash = (data.password + session.data.token).md5(); - } + // Create hash from password for JavaScript-disabled browsers + if (!data.hash) { + // Check if passwords match + if (!data.password || !data.passwordConfirm) { + throw Error(gettext("Could not verify your password. Please repeat your input.")) + } else if (data.password !== data.passwordConfirm) { + throw Error(gettext("Unfortunately, your passwords did not match. Please repeat your input.")); + } + data.hash = (data.password + session.data.token).md5(); + } - var user = User.add(data); - // grant trust and sysadmin-rights if there's no sysadmin 'til now - if (root.admins.size() < 1) { - user.status = User.PRIVILEGED; - } - session.login(user); - return user; + var user = User.add(data); + // grant trust and sysadmin-rights if there's no sysadmin 'til now + if (root.admins.size() < 1) { + user.status = User.PRIVILEGED; + } + session.login(user); + return user; } /** @@ -164,72 +164,72 @@ User.register = function(data) { * @returns {Boolean} */ User.isBlacklisted = function(data) { - var url; - var name = encodeURIComponent(data.name); - var email = encodeURIComponent(data.email); - var ip = encodeURIComponent(data.http_remotehost); + var url; + var name = encodeURIComponent(data.name); + var email = encodeURIComponent(data.email); + var ip = encodeURIComponent(data.http_remotehost); - var key = getProperty("botscout.apikey"); - if (key) { - url = ["http://botscout.com/test/?multi", "&key=", key, "&mail=", email, "&ip=", ip]; - try { - mime = getURL(url.join(String.EMPTY)); - if (mime && mime.text && mime.text.startsWith("Y")) { - return true; - } - } catch (ex) { - app.log("Exception while trying to check blacklist URL " + url); - app.log(ex); - } - } - //return false; - - // We only get here if botscout.com does not already blacklist the ip or email address - url = ["http://www.stopforumspam.com/api?f=json", "&email=", email]; - if (ip.match(/^(?:\d{1,3}\.){3}\d{1,3}$/)) { - url.push("&ip=", ip); - } - try { + var key = getProperty("botscout.apikey"); + if (key) { + url = ["http://botscout.com/test/?multi", "&key=", key, "&mail=", email, "&ip=", ip]; + try { mime = getURL(url.join(String.EMPTY)); - } catch (ex) { + if (mime && mime.text && mime.text.startsWith("Y")) { + return true; + } + } catch (ex) { app.log("Exception while trying to check blacklist URL " + url); app.log(ex); - } - if (mime && mime.text) { - var result = JSON.parse(mime.text); - if (result.success) { - return !!(result.email.appears || (result.ip && result.ip.appears)); - } - } - return false; + } + } + //return false; + + // We only get here if botscout.com does not already blacklist the ip or email address + url = ["http://www.stopforumspam.com/api?f=json", "&email=", email]; + if (ip.match(/^(?:\d{1,3}\.){3}\d{1,3}$/)) { + url.push("&ip=", ip); + } + try { + mime = getURL(url.join(String.EMPTY)); + } catch (ex) { + app.log("Exception while trying to check blacklist URL " + url); + app.log(ex); + } + if (mime && mime.text) { + var result = JSON.parse(mime.text); + if (result.success) { + return !!(result.email.appears || (result.ip && result.ip.appears)); + } + } + return false; } /** * */ User.autoLogin = function() { - if (session.user) { - return; - } - var name = req.cookies[User.COOKIE]; - var hash = req.cookies[User.HASHCOOKIE]; - if (!name || !hash) { - return; - } - var user = User.getByName(name); - if (!user) { - return; - } - var ip = req.data.http_remotehost.clip(getProperty("cookieLevel", "4"), - String.EMPTY, "\\."); - if ((user.hash + ip).md5() !== hash) { - return; - } - session.login(user); - user.touch(); - res.message = gettext('Welcome to {0}, {1}. Have fun!', - res.handlers.site.title, user.name); - return; + if (session.user) { + return; + } + var name = req.cookies[User.COOKIE]; + var hash = req.cookies[User.HASHCOOKIE]; + if (!name || !hash) { + return; + } + var user = User.getByName(name); + if (!user) { + return; + } + var ip = req.data.http_remotehost.clip(getProperty("cookieLevel", "4"), + String.EMPTY, "\\."); + if ((user.hash + ip).md5() !== hash) { + return; + } + session.login(user); + user.touch(); + res.message = gettext('Welcome to {0}, {1}. Have fun!', + res.handlers.site.title, user.name); + return; } /** @@ -238,29 +238,29 @@ User.autoLogin = function() { * @returns {User} */ User.login = function(data) { - var user = User.getByName(data.name); - if (!user) { - throw Error(gettext("Unfortunately, your login failed. Maybe a typo?")); - } - var digest = data.digest; - // Calculate digest for JavaScript-disabled browsers - if (!digest) { - app.logger.warn("Received clear text password from " + req.data.http_referer); - digest = ((data.password + user.salt).md5() + session.data.token).md5(); - } - // Check if login is correct - if (digest !== user.getDigest(session.data.token)) { - throw Error(gettext("Unfortunately, your login failed. Maybe a typo?")) - } - if (data.remember) { - // Set long running cookies for automatic login - res.setCookie(User.COOKIE, user.name, 365); - var ip = req.data.http_remotehost.clip(getProperty("cookieLevel", "4"), String.EMPTY, "\\."); - res.setCookie(User.HASHCOOKIE, (user.hash + ip).md5(), 365); - } - user.touch(); - session.login(user); - return user; + var user = User.getByName(data.name); + if (!user) { + throw Error(gettext("Unfortunately, your login failed. Maybe a typo?")); + } + var digest = data.digest; + // Calculate digest for JavaScript-disabled browsers + if (!digest) { + app.logger.warn("Received clear text password from " + req.data.http_referer); + digest = ((data.password + user.salt).md5() + session.data.token).md5(); + } + // Check if login is correct + if (digest !== user.getDigest(session.data.token)) { + throw Error(gettext("Unfortunately, your login failed. Maybe a typo?")) + } + if (data.remember) { + // Set long running cookies for automatic login + res.setCookie(User.COOKIE, user.name, 365); + var ip = req.data.http_remotehost.clip(getProperty("cookieLevel", "4"), String.EMPTY, "\\."); + res.setCookie(User.HASHCOOKIE, (user.hash + ip).md5(), 365); + } + user.touch(); + session.login(user); + return user; } /** @@ -281,33 +281,33 @@ User.logout = function() { * @returns {Boolean} */ User.require = function(requiredStatus) { - var status = [User.BLOCKED, User.REGULAR, User.TRUSTED, User.PRIVILEGED]; - if (requiredStatus && session.user) { - return status.indexOf(session.user.status) >= status.indexOf(requiredStatus); - } - return false; + var status = [User.BLOCKED, User.REGULAR, User.TRUSTED, User.PRIVILEGED]; + if (requiredStatus && session.user) { + return status.indexOf(session.user.status) >= status.indexOf(requiredStatus); + } + return false; } /** * @returns {String} */ User.getCurrentStatus = function() { - if (session.user) { - return session.user.status; - } - return null; + if (session.user) { + return session.user.status; + } + return null; } /** * @returns {Membership} */ User.getMembership = function() { - var membership; - if (session.user) { - membership = Membership.getByName(session.user.name); - } - HopObject.confirmConstructor(Membership); - return membership || new Membership; + var membership; + if (session.user) { + membership = Membership.getByName(session.user.name); + } + HopObject.confirmConstructor(Membership); + return membership || new Membership; } /** @@ -315,19 +315,19 @@ User.getMembership = function() { * @param {String} url */ User.setLocation = function(url) { - session.data.location = url || req.data.http_referer; - //app.debug("Pushed location " + session.data.location); - return; + session.data.location = url || req.data.http_referer; + //app.debug("Pushed location " + session.data.location); + return; } /** * @returns {String} */ User.getLocation = function() { - var url = session.data.location; - delete session.data.location; - //app.debug("Popped location " + url); - return url; + var url = session.data.location; + delete session.data.location; + //app.debug("Popped location " + url); + return url; } /** @@ -336,15 +336,15 @@ User.getLocation = function() { * @param {String} newName The desired name of the user account. */ User.rename = function(currentName, newName) { - var user = User.getByName(currentName); - if (user) { - if (user.name === newName) { - return newName; - } - user.name = root.users.getAccessName(newName); - return user.name; - } - return currentName; + var user = User.getByName(currentName); + if (user) { + if (user.name === newName) { + return newName; + } + user.name = root.users.getAccessName(newName); + return user.name; + } + return currentName; } /** @@ -372,8 +372,8 @@ User.rename = function(currentName, newName) { * @extends HopObject */ User.prototype.constructor = function(data) { - HopObject.confirmConstructor(User); - return this; + HopObject.confirmConstructor(User); + return this; } /** @@ -387,7 +387,7 @@ User.prototype.onLogout = function() { /* ... */ } * @returns {Boolean} */ User.prototype.getPermission = function(action) { - return User.require(User.PRIVILEGED); + return User.require(User.PRIVILEGED); } /** @@ -395,45 +395,45 @@ User.prototype.getPermission = function(action) { * @param {Object} data */ User.prototype.update = function(data) { - if (!data.digest && data.password) { - data.digest = ((data.password + this.salt).md5() + - session.data.token).md5(); - } - if (data.digest) { - if (data.digest !== this.getDigest(session.data.token)) { - throw Error(gettext("Oops, your old password is incorrect. Please re-enter it.")); + if (!data.digest && data.password) { + data.digest = ((data.password + this.salt).md5() + + session.data.token).md5(); + } + if (data.digest) { + if (data.digest !== this.getDigest(session.data.token)) { + throw Error(gettext("Oops, your old password is incorrect. Please re-enter it.")); + } + if (!data.hash) { + if (!data.newPassword || !data.newPasswordConfirm) { + throw Error(gettext("Please specify a new password.")); + } else if (data.newPassword !== data.newPasswordConfirm) { + throw Error(gettext("Unfortunately, your passwords did not match. Please repeat your input.")); } - if (!data.hash) { - if (!data.newPassword || !data.newPasswordConfirm) { - throw Error(gettext("Please specify a new password.")); - } else if (data.newPassword !== data.newPasswordConfirm) { - throw Error(gettext("Unfortunately, your passwords did not match. Please repeat your input.")); - } - data.hash = (data.newPassword + session.data.token).md5(); - } - this.map({ - hash: data.hash, - salt: session.data.token - }); - } - if (!(data.email = validateEmail(data.email))) { - throw Error(gettext("Please enter a valid e-mail address")); - } - if (data.url && !(data.url = validateUrl(data.url))) { - throw Error(gettext("Please enter a valid URL")); - } - this.email = data.email; - this.url = data.url; - this.touch(); - return this; + data.hash = (data.newPassword + session.data.token).md5(); + } + this.map({ + hash: data.hash, + salt: session.data.token + }); + } + if (!(data.email = validateEmail(data.email))) { + throw Error(gettext("Please enter a valid e-mail address")); + } + if (data.url && !(data.url = validateUrl(data.url))) { + throw Error(gettext("Please enter a valid URL")); + } + this.email = data.email; + this.url = data.url; + this.touch(); + return this; } /** * */ User.prototype.touch = function() { - this.modified = new Date; - return; + this.modified = new Date; + return; } /** @@ -442,8 +442,8 @@ User.prototype.touch = function() { * @returns {String} */ User.prototype.getDigest = function(token) { - token || (token = String.EMPTY); - return (this.hash + token).md5(); + token || (token = String.EMPTY); + return (this.hash + token).md5(); } /** @@ -452,20 +452,20 @@ User.prototype.getDigest = function(token) { * @returns {Object} */ User.prototype.getFormOptions = function(name) { - switch (name) { - case "status": - return User.getStatus(); - } + switch (name) { + case "status": + return User.getStatus(); + } } /** * Enable <% user.email %> macro for privileged users only */ User.prototype.email_macro = function() { - if (User.require(User.PRIVILEGED)) { - res.write(this.email); - } - return; + if (User.require(User.PRIVILEGED)) { + res.write(this.email); + } + return; } /** @@ -474,19 +474,19 @@ User.prototype.email_macro = function() { * @param {String} type */ User.prototype.list_macro = function(param, type) { - switch (type) { - case "sites": - var memberships = session.user.list(); - memberships.sort(function(a, b) { - return b.site.modified - a.site.modified; - }); - memberships.forEach(function(membership) { - var site; - if (site = membership.get("site")) { - site.renderSkin("$Site#listItem"); - } - return; - }); - } - return; + switch (type) { + case "sites": + var memberships = session.user.list(); + memberships.sort(function(a, b) { + return b.site.modified - a.site.modified; + }); + memberships.forEach(function(membership) { + var site; + if (site = membership.get("site")) { + site.renderSkin("$Site#listItem"); + } + return; + }); + } + return; } diff --git a/code/Vote/Vote.js b/code/Vote/Vote.js index 45ca2cfb..fc8324d4 100644 --- a/code/Vote/Vote.js +++ b/code/Vote/Vote.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -35,13 +35,13 @@ markgettext("vote"); * @returns {Vote} */ Vote.add = function(choice, poll) { - HopObject.confirmConstructor(Vote); - var vote = new Vote; - vote.choice = choice; - vote.creator = session.user; - vote.creator_name = session.user.name; - vote.created = vote.modified = new Date; - poll.votes.add(vote); + HopObject.confirmConstructor(Vote); + var vote = new Vote; + vote.choice = choice; + vote.creator = session.user; + vote.creator_name = session.user.name; + vote.created = vote.modified = new Date; + poll.votes.add(vote); return vote; } @@ -57,6 +57,6 @@ Vote.add = function(choice, poll) { * @extends HopObject */ Vote.prototype.constructor = function(choice) { - HopObject.confirmConstructor(this); - return this; + HopObject.confirmConstructor(this); + return this; } diff --git a/compat/Comment/Comment.js b/compat/Comment/Comment.js index babdea60..de479aed 100644 --- a/compat/Comment/Comment.js +++ b/compat/Comment/Comment.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -24,5 +24,5 @@ // $URL$ Comment.prototype.replylink_macro = function(param) { - return this.link_macro(param, "comment"); + return this.link_macro(param, "comment"); } diff --git a/compat/File/File.js b/compat/File/File.js index 494dc56c..801505ab 100644 --- a/compat/File/File.js +++ b/compat/File/File.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -27,74 +27,74 @@ relocateProperty(Site, "createtime", "created"); relocateProperty(Site, "modifytime", "modified"); File.prototype.alias_macro = function(param) { - if (param.as === "editor") { - this.input_macro(param, "name"); - } else if (param.as === "link") { - param.title = encodeForm(this.description); - this.link_filter(this.name, param, this.href()); - } else { - res.write(this.name); - } - return; + if (param.as === "editor") { + this.input_macro(param, "name"); + } else if (param.as === "link") { + param.title = encodeForm(this.description); + this.link_filter(this.name, param, this.href()); + } else { + res.write(this.name); + } + return; } File.prototype.description_macro = function(param) { - if (param.as === "editor") { - this.input_macro(param, "description"); - } else { - res.write(this.description); - } - return; + if (param.as === "editor") { + this.input_macro(param, "description"); + } else { + res.write(this.description); + } + return; } File.prototype.filesize_macro = function(param) { - return this.contentLength_macro(param); + return this.contentLength_macro(param); } File.prototype.editlink_macro = function(param) { - return this.link_macro(param, "edit", param.text || "edit"); + return this.link_macro(param, "edit", param.text || "edit"); } File.prototype.deletelink_macro = function(param) { - res.push(); - var image; - if (param.image && (image = this.site.images.get(param.image))) { - image.render_macro(param); - } else { - res.write(param.text || "delete"); - } - return this.link_macro(param, "delete", res.pop()); + res.push(); + var image; + if (param.image && (image = this.site.images.get(param.image))) { + image.render_macro(param); + } else { + res.write(param.text || "delete"); + } + return this.link_macro(param, "delete", res.pop()); } File.prototype.viewlink_macro = function(param) { - param.title = encodeForm(this.description); - return this.link_macro(param, ".", param.text || "view") + param.title = encodeForm(this.description); + return this.link_macro(param, ".", param.text || "view") } File.prototype.mimetype_macro = function(param) { - return res.write(this.contentType); + return res.write(this.contentType); } File.prototype.filetype_macro = function(param) { - if (this.contentType) { - res.write(this.contentType.substring(this.contentType.indexOf("/") + 1)); - } else { - var i = this.name.lastIndexOf("."); - if (i > -1) { - res.write(this.name.substring(i+1, this.name.length)); - } - } - return; + if (this.contentType) { + res.write(this.contentType.substring(this.contentType.indexOf("/") + 1)); + } else { + var i = this.name.lastIndexOf("."); + if (i > -1) { + res.write(this.name.substring(i+1, this.name.length)); + } + } + return; } File.prototype.clicks_macro = function(param) { - if (!this.requests) { - res.write(param.no || "no downloads"); - } else if (this.requests < 2) { - res.write(param.one || "one download"); - } else { - res.write(param.more ? this.requests + " " + param.more : - this.requests + " downloads"); - } - return; + if (!this.requests) { + res.write(param.no || "no downloads"); + } else if (this.requests < 2) { + res.write(param.one || "one download"); + } else { + res.write(param.more ? this.requests + " " + param.more : + this.requests + " downloads"); + } + return; } diff --git a/compat/Global/Global.js b/compat/Global/Global.js index 6d453e4a..361dc04e 100644 --- a/compat/Global/Global.js +++ b/compat/Global/Global.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,194 +26,194 @@ app.addRepository("modules/helma/Color.js"); var disableAction = function(msg) { - res.data.title = msg + " :("; - res.data.body = msg + ". " + "Sorry."; - this.renderSkin("Site#page"); - return; + res.data.title = msg + " :("; + res.data.body = msg + ". " + "Sorry."; + this.renderSkin("Site#page"); + return; } var relocateProperty = function(proto, name, key) { - if (!proto || !name) { - return; - } - key || (key = name); - proto.prototype.__defineGetter__(name, function() { - return this[key]; - }); - proto.prototype.__defineSetter__(name, function(value) { - this[key] = value; - return; - }); - return addPropertyMacro.apply(this, arguments); + if (!proto || !name) { + return; + } + key || (key = name); + proto.prototype.__defineGetter__(name, function() { + return this[key]; + }); + proto.prototype.__defineSetter__(name, function(value) { + this[key] = value; + return; + }); + return addPropertyMacro.apply(this, arguments); } var addPropertyMacro = function(proto, name, key) { - // These two are managed by the HopObject prototype already - if (name === "createtime" || name === "modifytime") { - return; - } - key || (key = name); - proto.prototype[name + "_macro"] = function(param) { - if (param.as === "editor") { - this.input_macro(param, key); - } else { - res.write(this[key]); - } - }; - return; + // These two are managed by the HopObject prototype already + if (name === "createtime" || name === "modifytime") { + return; + } + key || (key = name); + proto.prototype[name + "_macro"] = function(param) { + if (param.as === "editor") { + this.input_macro(param, key); + } else { + res.write(this[key]); + } + }; + return; } var formatTimestamp = function() { - return formatDate.apply(this, arguments); + return formatDate.apply(this, arguments); } var linkedpath_macro = breadcrumbs_macro; function link_macro() { - var param = arguments[0]; - if (param.to) { - param.url = param.to; - delete param.to; - } - return renderLink.apply(this, arguments); + var param = arguments[0]; + if (param.to) { + param.url = param.to; + delete param.to; + } + return renderLink.apply(this, arguments); } function logo_macro(param, name) { - return image_macro.call(global, param, "/" + (name || param.name || "smallchaos")); + return image_macro.call(global, param, "/" + (name || param.name || "smallchaos")); } function input_macro(param) { - switch (param.type) { - case "button": - break; + switch (param.type) { + case "button": + break; - case "radio": - param.selectedValue = req.data[param.name]; break; + case "radio": + param.selectedValue = req.data[param.name]; break; - default: - param.value = param.name && req.data[param.name] ? - req.data[param.name] : param.value; - } + default: + param.value = param.name && req.data[param.name] ? + req.data[param.name] : param.value; + } - switch (param.type) { - case "textarea" : - html.textArea(param); break; + switch (param.type) { + case "textarea" : + html.textArea(param); break; - case "checkbox" : - html.checkBox(param); break; + case "checkbox" : + html.checkBox(param); break; - case "button" : - // FIXME: this is left for backwards compatibility - html.submit(param); break; + case "button" : + // FIXME: this is left for backwards compatibility + html.submit(param); break; - case "submit" : - html.submit(param); break; + case "submit" : + html.submit(param); break; - case "password" : - html.password(param); break; + case "password" : + html.password(param); break; - case "radio" : - html.radioButton(param); break; + case "radio" : + html.radioButton(param); break; - case "file" : - html.file(param); break; + case "file" : + html.file(param); break; - default : - html.input(param); - } - return; + default : + html.input(param); + } + return; } // FIXME: This method deserves some more compatibility pampering // (eg. itempre/suffix) function storylist_macro(param) { - var id = param.of ? param.of + "/stories" : "stories"; - return list_macro(param, id, param.limit); + var id = param.of ? param.of + "/stories" : "stories"; + return list_macro(param, id, param.limit); } function sitelist_macro(param) { - param.limit || (param.limit = 10); - return list_macro(param, "updates", Math.min(param.limit, 25)); + param.limit || (param.limit = 10); + return list_macro(param, "updates", Math.min(param.limit, 25)); } // FIXME: This method deserves some more compatibility pampering // (eg. itempre/suffix, as="thumbnail") function imagelist_macro(param) { - var id = param.of ? param.of + "/images" : "images"; - return list_macro(param, id, param.limit); + var id = param.of ? param.of + "/images" : "images"; + return list_macro(param, id, param.limit); } // FIXME: This method deserves some more compatibility pampering // (eg. itempre/suffix, limit) function topiclist_macro(param) { - var site = param.of ? root.get(param.of) : res.handlers.site; - if (site) { - site.tags.list_macro(param, param.skin); - } - return; + var site = param.of ? root.get(param.of) : res.handlers.site; + if (site) { + site.tags.list_macro(param, param.skin); + } + return; } function username_macro(param) { - if (!session.user) { - return; - } - if (session.user.url && param.as === "link") { - html.link({href: session.user.url}, session.user.name); - } else if (session.user.url && param.as === "url") { - res.write(session.user.url); - } else { - res.write(session.user.name); - } - return; + if (!session.user) { + return; + } + if (session.user.url && param.as === "link") { + html.link({href: session.user.url}, session.user.name); + } else if (session.user.url && param.as === "url") { + res.write(session.user.url); + } else { + res.write(session.user.name); + } + return; } function spacer_macro(param) { - param.width || (param.width = 2); - param.height || (param.height = 2); - param.border || (param.border = 0); - param.alt = ""; - param.name = "/pixel.gif"; - return image_macro(param); + param.width || (param.width = 2); + param.height || (param.height = 2); + param.border || (param.border = 0); + param.alt = ""; + param.name = "/pixel.gif"; + return image_macro(param); } function fakemail_macro(param) { var tldList = ["com", "net", "org", "mil", "edu", "de", "biz", "de", "ch", - "at", "ru", "de", "tv", "com", "st", "br", "fr", "de", "nl", "dk", - "ar", "jp", "eu", "it", "es", "com", "us", "ca", "pl"]; - var nOfMails = param.number ? (param.number <= 50 ? param.number : 50) : 20; - for (var i=0;i'); + } + return res.pop(); + } - var data = eval(metadata); - res.push(); - for (var key in styles) { - var name = styles[key]; - var value = String(data[key]).toLowerCase(); - if (key.endsWith("color") && !helma.Color.COLORNAMES[key] && - !value.startsWith("#")) { - value = "#" + value; - } - value = value.replace(/([0-9]+) +px/, "$1px"); - res.writeln('<% value "' + name + '" "' + value + '" %>'); + var quote = function(str) { + if (str === null) { + return str; + } + return "'" + str.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; + } + + var clean = function(source) { + if (source) { + // Renaming prototype and skin names in skin macros + var re = /(<%\s*)([^.]+)(\.skin\s+name="?)([^"\s]+)/g; + source = source.replace(re, function() { + var $ = arguments; + var skin = rename($[2].capitalize(), $[4]); + if (skin) { + // THIS LINE DIFFERS FROM THE UPDATER APP! + return $[1] + skin.prototype.toLowerCase() + $[3] + + skin.prototype + "#" + skin.name; + } + return $[0]; + }); + // Replacing layout.* macros with corresponding value macros + source = source.replace(/(<%\s*)layout\.([^\s]+)/g, function() { + var value = styles[arguments[2]]; + if (value) { + return arguments[1] + "value " + quote(value); + } + return arguments[0]; + }); + return source; + } + } + // *********************************** + // End of code copied from updater app + + var rename = function(proto, name) { + var allowed = ["Comment", "Day", "File", "Global", "Image", + "MemberMgr", "Membership", "Site", "Story", "Topic"]; + if (allowed.indexOf(proto) < 0) { + return; + } + + switch (proto) { + case "Comment": + name === "toplevel" && (name = "main"); + break; + + case "Day": + proto = "Archive"; + break; + + case "MemberMgr": + case "Membership": + if (name === "statusloggedin") { + name = "status"; + } else if (name === "statusloggedout") { + name = "login"; + } else if (proto === "MemberMgr") { + // FIXME: This return causes errors on Ubuntu?!? + //return; } - return res.pop(); - } + break; - var quote = function(str) { - if (str === null) { - return str; + case "Site": + if (name === "searchbox") { + name = "search"; + } else if (name === "style") { + name = "stylesheet"; } - return "'" + str.replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; - } + break; - var clean = function(source) { - if (source) { - // Renaming prototype and skin names in skin macros - var re = /(<%\s*)([^.]+)(\.skin\s+name="?)([^"\s]+)/g; - source = source.replace(re, function() { - var $ = arguments; - var skin = rename($[2].capitalize(), $[4]); - if (skin) { - // THIS LINE DIFFERS FROM THE UPDATER APP! - return $[1] + skin.prototype.toLowerCase() + $[3] + - skin.prototype + "#" + skin.name; - } - return $[0]; - }); - // Replacing layout.* macros with corresponding value macros - source = source.replace(/(<%\s*)layout\.([^\s]+)/g, function() { - var value = styles[arguments[2]]; - if (value) { - return arguments[1] + "value " + quote(value); - } - return arguments[0]; - }); - return source; + case "Story": + if (name === "dayheader") { + name = "date"; + } else if (name === "display") { + name = "content"; + } else if (name === "historyview") { + name = "history"; } - } - // *********************************** - // End of code copied from updater app + break; - var rename = function(proto, name) { - var allowed = ["Comment", "Day", "File", "Global", "Image", - "MemberMgr", "Membership", "Site", "Story", "Topic"]; - if (allowed.indexOf(proto) < 0) { - return; - } + case "Topic": + proto = "Tag"; + break; + } + (proto === "MemberMgr") && (proto = "Membership"); + return { + prototype: proto, + name: name + }; + } - switch (proto) { - case "Comment": - name === "toplevel" && (name = "main"); - break; - - case "Day": - proto = "Archive"; - break; - - case "MemberMgr": - case "Membership": - if (name === "statusloggedin") { - name = "status"; - } else if (name === "statusloggedout") { - name = "login"; - } else if (proto === "MemberMgr") { - // FIXME: This return causes errors on Ubuntu?!? - //return; - } - break; - - case "Site": - if (name === "searchbox") { - name = "search"; - } else if (name === "style") { - name = "stylesheet"; - } - break; - - case "Story": - if (name === "dayheader") { - name = "date"; - } else if (name === "display") { - name = "content"; - } else if (name === "historyview") { - name = "history"; - } - break; - - case "Topic": - proto = "Tag"; - break; - } - (proto === "MemberMgr") && (proto = "Membership"); - return { - prototype: proto, - name: name - }; - } - - var convert2subskins = function(proto, dir) { - res.push(); - for each (var fname in dir.list()) { - var file = new helma.File(dir, fname); - var name = fname.split(".")[0], skin; - if (skin = rename(proto, name)) { - res.writeln("<% #" + skin.name + " %>"); - var source = clean(file.readAll()); - if (skin.prototype === "Site" && skin.name === "stylesheet") { - source = source.replace(/(\.calHead)/g, - "table.calendar thead, $1"); - source = source.replace(/(\.calDay)/g, - "table.calendar th, table.calendar tbody td.day, $1"); - source = source.replace(/(\.calSelDay)/g, - "table.calendar tbody td.selected, $1"); - source = source.replace(/(\.calFoot)/g, - "table.calendar tfoot td, $1"); - } - res.writeln(source); - } - } - var str = res.pop(); - if (!str) { - return; - } - var target = new java.io.File(fpath, skin.prototype); - target.mkdirs(); - target = new helma.File(target, skin.prototype + ".skin"); - target.open({append: true}); - target.write(str); - target.close(); - } - - var convertImage = function(image) { - var result = new HopObject; - result.name = image.alias; - result.width = image.width; - result.height = image.height; - result.created = image.exporttime; - result.modified = image.exporttime; - result.description = image.alltext; - result.fileName = image.alias + "." + image.fileext, - result.contentType = "image/" + image.fileext; - result.contentLength = inventory[result.fileName].getLength(); - if (image.thumbnail) { - result.thumbnailName = image.thumbnail.filename + "." + image.fileext; - result.thumbnailWidth = image.thumbnail.width; - result.thumbnailHeight = image.thumbnail.height; - } - return result; - } - - var dir = new helma.File(fpath, "images"); - for each (var fname in dir.list()) { + var convert2subskins = function(proto, dir) { + res.push(); + for each (var fname in dir.list()) { var file = new helma.File(dir, fname); - file.move(new helma.File(fpath, fname)); - } - - var inventory = new function() { - var dir = new helma.File(fpath); - var result = {}; - for each (var fname in dir.list()) { - var file = new helma.File(dir, fname); - if (!file.isDirectory()) { - // Where does the "image\" prefix come from in files from layouts.antville.org? - var parts = fname.split("\\"); - var name = parts[parts.length-1]; - if (name !== fname) { - res.debug(file); - res.debug(new helma.File(fpath, name)) - file.renameTo(new helma.File(fpath, name)); - } - result[name] = file; - } + var name = fname.split(".")[0], skin; + if (skin = rename(proto, name)) { + res.writeln("<% #" + skin.name + " %>"); + var source = clean(file.readAll()); + if (skin.prototype === "Site" && skin.name === "stylesheet") { + source = source.replace(/(\.calHead)/g, + "table.calendar thead, $1"); + source = source.replace(/(\.calDay)/g, + "table.calendar th, table.calendar tbody td.day, $1"); + source = source.replace(/(\.calSelDay)/g, + "table.calendar tbody td.selected, $1"); + source = source.replace(/(\.calFoot)/g, + "table.calendar tfoot td, $1"); + } + res.writeln(source); } - return result; - } + } + var str = res.pop(); + if (!str) { + return; + } + var target = new java.io.File(fpath, skin.prototype); + target.mkdirs(); + target = new helma.File(target, skin.prototype + ".skin"); + target.open({append: true}); + target.write(str); + target.close(); + } - var xml = Xml.read(new helma.File(fpath, "preferences.xml")); - var file = new helma.File(fpath, "Site"); - file.makeDirectory(); - file = new helma.File(file, "Site.skin"); - file.open(); - res.push(); - res.writeln("<% #values %>"); - res.write(values(xml.preferences)); - file.write(res.pop()); - file.close(); + var convertImage = function(image) { + var result = new HopObject; + result.name = image.alias; + result.width = image.width; + result.height = image.height; + result.created = image.exporttime; + result.modified = image.exporttime; + result.description = image.alltext; + result.fileName = image.alias + "." + image.fileext, + result.contentType = "image/" + image.fileext; + result.contentLength = inventory[result.fileName].getLength(); + if (image.thumbnail) { + result.thumbnailName = image.thumbnail.filename + "." + image.fileext; + result.thumbnailWidth = image.thumbnail.width; + result.thumbnailHeight = image.thumbnail.height; + } + return result; + } - dir = new helma.File(fpath, "skins"); + var dir = new helma.File(fpath, "images"); + for each (var fname in dir.list()) { + var file = new helma.File(dir, fname); + file.move(new helma.File(fpath, fname)); + } - var skin; - for each (var fname in dir.list()) { + var inventory = new function() { + var dir = new helma.File(fpath); + var result = {}; + for each (var fname in dir.list()) { + var file = new helma.File(dir, fname); + if (!file.isDirectory()) { + // Where does the "image\" prefix come from in files from layouts.antville.org? + var parts = fname.split("\\"); + var name = parts[parts.length-1]; + if (name !== fname) { + res.debug(file); + res.debug(new helma.File(fpath, name)) + file.renameTo(new helma.File(fpath, name)); + } + result[name] = file; + } + } + return result; + } + + var xml = Xml.read(new helma.File(fpath, "preferences.xml")); + var file = new helma.File(fpath, "Site"); + file.makeDirectory(); + file = new helma.File(file, "Site.skin"); + file.open(); + res.push(); + res.writeln("<% #values %>"); + res.write(values(xml.preferences)); + file.write(res.pop()); + file.close(); + + dir = new helma.File(fpath, "skins"); + + var skin; + for each (var fname in dir.list()) { + file = new helma.File(dir, fname); + skin = convert2subskins(fname, file); + } + + var data = new HopObject; + data.images = new HopObject; + + var dir = new helma.File(fpath, "imagedata"); + for each (fname in dir.list()) { + if (fname.endsWith(".xml")) { file = new helma.File(dir, fname); - skin = convert2subskins(fname, file); - } + data.images.add(convertImage(Xml.read(file))); + } + } - var data = new HopObject; - data.images = new HopObject; + data.version = "1.2-compatible"; + data.origin = "Antville 1.2 Layout Converter"; + data.originated = new Date; + data.originator = session.user; + Xml.write(data, new helma.File(fpath, "data.xml")); - var dir = new helma.File(fpath, "imagedata"); - for each (fname in dir.list()) { - if (fname.endsWith(".xml")) { - file = new helma.File(dir, fname); - data.images.add(convertImage(Xml.read(file))); - } - } - - data.version = "1.2-compatible"; - data.origin = "Antville 1.2 Layout Converter"; - data.originated = new Date; - data.originator = session.user; - Xml.write(data, new helma.File(fpath, "data.xml")); - - (new helma.File(fpath, "preferences.xml")).remove(); - (new helma.File(fpath, "imagedata")).removeDirectory(); - (new helma.File(fpath, "skins")).removeDirectory(); - return; + (new helma.File(fpath, "preferences.xml")).remove(); + (new helma.File(fpath, "imagedata")).removeDirectory(); + (new helma.File(fpath, "skins")).removeDirectory(); + return; } diff --git a/compat/Layout/Layout.js b/compat/Layout/Layout.js index f7e018d8..e6886066 100644 --- a/compat/Layout/Layout.js +++ b/compat/Layout/Layout.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -29,74 +29,74 @@ relocateProperty(Layout, "createtime", "created"); relocateProperty(Layout, "modifytime", "modified"); Layout.prototype.__defineGetter__("shareable", function() { - return this.mode === Layout.SHARED; + return this.mode === Layout.SHARED; }); Layout.prototype.__defineSetter__("shareable", function(value) { - this.mode = !!value ? Layout.SHARED : Layout.DEFAULT; - return; + this.mode = !!value ? Layout.SHARED : Layout.DEFAULT; + return; }); Layout.prototype.getTitle = function() { - return gettext("Layout"); + return gettext("Layout"); } Layout.prototype.title_macro = function(param) { - if (param.as === "editor") { - this.input_macro(param, "title"); - } else if (param.linkto) { - (param.linkto === "main") && (param.linkto = ""); - this.link_filter(this.title, param, param.linkto); - } else { - res.write(this.title); - } - return; + if (param.as === "editor") { + this.input_macro(param, "title"); + } else if (param.linkto) { + (param.linkto === "main") && (param.linkto = ""); + this.link_filter(this.title, param, param.linkto); + } else { + res.write(this.title); + } + return; } Layout.prototype.description_macro = function(param) { - if (param.as == "editor") { - this.textarea_macro(param, "description"); - } else if (this.description) { - if (param.limit) { - res.write(this.description.clip(param.limit, "...", "\\s")); - } else { - res.write(this.description); - } - } - return; + if (param.as == "editor") { + this.textarea_macro(param, "description"); + } else if (this.description) { + if (param.limit) { + res.write(this.description.clip(param.limit, "...", "\\s")); + } else { + res.write(this.description); + } + } + return; } Layout.prototype.parent_macro = function(param) { - if (param.as === "editor") { - this.select_macro(param, "parent"); - } else if (this.parent) { - res.write(this.parent.title); - } - return; + if (param.as === "editor") { + this.select_macro(param, "parent"); + } else if (this.parent) { + res.write(this.parent.title); + } + return; } Layout.prototype.shareable_macro = function(param) { - if (param.as == "editor" && !this.site) { - // FIXME: HopObject.createCheckBoxParam() is obsolete - var inputParam = this.createCheckBoxParam("shareable", param); - if (req.data.save && !req.data.shareable) - delete inputParam.checked; - Html.checkBox(inputParam); - } else if (this.shareable) - res.write(param.yes || "yes"); - else - res.write(param.no || "no"); - return; + if (param.as == "editor" && !this.site) { + // FIXME: HopObject.createCheckBoxParam() is obsolete + var inputParam = this.createCheckBoxParam("shareable", param); + if (req.data.save && !req.data.shareable) + delete inputParam.checked; + Html.checkBox(inputParam); + } else if (this.shareable) + res.write(param.yes || "yes"); + else + res.write(param.no || "no"); + return; } Layout.prototype.testdrivelink_macro = function(param) { - return this.link_macro(param, "test", param.text || "test"); + return this.link_macro(param, "test", param.text || "test"); } Layout.prototype.deletelink_macro = function(param) { - return this.link_macro(param, "delete", param.text || "delete"); + return this.link_macro(param, "delete", param.text || "delete"); } Layout.prototype.activatelink_macro = function(param) { - return this.link_macro(param, "activate", param.text || "activate"); + return this.link_macro(param, "activate", param.text || "activate"); } diff --git a/compat/Members/Members.js b/compat/Members/Members.js index 00373620..f7d67277 100644 --- a/compat/Members/Members.js +++ b/compat/Members/Members.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -24,22 +24,22 @@ // $URL$ Members.prototype.sendpwd_action = function() { - res.data.title = gettext("Recover your password"); - res.data.body = gettext("Due to security reasons user passwords are not stored in the Antville database any longer. Thus, your password cannot be sent to you, anymore."); - res.data.body += "

" + gettext('If you should really have forgotten your password, you can use the password reset option.', - this.href("reset")) + "

"; - this._parent.renderSkin("Site#page"); - return; + res.data.title = gettext("Recover your password"); + res.data.body = gettext("Due to security reasons user passwords are not stored in the Antville database any longer. Thus, your password cannot be sent to you, anymore."); + res.data.body += "

" + gettext('If you should really have forgotten your password, you can use the password reset option.', + this.href("reset")) + "

"; + this._parent.renderSkin("Site#page"); + return; } Members.prototype.subscribelink_macro = function(param) { - return res.handlers.site.link_macro(param, "subscribe"); + return res.handlers.site.link_macro(param, "subscribe"); } Members.prototype.subscriptionslink_macro = function(param) { - return this.link_macro(param, "subscriptions"); + return this.link_macro(param, "subscriptions"); } Members.prototype.membership_macro = function(param) { - return res.handlers.membership.role; + return res.handlers.membership.role; } diff --git a/compat/Membership/Membership.js b/compat/Membership/Membership.js index 767fbb5b..aa0a92a9 100644 --- a/compat/Membership/Membership.js +++ b/compat/Membership/Membership.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -29,45 +29,45 @@ relocateProperty(Membership, "modifytime", "modified"); relocateProperty(Membership, "user", "creator"); Membership.prototype.username_macro = function(param) { - if (param.linkto && (param.linkto !== "edit" || - this.user !== session.user)) { - html.link({href: this.href(param.linkto)}, this.name); - } else { - res.write(this.name); - } - return; + if (param.linkto && (param.linkto !== "edit" || + this.user !== session.user)) { + html.link({href: this.href(param.linkto)}, this.name); + } else { + res.write(this.name); + } + return; } Membership.prototype.url_macro = function(param) { - var url; - if (url = this.user.url) { - if (param.as === "link") { - delete param.as; - link_filter(url, param, url); - } else { - res.write(url); - } - } - return; + var url; + if (url = this.user.url) { + if (param.as === "link") { + delete param.as; + link_filter(url, param, url); + } else { + res.write(url); + } + } + return; } Membership.prototype.level_macro = function(param) { - if (param.as === "editor") { - this.select_macro(param, "role"); - } else { - res.write(this.role); - } - return; + if (param.as === "editor") { + this.select_macro(param, "role"); + } else { + res.write(this.role); + } + return; } Membership.prototype.editlink_macro = function(param) { - return this.link_macro(param, "edit"); + return this.link_macro(param, "edit"); } Membership.prototype.deletelink_macro = function(param) { - return this.link_macro(param, "delete"); + return this.link_macro(param, "delete"); } Membership.prototype.unsubscribelink_macro = function(param) { - return res.handlers.site.link_macro(param, "unsubscribe"); + return res.handlers.site.link_macro(param, "unsubscribe"); } diff --git a/compat/Poll/Poll.js b/compat/Poll/Poll.js index 2b1fc8ac..50eea543 100644 --- a/compat/Poll/Poll.js +++ b/compat/Poll/Poll.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -24,84 +24,84 @@ // $URL$ Poll.prototype.choices_macro = function(param) { - var vote; - if (session.user && this.votes.get(session.user.name)) { - vote = this.votes.get(session.user.name).choice; - } - for (var i=0; i 0) { - param.percent = param.count.toPercent(this.votes.size()); - param.width = Math.round(param.percent * 2.5); - param.graph = c.renderSkinAsString("graph", param); - if (param.count == 1) - param.text = " " + (param2.one || "vote"); - else - param.text = " " + (param2.more || "votes"); - } else - param.text = " " + (param2.no || "votes"); - c.renderSkin("$Choice#result", param); - } - return; + for (var i=0; i 0) { + param.percent = param.count.toPercent(this.votes.size()); + param.width = Math.round(param.percent * 2.5); + param.graph = c.renderSkinAsString("graph", param); + if (param.count == 1) + param.text = " " + (param2.one || "vote"); + else + param.text = " " + (param2.more || "votes"); + } else + param.text = " " + (param2.no || "votes"); + c.renderSkin("$Choice#result", param); + } + return; } Poll.prototype.editlink_macro = function(param) { - return this.link_macro(param, "edit"); + return this.link_macro(param, "edit"); } Poll.prototype.deletelink_macro = function(param) { - return this.link_macro(param, "delete"); + return this.link_macro(param, "delete"); } Poll.prototype.viewlink_macro = function(param) { - return this.link_macro(param, ".", "view"); + return this.link_macro(param, ".", "view"); } Poll.prototype.closelink_macro = function(param) { - return this.link_macro(param, "rotate"); + return this.link_macro(param, "rotate"); } diff --git a/compat/Root/Root.js b/compat/Root/Root.js index facd9054..fb1d94a7 100644 --- a/compat/Root/Root.js +++ b/compat/Root/Root.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -27,27 +27,27 @@ //Root.VERSION += "-compatible"; Root.prototype.rss_action = function() { - return res.redirect(root.href("rss.xml")); + return res.redirect(root.href("rss.xml")); } Root.prototype.url_macro = function(param) { - return this.href_macro(param); + return this.href_macro(param); } Root.prototype.sitecounter_macro = function(param) { - if (param.count === "all") { - var size = root.size(); - } else { - var size = root.sites.size(); - } - if (size < 1) { - res.write(param.no || size); - } else if (size < 2) { - res.write(param.one || size); - } else { - res.write(size + (param.more || String.EMPTY)); - } - return; + if (param.count === "all") { + var size = root.size(); + } else { + var size = root.sites.size(); + } + if (size < 1) { + res.write(param.no || size); + } else if (size < 2) { + res.write(param.one || size); + } else { + res.write(size + (param.more || String.EMPTY)); + } + return; } diff --git a/compat/Site/Site.js b/compat/Site/Site.js index cedfa0a8..b82b3bc1 100644 --- a/compat/Site/Site.js +++ b/compat/Site/Site.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -35,291 +35,291 @@ addPropertyMacro(Site, "tagline"); addPropertyMacro(Site, "email"); Site.prototype.__defineGetter__("online", function() { - return this.mode === Site.PUBLIC; + return this.mode === Site.PUBLIC; }); Site.prototype.__defineSetter__("online", function(value) { - this.mode = Site.PUBLIC; - return; + this.mode = Site.PUBLIC; + return; }); Site.prototype.__defineGetter__("blocked", function() { - return this.status === Site.BLOCKED; + return this.status === Site.BLOCKED; }); Site.prototype.__defineGetter__("trusted", function() { - return this.status === Site.TRUSTED; + return this.status === Site.TRUSTED; }); Site.prototype.__defineGetter__("discussions", function() { - return this.commentsMode === Comment.ONLINE; + return this.commentsMode === Comment.ONLINE; }); // FIXME: obsolete? Site.prototype.renderStoryList = function(day) { - res.push(); - list_macro(param, "stories"); - res.write(res.pop()); - return; + res.push(); + list_macro(param, "stories"); + res.write(res.pop()); + return; } Site.prototype.rss_action = function() { - if (req.queryParams.show === "all") { - return res.redirect(this.href("rss.xml")) - } - return res.redirect(this.href("stories.xml")); + if (req.queryParams.show === "all") { + return res.redirect(this.href("rss.xml")) + } + return res.redirect(this.href("stories.xml")); } //Site.prototype.feeds_action = function() { -// return disableAction.call(this, "Feeds are currently not available"); +// return disableAction.call(this, "Feeds are currently not available"); //} Site.prototype.mostread_action = function() { - return res.redirect(this.stories.href("top")); + return res.redirect(this.stories.href("top")); } Site.prototype.link_macro = function(param, url, text) { - param.text || (param.text = text); - if (!param.to) { - param.to = url || "."; - } else if (param.to.contains(":")) { - link_macro.call(global, param, param.to, param.text); - return; - } - var handler; - var parts = param.to.split("/"); - var action = parts[0]; - switch (action) { - case "mostread": - handler = this.stories; - param.to = "top"; break; + param.text || (param.text = text); + if (!param.to) { + param.to = url || "."; + } else if (param.to.contains(":")) { + link_macro.call(global, param, param.to, param.text); + return; + } + var handler; + var parts = param.to.split("/"); + var action = parts[0]; + switch (action) { + case "mostread": + handler = this.stories; + param.to = "top"; break; - case "layouts": - action = "."; - handler = this.layout; - param.text = gettext("Layout"); - param.to = "."; break; + case "layouts": + action = "."; + handler = this.layout; + param.text = gettext("Layout"); + param.to = "."; break; - case "topics": - case "files": - case "images": - case "members": - case "polls": - case "stories": - handler = this[action]; - if (handler) { - var node = handler.get(parts[1]); - if (node) { - handler = node; - param.to = parts[2] || "main"; - } else { - param.to = parts[1] || "main"; - } + case "topics": + case "files": + case "images": + case "members": + case "polls": + case "stories": + handler = this[action]; + if (handler) { + var node = handler.get(parts[1]); + if (node) { + handler = node; + param.to = parts[2] || "main"; + } else { + param.to = parts[1] || "main"; } - break; + } + break; - default: - handler = this; - } - HopObject.prototype.link_macro.call(handler, param, param.to, param.text); - return; + default: + handler = this; + } + HopObject.prototype.link_macro.call(handler, param, param.to, param.text); + return; } Site.prototype.title_macro = function(param) { - if (param.as === "editor") { - this.input_macro(param, "title"); - } else { - var title = this.title; - if (param.linkto) { - if (param.linkto === "main") { - param.linkto = "."; - } - res.write(this.link_filter(title, param, param.linkto)); - } else { - res.write(title); + if (param.as === "editor") { + this.input_macro(param, "title"); + } else { + var title = this.title; + if (param.linkto) { + if (param.linkto === "main") { + param.linkto = "."; } - } - return; + res.write(this.link_filter(title, param, param.linkto)); + } else { + res.write(title); + } + } + return; } Site.prototype.loginstatus_macro = function(param) { - return res.handlers.membership.status_macro(); + return res.handlers.membership.status_macro(); } Site.prototype.navigation_macro = function(param) { - var group; - var navigation = {}; - // HopObject.renderSkinAsString() is overridden and will never return an empty skin - // due to the added skin edit controls! Thus, we are using the original methods first, - // and the overriden ones later. - navigation.contributors = this.__renderSkinAsString__("Site#contribnavigation"); - navigation.admins = this.__renderSkinAsString__("Site#adminnavigation"); - if (!navigation.contributors && !navigation.admins && !res.meta.navigation) { - res.meta.navigation = true; - this.renderSkin("Site#navigation"); - } else if ((group = param["for"]) && navigation[group]) { - if (group === "contributors" && this.stories.getPermission("create")) { - this.renderSkin("Site#contribnavigation"); - } else if (group === "admins" && this.getPermission("edit")) { - this.renderSkin("Site#adminnavigation"); - } - } - return; + var group; + var navigation = {}; + // HopObject.renderSkinAsString() is overridden and will never return an empty skin + // due to the added skin edit controls! Thus, we are using the original methods first, + // and the overriden ones later. + navigation.contributors = this.__renderSkinAsString__("Site#contribnavigation"); + navigation.admins = this.__renderSkinAsString__("Site#adminnavigation"); + if (!navigation.contributors && !navigation.admins && !res.meta.navigation) { + res.meta.navigation = true; + this.renderSkin("Site#navigation"); + } else if ((group = param["for"]) && navigation[group]) { + if (group === "contributors" && this.stories.getPermission("create")) { + this.renderSkin("Site#contribnavigation"); + } else if (group === "admins" && this.getPermission("edit")) { + this.renderSkin("Site#adminnavigation"); + } + } + return; } Site.prototype.image_macro = function() { - return global.image_macro.apply(global, arguments); + return global.image_macro.apply(global, arguments); } Site.prototype.xmlbutton_macro = function(param) { - param.linkto = this.href("rss.xml"); - image_macro(param, "/xmlbutton.gif"); - return; + param.linkto = this.href("rss.xml"); + image_macro(param, "/xmlbutton.gif"); + return; } Site.prototype.lastupdate_macro = function(param) { - var value; - if (value = this.modified) { - res.write(formatDate(value, param.format)); - } - return; + var value; + if (value = this.modified) { + res.write(formatDate(value, param.format)); + } + return; } Site.prototype.online_macro = function(param) { - var online = true; - var value = this.mode; - if (value === Site.PRIVATE || value === Site.CLOSED) { - online = false; - } - if (param.as === "editor") { - param.name = "online"; - param.value = "true"; - if (req.isPost()) { - param.selectedValue = req.postParams.online; - } else { - param.selectedValue = String(online); - } - //res.debug(param.name + ": " + param.value + "/" + param.selectedValue); - return html.checkBox(param); - } else if (online) { - res.write(param.yes || "yes"); - } else { - res.write(param.no || "no"); - } - return; + var online = true; + var value = this.mode; + if (value === Site.PRIVATE || value === Site.CLOSED) { + online = false; + } + if (param.as === "editor") { + param.name = "online"; + param.value = "true"; + if (req.isPost()) { + param.selectedValue = req.postParams.online; + } else { + param.selectedValue = String(online); + } + //res.debug(param.name + ": " + param.value + "/" + param.selectedValue); + return html.checkBox(param); + } else if (online) { + res.write(param.yes || "yes"); + } else { + res.write(param.no || "no"); + } + return; } Site.prototype.usermaycontrib_macro = function(param) { - if (param.as === "editor") { - param.name = "usermaycontrib"; - param.value = "true"; - if (req.isPost()) { - param.selectedValue = req.postParams.usermaycontrib; - } else { - param.selectedValue = String(this.mode === Site.OPEN); - } - return html.checkBox(param); - } else { - res.write(this.mode === Site.OPEN ? "yes" : "no"); - } - return; + if (param.as === "editor") { + param.name = "usermaycontrib"; + param.value = "true"; + if (req.isPost()) { + param.selectedValue = req.postParams.usermaycontrib; + } else { + param.selectedValue = String(this.mode === Site.OPEN); + } + return html.checkBox(param); + } else { + res.write(this.mode === Site.OPEN ? "yes" : "no"); + } + return; } Site.prototype.hasdiscussions_macro = function(param) { - if (param.as === "editor") { - this.checkbox_macro(param, "commentMode"); - } else { - res.write(this.commentsMode === Comment.ONLINE ? "yes" : "no"); - } - return; + if (param.as === "editor") { + this.checkbox_macro(param, "commentMode"); + } else { + res.write(this.commentsMode === Comment.ONLINE ? "yes" : "no"); + } + return; } Site.prototype.showarchive_macro = function(param) { - if (param.as === "editor") { - this.checkbox_macro(param, "archiveMode"); - } else { - res.write(this.archiveMode === Site.PUBLIC ? "yes" : "no"); - } - return; + if (param.as === "editor") { + this.checkbox_macro(param, "archiveMode"); + } else { + res.write(this.archiveMode === Site.PUBLIC ? "yes" : "no"); + } + return; } Site.prototype.enableping_macro = function(param) { - if (param.as === "editor") { - this.checkbox_macro(param, "callbackMode"); - } else { - res.write(this.callbackMode === Site.ENABLED ? "yes" : "no"); - } - return; + if (param.as === "editor") { + this.checkbox_macro(param, "callbackMode"); + } else { + res.write(this.callbackMode === Site.ENABLED ? "yes" : "no"); + } + return; } Site.prototype.localechooser_macro = function(param) { - return this.select_macro(param, "locale"); + return this.select_macro(param, "locale"); } Site.prototype.timezonechooser_macro = function(param) { - return this.select_macro(param, "timeZone"); + return this.select_macro(param, "timeZone"); } Site.prototype.history_macro = function(param, type) { - param.skin || (param.skin = "Story#history"); - var type = isNaN(param.show) ? param.show : "postings"; - var limit = Math.min(param.limit || parseInt(param.show) || 10, 50); - delete param.show; - delete param.limit; - return list_macro(param, type, limit); + param.skin || (param.skin = "Story#history"); + var type = isNaN(param.show) ? param.show : "postings"; + var limit = Math.min(param.limit || parseInt(param.show) || 10, 50); + delete param.show; + delete param.limit; + return list_macro(param, type, limit); } Site.prototype.membercounter_macro = function(param) { - return this.members.size(); + return this.members.size(); } Site.prototype.preferences_macro = function(param) { - if (param.as === "editor") { - // FIXME: Site.metadata is now a collection! - var inputParam = this.metadata.createInputParam(param.name, param); - delete inputParam.part; - if (param.cols || param.rows) { - html.textArea(inputParam); - } else { - html.input(inputParam); - } - } else { - res.write(this.getMetadata(param.name)); - } return; + if (param.as === "editor") { + // FIXME: Site.metadata is now a collection! + var inputParam = this.metadata.createInputParam(param.name, param); + delete inputParam.part; + if (param.cols || param.rows) { + html.textArea(inputParam); + } else { + html.input(inputParam); + } + } else { + res.write(this.getMetadata(param.name)); + } return; } Site.prototype.listReferrers_macro = function(param) { - return this.referrers_macro(param); + return this.referrers_macro(param); } Site.prototype.searchbox_macro = function(param) { - if (this.getPermission("search")) { - this.renderSkin("Site#search"); - } - return; + if (this.getPermission("search")) { + this.renderSkin("Site#search"); + } + return; } // FIXME: working? Site.prototype.monthlist_macro = function(param) { - if (!this.stories.size() || this.archiveMode !== Site.PUBLIC) { - return; - } - var collection = this.archive; - var size = Math.min(collection.size(), param.limit || Infinity); - for (var i=0; i 0) { - html.link({href: this.tags.get(0).tag.href()}, "topic"); - } - } - return; + default: + if (this.tags.size() > 0) { + html.link({href: this.tags.get(0).tag.href()}, "topic"); + } + } + return; } Story.prototype.topic_macro = function(param) { - // This method is applied to images as well, thus we check what we got first: - if (this.constructor !== Image && this.status !== Story.PUBLIC) { - return; - } - if (this.tags.size() < 1) { - return; - } - var tag = this.tags.get(0).tag; - if (!tag) { - return; - } - if (!param.as || param.as === "text") { - res.write(tag.name); - } else if (param.as === "link") { - html.link({href: tag.href()}, param.text || tag.name); - } else if (param.as === "image") { - param.imgprefix || (param.imgprefix = "topic_"); - var img = HopObject.getFromPath(param.imgprefix + tag.name, "images"); - delete param.imgprefix; - delete param.as; - if (img) { - res.push(); - img.render_macro(param); - delete param.height; - delete param.width; - delete param.border; - delete param.src; - delete param.alt; - link_filter(res.pop(), param, tag.href()); - } - } - return; + // This method is applied to images as well, thus we check what we got first: + if (this.constructor !== Image && this.status !== Story.PUBLIC) { + return; + } + if (this.tags.size() < 1) { + return; + } + var tag = this.tags.get(0).tag; + if (!tag) { + return; + } + if (!param.as || param.as === "text") { + res.write(tag.name); + } else if (param.as === "link") { + html.link({href: tag.href()}, param.text || tag.name); + } else if (param.as === "image") { + param.imgprefix || (param.imgprefix = "topic_"); + var img = HopObject.getFromPath(param.imgprefix + tag.name, "images"); + delete param.imgprefix; + delete param.as; + if (img) { + res.push(); + img.render_macro(param); + delete param.height; + delete param.width; + delete param.border; + delete param.src; + delete param.alt; + link_filter(res.pop(), param, tag.href()); + } + } + return; } Story.prototype.topicchooser_macro = function(param) { - var site = this.site || res.handlers.site; - var currentTopic = this.tags.size() > 0 ? this.tags.get(0).tag : null; - var topics = (this.constructor === Story ? site.stories.tags : - site.images.galleries); - var options = [], topic; - for (var i=0; i 0 ? this.tags.get(0).tag : null; + var topics = (this.constructor === Story ? site.stories.tags : + site.images.galleries); + var options = [], topic; + for (var i=0; i 0); - if (linkflag) { - html.openTag("a", {href: this.href() + "#comments"}); - } - if (commentCnt < 1) { - res.write(param.no || "no comments"); - } else if (commentCnt < 2) { - res.write(param.one || "one comment"); - } else { - res.write(commentCnt + (param.more || " " + "comments")); - } - if (linkflag) { - html.closeTag("a"); - } - return; + if (this.site.commentMode === Site.DISABLED || + this.commentMode === Story.CLOSED || + this.commentMode === Story.READONLY) { + return; + } + var commentCnt = this.comments.count(); + param.linkto || (param.linkto = "main"); + var linkflag = (param.as === "link" && param.as !== "text" || + !param.as && commentCnt > 0); + if (linkflag) { + html.openTag("a", {href: this.href() + "#comments"}); + } + if (commentCnt < 1) { + res.write(param.no || "no comments"); + } else if (commentCnt < 2) { + res.write(param.one || "one comment"); + } else { + res.write(commentCnt + (param.more || " " + "comments")); + } + if (linkflag) { + html.closeTag("a"); + } + return; } Story.prototype.reads_macro = function(param) { - res.write(this.requests); - return; + res.write(this.requests); + return; } diff --git a/compat/Topics/Topics.js b/compat/Topics/Topics.js index 90d2a01e..53e29d87 100644 --- a/compat/Topics/Topics.js +++ b/compat/Topics/Topics.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -24,15 +24,15 @@ // $URL$ Topics.prototype.main_action = function() { - return res.redirect(this.href()); + return res.redirect(this.href()); } Topics.prototype.getChildElement = function(id) { - return res.redirect(this.href() + id); + return res.redirect(this.href() + id); } Topics.prototype.href = function() { - var mountpoint = (this._parent.constructor === Site || - this._parent.constructor === Root ? "tags" : "galleries"); - return this._parent[mountpoint].href(); + var mountpoint = (this._parent.constructor === Site || + this._parent.constructor === Root ? "tags" : "galleries"); + return this._parent[mountpoint].href(); } diff --git a/compat/User/User.js b/compat/User/User.js index 0c2b1200..03024be9 100644 --- a/compat/User/User.js +++ b/compat/User/User.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,68 +26,68 @@ disableMacro(User, "password"); User.prototype.__defineGetter__("blocked", function() { - return this.status === User.BLOCKED; + return this.status === User.BLOCKED; }); User.prototype.__defineSetter__("blocked", function(blocked) { - this.status = blocked ? User.BLOCKED : User.DEFAULT; + this.status = blocked ? User.BLOCKED : User.DEFAULT; }); User.prototype.__defineGetter__("trusted", function() { - return this.status === User.TRUSTED; + return this.status === User.TRUSTED; }); User.prototype.__defineSetter__("trusted", function(trusted) { - this.status = trusted ? User.TRUSTED : User.DEFAULT; + this.status = trusted ? User.TRUSTED : User.DEFAULT; }); User.prototype.__defineGetter__("sysadmin", function() { - return this.status === User.PRIVILEGED; + return this.status === User.PRIVILEGED; }); User.prototype.__defineSetter__("sysadmin", function(privileged) { - this.status = privileged ? User.PRIVILEGED : User.DEFAULT; + this.status = privileged ? User.PRIVILEGED : User.DEFAULT; }); User.prototype.status_macro = function(param) { - // This macro is allowed for privileged users only - if (!User.require(User.PRIVILEGED)) { - return; - } - if (param.as === "editor") { - this.select_macro(param, "status"); - } else { - res.write(this.status); - } - return; + // This macro is allowed for privileged users only + if (!User.require(User.PRIVILEGED)) { + return; + } + if (param.as === "editor") { + this.select_macro(param, "status"); + } else { + res.write(this.status); + } + return; } User.prototype.name_macro = function(param) { - if (param.as === "link" && this.url) { - link_filter(this.name, param, this.url); - } else { - res.write(this.name); - } - return; + if (param.as === "link" && this.url) { + link_filter(this.name, param, this.url); + } else { + res.write(this.name); + } + return; } User.prototype.url_macro = function(param) { - if (param.as === "editor") { - this.input_macro(param, "url"); - } else { - res.write(this.url); - } - return; + if (param.as === "editor") { + this.input_macro(param, "url"); + } else { + res.write(this.url); + } + return; } User.prototype.email_macro = function(param) { - if (!User.require(User.PRIVILEGED) && this !== session.user) { - return; - } - if (param.as === "editor") { - this.input_macro(param, "email"); - } else { - res.write(this.email); - } - return; + if (!User.require(User.PRIVILEGED) && this !== session.user) { + return; + } + if (param.as === "editor") { + this.input_macro(param, "email"); + } else { + res.write(this.email); + } + return; } diff --git a/extra/connect/Global/connect.js b/extra/connect/Global/connect.js index 4bc79ee7..98bde8ef 100644 --- a/extra/connect/Global/connect.js +++ b/extra/connect/Global/connect.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,301 +34,301 @@ app.addRepository(app.dir + "/../extra/connect/scribe-1.3.0.jar"); // FIXME: Might be good to somehow define the action together with its permissions... Members.prototype.connect_action = function() { - try { - var connect = Feature.get("connect"); - switch (req.data.type) { - case "facebook": - connect.facebook(req); - break; - case "google": - connect.google(req); - break; - case "twitter": - connect.scribe(req.data.type); - break; - } - } catch (ex) { - session.logout(); - res.message = String(ex); - res.redirect(res.handlers.members.href("login")); - } - JSON.sendPaddedResponse(this._parent.stories.getPermission("create")); - res.redirect(User.getLocation() || res.handlers.site.href()); - return; + try { + var connect = Feature.get("connect"); + switch (req.data.type) { + case "facebook": + connect.facebook(req); + break; + case "google": + connect.google(req); + break; + case "twitter": + connect.scribe(req.data.type); + break; + } + } catch (ex) { + session.logout(); + res.message = String(ex); + res.redirect(res.handlers.members.href("login")); + } + JSON.sendPaddedResponse(this._parent.stories.getPermission("create")); + res.redirect(User.getLocation() || res.handlers.site.href()); + return; } Members.prototype.disconnect_action = function() { - switch (req.data.type) { - case "facebook": - case "google": - case "twitter": - res.handlers.membership.creator.deleteMetadata(req.data.type + "_id"); - break; - } - res.redirect(req.data.http_referer); - return; + switch (req.data.type) { + case "facebook": + case "google": + case "twitter": + res.handlers.membership.creator.deleteMetadata(req.data.type + "_id"); + break; + } + res.redirect(req.data.http_referer); + return; } Feature.add("connect", "http://code.google.com/p/antville/wiki/ConnectFeature", { - _getPermission: function(action) { - if (this.constructor === Members) { - switch (action) { - case "connect": - return true; - case "disconnect": - return User.require(User.REGULAR); - } + _getPermission: function(action) { + if (this.constructor === Members) { + switch (action) { + case "connect": + return true; + case "disconnect": + return User.require(User.REGULAR); } - }, - - main: function(options) { - var defaultDomain = getProperty("domain.*"); - var domain = getProperty("domain." + res.handlers.site.name); - if (defaultDomain && domain && !domain.endsWith(defaultDomain)) { - return; - } - var suffix = options.context ? "_" + options.context : ""; - getProperty("connect.facebook.id") && renderSkin("connect#facebook" + suffix); - getProperty("connect.google.id") && renderSkin("connect#google" + suffix); - getProperty("connect.twitter.id") && renderSkin("connect#twitter" + suffix); - }, - - getUserByConnection: function(type, id) { - var user; - var connections = root.connections.get(id); - if (connections) { - connections.forEach(function(index) { - if (this.name === type + "_id") { - user = this.parent; - } - }); - } - return user; - }, - - scribe: function(type) { - var name = type.titleize(); - var appId = getProperty("connect." + type + ".id"); - var secret = getProperty("connect." + type + ".key"); - - if (!secret || req.data.denied) { - throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name, - gettext("You denied the request."))); - } - - if (req.isPost()) { - try { - User.login(req.postParams); - } catch (ex) { } - } - - var scribe = Packages.org.scribe; - var provider, requestUrl, scope, getValues; - var headers = {}; - - switch (type) { - case "google": - provider = scribe.builder.api.GoogleApi; - requestUrl = "http://www-opensocial.googleusercontent.com/api/people/@me/@self"; - scope = "http://www-opensocial.googleusercontent.com/api/people/"; - headers["GData-Version"] = "3.0"; - getValues = function(data) { - data = data.entry; - return { - id: data.id, - name: data.displayName, - email: data.email, - url: data.url - } - } - break; - - case "twitter": - provider = scribe.builder.api.TwitterApi; - requestUrl = "https://api.twitter.com/1.1/account/verify_credentials.json"; - getValues = function(data) { - return { - id: data.id_str, - name: data.screen_name, - email: data.email, - url: data.profileUrl - } - } - break; - } - - var url = res.handlers.members.href(req.action) + "?type=" + type; - - var service = new scribe.builder.ServiceBuilder() - .provider(provider) - .apiKey(appId) - .apiSecret(secret) - .callback(url); - - if (scope) { - service.scope(scope); - } - - var oauth = service.build(); - - var verifier = req.data.oauth_verifier; - if (!verifier) { - // Because the service provider will redirect back to this URL the - // request token needs to be stored in the session object - session.data.requestToken = oauth.getRequestToken(); - res.redirect(oauth.getAuthorizationUrl(session.data.requestToken)); - } - - try { - var accessToken = oauth.getAccessToken(session.data.requestToken, - new scribe.model.Verifier(verifier)); - } catch (ex) { - throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name, - gettext("Something went wrong."))); - } - - var request = new scribe.model.OAuthRequest(scribe.model.Verb.GET, requestUrl); - oauth.signRequest(accessToken, request); - for (let name in headers) { - request.addHeader(name, headers[name]); - } - var response = request.send(); - - var data = getValues(JSON.parse(response.getBody())); - var user = this.getUserByConnection(type, data.id); - if (!user) { - if (!session.user) { - var name = root.users.getAccessName(data.name); - user = User.register({ - name: name, - hash: session.data.requestToken.getToken(), - email: data.email || root.replyTo, - url: data.url - }); - session.login(user); - } else { - user = session.user; - } - user.setMetadata(type + "_id", data.id); - } else if (user !== session.user) { - user.touch(); - session.login(user); - } - - return; + } }, - facebook: function(req) { - var appId = getProperty("connect.facebook.id"); - var secret = getProperty("connect.facebook.key"); - if (!secret || req.data.error) { - throw Error(gettext("Could not connect with Facebook. ({0})", -1)); - } - - if (req.isPost()) { - try { - User.login(req.postParams); - } catch (ex) { } - } - - var url = res.handlers.members.href(req.action) + "?type=facebook"; - - var code = req.data.code; - if (!code) { - res.redirect("https://www.facebook.com/dialog/oauth?client_id=" + appId + - "&scope=email&redirect_uri=" + url); - return; - } - - var mime = getURL("https://graph.facebook.com/oauth/access_token?client_id=" + appId + - "&redirect_uri=" + url + "&client_secret=" + secret + "&code=" + code); - if (!mime || !mime.text) { - throw Error(gettext("Could not connect with Facebook. ({0})", -3)); - } - - var token = mime.text; - mime = getURL("https://graph.facebook.com/me?" + token); - if (!mime) { - throw Error(gettext("Could not connect with Facebook. ({0})", -4)); - } - - var content = Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream); - if (!content) { - throw Error(gettext("Could not connect with Facebook. ({0})", -5)); - } - - var data = JSON.parse(content); - var user = this.getUserByConnection("facebook", data.id); - if (!user) { - if (!session.user) { - var name = root.users.getAccessName(data.name); - user = User.register({ - name: name, - hash: token, - email: data.email, - url: data.link, - }); - session.login(user); - } else { - user = session.user; - } - user.setMetadata("facebook_id", data.id); - } else if (user !== session.user) { - user.touch(); - session.login(user); - } - + main: function(options) { + var defaultDomain = getProperty("domain.*"); + var domain = getProperty("domain." + res.handlers.site.name); + if (defaultDomain && domain && !domain.endsWith(defaultDomain)) { return; - }, + } + var suffix = options.context ? "_" + options.context : ""; + getProperty("connect.facebook.id") && renderSkin("connect#facebook" + suffix); + getProperty("connect.google.id") && renderSkin("connect#google" + suffix); + getProperty("connect.twitter.id") && renderSkin("connect#twitter" + suffix); + }, - google: function(req) { - if (req.isPost()) { - try { - User.login(req.postParams); - } catch (ex) { } + getUserByConnection: function(type, id) { + var user; + var connections = root.connections.get(id); + if (connections) { + connections.forEach(function(index) { + if (this.name === type + "_id") { + user = this.parent; + } + }); + } + return user; + }, + + scribe: function(type) { + var name = type.titleize(); + var appId = getProperty("connect." + type + ".id"); + var secret = getProperty("connect." + type + ".key"); + + if (!secret || req.data.denied) { + throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name, + gettext("You denied the request."))); + } + + if (req.isPost()) { + try { + User.login(req.postParams); + } catch (ex) { } + } + + var scribe = Packages.org.scribe; + var provider, requestUrl, scope, getValues; + var headers = {}; + + switch (type) { + case "google": + provider = scribe.builder.api.GoogleApi; + requestUrl = "http://www-opensocial.googleusercontent.com/api/people/@me/@self"; + scope = "http://www-opensocial.googleusercontent.com/api/people/"; + headers["GData-Version"] = "3.0"; + getValues = function(data) { + data = data.entry; + return { + id: data.id, + name: data.displayName, + email: data.email, + url: data.url + } } + break; - var url = root.members.href('connect') + "?type=google"; + case "twitter": + provider = scribe.builder.api.TwitterApi; + requestUrl = "https://api.twitter.com/1.1/account/verify_credentials.json"; + getValues = function(data) { + return { + id: data.id_str, + name: data.screen_name, + email: data.email, + url: data.profileUrl + } + } + break; + } - if (req.data.code) { - var http = new helma.Http(); - http.setMethod("POST"); - http.setContent("code=" + encodeURIComponent(req.data.code) + - "&client_id=" + encodeURIComponent(getProperty("connect.google.id")) + - "&client_secret=" + encodeURIComponent(getProperty("connect.google.key")) + - "&redirect_uri=" + encodeURIComponent(url) + "&grant_type=authorization_code"); - var response = http.getUrl("https://accounts.google.com/o/oauth2/token"); - var data = JSON.parse(response.content); - var token = data.access_token; - var mime = getURL("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + - encodeURIComponent(data.access_token)); - var data = JSON.parse(Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream)); - var user = this.getUserByConnection("google", data.id); - if (!user) { - if (!session.user) { - var name = root.users.getAccessName(data.name); - user = User.register({ - name: name, - hash: token, - email: data.email, - url: data.link - }); - session.login(user); - } else { - user = session.user; - } - user.setMetadata("google_id", data.id); - } else if (user !== session.user) { - user.touch(); - session.login(user); - } + var url = res.handlers.members.href(req.action) + "?type=" + type; + + var service = new scribe.builder.ServiceBuilder() + .provider(provider) + .apiKey(appId) + .apiSecret(secret) + .callback(url); + + if (scope) { + service.scope(scope); + } + + var oauth = service.build(); + + var verifier = req.data.oauth_verifier; + if (!verifier) { + // Because the service provider will redirect back to this URL the + // request token needs to be stored in the session object + session.data.requestToken = oauth.getRequestToken(); + res.redirect(oauth.getAuthorizationUrl(session.data.requestToken)); + } + + try { + var accessToken = oauth.getAccessToken(session.data.requestToken, + new scribe.model.Verifier(verifier)); + } catch (ex) { + throw Error(gettext("Connecting with {0} failed. {1} Please try again.", name, + gettext("Something went wrong."))); + } + + var request = new scribe.model.OAuthRequest(scribe.model.Verb.GET, requestUrl); + oauth.signRequest(accessToken, request); + for (let name in headers) { + request.addHeader(name, headers[name]); + } + var response = request.send(); + + var data = getValues(JSON.parse(response.getBody())); + var user = this.getUserByConnection(type, data.id); + if (!user) { + if (!session.user) { + var name = root.users.getAccessName(data.name); + user = User.register({ + name: name, + hash: session.data.requestToken.getToken(), + email: data.email || root.replyTo, + url: data.url + }); + session.login(user); } else { - res.redirect("https://accounts.google.com/o/oauth2/auth?" + - "client_id=" + encodeURIComponent(getProperty("connect.google.id")) + - "&redirect_uri=" + encodeURIComponent(url) + - "&scope=" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.profile") + - "+" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.email") + - "&response_type=code"); + user = session.user; } - } + user.setMetadata(type + "_id", data.id); + } else if (user !== session.user) { + user.touch(); + session.login(user); + } + + return; + }, + + facebook: function(req) { + var appId = getProperty("connect.facebook.id"); + var secret = getProperty("connect.facebook.key"); + if (!secret || req.data.error) { + throw Error(gettext("Could not connect with Facebook. ({0})", -1)); + } + + if (req.isPost()) { + try { + User.login(req.postParams); + } catch (ex) { } + } + + var url = res.handlers.members.href(req.action) + "?type=facebook"; + + var code = req.data.code; + if (!code) { + res.redirect("https://www.facebook.com/dialog/oauth?client_id=" + appId + + "&scope=email&redirect_uri=" + url); + return; + } + + var mime = getURL("https://graph.facebook.com/oauth/access_token?client_id=" + appId + + "&redirect_uri=" + url + "&client_secret=" + secret + "&code=" + code); + if (!mime || !mime.text) { + throw Error(gettext("Could not connect with Facebook. ({0})", -3)); + } + + var token = mime.text; + mime = getURL("https://graph.facebook.com/me?" + token); + if (!mime) { + throw Error(gettext("Could not connect with Facebook. ({0})", -4)); + } + + var content = Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream); + if (!content) { + throw Error(gettext("Could not connect with Facebook. ({0})", -5)); + } + + var data = JSON.parse(content); + var user = this.getUserByConnection("facebook", data.id); + if (!user) { + if (!session.user) { + var name = root.users.getAccessName(data.name); + user = User.register({ + name: name, + hash: token, + email: data.email, + url: data.link, + }); + session.login(user); + } else { + user = session.user; + } + user.setMetadata("facebook_id", data.id); + } else if (user !== session.user) { + user.touch(); + session.login(user); + } + + return; + }, + + google: function(req) { + if (req.isPost()) { + try { + User.login(req.postParams); + } catch (ex) { } + } + + var url = root.members.href('connect') + "?type=google"; + + if (req.data.code) { + var http = new helma.Http(); + http.setMethod("POST"); + http.setContent("code=" + encodeURIComponent(req.data.code) + + "&client_id=" + encodeURIComponent(getProperty("connect.google.id")) + + "&client_secret=" + encodeURIComponent(getProperty("connect.google.key")) + + "&redirect_uri=" + encodeURIComponent(url) + "&grant_type=authorization_code"); + var response = http.getUrl("https://accounts.google.com/o/oauth2/token"); + var data = JSON.parse(response.content); + var token = data.access_token; + var mime = getURL("https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + + encodeURIComponent(data.access_token)); + var data = JSON.parse(Packages.org.apache.commons.io.IOUtils.toString(mime.inputStream)); + var user = this.getUserByConnection("google", data.id); + if (!user) { + if (!session.user) { + var name = root.users.getAccessName(data.name); + user = User.register({ + name: name, + hash: token, + email: data.email, + url: data.link + }); + session.login(user); + } else { + user = session.user; + } + user.setMetadata("google_id", data.id); + } else if (user !== session.user) { + user.touch(); + session.login(user); + } + } else { + res.redirect("https://accounts.google.com/o/oauth2/auth?" + + "client_id=" + encodeURIComponent(getProperty("connect.google.id")) + + "&redirect_uri=" + encodeURIComponent(url) + + "&scope=" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.profile") + + "+" + encodeURIComponent("https://www.googleapis.com/auth/userinfo.email") + + "&response_type=code"); + } + } }); diff --git a/extra/proxy/Global/proxy.js b/extra/proxy/Global/proxy.js index a515a823..696ee124 100644 --- a/extra/proxy/Global/proxy.js +++ b/extra/proxy/Global/proxy.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -28,33 +28,33 @@ */ Root.prototype.proxy_action = function() { - var url = req.data.url; - if (!url) { - return; - } + var url = req.data.url; + if (!url) { + return; + } - var http = new helma.Http; - var data = http.getUrl(url); + var http = new helma.Http; + var data = http.getUrl(url); - if (!data.content) { - throw Error("Failed to retrieve URL."); - } + if (!data.content) { + throw Error("Failed to retrieve URL."); + } - var callback = req.data.callback; - if (callback) { - res.contentType = "text/javascript"; - res.write(JSON.pad(data.content, callback)); - } else { - res.write(data.content); - } - return; + var callback = req.data.callback; + if (callback) { + res.contentType = "text/javascript"; + res.write(JSON.pad(data.content, callback)); + } else { + res.write(data.content); + } + return; } Feature.add("proxy", "http://code.google.com/p/antville/wiki/ProxyFeature", { - _getPermission: function(action) { - if (this._prototype in {Root: 1} && - action === "proxy" && User.require(User.TRUSTED)) { - return true; - } - } + _getPermission: function(action) { + if (this._prototype in {Root: 1} && + action === "proxy" && User.require(User.TRUSTED)) { + return true; + } + } }); diff --git a/extra/recaptcha/Global/recaptcha.js b/extra/recaptcha/Global/recaptcha.js index 39c34014..ef47a324 100644 --- a/extra/recaptcha/Global/recaptcha.js +++ b/extra/recaptcha/Global/recaptcha.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -29,35 +29,35 @@ */ Feature.add("recaptcha", "http://code.google.com/p/antville/wiki/RecaptchaFeature", new function() { - var key = getProperty("recaptcha.key"); + var key = getProperty("recaptcha.key"); - return { - main: function() { - if (key && !session.user) { - renderSkin("recaptcha", {id: getProperty("recaptcha.id")}); - } - return; - }, - - verify: function(data) { - if (session.user) { - return; - } - var http = new helma.Http; - http.setTimeout(200); - http.setReadTimeout(300); - http.setMethod("POST"); - http.setContent({ - privatekey: key, - remoteip: req.data.http_remotehost, - challenge: data.recaptcha_challenge_field, - response: data.recaptcha_response_field - }); - var request = http.getUrl("http://www.google.com/recaptcha/api/verify"); - if (request.code === 200 && !request.content.startsWith("true")) { - throw Error(gettext("Please enter the correct words in the CAPTCHA box.")); - } - return; + return { + main: function() { + if (key && !session.user) { + renderSkin("recaptcha", {id: getProperty("recaptcha.id")}); } - } + return; + }, + + verify: function(data) { + if (session.user) { + return; + } + var http = new helma.Http; + http.setTimeout(200); + http.setReadTimeout(300); + http.setMethod("POST"); + http.setContent({ + privatekey: key, + remoteip: req.data.http_remotehost, + challenge: data.recaptcha_challenge_field, + response: data.recaptcha_response_field + }); + var request = http.getUrl("http://www.google.com/recaptcha/api/verify"); + if (request.code === 200 && !request.content.startsWith("true")) { + throw Error(gettext("Please enter the correct words in the CAPTCHA box.")); + } + return; + } + } }); diff --git a/extra/updater/Global/Global.js b/extra/updater/Global/Global.js index 3d1ab44f..c2cfb2b8 100644 --- a/extra/updater/Global/Global.js +++ b/extra/updater/Global/Global.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -29,307 +29,307 @@ app.data.status = "idle"; var server = Packages.helma.main.Server.getServer(); var status = function(type) { - if (type) { - app.data.status = type; - return; - } else { - return app.data.status; - } + if (type) { + app.data.status = type; + return; + } else { + return app.data.status; + } } var antville = function() { - return new Packages.helma.framework.core.ApplicationBean(server. - getApplication("antville")); + return new Packages.helma.framework.core.ApplicationBean(server. + getApplication("antville")); } var db = function() { - app.data.db || (app.data.db = new Packages.helma.scripting.rhino.extensions. - DatabaseObject(antville().getDbSource("antville"))); - return app.data.db; + app.data.db || (app.data.db = new Packages.helma.scripting.rhino.extensions. + DatabaseObject(antville().getDbSource("antville"))); + return app.data.db; } var ResultWrapper = function(result) { - var columns = []; - this.values = {}; + var columns = []; + this.values = {}; - for (var i=1; i<=result.getColumnCount(); i+=1) { - columns.push(result.getColumnName(i)); - } + for (var i=1; i<=result.getColumnCount(); i+=1) { + columns.push(result.getColumnName(i)); + } - this.update = function() { - for each (var key in columns) { - this.values[key] = result.getColumnItem(key); - } - return; - } + this.update = function() { + for each (var key in columns) { + this.values[key] = result.getColumnItem(key); + } + return; + } - return this; + return this; } var version = function() { - try { - var rootSite = antville().__app__.getDataRoot(); - var metadata = eval(rootSite.metadata_source); - return metadata.version || ""; - } catch (ex) { - return ""; - } + try { + var rootSite = antville().__app__.getDataRoot(); + var metadata = eval(rootSite.metadata_source); + return metadata.version || ""; + } catch (ex) { + return ""; + } } var init = function() { - var currentVersion = version(); - if (status() === "running") { - msg("Updater is already running"); - return false; - } else if (getProperty("version.to") == currentVersion) { - msg("Antville installation is already up-to-date"); - status("finished"); - return false; - } else if (getProperty("version.from") != currentVersion) { - msg("Updater cannot upgrade version " + currentVersion); - status("failed") - return false; - } else { - status("running"); - } + var currentVersion = version(); + if (status() === "running") { + msg("Updater is already running"); + return false; + } else if (getProperty("version.to") == currentVersion) { + msg("Antville installation is already up-to-date"); + status("finished"); + return false; + } else if (getProperty("version.from") != currentVersion) { + msg("Updater cannot upgrade version " + currentVersion); + status("failed") + return false; + } else { + status("running"); + } return true; } var finalize = function() { - var rootSite = antville().__app__.getDataRoot(); - var metadata = eval(rootSite.metadata_source); - metadata.version = getProperty("version.to"); - rootSite.metadata_source = metadata.toSource(); - status("finished"); - return; + var rootSite = antville().__app__.getDataRoot(); + var metadata = eval(rootSite.metadata_source); + metadata.version = getProperty("version.to"); + rootSite.metadata_source = metadata.toSource(); + status("finished"); + return; } var out = function() { - var str; - if (app.data.out.length() > 0) { - str = app.data.out.toString(); - app.data.out.setLength(0); - } - res.write({ - status: status(), - log: str - }.toSource()); - return; + var str; + if (app.data.out.length() > 0) { + str = app.data.out.toString(); + app.data.out.setLength(0); + } + res.write({ + status: status(), + log: str + }.toSource()); + return; } var log = function(str) { - app.log(str); - return; + app.log(str); + return; } var msg = function(str1 /* , str2, str2, ... */) { - var str = ""; - for (var i=0; i 0) { - var callback; - if (typeof values[values.length - 1] === "function") { - callback = values.pop(); - } - if (typeof values[0] === "object") { - values = values[0]; - } - str = str.replace(/\$(\w*)/g, function(str, key) { - return callback ? callback(values[key]) : values[key]; - }); - } - return str; + var values = Array.prototype.slice.call(arguments, 1); + if (values.length > 0) { + var callback; + if (typeof values[values.length - 1] === "function") { + callback = values.pop(); + } + if (typeof values[0] === "object") { + values = values[0]; + } + str = str.replace(/\$(\w*)/g, function(str, key) { + return callback ? callback(values[key]) : values[key]; + }); + } + return str; } var retrieve = function(sql /*, value1, ..., valueN */) { - // Add callback for global value() method to stringf() arguments - Array.prototype.push.call(arguments, value); - app.data.query = stringf.apply(null, arguments); - return; + // Add callback for global value() method to stringf() arguments + Array.prototype.push.call(arguments, value); + app.data.query = stringf.apply(null, arguments); + return; } var traverse = function(callback, noOffset, idName) { - if (!app.data.query || !callback) { - return; - } - var STEP = 5000, start = Date.now(); - var sql, rows, offset = 0; - while (true) { - start = Date.now(); - if (noOffset) { - sql = app.data.query.replace(/\$min/, offset); - sql = sql.replace(/\$max/, offset += noOffset); - msg(sql); - } else { - sql = app.data.query + " limit " + STEP; - sql += " offset " + offset; - offset += STEP; - msg(sql); - } - result = db().executeRetrieval(sql); - error(); - msg("Select statement took " + (Date.now() - start) + " millis"); - // FIXME: The hasMoreRows() method does not work as expected - rows = result.next(); - if (!rows) { - result.release(); - break; - } - do { - var wrapper = new ResultWrapper(result); - wrapper.update(result); - callback.call(wrapper.values, result); - } while (rows = result.next()); + if (!app.data.query || !callback) { + return; + } + var STEP = 5000, start = Date.now(); + var sql, rows, offset = 0; + while (true) { + start = Date.now(); + if (noOffset) { + sql = app.data.query.replace(/\$min/, offset); + sql = sql.replace(/\$max/, offset += noOffset); + msg(sql); + } else { + sql = app.data.query + " limit " + STEP; + sql += " offset " + offset; + offset += STEP; + msg(sql); + } + result = db().executeRetrieval(sql); + error(); + msg("Select statement took " + (Date.now() - start) + " millis"); + // FIXME: The hasMoreRows() method does not work as expected + rows = result.next(); + if (!rows) { result.release(); - msg("Update took " + (Date.now() - start) + " millis"); - } - return; + break; + } + do { + var wrapper = new ResultWrapper(result); + wrapper.update(result); + callback.call(wrapper.values, result); + } while (rows = result.next()); + result.release(); + msg("Update took " + (Date.now() - start) + " millis"); + } + return; } var execute = function(sql /*, value1, ..., valueN */) { - // Add callback for global value() method to stringf() arguments - Array.prototype.push.call(arguments, value); - sql = stringf.apply(null, arguments); - log(sql.contains("\n") ? sql.substr(0, sql.indexOf("\n")) + " ..." : sql); - try { - db().executeCommand(sql); - error(); - } catch (ex) { - error(ex); - } - return; + // Add callback for global value() method to stringf() arguments + Array.prototype.push.call(arguments, value); + sql = stringf.apply(null, arguments); + log(sql.contains("\n") ? sql.substr(0, sql.indexOf("\n")) + " ..." : sql); + try { + db().executeCommand(sql); + error(); + } catch (ex) { + error(ex); + } + return; } var archive = function() { - var staticDir = new helma.File(app.dir + "/../static"); - for each (var siteName in staticDir.list()) { - var site = siteName !== "www" ? root.get(siteName) : root; - if (!site) { - continue; + var staticDir = new helma.File(app.dir + "/../static"); + for each (var siteName in staticDir.list()) { + var site = siteName !== "www" ? root.get(siteName) : root; + if (!site) { + continue; + } + var dir = new helma.File(staticDir, siteName + "/layouts"); + for each (var layoutName in dir.list()) { + if (layoutName.startsWith(".")) { + continue; } - var dir = new helma.File(staticDir, siteName + "/layouts"); - for each (var layoutName in dir.list()) { - if (layoutName.startsWith(".")) { - continue; - } - var layout = new Layout(site); - for each (var image in dir.listRecursive(/\.(jpg|gif|png)$/)) { - var name = image.split("/").pop().split(".")[0]; - retrieve(query("archive", name, layoutName, siteName)); - traverse(function() { - var img = new Image(this); - log(img); - }); - } + var layout = new Layout(site); + for each (var image in dir.listRecursive(/\.(jpg|gif|png)$/)) { + var name = image.split("/").pop().split(".")[0]; + retrieve(query("archive", name, layoutName, siteName)); + traverse(function() { + var img = new Image(this); + log(img); + }); } - } + } + } } diff --git a/extra/updater/Global/convert.js b/extra/updater/Global/convert.js index 7e4a2fd5..979c2752 100644 --- a/extra/updater/Global/convert.js +++ b/extra/updater/Global/convert.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -24,606 +24,606 @@ // $URL$ var convert = function(type) { - if (!type) { - return; - } + if (!type) { + return; + } - var func; - if (func = arguments.callee[type]) { - try { - func(); - } catch (ex) { - error(ex.toString()); - } - } else { - execute(query(type)); - } + var func; + if (func = arguments.callee[type]) { + try { + func(); + } catch (ex) { + error(ex.toString()); + } + } else { + execute(query(type)); + } } convert.files = function() { - retrieve(query("files")); - traverse(function() { - var metadata = { - fileName: this.fileName, - contentType: this.type, - contentLength: this.size || 0, - } - this.description && (metadata.description = clean(this.description)); - execute("update file set prototype = 'File', parent_type = 'Site', " + - "parent_id = site_id, metadata = $0 where id = $1", - metadata.toSource(), this.id); - }); + retrieve(query("files")); + traverse(function() { + var metadata = { + fileName: this.fileName, + contentType: this.type, + contentLength: this.size || 0, + } + this.description && (metadata.description = clean(this.description)); + execute("update file set prototype = 'File', parent_type = 'Site', " + + "parent_id = site_id, metadata = $0 where id = $1", + metadata.toSource(), this.id); + }); } convert.images = function() { - execute("alter table tag change id id int(11) not null auto_increment") - execute("alter table tag_hub change id id int(11) not null auto_increment"); + execute("alter table tag change id id int(11) not null auto_increment") + execute("alter table tag_hub change id id int(11) not null auto_increment"); - retrieve("select distinct(IMAGE_TOPIC), IMAGE_F_SITE " + - "from AV_IMAGE where IMAGE_TOPIC is not null"); - traverse(function() { - execute("insert into tag set site_id = $0, name = $1, type = $2", - this.IMAGE_F_SITE, this.IMAGE_TOPIC.replace(/^[\/\.]*$/, "?"), 'Image'); - }); + retrieve("select distinct(IMAGE_TOPIC), IMAGE_F_SITE " + + "from AV_IMAGE where IMAGE_TOPIC is not null"); + traverse(function() { + execute("insert into tag set site_id = $0, name = $1, type = $2", + this.IMAGE_F_SITE, this.IMAGE_TOPIC.replace(/^[\/\.]*$/, "?"), 'Image'); + }); - retrieve("select *, t.IMAGE_WIDTH as thumbnailWidth, t.IMAGE_HEIGHT " + - "as thumbnailHeight from AV_IMAGE i left join AV_IMAGE t on " + - "i.IMAGE_F_IMAGE_THUMB = t.IMAGE_ID left join tag on " + - "i.IMAGE_F_SITE = site_id and i.IMAGE_TOPIC = name and " + - "type = 'Image' left join AV_LAYOUT l on LAYOUT_ID = i.IMAGE_F_LAYOUT " + - "where i.IMAGE_WIDTH is not null and i.IMAGE_HEIGHT is not null and " + - "i.IMAGE_F_IMAGE_PARENT is null and i.IMAGE_ID > $min and " + - "i.IMAGE_ID <= $max order by i.IMAGE_ID"); + retrieve("select *, t.IMAGE_WIDTH as thumbnailWidth, t.IMAGE_HEIGHT " + + "as thumbnailHeight from AV_IMAGE i left join AV_IMAGE t on " + + "i.IMAGE_F_IMAGE_THUMB = t.IMAGE_ID left join tag on " + + "i.IMAGE_F_SITE = site_id and i.IMAGE_TOPIC = name and " + + "type = 'Image' left join AV_LAYOUT l on LAYOUT_ID = i.IMAGE_F_LAYOUT " + + "where i.IMAGE_WIDTH is not null and i.IMAGE_HEIGHT is not null and " + + "i.IMAGE_F_IMAGE_PARENT is null and i.IMAGE_ID > $min and " + + "i.IMAGE_ID <= $max order by i.IMAGE_ID"); - traverse(function() { - var metadata = { - fileName: this.IMAGE_FILENAME + "." + this.IMAGE_FILEEXT, - contentLength: this.IMAGE_FILESIZE || 0, - contentType: "image/" + this.IMAGE_FILEEXT, - width: this.IMAGE_WIDTH, - height: this.IMAGE_HEIGHT - }; - this.IMAGE_ALTTEXT && (metadata.description = clean(this.IMAGE_ALTTEXT)); - if (this.thumbnailWidth && this.thumbnailHeight) { - metadata.thumbnailName = this.IMAGE_FILENAME + "_small" + "." + - this.IMAGE_FILEEXT; - metadata.thumbnailWidth = this.thumbnailWidth; - metadata.thumbnailHeight = this.thumbnailHeight; - } - this.metadata = metadata; + traverse(function() { + var metadata = { + fileName: this.IMAGE_FILENAME + "." + this.IMAGE_FILEEXT, + contentLength: this.IMAGE_FILESIZE || 0, + contentType: "image/" + this.IMAGE_FILEEXT, + width: this.IMAGE_WIDTH, + height: this.IMAGE_HEIGHT + }; + this.IMAGE_ALTTEXT && (metadata.description = clean(this.IMAGE_ALTTEXT)); + if (this.thumbnailWidth && this.thumbnailHeight) { + metadata.thumbnailName = this.IMAGE_FILENAME + "_small" + "." + + this.IMAGE_FILEEXT; + metadata.thumbnailWidth = this.thumbnailWidth; + metadata.thumbnailHeight = this.thumbnailHeight; + } + this.metadata = metadata; - this.IMAGE_F_SITE = this.IMAGE_F_SITE || this.LAYOUT_F_SITE || null; - this.IMAGE_F_IMAGE_PARENT = this.IMAGE_F_LAYOUT || this.IMAGE_F_SITE; - this.IMAGE_CREATETIME || (this.IMAGE_CREATETIME = null); - this.IMAGE_F_USER_CREATOR || (this.IMAGE_F_USER_CREATOR = null); - this.IMAGE_MODIFYTIME || (this.IMAGE_MODIFYTIME = null); - this.IMAGE_F_USER_MODIFIER || (this.IMAGE_F_USER_MODIFIER = null); + this.IMAGE_F_SITE = this.IMAGE_F_SITE || this.LAYOUT_F_SITE || null; + this.IMAGE_F_IMAGE_PARENT = this.IMAGE_F_LAYOUT || this.IMAGE_F_SITE; + this.IMAGE_CREATETIME || (this.IMAGE_CREATETIME = null); + this.IMAGE_F_USER_CREATOR || (this.IMAGE_F_USER_CREATOR = null); + this.IMAGE_MODIFYTIME || (this.IMAGE_MODIFYTIME = null); + this.IMAGE_F_USER_MODIFIER || (this.IMAGE_F_USER_MODIFIER = null); - execute("insert into image values ($IMAGE_ID, $IMAGE_ALIAS, " + - "$IMAGE_PROTOTYPE, $IMAGE_F_SITE, $IMAGE_F_IMAGE_PARENT, null, " + - "$metadata, $IMAGE_CREATETIME, $IMAGE_F_USER_CREATOR, " + - "$IMAGE_MODIFYTIME, $IMAGE_F_USER_MODIFIER)", this); + execute("insert into image values ($IMAGE_ID, $IMAGE_ALIAS, " + + "$IMAGE_PROTOTYPE, $IMAGE_F_SITE, $IMAGE_F_IMAGE_PARENT, null, " + + "$metadata, $IMAGE_CREATETIME, $IMAGE_F_USER_CREATOR, " + + "$IMAGE_MODIFYTIME, $IMAGE_F_USER_MODIFIER)", this); - if (this.IMAGE_TOPIC) { - execute("insert into tag_hub set tag_id = $0, tagged_id = $1, " + - "tagged_type = 'Image', user_id = $2", this.id, this.IMAGE_ID, - this.IMAGE_F_USER_MODIFIER || this.IMAGE_F_USER_CREATOR); - } + if (this.IMAGE_TOPIC) { + execute("insert into tag_hub set tag_id = $0, tagged_id = $1, " + + "tagged_type = 'Image', user_id = $2", this.id, this.IMAGE_ID, + this.IMAGE_F_USER_MODIFIER || this.IMAGE_F_USER_CREATOR); + } - //execute("delete from AV_IMAGE where IMAGE_ID = $0", this.IMAGE_ID); - }, 5000); + //execute("delete from AV_IMAGE where IMAGE_ID = $0", this.IMAGE_ID); + }, 5000); - execute("alter table tag change id id int(11)") - execute("alter table tag_hub change id id int(11)"); + execute("alter table tag change id id int(11)") + execute("alter table tag_hub change id id int(11)"); } convert.layoutImages = function() { - retrieve("select *, i.IMAGE_ALIAS, l.LAYOUT_ALIAS as layoutName, " + - "l.LAYOUT_ID as layoutId, t.IMAGE_WIDTH as thumbnailWidth, " + - "t.IMAGE_HEIGHT as thumbnailHeight, pl.LAYOUT_ALIAS as " + - "parentLayout from AV_LAYOUT pl, AV_IMAGE i left join " + - "AV_IMAGE t on i.IMAGE_F_IMAGE_THUMB = t.IMAGE_ID, AV_LAYOUT l " + - "left join AV_SITE site on SITE_ID = l.LAYOUT_F_SITE where " + - "i.IMAGE_F_LAYOUT = pl.LAYOUT_ID and l.LAYOUT_F_LAYOUT_PARENT = " + - "pl.LAYOUT_ID and pl.LAYOUT_F_SITE is null and i.IMAGE_PROTOTYPE " + - "= 'LayoutImage' and i.IMAGE_F_IMAGE_PARENT is null and " + - "i.IMAGE_ALIAS not in (select IMAGE_ALIAS from AV_IMAGE, " + - "AV_LAYOUT, AV_SITE where LAYOUT_ID = IMAGE_F_LAYOUT and " + - "SITE_ID = LAYOUT_F_SITE and IMAGE_PROTOTYPE = 'LayoutImage' " + - "and IMAGE_F_IMAGE_PARENT is null and LAYOUT_ID = l.LAYOUT_ID " + - "and SITE_ID = site.SITE_ID) and l.LAYOUT_ID > $min and " + - "l.LAYOUT_ID <= $max order by l.LAYOUT_ID"); + retrieve("select *, i.IMAGE_ALIAS, l.LAYOUT_ALIAS as layoutName, " + + "l.LAYOUT_ID as layoutId, t.IMAGE_WIDTH as thumbnailWidth, " + + "t.IMAGE_HEIGHT as thumbnailHeight, pl.LAYOUT_ALIAS as " + + "parentLayout from AV_LAYOUT pl, AV_IMAGE i left join " + + "AV_IMAGE t on i.IMAGE_F_IMAGE_THUMB = t.IMAGE_ID, AV_LAYOUT l " + + "left join AV_SITE site on SITE_ID = l.LAYOUT_F_SITE where " + + "i.IMAGE_F_LAYOUT = pl.LAYOUT_ID and l.LAYOUT_F_LAYOUT_PARENT = " + + "pl.LAYOUT_ID and pl.LAYOUT_F_SITE is null and i.IMAGE_PROTOTYPE " + + "= 'LayoutImage' and i.IMAGE_F_IMAGE_PARENT is null and " + + "i.IMAGE_ALIAS not in (select IMAGE_ALIAS from AV_IMAGE, " + + "AV_LAYOUT, AV_SITE where LAYOUT_ID = IMAGE_F_LAYOUT and " + + "SITE_ID = LAYOUT_F_SITE and IMAGE_PROTOTYPE = 'LayoutImage' " + + "and IMAGE_F_IMAGE_PARENT is null and LAYOUT_ID = l.LAYOUT_ID " + + "and SITE_ID = site.SITE_ID) and l.LAYOUT_ID > $min and " + + "l.LAYOUT_ID <= $max order by l.LAYOUT_ID"); - traverse(function() { - var metadata = { - fileName: this.IMAGE_FILENAME + "." + this.IMAGE_FILEEXT, - contentLength: this.IMAGE_FILESIZE || 0, - contentType: "image/" + this.IMAGE_FILEEXT, - width: this.IMAGE_WIDTH, - height: this.IMAGE_HEIGHT - }; - this.IMAGE_ALTTEXT && (metadata.description = clean(this.IMAGE_ALTTEXT)); - if (this.thumbnailWidth && this.thumbnailHeight) { - metadata.thumbnailName = this.IMAGE_FILENAME + "_small" + "." + - this.IMAGE_FILEEXT; - metadata.thumbnailWidth = this.thumbnailWidth; - metadata.thumbnailHeight = this.thumbnailHeight; + traverse(function() { + var metadata = { + fileName: this.IMAGE_FILENAME + "." + this.IMAGE_FILEEXT, + contentLength: this.IMAGE_FILESIZE || 0, + contentType: "image/" + this.IMAGE_FILEEXT, + width: this.IMAGE_WIDTH, + height: this.IMAGE_HEIGHT + }; + this.IMAGE_ALTTEXT && (metadata.description = clean(this.IMAGE_ALTTEXT)); + if (this.thumbnailWidth && this.thumbnailHeight) { + metadata.thumbnailName = this.IMAGE_FILENAME + "_small" + "." + + this.IMAGE_FILEEXT; + metadata.thumbnailWidth = this.thumbnailWidth; + metadata.thumbnailHeight = this.thumbnailHeight; + } + this.metadata = metadata; + + this.SITE_ID || (this.SITE_ID = null); + this.IMAGE_CREATETIME || (this.IMAGE_CREATETIME = this.SITE_CREATETIME); + this.IMAGE_F_USER_CREATOR || (this.IMAGE_F_USER_CREATOR = + this.SITE_F_USER_CREATOR || null); + this.IMAGE_MODIFYTIME || (this.IMAGE_MODIFYTIME = null); + this.IMAGE_F_USER_MODIFIER || (this.IMAGE_F_USER_MODIFIER = null); + + execute("insert into image values ($IMAGE_ID, $IMAGE_ALIAS, " + + "'LayoutImage', $SITE_ID, $layoutId, 'Layout', $metadata, " + + "$IMAGE_CREATETIME, $IMAGE_F_USER_CREATOR, $IMAGE_MODIFYTIME, " + + "$IMAGE_F_USER_MODIFIER)", this); + + var fpath = antville().properties.staticPath; + var files = [metadata.fileName, metadata.thumbnailName]; + for each (var fname in files) { + var source = new helma.File(fpath + "/layouts/" + + this.parentLayout, fname); + var layoutDir = new helma.File(fpath + this.SITE_ALIAS + + "/layouts/", this.layoutName); + layoutDir.exists() || layoutDir.makeDirectory(); + var dest = new helma.File(layoutDir, fname); + if (source.exists()) { + log("Copy " + source + " to " + dest); + if (dest.exists()) { + dest.remove(); + } + source.hardCopy(dest); } - this.metadata = metadata; - - this.SITE_ID || (this.SITE_ID = null); - this.IMAGE_CREATETIME || (this.IMAGE_CREATETIME = this.SITE_CREATETIME); - this.IMAGE_F_USER_CREATOR || (this.IMAGE_F_USER_CREATOR = - this.SITE_F_USER_CREATOR || null); - this.IMAGE_MODIFYTIME || (this.IMAGE_MODIFYTIME = null); - this.IMAGE_F_USER_MODIFIER || (this.IMAGE_F_USER_MODIFIER = null); - - execute("insert into image values ($IMAGE_ID, $IMAGE_ALIAS, " + - "'LayoutImage', $SITE_ID, $layoutId, 'Layout', $metadata, " + - "$IMAGE_CREATETIME, $IMAGE_F_USER_CREATOR, $IMAGE_MODIFYTIME, " + - "$IMAGE_F_USER_MODIFIER)", this); - - var fpath = antville().properties.staticPath; - var files = [metadata.fileName, metadata.thumbnailName]; - for each (var fname in files) { - var source = new helma.File(fpath + "/layouts/" + - this.parentLayout, fname); - var layoutDir = new helma.File(fpath + this.SITE_ALIAS + - "/layouts/", this.layoutName); - layoutDir.exists() || layoutDir.makeDirectory(); - var dest = new helma.File(layoutDir, fname); - if (source.exists()) { - log("Copy " + source + " to " + dest); - if (dest.exists()) { - dest.remove(); - } - source.hardCopy(dest); - } - } - }, 100); + } + }, 100); } convert.layouts = function() { - convert.xml("layout"); - retrieve(query("layouts")); - traverse(function() { - var metadata = eval(this.metadata) || {}; - metadata.title = this.LAYOUT_TITLE || "Layout #" + this.id; - metadata.description = this.LAYOUT_DESCRIPTION; - if (this.LAYOUT_ISIMPORT) { - // FIXME: metadata.origin = Layout.getById(id).href(); - } - execute("update layout set metadata = " + - quote(metadata.toSource()) + " where id = " + this.id); - }); + convert.xml("layout"); + retrieve(query("layouts")); + traverse(function() { + var metadata = eval(this.metadata) || {}; + metadata.title = this.LAYOUT_TITLE || "Layout #" + this.id; + metadata.description = this.LAYOUT_DESCRIPTION; + if (this.LAYOUT_ISIMPORT) { + // FIXME: metadata.origin = Layout.getById(id).href(); + } + execute("update layout set metadata = " + + quote(metadata.toSource()) + " where id = " + this.id); + }); } convert.sites = function() { - convert.xml("site"); - retrieve(query("sites")); - traverse(function() { - var metadata = eval(this.metadata) || {}; - metadata.email = this.SITE_EMAIL; - metadata.title = this.SITE_TITLE; - metadata.configured = this.SITE_LASTUPDATE; - metadata.pageSize = metadata.days || 3; - metadata.pageMode = "days"; - metadata.timeZone = metadata.timezone || "CET"; - metadata.archiveMode = metadata.archive ? "public" : "closed"; - metadata.commentMode = metadata.discussions ? "enabled" : "disabled"; - metadata.shortDateFormat = metadata.shortdateformat; - metadata.longDateFormat = metadata.longdateformat; - metadata.closed = this.SITE_LASTOFFLINE; - metadata.notifiedOfBlocking = this.SITE_LASTBLOCKWARN; - metadata.notifiedOfDeletion = this.SITE_LASTDELWARN; - metadata.callbackMode = this.SITE_ENABLEPING ? - "enabled" : "disabled"; - // FIXME: metadata.webHookUrl = ""; - metadata.locale = metadata.language; - if (metadata.country) { - metadata.locale += "_" + metadata.country; - } - var mode = metadata.usercontrib ? 'open' : this.mode; - for each (var key in ["enableping", "usercontrib", "archive", - "discussions", "days", "shortdateformat", "longdateformat", - "linkcolor", "alinkcolor", "vlinkcolor", "smallcolor", - "titlecolor", "titlefont", "textfont", "textcolor", "smallsize", - "smallfont", "textsize", "titlesize", "timezone", "bgcolor", - "language", "country"]) { - delete metadata[key]; - } - execute("update site set metadata = " + quote(metadata.toSource()) + - ", mode = " + quote(mode) + " where id = " + this.id); - }); + convert.xml("site"); + retrieve(query("sites")); + traverse(function() { + var metadata = eval(this.metadata) || {}; + metadata.email = this.SITE_EMAIL; + metadata.title = this.SITE_TITLE; + metadata.configured = this.SITE_LASTUPDATE; + metadata.pageSize = metadata.days || 3; + metadata.pageMode = "days"; + metadata.timeZone = metadata.timezone || "CET"; + metadata.archiveMode = metadata.archive ? "public" : "closed"; + metadata.commentMode = metadata.discussions ? "enabled" : "disabled"; + metadata.shortDateFormat = metadata.shortdateformat; + metadata.longDateFormat = metadata.longdateformat; + metadata.closed = this.SITE_LASTOFFLINE; + metadata.notifiedOfBlocking = this.SITE_LASTBLOCKWARN; + metadata.notifiedOfDeletion = this.SITE_LASTDELWARN; + metadata.callbackMode = this.SITE_ENABLEPING ? + "enabled" : "disabled"; + // FIXME: metadata.webHookUrl = ""; + metadata.locale = metadata.language; + if (metadata.country) { + metadata.locale += "_" + metadata.country; + } + var mode = metadata.usercontrib ? 'open' : this.mode; + for each (var key in ["enableping", "usercontrib", "archive", + "discussions", "days", "shortdateformat", "longdateformat", + "linkcolor", "alinkcolor", "vlinkcolor", "smallcolor", + "titlecolor", "titlefont", "textfont", "textcolor", "smallsize", + "smallfont", "textsize", "titlesize", "timezone", "bgcolor", + "language", "country"]) { + delete metadata[key]; + } + execute("update site set metadata = " + quote(metadata.toSource()) + + ", mode = " + quote(mode) + " where id = " + this.id); + }); } convert.content = function() { - execute("alter table tag change id id int(11) not null auto_increment") - execute("alter table tag_hub change id id int(11) not null auto_increment"); + execute("alter table tag change id id int(11) not null auto_increment") + execute("alter table tag_hub change id id int(11) not null auto_increment"); - retrieve("select distinct(TEXT_TOPIC), TEXT_F_SITE " + - "from AV_TEXT where TEXT_TOPIC is not null"); - traverse(function() { - execute("insert into tag set site_id = $0, name = $1, type = 'Story'", - this.TEXT_F_SITE, this.TEXT_TOPIC.replace(/^[\/\.]*$/, "?")); - }); + retrieve("select distinct(TEXT_TOPIC), TEXT_F_SITE " + + "from AV_TEXT where TEXT_TOPIC is not null"); + traverse(function() { + execute("insert into tag set site_id = $0, name = $1, type = 'Story'", + this.TEXT_F_SITE, this.TEXT_TOPIC.replace(/^[\/\.]*$/, "?")); + }); - var metadata = function(xml) { - try { - return Xml.readFromString(clean(xml)); - } catch (ex) { - app.debug(ex); - } - return {}; - } + var metadata = function(xml) { + try { + return Xml.readFromString(clean(xml)); + } catch (ex) { + app.debug(ex); + } + return {}; + } - retrieve("select * from AV_TEXT left join tag on TEXT_F_SITE = site_id " + - "and TEXT_TOPIC = name and type = 'Story' where TEXT_ID > $min " + - "and TEXT_ID <= $max order by TEXT_ID"); + retrieve("select * from AV_TEXT left join tag on TEXT_F_SITE = site_id " + + "and TEXT_TOPIC = name and type = 'Story' where TEXT_ID > $min " + + "and TEXT_ID <= $max order by TEXT_ID"); - traverse(function() { - if (this.TEXT_PROTOTYPE === "Comment") { - if (!this.TEXT_F_TEXT_PARENT) { - this.parent_type = "Story"; - this.TEXT_F_TEXT_PARENT = this.TEXT_F_TEXT_STORY; - } else { - this.parent_type = "Comment"; - } - this.status = "public"; - this.mode = "hidden"; - this.comment_mode = "open"; + traverse(function() { + if (this.TEXT_PROTOTYPE === "Comment") { + if (!this.TEXT_F_TEXT_PARENT) { + this.parent_type = "Story"; + this.TEXT_F_TEXT_PARENT = this.TEXT_F_TEXT_STORY; } else { - this.TEXT_F_TEXT_STORY = this.TEXT_F_TEXT_PARENT = null; - this.parent_type = null; + this.parent_type = "Comment"; + } + this.status = "public"; + this.mode = "hidden"; + this.comment_mode = "open"; + } else { + this.TEXT_F_TEXT_STORY = this.TEXT_F_TEXT_PARENT = null; + this.parent_type = null; - this.status = "public"; - this.mode = "featured"; - if (this.TEXT_ISONLINE == 1) { - this.mode = "hidden"; - } else if (this.TEXT_ISONLINE != 2) { - this.status = "closed"; - } - - if (this.TEXT_EDITABLEBY == 1) { - this.status = "shared"; - } else if (this.TEXT_EDITABLEBY == 2) { - this.status = "open"; - } - this.comment_mode = this.TEXT_HASDISCUSSIONS == 1 ? "open" : "closed"; + this.status = "public"; + this.mode = "featured"; + if (this.TEXT_ISONLINE == 1) { + this.mode = "hidden"; + } else if (this.TEXT_ISONLINE != 2) { + this.status = "closed"; } - this.TEXT_F_USER_MODIFIER || (this.TEXT_F_USER_MODIFIER = null); - - this.name = this.ALIAS || ""; - this.metadata = metadata(this.TEXT_CONTENT); - execute("insert into content values ($TEXT_ID, $name, " + - "$TEXT_PROTOTYPE, $TEXT_F_SITE, $TEXT_F_TEXT_STORY, " + - "$TEXT_F_TEXT_PARENT, $parent_type, $TEXT_READS, $status, " + - "$mode, $comment_mode, $metadata, $TEXT_CREATETIME, " + - "$TEXT_F_USER_CREATOR, $TEXT_MODIFYTIME, $TEXT_F_USER_MODIFIER)", - this); - if (this.TEXT_TOPIC) { - execute("insert into tag_hub set tag_id = $0, tagged_id = $1, " + - "tagged_type = 'Story', user_id = $2", this.id, this.TEXT_ID, - this.TEXT_F_USER_MODIFIER || this.TEXT_F_USER_CREATOR); + if (this.TEXT_EDITABLEBY == 1) { + this.status = "shared"; + } else if (this.TEXT_EDITABLEBY == 2) { + this.status = "open"; } - //execute("delete from AV_TEXT where TEXT_ID = " + this.TEXT_ID); - }, 5000); + this.comment_mode = this.TEXT_HASDISCUSSIONS == 1 ? "open" : "closed"; + } - execute("alter table tag change id id int(11)") - execute("alter table tag_hub change id id int(11)"); + this.TEXT_F_USER_MODIFIER || (this.TEXT_F_USER_MODIFIER = null); + + this.name = this.ALIAS || ""; + this.metadata = metadata(this.TEXT_CONTENT); + execute("insert into content values ($TEXT_ID, $name, " + + "$TEXT_PROTOTYPE, $TEXT_F_SITE, $TEXT_F_TEXT_STORY, " + + "$TEXT_F_TEXT_PARENT, $parent_type, $TEXT_READS, $status, " + + "$mode, $comment_mode, $metadata, $TEXT_CREATETIME, " + + "$TEXT_F_USER_CREATOR, $TEXT_MODIFYTIME, $TEXT_F_USER_MODIFIER)", + this); + if (this.TEXT_TOPIC) { + execute("insert into tag_hub set tag_id = $0, tagged_id = $1, " + + "tagged_type = 'Story', user_id = $2", this.id, this.TEXT_ID, + this.TEXT_F_USER_MODIFIER || this.TEXT_F_USER_CREATOR); + } + //execute("delete from AV_TEXT where TEXT_ID = " + this.TEXT_ID); + }, 5000); + + execute("alter table tag change id id int(11)") + execute("alter table tag_hub change id id int(11)"); } convert.users = function() { - retrieve("select id, hash, salt, USER_URL from user"); - traverse(function() { - var metadata = { - hash: this.hash, - salt: this.salt, - url: this.USER_URL - } - execute("update user set metadata = " + - quote(metadata.toSource()) + " where id = " + this.id); - }); + retrieve("select id, hash, salt, USER_URL from user"); + traverse(function() { + var metadata = { + hash: this.hash, + salt: this.salt, + url: this.USER_URL + } + execute("update user set metadata = " + + quote(metadata.toSource()) + " where id = " + this.id); + }); } convert.xml = function(table) { - var metadata = function(xml) { - try { - return Xml.readFromString(clean(xml)); - } catch (ex) { - app.debug(ex); - } - return {}; - }; - retrieve(query("jsonize", table)); - traverse(function() { - var data = metadata(this.xml); - execute("update " + table + " set metadata = " + - quote(data.toSource()) + ", xml = '' where id = " + this.id); - }); + var metadata = function(xml) { + try { + return Xml.readFromString(clean(xml)); + } catch (ex) { + app.debug(ex); + } + return {}; + }; + retrieve(query("jsonize", table)); + traverse(function() { + var data = metadata(this.xml); + execute("update " + table + " set metadata = " + + quote(data.toSource()) + ", xml = '' where id = " + this.id); + }); } convert.skins = function() { - var styles = { - "bgcolor": "background color", - "linkcolor": "link color", - "alinkcolor": "active link color", - "vlinkcolor": "visited link color", - "titlefont": "big font", - "titlesize": "big font size", - "titlecolor": "big font color", - "textfont": "base font", - "textsize": "base font size", - "textcolor": "base font color", - "smallfont": "small font", - "smallsize": "small font size", - "smallcolor": "small font color" - } + var styles = { + "bgcolor": "background color", + "linkcolor": "link color", + "alinkcolor": "active link color", + "vlinkcolor": "visited link color", + "titlefont": "big font", + "titlesize": "big font size", + "titlecolor": "big font color", + "textfont": "base font", + "textsize": "base font size", + "textcolor": "base font color", + "smallfont": "small font", + "smallsize": "small font size", + "smallcolor": "small font color" + } - var rename = function(prototype, skin) { - var map = { - Day: "Archive", - LayoutImage: "Image", - LayoutImageMgr: "Images", - RootLayoutMgr: "Layouts", // FIXME: obsolete - StoryMgr: "Stories", - SysMgr: "Admin", - SysLog: "LogEntry", - Topic: "Tag", - TopicMgr: "Tags", + var rename = function(prototype, skin) { + var map = { + Day: "Archive", + LayoutImage: "Image", + LayoutImageMgr: "Images", + RootLayoutMgr: "Layouts", // FIXME: obsolete + StoryMgr: "Stories", + SysMgr: "Admin", + SysLog: "LogEntry", + Topic: "Tag", + TopicMgr: "Tags", - Comment: { - toplevel: "main" - }, + Comment: { + toplevel: "main" + }, - Members: { - statusloggedin: ["Membership", "status"], - statusloggedout: ["Membership", "login"] - }, + Members: { + statusloggedin: ["Membership", "status"], + statusloggedout: ["Membership", "login"] + }, - Site: { - searchbox: "search", - style: "stylesheet" - }, + Site: { + searchbox: "search", + style: "stylesheet" + }, - Story: { - dayheader: "date", - display: "content", - historyview: "history" - } + Story: { + dayheader: "date", + display: "content", + historyview: "history" } + } - var renamed; - if (renamed = map[prototype]) { - if (renamed.constructor === String) { - return rename(renamed, skin); - } else if (skin) { - renamed = renamed[skin]; - if (renamed) { - if (renamed.constructor === Array) { - prototype = renamed[0]; - skin = renamed[1]; - } else { - skin = renamed; - } - } - } - } else if (prototype.lastIndexOf("Mgr") > 0) { - prototype = prototype.substr(0, prototype.length - 3) + "s"; - return rename(prototype, skin); + var renamed; + if (renamed = map[prototype]) { + if (renamed.constructor === String) { + return rename(renamed, skin); + } else if (skin) { + renamed = renamed[skin]; + if (renamed) { + if (renamed.constructor === Array) { + prototype = renamed[0]; + skin = renamed[1]; + } else { + skin = renamed; + } + } } - return [prototype, skin]; - } + } else if (prototype.lastIndexOf("Mgr") > 0) { + prototype = prototype.substr(0, prototype.length - 3) + "s"; + return rename(prototype, skin); + } + return [prototype, skin]; + } - var values = function(metadata) { - if (!metadata) { - return; - } - - var data = eval(metadata); - res.push(); - for (var key in styles) { - var name = styles[key]; - var value = String(data[key]).toLowerCase(); - if (key.endsWith("color") && !helma.Color.COLORNAMES[key] && - !value.startsWith("#")) { - value = "#" + value; - } - value = value.replace(/([0-9]+) +px/, "$1px"); - res.writeln('<% value "' + name + '" "' + value + '" %>'); - } - return res.pop(); - } - - var clean = function(source) { - if (source) { - // Renaming prototype and skin names in skin macros - var re = /(<%\s*)([^.]+)(\.skin\s+name="?)([^"\s]+)/g; - source = source.replace(re, function() { - var $ = arguments; - var renamed = rename($[2].capitalize(), $[4]); - return $[1] + renamed[0].toLowerCase() + $[3] + - renamed[0] + "#" + renamed[1]; - }); - // Replacing layout.* macros with corresponding value macros - source = source.replace(/(<%\s*)layout\.([^\s]+)/g, function() { - var value = styles[arguments[2]]; - if (value) { - return arguments[1] + "value " + quote(value); - } - return arguments[0]; - }); - return source; - } - } - - var move = function(sourcePath, destPath) { - var source = new helma.File(sourcePath); - if (source.exists()) { - var destination = new helma.File(destPath); - if (destination.exists()) { - destination.removeDirectory(); - } - destination.makeDirectory(); - var files = source.list(); - for each (var fname in files) { - (new helma.File(source, fname)).hardCopy(new helma.File(destination, fname)); - } - } - return destPath; - } - - var save = function(skins, fpath) { - if (!skins) { - return; - } - - for (var prototype in skins) { - res.push(); - var skinset = skins[prototype]; - for (var skinName in skinset) { - res.writeln("<% #" + skinName + " %>"); - skinset[skinName] && res.writeln(skinset[skinName].trim()); - } - var data = res.pop(); - - if (data) { - var dir = new java.io.File(fpath, prototype); - dir.exists() || dir.mkdirs(); - var file = new java.io.File(dir, prototype + ".skin"); - file.exists() && file["delete"](); - log("Write " + prototype + ".skin" + " to " + file.getCanonicalPath()); - var fos = new java.io.FileOutputStream(file); - var bos = new java.io.BufferedOutputStream(fos); - var writer = new java.io.OutputStreamWriter(bos, "UTF-8"); - writer.write(data); - writer.close(); - bos.close(); - fos.close(); - } - } + var values = function(metadata) { + if (!metadata) { return; - } + } - var appSkins = {}; - var skinfiles = antville().getSkinfiles(); - - for (var prototype in skinfiles) { - // Ignore lowercase prototypes - if (prototype.charCodeAt(0) > 90) { - continue; + var data = eval(metadata); + res.push(); + for (var key in styles) { + var name = styles[key]; + var value = String(data[key]).toLowerCase(); + if (key.endsWith("color") && !helma.Color.COLORNAMES[key] && + !value.startsWith("#")) { + value = "#" + value; } - appSkins[prototype] || (appSkins[prototype] = {}); - var skin = createSkin(skinfiles[prototype][prototype]); - var subskins = skin.getSubskinNames(); - for each (var name in subskins) { - appSkins[prototype][name] = skin.getSubskin(name).getSource(); - } - } + value = value.replace(/([0-9]+) +px/, "$1px"); + res.writeln('<% value "' + name + '" "' + value + '" %>'); + } + return res.pop(); + } - var current, fpath, skins; - retrieve(query("skins")); - traverse(function() { - var site = this.site_name || ""; - if (current !== site + this.layout_name) { - save(skins, fpath); - current = site + this.layout_name; - fpath = antville().properties.staticPath + site; - if (!site) { - return; // FIXME: root layouts not ready, yet - var file = new helma.File("db/antville/0.xml"); - var xml = file.readAll(); - var rootLayoutId = /sys_layout idref="(\d)*"/.exec(xml)[1] || 1; - fpath += rootLayoutId == this.layout_id ? - "/layout/" : "/layouts/" + this.layout_name; - } else { - fpath += "/layouts/" + this.layout_name; - } - skins = appSkins.clone({}, true); - skins.Site.values = values(this.layout_metadata); - } + var clean = function(source) { + if (source) { + // Renaming prototype and skin names in skin macros + var re = /(<%\s*)([^.]+)(\.skin\s+name="?)([^"\s]+)/g; + source = source.replace(re, function() { + var $ = arguments; + var renamed = rename($[2].capitalize(), $[4]); + return $[1] + renamed[0].toLowerCase() + $[3] + + renamed[0] + "#" + renamed[1]; + }); + // Replacing layout.* macros with corresponding value macros + source = source.replace(/(<%\s*)layout\.([^\s]+)/g, function() { + var value = styles[arguments[2]]; + if (value) { + return arguments[1] + "value " + quote(value); + } + return arguments[0]; + }); + return source; + } + } - if (!this.prototype || !this.name) { - return; + var move = function(sourcePath, destPath) { + var source = new helma.File(sourcePath); + if (source.exists()) { + var destination = new helma.File(destPath); + if (destination.exists()) { + destination.removeDirectory(); } + destination.makeDirectory(); + var files = source.list(); + for each (var fname in files) { + (new helma.File(source, fname)).hardCopy(new helma.File(destination, fname)); + } + } + return destPath; + } - var renamed = rename(this.prototype, this.name); - var prototype = renamed[0]; - var skinName = renamed[1]; - var source, parent; - var appSkin = (skins[prototype] && skins[prototype][skinName]); - if (this.source !== null) { - source = this.source; - parent = this.parent !== null ? this.parent : appSkin; + var save = function(skins, fpath) { + if (!skins) { + return; + } + + for (var prototype in skins) { + res.push(); + var skinset = skins[prototype]; + for (var skinName in skinset) { + res.writeln("<% #" + skinName + " %>"); + skinset[skinName] && res.writeln(skinset[skinName].trim()); + } + var data = res.pop(); + + if (data) { + var dir = new java.io.File(fpath, prototype); + dir.exists() || dir.mkdirs(); + var file = new java.io.File(dir, prototype + ".skin"); + file.exists() && file["delete"](); + log("Write " + prototype + ".skin" + " to " + file.getCanonicalPath()); + var fos = new java.io.FileOutputStream(file); + var bos = new java.io.BufferedOutputStream(fos); + var writer = new java.io.OutputStreamWriter(bos, "UTF-8"); + writer.write(data); + writer.close(); + bos.close(); + fos.close(); + } + } + return; + } + + var appSkins = {}; + var skinfiles = antville().getSkinfiles(); + + for (var prototype in skinfiles) { + // Ignore lowercase prototypes + if (prototype.charCodeAt(0) > 90) { + continue; + } + appSkins[prototype] || (appSkins[prototype] = {}); + var skin = createSkin(skinfiles[prototype][prototype]); + var subskins = skin.getSubskinNames(); + for each (var name in subskins) { + appSkins[prototype][name] = skin.getSubskin(name).getSource(); + } + } + + var current, fpath, skins; + retrieve(query("skins")); + traverse(function() { + var site = this.site_name || ""; + if (current !== site + this.layout_name) { + save(skins, fpath); + current = site + this.layout_name; + fpath = antville().properties.staticPath + site; + if (!site) { + return; // FIXME: root layouts not ready, yet + var file = new helma.File("db/antville/0.xml"); + var xml = file.readAll(); + var rootLayoutId = /sys_layout idref="(\d)*"/.exec(xml)[1] || 1; + fpath += rootLayoutId == this.layout_id ? + "/layout/" : "/layouts/" + this.layout_name; } else { - source = this.parent; - parent = appSkin; + fpath += "/layouts/" + this.layout_name; } - if (source !== null && source !== undefined) { - // FIXME: Ugly hack to change Membership to Members in a few skins - if (prototype === "Membership" && - (skinName === "login" || skinName === "status")) { - source = source.replace(/(<%\s*)this./g, "$1members."); - } - // Adding the new calendar CSS classes to the old ones - if (prototype === "Site" && skinName === "stylesheet") { - source = source.replace(/(\.calHead)/g, - "table.calendar thead, $1"); - source = source.replace(/(\.calDay)/g, - "table.calendar th, table.calendar tbody td.day, $1"); - source = source.replace(/(\.calSelDay)/g, - "table.calendar tbody td.selected, $1"); - source = source.replace(/(\.calFoot)/g, - "table.calendar tfoot td, $1"); - } - ref = (skins[prototype] || (skins[prototype] = {})); - ref[skinName] = clean(source); + skins = appSkins.clone({}, true); + skins.Site.values = values(this.layout_metadata); + } + + if (!this.prototype || !this.name) { + return; + } + + var renamed = rename(this.prototype, this.name); + var prototype = renamed[0]; + var skinName = renamed[1]; + var source, parent; + var appSkin = (skins[prototype] && skins[prototype][skinName]); + if (this.source !== null) { + source = this.source; + parent = this.parent !== null ? this.parent : appSkin; + } else { + source = this.parent; + parent = appSkin; + } + if (source !== null && source !== undefined) { + // FIXME: Ugly hack to change Membership to Members in a few skins + if (prototype === "Membership" && + (skinName === "login" || skinName === "status")) { + source = source.replace(/(<%\s*)this./g, "$1members."); } - if (parent !== null && parent !== undefined) { - execute("update skin set source = '" + - clean(parent).replace(/'/g, "\\'") + "' where " + - 'id = ' + this.id); + // Adding the new calendar CSS classes to the old ones + if (prototype === "Site" && skinName === "stylesheet") { + source = source.replace(/(\.calHead)/g, + "table.calendar thead, $1"); + source = source.replace(/(\.calDay)/g, + "table.calendar th, table.calendar tbody td.day, $1"); + source = source.replace(/(\.calSelDay)/g, + "table.calendar tbody td.selected, $1"); + source = source.replace(/(\.calFoot)/g, + "table.calendar tfoot td, $1"); } - }); - // One last time to be sure every layout's skins are saved - save(skins, fpath); - return; + ref = (skins[prototype] || (skins[prototype] = {})); + ref[skinName] = clean(source); + } + if (parent !== null && parent !== undefined) { + execute("update skin set source = '" + + clean(parent).replace(/'/g, "\\'") + "' where " + + 'id = ' + this.id); + } + }); + // One last time to be sure every layout's skins are saved + save(skins, fpath); + return; } convert.folders = function() { - retrieve("select site.name as site_name, layout.name as layout_name from " + - "site left join layout on site.layout_id = layout.id"); - traverse(function() { - var dir = antville().properties.staticPath + this.site_name; - var source = new helma.File(dir, "layouts/" + this.layout_name); - var dest = new helma.File(dir, "layout"); - log("Copy " + source + " to " + dest); - if (dest.exists()) { - dest.removeDirectory(); - } - source.renameTo(dest); - }); + retrieve("select site.name as site_name, layout.name as layout_name from " + + "site left join layout on site.layout_id = layout.id"); + traverse(function() { + var dir = antville().properties.staticPath + this.site_name; + var source = new helma.File(dir, "layouts/" + this.layout_name); + var dest = new helma.File(dir, "layout"); + log("Copy " + source + " to " + dest); + if (dest.exists()) { + dest.removeDirectory(); + } + source.renameTo(dest); + }); } convert.root = function() { - var rootId = antville().__app__.getProperty("rootId"); - var staticDir = antville().properties.staticPath; - retrieve("select name from site where id = " + rootId); - traverse(function() { - if (this.name === "www") { - return; - } - var dir = new helma.File(staticDir, this.name); - var files = dir.list(); - for each (fname in files) { - var source = new helma.File(dir, fname); - var dest = new helma.File(staticDir, "www/" + fname); - log("Rename " + source + " to " + dest); - source.renameTo(dest); - } + var rootId = antville().__app__.getProperty("rootId"); + var staticDir = antville().properties.staticPath; + retrieve("select name from site where id = " + rootId); + traverse(function() { + if (this.name === "www") { return; - }); - execute("update site set name = 'www' where id = " + rootId); - return; + } + var dir = new helma.File(staticDir, this.name); + var files = dir.list(); + for each (fname in files) { + var source = new helma.File(dir, fname); + var dest = new helma.File(staticDir, "www/" + fname); + log("Rename " + source + " to " + dest); + source.renameTo(dest); + } + return; + }); + execute("update site set name = 'www' where id = " + rootId); + return; } diff --git a/extra/updater/Root/Root.js b/extra/updater/Root/Root.js index a5696f40..dd0b19be 100644 --- a/extra/updater/Root/Root.js +++ b/extra/updater/Root/Root.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -30,86 +30,86 @@ app.addRepository("modules/helma/Color.js"); app.addRepository("modules/helma/File.js"); Root.prototype.updater_action = function() { - // Disabled for safety reasons - return; + // Disabled for safety reasons + return; - app.invokeAsync(global, function() { - if (init()) { - //update("size"); // DEBUG - //update("legacy"); - update("tag"); - update("tag_hub"); - update("AV_ACCESSLOG"); - update("AV_CHOICE"); - update("AV_FILE"); - update("AV_IMAGE"); - update("AV_LAYOUT"); - update("AV_MEMBERSHIP"); - update("AV_POLL"); - update("AV_SITE"); - update("AV_SKIN"); - update("AV_TEXT"); - update("AV_USER"); - update("AV_VOTE"); - update("AV_SYSLOG"); // This table has to go last! - convert("folders"); - convert("root"); - finalize(); - } - return; - }, [], -1); - this.renderSkin("~Root"); - return; + app.invokeAsync(global, function() { + if (init()) { + //update("size"); // DEBUG + //update("legacy"); + update("tag"); + update("tag_hub"); + update("AV_ACCESSLOG"); + update("AV_CHOICE"); + update("AV_FILE"); + update("AV_IMAGE"); + update("AV_LAYOUT"); + update("AV_MEMBERSHIP"); + update("AV_POLL"); + update("AV_SITE"); + update("AV_SKIN"); + update("AV_TEXT"); + update("AV_USER"); + update("AV_VOTE"); + update("AV_SYSLOG"); // This table has to go last! + convert("folders"); + convert("root"); + finalize(); + } + return; + }, [], -1); + this.renderSkin("~Root"); + return; } Root.prototype.out_action = function() { - res.contentType = "text/plain"; - return out(); + res.contentType = "text/plain"; + return out(); } Root.prototype.nonames_action = function() { - app.invokeAsync(global, function() { - ["image", "file"].forEach(function(table) { - retrieve("select * from " + table + " where name = ''"); - traverse(function() { - this.name = Date.now() + "-" + this.id; - var metadata = eval(this.metadata); - var extension = metadata.contentType.split("/").pop(); - metadata.fileName = this.name + "." + extension; - metadata.thumbnailName = this.name + "_small." + extension; - this.metadata = metadata; - execute("update " + table + " set name = $name, metadata = " + - "$metadata where id = $id", this); - }); + app.invokeAsync(global, function() { + ["image", "file"].forEach(function(table) { + retrieve("select * from " + table + " where name = ''"); + traverse(function() { + this.name = Date.now() + "-" + this.id; + var metadata = eval(this.metadata); + var extension = metadata.contentType.split("/").pop(); + metadata.fileName = this.name + "." + extension; + metadata.thumbnailName = this.name + "_small." + extension; + this.metadata = metadata; + execute("update " + table + " set name = $name, metadata = " + + "$metadata where id = $id", this); }); - status("finished"); - }, [], -1); - this.renderSkin("~Root"); - return; + }); + status("finished"); + }, [], -1); + this.renderSkin("~Root"); + return; } Root.prototype.galleries_action = function() { - var oldDatabase = "antville_1_1"; - app.invokeAsync(global, function() { - execute("alter table tag_hub add column `tagged_id_old` int(11) default NULL"); - execute("alter table tag_hub add column `tagged_type_old` enum('Story','Image') default NULL"); - execute("update tag_hub set tagged_type_old = tagged_type, tagged_id_old = tagged_id;"); - retrieve(stringf("select tag_hub.*, IMAGE_ALIAS as name, " + - "IMAGE_F_SITE as site from tag_hub left join $0.AV_IMAGE on " + - "IMAGE_ID = tagged_id where tagged_id in " + - "(select IMAGE_ID from $0.AV_IMAGE where IMAGE_TOPIC is not " + - "null and IMAGE_F_IMAGE_PARENT is null)", oldDatabase)); - traverse(function() { - execute("update tag_hub set tagged_type = 'Image', tagged_id = " + - "(select id from image where name = $name and site_id = " + - "$site and parent_type = 'Site') where id = $id", this); - }); - status("finished"); - }, [], -1); - this.renderSkin("~Root"); - return; + var oldDatabase = "antville_1_1"; + app.invokeAsync(global, function() { + execute("alter table tag_hub add column `tagged_id_old` int(11) default NULL"); + execute("alter table tag_hub add column `tagged_type_old` enum('Story','Image') default NULL"); + execute("update tag_hub set tagged_type_old = tagged_type, tagged_id_old = tagged_id;"); + retrieve(stringf("select tag_hub.*, IMAGE_ALIAS as name, " + + "IMAGE_F_SITE as site from tag_hub left join $0.AV_IMAGE on " + + "IMAGE_ID = tagged_id where tagged_id in " + + "(select IMAGE_ID from $0.AV_IMAGE where IMAGE_TOPIC is not " + + "null and IMAGE_F_IMAGE_PARENT is null)", oldDatabase)); + traverse(function() { + execute("update tag_hub set tagged_type = 'Image', tagged_id = " + + "(select id from image where name = $name and site_id = " + + "$site and parent_type = 'Site') where id = $id", this); + }); + status("finished"); + }, [], -1); + this.renderSkin("~Root"); + return; } Root.prototype.patch = function(code) { - eval(code); + eval(code); } diff --git a/extra/updater/patch-20080913.js b/extra/updater/patch-20080913.js index bdfa75a1..1abc7b62 100644 --- a/extra/updater/patch-20080913.js +++ b/extra/updater/patch-20080913.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,48 +26,48 @@ // Apply with enabled updater repository via ant patch -Dpatch.id=20080913 root.forEach(function() { - var site = this; - if (site.layout) { - res.handlers.layout = site.layout; - res.skinpath = site.layout.getSkinPath(); + var site = this; + if (site.layout) { + res.handlers.layout = site.layout; + res.skinpath = site.layout.getSkinPath(); - // Fixing the corrupted <% site#history" %> macros - var skin = site.layout.skins.getSkin("Site", "page"); + // Fixing the corrupted <% site#history" %> macros + var skin = site.layout.skins.getSkin("Site", "page"); + var source = skin.getSource(); + + var newSource = source.replace(/<%(\s+site#(history|searchbox)"[^%]*%>)/g, function() { + var replacement = "<% // " + arguments[1]; + app.log(arguments[0] + " ==> " + replacement); + return replacement; + }); + if (newSource !== source) { + var delta = source.length - newSource.length; + //if (Math.abs(delta) > 5) res.debug("!!! Delta in " + site + ": " + delta); + skin.setSource(newSource); + } + + // Fixing the macro handlers in skins shared between Story and Comment + ["history", "rss", "result"].forEach(function(name) { + var skin = site.layout.skins.getSkin("Story", name); var source = skin.getSource(); - - var newSource = source.replace(/<%(\s+site#(history|searchbox)"[^%]*%>)/g, function() { - var replacement = "<% // " + arguments[1]; - app.log(arguments[0] + " ==> " + replacement); - return replacement; - }); - if (newSource !== source) { - var delta = source.length - newSource.length; - //if (Math.abs(delta) > 5) res.debug("!!! Delta in " + site + ": " + delta); - skin.setSource(newSource); + if (!source) { + // FIXME: What the heck is going on here? + app.log("????? " + site.name + ": " + skin); + return; } - - // Fixing the macro handlers in skins shared between Story and Comment - ["history", "rss", "result"].forEach(function(name) { - var skin = site.layout.skins.getSkin("Story", name); - var source = skin.getSource(); - if (!source) { - // FIXME: What the heck is going on here? - app.log("????? " + site.name + ": " + skin); - return; - } - var newSource = source.replace(/(<%\s+)story\./g, function() { - var replacement = arguments[1] + "this."; - app.log(arguments[0] + " ==> " + replacement); - return replacement; - }); - var delta = source.length - newSource.length; - if (delta !== 0) { - //if (Math.abs(delta) > 5) app.log("!!! Delta in " + site + " skin Story:" + name + ": " + delta); - skin.setSource(newSource); - } + var newSource = source.replace(/(<%\s+)story\./g, function() { + var replacement = arguments[1] + "this."; + app.log(arguments[0] + " ==> " + replacement); + return replacement; }); + var delta = source.length - newSource.length; + if (delta !== 0) { + //if (Math.abs(delta) > 5) app.log("!!! Delta in " + site + " skin Story:" + name + ": " + delta); + skin.setSource(newSource); + } + }); } else { - app.log("Creating missing layout for site " + site.name); - site.layout = new Layout(site); - } + app.log("Creating missing layout for site " + site.name); + site.layout = new Layout(site); + } }); diff --git a/extra/updater/patch-20081211.js b/extra/updater/patch-20081211.js index 3cf5d2e4..2fb6f859 100644 --- a/extra/updater/patch-20081211.js +++ b/extra/updater/patch-20081211.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,22 +26,22 @@ // Apply with enabled updater repository via ant patch -Dpatch.id=20081211 root.forEach(function() { - var site = this; - if (site.layout) { - res.handlers.layout = site.layout; - res.skinpath = site.layout.getSkinPath(); + var site = this; + if (site.layout) { + res.handlers.layout = site.layout; + res.skinpath = site.layout.getSkinPath(); - // Fixing the <% if <% comment.created %> %> macro - var skin = site.layout.skins.getSkin("Comment", "edit"); - var source = skin.getSource(); - var re = /(<%\s+if\s+<%\s+comment\.creat)ed(\s+%>\s+is\s+null)/g; - var newSource = source.replace(re, function() { - var replacement = arguments[1] + "or" + arguments[2]; - app.log(arguments[0] + " ==> " + replacement); - return replacement; - }); - if (newSource !== source) { - skin.setSource(newSource); - } - } + // Fixing the <% if <% comment.created %> %> macro + var skin = site.layout.skins.getSkin("Comment", "edit"); + var source = skin.getSource(); + var re = /(<%\s+if\s+<%\s+comment\.creat)ed(\s+%>\s+is\s+null)/g; + var newSource = source.replace(re, function() { + var replacement = arguments[1] + "or" + arguments[2]; + app.log(arguments[0] + " ==> " + replacement); + return replacement; + }); + if (newSource !== source) { + skin.setSource(newSource); + } + } }); diff --git a/extra/updater/patch-20091207.js b/extra/updater/patch-20091207.js index 9090b9c8..16419a25 100644 --- a/extra/updater/patch-20091207.js +++ b/extra/updater/patch-20091207.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -30,8 +30,8 @@ var template; // Add deleted mode to site table sql.execute("alter table antville.site change column mode mode \ - enum('deleted','closed','restricted','public','open') \ - character set latin1 collate latin1_general_ci default 'closed'"); + enum('deleted','closed','restricted','public','open') \ + character set latin1 collate latin1_general_ci default 'closed'"); // Rename user table to conform to standard SQL / Postgre specification sql.execute("alter table antville.user rename to account"); diff --git a/extra/updater/patch-20100401.js b/extra/updater/patch-20100401.js index 9a807b20..b78e6a91 100644 --- a/extra/updater/patch-20100401.js +++ b/extra/updater/patch-20100401.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -30,15 +30,15 @@ var sql = new Sql; // Correct Image.contentLength property for some images sql.retrieve("select id from image"); sql.traverse(function() { - var image = Image.getById(this.id); - try { - var contentLength = image.getFile().getLength(); - app.log("Processing " + image + ": " + image.contentLength); - if (contentLength && image.contentLength !== contentLength) { - app.log("Updating content length to " + contentLength); - image.contentLength = contentLength; - res.commit(); - } - } catch (x) { } + var image = Image.getById(this.id); + try { + var contentLength = image.getFile().getLength(); + app.log("Processing " + image + ": " + image.contentLength); + if (contentLength && image.contentLength !== contentLength) { + app.log("Updating content length to " + contentLength); + image.contentLength = contentLength; + res.commit(); + } + } catch (x) { } }); app.log("Done."); diff --git a/extra/updater/patch-20100405.js b/extra/updater/patch-20100405.js index 491f393a..f71c242a 100644 --- a/extra/updater/patch-20100405.js +++ b/extra/updater/patch-20100405.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -34,25 +34,25 @@ var template; // Afterwards user permissions should be restored: // mysql -e "grant select, insert, update, delete on antville.* to 'antville'@'localhost'" if (app.getDbSource("antville").isMySQL()) { - template = "alter table $0 modify column $1 varchar(20) default null"; - sql.execute(template, "account", "status"); - sql.execute(template, "content", "comment_mode"); - sql.execute(template, "content", "mode"); - sql.execute(template, "content", "parent_type"); - sql.execute(template, "content", "prototype"); - sql.execute(template, "content", "status"); - sql.execute(template, "file", "prototype"); - sql.execute(template, "file", "parent_type"); - sql.execute(template, "image", "prototype"); - sql.execute(template, "image", "parent_type"); - sql.execute(template, "layout", "mode"); - sql.execute(template, "log", "context_type"); - sql.execute(template, "membership", "role"); - sql.execute(template, "poll", "status"); - sql.execute(template, "site", "status"); - sql.execute(template, "site", "mode"); - sql.execute(template, "tag", "type"); - sql.execute(template, "tag_hub", "tagged_type"); + template = "alter table $0 modify column $1 varchar(20) default null"; + sql.execute(template, "account", "status"); + sql.execute(template, "content", "comment_mode"); + sql.execute(template, "content", "mode"); + sql.execute(template, "content", "parent_type"); + sql.execute(template, "content", "prototype"); + sql.execute(template, "content", "status"); + sql.execute(template, "file", "prototype"); + sql.execute(template, "file", "parent_type"); + sql.execute(template, "image", "prototype"); + sql.execute(template, "image", "parent_type"); + sql.execute(template, "layout", "mode"); + sql.execute(template, "log", "context_type"); + sql.execute(template, "membership", "role"); + sql.execute(template, "poll", "status"); + sql.execute(template, "site", "status"); + sql.execute(template, "site", "mode"); + sql.execute(template, "tag", "type"); + sql.execute(template, "tag_hub", "tagged_type"); } // Convert membership roles to lowercase @@ -64,7 +64,7 @@ sql.execute(template, 'owner', 'Owner'); // Convert notification modes to lowercase root.forEach(function() { - if (this.notificationMode !== null) { - this.notificationMode = this.notificationMode.toLowerCase() - } + if (this.notificationMode !== null) { + this.notificationMode = this.notificationMode.toLowerCase() + } }); diff --git a/extra/updater/patch-20101209.js b/extra/updater/patch-20101209.js index 2cacc474..8cce5606 100644 --- a/extra/updater/patch-20101209.js +++ b/extra/updater/patch-20101209.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,20 +26,20 @@ // Apply with enabled updater repository via ant patch -Dpatch.id=20101209 root.forEach(function() { - var site = this; - var locale = site.locale; - // Update locales to new format - if (locale.contains("_")) { - site.locale = locale.substr(0, locale.lastIndexOf("_")); - } - // Update time zones to new format - var timeZone = site.timeZone; - switch (timeZone) { - case "CET": - site.timeZone = "Europe/Vienna"; - break; - case "GMT": - site.timeZone = "Europe/London"; - break; - } + var site = this; + var locale = site.locale; + // Update locales to new format + if (locale.contains("_")) { + site.locale = locale.substr(0, locale.lastIndexOf("_")); + } + // Update time zones to new format + var timeZone = site.timeZone; + switch (timeZone) { + case "CET": + site.timeZone = "Europe/Vienna"; + break; + case "GMT": + site.timeZone = "Europe/London"; + break; + } }); diff --git a/extra/updater/patch-20110209.js b/extra/updater/patch-20110209.js index 7b289fd5..77e337ed 100644 --- a/extra/updater/patch-20110209.js +++ b/extra/updater/patch-20110209.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,7 +26,7 @@ // Apply with enabled updater repository via ant patch -Dpatch.id=20110209 if (!String(Root.VERSION).startsWith("1.2")) { - throw Error("This patch needs to be applied to version 1.2 of the Antville codebase."); + throw Error("This patch needs to be applied to version 1.2 of the Antville codebase."); } app.addRepository("modules/helma/Database.js"); diff --git a/extra/updater/patch-20110210.js b/extra/updater/patch-20110210.js index 28aee0be..45d2d028 100644 --- a/extra/updater/patch-20110210.js +++ b/extra/updater/patch-20110210.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -26,7 +26,7 @@ // Apply with enabled updater repository via ant patch -Dpatch.id=20110210 if (Root.VERSION.minor < 1.3) { - throw Error("Please update the Antville codebase to version 1.3 first."); + throw Error("Please update the Antville codebase to version 1.3 first."); } app.addRepository("modules/helma/Database.js"); @@ -34,40 +34,40 @@ app.addRepository("modules/helma/Database.js"); var sql = new Sql; function convertMetadata(prototype, table) { - table || (table = prototype.name.toLowerCase()); + table || (table = prototype.name.toLowerCase()); - var start = 0; - var max, end; + var start = 0; + var max, end; - sql.retrieve("select max(id) as count from $0", table); - sql.traverse(function() { - max = this.count; - }); + sql.retrieve("select max(id) as count from $0", table); + sql.traverse(function() { + max = this.count; + }); - while (start < max) { - end = start + 1000; - sql.retrieve("select id, metadata from $0 where id >= $1 and id < $2", table, start, end); - sql.traverse(function() { - try { - var newMetadata; - var parent = prototype.getById(this.id); - var metadata = eval(this.metadata); - for (let name in metadata) { - let value = metadata[name]; - parent.setMetadata(name, value); - } - } catch (ex) { - app.log("***** Original or converted metadata might not be kosher for " + - prototype.name + " #" + this.id); - app.log(ex.rhinoException); - } - }); - res.commit(); - start = end; - app.log(java.lang.String.format("Processed %.0f of %.0f %s objects", start, max, prototype.name)); - } + while (start < max) { + end = start + 1000; + sql.retrieve("select id, metadata from $0 where id >= $1 and id < $2", table, start, end); + sql.traverse(function() { + try { + var newMetadata; + var parent = prototype.getById(this.id); + var metadata = eval(this.metadata); + for (let name in metadata) { + let value = metadata[name]; + parent.setMetadata(name, value); + } + } catch (ex) { + app.log("***** Original or converted metadata might not be kosher for " + + prototype.name + " #" + this.id); + app.log(ex.rhinoException); + } + }); + res.commit(); + start = end; + app.log(java.lang.String.format("Processed %.0f of %.0f %s objects", start, max, prototype.name)); + } - return; + return; } convertMetadata(File); diff --git a/extra/updater/patch-20110301.js b/extra/updater/patch-20110301.js index ff08b7a6..3c749c46 100644 --- a/extra/updater/patch-20110301.js +++ b/extra/updater/patch-20110301.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, @@ -28,9 +28,9 @@ var sql = new Sql(); var sql2 = new Sql(); for each (let table in ["file", "image", "tag"]) { - sql.retrieve("select * from $0 where name like '%?%';", table); - sql.traverse(function() { - var name = "-".repeat(this.name.count("?")); - sql2.execute("update $0 set name = '$1' where id = $2", table, name, this.id); - }); + sql.retrieve("select * from $0 where name like '%?%';", table); + sql.traverse(function() { + var name = "-".repeat(this.name.count("?")); + sql2.execute("update $0 set name = '$1' where id = $2", table, name, this.id); + }); } diff --git a/extra/updater/patch-20110606.js b/extra/updater/patch-20110606.js index 645d04fa..3d6f695e 100644 --- a/extra/updater/patch-20110606.js +++ b/extra/updater/patch-20110606.js @@ -10,7 +10,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, diff --git a/static/www/antville.js b/static/www/antville.js index b72c16bc..c97c097b 100644 --- a/static/www/antville.js +++ b/static/www/antville.js @@ -1,82 +1,82 @@ $(function() { - - setLayoutMode(); - // Extend jQuery with selectText() method. - $.fn.selectText = function() { - var element = this.get(0); - if (document.body.createTextRange) { // ms - var range = document.body.createTextRange(); - range.moveToElementText(element); - range.select(); - } else if (window.getSelection) { // moz, opera, webkit - var selection = window.getSelection(); - var range = document.createRange(); - range.selectNodeContents(element); - selection.removeAllRanges(); - selection.addRange(range); - } - } - - // Go back one step in history when clicking on links with the cancel class. - $("a.cancel").click(function(event) { - event.preventDefault(); - history.back(); - }); + setLayoutMode(); - // Select the macro code when clicking on elements with the macro-code class. - $('.macro-code').click(function(event) { - $(this).selectText(); - }); + // Extend jQuery with selectText() method. + $.fn.selectText = function() { + var element = this.get(0); + if (document.body.createTextRange) { // ms + var range = document.body.createTextRange(); + range.moveToElementText(element); + range.select(); + } else if (window.getSelection) { // moz, opera, webkit + var selection = window.getSelection(); + var range = document.createRange(); + range.selectNodeContents(element); + selection.removeAllRanges(); + selection.addRange(range); + } + } - // Group related elements. - var groups = [], - element = $("form#prefs #timeZone"); - element.find("option").each(function(index, item) { - var zone = $(item), - parts = zone.html().split("/"), // E.g. Europe/Vienna - group = parts[0]; + // Go back one step in history when clicking on links with the cancel class. + $("a.cancel").click(function(event) { + event.preventDefault(); + history.back(); + }); - if ($.inArray(group, groups) < 0) { - groups.push(group); - } - }); - groups.sort(); - $.each(groups, function(index, group) { - var key = group + "/"; // E.g. Europe/ - element.find("option:contains(" + key + ")") - .wrapAll($("").attr("label", group)) - .each(function(index, item) { - $(item).html($(item).html().replace(key, "")); - }); - }); + // Select the macro code when clicking on elements with the macro-code class. + $('.macro-code').click(function(event) { + $(this).selectText(); + }); + + // Group related elements. + var groups = [], + element = $("form#prefs #timeZone"); + element.find("option").each(function(index, item) { + var zone = $(item), + parts = zone.html().split("/"), // E.g. Europe/Vienna + group = parts[0]; + + if ($.inArray(group, groups) < 0) { + groups.push(group); + } + }); + groups.sort(); + $.each(groups, function(index, group) { + var key = group + "/"; // E.g. Europe/ + element.find("option:contains(" + key + ")") + .wrapAll($("").attr("label", group)) + .each(function(index, item) { + $(item).html($(item).html().replace(key, "")); + }); + }); }); function setLayoutMode(mode) { - if (mode === false || $('.skin-control').length < 0) { - $('.skin-control').remove(); - return; - } - /*$('body').prepend($('
').attr('class', 'layout-sandbox') - .append($('
') - .append($('