// // Jala Project [http://opensvn.csie.org/traccgi/jala] // // Copyright 2004 ORF Online und Teletext GmbH // // Licensed under the Apache License, Version 2.0 (the ``License''); // 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 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an ``AS IS'' BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // // $Revision$ // $LastChangedBy$ // $LastChangedDate$ // $HeadURL$ // /** * Dependencies */ app.addRepository("modules/core/String.js"); app.addRepository(getProperty("jala.dir", "modules/jala") + "/code/XmlRpcRequest.js"); /** * A safe eval method that uses a standard Javascript scope * without any Helma specifics for evaluation. This method * does a double evaluation: first it evaluates the code * in a separate javascript scope without any Helma specifics, and only * if that doesn't throw an exception it evaluates the expression in the * application scope, so that objects constructed during evaluation * belong to the correct scope (and eg. testing with instanceof returns * the expected result). Keep in mind that due to the double * evaluation using this method is quite costly. * @param {String} code The code to evaluate * @returns The result of the evaluated code */ var safeEval = function(code) { var context = new Packages.org.mozilla.javascript.Context(); try { context.enter(); // first evaluation in separate scope context.evaluateString(safeEval.SCOPE, code, null, 0, null); return eval(code); } finally { context.exit(); } }; safeEval.SCOPE = Packages.org.mozilla.javascript.Context.getCurrentContext().initStandardObjects(); /** * Returns true if the value passed as argument is a string. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is a string, false otherwise */ var isString = function(val) { return typeof(val) == "string" || val instanceof java.lang.String || val instanceof String; }; /** * Returns true if the value passed as argument is a boolean. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is a boolean, false otherwise */ var isBoolean = function(val) { return typeof(val) == "boolean" || val instanceof Boolean; }; /** * Returns true if the value passed as argument is a number. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is a number, false otherwise */ var isNumber = function(val) { return typeof(val) == "number" || val instanceof java.lang.Integer || val instanceof Number; }; /** * Returns true if the value passed as argument is null. * @param {Object} val The value to test * @returns True if the value is null, false otherwise */ var isNull = function(val) { return val === null; }; /** * Returns true if the value passed as argument is undefined. * @param {Object} val The value to test * @returns True if the value is undefined, false otherwise */ var isUndefined = function(val) { return val === undefined; }; /** * Returns true if the value passed as argument is an array. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is an array, false otherwise */ var isArray = function(val) { return val instanceof Array; }; /** * Returns true if the value passed as argument is a date. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is a date, false otherwise */ var isDate = function(val) { return val instanceof Date || val instanceof java.util.Date; }; /** * Returns true if the value passed as argument is an object. Since * this value might be constructed using the safeEval's scope * this method tests both the application's scope and the safe one. * @param {Object} val The value to test * @returns True if the value is an object, false otherwise */ var isObject = function(val) { return val instanceof Object || val instanceof java.lang.Object; }; /** * Parses the argument string passed into an array containing * evaluated arguments. The string can contain object and array literals, * strings, numbers and dates (using standard Javascript syntax). * @param {String} str The string to parse * @returns The parsed arguments * @type Array */ var parseArguments = function(str) { var result = []; var c, literalLevel = 0; var buf = new java.lang.StringBuffer(); for (var i=0;i 0) { result.push(evalArgument(buf.toString())); } return result; }; /** * Parses a single argument string using the safeEval's method * eval(). This way users can't do any harm since all they have is * a plain Javascript environment without any Helma specifics. * @param {String} str The string to evaluate * @returns The evaluated argument */ var evalArgument = function(str) { if (str) { str = str.trim(); return safeEval("(" + str + ")"); } return null; }; /** * Returns the object passed as argument as formatted JSOn compatible * string. * @param {Object} obj The object to format as string * @returns The formatted string */ var prettyPrint = function(obj) { var pad = function(str) { return " ".repeat((lvl) * 6) + str; }; var printString = function(str) { return '"' + encode(str) + '"'; }; var printInteger = function(nr) { return nr.toString(); }; var printBoolean = function(bool) { return bool.toString(); }; var printUndefined = function() { return "undefined"; }; var printNull = function() { return "null"; }; var printDate = function(date) { return date.toString(); }; var printArray = function(arr) { var buf = new java.lang.StringBuffer(); buf.append("["); lvl += 1; for (var i=0;i 0) { buf.append(","); } buf.append("\n"); buf.append(pad(printValue(arr[i]))); } lvl -= 1; buf.append("\n"); buf.append(pad("]")); return buf.toString(); }; var printObject = function(obj) { var buf = new java.lang.StringBuffer(); buf.append("{"); lvl += 1; var first = true; for (var i in obj) { if (first) { first = !first; } else { buf.append(","); } buf.append("\n"); buf.append(pad(printString(i) + ": ")); buf.append(printValue(obj[i])); } lvl -= 1; buf.append("\n"); buf.append(pad("}")); return buf.toString(); }; var printValue = function(val) { if (isArray(val)) { return printArray(val); } else if (isDate(val)) { return printDate(val); } else if (isString(val)) { return printString(val); } else if (isNumber(val)) { return printInteger(val); } else if (isBoolean(val)) { return printBoolean(val); } else if (isNull(val)) { return printNull(); } else if (isUndefined(val)) { return printUndefined(); } else if (isObject(val)) { return printObject(val); } else if (val.toString != null) { return val.toString(); } return; }; var lvl = 0; return printValue(obj); }; /** * Returns the xml source passed as argument as readable string * with appropriate linefeeds and indents. This method uses a * regular expression instead of converting the xml source into * a DOM tree to be able to format invalid xml which might be useful * for debugging. * @param {String} xmlSource The XML source for format * @returns The formatted source */ var prettyPrintXml = function(xmlSource) { var pad = function(str) { res.write(" ".repeat((lvl) * 6) + encode(str)); }; // remove all linefeeds and carriage returns var xml = xmlSource.replace(/\r\n|\n\r|\n|\r/g, ""); var re = /<(\/?)([^>]+)[^<]+(?=<|$)/gm; var lvl = 0; var match; var tag, prevTag; res.push(); while (match = re.exec(xml)) { tag = match[2]; if (!match[1]) { // opening or contentless tag if (match.index > 0) { res.write("\n"); lvl += 1; } pad(match[0]); if (tag.indexOf("/") > -1) { lvl -= 1; } } else { // closing tag if (tag == prevTag) { lvl -= 1; res.encode(match[0]); } else { res.write("\n"); pad(match[0]); lvl -= 1; } } prevTag = tag; } return res.pop(); }; /** * Basic selection macro useable for checkboxes * and select dropdowns. This macro checks if * req.data[param.name] equals param.value, and if * true it writes the specified param.attribute in * the form 'attribute="attribute"' to response. */ var selection_macro = function(param) { if (req.data[param.name] == param.value) { res.write(" "); res.write(param.attribute); res.write('="'); res.write(param.attribute); res.write('"'); } return; };