chore: remove useless stuff

Stray bits of config, MacOS dashboard widget...
This commit is contained in:
Emmanuel BENOîT 2024-12-31 17:41:29 +01:00
parent 46df0f2d61
commit 3922a78de9
Signed by: Emmanuel BENOîT
SSH key fingerprint: SHA256:l7PFUUF5TCDsvYeQC9OnTNz08dFY7Fvf4Hv3neIqYpg
60 changed files with 6 additions and 4929 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AllowNetworkAccess</key>
<true/>
<key>CFBundleDisplayName</key>
<string>Legacy Worlds</string>
<key>CFBundleIdentifier</key>
<string>com.apple.widget.legacyworlds</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MainHTML</key>
<string>LW.html</string>
</dict>
</plist>

View file

@ -1,109 +0,0 @@
body {
margin: 0;
}
#mainDiv {
position: absolute;
top: 35px;
left: 7px;
width: 307px;
height: 290px;
margin: 0;
padding: 0;
}
#debugLink {
position: absolute;
top: 326px;
left: 30px;
width: 271px;
height: 14px;
margin: 0;
padding: 0;
color: white;
font-size: 12px;
text-align: center;
}
#debugDiv {
display: none;
position: absolute;
top: 35px;
left: 7px;
width: 307px;
height: 290px;
margin: 0;
padding: 0;
color: white;
font-size: 12px;
z-index: 1;
border: 1px solid #7f7f7f;
}
#debugTable {
width: 301px;
height: 284px;
margin: 3px;
padding: 0;
border: 0px;
}
#debugTable td {
color: white;
font-size: 12px;
}
tr#dbgHdr {
height: 14px;
}
#mainTable {
width: 305px;
height: 288px;
margin: 1px;
padding: 0;
border: 1px solid #7f7f7f;
border-collapse: collapse;
}
#mtTitle {
text-align: center;
vertical-align: middle;
height: 30px;
font-size: 18px;
color: white;
font-weight: bold;
}
#mtMenu {
text-align: center;
vertical-align: middle;
height: 30px;
border: 1px solid #7f7f7f;
font-size: 12px;
color: white;
}
#mtContents {
color: white;
vertical-align: middle;
text-align: center;
font-size: 13px;
}
a, a:active, a:visited {
text-decoration: underline;
font-style: italic;
color: white;
}
.table {
margin: 0% 4%;
width: 96%;
border: 0;
}
.table td {
color: white;
font-size: 13px;
}

View file

@ -1,58 +0,0 @@
<html>
<head>
<style>
@import "LW.css";
</style>
<!-- DeepClone components library -->
<script type='text/javascript' src='lib/Base.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Util.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Util/Hashtable.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Log.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Comp.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Comp/Evt.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Comp/Slot.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Timer.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/Browser.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/Base/XMLLoader.js' charset='utf-8'></script>
<!-- Main widget code -->
<script type='text/javascript' src='lib/LWWidget.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Main.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Debug.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/VersionCheck.js' charset='utf-8'></script>
<!-- Data management -->
<script type='text/javascript' src='lib/LWWidget/Data.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Data/Leaf.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Data/Node.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Data/Loader.js' charset='utf-8'></script>
<!-- Menu code -->
<script type='text/javascript' src='lib/LWWidget/Menu.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Menu/Mode.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Menu/Item.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Menu/Text.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Menu/Command.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Menu/Entry.js' charset='utf-8'></script>
<!-- Top-level pages -->
<script type='text/javascript' src='lib/LWWidget/Page.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Login.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/TextPage.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/GameSelector.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/GameDisplay.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/NewVersion.js' charset='utf-8'></script>
<!-- Game handling -->
<script type='text/javascript' src='lib/LWWidget/Game.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Game/Page.js' charset='utf-8'></script>
<!-- Beta 5 -->
<script type='text/javascript' src='lib/LWWidget/Beta5.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Player.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Planets.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Fleets.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Cash.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Techs.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Msg.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Forums.js' charset='utf-8'></script>
<script type='text/javascript' src='lib/LWWidget/Beta5/Ticks.js' charset='utf-8'></script>
</head>
<body>
<img src="Default.png" />
</body>
</html>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

View file

@ -1,189 +0,0 @@
/** This function defines the Base class, from which all other classes are inherited.
* The Base class defines a somewhat sound framework for inheritance.
*/
Base = function () {
if (arguments.length) {
if (this == window) {
Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
} else {
this.extend(arguments[0]);
}
}
};
/** This class property lists the functions to be called when the page
* containing the code is first loaded.
*/
Base.initialisers = new Array();
/** This class property lists the functions to be called when the page
* containing the code is unloaded.
*/
Base.destructors = new Array();
/** This class method adds a function to the list of initialisers.
*/
Base.registerInitialiser = function (initialiser) {
Base.initialisers.push(initialiser);
};
/** This class method adds a function to the list of destructors.
*/
Base.registerDestructor = function (destructor) {
Base.destructors.push(destructor);
};
Base.prototype = {
/** The extend() method adds a set of methods and properties to an existing object.
* @param addition an object containing the methods and properties to add.
* @returns the extended object.
*/
extend: function (addition) {
var _o = Base.prototype.overload;
var _p = { toSource: null };
var _l = ['toString', 'valueOf'];
if (Base._inherits) {
_l.push('constructor');
}
for (var i in _l) {
var _n = _l[i];
if (addition[_n] != _p[_n]) {
_o.call(this, _n, addition[_n]);
_p[_n] = addition[_n];
}
}
for (var i in addition) {
if (_p[i]) {
continue;
}
if (addition[i] instanceof Function) {
_o.call(this, i, addition[i]);
} else {
this[i] = addition[i];
}
}
return this;
},
/** The overload() method overloads a single method in an object; it
* creates a new function that sets this.base to the old value then
* calls the new code.
* @param name the name of the method to be overloaded.
* @param value the Function object for the new method.
* @returns the value for the overloaded method.
*/
overload: function (name, value) {
if (value == this[name] || name == 'base') {
return;
}
var _v = value, _ov = this[name];
value = function () {
var _b = this.base;
this.base = _ov;
var _r = _v.apply(this, arguments);
this.base = _b;
return _r;
};
value.valueOf = function() {
return _v;
};
value.toString = function () {
return String(_v);
};
return this[name] = value;
}
};
/** This class property stores the list of namespaces to preserve when onunload is called. */
Base._preserve = new Array();
/** This static method is used to define class inheritance.
* @param members an object containing the new methods and properties to be added or overloaded.
* @param cMembers an object containing the methods and properties to be added as static members.
* @param name a string indicating the namespace this object is supposed to define; it is used
* to preserve namespaces from being deleted before the onunload() handler.
* @return the object corresponding to the newly created class.
*/
Base.inherits = function (members, cMembers, name) {
if (!members) {
members = { };
}
var _e = Base.prototype.extend;
var _b = this;
Base._inherits = true;
var _p = new _b;
_e.call(_p, members);
delete Base._inherits;
var _c = _p.constructor;
_p.constructor = this;
var _cl = function() {
this.base = _b;
if (!Base._inherits) {
_c.apply(this, arguments);
}
this.constructor = _cl;
delete this.base;
};
_cl.inherits = this.inherits;
_cl.toString = function() {
return String(_c);
};
_cl.prototype = _p;
if (!cMembers) {
cMembers = { };
}
_e.call(_cl, cMembers);
if (cMembers["onLoad"] instanceof Function) {
Base.registerInitialiser(_cl["onLoad"]);
}
if (cMembers["onUnload"] instanceof Function) {
Base.registerDestructor(_cl["onUnload"]);
}
if (name && name != "") {
Base._preserve[name] = _cl;
}
return _cl;
};
/** Set the page's onload() handler. */
window.onload = function () {
var _b = Base;
for (var i in _b.initialisers) {
if (typeof _b.initialisers[i] == 'undefined') {
continue;
}
_b.initialisers[i]();
}
/** Set the page's onunload() handler. */
window.onunload = function () {
Base = _b;
for (var i in _b._preserve) {
eval(i + " = _b._preserve[i]");
}
for (var i = _b.destructors.length - 1; i >= 0; i--) {
_b.destructors[i]();
}
};
};

View file

@ -1,94 +0,0 @@
/** The Base.Browser class contains the code that detects the user's browser and keeps
* track of the current window's size.
*/
Base.Browser = Base.Comp.inherits({
/** The constructor detects the browser type, then initialises the window size
* watching code.
*/
constructor: function () {
if (Base.Browser.singleton) {
throw "SingletonException";
}
this.base();
// Get the document body object
this.docBody = (document.compatMode && document.compatMode != 'BackCompat') ? document.documentElement : (document.body ? document.body : null);
// Detect the browser's type
var nav = navigator.userAgent.toLowerCase(), ver = navigator.appVersion;
this.opera = window.opera && document.getElementById;
this.ie = nav.indexOf("msie") != -1 && document.all && this.docBody && !this.opera;
this.opera6 = this.opera && !document.defaultView;
this.operaOther = this.opera && !this.opera6;
this.ie7 = this.ie && parseFloat(ver.substring(ver.indexOf("MSIE")+5)) >= 7;
this.ie6 = this.ie && !this.ie7 && parseFloat(ver.substring(ver.indexOf("MSIE")+5)) >= 5.5;
var ns = !this.opera && document.defaultView && (typeof document.defaultView.getComputedStyle != "undefined");
this.konqueror = ns && nav.indexOf('konqueror') != -1;
this.safari = ns && nav.indexOf('applewebkit') != -1;
this.ns6 = ns && !this.konqueror && !this.safari;
this.supported = this.docBody && (this.ie6 || this.ie7 || this.opera || this.ns6 || this.konqueror || this.safari);
// Prepare the window size watching code
this.addEvent('SizeChanged');
var _cid = this._cid;
window.onresize = function () {
Base.Comp.get(_cid).handleResize();
};
if (this.konqueror) {
this.addSlot('resizeTimer');
this.timer = new Base.Timer(250, false);
this.timer.bindEvent('Tick', 'resizeTimer', this);
}
this.readSize();
},
/** This method reads the current window's size.
*/
readSize: function () {
this.width = (this.ie ? this.docBody.offsetWidth : window.innerWidth);
this.height = (this.ie ? this.docBody.offsetHeight : window.innerHeight);
},
/** This method is called by the resize handler or, if the user is running Konqueror,
* by the timer that keeps track of resizing. It reads the current size, and if that
* size is different from the old size, it sends a SizeChanged(width,height) event.
*/
resizeTimer: function () {
var ow = this.width, oh = this.height;
this.readSize();
if (ow != this.width || oh != this.height) {
this.onSizeChanged(this.width, this.height);
}
},
/** This method either forces the object to re-check the window's size or, if the
* user is running Konqueror, starts or restarts the update timer to prevent
* receiving multiple window update codes.
*/
handleResize: function () {
if (this.konqueror) {
this.timer.restart();
return;
}
this.resizeTimer();
}
}, {
/** This class property contains the single Base.Browser instance.
*/
singleton: null,
/** This class method returns the Base.Browser instance after creating it
* if it didn't exist.
*/
get: function () {
if (!Base.Browser.singleton) {
Base.Browser.singleton = new Base.Browser();
}
return Base.Browser.singleton;
}
});

View file

@ -1,217 +0,0 @@
/** The Base.Comp class is the base class for all of the components. It provides the
* signal/slot framework that the components use, and allows access to components using
* their unique identifier.
*/
Base.Comp = Base.inherits({
/** The constructor initialises the component by assigning its identifier, creating the
* tables listing the slots, events and children, and creating the low-level slots and
* events common to all components.
*/
constructor: function () {
this._cid = ++ Base.Comp.lastId;
this._slots = new Base.Util.Hashtable();
this._evts = new Base.Util.Hashtable();
this._chld = new Base.Util.Hashtable();
this._cnt = null;
Base.Comp.list.put(this._cid, this);
Base.Comp.count ++;
this.destroyChildren = false;
this.addEvent('Destroy');
this.addSlot('addChild');
this.addSlot('removeChild');
},
/** This method is responsible for the destruction of a component. It
* starts by launching the onDestroy() event; it then detaches the
* component's children (or destroy them if the destroyChildren member
* is set to true), then detaches all of the component's slots and
* events. Finally, it removes the reference to the component in the
* global components list.
*/
destroy: function () {
this.onDestroy(this._cid);
var k = this._chld.keys();
for (var i in k) {
var c = this._chld.get(k[i]);
if (this.destroyChildren) {
c.destroy();
} else {
this.removeChild(c);
}
}
k = this._slots.keys();
for (var i in k) {
this._slots.get(k[i]).destroy();
}
this._slots.clear();
k = this._evts.keys();
for (var i in k) {
this._evts.get(k[i]).destroy();
}
this._evts.clear();
Base.Comp.list.remove(this._cid);
Base.Comp.count --;
for (var i in this) {
this[i] = null;
}
},
/** This method declares a new slot for the current component.
* @param name the name of the slot to be declared
*/
addSlot: function (name) {
if (this._slots.containsKey(name) || !this[name]) {
return;
}
this._slots.put(name, new Base.Comp.Slot(name, this));
},
/** This method generates a new event handler for the current component.
* @param name the name of the event to create
* @param propagate a boolean indicating the event propagates to the component's children
*/
addEvent: function (name, propagate) {
if (this._evts.containsKey(name) || this["on" + name]) {
return;
}
this._evts.put(name, new Base.Comp.Evt(name, propagate));
this["on" + name] = function() {
this.triggerEvent(name, arguments);
};
this.addSlot('on' + name);
},
/** This method binds an event from the current component to a slot on either the current
* component or, if the last parameter is present, another component.
* @param eName the name of the event to bind
* @param sName the name of the slots to bind an event to
* @param cmp the component on which to bind (if this parameter isn't passed, the current component is used)
*/
bindEvent: function (eName, sName, cmp) {
var e = this._evts.get(eName), c = (cmp ? cmp : this), s = c._slots.get(sName);
if (!(e && s)) {
return;
}
e.bind(s);
},
/** This method detaches an event from the current component from a slot to which it had been bound.
* @param eName the name of the event to detach
* @param sName the name of the slot to detach
* @param cmp the component on which the slot to detach is located
*/
detachEvent: function (eName, sName, cmp) {
var e = this._evts.get(eName), c = (cmp ? cmp : this), s = c._slots.get(sName);
if (!(e && s)) {
return;
}
e.detach(s);
},
/** This method triggers the execution of an event on the current component.
* @param eName the name of the event to trigger
* @param args an array containing the arguments to be passed to the event's handlers
*/
triggerEvent: function (eName, args) {
var e = this._evts.get(eName);
if (!e) {
return;
}
e.trigger.apply(e, args);
if (!e.propagate) {
return;
}
var k = this._chld.keys();
for (i=0;i<k.length;i++) {
this._chld.get(k[i]).triggerEvent(eName, args);
}
},
/** This method adds a child to the current component.
* @param cmp the component to add as a child of the current component
*/
addChild: function (cmp) {
if (!cmp || cmp._cid == this._cid || cmp.container != null) {
return;
}
cmp.container = this;
this._chld.put(cmp._cid, cmp);
cmp.bindEvent('Destroy', 'removeChild', this);
},
/** This method removes a child from the current component's list of children.
* @param cmp the child component to remove
*/
removeChild: function (cmp) {
if (!(cmp && this._chld.containsKey(cmp._cid))) {
return;
}
this._chld.remove(cmp._cid);
cmp.container = null;
cmp.detachEvent('Destroy', 'removeChild', this);
},
/** This method checks whether a component is a child of the current component.
* @param cmp the component to verify
* @returs true if the specified component is a child of the current component, false otherwise
*/
hasChild: function (cmp) {
return (cmp && cmp.container && cmp.container._cid == this._cid);
}
}, {
/** This class property contains the list of all available components;
* the components' identifiers are used as the key.
*/
list: new Base.Util.Hashtable(),
/** This class property stores the last identifier assigned to a
* component.
*/
lastId: -1,
/** This class property stores the amount of components currently
* being used.
*/
count: 0,
/** This static method returns a component from its identifier.
* @param id the component's identifier
*/
get: function (id) {
if (!Base.Comp.list.containsKey(id)) {
return null;
}
return Base.Comp.list.get(id);
},
/** This static method destroys all of the components.
*/
onUnload: function () {
var l = Base.Comp.list.values();
for (var i in l) {
if (l[i] && l[i].destroy) {
l[i].destroy();
}
}
Base.Comp.list.clear();
}
});

