obfuscator + js moved to messenger/js

git-svn-id: https://webim.svn.sourceforge.net/svnroot/webim/trunk@126 c66351dc-e62f-0410-b875-e3a5c0b9693f
This commit is contained in:
Evgeny Gryaznov 2008-09-29 23:35:29 +00:00
parent fa2f03d3e5
commit b2127923d0
6 changed files with 0 additions and 1999 deletions

View File

@ -1,731 +0,0 @@
/*
* JavaScript Obfucator is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* JavaScript Obfucator is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
import java.util.*;
import java.io.*;
/**
* Obfuscate the JavaScript code.
* updated by Evgeny Gryaznov, March 2006
* @author Shane Ng <gnenahs at poboxes dot com>
*/
public class JSO {
public static final String[] reserved = {
"abstract", "else", "instanceof", "switch", "boolean", "enum", "int",
"synchronized", "break", "export", "interface", "this", "byte", "extends",
"long", "throw", "case", "false", "native", "throws", "catch", "final",
"new", "transient", "char", "finally", "null", "true", "class", "float",
"package", "try", "const", "for", "private", "typeof", "continue", "function",
"protected", "var", "debugger", "goto", "public", "void", "default", "if",
"return", "volatile", "delete", "implements", "short", "while", "do", "import",
"static", "with", "double", "in", "super", "undefined", "arguments"
};
public static final String[] builtIn = {
"history", "packages", "pageXOffset", "pageYOffset", "isNaN", "array", "java",
"plugin", "clientInformation", "prototype", "layer", "layers", "crypto", "date", "secure",
"embed", "navigator", "product", "netscape", "escape", "eval", "sun",
"taint", "fileUpload", "toString", "unescape", "untaint", "frameRate",
"valueOf", "getClass", "encodeURIComponent", "overrideMimeType",
// Types
"Math", "Date", "Array", "RegExp", "Image", "Function", "ActiveXObject",
"Number", "String", "Object", "JavaClass", "JavaObject", "JavaPackage", "JavaArray",
// DOM
"anchor", "image", "area", "checkbox", "password", "radio", "textarea",
"contentDocument", "contentWindow", "document",
"window", "element", "location", "option", "style",
// Properties
"accessKey", "action", "activeElement", "align", "aLink", "aLinkColor", "alt",
"altHTML", "altKey", "appCodeName", "appMinorVersion", "appName", "appVersion",
"autocomplete", "availHeight", "availWidth", "background", "backgroundAttachment",
"backgroundColor", "backgroundImage", "backgroundPosition", "backgroundPositionX",
"backgroundPositionY", "backgroundRepeat", "balance", "behavior", "bgColor",
"bgProperties", "border", "borderBottom", "borderBottomColor", "borderBottomStyle",
"borderBottomWidth", "borderCollapse", "borderColor", "borderColorDark",
"borderColorLight", "borderLeft", "borderLeftColor", "borderLeftStyle",
"borderLeftWidth", "borderRight", "borderRightColor", "borderRightStyle",
"borderRightWidth", "borderStyle", "borderTop", "borderTopColor", "borderTopStyle",
"borderTopWidth", "borderWidth", "bottom", "bottomMargin", "boundingHeight", "boundingLeft",
"boundingTop", "boundingWidth", "browserLanguage", "bufferDepth", "button",
"cancelBubble", "canHaveChildren", "caption", "cellIndex", "cellPadding", "cellSpacing",
"checked", "classid", "className", "clear", "clientHeight", "clientLeft", "clientTop",
"clientWidth", "clientX", "clientY", "clip", "clipBottom", "clipLeft", "clipRight",
"clipTop", "closed", "code", "codeBase", "codeType", "color", "colorDepth", "cols",
"colSpan", "compact", "complete", "content", "cookie", "cookieEnabled", "coords",
"cpuClass", "cssText", "ctrlKey", "cursor", "data", "dataFld", "dataFormatAs",
"dataPageSize", "dataSrc", "defaultCharset", "defaultChecked", "defaultSelected",
"defaultStatus", "defaultValue", "defer", "designMode", "dialogArguments", "dialogHeight",
"dialogLeft", "dialogTop", "dialogWidth", "dir", "direction", "disabled", "display",
"documentElement", "domain", "dropEffect", "dynsrc", "effectAllowed", "encoding", "event",
"expando", "face", "fgColor", "fileCreatedDate", "fileModifiedDate", "fileSize",
"fileUpdatedDate", "filter", "firstChild", "font", "fontFamily", "fontSize",
"fontSmoothingEnabled", "fontStyle", "fontVariant", "fontWeight", "form", "frame",
"frameBorder", "frameSpacing", "fromElement", "hash", "height", "hidden", "host",
"hostname", "href", "hspace", "htmlFor", "htmlText", "httpEquiv", "id", "imeMode",
"indeterminate", "index", "innerHTML", "innerText", "isMap", "isTextEdit", "keyCode",
"lang", "language", "lastChild", "lastModified", "layoutGrid", "layoutGridChar",
"layoutGridCharSpacing", "layoutGridLine", "layoutGridMode", "layoutGridType", "left",
"leftMargin", "length", "letterSpacing", "lineBreak", "lineHeight", "link", "linkColor",
"listStyle", "listStyleImage", "listStylePosition", "listStyleType", "loop", "lowsrc",
"margin", "marginBottom", "marginHeight", "marginLeft", "marginRight", "marginTop",
"marginWidth", "maxLength", "media", "menuArguments", "method", "Methods", "multiple",
"name", "nameProp", "nextSibling", "nodeName", "nodeType", "nodeValue", "noHref",
"noResize", "noShade", "noWrap", "object", "offscreenBuffering", "offsetHeight",
"offsetLeft", "offsetParent", "offsetTop", "offsetWidth", "offsetX", "offsetY",
"onLine", "opener", "outerHTML", "outerText", "overflow", "overflowX", "overflowY",
"owningElement", "padding", "paddingBottom", "paddingLeft", "paddingRight", "paddingTop",
"pageBreakAfter", "pageBreakBefore", "palette", "parent", "parentElement", "parentNode",
"parentStyleSheet", "parentTextEdit", "parentWindow", "pathname", "pixelBottom",
"pixelHeight", "pixelLeft", "pixelRight", "pixelTop", "pixelWidth", "platform",
"pluginspage", "port", "posBottom", "posHeight", "position", "posLeft", "posRight",
"posTop", "posWidth", "previousSibling", "propertyName", "protocol", "qualifier",
"readOnly", "reason", "recordNumber", "recordset", "referrer", "rel",
"repeat", "returnValue", "rev", "right", "rightMargin", "rowIndex", "rowSpan",
"rubyAlign", "rubyOverhang", "rubyPosition", "scopeName", "screenLeft",
"screenTop", "screenX", "screenY", "scrollAmount", "scrollDelay",
"scrollHeight", "scrolling", "scrollLeft", "scrollTop", "scrollWidth", "search",
"sectionRowIndex", "selected", "selectedIndex", "selectorText", "self", "shape",
"shiftKey", "size", "sourceIndex", "span", "specified", "src", "srcElement", "srcFilter",
"srcUrn", "start", "status", "styleFloat", "systemLanguage", "tabIndex", "tableLayout",
"tagName", "tagUrn", "target", "text", "textAlign", "textAutospace", "textDecoration",
"textDecorationLineThrough", "textDecorationNone", "textDecorationOverline",
"textDecorationUnderline", "textIndent", "textJustify", "textTransform", "tFoot", "tHead",
"title", "toElement", "top", "topMargin", "trueSpeed", "type", "unicodeBidi", "uniqueID",
"units", "updateInterval", "URL", "urn", "useMap", "userAgent", "userLanguage", "vAlign",
"value", "vcard_name", "verticalAlign", "visibility", "vLink", "vlinkColor", "volume",
"vspace", "whiteSpace", "width", "wordBreak", "wordSpacing", "wrap", "x",
"XMLDocument", "y", "zIndex",
// non-IE
"outerHeight", "innerHeight", "outerWidth", "innerWidth",
"which",
// collections
"all", "anchors", "applets", "areas", "attributes", "behaviorUrns",
"bookmarks", "boundElements", "cells", "childNodes", "children",
"controlRange", "elements", "embeds", "filters", "forms", "frames",
"images", "imports", "links", "mimeTypes", "options", "plugins", "rows",
"rules", "scripts", "styleSheets", "tBodies", "TextRectangle",
// Methods
"add", "addBehavior", "AddFavorite", "addImport", "addRule", "alert",
"appendChild", "applyElement", "assign", "attachEvent", "back", "blur",
"clearAttributes", "clearData", "clearInterval", "clearRequest",
"clearTimeout", "click", "cloneNode", "close", "collapse", "compareEndPoints",
"componentFromPoint", "confirm", "contains", "createCaption", "createControlRange",
"createElement", "createRange", "createStyleSheet", "createTextNode", "createTextRange",
"createTFoot", "createTHead", "deleteCaption", "deleteCell", "deleteRow", "deleteTFoot",
"deleteTHead", "detachEvent", "doScroll", "duplicate", "elementFromPoint",
"empty", "execCommand", "execScript", "expand", "findText", "firstPage", "focus",
"forward", "getAdjacentText", "getAttribute", "getBookmark", "getBoundingClientRect",
"getClientRects", "getData", "getElementById", "getElementsByName", "getElementsByTagName",
"getExpression", "go", "hasChildNodes", "inRange",
"insertAdjacentElement", "insertAdjacentHTML", "insertAdjacentText", "insertBefore",
"insertCell", "insertRow", "isEqual", "IsSubscribed", "item", "javaEnabled", "lastPage",
"mergeAttributes", "move", "moveBy", "moveEnd", "moveRow", "moveStart", "moveTo",
"moveToBookmark", "moveToElementText", "moveToPoint", "namedRecordset", "navigate",
"NavigateAndFind", "nextPage", "open", "pasteHTML",
"previousPage", "print", "prompt", "queryCommandEnabled", "queryCommandIndeterm",
"queryCommandState", "queryCommandSupported", "queryCommandValue", "recalc", "refresh",
"releaseCapture", "reload", "remove", "removeAttribute", "removeBehavior",
"removeChild", "removeExpression", "removeNode", "removeRule", "replace",
"replaceAdjacentText", "replaceChild", "replaceNode", "reset", "resizeBy",
"resizeTo", "scroll", "scrollBy", "scrollIntoView", "scrollTo", "select",
"setAttribute", "setCapture", "setData", "setEndPoint", "setExpression", "setInterval",
"setTimeout", "ShowBrowserUI", "showHelp", "showModalDialog", "showModelessDialog",
"splitText", "stop", "submit", "swapNode", "tags", "taintEnabled",
"urns", "write", "writeln",
// builtIn
"toUpperCase", "toLowerCase", "match", "substring", "split", "indexOf",
"parseFloat", "parseInt",
"getYear", "getTime", "getMonth", "getFullYear", "getDay", "getDate",
"exec", "join", "call", "floor",
// events
"onabort", "onafterprint", "onafterupdate", "onbeforecopy", "onbeforecut",
"onbeforeeditfocus", "onbeforepaste", "onbeforeprint", "onbeforeunload",
"onbeforeupdate", "onblur", "onbounce", "oncellchange", "onchange", "onclick",
"oncontextmenu", "oncopy", "oncut", "ondataavailable", "ondatasetchanged", "ondatasetcomplete",
"ondblclick", "ondrag", "ondragend", "ondragenter", "ondragleave", "ondragover",
"ondragstart", "ondrop", "onerror", "onerrorupdate", "onfilterchange", "onfinish",
"onfocus", "onhelp", "onkeydown", "onkeypress", "onkeyup", "onload",
"onlosecapture", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup",
"onpaste", "onpropertychange", "onreset", "onresize", "onrowenter",
"onrowexit", "onrowsdelete", "onrowsinserted", "onscroll", "onselect", "onselectstart",
"onstart", "onstop", "onsubmit", "onunload",
// Ajax
"XMLHttpRequest", "readyState", "onreadystatechange", "responseXML",
"responseText", "responseBody", "statusText",
"send", "abort", "setRequestHeader", "getResponseHeader", "getAllResponseHeaders",
};
public static final char[] DELIMITER = {'?', ':', '!', '=', '(', ')', '[', ']',
'{', '}', '\r', '\n', '\t', ' ', '\"', '\'', '<', '>', ',', '.', '/',
'\\', '+', '-', '*', '&', '|', '^', '%', ';'
};
public static final String[] alpha = {
"m", "n", "q", "r", "s", "t", "u",
"h", "i", "j", "k", "l", "o", "p",
"d", "e", "f", "g", "a", "b", "c",
"v", "w", "x", "y", "z", "$", "_"
};
public static final HashSet exclusionTokenSet = new HashSet();
public static final HashSet forceReplace = new HashSet();
public static final HashSet forceReplaceInStrings = new HashSet();
public static final HashMap forceTextualReplace = new HashMap();
public static int ref = alpha.length;
public static HashMap map = new HashMap();
public static final String ARG_EXCLUDE_TOKENS = "e=";
public static final String ARG_DESTINATION_DIR = "d=";
public static final String ARG_OBFUSCATE_STRING = "o=";
public static final String ARG_DEBUG = "debug";
public static final String ARG_DEBUGEXCLUDE = "debugnames";
public static final String ARG_REPLACE = "textrepl=";
private double[] stringObfuscationParameter = {0, 0, 0.5};
private String[] file = null;
public static boolean isDebug = false;
public static boolean isExcludeAll = false;
private String destinationDir = null;
private JSOState state = new JSOState();
private String delimiter = new String(DELIMITER);
private HashSet encounteredInStrings = new HashSet();
private HashMap encounteredInStringsFiles = new HashMap();
public static void main(String[] args) throws Exception {
ArrayList fileList = new ArrayList(args.length);
String[] file = null;
String destinationDir = null;
double[] stringObfuscationParameter = {1, .59, 0.5};
if (args.length == 0) {
printUsage();
return;
} else if (args.length > 1) {
for (int i = 0; i < args.length; i++) {
if( args[i].equals(ARG_DEBUG)) {
isDebug = true;
} else if( args[i].equals(ARG_DEBUGEXCLUDE) ) {
isExcludeAll = true;
} else if (args[i].startsWith(ARG_EXCLUDE_TOKENS)) {
readexclusionTokenSet(args[i].substring(ARG_EXCLUDE_TOKENS.length()));
} else if (args[i].startsWith(ARG_DESTINATION_DIR) && destinationDir == null) {
File dir = new File(args[i].substring(ARG_DESTINATION_DIR.length()));
if (!dir.exists() && !dir.mkdirs()) {
System.err.println("Cannot create the output directory \"" + dir.getName() + "\"");
return;
} else if (dir.exists() && dir.isFile()) {
System.err.println("The output parameter \"" + args[i] + "\" is not a directory");
return;
}
destinationDir = dir.getAbsolutePath();
} else if (args[i].startsWith(ARG_OBFUSCATE_STRING)) {
String[] param = args[i].substring(ARG_OBFUSCATE_STRING.length()).split(",", 3);
if (param.length >= 2) {
try {
stringObfuscationParameter[0] = Double.parseDouble(param[0]);
stringObfuscationParameter[1] = Double.parseDouble(param[1]);
if (param.length == 3) {
stringObfuscationParameter[2] = Double.parseDouble(param[2]);
}
} catch (NumberFormatException e) {
System.err.println("The obfuscation parameters are not numbers.");
return;
}
} else {
System.err.println("At least 2 obfuscation parameters are required, e.g. o=0.4,0.7.");
return;
}
} else if( args[i].startsWith(ARG_REPLACE) ) {
String[] param = args[i].substring(ARG_REPLACE.length()).split(",", 3);
if (param.length == 2) {
forceTextualReplace.put(param[0], param[1]);
} else {
System.err.println("2 parameters are required, e.g. textrepl=a,b");
return;
}
} else {
fileList.add(args[i]);
}
}
file = new String[fileList.size()];
fileList.toArray(file);
} else {
file = new String[]{args[0]};
}
addexclusionTokenSet(reserved);
addexclusionTokenSet(builtIn);
JSO obfuscator = new JSO(file, destinationDir, stringObfuscationParameter);
obfuscator.run();
}
private static void printUsage() {
System.err.println("Usage: java JSO <list of javascript file> [options]");
System.err.println("");
System.err.println("where the options are:");
System.err.println("\te=<exception list file>");
System.err.println("\t\t- filename of the exception list");
System.err.println("\t\t- exception tokens are delimited by tab, space, dot, comma, ");
System.err.println("\t\t single quote and double quote");
System.err.println("\td=<destination directory>");
System.err.println("\t\t- the output directory");
System.err.println("\t\t- print to the STDOUT if not specified");
System.err.println("\to=<obfuscation parameters of string literals>");
System.err.println("\t\t- If it is specified, the characters in string literals will be ");
System.err.println("\t\t encoded to either \\uXXXX (hexidemcial) or \\XXX (octal) format");
System.err.println("\t\t- The parameters are a 2 or 3 floating point values delimited ");
System.err.println(" by commas. e.g. 0.5,0.3 or 0.5,0.3,0.9");
System.err.println("\t\t- The values are ");
System.err.println("\t\t * probability to encode a string");
System.err.println("\t\t * probability to encode a character in a candidate string");
System.err.println("\t\t * probability to encode a character into \\uXXXX format");
System.err.println("\t\t- The last parameter is set to 0.5 if not specified");
System.err.println("");
System.err.println("Press Enter to read the examples...");
try{
System.in.read();
} catch (Exception e){}
System.err.println("Examples:");
System.err.println("");
System.err.println(" Obfuscate all scripts in the current directory and output to ./out directory:");
System.err.println("\tjava JSO *.js d=out");
System.err.println("");
System.err.println(" Pipe the STDOUT output to x.o.js:");
System.err.println("\tjava JSO x.js > x.o.js ");
System.err.println("");
System.err.println(" Merge a.js and b.js and pipe the merged output to script.js. Tokens in ");
System.err.println(" exception list, noReplace.txt will not be replaced:");
System.err.println("\tjava JSO a.js b.js e=noReplace.txt > script.js");
System.err.println("");
System.err.println(" Obfuscate the 100% of string literals, 68% of the characters will be encoded. ");
System.err.println(" 50% of the characters will be encoded as \\uXXXX format (default):");
System.err.println("\tjava JSO x.js o=1,0.68");
}
public JSO(String[] file, String destinationDir, double[] stringObfuscationParameter){
this.file = file;
this.destinationDir = destinationDir;
if (stringObfuscationParameter != null && stringObfuscationParameter.length >= 2) {
this.stringObfuscationParameter = stringObfuscationParameter;
}
}
public void run() throws IOException {
for (int i = 0; i < file.length; i++) {
BufferedReader in = new BufferedReader(new FileReader(file[i]));
PrintWriter out = null;
File f = new File(file[i]);
if (destinationDir == null) {
out = new PrintWriter(System.out, true);
} else {
out = new PrintWriter(new FileWriter(new File(destinationDir + File.separator + f.getName())));
}
this.obfuscate(in, out, f.getName());
System.out.println("obfuscated " + f.getName());
in.close();
out.flush();
out.close();
}
System.err.println( "Obfuscated" );
System.err.println(map.toString().replace(',', '\n'));
encounteredInStrings.retainAll(map.keySet());
System.err.println( "Not Obfuscated in strings:" );
for( Iterator it = encounteredInStrings.iterator(); it.hasNext(); ) {
String s = (String)it.next();
System.err.println( "\t"+s+": " + (String)encounteredInStringsFiles.get(s) );
}
}
private void obfuscate(BufferedReader in, PrintWriter out, String fname) throws IOException {
state.reset();
int line_counter = 0;
for (String line = in.readLine(); line != null; line = in.readLine()) {
line_counter++;
if( !isDebug )
line = line.trim();
if (line.length() == 0) {
if( isDebug )
out.println();
continue;
}
if( line.startsWith( "//-" ) ) {
String[] toAdd = line.substring(3).split(",");
for( int i = 0; i < toAdd.length; i++ )
exclusionTokenSet.add(toAdd[i].trim());
continue;
} else if( line.startsWith("//+")) {
String[] toAdd = line.substring(3).split(",");
for( int i = 0; i < toAdd.length; i++ )
forceReplace.add(toAdd[i].trim());
continue;
} else if( line.startsWith("//'")) {
String[] toAdd = line.substring(3).split(",");
for( int i = 0; i < toAdd.length; i++ ) {
forceReplace.add(toAdd[i].trim());
forceReplaceInStrings.add(toAdd[i].trim());
}
}
for( Iterator it = forceTextualReplace.keySet().iterator(); it.hasNext(); ) {
String key = (String)it.next();
line = line.replaceAll(key, (String)forceTextualReplace.get(key));
}
StringTokenizer st = new StringTokenizer(line, delimiter, true);
if (st.hasMoreTokens()) {
state.setToken(st.nextToken());
}
for (; state.token != null; state.skipToken()) {
if (st.hasMoreTokens()) {
state.setNextToken(st.nextToken());
} else {
state.noToken();
}
boolean doubleSlashed = state.flipFlags();
if (doubleSlashed) {
break;
}
handleToken(out, fname, line_counter);
}
if( isDebug )
out.println();
else if (!state.delimiter && !state.commented )
out.print(" ");
}
}
private void handleToken(PrintWriter out, String fname, int line ) {
if (state.token.length() > 0) {
if (state.delimiter) {
if (state.inString() && !state.backslashed && state.c != '\\' &&
state.c != '\"' && state.c != '\'') {
state.token = obfuscateQuotedString(state.token);
}
} else {
if (state.inString()) {
if( forceReplaceInStrings.contains(state.token) && canReplace(state.token) ) {
state.token = generateToken(state.token);
} else if( Character.isJavaIdentifierStart(state.token.charAt(0))) {
encounteredInStrings.add(state.token);
String s = (String)encounteredInStringsFiles.get(state.token);
s = ( s == null ) ? "" : s + ", ";
s += fname +"[" + line + "]";
encounteredInStringsFiles.put(state.token, s);
}
if (!state.backslashed) {
state.token = obfuscateQuotedString(state.token);
}
} else if( !state.commented ) {
if(canReplace(state.token)){
state.token = generateToken(state.token);
} else if( state.token.length() > 0 && Character.isDigit( state.token.charAt(0) ) ) {
try {
int i = Integer.parseInt( state.token );
double res = Math.random();
int e = (int)(i * res);
if( i > 3 ) {
if( res < 0.2 && i >= 16 )
state.token = "0x"+Integer.toHexString(i);
else if( res < 0.6 && i >= 8 )
state.token = "0" + Integer.toOctalString(i);
else
state.token = "(" + e + "+" + (i-e) + ")";
}
} catch( NumberFormatException ex ) {
}
}
}
}
}
if (!state.commented && (state.printToken || state.inString())) {
out.print(state.token);
}
if (state.c == '}' && !state.commented && !isDebug) {
out.print(" ");
}
}
private static void readexclusionTokenSet(String file) throws IOException {
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader(file));
for (String line = in.readLine(); line != null; line = in.readLine()) {
StringTokenizer st = new StringTokenizer(line, "\t ,.\"\'");
for (; st.hasMoreTokens();) {
exclusionTokenSet.add(st.nextToken());
}
}
} finally {
if (in != null) {
in.close();
}
}
}
private String obfuscateQuotedString(String token) {
if (Math.random() < stringObfuscationParameter[0]) {
StringBuffer buffer = new StringBuffer(token.length());
int n = token.length();
int pos = 0;
for (int i = 0; i < n; i++) {
if (Math.random() < stringObfuscationParameter[1]) {
buffer.append(token.substring(pos, i));
encode(token.charAt(i), buffer);
pos = i + 1;
}
}
if (pos < n) {
buffer.append(token.substring(pos));
}
return buffer.toString();
} else {
return token;
}
}
private void encode(char c, StringBuffer buffer) {
if (Math.random() < stringObfuscationParameter[2] || c > 0777) {
buffer.append("\\u");
encode(c, 16, 4, buffer);
} else {
buffer.append("\\");
encode(c, 8, 3, buffer);
}
}
private void encode(char c, int radix, int length, StringBuffer buffer) {
String value = Integer.toString(c, radix);
int n = length - value.length();
if (n > 0) {
for (int i = 0; i < n; i++) {
buffer.append('0');
}
buffer.append(value);
} else {
buffer.append(value.substring(-n));
}
}
private static String generateToken(String token) {
if (map.containsKey(token)) {
return (String) map.get(token);
} else {
String result = null;
do {
StringBuffer buffer = new StringBuffer(token.length());
for (int i = ref; i > 0; i = i / alpha.length) {
buffer.append(alpha[i % alpha.length]);
}
ref++;
result = buffer.toString();
} while (exclusionTokenSet.contains(result) || map.containsValue(result));
map.put(token, result);
return result;
}
}
private static boolean canReplace(String token) {
if (token.length() <= 1 || token.charAt(0) == '$' )
return false;
if (map.containsKey(token))
return true;
if( isExcludeAll )
return false;
if( forceReplace.contains(token) )
return true;
if (exclusionTokenSet.contains(token) )
return false;
if (Character.isDigit(token.charAt(0)))
return false;
if( token.charAt(0) == '_' )
return true;
return true;
}
private static void addexclusionTokenSet(String[] array) {
if (array != null) {
for (int i = 0; i < array.length; i++) {
if( exclusionTokenSet.contains(array[i]) )
System.err.println( "warn, already excluded: " + array[i] );
exclusionTokenSet.add(array[i]);
}
}
}
public static boolean isDelimiter(String token) {
if (token != null && token.length() > 0) {
for (int i = 0; i < DELIMITER.length; i++) {
if (token.charAt(0) == DELIMITER[i]) {
return true;
}
}
}
return false;
}
}
class JSOState {
boolean dotted = false;
boolean doubleQuoted = false;
boolean singleQuoted = false;
boolean backslashed = false;
boolean commented = false;
boolean printToken = true;
boolean delimiter = false;
String token;
String lastToken;
String nextToken;
char c0 = 0;
char c = 0;
char c2 = 0;
void reset() {
dotted = false;
doubleQuoted = false;
singleQuoted = false;
backslashed = false;
commented = false;
printToken = true;
delimiter = false;
token = null;
lastToken = null;
nextToken = null;
c0 = 0;
c = 0;
c2 = 0;
}
boolean printable() {
return !commented && (printToken || inString());
}
boolean inString() {
return doubleQuoted || singleQuoted;
}
boolean delimiterSurrounded() {
return !JSO.isDelimiter(nextToken) && !JSO.isDelimiter(lastToken);
}
boolean isWhitespace(){
return Character.isWhitespace(c);
}
String setToken(String value) {
String oldToken = lastToken;
lastToken = token;
token = value;
nextToken = null;
if (value != null) {
c0 = c;
c = token == null ? 0 : token.charAt(0);
c2 = 0;
backslashed = c0 == '\\';
dotted = c0 == '.';
delimiter = JSO.isDelimiter(token);
printToken = true;
}
return oldToken;
}
String tokenBackslashed() {
String result = null;
int index = 0;
if (c == 'u') {
index = 4;
} else if (Character.isDigit(c)) {
index = 3;
} else {
throw new IllegalStateException("Token not backslashed or invalid JavaScript syntax.");
}
result = token.substring(0, index);
token = token.substring(index);
return result;
}
void setNextToken(String value) {
nextToken = value;
c2 = value.charAt(0);
}
void skipToken() {
this.setToken(nextToken);
}
void noToken() {
nextToken = null;
c2 = 0;
}
boolean flipFlags() {
if (isWhitespace()) {
printToken = delimiterSurrounded() || JSO.isDebug;
} else if (c == '/') {
if (!commented && c2 == '/') {
return true;
} else if (!commented && c2 == '*' &&
!inString()) {
commented = true;
} else if (commented && c0 == '*') {
commented = false;
printToken = false;
}
} else if (c == '\"' && !singleQuoted && !backslashed && !commented) {
doubleQuoted = !doubleQuoted;
} else if (c == '\'' && !doubleQuoted && !backslashed && !commented) {
singleQuoted = !singleQuoted;
}
return false;
}
}

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project [<!ENTITY buildfile SYSTEM "file:./build-user.xml">]>
<project basedir="." default="update" name="Obfuscator">
<property name="obfuscator.location" value="." />
<property name="webim.location" value="../webim" />
<target name="update" depends="build">
<java classname="JSO" fork="true" error="${obfuscator.location}/bin/obfuscation.log">
<arg value="${obfuscator.location}/src/common.js" />
<arg value="${obfuscator.location}/src/page_chat2.js" />
<arg value="${obfuscator.location}/src/page_pendingclients2.js" />
<arg value="${obfuscator.location}/src/brws.js" />
<arg value="d=${webim.location}/js/" />
<!-- <arg value="debug"/> -->
<!-- <arg value="debugnames"/> -->
<!-- <arg value="o=0,0"/> -->
<classpath>
<pathelement location="${obfuscator.location}/bin/" />
</classpath>
</java>
</target>
<target name="build" depends="init">
<javac destdir="${obfuscator.location}/bin" fork="false">
<src path="${obfuscator.location}" />
</javac>
</target>
<target name="init">
<mkdir dir="${obfuscator.location}/bin"/>
</target>
</project>

