Branch oldpackages for 14.07
[14.07/packages.git] / net / wiviz / files / www / wiviz / wiviz.js
1 /*
2 This file is part of Wi-viz (http://wiviz.natetrue.com).
3
4 Wi-viz is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License v2 as published by
6 the Free Software Foundation.
7
8 Wi-viz is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with Wi-viz; if not, write to the Free Software
15 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16 */
17 var mv = 353;
18 var stupid = eval('window.attachEvent') ? 1 : 0;
19 var hosts;
20 var idle_timeout = 20;
21 var erase_timeout = 35;
22 var skew_x = 0; skew_y = 0;
23 var listening = 1;
24 var wiviz_cgi_url = "/cgi-bin/wiviz/get.cgi";
25
26 //What? You mean the POSIX thread API hasn't been ported to Javascript?  Bugger.
27 function scan_thread() {
28         var loc = document.getElementById('wivizGetFrame').contentWindow.location;
29         if (!listening) return;
30         if (loc.href != wiviz_cgi_url) {
31                 loc.replace(wiviz_cgi_url);
32         }
33         else {
34                 loc.reload(true);
35         }
36         setTimeout("scan_thread()", 5000);
37 }
38
39 function toggleListen() {
40         statusel = document.getElementById('status');
41         statusbutton = document.getElementById('togglelisten');
42         listening = 1 - listening;
43         if (listening) {
44             statusel.innerHTML = "Monitoring";
45             statusbutton.value = "Stop monitoring";
46             document.getElementById('content').innerHTML = '';
47             scan_thread();
48         }
49         else {
50             statusel.innerHTML = "Stopped";
51             statusbutton.value = "Start monitoring";
52         }
53 }
54
55 function channelSet() {
56         channelset = document.getElementById('channelsel').value;
57         if (channelset == 'hop') {
58             document.getElementById('hopoptions').style.display = 'inline';
59         }
60         else {
61             document.getElementById('hopoptions').style.display = 'none';
62             if (channelset != 'nochange') document.forms[0].submit();
63         }
64 }
65
66 function mousenter(e) {
67         if (stupid) e = event;
68         el = stupid ? e.srcElement : e.currentTarget;
69         el.parentNode.parentNode.className = 'hostdiv_hov';
70         el.nextSibling.nextSibling.nextSibling.style.visibility = 'visible';
71 }
72
73 function mouseout(e) {
74         if (stupid) e = event;
75         el = stupid ? e.srcElement : e.currentTarget;
76         el.parentNode.parentNode.className = 'hostdiv';
77         el.nextSibling.nextSibling.nextSibling.style.visibility = 'hidden';
78 }
79
80 function generate_mnemonic(hash) {
81         c = new Array('b','c','d','f','g','h','j','k','l','m','n','p','qu','r','s',
82                 't','v','w','y','z','th','ch','sh','cc','rr');
83         v = new Array('a','e','i','o','u','ae','ai','ao','au','eo','ei','eu','iu','oa','oe');
84         var i, a;
85         var p = hash & 1;
86         var n = '';
87         for (i = 0; i < 4; i++) {
88                 a = p ? c : v;
89                 n += a[hash % a.length];
90                 hash += a.length << 3 + a.length / 2;
91                 hash *= hash;
92           p = 1 - p;
93         }
94         return n;
95 }
96
97 function mkhash(mac) {
98         var     macarr = mac.split(/:/);
99   var hash = 0;
100                 for (j = 0; j < 6; j++) {
101                         hash += parseInt(macarr[j]) * j << j;
102                         hash += 11;
103                 }
104         if (hash < 0) hash = -hash;
105         return hash;
106 }
107
108 function wiviz_callback(mhosts, cfgstring) {
109         var nh = '';
110         hosts = mhosts;
111         for (i = 0; i < hosts.length; i++) {
112           hs = hosts[i];
113           if (hs.length == 0) break;
114     hs.mac = hs[0];
115     hs.rssi = hs[1];
116     hs.desc = hs[2];
117     hs.descarr = hs.desc.split(/-/)
118     hs.age = hs[3];
119                 hs.hash = mkhash(hs.mac);
120     hs.mnem = generate_mnemonic(hs.hash)
121     hs.name = hs.mnem;
122     el = document.getElementById(hs.mnem);
123     if (el) {
124       if (hs.age > erase_timeout) {
125         el.parentNode.removeChild(el);
126         continue;
127       }
128         el.innerHTML = genHTML(hs);
129     }
130     else {
131       if (hs.age > erase_timeout) continue;
132                         hs.x = Math.sin(hs.hash / mv) * hs.rssi * 2 - 67;
133                         hs.y = Math.cos(hs.hash / mv) * hs.rssi * 2;
134                         nh += "<div class='hostdiv' id='" + hs.mnem + "' style='top: ";
135                         nh += parseInt(hs.y) + "px; left: " + parseInt(hs.x) + "px'>";
136                   nh += genHTML(hs) + "</div>";
137     }
138         }
139         document.getElementById('content').innerHTML += nh;
140         
141         cfgarr = cfgstring.split(/-/);
142         if (cfgarr[1]) {
143             if (cfgarr[1] == 'hopping') cfgarr[1] = 'hop';
144             document.getElementById('channelsel').value = cfgarr[1];
145             if (cfgarr[1] == 'hop') channelSet();
146         }
147         
148         //repip();
149         setTimeout("declump(); repip();", 250);
150 }
151
152 function repip() {
153   var nh = "";
154   if (!hosts) return;
155         for (i = 0; i < hosts.length; i++) {
156           hs = hosts[i];
157           if (hs.length == 0) break;
158     mac = hs[0];
159     rssi = hs[1];
160     desc = hs[2].split(/-/);
161                 if (desc[0] == 'sta' && desc[1] == 'assoc') {
162                         bss = desc[2];
163                         hs.apmnem = generate_mnemonic(mkhash(bss));
164                         ap = document.getElementById(hs.apmnem);
165                         sta = document.getElementById(hs.mnem);
166                         if (ap && sta) {
167                           x = parseInt(sta.style.left);
168                           y = parseInt(sta.style.top);
169                           dx = parseInt(ap.style.left) - x;
170                           dy = parseInt(ap.style.top) - y;
171                           x += 67;
172                           y += 10;
173                           d = Math.sqrt(dx*dx+dy*dy);
174                           for (j = 0; j < d; j += 15) {
175                             nh += "<img src='"
176                                           + ((hs.age < idle_timeout) ? "pip" : "pip-idle")
177                                           + (stupid ? ".gif" : ".png")
178                                                 + "' class='pip' style='top:"
179                               + parseInt(y+dy * j / d) + "; left:"
180                               + parseInt(x+dx * j / d) + "'>";
181                           }
182                         }
183                 }
184         }
185         document.getElementById('pips').innerHTML = nh;
186 }
187
188 function declump() {
189         var c = 0;
190         var top = 30000,left = 30000,right = -30000,bottom = -30000;
191         for (i = 0; i < hosts.length; i++) {
192           for (j = 0; j < hosts.length; j++) {
193             if (i == j) continue;
194                         e1 = document.getElementById(hosts[i].mnem);
195                         e2 = document.getElementById(hosts[j].mnem);
196                         if (!e1 || !e2) continue;
197                         x1 = parseInt(e1.style.left);
198                         x2 = parseInt(e2.style.left);
199                         y1 = parseInt(e1.style.top);
200                         y2 = parseInt(e2.style.top);
201                         if (x1 < left) left = x1;
202                         if (y1 < top) top = y1;
203                         if (x1 > right) right = x1;
204                         if (y1 > bottom) bottom = y1;
205                         ox = x2;
206                         oy = y2;
207                         dist = Math.sqrt(Math.pow((x1-x2), 2) + Math.pow((y1-y2), 2));
208                         if (dist == 0) {
209                             x2 += Math.random() * 5;
210                                 y2 += Math.random() * 5;
211                                 dist = 10;
212                         }
213                         if (dist < 100) {
214                                 cx = (x1-x2) * 5 / (dist / 3);
215                                 cy = (y1-y2) * 5 / (dist / 3);
216                                 x2 -= cx;
217                                 y2 -= cy;
218                                 }
219                         if (hosts[j].apmnem == hosts[i].mnem
220                                         || hosts[i].apmnem == hosts[j].mnem) {
221                           cx = (x1-x2) * 5 / (dist / 3);
222                           cy = (y1-y2) * 5 / (dist / 3);
223                                 if (dist > 150) {
224                                   x2 += cx;
225                                   y2 += cy;
226                                 }
227                         }
228                         if (Math.abs(ox-x2) > 2 || Math.abs(oy-y2) > 2) {
229                                 e2.style.left = parseInt(x2);
230                                 e2.style.top = parseInt(y2);
231                                 c++;
232                         }
233           }
234         }
235         if (top < bottom && left < right) {
236           document.getElementById('debug').innerHTML = left + "," + right + "," + top + "," +bottom;
237           document.getElementById('content').style.left =
238                 document.getElementById('pips').style.left =
239                          -(right - left) / 2 - left - 67;
240           document.getElementById('content').style.top =
241           document.getElementById('pips').style.top =
242                          -(bottom - top) / 2 - top - 25;
243         }
244         repip();
245         if (c) setTimeout("declump()", 100);
246 }
247
248 function genHTML(hs) {
249         var nh = '';
250   nh += "<center><img class='icon' src='"
251         a = hs.descarr;
252         if (a[0] == 'ap' || a[0] == 'adhoc') {
253           if (a[0] == 'ap') {
254                         nh += "ap";
255                         if (a[5] == 'enc') nh += "-wep";
256           }
257           else {
258             nh += "adhoc";
259           }
260                 hs.channel = a[2];
261                 hs.name = a[4];
262         }
263         else if (a[0] == 'sta') {
264                 nh += "station";
265                 hs.channel = 0;
266         }
267         nh += (hs.age < idle_timeout) ? "": "-idle";
268         nh += stupid ? ".gif" : ".png";
269         nh += "' onmouseover='mousenter(event)' onmouseout='mouseout(event)'"
270                 + "><br><span class='hostdesc'>" + hs.mac + "<br><i>'" + hs.name;
271         nh += "'</i>";
272         if (hs.channel) {
273           nh += " ch" + hs.channel;
274         }
275         nh += "</span><span class='extrafo'><br>";
276         if (a[0] == 'ap') nh += "Access point";
277         if (a[0] == 'sta') nh += "Station";
278         if (a[0] == 'adhoc') nh += "Logical ad-hoc entity";
279         if (a[0] == 'ap' || a[0] == 'adhoc') {
280                 nh += "<br>";
281                 if (a[5] == '?enc') nh += "Encryption unknown";
282                 if (a[5] == 'enc') nh += "Encrypted";
283                 if (a[5] == 'unenc') nh += "Unencrypted";
284                 if (a[6] == 'wep') nh += "-WEP";
285                 if (a[6] == 'wpa') nh += "-WPA";
286         }
287         nh += "<br>RSSI: " + hs.rssi + " dBm<br>"
288                 + "Seen " + hs.age + " seconds ago<br>";
289         nh += "</span></center>";
290         return nh;
291 }