View file

@ -1,77 +0,0 @@
/** This class defines the data structure and operations required to handle a component's
* events.
*/
Base.Comp.Evt = Base.inherits({
/** The constructor generates an event storage for an event on a component's
* instance.
* @param name the name of the event
* @param propagate a boolean indicating whether this event should
* be propagated to a component's children
*/
constructor: function (name, propagate) {
this.id = ++Base.Comp.Evt.lId;
this.name = name;
this.propagate = propagate;
this.bindings = new Base.Util.Hashtable();
Base.Comp.Evt.list[this.id] = this;
},
/** This method is responsible for cleaning up an event storage instance being
* destroyed.
*/
destroy: function () {
var k = this.bindings.keys(), i;
for (i=0;i<k.length;i++) {
var s = this.bindings.get(k[i]);
s.events.remove(this.id);
this.bindings.remove(s.id);
}
Base.Comp.Evt.list[this.id] = null;
for (var i in this) {
this[i] = null;
}
},
/** This method binds the current event to a specified slot.
* @param slot the slot to which the event will be bound
*/
bind: function (slot) {
if (slot && !this.bindings.containsKey(slot.id) && !slot.events.containsKey(this.id)) {
slot.events.put(this.id, this);
this.bindings.put(slot.id, slot);
}
},
/** This method detaches the current event from a specified slot.
* @param slot the slot from which the event should be detached
*/
detach: function (slot) {
if (slot && this.bindings.containsKey(slot.id) && slot.events.containsKey(this.id)) {
slot.events.remove(this.id);
this.bindings.remove(slot.id);
}
},
/** This method triggers the execution of all the slots bound to the event.
*/
trigger: function() {
var i, k = this.bindings.keys();
for (i=0;i<k.length;i++) {
this.bindings.get(k[i]).call(arguments);
}
}
}, {
/** This class property stores the value of the last attributed event identifier.
*/
lId: -1,
/** This class property stores the list of all existing events.
*/
list: new Array()
});

View file

@ -1,50 +0,0 @@
/** This class defines the data structure and operations required to handle a component's
* slots.
*/
Base.Comp.Slot = Base.inherits({
/** The constructor generates a new slot bound to a specified component.
* @param name the slot's name
* @param component the component instance to which this slot belongs
*/
constructor: function (name, component) {
this.id = ++Base.Comp.Slot.lId;
this.name = name;
this.component = component;
this.events = new Base.Util.Hashtable();
},
/** This method calls the component's method for the slot the current instance
* represents.
* @param a an array containing the parameters to be passed to the
* component's method.
*/
call: function(a) {
this.component[this.name].apply(this.component, a);
},
/** This method destroys a slot.
*/
destroy: function () {
var k = this.events.keys(), i;
for (i=0;i<k.length;i++) {
this.events.get(k[i]).detach(this);
}
Base.Comp.Slot.list[this.id] = null;
for (var i in this) {
this[i] = null;
}
}
}, {
/** This class property contains the last attributed slot identifier.
*/
lId: -1,
/** This class property contains the list of all existing slots.
*/
list: new Array()
});

View file

@ -1,52 +0,0 @@
Base.Log = Base.inherits({
constructor: function (maxSize) {
this.base();
this.log = new Array();
this.maxSize = maxSize ? maxSize : 4096;
},
insert: function (line) {
if (!line) {
return;
}
if (this.log.length == this.maxSize) {
this.log.shift();
}
this.log.push(line);
},
flush: function () {
this.log = new Array();
}
}, {
singleton: null,
initLog: function (maxSize) {
if (!this.singleton) {
this.singleton = new this(maxSize);
}
},
write: function (line) {
if (this.singleton) {
this.singleton.insert(line);
}
},
get: function () {
return (this.singleton ? this.singleton.log : new Array());
},
flush: function () {
if (!this.singleton) {
return new Array();
}
var _r = this.singleton.log;
this.singleton.flush();
return _r;
}
});

View file

@ -1,169 +0,0 @@
Base.Timer = Base.Comp.inherits({
/** This property contains the setTimeout() result value being used for the
* timer.
*/
timer: null,
/** This property contains the timestamp of the last executed tick.
*/
lastAt: 0,
/** This property contains the timestamp at which the timer was paused.
*/
pausedAt: 0,
/** This property is used internally to lock access to the instance's
* properties.
*/
locked: false,
/** This property indicates whether the timer is currently running.
*/
running: false,
/** The constructor initialises a new timer instance. It does not start
* the timer, however - the start() method has to be called.
* @param miliseconds the interval for the timer, in milliseconds
* @param repeat a boolean indicating whether the timer fires
* only once (false) or repeatedly (true)
*/
constructor: function (miliseconds, repeat) {
this.base();
this.addSlot('start');
this.addSlot('stop');
this.addSlot('restart');
this.addSlot('pause');
this.addEvent('Tick');
this.miliseconds = miliseconds;
this.repeat = repeat;
},
/** This method stops the timer then destroys the instance.
*/
destroy: function () {
while (this.locked) ;
this.locked = true;
if (this.running) {
clearTimeout(this.timer);
this.lastAt = this.pausedAt = 0;
this.running = false;
}
this.base();
},
/** This method initialises the timer itself.
*/
start: function() {
while (this.locked) ;
this.locked = true;
if (!this.running) {
this.running = true;
this.lastAt = new Date().getTime();
this.setTimer();
}
this.locked = false;
},
/** This method stops the timer from running.
*/
stop: function() {
while (this.locked) ;
this.locked = true;
if (this.running) {
clearTimeout(this.timer);
this.lastAt = this.pausedAt = 0;
this.running = false;
}
this.locked = false;
},
/** This method restarts the timer. It is equivalent to calling
* stop() then start(), but it is faster.
*/
restart: function() {
while (this.locked) ;
this.locked = true;
if (this.running) {
clearTimeout(this.timer);
this.pausedAt = 0;
} else {
this.running = true;
}
this.lastAt = new Date().getTime();
this.setTimer();
this.locked = false;
},
/** This method puts the timer on pause if it is currently running or
* restarts it if it had been paused earlier.
*/
pause: function () {
while (this.locked) ;
this.locked = true;
if (this.running) {
if (this.pausedAt == 0) {
this.pausedAt = new Date().getTime();
if (this.timer) {
clearTimeout(this.timer);
}
} else {
this.setTimer();
this.pausedAt = 0;
}
}
this.locked = false;
},
/** This method is called automatically by the setTimeout() timer; if
* the current instance is still supposed to be running, it will:
* - re-run setTimeout() to initialise the next tick if the timer is
* in "repeat" mode,
* - trigger the Tick event.
*/
tick: function() {
while (this.locked) ;
this.locked = true;
var re;
if (re = (this.running && !this.pausedAt)) {
if (this.repeat) {
this.lastAt = new Date().getTime();
this.setTimer();
} else {
this.running = false;
this.timer = null;
this.lastAt = 0;
}
}
this.locked = false;
if (re) {
this.onTick();
}
},
/** This method is used internally in order to run setTimeout() with
* the required parameters.
*/
setTimer: function() {
var _t = this.pausedAt ? (this.miliseconds - this.pausedAt + this.lastAt) : this.miliseconds;
this.timer = setTimeout("Base.Comp.get(" + this._cid + ").tick()", _t);
}
});

View file

@ -1,95 +0,0 @@
/** The Base.Util class provide a few utility functions such as number formatting. */
Base.Util = Base.inherits(null, {
/** This class property is used on IE to determine which type of ActiveX object
* the current version uses, depending on the amount of frogs that fell from the
* sky and the amount of hairs under my armpits at this time.
*/
_ieXMLParser: null,
/** The formatNumber() method transforms an integer into a string in which
* the integer has commas between each group of thousands.
* @param n the value to be formatted
*/
formatNumber: function (n) {
var x = parseInt(n, 10);
if (isNaN(x)) {
return "N/A";
}
if (x < 0) {
x = -x;
s = '-';
} else {
s = '';
}
x = x.toString();
var l = x.length, m = l % 3, c = (l - m) / 3, v = ((m > 0) ? x.substr(0, m) : ''), z;
for (z=0;z<c;z++) {
if (v != "" && v != '-') {
v += ',';
}
v += x.substr(m+(z*3), 3);
}
return s + v;
},
/** This method parses an XML document using the brower-supplied DOM parser.
* @param text the XML data to be parsed
* @returns the boolean value "false" on failure or the DOM document on
* success
*/
parseXML: function (text) {
var xmlDoc;
try {
if (Base.Browser.get().ie) {
if (!this._ieXMLParser) {
this._checkIEXMLParser();
}
xmlDoc = new ActiveXObject(this._ieXMLParser);
xmlDoc.async = "false";
xmlDoc.loadXML(text);
} else {
var parser = new DOMParser();
xmlDoc = parser.parseFromString(text, "text/xml");
}
} catch (e) {
Base.Log.write('Base.Util.parseXML(): failed with exception ' + (e.toString ? e.toString() : e));
xmlDoc = false;
}
return xmlDoc;
},
/** This class method is used by the parseXML() method to check on known XML parsers
* when running IE. It throws a random exception if none of the listed implementations
* actually exist.
*/
_checkIEXMLParser: function () {
var impls = [
"Msxml2.DOMDocument.7.0", "Msxml2.DOMDocument.6.0",
"Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0",
"Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument",
"MSXML.DOMDocument", "Microsoft.XMLDOM"
];
for (var i in impls) {
try {
new ActiveXObject(impls[i]);
} catch (e) {
continue;
}
this._ieXMLParser = impls[i];
break;
}
if (!this._ieXMLParser) {
throw "IEWithoutXMLParser";
}
}
});

View file

@ -1,125 +0,0 @@
/** The Base.Util.Hashtable class allows manipulation of hashtables by encapsulating a
* JavaScript array and using it to store the data.
*/
Base.Util.Hashtable = Base.inherits({
/** The constructor initialises the array used to store the hashtable.
*/
constructor: function () {
this.hashtable = new Array();
},
/** The clear() method reinitialises the hashtable. */
clear: function () {
this.hashtable = new Array();
},
/** The get() method returns the value associated with a specified key.
* @param key the key for which the value must be returned
* @returns the value associated with the key or undefined/null if none was found
*/
get: function (key) {
return this.hashtable[key];
},
/** This method indicates whether the hashtable contains items or not.
* @returns true if the table is empty, false otherwise
*/
isEmpty: function () {
return (parseInt(this.size()) == 0);
},
/** This method indicates whether the hashtable contains a specified key or not.
* @param key the key to look up in the table
* @return true if a value is associated with the specified key, false otherwise
*/
containsKey: function (key) {
var exists = false;
for (var i in this.hashtable) {
if (i == key && this.hashtable[i] != null) {
exists = true;
break;
}
}
return exists;
},
/** This method checks whether a specific value is stored within the hashtable.
* @param value the value to search for
* @return true if the value was found, false otherwise
*/
containsValue: function (value) {
var contains = false;
if (value != null) {
for (var i in this.hashtable) {
if (this.hashtable[i] == value) {
contains=true;
break;
}
}
}
return contains;
},
/** This method returns an array containing all of the hashtable's keys to which a
* value has been associated.
* @returns the array containing all of the table's keys
*/
keys: function () {
var keys=new Array();
for (var i in this.hashtable) {
if (this.hashtable[i] != null) {
keys.push(i);
}
}
return keys;
},
/** This method returns an array containing all of the values stored within the
* hashtable.
* @returns the array containing all of the table's values
*/
values: function () {
var values = new Array();
for (var i in this.hashtable) {
if (this.hashtable[i] != null) {
values.push(this.hashtable[i]);
}
}
return values;
},
/** This method stores a value in the table, associating it with the specified key.
* If a value was already associated with the specified key, it is overwritten.
* @param key the key to which the value is to be associated.
* @param value the value to store
*/
put: function (key, value) {
if (key == null || value == null) {
throw "NullPointerException {"+key+"},{"+value+"}";
}
this.hashtable[key] = value;
},
/** This method removes an association from the table.
* @param key the key for the association to be removed
*/
remove: function (key) {
var rtn = this.hashtable[key];
this.hashtable[key] = null;
return rtn;
},
/** This method computes the amount of associations currently stored in the table.
* @returns the amount of associations
*/
size: function () {
var size = 0;
for (var i in this.hashtable) {
if (this.hashtable[i] != null) {
size++;
}
}
return size;
}
});

View file