View File

@ -1,30 +0,0 @@
var myAgent = "";
var myVer = 0;
var myRealAgent = "";
function detectAgent() {
var AGENTS = ["opera","msie","safari","firefox","netscape","mozilla"];
var agent = navigator.userAgent.toLowerCase();
for (var i = 0; i < AGENTS.length; i++) {
var agentStr = AGENTS[i];
if (agent.indexOf(agentStr) != -1) {
myAgent = agentStr;
if (!window.RegExp)
break;
var versionExpr = new RegExp(agentStr + "[ \/]?([0-9]+(\.[0-9]+)?)");
if (versionExpr.exec(agent) != null) {
myVer = parseFloat(RegExp.$1);
}
break;
}
}
myRealAgent = myAgent;
if( navigator.product == "Gecko")
myAgent = "moz";
}
detectAgent();
function getEl(name) {
return document.getElementById(name);
}

View File

@ -1,526 +0,0 @@
/*
* Web Messenger common script
* http://sourceforge.net/projects/webim
*
* Based on Prototype JavaScript framework, version 1.3.1
* http://prototype.conio.net/ (c) 2005 Sam Stephenson <sam@conio.net>
*/
//- getEl, myAgent, myRealAgent
//- localized
//- onComplete, obj, params, $apply$
//- threadParams, servl, frequency, user, threadid, token
//- updaterOptions, url, company, agentservl, noclients, wroot
var Class = {
create: function() {
return function() {
this./**/initialize./**/apply(this, arguments);
};
},
inherit: function(child,parent,body) {
Object./**/extend(Object.extend(child.prototype, parent.prototype), body );
}
};
Object.extend = function(destination, source) {
for (property in source) {
destination[property] = source[property];
}
return destination;
};
Object.prototype.extend = function(_object) {
return Object.extend.apply(this, [this, _object]);
};
Function.prototype./**/bind = function(_object) {
var __method = this;
return function() {
return __method.apply(_object, arguments);
}
};
Function.prototype./**/bindAsEventListener = function(_object) {
var __method = this;
return function(event) {
__method.call(_object, event || window.event);
}
};
Number.prototype./**/toColorPart = function() {
var digits = this.toString(16);
if (this < 16) return '0' + digits;
return digits;
};
var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
};
/*--------------------------------------------------------------------------*/
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this./**/currentlyExecuting = false;
this./**/registerCallback();
},
registerCallback: function() {
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.callback();
} finally {
this.currentlyExecuting = false;
}
}
}
};
/*--------------------------------------------------------------------------*/
function findObj( id )
{
var x;
if( !( x = document[ id ] ) && document.all ) x = document.all[ id ];
if( !x && document.getElementById ) x = document.getElementById( id );
if( !x && !document.all && document.getElementsByName )
{
x = document.getElementsByName( id );
if( x.length == 0 ) return null;
if( x.length == 1 ) return x[ 0 ];
}
return x;
}
if (!Array.prototype./**/push) {
Array.prototype.push = function() {
var startLength = this.length;
for (var i = 0; i < arguments.length; i++)
this[startLength + i] = arguments[i];
return this.length;
};
}
function $() {
var elems = new Array();
for (var i = 0; i < arguments.length; i++) {
var elem = arguments[i];
if (typeof elem == 'string')
elem = findObj(elem);
if (arguments.length == 1)
return elem;
elems.push(elem);
}
return elems;
}
if (!Function.prototype.apply) {
Function.prototype.apply = function(obj, params) {
var parameterStrings = new Array();
if (!obj) obj = window;
if (!params) params = new Array();
for (var i = 0; i < params.length; i++)
parameterStrings[i] = 'params[' + i + ']';
obj.$apply$ = this;
var result = eval('obj.$apply$(' +
parameterStrings.join(', ') + ')');
obj.$apply$ = null;
return result;
};
}
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
},
getXml: function(_response) {
if( _response &&
_response.status >= 200 &&
_response.status < 300 ) {
var xmlDoc = _response.responseXML;
if( xmlDoc && xmlDoc.documentElement )
return xmlDoc.documentElement;
}
return null;
},
getError: function(_response) {
return _response.statusText || "connection error N" + _response.status;
},
emptyFunction: function() {}
};
Ajax./**/Base = function() {};
Ajax.Base.prototype = {
setOptions: function(_options) {
this._options = {
_method: 'post',
asynchronous: true,
parameters: ''
}.extend(_options || {});
},
responseIsSuccess: function() {
return this./**/transport.status == undefined
|| this.transport.status == 0
|| (this.transport.status >= 200 && this.transport.status < 300);
},
responseIsFailure: function() {
return !this.responseIsSuccess();
}
};
Ajax./**/Request = Class.create();
Ajax.Request./**/Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Class.inherit( Ajax.Request, Ajax.Base, {
initialize: function(url, _options) {
this.transport = Ajax.getTransport();
this.setOptions(_options);
this.request(url);
},
request: function(url) {
var parameters = this._options.parameters || '';
if (parameters.length > 0) parameters += '&_=';
try {
if (this._options._method == 'get' && parameters.length > 0)
url += '?' + parameters;
this.transport.open(this._options._method, url, this._options.asynchronous);
if (this._options.asynchronous) {
this.transport.onreadystatechange = this.onStateChange.bind(this);
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
}
this.setRequestHeaders();
var pbody = this._options.postBody ? this._options.postBody : parameters;
this.transport.send(this._options._method == 'post' ? pbody : null);
} catch (e) {
this.dispatchException(e);
}
},
setRequestHeaders: function() {
var requestHeaders =
['X-Requested-With', 'XMLHttpRequest'];
if (this._options._method == 'post') {
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType)
requestHeaders.push('Connection', 'close');
}
if (this._options.requestHeaders)
requestHeaders.push.apply(requestHeaders, this._options.requestHeaders);
for (var i = 0; i < requestHeaders.length; i += 2)
this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
onStateChange: function() {
var readystate = this.transport.readyState;
if (readystate != 1)
this.respondToReadyState(this.transport.readyState);
},
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
},
evalResponse: function() {
try {
return eval(this.transport.responseText);
} catch (e) {
this.dispatchException(e);
}
},
respondToReadyState: function(readystate) {
var event = Ajax.Request.Events[readystate];
if (event == 'Complete') {
try {
(this._options['on' + this.transport.status]
|| this._options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
|| Ajax.emptyFunction)(this.transport);
} catch (e) {
this.dispatchException(e);
}
if ((this.header('Content-type') || '').match("text\\/javascript"))
this.evalResponse();
}
try {
(this._options['on' + event] || Ajax.emptyFunction)(this.transport);
} catch (e) {
this.dispatchException(e);
}
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
this.transport.onreadystatechange = Ajax.emptyFunction;
},
dispatchException: function(exception) {
(this._options.onException || Ajax.emptyFunction)(this, exception);
}
});
var EventHelper = {
register : function(obj, ev,func){
var oldev = obj[ev];
if (typeof oldev != 'function') {
obj[ev] = func;
} else {
obj[ev] = function() {
oldev();
func();
}
}
}
};
/*
Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
of Simon Willison (see comments by Simon below).
http://ripcord.co.nz/behaviour/
*/
var Behaviour = {
list : new Array,
register : function(sheet){
Behaviour.list.push(sheet);
},
init : function(){
EventHelper.register(window, 'onload', function(){
Behaviour.apply();
});
},
apply : function(){
for (h=0;sheet=Behaviour.list[h];h++){
for (selector in sheet) {
list = document.getElementsBySelector(selector);
if (!list)
continue;
for( i = 0; element = list[i]; i++ ) {
sheet[selector]( element );
}
}
}
}
};
Behaviour.init();
function getAllChildren(e) {
// Returns all children of element. Workaround required for IE5/Windows. Ugh.
return e.all ? e.all : e.getElementsByTagName('*');
}
document.getElementsBySelector = function(selector) {
// Attempt to fail gracefully in lesser browsers
if (!document.getElementsByTagName) {
return new Array();
}
// Split selector in to tokens
var tokens = selector.split(' ');
var currentContext = new Array(document);
for (var i = 0; i < tokens.length; i++) {
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
if (token.indexOf('#') > -1) {
// Token is an ID selector
var bits = token.split('#');
var tag_name = bits[0];
var id = bits[1];
var element = document.getElementById(id);
if (element == null || tag_name && element.nodeName.toLowerCase() != tag_name ) {
// tag with that ID not found, return false
return new Array();
}
// Set currentContext to contain just this element
currentContext = new Array(element);
continue; // Skip to next token
}
if (token.indexOf('.') > -1) {
// Token contains a class selector
var bits = token.split('.');
var tag_name = bits[0];
var class_name = bits[1];
if (!tag_name) {
tag_name = '*';
}
// Get elements matching tag, filter them for class selector
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements;
if (tag_name == '*') {
elements = getAllChildren(currentContext[h]);
} else {
elements = currentContext[h].getElementsByTagName(tag_name);
}
if( elements == null )
continue;
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = new Array;
var currentContextIndex = 0;
for (var k = 0; k < found.length; k++) {
if (found[k].className && found[k].className.match(new RegExp("\\b"+class_name+"\\b"))) {
currentContext[currentContextIndex++] = found[k];
}
}
continue; // Skip to next token
}
// [evgeny] code for attribute selection is removed...
if (!currentContext[0]){
return;
}
// If we get here, token is JUST an element (not a class or ID selector)
tag_name = token;
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements = currentContext[h].getElementsByTagName(tag_name);
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = found;
}
return currentContext;
};
var NodeUtils = {
getNodeValue: function(parent,name) {
var nodes = parent.getElementsByTagName( name );
if( nodes.length == 0 )
return "";
nodes = nodes[0].childNodes;
var reslt = "";
for( i = 0; i < nodes.length; i++ )
reslt += nodes[i].nodeValue;
return reslt;
},
getNodeText: function(_node) {
var _nodes = _node.childNodes;
var _text = "";
for( i = 0; i < _nodes.length; i++ )
_text += _nodes[i].nodeValue;
return _text;
},
getAttrValue: function(parent,name) {
for( k=0; k < parent.attributes.length; k++ )
if( parent.attributes[k].nodeName == name )
return parent.attributes[k].nodeValue;
return null;
}
};
var CommonUtils = {
getRow: function(_id,_table) {
var _row = _table.rows[_id];
if( _row != null )
return _row;
if( _table.rows['head'] != null )
return null;
for( k=0; k < _table.rows.length; k++ ) {
if( _table.rows[k].id == _id )
return _table.rows[k];
}
return null;
},
getCell: function(_id,_row,_table) {
var _cell = _row.cells[_id];
if( _cell != null )
return _cell;
if( _table.rows['head'] != null )
return null;
for( k=0; k < _row.cells.length; k++ ) {
if( _row.cells[k].id == _id )
return _row.cells[k];
}
return null;
},
insertCell: function(_row,_id,_className,_align,_height, _inner) {
var cell = _row.insertCell(-1);
cell.id = _id;
if(_align)
cell.align = _align;
cell.className = _className;
if(_height)
cell.height = _height;
cell.innerHTML = _inner;
}
};