@ -1,313 +0,0 @@
/** This class allows the user to load data files from the server using the browser's
* native XML loader class.
*/
Base.XMLLoader = Base.Comp.inherits({
/** This property indicates whether the instance is currently loading data
* from the server.
*/
isLoading: false,
/** This property contains the native XML loader object when data is being
* loaded or null when the loader isn't active.
*/
xmlObject: null,
/** This property contains the loader's timer when data is being retrieved.
* The timer will be used to force the loader object to timeout. When no
* data is being loaded, the property contains the null value.
*/
timer: null,
/** The constructor initialises the component itself and sets default values
* for the URI, method and timeout to use.
* @param uri a string containing the URI from which the data is
* to be fetched
* @param usePost a boolean indicating whether the loader should use
* the HTTP POST method (true) or GET method
* @param timeout an optionnal integer containing the amount of seconds
* before the loader times out; this defaults to
* 20 seconds if the parameter is missing
*/
constructor: function (uri, usePost, timeout) {
this.base();
this.addEvent('Aborted');
this.addEvent('Loaded');
this.addEvent('NetworkError');
this.addEvent('ServerError');
this.addEvent('Timeout');
this.addEvent('Unsupported');
this.addSlot('load');
this.addSlot('abort');
this.addSlot('timedOut');
this.uri = uri;
this.usePost = usePost;
this.timeout = timeout ? timeout : 20;
},
/** The destructor starts by aborting the loader's operation, then calls
* the standard component destructor.
*/
destroy: function () {
this.abort();
this.base();
},
/** This method allows the user to change the parameters such as the URI, the
* method to be used and the timeout value. It will only be able to do so if
* the loader isn't operating.
* @param uri the new data URI (ignored if null)
* @param usePost the new method to use (ignored if null)
* @param timeout the new value for the loader's timeout (ignored if
* null)
* @returns true if the values were set, false if they weren't
*/
changeParameters: function (uri, usePost, timeout) {
if (this.isLoading) {
return false;
}
this.uri = uri ? uri : this.uri;
this.usePost = (typeof usePost == 'boolean') ? usePost : this.usePost;
this.timeout = timeout ? timeout : 20;
return true;
},
/** This method loads the data using the object's URI and method using the
* specified parameters.
* @param parameters a hashtable associating to each of the parameters'
* name a value that is either a string or an
* array
* @returns true if the loader was successfully started
*/
load: function (parameters) {
// Make sure we're not already loading
if (this.isLoading) {
return false;
}
this.isLoading = true;
Base.Log.write('Base.XMLLoader.load(): ' + (this.usePost ? 'POST' : 'GET') + ' ' + this.uri);
// Initialise the native loader object
var obj = Base.XMLLoader.makeNativeInstance();
if (!obj) {
this.isLoading = false;
Base.Log.write('Base.XMLLoader.load(): XMLHttpRequest unsupported');
this.onUnsupported();
return false;
}
// Generate the parameters string and the URI
var uri = this.uri, ps;
if (parameters) {
ps = Base.XMLLoader.encodeParameters(parameters);
if (!this.usePost) {
uri += '?' + ps;
}
} else {
ps = "";
}
/*
// Safari and IE are stupid
if (Base.Browser.get().safari || Base.Browser.get().IE) {
if (this.usePost || ps == '') {
uri += '?stoopid_browsa=' + (new Date()).getTime();
} else {
uri += '&stoopid_browsa=' + (new Date()).getTime();
}
}
*/
// Get ready to send the request
try {
obj.open(this.usePost ? "POST" : "GET", uri, true);
} catch (e) {
// We got a permission problem
this.isLoading = false;
Base.Log.write('Base.XMLLoader.load(): XMLHttpRequest.open() failed, possible permission problem');
Base.Log.write('Base.XMLLoader.load(): exception was ' + (e.toString ? e.toString() : e));
this.onUnsupported();
return false;
}
if (this.usePost) {
obj.setRequestHeader("Method", "POST " + uri + " HTTP/1.1");
obj.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
}
// Safari is still stupid
if (Base.Browser.get().safari) {
obj.setRequestHeader('If-Modified-Since', 'Wed, 15 Nov 1995 00:00:00 GMT');
obj.setRequestHeader("Cache-Control", "no-cache");
}
// Initialise the timer
this.timer = new Base.Timer(this.timeout * 1000);
this.timer.bindEvent('Tick', 'timedOut', this);
// Prepare the callback
var _id = this._cid;
obj.onreadystatechange = function () {
if (typeof Base != 'undefined') {
Base.Comp.get(_id).loaderEvent();
}
};
// Start the timer and send the request
this.xmlObject = obj;
this.timer.start();
obj.send((parameters && this.usePost) ? ps : null);
return true;
},
/** This method cancels the current operation if there is one.
*/
abort: function () {
if (!this.isLoading) {
return;
}
this.doAbort();
this.onAborted();
},
/** This method is used as a callback for the native loader object.
*/
loaderEvent: function () {
if (!this.isLoading) {
return;
}
var obj = this.xmlObject;
try {
if (obj.readyState != 4) {
return;
}
if (obj.status != 200) {
this.doAbort();
Base.Log.write('Base.XMLLoader.load(): server returned ' + obj.status);
this.onServerError(obj.status);
return;
}
} catch (e) {
this.doAbort();
Base.Log.write('Base.XMLLoader.load(): exception ' + (e.toString ? e.toString() : e) + ' while receiving');
this.onNetworkError(e);
return;
}
var _r = obj.responseText;
this.doAbort();
this.onLoaded(_r);
},
/** This method is responsible for deleting existing objects such as
* the native loader and the timer component.
*/
doAbort: function () {
this.isLoading = false;
if (this.xmlObject) {
this.xmlObject.abort();
delete this.xmlObject;
this.xmlObject = null;
}
if (this.timer) {
this.timer.destroy();
this.timer = null;
}
},
/** This method is called by the timer when the time imparted for loading the
* data expires.
*/
timedOut: function () {
if (!this.isLoading) {
return;
}
Base.Log.write('Base.XMLLoader: timeout :(');
this.doAbort();
this.onTimeout();
}
}, {
/** This class property stores the code to be used to generate native
* loader objects. If it is empty, the code hasn't been determined yet,
* and the "E" value indicates an error.
*/
objCode: "",
/** This class method generates native loader objects. If the objCode
* class property has been initialised, it uses its content to generate
* the new object. Otherwise it explores available options to try and
* generate a native loader object.
* @returns the native loader instance on success, null on failure
*/
makeNativeInstance: function () {
var obj;
if (this.objCode == "E") {
return null;
}
if (this.objCode != "") {
eval('obj=' + this.objCode);
} else {
try {
obj = new ActiveXObject("Msxml2.XMLHTTP");
this.objCode = 'new ActiveXObject("Msxml2.XMLHTTP")';
} catch (e) {
try {
obj = new ActiveXObject("Microsoft.XMLHTTP");
this.objCode = 'new ActiveXObject("Microsoft.XMLHTTP")';
} catch (oc) {
obj = null;
}
}
if (!obj && typeof XMLHttpRequest != "undefined") {
obj = new XMLHttpRequest();
this.objCode = "new XMLHttpRequest()";
}
}
if (!obj && typeof obj == "object" && this.objCode != "E") {
this.objCode = "E";
obj = null;
}
return obj;
},
/** This class method encodes a hashtable containing request parameters into
* a string usable when loading the data.
* @param parameters the hashtable containing the parameters to be encoded.
* @returns the encoded string
*/
encodeParameters: function (parameters) {
var mk = new Array(), pl = parameters.keys();
for (var i in pl) {
var _k = pl[i], _pn = encodeURIComponent(_k), _v = parameters.get(_k);
if (_v instanceof Array) {
for (var j in _v) {
mk.push(_pn + '[]=' + encodeURIComponent(_v[j]));
}
} else {
mk.push(_pn + '=' + encodeURIComponent(_v));
}
}
return mk.join('&');
}
});

View file

@ -1,85 +0,0 @@
LWWidget = Base.inherits({
constructor: function () {
this.base();
LWWidget.main = this;
if (LWWidget.debug) {
Base.Log.initLog();
}
this.loadPreferences();
new LWWidget.Main();
},
loadPreferences: function () {
var keys = ['lwLogin', 'lwPassword', 'lwRemAuth', 'lwGame', 'lwRemGame', 'lwColour'];
var defs = ['', '', '0', '', '0', 'blue'];
this.preferences = new Base.Util.Hashtable();
if (window.widget) {
// If we're really running inside Dashboard, load the preferences
for (var i in keys) {
var p = widget.preferenceForKey(keys[i]);
if (p && p.length > 0) {
this.preferences.put(keys[i], p);
} else {
this.preferences.put(keys[i], defs[i]);
}
}
} else {
// We're not inside Dashboard. Use defaults.
for (var i in keys) {
this.preferences.put(keys[i], defs[i]);
}
}
},
getPreference: function (key) {
return (this.preferences.containsKey(key) ? this.preferences.get(key) : null);
},
setPreference: function (key, value) {
if (this.preferences.containsKey(key) && typeof value == 'string') {
Base.Log.write("Setting preference " + key + " to '" + value + "'");
this.preferences.put(key, value);
if (window.widget) {
widget.setPreferenceForKey(key, value);
}
}
},
showDebug: function () {
if (!this.debugPanel) {
this.debugPanel = new LWWidget.Debug();
}
this.debugPanel.show();
}
}, {
// Base URL for the LegacyWorlds website.
base: 'http://www.legacyworlds.com',
// Enable/disable debugging
debug: true,
// This widget's version number
version: 1,
// Main widget instance
main: null,
// Password storage
password: '',
// When the widget page is loaded, initialise the component
onLoad: function () {
new LWWidget();
}
}, "LWWidget");

View file

@ -1,77 +0,0 @@
LWWidget.Beta5 = LWWidget.Game.inherits({
constructor: function (path) {
this.base(path);
this.pageElement = 'b5Display';
this.pages[0] = new LWWidget.Beta5.Player(this);
this.pages[1] = new LWWidget.Beta5.Planets(this);
this.pages[2] = new LWWidget.Beta5.Fleets(this);
this.pages[3] = new LWWidget.Beta5.Cash(this);
this.pages[4] = new LWWidget.Beta5.Techs(this);
this.pages[5] = new LWWidget.Beta5.Msg(this);
this.pages[6] = new LWWidget.Beta5.Forums(this);
this.pages[7] = new LWWidget.Beta5.Ticks(this);
this.setPage('player');
this.addSlot('updateServerTime');
this.stUpdate = new Base.Timer(1000, true);
this.stUpdate.bindEvent('Tick', 'updateServerTime', this);
this.stUpdate.start();
},
destroy: function () {
this.stUpdate.destroy();
this.base();
},
setData: function (data) {
this.base(data);
this.serverTime = parseInt(data.getAttribute('serverTime'), 10);
this.drawServerTime();
},
draw: function () {
var _e = document.getElementById('gDisplay');
if (!_e) {
return;
}
var _e2 = document.getElementById('b5Display');
if (!_e2) {
_e.style.overflow = 'visible';
_e.innerHTML = '<table style="width:98%;height:208px;margin:0% 1%;padding:0%;border:0">'
+ '<tr><td style="font-size:13px;color:white;height:16px;text-align:center" id="serverTime">&nbsp;</td></tr>'
+ '<tr><td style="font-size:13px;color:white"><div id="b5Display" style="overflow:auto;height:192px;width:100%">&nbsp;</div></td></tr>'
+ '</table>';
}
this.drawServerTime();
this.base();
},
updateServerTime: function () {
if (!this.serverTime) {
return;
}
this.serverTime ++;
this.drawServerTime();
},
drawServerTime: function (u) {
var _e = document.getElementById('serverTime');
if (!_e || !this.serverTime) {
return;
}
_e.innerHTML = LWWidget.Game.formatTime(this.serverTime);
}
});
// Register the version
LWWidget.Game.versions().put('beta5', LWWidget.Beta5);

View file

@ -1,17 +0,0 @@
LWWidget.Beta5.Cash = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Empire')[0].getChildren('Budget')[0];
this.income = parseInt(_d.getAttribute('income'), 10);
this.upkeep = parseInt(_d.getAttribute('upkeep'), 10);
this.profit = parseInt(_d.getAttribute('profit'), 10);
},
draw: function (_e) {
_e.innerHTML = '<p style="text-align:center"><br/><br/>Planetary income: <b>&euro;' + Base.Util.formatNumber(this.income)
+ '</b><br/><br/>Fleet upkeep: <b>&euro;' + Base.Util.formatNumber(this.upkeep)
+ '</b><br/><br/>Daily profit: <b>&euro;' + Base.Util.formatNumber(this.profit) + '</p>';
}
});

View file

@ -1,55 +0,0 @@
LWWidget.Beta5.Fleets = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Empire')[0].getChildren('Fleets')[0];
this.fleets = parseInt(_d.getAttribute('count'), 10);
if (this.fleets) {
// Fleets in battle
this.inBattle = parseInt(_d.getAttribute('inBattle'), 10);
// Total fleet power
this.power = parseInt(_d.getAttribute('power'), 10);
// Ships types
this.gaships = parseInt(_d.getAttribute('gaships'), 10);
this.fighters = parseInt(_d.getAttribute('fighters'), 10);
this.cruisers = parseInt(_d.getAttribute('cruisers'), 10);
this.bcruisers = parseInt(_d.getAttribute('bcruisers'), 10);
// Upkeep
_d = data.getChildren('Empire')[0].getChildren('Budget')[0];
this.upkeep = parseInt(_d.getAttribute('upkeep'), 10);
}
},
draw: function (_e) {
if (this.fleets == 0) {
_e.innerHTML = '<p style="text-align:center">No fleets</p>';
return;
}
var _s = '<p style="text-align:center"><b>' + Base.Util.formatNumber(this.fleets)
+ '</b> fleet' + (this.fleets > 1 ? 's' : '');
if (this.inBattle) {
_s += ' (<b>' + Base.Util.formatNumber(this.inBattle) + '</b> engaged in battle!)';
}
_s += '<br/><br/>Total fleet power: <b>' + Base.Util.formatNumber(this.power)
+ '</b><br/>Upkeep: <b>&euro;' + Base.Util.formatNumber(this.upkeep)
+ '</b><br/><br/><u>Ship types</u><br/>';
if (this.gaships) {
_s += 'G.A. ships: <b>' + Base.Util.formatNumber(this.gaships) + '</b><br/>';
}
if (this.fighters) {
_s += 'Fighters: <b>' + Base.Util.formatNumber(this.fighters) + '</b><br/>';
}
if (this.cruisers) {
_s += 'Cruisers: <b>' + Base.Util.formatNumber(this.cruisers) + '</b><br/>';
}
if (this.bcruisers) {
_s += 'Battle Cruisers: <b>' + Base.Util.formatNumber(this.bcruisers) + '</b><br/>';
}
_s += '</p>';
_e.innerHTML = _s;
}
});

View file

@ -1,125 +0,0 @@
LWWidget.Beta5.Forums = LWWidget.Game.Page.inherits({
switchMode: function () {
this.details = !this.details;
this.game.draw();
},
setData: function (data) {
var _f = data.getChildren('Communications')[0].getChildren('Forums')[0];
// Read general forums
var gf = _f.getChildren('GeneralForums'), gcats = new Base.Util.Hashtable();
for (var i in gf) {
var c = gf[i], desc = c.getChildren('Description')[0].getText(),
cf = c.getChildren('Forum'), forums = new Array();
for (var j in cf) {
forums.push([cf[j].getText(), parseInt(cf[j].getAttribute('topics'), 10), parseInt(cf[j].getAttribute('unread'), 10)]);
}
gcats.put(desc, forums);
}
// Read alliance forums
var af = _f.getChildren('AllianceForums'), aForums = new Array();
if (af.length) {
af = af[0].getChildren('Forum');
for (var i in af) {
aForums.push([af[i].getText(), parseInt(af[i].getAttribute('topics'), 10), parseInt(af[i].getAttribute('unread'), 10)]);
}
}
// Store data
this.general = gcats;
this.alliance = aForums;
},
show: function () {
this.details = false;
},
draw: function (_e) {
if (this.details) {
_e.innerHTML = this.getDetailedHTML();
} else {
_e.innerHTML = this.getShortHTML();
}
},
getShortHTML: function () {
var text = new Array(), gk = this.general.keys();
for (var i in gk) {
text.push(this.catSummary(gk[i], this.general.get(gk[i])));
}
if (this.alliance.length) {
text.push(this.catSummary('Alliance forums', this.alliance));
}
return '<p style="text-align:center">' + text.join('<br/>') + '<br/><br/><a href="#" onclick="Base.Comp.get('
+ this._cid + ').switchMode();return false">Show details</a>';
},
catSummary: function (name, list) {
var s = '<u>' + name + '</u>: ';
var unread = this.countUnread(list);
if (unread > 0) {
s += '<b>' + Base.Util.formatNumber(unread) + '</b> unread topic' + (unread > 1 ? 's' : '');
} else {
s += 'no unread topics';
}
return s;
},
countUnread: function (forums) {
var s = 0;
for (var i in forums) {
s += forums[i][2];
}
return s;
},
getDetailedHTML: function () {
var text = new Array(), gk = this.general.keys();
for (var i in gk) {
text.push(this.catDetailed(gk[i], this.general.get(gk[i])));
}
if (this.alliance.length) {
text.push(this.catDetailed('Alliance forums', this.alliance));
}
return '<p style="text-align:center"><a href="#" onclick="Base.Comp.get('
+ this._cid + ').switchMode();return false">Hide details</a><br/><br/>' + text.join('<br/><br/>');
},
catDetailed: function (name, forums) {
if (!forums.length) {
return "";
}
var text = new Array();
text.push('<b>' + name + '</b>');
for (var i in forums) {
var f = forums[i], s = '<u>' + f[0] + '</u>: ';
if (f[1]) {
s += '<b>' + Base.Util.formatNumber(f[1]) + '</b> topic' + (f[1] > 1 ? 's' : '');
if (f[2]) {
s += ' (<b>' + Base.Util.formatNumber(f[2]) + '</b> unread)';
}
} else {
s += 'empty forum';
}
text.push(s);
}
return text.join('<br/>');
}
});

View file

@ -1,71 +0,0 @@
LWWidget.Beta5.Msg = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Communications')[0].getChildren('Messages')[0];
// Get default folders
var _f = _d.getChildren('DefaultFolder');
for (var i in _f) {
var _a = [parseInt(_f[i].getAttribute('all'), 10), parseInt(_f[i].getAttribute('new'), 10)];
switch (_f[i].getAttribute('id')) {
case 'IN': this.inbox = _a; break;
case 'INT': this.internal = _a; break;
case 'OUT': this.outbox = _a; break;
}
}
// Get custom folders
this.custom = new Base.Util.Hashtable();
_f = _d.getChildren('CustomFolder');
for (var i in _f) {
this.custom.put(_f[i].getAttribute('id'), [parseInt(_f[i].getAttribute('all'), 10), parseInt(_f[i].getAttribute('new'), 10), _f[i].getText()]);
}
},
show: function () {
this.dCustom = false;
},
draw: function (_e) {
var _s = '<p style="text-align:center">';
_s += this.folderCode('Inbox', this.inbox[0], this.inbox[1]) + '<br/>';
_s += this.folderCode('Transmissions', this.internal[0], this.internal[1]) + '<br/>'
_s += this.folderCode('Sent messages', this.outbox[0], this.outbox[1]) + '<br/><br/>';
if (this.custom.isEmpty()) {
_s += 'No custom folders';
} else if (this.dCustom) {
_s += '<a href="#" onclick="Base.Comp.get(' + this._cid + ').switchCustom();return false">Hide custom folders</a><br/>';
var cf = this.custom.values();
for (var i in cf) {
_s += this.folderCode(cf[i][2], cf[i][0], cf[i][1]) + '<br/>';
}
} else {
_s += '<a href="#" onclick="Base.Comp.get(' + this._cid + ').switchCustom();return false">Display custom folders</a>';
}
_s += '</p>';
_e.innerHTML = _s;
},
folderCode: function (name, a, n) {
var _s = '<b>' + name + '</b>: ';
if (a) {
if (n) {
_s += '<b>' + Base.Util.formatNumber(n) + '</b> new message' + (n > 1 ? 's' : '');
} else {
_s += 'no new messages';
}
_s += ' (<b>' + Base.Util.formatNumber(a) + '</b> total)';
} else {
_s += 'no messages';
}
return _s;
},
switchCustom: function () {
this.dCustom = !this.dCustom;
this.game.draw();
}
});

View file

@ -1,86 +0,0 @@
LWWidget.Beta5.Planets = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Empire')[0].getChildren('Planets')[0];
this.planets = parseInt(_d.getAttribute('count'), 10);
this.pList = new Array();
if (this.planets) {
// Planets under attack
this.underAttack = parseInt(_d.getAttribute('siege'), 10);
// Happiness / Corruption
this.avgHappiness = parseInt(_d.getAttribute('avgHap'), 10);
this.avgCorruption = parseInt(_d.getAttribute('avgCor'), 10);
// Population
this.totPopulation = parseInt(_d.getAttribute('totPop'), 10);
this.avgPopulation = parseInt(_d.getAttribute('avgPop'), 10);
// Factories
this.totFactories = parseInt(_d.getAttribute('totFac'), 10);
this.avgFactories = parseInt(_d.getAttribute('avgFac'), 10);
// Factories
this.totTurrets = parseInt(_d.getAttribute('totTur'), 10);
this.avgTurrets = parseInt(_d.getAttribute('avgTur'), 10);
// Planet list
var _l = _d.getChildren('List')[0].getChildren('Planet');
for (var i in _l) {
this.pList.push(_l[i].getText());
}
}
},
show: function () {
this.mode = 0;
},
draw: function (_e) {
_e.innerHTML = (this.mode == 0 || !this.planets) ? this.getStats() : this.getList();
},
setMode: function (m) {
this.mode = m;
if (this.game) {
this.game.draw();
}
},
getStats: function () {
if (this.planets == 0) {
return '<p style="text-align:center">No planets.</p>';
}
var _s = '<p style="text-align:center"><b>' + Base.Util.formatNumber(this.planets) + '</b> planet'
+ (this.planets > 1 ? 's' : '') + '<br/>';
if (this.underAttack) {
_s += '<b>' + Base.Util.formatNumber(this.underAttack) + ' planet'
+ (this.underAttack > 1 ? 's' : '') + ' under attack!</b>';
} else {
_s += 'No planets under attack';
}
_s += '<br/><br/>Average happiness: <b>' + this.avgHappiness + '%</b><br/>Average corruption: <b>'
+ this.avgCorruption + '%</b><br/>Population: <b>' + Base.Util.formatNumber(this.totPopulation) + '</b>';
if (this.planets > 1) {
_s += ' (<b>' + Base.Util.formatNumber(this.avgPopulation) + '</b> on average)';
}
_s += '<br/>Factories: <b>' + Base.Util.formatNumber(this.totFactories) + '</b>';
if (this.planets > 1) {
_s += ' (<b>' + Base.Util.formatNumber(this.avgFactories) + '</b> on average)';
}
_s += '<br/>Turrets: <b>' + Base.Util.formatNumber(this.totTurrets) + '</b>';
if (this.planets > 1) {
_s += ' (<b>' + Base.Util.formatNumber(this.avgTurrets) + '</b> on average)';
}
_s += '<br/><br/><a href="#" onclick="Base.Comp.get(' + this._cid + ').setMode(1);return false">View list</a></p>';
return _s;
},
getList: function () {
return '<p style="text-align:center"><a href="#" onclick="Base.Comp.get(' + this._cid
+ ').setMode(0);return false">&lt;&lt;- Back</a><br/><br/><b>'
+ this.pList.join('</b><br/><b>') + '</b></p>';
}
});

View file

@ -1,82 +0,0 @@
LWWidget.Beta5.Player = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Player')[0];
// Player name and cash
this.playerName = _d.getAttribute('name');
this.cash = _d.getAttribute('cash');
// Alliance status
var _a = _d.getChildren('Alliance');
if (_a.length) {
_a = _a[0];
this.alliance = { joined: (_a.getAttribute('inalliance') == '1'), tag: _a.getAttribute('tag') };
} else {
this.alliance = null;
}
// General rankings
_a = _d.getChildren('Rankings')[0];
var _r = _a.getChildren('Ranking');
for (var i in _r) {
if (_r[i].getText() != 'General Ranking') {
continue;
}
this.points = _r[i].getAttribute('points');
this.rank = _r[i].getAttribute('rank');
break;
}
// Planets / planets under attack
_d = data.getChildren('Empire')[0].getChildren('Planets')[0];
this.planets = parseInt(_d.getAttribute('count'), 10);
this.underAttack = parseInt(_d.getAttribute('siege'), 10);
// Fleets / fleets in battle
_d = data.getChildren('Empire')[0].getChildren('Fleets')[0];
this.fleets = parseInt(_d.getAttribute('count'), 10);
this.inBattle = parseInt(_d.getAttribute('inBattle'), 10);
},
draw: function (_e) {
if (!this.playerName) {
return;
}
var str = '<p style="text-align:center">Player <b>' + this.playerName + '</b>';
if (this.alliance && this.alliance.joined) {
str += ' [<b>' + this.alliance.tag + '</b>]';
} else if (this.alliance && !this.alliance.joined) {
str += '<br/>Requesting to join alliance [<b>' + this.alliance.tag + '</b>]';
}
str += '<br/><br/>Cash: <b>&euro;' + Base.Util.formatNumber(this.cash) + '</b>'
+ '<br/>General ranking: <b>#' + Base.Util.formatNumber(this.rank) + '</b> (<b>'
+ Base.Util.formatNumber(this.points) + '</b> points)<br/><br/>';
if (this.planets == 0) {
str += "No planets";
} else {
str += '<b>' + Base.Util.formatNumber(this.planets) + '</b> planet' + (this.planets > 1 ? 's' : '');
if (this.underAttack > 0) {
str += ' (<b>' + Base.Util.formatNumber(this.underAttack) + '</b> under attack!)';
}
}
str += '<br/>';
if (this.fleets == 0) {
str += "No fleets";
} else {
str += '<b>' + Base.Util.formatNumber(this.fleets) + '</b> fleet' + (this.fleets > 1 ? 's' : '');
if (this.inBattle > 0) {
str += ' (<b>' + Base.Util.formatNumber(this.inBattle) + '</b> in battle)';
}
}
str += '</p>';
_e.innerHTML = str;
}
});

View file

@ -1,37 +0,0 @@
LWWidget.Beta5.Techs = LWWidget.Game.Page.inherits({
setData: function (data) {
var _d = data.getChildren('Empire')[0].getChildren('Research')[0];
this.points = parseInt(_d.getAttribute('points'), 10);
this.newTechs = parseInt(_d.getAttribute('new'), 10);
this.foreseen = parseInt(_d.getAttribute('foreseen'), 10);
_d = _d.getChildren('RBudget')[0];
this.fundamental = parseInt(_d.getAttribute('fundamental'), 10);
this.military = parseInt(_d.getAttribute('military'), 10);
this.civilian = parseInt(_d.getAttribute('civilian'), 10);
},
draw: function (_e) {
var _s = '<p style="text-align:center">';
if (this.newTechs == 0) {
_s += 'No new technologies discovered.';
} else {
_s += '<b>' + this.newTechs + '</b> new technolog' + (this.newTechs > 1 ? 'ies' : 'y') + ' discovered.';
}
_s += '<br/>';
if (this.foreseen == 0) {
_s += 'No breakthroughs foreseen.';
} else {
_s += '<b>' + this.foreseen + '</b> breakthrough' + (this.foreseen > 1 ? 's' : '') + ' foreseen.';
}
_s += '<br/><br/><u>Research budget</u><br/><br/><b>' + Base.Util.formatNumber(this.points) + '</b> research points per day<br/><b>'
+ this.fundamental + '%</b> allocated to Fundamental research<br/><b>'
+ this.military + '%</b> allocated to Military research<br/><b>'
+ this.civilian + '%</b> allocated to Civilian research</p>';
_e.innerHTML = _s;
}
});

View file

@ -1,121 +0,0 @@
LWWidget.Beta5.Ticks = LWWidget.Game.Page.inherits({
constructor: function (game) {
this.base(game);
this.addSlot('update');
this.timer = new Base.Timer(1000, true);
this.timer.bindEvent('Tick', 'update', this);
},
destroy: function () {
this.timer.destroy();
this.base();
},
setData: function (data) {
var tList = data.getChildren('Ticks')[0].getChildren('Tick'), ticks = new Array();
for (var i in tList) {
var tick = new Array();
tick[0] = tList[i].getText();
tick[1] = parseInt(tList[i].getAttribute('first'), 10);
tick[2] = parseInt(tList[i].getAttribute('interval'), 10);
var l = tList[i].getAttribute('last');
if (typeof l == 'string') {
tick[3] = parseInt(l, 10);
} else {
tick[3] = null;
}
ticks.push(tick);
}
this.tDiff = (new Date()).getTime() - (parseInt(data.getAttribute('serverTime'), 10) * 1000);
this.ticks = ticks;
},
show: function () {
this.timer.start();
},
hide: function () {
this.timer.stop();
},
draw: function (_e) {
var text = new Array();
for (var i in this.ticks) {
text.push('Next ' + this.ticks[i][0] + ': <span id="dtick' + i + '">&nbsp;</span>');
}
_e.innerHTML = '<p style="text-align:center">' + text.join('<br/>') + '</p>';
this.update();
},
update: function () {
this.computeNextTicks();
for (var i in this.ticks) {
var t;
if (typeof this.ticks[i][5] == 'number') {
var d, h, m, s;
h = this.ticks[i][5] % 86400; d = (this.ticks[i][5] - h) / 86400;
m = h % 3600; h = (h - m) / 3600;
s = m % 60; m = (m - s) / 60;
if (h < 10) { h = '0' + h; }
if (m < 10) { m = '0' + m; }
if (s < 10) { s = '0' + s; }
t = '<b>' + h + ':' + m + ':' + s + '</b>';
if (d > 0) {
t = '<b>' + d + '</b> day' + (d > 1 ? 's' : '') + ', ' + t;
}
} else {
t = 'never';
}
var e = document.getElementById('dtick' + i);
if (!e) {
break;
}
e.innerHTML = t;
}
},
computeNextTicks: function () {
var now = Math.round(((new Date()).getTime() - this.tDiff) / 1000);
for (var i in this.ticks) {
if (this.ticks[i][3] && now > this.ticks[i][3]) {
this.ticks[i][4] = null;
continue;
}
if (now <= this.ticks[i][1]) {
this.ticks[i][4] = this.ticks[i][1];
continue;
}
var d = now - this.ticks[i][1], m = (d - (d % this.ticks[i][2])) / this.ticks[i][2];
this.ticks[i][4] = this.ticks[i][1] + (m + 1) * this.ticks[i][2];
}
for (var i in this.ticks) {
if (typeof this.ticks[i][4] != 'number') {
this.ticks[i][5] = null;
} else {
this.ticks[i][5] = this.ticks[i][4] - now;
}
}
}
});

View file

@ -1,25 +0,0 @@
LWWidget.Data = Base.inherits({
constructor: function (name) {
this.base();
this.name = name;
this.attributes = new Base.Util.Hashtable();
},
setAttribute: function (name, value) {
this.attributes.put(name, value);
},
getAttribute: function (name) {
return (this.attributes.containsKey(name) ? this.attributes.get(name) : null);
},
getChildren: function (name) {
return new Array();
},
getText: function () {
return "";
}
});

View file

@ -1,12 +0,0 @@
LWWidget.Data.Leaf = LWWidget.Data.inherits({
constructor: function (name, text) {
this.base(name);
this.text = text;
},
getText: function () {
return this.text;
}
});

View file

@ -1,130 +0,0 @@
LWWidget.Data.Loader = Base.Comp.inherits({
constructor: function (login, password) {
this.base();
this.addEvent('CommError');
this.addEvent('FatalError');
this.addEvent('Kick');
this.addEvent('Load');
this.addEvent('LoginFailure');
this.addEvent('Maintenance');
this.addSlot('loaderDestroyed');
this.addSlot('dataReceived');
this.loader = new Base.XMLLoader('', true);
this.loader.bindEvent('Destroy', 'loaderDestroyed', this);
this.loader.bindEvent('NetworkError', 'onCommError', this);
this.loader.bindEvent('ServerError', 'onCommError', this);
this.loader.bindEvent('Timeout', 'onCommError', this);
this.loader.bindEvent('Unsupported', 'onCommError', this);
this.loader.bindEvent('Aborted', 'onCommError', this);
this.loader.bindEvent('Loaded', 'dataReceived', this);
this.params = new Base.Util.Hashtable();
this.params.put('__s', '1');
this.params.put('__l', login);
this.params.put('__p', password);
},
destroy: function () {
if (this.loader) {
this.loader.destroy();
}
this.base();
},
load: function (from) {
if (this.loader.isLoading) {
return false;
}
this.loader.changeParameters(LWWidget.base + '/index.php/' + from + '.xml');
this.loader.load(this.params);
},
loaderDestroyed: function () {
this.loader = null;
},
dataReceived: function (data) {
var _xml = Base.Util.parseXML(data);
if (!_xml) {
this.onCommError();
return;
}
var _doc = _xml.documentElement;
if (_doc.nodeName == 'Maintenance') {
var _r, _u, _c;
_r = LWWidget.Data.Loader.getXMLText(_doc, 'Reason');
_u = LWWidget.Data.Loader.getXMLText(_doc, 'Until');
_c = LWWidget.Data.Loader.getXMLText(_doc, 'Current');
this.onMaintenance(_r, _u, _c);
} else if (_doc.nodeName == 'FatalError') {
this.onFatalError(_doc.getAttribute('code'), LWWidget.Data.Loader.getXMLText(_doc, 'Text'));
} else if (_doc.nodeName == 'Kicked') {
this.onKick(LWWidget.Data.Loader.getXMLText(_doc, 'Reason'));
} else if (_doc.nodeName == 'Failed') {
this.onLoginFailure(_doc.getAttribute('code'));
} else {
var _data = LWWidget.Data.Loader.parse(_doc);
if (_data) {
this.onLoad(_data);
} else {
this.onCommError();
}
}
}
}, {
getXMLText: function (node, name) {
var _t = '';
for (var i=0;i<node.childNodes.length;i++) {
var _c = node.childNodes[i];
if (_c.nodeType == 1 && _c.nodeName == name) {
_t += _c.childNodes[0].nodeValue;
}
}
return _t;
},
parse: function (xmlNode) {
if (xmlNode.nodeType != 1 || xmlNode.nodeName != 'Node') {
return null;
}
var _in = (xmlNode.getAttribute('node') == '1'), _n;
if (_in) {
_n = new LWWidget.Data.Node(xmlNode.getAttribute('name'));
} else {
_n = new LWWidget.Data.Leaf(xmlNode.getAttribute('name'), LWWidget.Data.Loader.getXMLText(xmlNode, 'Text'));
}
for (var i=0;i<xmlNode.childNodes.length;i++) {
var _c = xmlNode.childNodes[i];
if (_c.nodeType != 1) {
continue;
}
if (_c.nodeName == 'Attr') {
var _t;
if (_c.childNodes.length) {
_t = _c.childNodes[0].nodeValue;
} else {
_t = '';
}
_n.setAttribute(_c.getAttribute('name'), _t);
} else if (_c.nodeName == 'Node' && _in) {
_n.addChild(this.parse(_c));
}
}
return _n;
}
});