View File

@ -1,368 +0,0 @@
var FrameUtils = {
getDocument: function(frm) {
if (frm.contentDocument) {
return frm.contentDocument;
} else if (frm.contentWindow) {
return frm.contentWindow.document;
} else if (frm.document) {
return frm.document;
} else {
alert( myRealAgent + ": cannot find document in frame " + frm);
//for( var a in frm )
// alert( a );
return null;
}
},
initFrame: function(frm) {
var doc = this.getDocument(frm);
doc.open();
doc.write("<html><head>");
doc.write("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""+Chat.webimRoot+"/chat.css\" />");
doc.write("</head><body bgcolor='#FFFFFF' text='#000000' link='#C28400' vlink='#C28400' alink='#C28400' marginwidth='0' marginheight='0' leftmargin='0' rightmargin='0' topmargin='0' bottommargin='0'>");
doc.write("<table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td valign='top' class='message' id='content'></td></tr></table><a id='bottom'/>");
doc.write("</body></html>");
doc.close();
frm.onload = function() {
if( frm./**/myHtml ) {
FrameUtils.getDocument(frm).getElementById('content').innerHTML += frm.myHtml;
FrameUtils.scrollDown(frm);
}
};
},
insertIntoFrame: function(frm, htmlcontent) {
var vcontent = this.getDocument(frm).getElementById('content');
if( vcontent == null ) {
if( !frm.myHtml ) frm.myHtml = "";
frm.myHtml += htmlcontent;
} else {
vcontent.innerHTML += htmlcontent;
}
},
scrollDown: function(frm) {
var vbottom = this.getDocument(frm).getElementById('bottom');
if( myAgent == 'opera' ) {
frm.contentWindow.scrollTo(0,this.getDocument(frm).getElementById('content').clientHeight);
} else if( vbottom )
vbottom.scrollIntoView(false);
}
};
Ajax.ChatThreadUpdater = Class.create();
Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.onComplete = this.requestComplete.bind(this);
this._options.onException = this.handleException.bind(this);
this.updater = {};
this.frequency = (this._options.frequency || 2);
this.cansend = true;
FrameUtils.initFrame(this._options.container);
if( this._options.message ) {
this._options.message.onkeydown = this.handleKeyDown.bind(this);
this._options.message.onfocus = (function() { this.focused = true; }).bind(this);
this._options.message.onblur = (function() { this.focused = false; }).bind(this)
}
this.update();
},
handleException: function(_request, ex) {
this.setStatus(ex.name + " occured: " + ex.message);
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
updateOptions: function(act) {
this._options.parameters = 'act='+act+'&thread=' + (this._options.threadid || -1) +
'&token=' + (this._options.token || 0)+
'&lastid=' + (this._options.lastid || 0);
if( this._options.user )
this._options.parameters += "&user=true";
if( act == 'refresh' && this._options.message && this._options.message.value != '' )
this._options.parameters += "&typed=1";
},
enableInput: function(val) {
if( this._options.message )
this._options.message.disabled = !val;
},
stopUpdate: function() {
this.enableInput(true);
if( this.updater._options )
this.updater._options.onComplete = undefined;
clearTimeout(this.timer);
},
update: function() {
this.updateOptions("refresh");
this.updater = new Ajax.Request(this._options.servl, this._options);
},
requestComplete: function(_response) {
this.enableInput(true);
this.cansend = true;
var xmlRoot = Ajax.getXml(_response);
if( xmlRoot && xmlRoot.tagName == 'thread' ) {
this.updateContent( xmlRoot );
} else {
this.handleError(_response, xmlRoot, 'refresh messages failed');
}
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
postMessage: function(msg) {
if( msg == "" || !this.cansend) {
return;
}
this.cansend = false;
this.stopUpdate();
this.updateOptions("post");
var postOptions = {}.extend(this._options);
postOptions.parameters += "&message=" + encodeURIComponent(msg);
postOptions.onComplete = (function(presponse) {
this.requestComplete( presponse );
if( this._options.message ) {
this._options.message.value = '';
this._options.message.focus();
}
}).bind(this);
if( myRealAgent != 'opera' )
this.enableInput(false);
this.updater = new Ajax.Request(this._options.servl, postOptions);
},
changeName: function(newname) {
new Ajax.Request(this._options.servl, {parameters:'act=rename&thread=' + (this._options.threadid || -1) +
'&token=' + (this._options.token || 0) + '&name=' + encodeURIComponent(newname)});
},
onThreadClosed: function(_response) {
var xmlRoot = Ajax.getXml(_response);
if( xmlRoot && xmlRoot.tagName == 'closed' ) {
setTimeout('window.close()', 2000);
} else {
this.handleError(_response, xmlRoot, 'cannot close');
}
},
closeThread: function() {
var _params = 'act=close&thread=' + (this._options.threadid || -1) + '&token=' + (this._options.token || 0);
if( this._options.user )
_params += "&user=true";
new Ajax.Request(this._options.servl, {parameters:_params, onComplete: this.onThreadClosed.bind(this)});
},
processMessage: function(_target, message) {
var destHtml = NodeUtils.getNodeText(message);
FrameUtils.insertIntoFrame(_target, destHtml );
},
showTyping: function(istyping) {
if( $("typingdiv") ) {
$("typingdiv").style.display=istyping ? 'inline' : 'none';
}
},
setupAvatar: function(avatar) {
var imageLink = NodeUtils.getNodeText(avatar);
if( this._options.avatar && this._options.user ) {
this._options.avatar.innerHTML = imageLink != ""
? "<img src=\""+Chat.webimRoot+"/images/free.gif\" width=\"7\" height=\"1\" border=\"0\" alt=\"\" /><img src=\""
+imageLink+ "\" border=\"0\" alt=\"\"/>"
: "";
}
},
updateContent: function(xmlRoot) {
var haveMessage = false;
var result_div = this._options.container;
var _lastid = NodeUtils.getAttrValue(xmlRoot, "lastid");
if( _lastid ) {
this._options.lastid = _lastid;
}
var typing = NodeUtils.getAttrValue(xmlRoot, "typing");
if( typing ) {
this.showTyping(typing == '1');
}
for( var i = 0; i < xmlRoot.childNodes.length; i++ ) {
var node = xmlRoot.childNodes[i];
if( node.tagName == 'message' ) {
haveMessage = true;
this.processMessage(result_div, node);
} else if( node.tagName == 'avatar' ) {
this.setupAvatar(node);
}
// TODO thread events
}
if( haveMessage ) {
FrameUtils.scrollDown(this._options.container);
if( !this.focused )
window.focus();
}
},
handleKeyDown: function(k) {
if( k ){ ctrl=k.ctrlKey;k=k.which; } else { k=event.keyCode;ctrl=event.ctrlKey; }
if( this._options.message && ((k==13 && (ctrl || myRealAgent == 'opera')) || (k==10)) ) {
var mmsg = this._options.message.value;
if( myRealAgent == 'opera' ) {
mmsg = mmsg.replace(/[\r\n]+$/,'');
}
this.postMessage( mmsg );
return false;
}
return true;
},
handleError: function(_response, xmlRoot, _action) {
if( xmlRoot && xmlRoot.tagName == 'error' ) {
this.setStatus(NodeUtils.getNodeValue(xmlRoot,"descr"));
} else {
this.setStatus(_action+', ' + Ajax.getError(_response));
}
},
setStatus: function(k) {
if( this.statusTimeout )
clearTimeout(this.statusTimeout);
window.status = k;
this.statusTimeout = setTimeout(this.clearStatus.bind(this), 4000);
},
clearStatus: function() {
window.status = "";
}
});
HSplitter = Class.create();
HSplitter.prototype = {
initialize: function(_options) {
this._options = _options;
this.captured = 0;
if( this._options.first && this._options.second && this._options.control ) {
this._options.control.onmousedown = this.onmousedownEvent.bind(this);
this._options.control.onmouseup = this.onmouseupEvent.bind(this);
this._options.control.onmousemove = this.onmouseMoveEvent.bind(this);
}
},
onmousedownEvent: function(e) {
var ev = e || event;
if( this._options.control.setCapture )
this._options.control.setCapture();
this.start_height = this._options.first.style.pixelHeight || this._options.first.clientHeight;
this.start_offset = ev.screenY;
this._options.maxfirst = this._options.first.style.pixelHeight + this._options.second.clientHeight - this._options.minsec;
this.captured = 1;
},
onmouseupEvent: function() {
if( this.captured ) {
if( this._options.control.releaseCapture )
this._options.control.releaseCapture();
this.captured = 0;
}
},
onmouseMoveEvent: function(e) {
var ev = e || event;
if( this.captured ) {
var new_height = this.start_height - (ev.screenY - this.start_offset);
if( new_height > this._options.maxfirst )
new_height = this._options.maxfirst;
else if( new_height < this._options.minfirst )
new_height = this._options.minfirst;
if( myAgent == 'moz' )
this._options.first.style.height=new_height+'px';
else
this._options.first.style.pixelHeight = new_height;
}
}
};
var Chat = {
threadUpdater : {},
hSplitter : {},
applyName: function() {
Chat.threadUpdater.changeName($('uname').value);
$('changename1').style.display='none';
$('changename2').style.display='inline';
},
showNameField: function() {
$('changename1').style.display='inline';
$('changename2').style.display='none';
}
};
Behaviour.register({
'#postmessage a' : function(el) {
el.onclick = function() {
var message = $('msgwnd');
if( message )
Chat.threadUpdater.postMessage(message.value);
};
},
'a#sndmessagelnk' : function(el) {
if( myRealAgent == 'opera' ) {
el.innerHTML = el.innerHTML.replace('Ctrl-','');
}
},
'select#predefined' : function(el) {
el.onchange = function() {
var message = $('msgwnd');
message.value = this.options[this.selectedIndex].innerText || this.options[this.selectedIndex].innerHTML;
this.selectedIndex = 0;
message.focus();
};
},
'div#changename2 a' : function(el) {
el.onclick = function() {
Chat.showNameField();
return false;
};
},
'div#changename1 a' : function(el) {
el.onclick = function() {
Chat.applyName();
return false;
};
},
'div#changename1 input#uname' : function(el) {
el.onkeydown = function(e) {
var ev = e || event;
if( ev.keyCode == 13 ) {
Chat.applyName();
}
};
},
'a#refresh' : function(el) {
el.onclick = function() {
Chat.threadUpdater.stopUpdate();
Chat.threadUpdater.update();
};
},
'a.closethread' : function(el) {
el.onclick = function() {
Chat.threadUpdater.closeThread();
};
}
});
EventHelper.register(window, 'onload', function(){
Chat.webimRoot = threadParams.wroot;
Chat.hSplitter = new HSplitter({control:$("spl1"), first:$("msgwndtd"), second:$("chatwndtd"), minfirst:30, minsec:30});
Chat.threadUpdater = new Ajax.ChatThreadUpdater(({container:myRealAgent=='safari'?self.frames[0]:$("chatwnd"),avatar:$("avatarwnd"),message:$("msgwnd")}).extend( threadParams || {} ));
});