View file

@ -1,25 +0,0 @@
LWWidget.Data.Node = LWWidget.Data.inherits({
constructor: function (name) {
this.base(name);
this.contents = new Array();
},
addChild: function (child) {
if (child instanceof LWWidget.Data.Node || child instanceof LWWidget.Data.Leaf) {
this.contents.push(child);
}
},
getChildren: function (name) {
var _c = new Array();
for (var i in this.contents) {
if (this.contents[i] && this.contents[i].name == name) {
_c.push(this.contents[i]);
}
}
return _c;
}
});

View file

@ -1,67 +0,0 @@
LWWidget.Debug = Base.Comp.inherits({
constructor: function () {
this.base();
this.addSlot('drawLog');
this.timer = new Base.Timer(1000, true);
this.timer.bindEvent('Tick', 'drawLog', this);
},
show: function () {
document.getElementById('debugLink').style.display = 'none';
document.getElementById('mainDiv').style.display = 'none';
this.lastLength = -1;
this.draw();
document.getElementById('debugDiv').style.display = 'block';
this.timer.start();
},
hide: function () {
this.timer.stop();
document.getElementById('debugDiv').style.display = 'none';
document.getElementById('debugLink').style.display = 'block';
document.getElementById('mainDiv').style.display = 'block';
},
draw: function () {
var _str = '<table id="debugTable"><tr id="dbgHdr"><td><b>Debug mode</b></td>'
+ '<td style="text-align:right"><a href="#" onclick="Base.Comp.get('
+ this._cid + ').clear()">Flush log</a> - <a href="#" onclick="Base.Comp.get('
+ this._cid + ').hide()">Hide</a></td></tr>'
+ '<tr><td colspan="2"><div style="overflow:auto;height:260px;width:296px;color:white" id="dbgContents">&nbsp;</div></td></tr></table>';
document.getElementById('debugDiv').innerHTML = _str;
this.drawLog();
},
clear: function () {
Base.Log.flush();
this.drawLog();
},
drawLog: function () {
var _e = document.getElementById('dbgContents');
if (!_e) {
return;
}
var _l = Base.Log.get();
if (_l.length == this.lastLength) {
return;
}
this.lastLength = _l.length;
var _s;
if (_l.length == 0) {
_s = '<p style="text-align:center">The log is empty</p>';
} else {
_s = '<p>';
for (var i=_l.length;i>0;i--) {
_s += '[' + i + '] ' + _l[i-1] + '<br/>';
}
_s += '</p>';
}
_e.innerHTML = _s;
}
});

View file

@ -1,168 +0,0 @@
LWWidget.Game = Base.Comp.inherits({
constructor: function (path) {
this.base();
this.path = path;
this.addEvent('RequestUpdate');
this.addSlot('startDataUpdate');
this.pageElement = 'gDisplay';
this.autoUpdate = new Base.Timer(30000, true);
this.autoUpdate.bindEvent('Tick', 'startDataUpdate', this);
this.autoUpdate.start();
this.pages = [null, null, null, null, null, null, null, null];
this.page = null;
this.data = null;
},
destroy: function () {
this.autoUpdate.destroy();
if (this.page) {
this.page.hide();
this.page = null;
}
for (var i in this.pages) {
if (this.pages[i]) {
var _p = this.pages[i];
this.pages[i] = null;
_p.destroy();
}
}
this.base();
},
startDataUpdate: function () {
this.onRequestUpdate(this.path);
},
setData: function (data) {
this.data = data;
for (var i in this.pages) {
if (this.pages[i]) {
this.pages[i].setData(data);
}
}
this.draw();
},
setPage: function (pName) {
// Check for a valid page name
if (!LWWidget.Game.pageMap().containsKey(pName)) {
return;
}
// Check if something was changed
var _p = this.pages[LWWidget.Game.pageMap().get(pName)];
if (_p && this.page && _p._cid == this.page._cid || !(_p || this.page)) {
return;
}
// Hide current page and show new page
if (this.page) {
this.page.hide();
}
this.page = _p;
if (_p) {
this.page.show();
}
this.draw();
},
draw: function () {
var _e = document.getElementById(this.pageElement);
if (_e) {
if (this.page) {
this.page.draw(_e);
} else {
_e.innerHTML = '<p style="text-align:center">Page not implemented</p>';
}
}
},
show: function () {
this.startDataUpdate();
this.autoUpdate.start();
if (this.page) {
this.page.show();
}
},
hide: function () {
this.autoUpdate.stop();
if (this.page) {
this.page.hide();
}
}
}, {
pageMapInst: null,
versionsInst: null,
pageMap: function () {
if (!LWWidget.Game.pageMapInst) {
var _h = new Base.Util.Hashtable();
_h.put('player', 0);
_h.put('planets', 1);
_h.put('fleets', 2);
_h.put('budget', 3);
_h.put('tech', 4);
_h.put('msg', 5);
_h.put('forums', 6);
_h.put('ticks', 7);
LWWidget.Game.pageMapInst = _h;
}
return LWWidget.Game.pageMapInst;
},
versions: function () {
if (!LWWidget.Game.versionsInst) {
LWWidget.Game.versionsInst = new Base.Util.Hashtable();
}
return LWWidget.Game.versionsInst;
},
formatTime: function (ts) {
var d = new Date(ts * 1000);
var str, s2;
s2 = d.getUTCHours().toString();
if (s2.length == 1) {
s2 = "0" + s2;
}
str = s2 + ':';
s2 = d.getUTCMinutes().toString();
if (s2.length == 1) {
s2 = "0" + s2;
}
str += s2 + ':';
s2 = d.getUTCSeconds().toString();
if (s2.length == 1) {
s2 = "0" + s2;
}
str += s2 + ' on ';
s2 = d.getUTCDate().toString();
if (s2.length == 1) {
s2 = "0" + s2;
}
str += s2 + '/';
s2 = (d.getUTCMonth() + 1).toString();
if (s2.length == 1) {
s2 = "0" + s2;
}
str += s2 + '/' + d.getUTCFullYear();
return str;
}
});

View file

@ -1,34 +0,0 @@
LWWidget.Game.Page = Base.Comp.inherits({
constructor: function (game) {
this.base();
this.addSlot('gameDestroyed');
this.game = game;
this.game.bindEvent('Destroy', 'gameDestroyed', this);
},
writeContents: function (contents) {
var e = document.getElementById('gDisplay');
if (e) {
e.innerHTML = contents;
}
},
gameDestroyed: function () {
this.game = null;
},
setData: function (data) {
},
draw: function (_e) {
},
show: function () {
},
hide: function () {
}
});

View file

@ -1,73 +0,0 @@
LWWidget.GameDisplay = LWWidget.Page.inherits({
constructor: function () {
this.base();
this.addSlot('gameDestroyed');
this.addEvent('Refresh');
this.gPath = '';
this.game = null;
},
destroy: function () {
if (this.game) {
this.game.destroy();
}
this.base();
},
setGame: function (gClass, gPath) {
if (this.game) {
this.game.destroy();
}
this.game = new gClass(gPath);
this.game.bindEvent('Destroy', 'gameDestroyed', this);
this.game.bindEvent('RequestUpdate', 'onRefresh', this);
},
gameDestroyed: function () {
this.game = null;
},
handleData: function (data) {
if (this.game) {
this.game.setData(data);
}
},
hide: function () {
if (this.game) {
this.game.hide();
}
},
show: function () {
if (this.game) {
this.game.show();
}
this.draw();
},
setPage: function (pName) {
if (this.game) {
this.game.setPage(pName);
}
},
draw: function () {
if (!document.getElementById('gDisplay')) {
this.writeContents('<div id="gDisplay" style="overflow:auto;width:100%;height:100%">&nbsp;</div>');
}
if (this.game) {
this.game.draw();
}
}
});

View file

@ -1,65 +0,0 @@
LWWidget.GameSelector = LWWidget.Page.inherits({
constructor: function () {
this.base();
this.games = [];
this.addEvent('Select');
},
setGames: function (games) {
if (games instanceof Array) {
this.games = games;
this.draw();
}
},
draw: function () {
var cc = '"return Base.Comp.get(' + this._cid + ').select()"',
st = ' style="color:white;font-size:13px;background-color:#3f7fff;width:100%" ',
st2 = ' style="color:white;font-size:13px;background-color:#3f7fff" ',
str = '<form name="gsel" onsubmit=' + cc + '><table class="table">'
+ '<tr><td colspan="2" style="text-align:center"><b>Game selection</b></td></tr>'
+ '<tr><td colspan="2">&nbsp;</td></tr>'
+ '<tr><td><label for="gsel">Game:</label></td>'
+ '<td><select name="gsel" id="gsel"' + st;
for (var i in this.games) {
var g = this.games[i];
str += '<option value="' + i + '">' + g.name + '</option>';
}
str += '</select></td></tr><tr><td style="text-align:right">'
+ '<input type="checkbox" name="grem" id="grem"' + st2 + '/></td>'
+ '<td><label for="grem">Remember selection</label></td></tr>'
+ '<tr><td colspan="2">&nbsp;</td></tr>'
+ '<tr><td colspan="2"><input type="submit" value="Select this game"'
+ st + '</td></tr></table></form>';
this.writeContents(str);
var _cb = document.getElementById('grem');
if (_cb) {
_cb.checked = (LWWidget.main.getPreference('lwRemGame') == '1');
}
},
select: function () {
var _s = document.getElementById('gsel');
if (!_s) {
return false;
}
var sv = parseInt(_s.options[_s.selectedIndex].value, 10), rem = document.getElementById('grem').checked;
LWWidget.main.setPreference('lwRemGame', rem ? '1' : '0');
if (rem) {
LWWidget.main.setPreference('lwGame', this.games[sv].path);
}
this.onSelect(this.games[sv]);
return false;
}
});

View file

@ -1,77 +0,0 @@
LWWidget.Login = LWWidget.Page.inherits({
constructor: function () {
this.base();
this.addEvent('Login');
this.error = "";
},
draw: function () {
var cc = '"return Base.Comp.get(' + this._cid + ').login()"',
st = ' style="color:white;font-size:13px;background-color:#3f7fff;width:100%" ',
st2 = ' style="color:white;font-size:13px;background-color:#3f7fff" ',
str = '<form name="login" onsubmit=' + cc + '><table class="table">'
+ '<tr><td><label for="lname">Username:</label></td><td>'
+ '<input type="text" name="lname" id="lname" value=""'
+ st + '/></td></tr>'
+ '<tr><td><label for="lpass">Password:</label></td><td>'
+ '<input type="password" name="lpass" id="lpass" value=""'
+ st + '/></td></tr>'
+ '<tr><td style="text-align:right"><input type="checkbox" '
+ ' name="lrem" id="lrem"' + st2 + '/></td><td>'
+ '<label for="lrem">Remember password</label></td></tr>'
+ '<tr><td colspan="2">&nbsp;</td></tr>'
+ '<tr><td colspan="2" style="text-align:center" id="lerror">&nbsp;</td></tr>'
+ '<tr><td colspan="2">&nbsp;</td></tr>'
+ '<tr><td colspan="2"><input type="submit" value="Connect to Legacy Worlds!"'
+ st + '</td></tr></table></form>';
this.writeContents(str);
this.fillForm();
},
fillForm: function () {
var l = LWWidget.main.getPreference('lwLogin'), p = LWWidget.main.getPreference('lwPassword'), r = LWWidget.main.getPreference('lwRemAuth');
if (!document.getElementById('lname')) {
return;
}
document.getElementById('lname').value = l;
document.getElementById('lpass').value = p;
document.getElementById('lrem').checked = (r == '1');
document.getElementById("lerror").innerHTML = (this.error == "") ? '&nbsp;' : this.error;
},
setError: function (error) {
this.error = error;
var e = document.getElementById("lerror");
if (e) {
e.innerHTML = (error == "") ? '&nbsp;' : error;
}
},
login: function () {
if (!document.getElementById('lname')) {
return false;
}
var l = document.getElementById('lname').value, p = document.getElementById('lpass').value,
r = document.getElementById('lrem').checked ? '1' : '0';
if (l == '') {
this.setError("Please type in your username");
} else if (p == '') {
this.setError("Please type in your password");
} else {
// Save the login as a preference and store the rest until we're sure
LWWidget.main.setPreference('lwLogin', l);
LWWidget.main.setPreference('lwRemAuth', r);
LWWidget.main.password = p;
this.onLogin();
}
return false;
}
});

View file

@ -1,392 +0,0 @@
LWWidget.Main = Base.Comp.inherits({
constructor: function () {
this.base();
this.addEvent('Show');
this.addEvent('Hide');
this.addSlot('draw');
this.bindEvent('Show', 'draw');
// Game-related slots
this.addSlot('login');
this.addSlot('loadGame');
this.addSlot('loadData');
// Version management slots
this.addSlot('versionError');
this.addSlot('versionNewAvailable');
this.addSlot('versionNewRequired');
this.addSlot('versionOk');
// Generate the menu
this.makeMenu();
// Version checker
this.versionCheck = new LWWidget.VersionCheck();
this.versionPage = new LWWidget.NewVersion();
this.versionCheck.bindEvent('CommError', 'versionError', this);
this.versionCheck.bindEvent('NewVersion', 'versionNewAvailable', this);
this.versionCheck.bindEvent('RequiredVersion', 'versionNewRequired', this);
this.versionCheck.bindEvent('VersionOk', 'versionOk', this);
this.versionChecked = false;
// Login page
this.loginPage = new LWWidget.Login();
this.loginPage.bindEvent('Login', 'login', this);
// Game selection page
this.gameSelector = new LWWidget.GameSelector();
this.gameSelector.bindEvent('Select', 'loadGame', this);
// Game display
this.gameDisplay = new LWWidget.GameDisplay(this);
this.gameDisplay.bindEvent('Refresh', 'loadData', this);
// Generic text display
this.textPage = new LWWidget.TextPage();
// FIXME: Set Dashboard-specific event handlers
// this.initDashboard();
// FIXME: should use saved password if possible
this.page = this.loginPage;
this.menu.setMode('out');
this.state = 0;
this.onShow(); // FIXME: use Dashboard events if possible
},
initDashboard: function () {
if (window.widget) {
var _cid = this._cid;
widget.onshow = function () {
if (Base) {
Base.Comp.get(_cid).onShow();
}
};
widget.onhide = function () {
if (Base) {
Base.Comp.get(_cid).onHide();
}
};
}
},
makeMenu: function () {
var _m;
this.menu = new LWWidget.Menu();
this.addSlot('menuCommand');
this.menu.bindEvent('Click', 'menuCommand', this);
// Waiting
_m = this.menu.newMode('wait');
_m.addItem(new LWWidget.Menu.Text('Loading ... Please wait ...'));
// New version available
_m = this.menu.newMode('nvAvail');
_m.addItem(new LWWidget.Menu.Text('New version! &nbsp; &nbsp; '));
_m.addItem(new LWWidget.Menu.Command('continue', 'Continue'));
_m.addItem(new LWWidget.Menu.Command('logout', 'Log out'));
// New version required
_m = this.menu.newMode('nvReq');
_m.addItem(new LWWidget.Menu.Text('Update required &nbsp; &nbsp; '));
_m.addItem(new LWWidget.Menu.Command('logout', 'Log out'));
// Logged out user
_m = this.menu.newMode('out');
_m.addItem(new LWWidget.Menu.Text('Please log in'));
// Game selection
_m = this.menu.newMode('game');
_m.addItem(new LWWidget.Menu.Entry('gamesel', 'Game selection'));
_m.addItem(new LWWidget.Menu.Command('logout', 'Log out'));
// Error
_m = this.menu.newMode('error');
_m.addItem(new LWWidget.Menu.Text('Error! - '));
_m.addItem(new LWWidget.Menu.Command('logout', 'Log out'));
// Standard
_m = this.menu.newMode('std');
_m.addItem(new LWWidget.Menu.Command('gamesel', 'Game selection'));
_m.addItem(new LWWidget.Menu.Entry('player', 'Player'));
_m.addItem(new LWWidget.Menu.Entry('planets', 'Planets'));
_m.addItem(new LWWidget.Menu.Entry('fleets', 'Fleets'));
_m.addItem(new LWWidget.Menu.Entry('budget', 'Budget'));
_m.addItem(new LWWidget.Menu.Entry('tech', 'Research'));
_m.addItem(new LWWidget.Menu.Entry('msg', 'Messages'));
_m.addItem(new LWWidget.Menu.Entry('forums', 'Forums'));
_m.addItem(new LWWidget.Menu.Entry('ticks', 'Ticks'));
_m.addItem(new LWWidget.Menu.Command('logout', 'Log out'));
},
initLoader: function (login, password) {
this.loader = new LWWidget.Data.Loader(LWWidget.main.getPreference('lwLogin'), LWWidget.main.password);
var events = ['CommError', 'FatalError', 'Kick', 'Load', 'LoginFailure', 'Maintenance', 'Destroy'];
var slots = ['commError', 'serverError', 'playerKicked', 'dataLoaded', 'loginFailed', 'serverMaintenance', 'loaderDestroyed'];
for (var i=0;i<events.length;i++) {
this.addSlot(slots[i]);
this.loader.bindEvent(events[i], slots[i], this);
}
},
draw: function () {
var c = LWWidget.main.getPreference('lwColour');
var str = '<img src="images/' + c + '.png" />'
+ '<div id="mainDiv"><table id="mainTable">'
+ '<tr><td id="mtTitle">Legacy Worlds</td></tr>'
+ '<tr><td id="mtMenu">&nbsp;</td></tr>'
+ '<tr><td id="mtContents">&nbsp;</td></tr>'
+ '</table></div>';
if (LWWidget.debug) {
str += '<div id="debugDiv">&nbsp;</div><div id="debugLink"><a href="#" onclick="LWWidget.main.showDebug();return false">Debug mode</a></div>';
}
Base.Browser.get().docBody.innerHTML = str;
this.menu.draw();
this.page.draw();
},
setTextPage: function (mMode, text) {
this.menu.setMode(mMode);
this.page = this.textPage;
this.page.setText(text);
},
menuCommand: function (command) {
if (command == 'logout') {
if (this.loader) {
this.loader.destroy();
}
if (this.versionCheck) {
this.versionCheck.stop();
}
if (this.state == 3) {
this.gameDisplay.hide();
}
this.state = 0;
this.versionChecked = false;
this.loginPage.setError('');
this.page = this.loginPage;
this.menu.setMode('out');
this.page.draw();
} else if (command == 'continue') {
this.login();
} else if (command == 'gamesel') {
if (this.state == 3) {
this.page.hide();
}
this.state = 1;
this.setTextPage('wait', 'Connecting to the Legacy Worlds server<br/><br/>Please wait');
this.loader.load('main/index');
} else if (this.state == 3) {
this.gameDisplay.setPage(command);
}
},
versionError: function () {
// Ignore the error if the version has already been checked
if (!this.versionChecked) {
this.commError();
}
},
versionNewAvailable: function (url) {
// Ignore the new version unless it is the first time we check
if (this.versionChecked) {
return;
}
this.versionChecked = true;
this.versionPage.setData(url, false);
this.page = this.versionPage;
this.menu.setMode('nvAvail');
this.page.draw();
},
versionNewRequired: function (url) {
if (this.state == 3) {
this.gameDisplay.hide();
}
this.versionCheck.stop();
this.versionPage.setData(url, true);
this.page = this.versionPage;
this.menu.setMode('nvReq');
this.page.draw();
},
versionOk: function () {
if (!this.versionChecked) {
// Continue login
this.versionChecked = true;
this.login();
}
},
login: function () {
this.setTextPage('wait', 'Connecting to the Legacy Worlds server<br/><br/>Please wait');
// If the version hasn't been checked, well, check it
if (!this.versionChecked) {
this.versionCheck.start();
return;
}
// Initialise the loader and get the game list
this.initLoader();
this.loader.load('main/index');
},
handleGameList: function (data, force) {
this.state = 1;
var games = new Array(), auto = null;
if (!force && LWWidget.main.getPreference('lwRemGame') == '1') {
auto = LWWidget.main.getPreference('lwGame');
}
for (var i in data.contents) {
// Check if version is supported
var _v = data.contents[i].getAttribute('version');
if (!LWWidget.Game.versions().containsKey(_v)) {
continue;
}
var _g = {
name: data.contents[i].getText(),
path: data.contents[i].getAttribute('path'),
version: LWWidget.Game.versions().get(_v)
};
if (auto && auto == _g.path) {
this.loadGame(_g);
return;
}
games.push(_g);
}
if (games.length == 0) {
this.setTextPage('error', 'It appears that you are not registered to any Legacy Worlds game.');
} else if (!force && games.length == 1) {
this.loadGame(games[0]);
} else {
this.page = this.gameSelector;
this.menu.setMode('game');
this.gameSelector.setGames(games);
}
},
loadGame: function (game) {
this.state = 2;
this.currentGame = game;
this.loader.load(game.path + '/play');
},
loadData: function (path) {
if (this.state == 3 && this.loader) {
this.loader.load(path + '/play');
}
},
commError: function () {
this.setTextPage('error', '<b>Communications error</b><br/><br/>The server could not be reached or it sent an invalid reply.');
},
serverError: function (code, text) {
var str = '<b>Server error</b><br/><br/>The server encountered an internal error:<br/><i>'
+ text + '</i><br/>(code: ' + code + ')';
this.setTextPage('error', str);
},
playerKicked: function (reason) {
var str = (reason == '' ? 'No reason was specified' : ('<b>Reason:</b> ' + reason));
if (this.state == 3) {
this.gameDisplay.hide();
}
this.setTextPage('error', 'You have been <b>kicked</b> from the game!<br/><br/>' + str);
},
loginFailed: function (code) {
switch (code) {
case '0':
if (this.state == 0) {
this.loader.destroy();
LWWidget.main.password = '';
this.loginPage.setError('Invalid username or password');
this.page = this.loginPage;
this.page.draw();
} else {
this.setTextPage('error', 'Your password has been changed.');
}
break;
case '1':
this.setTextPage('error', 'The server encountered an internal error while authenticating your account.');
break;
case '2':
this.setTextPage('error', 'Your account has been closed!');
break;
case '3':
this.setTextPage('error', 'Your account has not been validated yet, please check your e-mail.');
break;
case '4':
if (this.state < 2) {
this.setTextPage('error', 'The server just did something it\'s not supposed to do. Ever.');
} else {
this.gameDisplay.hide();
this.setTextPage('errsel', 'You are no longer registered to this game!');
}
break;
}
},
serverMaintenance: function (reason, until, now) {
var str = '<b>The server is undergoing maintenance.</b><br/><br/>Reason: ' + reason
+ '<br/><br/>It will be down until <b>' + until + '</b>.<br/>Current server time: ' + now;
this.setTextPage('error', str);
},
loaderDestroyed: function () {
this.loader = null;
},
dataLoaded: function (data) {
if (this.state == 0) {
// We were not loging in, save password if needed
if (LWWidget.main.getPreference('lwRemAuth') == '1') {
LWWidget.main.setPreference('lwPassword', LWWidget.main.password);
}
this.handleGameList(data);
} else if (this.state == 1) {
// We were logged in but asked to select a game
this.handleGameList(data, true);
} else if (this.state == 2) {
// We just received game data for the first time
this.gameDisplay.setGame(this.currentGame.version, this.currentGame.path);
this.gameDisplay.handleData(data);
this.page = this.gameDisplay;
this.menu.setMode('std');
this.menu.setSelected('player');
this.page.draw();
this.state = 3;
} else {
// Update game contents
this.gameDisplay.handleData(data);
}
}
});

View file

@ -1,81 +0,0 @@
LWWidget.Menu = Base.Comp.inherits({
constructor: function () {
this.base();
this.currentMode = null;
this.modes = new Base.Util.Hashtable();
this.addSlot('modeDestroyed');
this.addSlot('draw');
this.addEvent('Click');
this.bindEvent('Click', 'draw');
},
destroy: function () {
var modes = this.modes.values();
for (var i in modes) {
modes[i].destroy();
}
this.base();
},
newMode: function (name) {
if (this.modes.containsKey(name)) {
return null;
}
var mode = new LWWidget.Menu.Mode(name);
this.modes.put(name, mode);
if (!this.currentMode) {
this.currentMode = mode;
}
mode.bindEvent('Destroy', 'modeDestroyed', this);
mode.bindEvent('Click', 'onClick', this);
return mode;
},
setMode: function (name) {
if (!this.modes.containsKey(name) || this.currentMode && this.currentMode.name == name) {
return;
}
this.currentMode = this.modes.get(name);
this.draw();
},
setSelected: function (name) {
if (this.currentMode) {
this.currentMode.setSelected(name);
this.draw();
}
},
modeDestroyed: function (mode) {
if (!(mode && mode._cid && mode.name && this.modes.containsKey(mode.name))) {
return;
}
this.modes.remove(mode.name);
if (this.currentMode && this.currentMode._cid == mode._cid) {
var _v = this.modes.values();
if (_v.length) {
this.currentMode = _v[0];
} else {
this.currentMode = null;
}
}
},
draw: function () {
var e = document.getElementById('mtMenu');
if (!(e && this.currentMode)) {
return;
}
e.innerHTML = this.currentMode.draw();
}
});

View file

@ -1,7 +0,0 @@
LWWidget.Menu.Command = LWWidget.Menu.Item.inherits({
constructor: function (name, text) {
this.base(name, text, true, false, ' - ');
}
});

View file

@ -1,7 +0,0 @@
LWWidget.Menu.Entry = LWWidget.Menu.Item.inherits({
constructor: function (name, text) {
this.base(name, text, true, true, ' - ');
}
});

View file

@ -1,38 +0,0 @@
LWWidget.Menu.Item = Base.Comp.inherits({
constructor: function (name, text, clickable, selectable, separator) {
this.base();
this.name = name;
this.text = text;
this.clickable = !!clickable;
this.selectable = this.clickable && !!selectable;
this.separator = (typeof separator == 'string') ? separator : '';
this.selected = false;
this.addEvent('Click');
},
draw: function () {
var pfx, sfx;
if (this.clickable && !this.selected) {
pfx = '<a href="#" onclick="Base.Comp.get(' + this._cid + ').click();return false">';
sfx = '</a>';
} else if (this.selectable && this.selected) {
pfx = '<b>';
sfx = '</b>';
} else {
pfx = sfx = '';
}
return pfx + this.text + sfx;
},
click: function () {
if (this.selectable) {
this.selected = true;
}
this.onClick(this);
}
});

View file

@ -1,109 +0,0 @@
LWWidget.Menu.Mode = Base.Comp.inherits({
constructor: function (name) {
this.base();
this.name = name;
this.items = new Base.Util.Hashtable();
this.selected = null;
this.addSlot('itemDestroyed');
this.addSlot('itemClicked');
this.addEvent('Click');
},
destroy: function () {
var items = this.items.values();
for (var i in items) {
var _i = items[i];
this.items.remove(items[i]._cid);
items[i].destroy();
}
this.base();
},
draw: function () {
var str = '', items = this.items.values();
for (var i=0;i<items.length;i++) {
str += items[i].draw();
if (i < items.length - 1 && items[i].separator) {
str += items[i].separator;
}
}
return str;
},
addItem: function (item) {
if (!(item && item._cid) || this.items.containsKey(item._cid)) {
return;
}
this.items.put(item._cid, item);
if (item.selectable && !this.selected) {
item.selected = true;
this.selected = item;
} else {
item.selected = false;
}
item.bindEvent('Destroy', 'itemDestroyed', this);
item.bindEvent('Click', 'itemClicked', this);
},
setSelected: function (name) {
var _k = this.items.values();
for (var i in _k) {
var item = _k[i];
if (item.selectable && item.name == name) {
if (this.selected) {
if (this.selected._cid == item._cid) {
return;
}
this.selected.selected = false;
}
item.selected = true;
this.selected = item;
return;
} else if (item.name == name) {
return;
}
}
},
itemClicked: function (item) {
if (item.selectable) {
if (this.selected) {
this.selected.selected = false;
}
item.selected = true;
this.selected = item;
}
this.onClick(item.name);
},
itemDestroyed: function (item) {
if (!(item && item._cid && this.items.containsKey(item._cid))) {
return;
}
this.items.remove(item._cid);
if (this.selected && this.selected._cid == item._cid) {
var _v = this.items.values(), _s = null;
for (var i in _v) {
var _i = _v[i];
if (_i.selectable) {
_s = _i;
_i.selected = true;
break;
}
}
this.selected = _s;
}
}
});

View file

@ -1,7 +0,0 @@
LWWidget.Menu.Text = LWWidget.Menu.Item.inherits({
constructor: function (text) {
this.base('', text);
}
});

View file

@ -1,33 +0,0 @@
LWWidget.NewVersion = LWWidget.Page.inherits({
setData: function (url, required) {
this.url = url;
this.required = required;
},
draw: function () {
var _s;
if (this.required) {
_s = 'Due to server updates, you are required to download a new version of this widget in order to keep using it.';
} else {
_s = 'A new version of the LegacyWorlds widget is available!<br/><br/>'
+ 'Upgrading the widget is not mandatory; the new version only brings new features and bugfixes.';
}
_s += '<br/><br/><a href="#" onclick="Base.Comp.get(' + this._cid + ').startDownload();return false">Download the new version</a>';
this.writeContents(_s);
},
startDownload: function () {
if (window.widget) {
widget.openURL(this.url);
} else {
window.open(this.url);
}
}
});

View file

@ -1,17 +0,0 @@
LWWidget.Page = Base.Comp.inherits({
constructor: function () {
this.base();
this.addEvent('Show');
this.addEvent('Hide');
},
writeContents: function (contents) {
var e = document.getElementById('mtContents');
if (e) {
e.innerHTML = contents;
}
}
});

View file

@ -1,18 +0,0 @@
LWWidget.TextPage = LWWidget.Page.inherits({
constructor: function () {
this.text = "";
},
setText: function (text) {
if (this.text != text) {
this.text = text;
}
this.draw();
},
draw: function () {
this.writeContents(this.text == "" ? '&nbsp;' : this.text);
}
});

View file