View File

@ -1,310 +0,0 @@
Ajax.PeriodicalUpdater = Class.create();
Class.inherit( Ajax.PeriodicalUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.onComplete = this.requestComplete.bind(this);
this._options.onException = this.handleException.bind(this);
this.frequency = (this._options.frequency || 2);
this.updater = {};
this.update();
},
handleException: function(_request, ex) {
if( this._options.handleError )
this._options.handleError( ex.name + " occured: " + ex.message );
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
stopUpdate: function() {
if( this.updater._options )
this.updater._options.onComplete = undefined;
clearTimeout(this.timer);
},
update: function() {
if( this._options.updateParams )
this._options.parameters = (this._options.updateParams)();
this.updater = new Ajax.Request(this._options.url, this._options);
},
requestComplete: function(presponse) {
if (presponse != null && presponse.status == 200 ) {
var xmlDoc = presponse.responseXML;
(this._options.updateContent || Ajax.emptyFunction)( xmlDoc );
} else {
if( this._options.handleError )
this._options.handleError(Ajax.getError(_response));
}
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
}
});
var HtmlGenerationUtils = {
insertSplitter: function( _row ) {
var cell = _row.insertCell(-1);
cell.style.backgroundImage = 'url('+webimRoot+'/images/tablediv3.gif)';
cell.innerHTML = '<img src="'+webimRoot+'/images/free.gif" width="3" height="1" border="0" alt="">';
},
removeHr: function(_table, _index ) {
_table.deleteRow(_index+2);
_table.deleteRow(_index+1);
_table.deleteRow(_index);
},
insertHr: function(_table, _index) {
var row = _table.insertRow(_index);
var cell = row.insertCell(-1);
cell.colSpan = 13;
cell.height = 2;
row = _table.insertRow(_index);
cell = row.insertCell(-1);
cell.colSpan = 13;
cell.style.backgroundColor = '#E1E1E1';
cell.innerHTML = '<img src="'+webimRoot+'/images/free.gif" width="1" height="1" border="0" alt="">';
row = _table.insertRow(_index);
cell = row.insertCell(-1);
cell.colSpan = 13;
cell.height = 2;
},
popupLink: function(link, title, wndid, inner, width, height) {
return '<a href="'+link+'" target="_blank" title="'+title+'" onclick="this.newWindow = window.open(\''+link+'\', \''+
wndid+'\', \'toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width='+width+',height='+height+',resizable=1\');this.newWindow.focus();this.newWindow.opener=window;return false;">'+
inner+'</a>';
},
generateOneRowTable: function(content) {
return '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr>' + content + '</tr></table>';
},
viewOpenCell: function(username,servlet,id,canview,canopen,ban,message) {
var cellsCount = 2;
var link = servlet+"?thread="+id;
var innerContent = ( ban == "full" ) ? "<i style='color:#aaaaaa;'>"+username+"</i>" : ( ( ban == "other" ) ? "<i>"+username+"</i>" : username );
var gen = '<td class="table" style="padding-left:0px; padding-right:0px;">';
gen += HtmlGenerationUtils.popupLink( canopen ? link : link+"&viewonly=true", localized[canopen ? 0 : 1], "ImCenter"+id, innerContent, 600, 420);
gen += '</td><td><img src="'+webimRoot+'/images/free.gif" width="5" height="1" border="0" alt=""></td>';
if( canopen ) {
gen += '<td width="30" align="center">';
gen += HtmlGenerationUtils.popupLink( link, localized[0], "ImCenter"+id, '<img src="'+webimRoot+'/images/tbliclspeak.gif" width="15" height="15" border="0" alt="'+localized[0]+'">', 600, 420);
gen += '</td>';
cellsCount++;
}
return HtmlGenerationUtils.generateOneRowTable(gen);
}
};
Ajax.ThreadListUpdater = Class.create();
Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.updateParams = this.updateParams.bind(this);
this._options.handleError = this.handleError.bind(this);
this._options.updateContent = this.updateContent.bind(this);
this._options.lastrevision = 0;
this.threadTimers = new Object();
this.delta = 0;
this.t = this._options.table;
this.periodicalUpdater = new Ajax.PeriodicalUpdater(this._options);
},
updateParams: function() {
return "company=" + this._options.company + "&since=" + this._options.lastrevision;
},
setStatus: function(msg) {
this._options.status.innerHTML = msg;
},
handleError: function(s) {
this.setStatus( s );
},
updateThread: function(node) {
var id, stateid, vstate, canview = false, canopen = false, ban = null;
for( var i = 0; i < node.attributes.length; i++ ) {
var attr = node.attributes[i];
if( attr.nodeName == "id" )
id = attr.nodeValue;
else if( attr.nodeName == "stateid" )
stateid = attr.nodeValue;
else if( attr.nodeName == "state" )
vstate = attr.nodeValue;
else if( attr.nodeName == "canopen" )
canopen = true;
}
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
var row = CommonUtils.getRow("thr"+id, this.t);
if( stateid == "closed" ) {
if( row ) {
HtmlGenerationUtils.removeHr(this.t, row.rowIndex+1);
this.t.deleteRow(row.rowIndex);
}
this.threadTimers[id] = null;
return;
}
var vname = NodeUtils.getNodeValue(node,"name");
var vaddr = NodeUtils.getNodeValue(node,"addr");
var vtime = NodeUtils.getNodeValue(node,"time");
var agent = NodeUtils.getNodeValue(node,"agent");
var modified = NodeUtils.getNodeValue(node,"modified");
var message = NodeUtils.getNodeValue(node,"message");
var etc = "";
var startRow = CommonUtils.getRow(stateid, this.t);
var endRow = CommonUtils.getRow(stateid+"end", this.t);
if( row != null && (row.rowIndex <= startRow.rowIndex || row.rowIndex >= endRow.rowIndex ) ) {
HtmlGenerationUtils.removeHr(this.t, row.rowIndex+1);
this.t.deleteRow(row.rowIndex);
this.threadTimers[id] = null;
row = null;
}
if( row == null ) {
row = this.t.insertRow(startRow.rowIndex+1);
HtmlGenerationUtils.insertHr(this.t, startRow.rowIndex+2);
row.id = "thr"+id;
this.threadTimers[id] = new Array(vtime,modified,stateid);
CommonUtils.insertCell(row, "name", "table", null, 30, HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message) );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "contid", "table", "center", null, vaddr );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "state", "table", "center", null, vstate );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "op", "table", "center", null, agent );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "time", "table", "center", null, this.getTimeSince(vtime) );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "wait", "table", "center", null, (stateid!='chat' ? this.getTimeSince(modified) : '-') );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "etc", "table", "center", null, etc );
if( stateid == 'wait' || stateid == 'prio' )
return true;
} else {
this.threadTimers[id] = new Array(vtime,modified,stateid);
setcell(this.t, row,"name",HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message));
setcell(this.t, row,"contid",vaddr);
setcell(this.t, row,"state",vstate);
setcell(this.t, row,"op",agent);
setcell(this.t, row,"time",this.getTimeSince(vtime));
setcell(this.t, row,"wait",(stateid!='chat' ? this.getTimeSince(modified) : '-'));
setcell(this.t, row,"etc",etc);
}
return false;
},
updateQueueMessages: function() {
function updateQueue(t,id,nclients) {
var startRow = t.rows[id];
var endRow = t.rows[id+"end"];
if( startRow == null || endRow == null )
return;
var _status = endRow.cells["status"];
if( _status == null )
return;
_status.innerHTML = (startRow.rowIndex + 1 == endRow.rowIndex) ? nclients : "";
_status.height = (startRow.rowIndex + 1 == endRow.rowIndex) ? 30 : 10;
}
updateQueue(this.t, "wait", this._options.noclients);
updateQueue(this.t, "prio", this._options.noclients);
updateQueue(this.t, "chat", this._options.noclients);
},
getTimeSince: function(srvtime) {
var secs = Math.floor(((new Date()).getTime()-srvtime-this.delta)/1000);
var minutes = Math.floor(secs/60);
var prefix = "";
secs = secs % 60;
if( secs < 10 )
secs = "0" + secs;
if( minutes >= 60 ) {
var hours = Math.floor(minutes/60);
minutes = minutes % 60;
if( minutes < 10 )
minutes = "0" + minutes;
prefix = hours + ":";
}
return prefix + minutes+":"+secs;
},
updateTimers: function() {
for (var i in this.threadTimers) {
if (this.threadTimers[i] != null) {
var value = this.threadTimers[i];
var row = CommonUtils.getRow("thr"+i, this.t);
if( row != null ) {
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
setcell(this.t, row,"time",this.getTimeSince(value[0]));
setcell(this.t, row,"wait",(value[2]!='chat' ? this.getTimeSince(value[1]) : '-'));
}
}
}
},
updateContent: function(xmldoc) {
var root = xmldoc.documentElement;
var newAdded = false;
if( root.tagName == 'threads' ) {
var _time = NodeUtils.getAttrValue(root, "time");
var _revision = NodeUtils.getAttrValue(root, "revision" );
if( _time )
this.delta = (new Date()).getTime() - _time;
if( _revision )
this._options.lastrevision = _revision;
for( var i = 0; i < root.childNodes.length; i++ ) {
var node = root.childNodes[i];
if( node.tagName == 'thread' )
if( this.updateThread(node) )
newAdded = true;
}
this.updateQueueMessages();
this.updateTimers();
this.setStatus( "Up to date" );
if( newAdded )
window.focus();
} else if( root.tagName == 'error' ) {
this.setStatus( "error: " + NodeUtils.getNodeValue(root,"descr") );
} else {
this.setStatus( "wrong response" );
}
}
});
var webimRoot = "";
EventHelper.register(window, 'onload', function(){
webimRoot = updaterOptions.wroot;
new Ajax.ThreadListUpdater(({table:$("threadlist"),status:$("connstatus")}).extend(updaterOptions || {}));
});