@ -1,101 +0,0 @@
LWWidget.VersionCheck = Base.Comp.inherits({
constructor: function () {
this.base();
this.addEvent('CommError');
this.addEvent('NewVersion');
this.addEvent('RequiredVersion');
this.addEvent('VersionOk');
this.addSlot('dataReceived');
this.addSlot('loaderDestroyed');
this.addSlot('timerDestroyed');
this.loader = new Base.XMLLoader(LWWidget.base + '/index.php/main/macwidget.xml', false);
this.loader.bindEvent('Destroy', 'loaderDestroyed', this);
this.loader.bindEvent('NetworkError', 'onCommError', this);
this.loader.bindEvent('ServerError', 'onCommError', this);
this.loader.bindEvent('Timeout', 'onCommError', this);
this.loader.bindEvent('Unsupported', 'onCommError', this);
this.loader.bindEvent('Aborted', 'onCommError', this);
this.loader.bindEvent('Loaded', 'dataReceived', this);
this.timer = new Base.Timer(300000, true);
this.timer.bindEvent('Tick', 'load', this.loader);
this.timer.bindEvent('Destroy', 'timerDestroyed', this);
this.knownVersion = LWWidget.version;
},
destroy: function () {
if (this.loader) {
this.loader.destroy();
}
if (this.timer) {
this.timer.destroy();
}
this.base();
},
timerDestroyed: function () {
this.timer = null;
},
loaderDestroyed: function () {
this.loader = null;
},
start: function () {
if (typeof this.requiredVersion != 'undefined' && LWWidget.version < this.requiredVersion) {
return;
}
this.timer.start();
this.loader.load();
},
stop: function () {
this.timer.stop();
this.knownVersion = LWWidget.version;
delete this.latestVersion;
delete this.requiredVersion;
},
dataReceived: function (data) {
var _xml = Base.Util.parseXML(data);
if (!_xml) {
this.onCommError();
return;
}
var _doc = _xml.documentElement;
this.latestVersion = parseInt(_doc.getAttribute('latest'), 10);
this.requiredVersion = parseInt(_doc.getAttribute('oldestOk'), 10);
this.url = _doc.childNodes[0].nodeValue;
if (this.knownVersion == this.latestVersion && this.requiredVersion <= LWWidget.version) {
this.onVersionOk();
return;
}
Base.Log.write('Version check: current version = ' + LWWidget.version);
Base.Log.write('Version check: latest received version = ' + this.knownVersion);
Base.Log.write('Version check: latest version = ' + this.latestVersion);
Base.Log.write('Version check: oldest accepted version = ' + this.requiredVersion);
this.knownVersion = this.latestVersion;
if (LWWidget.version < this.requiredVersion) {
this.onRequiredVersion(this.url);
this.timer.stop();
} else if (LWWidget.version < this.latestVersion) {
this.onNewVersion(this.url);
} else {
this.onVersionOk();
}
}
});

View file

@ -1,2 +0,0 @@
LWWidget.Versions = new Base.Util.Hashtable();
LWWidget.Versions.put('beta5', LWWidget.Beta5);

View file

@ -4,18 +4,12 @@
// engine instance // engine instance
$config = array( $config = array(
// Database connection parameters
"dbhost" => "localhost",
"dbuser" => "legacy",
"dbpass" => "",
"dbname" => "legacy",
// Path and URL to static contents // Path and URL to static contents
"staticdir" => dirname(__FILE__) . "/../site/static", "staticdir" => __DIR__ . "/../site/static",
"staticurl" => "http://www.legacyworlds.com/static", "staticurl" => "http://localhost/static",
// Path to game scripts // Path to game scripts
"scriptdir" => dirname(__FILE__), "scriptdir" => __DIR__,
// Path to the cache // Path to the cache
"cachedir" => "/tmp/lwcache", "cachedir" => "/tmp/lwcache",
@ -33,11 +27,6 @@ $config = array(
), ),
*/ */
// Mac widget version numbers and location
"latestWidget" => 1,
"oldestWidget" => 1,
"widgetURL" => "http://www.legacyworlds.com/downloads/LegacyWorlds-Dashboard-latest.zip",
// Version numbers to make us feel good // Version numbers to make us feel good
"v_engine" => "0.85a", "v_engine" => "0.85a",
"v_game" => "Beta 5", "v_game" => "Beta 5",

View file

@ -150,14 +150,6 @@ class main_ticks_deathofrats_library {
l::debug("Analysing " . count($this->connections) . " new record(s)"); l::debug("Analysing " . count($this->connections) . " new record(s)");
$this->makePerAccountRecords(); $this->makePerAccountRecords();
// Start with open proxies
l::debug("Checking for open proxies ...");
$this->checkOpenProxies();
if ($this->proxiedAccounts) {
l::info("Logging " . count($this->proxiedAccounts) . " account(s) using open proxies");
$this->db->safeTransaction(array($this, 'logOpenProxies'));
}
// Now examine per-account entries to find different types of rats // Now examine per-account entries to find different types of rats
l::debug("Checking single player badness"); l::debug("Checking single player badness");
foreach ($this->perAccount as $records) { foreach ($this->perAccount as $records) {
@ -660,111 +652,6 @@ class main_ticks_deathofrats_library {
} }
/***********************************************************************
* OPEN PROXIES *
***********************************************************************/
/** This method checks for open proxies in the latest log entries.
*/
private function checkOpenProxies() {
$IPs = array();
// Make lists of accounts for each IP
foreach ($this->connections as $record) {
if ($record['ip_addr'] == 'AUTO' || $record['action'] == 'OUT') {
continue;
}
$ip = $record['ip_addr'];
$account = $record['account'];
if (!is_array($IPs[$ip])) {
$IPs[$ip] = array($account);
} elseif (!in_array($account, $IPs[$ip])) {
array_push($IPs[$ip], $account);
}
}
// Check for proxies on the IPs
$requests = array();
$proxies = array();
foreach (array_keys($IPs) as $ip) {
if (count($requests) < 20) {
array_push($requests, $ip);
continue;
}
try {
$results = pcheck::check($requests);
} catch (Exception $e) {
l::error("Failed to check some addresses for open proxies");
l::info($e->getMessage());
return;
}
foreach ($results as $host => $status) {
if ($status == 1) {
array_push($proxies, $host);
}
}
$requests = array();
}
// If there are some requests we didn't execute, do it
if (count($requests)) {
try {
$results = pcheck::check($requests);
} catch (Exception $e) {
l::error("Failed to check some addresses for open proxies");
l::info($e->getMessage());
return;
}
foreach ($results as $host => $status) {
if ($status == 1) {
array_push($proxies, $host);
}
}
}
// Check for proxied accounts
$proxyAccounts = array();
foreach ($proxies as $ip) {
foreach ($IPs[$ip] as $account) {
if (in_array($account, $proxyAccounts)) {
continue;
}
array_push($proxyAccounts, $account);
}
}
$this->proxiedAccounts = $proxyAccounts;
}
/** This method logs access to accounts using open proxies. A log
* entry is only added every 24h.
*/
public function logOpenProxies() {
// Get all recent open proxy logs
$this->db->query(
"SELECT account FROM dor_single "
. "WHERE message = 'PROXY' AND {$this->now} - ts < 86400"
);
$recent = array();
while ($r = dbFetchArray($q)) {
$recent[] = $r[0];
}
// Insert proxy logs
foreach ($this->proxiedAccounts as $account) {
if (in_array($account, $recent)) {
continue;
}
$this->singlePlayerLog("PROXY", $account);
}
}
/*********************************************************************** /***********************************************************************
* SINGLE PLAYER SUSPICIOUS BEHAVIOUR * * SINGLE PLAYER SUSPICIOUS BEHAVIOUR *
***********************************************************************/ ***********************************************************************/

View file

@ -15,17 +15,6 @@
<!-- Planet generator script --> <!-- Planet generator script -->
<Param name="pgenreq" value="/tmp/pgen" /> <Param name="pgenreq" value="/tmp/pgen" />
<!-- MacOS Dashboard widget -->
<Param name="latestWidget" value="1" />
<Param name="oldestWidget" value="1" />
<Param name="widgetURL" value="http://www.legacyworlds.com/downloads/LegacyWorlds-Dashboard-latest.zip" />
<!-- Proxy detector -->
<Param name="pcheck_server" value="www.legacyworlds.com" />
<Param name="pcheck_path" value="/index.php/main/pcheck" />
<Param name="pcheck_timeout" value="3" />
<Param name="pcheck_threads" value="20" />
</MainParams> </MainParams>
<!-- This part configures the general ticks that are not related to a <!-- This part configures the general ticks that are not related to a

View file

@ -1,104 +0,0 @@
<?php
//-----------------------------------------------------------------------
// LegacyWorlds Beta 5
// Game libraries
//
// lib/pcheck.inc
//
// This library allows access to the proxy detector.
//
// Copyright(C) 2004-2008, DeepClone Development
//-----------------------------------------------------------------------
class pcheck {
private static $queue = null;
private static $pid = null;
public static function isRunning() {
$fName = config::$main['cs_path'] . "/proxyDetector.pid";
if (!file_exists($fName)) {
return false;
}
$file = fopen($fName, "r");
$line = rtrim(fgets($file));
fclose($file);
list($pid, $time) = explode(" ", $line);
if (time() - $time > 22) {
return false;
}
return $pid;
}
private static function getQueue() {
if (! is_null(self::$queue)) {
return;
}
$key = ftok(config::$main['scriptdir'] . "/lib/pcheck_manager.inc", "C");
if ($key == -1) {
throw new Exception("Could not create the control queue's key");
}
self::$queue = @msg_get_queue($key);
if (self::$queue === FALSE) {
self::$queue = null;
throw new Exception("Could not access the control queue (using key $key)");
}
self::$pid = posix_getpid();
}
private static function sendRequest($addresses) {
array_unshift($addresses, self::$pid);
if (!@msg_send(self::$queue, 1, $addresses, true, false)) {
throw new Exception("Error while sending request");
}
}
private static function getResults() {
$wait = 30;
do {
$success = @msg_receive(self::$queue, self::$pid, $type, 32768, $result,
true, MSG_IPC_NOWAIT, $error);
if (!$success && $error != MSG_ENOMSG) {
throw new Exception("Error while waiting for results");
} elseif ($success) {
if (is_array($result)) {
return $result;
} elseif ($result == 'PING') {
$wait = 30;
} else {
throw new Exception("Invalid message received");
}
} else {
sleep(1);
}
$wait --;
} while ($wait);
throw new Exception("Timeout while waiting for results");
}
public static function check($addresses, $force = false) {
if (!($force || self::isRunning())) {
throw new Exception("The detector doesn't seem to be running");
}
self::getQueue();
self::sendRequest($addresses);
return self::getResults();
}
}
?>

View file

@ -1,629 +0,0 @@
<?php
//-----------------------------------------------------------------------
// LegacyWorlds Beta 5
// Game libraries
//
// lib/pcheck_manager.inc
//
// This library contains the code of the open proxy detector's main
// thread.
//
// Copyright(C) 2004-2008, DeepClone Development
//-----------------------------------------------------------------------
declare(ticks = 1); // PHP stupidity
class pcheck_manager {
/** This property indicates how many of the threads are free.
*/
private $nFree;
/** These properties are accessed by the detection threads to
* read their parameters.
*/
public static $timeout;
public static $requests;
/** This property points to the only current instance of the
* proxy detector.
*/
private static $instance = null;
/** This property indicates whether the manager is being run in
* debugging mode.
*/
private $debug;
/** This property contains the objects corresponding to each thread.
*/
private $threads = array();
/** This property is set to true when the manager is shutting down.
*/
private $ending = false;
/** Ports to scan on.
*/
static private $ports = array(
80, 81, 1075, 3128, 4480, 5490, 6588, 7033, 8000,
8080, 8081, 8085, 8090, 8095, 8100, 8105, 8110
);
/** This method sends commands to the FIFO controller. If the manager
* is being run in debugging mode, the commands are not sent.
*/
private static function sendToControl($command) {
if (self::$instance->debug) {
return;
}
$pipe = fopen(config::$main['cs_fifo'], "w");
fwrite($pipe, "$command\n");
fclose($pipe);
}
/** This method is called by the error manager in case a fatal error
* prevents the manager from functionning properly.
*/
public static function fatalError($errno, $errorText, $information) {
$instance->shutdown();
exit(1);
}
/** The constructor forks, initialises the message queues, starts
* the detector threads then calls waitForInstructions(). It never
* returns.
*/
public function __construct($debug) {
self::$instance = $this;
$this->debug = $debug;
$this->backgroundProcess();
$this->initMessageQueues();
$this->initSignals();
$this->initData();
$this->initThreads();
$this->initCache();
// Sends our PID to the controller
self::sendToControl("PCPID " . ($this->pid = posix_getpid()));
l::notice("Proxy detector initialised");
l::debug("Timeout: " . self::$timeout . "s; threads: " . count($this->threads));
l::debug("Using URL {$this->url}");
$this->mainLoop();
$this->shutdown();
exit(0);
}
/** This method initialises the manager's signal handlers.
*/
private function initSignals() {
pcntl_signal(SIGTERM, array($this, "terminateHandler"));
pcntl_signal(SIGINT, array($this, "terminateHandler"));
pcntl_signal(SIGCHLD, array($this, "threadEndHandler"));
}
/** This method handles the TERM and INT signals, which both cause
* a clean shutdown.
*/
public function terminateHandler($signo) {
if (! $this->mustEnd) {
l::notice("Main thread terminating on SIG" . ($signo == SIGTERM ? "TERM" : "INT"));
$this->mustEnd = true;
}
}
/** This method handles SIGCHLD and takes appropriate measures if
* it has been caused by an error.
*/
public function threadEndHandler($signo) {
// Wait for the child processes and stores their IDs
$ended = array();
do {
$pid = pcntl_waitpid(-1, $status, WNOHANG);
if ($pid > 0) {
$ended[$pid] = $status;
}
} while ($pid > 0);
foreach ($this->threads as $thread) {
if (array_key_exists($thread->pid, $ended)) {
$thread->ended = true;
}
}
if ($this->ending) {
l::trace("Threads have ended: " . join(', ', array_keys($ended)));
} else {
l::notice("Some children have met an untimely end! Terminating.");
$this->mustEnd = true;
}
}
/** This method causes the proxy checked to be run in the background.
*/
private function backgroundProcess() {
if ($this->debug) {
return;
}
// Fork to the background
$pid = pcntl_fork();
if ($pid == -1) {
l::crit("The open proxy detector failed to start.");
exit(1);
} elseif ($pid) {
exit(0);
}
posix_setsid();
}
/** This method initialises the message queues: a first queue to be
* used as a control channel and on which requests will be received,
* and a second queue to communicate with the threads.
*/
private function initMessageQueues() {
// Create the control queue's key
$ctrlKey = ftok(config::$main['scriptdir'] . "/lib/pcheck_manager.inc", "C");
if ($ctrlKey == -1) {
l::crit("Could not create the control queue's key");
exit(1);
}
// Create the thread queue's key
$thrdKey = ftok(config::$main['scriptdir'] . "/lib/pcheck_manager.inc", "T");
if ($ctrlKey == -1) {
l::crit("Could not create the thread queue's key");
exit(1);
}
// Create the control queue
$ctrlQueue = msg_get_queue($ctrlKey, 0666 | IPC_CREAT);
if ($ctrlQueue === FALSE) {
l::crit("Could not create the control queue (using key $ctrlKey)");
exit(1);
}
// Create the thread queue
$thrdQueue = msg_get_queue($thrdKey, 0600 | IPC_CREAT);
if ($thrdQueue === FALSE) {
l::crit("Could not create the thread queue (using key $thrdKey)");
@msg_remove_queue($ctrlQueue);
exit(1);
}
$this->control = $ctrlQueue;
$this->threadQueue = $thrdQueue;
}
/** This method destroys the queues.
*/
private function destroyMsgQueues() {
@msg_remove_queue($this->control);
@msg_remove_queue($this->threadQueue);
}
/** This method initialises the data used by the proxy detector
* threads.
*/
private function initData() {
$serv = config::getParam('pcheck_server');
$this->url = "http://$serv" . config::getParam('pcheck_path');
$timeout = (int) config::getParam('pcheck_timeout');
self::$requests = array(
"GET" => "GET {$this->url}?k=__key__ HTTP/1.0\r\n"
. "Host: $serv\r\n"
. "Cache-Control: no-cache\r\n"
. "Pragma: no-cache\r\n"
. "User-Agent: OpenCheck 1.0\r\n"
. "\r\n",
"POST" => "POST {$this->url} HTTP/1.0\r\n"
. "Host: $serv\r\n"
. "Cache-Control: no-cache\r\n"
. "Pragma: no-cache\r\n"
. "User-Agent: OpenCheck 1.0\r\n"
. "Content-Length: 34\r\n"
. "\r\n"
. "k=__key__\r\n"
);
self::$timeout = $timeout;
}
/** This method initialises all threads.
*/
private function initThreads() {
$nThreads = (int) config::getParam('pcheck_threads');
for ($i = 0; $i < $nThreads; $i ++) {
try {
$thread = new pcheck_thread($this->threadQueue);
} catch (Exception $e) {
l::crit("Thread " . ($i + 1) . " failed to initialise, exiting!");
$this->shutdown();
exit(1);
}
array_push($this->threads, $thread);
}
$this->nFree = $nThreads;
}
/** This method shuts down the manager.
*/
private function shutdown() {
$this->ending = true;
// Kill threads
foreach ($this->threads as $thread) {
$thread->send(array("type" => "QUIT"));
}
// Wait until all threads have ended
do {
$endOk = true;
foreach ($this->threads as $thread) {
if (! $thread->ended) {
$endOk = false;
sleep(1);
break;
}
}
} while (!$endOk);
// Destroy message queues
$this->destroyMsgQueues();
}
/** This method contains the manager's main loop, which handles everything
* from receiving requests and sending results to managing the detection
* threads.
*/
private function mainLoop() {
$this->requests = array();
$this->reqHostsFound = array();
$this->jobsQueue = array();
$this->jobsData = array();
$ticker = 0;
while (!$this->mustEnd) {
// Check for incoming requests
$success = msg_receive($this->control, 1, $type, 32768,
$message, true, MSG_IPC_NOWAIT, $error);
if (!$success && $error != MSG_ENOMSG) {
l::error("Manager failed to receive from control queue");
break;
} elseif ($success) {
$this->requestReceived(array_shift($message), $message);
continue;
}
// Check for incoming results from the detection threads
$success = msg_receive($this->threadQueue, 1, $type, 32768,
$message, true, MSG_IPC_NOWAIT, $error);
if (!$success && $error != MSG_ENOMSG) {
l::error("Manager failed to receive from thread queue");
break;
} elseif ($success) {
// A result has been received
$this->resultReceived(array_shift($message), $message);
continue;
}
sleep(1);
$ticker ++;
// For each request in progress, send a message every 10 ticks
// to signal the process we're not dead yet
if ($ticker % 10 == 0 && count($this->requests)) {
$this->sendPing();
}
// Send PID to controller every 20 ticks
if ($ticker == 20) {
$ticker = 0;
self::sendToControl("PCPID {$this->pid}");
$this->flushCache();
}
}
}
/** This method handles the reception of a new request.
*/
private function requestReceived($fromPID, $hosts) {
l::debug("Request received from $fromPID");
$now = time();
$this->requests[$fromPID] = array();
$this->reqHostsFound[$fromPID] = 0;
foreach ($hosts as $host) {
if (is_array($this->cache[$host]) && $now - $this->cache[$host]['last'] < 86400) {
// Cached entry found, store result
$this->requests[$fromPID][$host] = $this->cache[$host]['status'];
$this->reqHostsFound[$fromPID] ++;
continue;
}
// No cached entry found
$this->requests[$fromPID][$host] = -2;
if (is_array($this->jobsData[$host])) {
// We're already trying to detect this host
continue;
}
// This host needs to be detected
$this->addToJobsQueue($host);
}
if ($this->reqHostsFound[$fromPID] == count($this->requests[$fromPID])) {
// The request could be satisfied directly from cached data
$this->sendResponse($fromPID);
}
}
/** This method stores the results of a scan performed by one of the
* detection threads.
*/
private function resultReceived($fromThread, $result) {
list($host, $found) = $result;
// If a proxy was detected, log it
if ($found) {
l::info("Found open proxy at $host on port $port");
}
// Store the results
$this->jobsData[$host][1] |= $found;
$this->jobsData[$host][0] --;
if ($this->jobsData[$host][0] == 0) {
$this->hostFinished($host);
}
// Increase amount of free threads, set the thread as free
$this->nFree ++;
foreach ($this->threads as $thread) {
if ($thread->pid == $fromThread) {
$thread->free = true;
break;
}
}
// Shift the jobs queue
$this->moveQueue();
}
/** This method adds the jobs required to scan a host to the queue.
*/
private function addToJobsQueue($host) {
l::trace("Adding host $host to the queue...");
$this->jobsData[$host] = array(count(self::$ports), false);
foreach (self::$ports as $port) {
array_push($this->jobsQueue, array($host, $port));
}
$this->moveQueue();
}
/** This method returns the response to a request through the queue.
*/
private function sendResponse($requestPID) {
$request = $this->requests[$requestPID];
$nRequests = array();
$nReqHF = array();
foreach ($this->requests as $id => $data) {
if ($id != $requestPID) {
$nRequests[$id] = $data;
$nReqHF[$id] = $this->reqHostsFound[$id];
}
}
$this->reqHostsFound = $nReqHF;
$this->requests = $nRequests;
l::debug("Sending response to process #$requestPID");
msg_send($this->control, $requestPID, $request, true);
}
/** This method sends a "ping" packet to all waiting processes.
*/
private function sendPing() {
l::trace("Pinging processes");
foreach (array_keys($this->requests) as $id) {
msg_send($this->control, $id, "PING", true);
}
}
/** This method is called when the processing of a host
* is complete.
*/
private function hostFinished($host) {
l::trace("Host scanning finished for $host");
$result = $this->jobsData[$host][1];
// Remove the entry from jobsData
$nData = array();
foreach ($this->jobsData as $h => $d) {
if ($h != $host) {
$nData[$h] = $d;
}
}
$this->jobsData = $nData;
// Store result in cache
$this->storeCache($host, $result);
// Check all requests that contained this host
$checkRequests = array();
foreach (array_keys($this->requests) as $request) {
if (array_key_exists($host, $this->requests[$request])) {
$this->reqHostsFound[$request] ++;
$this->requests[$request][$host] = $result ? 1 : 0;
array_push($checkRequests, $request);
}
}
// For each request that contained the host, check if it's completed
$finished = array();
foreach ($checkRequests as $request) {
if ($this->reqHostsFound[$request] == count($this->requests[$request])) {
array_push($finished, $request);
}
}
// Send responses to completed requests
foreach ($finished as $request) {
$this->sendResponse($request);
}
}
/** This method sends free threads a scanning order if the
* jobs queue isn't empty.
*/
private function moveQueue() {
while ($this->nFree > 0 && count($this->jobsQueue)) {
$job = array_shift($this->jobsQueue);
foreach ($this->threads as $thread) {
if ($thread->free) {
l::trace("Assigning port {$job[1]} at {$job[0]} to thread {$thread->pid}");
$this->nFree --;
$thread->free = false;
$thread->send(array(
"type" => "SCAN",
"scan" => $job
));
break;
}
}
}
}
/** This method stores the result of a scan in the cache.
*/
private function storeCache($host, $result) {
$this->cache[$host] = array(
"status" => $result ? 1 : 0,
"last" => time()
);
$this->cacheModified = time();
}
/** This method reads the cache from the database.
*/
private function initCache() {
$this->cacheModified = 0;
$this->cache = array();
$success = false;
do {
try {
$db = db::connect();
$db->enableExceptions();
$db->query("LOCK TABLE proxy_detector IN ACCESS EXCLUSIVE MODE");
$cacheRead = new db_copy("proxy_detector");
$cacheRead->setAccessor($db);
$cacheRead->execute();
$db->end();
$db->close();
$db->disableExceptions();
$success = true;
} catch (Exception $e) {
l::notice("Could not read cache from database. Will retry in 20 seconds.");
l::info($e->getMessage());
if (!is_null($db)) {
l::trace("Closing database connection");
$db->close();
$db->disableExceptions();
}
sleep(20);
}
} while (! $success);
for ($i = 0; $i < $cacheRead->rows(); $i ++) {
$row = $cacheRead->getRow($i);
$this->cache[$row[0]] = array(
"last" => $row[1],
"status" => $row[2] == 't' ? 1 : 0
);
}
}
/** This method tries to store the cache's contents in the
* database.
*/
private function flushCache() {
if (! $this->cacheModified || time() - $this->cacheModified < 20) {
return;
}
l::debug("Flushing cache to database");
$db = null;
try {
$db = db::connect();
$db->enableExceptions();
$db->query("LOCK TABLE proxy_detector IN ACCESS EXCLUSIVE MODE");
$toWrite = $this->formatCache();
$toWrite->setAccessor($db);
$toWrite->execute();
$db->end();
$db->close();
$db->disableExceptions();
} catch (Exception $e) {
l::notice("Could not write cache to database.");
l::info($e->getMessage());
if (!is_null($db)) {
l::trace("Closing database connection");
$db->close();
$db->disableExceptions();
}
return;
}
$this->cacheModified = 0;
}
/** This method prepares the cache for copy into the database.
*/
private function formatCache() {
$cache = new db_copy("proxy_detector", db_copy::copyToClean);
$now = time();
foreach ($this->cache as $host => $data) {
if ($now - $data['last'] > 3 * 86400) {
continue;
}
$cache->appendRow(array($host, $data['last'], $data['status'] ? 't' : 'f'));
}
return $cache;
}
}
?>

View file

@ -1,144 +0,0 @@
<?php
//-----------------------------------------------------------------------
// LegacyWorlds Beta 5
// Game libraries
//
// lib/pcheck_thread.inc
//
// This library contains the code of the open proxy detector's scanning
// threads.
//
// Copyright(C) 2004-2008, DeepClone Development
//-----------------------------------------------------------------------
class pcheck_thread {
/** The process ID of the thread.
*/
public $pid;
/** The message queue the thread is bound to. Undefined in the
* parent process.
*/
private $queue;
/** This property indicates that the thread has ended.
*/
public $ended = false;
/** The constructor forks (throwing an exception on failure), then
* depending on whether it is in the parent process or in the child,
* returns or enters the instruction loop.
*/
public function __construct($queue) {
$pid = @pcntl_fork();
if ($pid == -1) {
throw new Exception("Unable to fork");
}
if ($pid != 0) {
// In the parent, store the child's PID and get going.
$this->pid = $pid;
$this->free = true;
$this->queue = $queue;
return;
}
// In the child, store our PID and the queue, then starts
// waiting for instructions.
$this->pid = posix_getpid();
$this->queue = $queue;
$this->waitLoop();
}
/** This method is called by the manager to send messages to the
* threads.
*/
public function send($message) {
return $this->ended ? false : msg_send($this->queue, $this->pid, $message, true);
}
/** This method implements the instruction loop.
*/
private function waitLoop() {
$quit = false;
$error = false;
do {
$success = msg_receive($this->queue, $this->pid, $type, 32768, $message, true);
if (! $success) {
l::error("Child failed to receive a message");
$quit = $error = true;
} elseif ($message['type'] == 'QUIT') {
$quit = true;
} elseif ($message['type'] == 'SCAN') {
list($host, $port) = $message['scan'];
$found = $this->executeCheck($host, $port, "GET")
|| $this->executeCheck($host, $port, "POST");
if (!msg_send($this->queue, 1, array($this->pid, $host, $found), true)) {
l::error("Child failed to send message");
$quit = $error = true;
}
} else {
l::notice("Unknown message {$message['type']} received");
}
} while (!$quit);
exit($error ? 1 : 0);
}
/** This method will try to check one port for open proxy software, using
* a specific method (POST or GET).
*/
private function executeCheck($ipAddress, $port, $method) {
$key = md5(uniqid(rand()));
// Open the socket
$socket = @fsockopen("tcp://$ipAddress", $port, $errno, $errstr, pcheck_manager::$timeout);
if ($socket === FALSE) {
return false;
}
// Make sure I/O doesn't timeout
stream_set_timeout($socket, pcheck_manager::$timeout);
// Send the request
$result = @fwrite($socket, preg_replace('/__key__/', $key, pcheck_manager::$requests[$method]));
if ($result !== FALSE) {
$info = stream_get_meta_data($socket);
if ($info['timed_out']) {
$result = false;
}
}
// Get the page
if ($result !== FALSE) {
$result = @fread($socket, 4096);
}
if ($result !== FALSE) {
$info = stream_get_meta_data($socket);
if ($info['timed_out']) {
$result = false;
}
}
// Close the socket
@fclose($socket);
if ($result === FALSE) {
return false;
}
return preg_match("/Key is \\<$key\\>/", $result);
}
}
?>

View file

@ -1,67 +0,0 @@
<?php
//-----------------------------------------------------------------------
// LegacyWorlds Beta 5
// Game libraries
//
// proxycheck.php
//
// This is the main script for the proxy detector.
//
// Copyright(C) 2004-2008, DeepClone Development
//-----------------------------------------------------------------------
/* Checks for fork() */
if (!(function_exists('pcntl_fork') || $__runFromAdmin)) {
die("This script may not be called from the web server.\n");
}
/* Load the required libraries */
$__loader = array(
'log', 'classloader',
'version', 'game', 'tick', 'config',
'db_connection', 'db_accessor', 'db_copy',
'pcheck_thread', 'pcheck_manager', 'pcheck'
);
require_once("loader.inc");
l::setSyslogPrefix("lwProxy");
if (count($argv) > 1) {
/* Checks for command line arguments */
if (count($argv) > 2 && ($argv[1] == '-c' || $argv[1] == '-f')) {
$addresses = $argv;
array_shift($addresses);
array_shift($addresses);
print "Running manual check, please wait ...\n";
try {
$results = pcheck::check($addresses, $argv[1] == '-f');
} catch (Exception $e) {
print "{$argv[0]}: " . $e->getMessage() . "\n";
exit(1);
}
foreach ($results as $address => $proxy) {
print "\t$address - ";
switch ($proxy) {
case -1: print "detection failed"; break;
case 0: print "no proxy detected"; break;
case 1: print "OPEN PROXY DETECTED!"; break;
}
print "\n";
}
exit(0);
} elseif ($argv[1] != "-d") {
die("Syntax: {$argv[0]}\n\t -> to run as a daemon\n\t{$argv[0]} -d\n\t -> to run in debugging mode\n\t{$argv[0]} -c ip [ip [...]]\n\t -> to check addresses for open proxies\n\t{$argv[0]} -f ip [ip [...]]\n\t -> same as -c, but doesn't check for a running server\n");
}
}
/* Starts the main thread */
@posix_setgid(33);
new pcheck_manager($argv[1] == "-d");
?>

View file

@ -1,18 +0,0 @@
<?php
class page_handler {
var $engines = array('xml');
function xml($input) {
$data = new data_leaf('MacWidget', config::getParam('widgetURL'));
$data->setAttribute('latest', config::getParam('latestWidget'));
$data->setAttribute('oldestOk', config::getParam('oldestWidget'));
return $data;
}
}
?>

View file

@ -1,18 +0,0 @@
<?php
class page_handler {
public $engines = array('page');
public $noTracking = true;
public function handle($input) {
$key = strtolower($input['k']);
if (!$key || strlen($key) != 32 || preg_match('/[^a-z0-9]/', $key)) {
$this->data = "X";
} else {
$this->data = "Key is $key";
}
$this->output = "pcheck";
}
}
?>

View file

@ -33,7 +33,7 @@ class page_layout {
} }
public function header($pg, $lg) { public function header($pg, $lg) {
if ($pg == "ppipn" || $pg == "pcheck") { if ($pg == "ppipn") {
return; return;
} }
@ -53,7 +53,7 @@ class page_layout {
} }
public function footer($pg, $lg) { public function footer($pg, $lg) {
if ($pg == "ppipn" || $pg == "pcheck") { if ($pg == "ppipn") {
echo $this->pageContents; echo $this->pageContents;
return; return;
} }

View file

@ -21,7 +21,7 @@ $__loader = array(
'log', 'classloader', 'log', 'classloader',
'version', 'game', 'tick', 'config', 'version', 'game', 'tick', 'config',
'db_connection', 'db_accessor', 'db_copy', 'db', 'db_connection', 'db_accessor', 'db_copy', 'db',
'pcheck', 'library', 'tick_manager', 'library', 'tick_manager',
); );
require_once("loader.inc"); require_once("loader.inc");