Project

General

Profile

Download (15 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2
/*
3
	graph.php
4 6afa3a82 Scott Ullrich
	part of m0n0wall (http://m0n0.ch/wall)
5 2c5fda82 Jose Luis Duran
6 ce77a9c4 Phil Davis
	Copyright (C) 2013-2015 Electric Sheep Fencing, LP
7 985a897f Scott Ullrich
	Copyright (C) 2004-2006 T. Lechat <dev@lechat.org>, Manuel Kasper <mk@neon1.net>
8 6afa3a82 Scott Ullrich
	and Jonathan Watt <jwatt@jwatt.org>.
9 5b237745 Scott Ullrich
	All rights reserved.
10 2c5fda82 Jose Luis Duran
11 5b237745 Scott Ullrich
	Redistribution and use in source and binary forms, with or without
12
	modification, are permitted provided that the following conditions are met:
13 2c5fda82 Jose Luis Duran
14 5b237745 Scott Ullrich
	1. Redistributions of source code must retain the above copyright notice,
15
	   this list of conditions and the following disclaimer.
16 2c5fda82 Jose Luis Duran
17 5b237745 Scott Ullrich
	2. Redistributions in binary form must reproduce the above copyright
18
	   notice, this list of conditions and the following disclaimer in the
19
	   documentation and/or other materials provided with the distribution.
20 2c5fda82 Jose Luis Duran
21 5b237745 Scott Ullrich
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
23
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
25
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30
	POSSIBILITY OF SUCH DAMAGE.
31
*/
32 7ac5a4cb Scott Ullrich
/*
33
	pfSense_MODULE:	graph
34
*/
35 5b237745 Scott Ullrich
36 6b07c15a Matthew Grooms
##|+PRIV
37
##|*IDENT=page-diagnostics-interfacetraffic
38
##|*NAME=Diagnostics: Interface Traffic page
39
##|*DESCR=Allow access to the 'Diagnostics: Interface Traffic' page.
40
##|*MATCH=graph.php*
41
##|-PRIV
42
43 12e437a2 Scott Ullrich
require("globals.inc");
44 8b379e47 Scott Ullrich
require("guiconfig.inc");
45 beb54c8f Scott Ullrich
46 45581172 Ermal Luçi
header("Last-Modified: " . gmdate( "D, j M Y H:i:s" ) . " GMT" );
47
header("Expires: " . gmdate( "D, j M Y H:i:s", time() ) . " GMT" );
48 2ebbb0bc Jose Luis Duran
header("Cache-Control: no-cache, no-store, must-revalidate" ); // HTTP/1.1
49 45581172 Ermal Luçi
header("Pragma: no-cache"); // HTTP/1.0
50 6afa3a82 Scott Ullrich
header("Content-type: image/svg+xml");
51 5b237745 Scott Ullrich
52
/********** HTTP GET Based Conf ***********/
53 6afa3a82 Scott Ullrich
$ifnum=@$_GET["ifnum"];  // BSD / SNMP interface name / number
54 ce2078f7 Scott Ullrich
$ifnum = get_real_interface($ifnum);
55 6afa3a82 Scott Ullrich
$ifname=@$_GET["ifname"]?$_GET["ifname"]:"Interface $ifnum";  //Interface name that will be showed on top right of graph
56 5b237745 Scott Ullrich
57
/********* Other conf *******/
58 41b1ff89 Phil Davis
if (isset($config["widgets"]["trafficgraphs"]["scale_type"])) {
59 0c8fb222 dwayne voelker
	$scale_type = $config["widgets"]["trafficgraphs"]["scale_type"];
60 41b1ff89 Phil Davis
} else {
61 0c8fb222 dwayne voelker
	$scale_type = "up";
62 41b1ff89 Phil Davis
}
63 0c8fb222 dwayne voelker
64 6afa3a82 Scott Ullrich
$nb_plot=120;                   //NB plot in graph
65 41b1ff89 Phil Davis
if ($_GET["timeint"]) {
66 358cb12c Scott Dale
	$time_interval = $_GET["timeint"];		//Refresh time Interval
67 41b1ff89 Phil Davis
} else {
68 920e60b5 Scott Ullrich
	$time_interval = 3;
69 41b1ff89 Phil Davis
}
70 0543e1e9 Scott Ullrich
71 41b1ff89 Phil Davis
if ($_GET["initdelay"]) {
72 9228de6c jim-p
	$init_delay = $_GET["initdelay"];		//Initial Delay
73 41b1ff89 Phil Davis
} else {
74 9228de6c jim-p
	$init_delay = 3;
75 41b1ff89 Phil Davis
}
76 9228de6c jim-p
77 6afa3a82 Scott Ullrich
//SVG attributes
78
$attribs['axis']='fill="black" stroke="black"';
79 a85f75c2 Scott Ullrich
$attribs['in']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
80
$attribs['out']='fill="#000000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="7"';
81
$attribs['graph_in']='fill="none" stroke="#FF0000" stroke-opacity="0.8"';
82
$attribs['graph_out']='fill="none" stroke="#000000" stroke-opacity="0.8"';
83 6afa3a82 Scott Ullrich
$attribs['legend']='fill="black" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
84 a85f75c2 Scott Ullrich
$attribs['graphname']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="8"';
85 6afa3a82 Scott Ullrich
$attribs['grid_txt']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="6"';
86
$attribs['grid']='stroke="gray" stroke-opacity="0.5"';
87 a85f75c2 Scott Ullrich
$attribs['switch_unit']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
88
$attribs['switch_scale']='fill="#FF0000" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4" text-decoration="underline"';
89 6afa3a82 Scott Ullrich
$attribs['error']='fill="blue" font-family="Arial" font-size="4"';
90
$attribs['collect_initial']='fill="gray" font-family="Tahoma, Verdana, Arial, Helvetica, sans-serif" font-size="4"';
91 5b237745 Scott Ullrich
92
//Error text if we cannot fetch data : depends on which method is used
93 8625c24f Scott Ullrich
$error_text = "Cannot get data about interface " . htmlspecialchars($ifnum);
94 5b237745 Scott Ullrich
95 6afa3a82 Scott Ullrich
$height=100;            //SVG internal height : do not modify
96
$width=200;             //SVG internal width : do not modify
97 5b237745 Scott Ullrich
98 8625c24f Scott Ullrich
$fetch_link = "ifstats.php?if=" . htmlspecialchars($ifnum);
99 72d1b575 Scott Ullrich
100
/* check for custom theme colors */
101 41b1ff89 Phil Davis
if (file_exists("/usr/local/www/themes/{$g['theme']}/graph.php")) {
102 72d1b575 Scott Ullrich
	$themetxt = file_get_contents("/usr/local/www/themes/{$g['theme']}/graph.php");
103
	eval($themetxt);
104 2c5fda82 Jose Luis Duran
}
105 72d1b575 Scott Ullrich
106 5b237745 Scott Ullrich
/********* Graph DATA **************/
107 cd94a9a8 Renato Botelho
print('<?xml version="1.0" encoding="UTF-8"?>' . "\n");?>
108 6afa3a82 Scott Ullrich
<svg width="100%" height="100%" viewBox="0 0 <?=$width?> <?=$height?>" preserveAspectRatio="none" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="init(evt)">
109
  <g id="graph">
110
    <rect id="bg" x1="0" y1="0" width="100%" height="100%" fill="white"/>
111
    <line id="axis_x" x1="0" y1="0" x2="0" y2="100%" <?=$attribs['axis']?>/>
112
    <line id="axis_y" x1="0" y1="100%" x2="100%" y2="100%" <?=$attribs['axis']?>/>
113
    <path id="graph_out" d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_out']?>/>
114
    <path id="graph_in"  d="M0 <?=$height?> L 0 <?=$height?>" <?=$attribs['graph_in']?>/>
115
    <path id="grid"  d="M0 <?=$height/4*1?> L <?=$width?> <?=$height/4*1?> M0 <?=$height/4*2?> L <?=$width?> <?=$height/4*2?> M0 <?=$height/4*3?> L <?=$width?> <?=$height/4*3?>" <?=$attribs['grid']?>/>
116
    <text id="grid_txt1" x="<?=$width?>" y="<?=$height/4*1?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
117
    <text id="grid_txt2" x="<?=$width?>" y="<?=$height/4*2?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
118
    <text id="grid_txt3" x="<?=$width?>" y="<?=$height/4*3?>" <?=$attribs['grid_txt']?> text-anchor="end"> </text>
119 8454080a Carlos Eduardo Ramos
    <text id="graph_in_lbl" x="5" y="8" <?=$attribs['in']?>><?=gettext("In"); ?></text>
120
    <text id="graph_out_lbl" x="5" y="16" <?=$attribs['out']?>><?=gettext("Out"); ?></text>
121 6afa3a82 Scott Ullrich
    <text id="graph_in_txt" x="20" y="8" <?=$attribs['in']?>> </text>
122
    <text id="graph_out_txt" x="20" y="16" <?=$attribs['out']?>> </text>
123 8625c24f Scott Ullrich
    <text id="ifname" x="<?=$width?>" y="8" <?=$attribs['graphname']?> text-anchor="end"><?=htmlspecialchars($ifname)?></text>
124 8454080a Carlos Eduardo Ramos
    <text id="switch_unit" x="<?=$width*0.55?>" y="5" <?=$attribs['switch_unit']?>><?=gettext("Switch to bytes/s"); ?></text>
125
    <text id="switch_scale" x="<?=$width*0.55?>" y="11" <?=$attribs['switch_scale']?>><?=gettext("AutoScale"); ?> (<?=$scale_type?>)</text>
126 3bae4ee4 Charlie Marshall
    <text id="date" x="<?=$width*0.33?>" y="5" <?=$attribs['legend']?>> </text>
127
    <text id="time" x="<?=$width*0.33?>" y="11" <?=$attribs['legend']?>> </text>
128 8454080a Carlos Eduardo Ramos
    <text id="graphlast" x="<?=$width*0.55?>" y="17" <?=$attribs['legend']?>><?=gettext("Graph shows last"); ?> <?=$time_interval*$nb_plot?> <?=gettext("seconds"); ?></text>
129 6afa3a82 Scott Ullrich
    <polygon id="axis_arrow_x" <?=$attribs['axis']?> points="<?=($width) . "," . ($height)?> <?=($width-2) . "," . ($height-2)?> <?=($width-2) . "," . $height?>"/>
130
    <text id="error" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['error']?> text-anchor="middle"><?=$error_text?></text>
131 8454080a Carlos Eduardo Ramos
    <text id="collect_initial" x="<?=$width*0.5?>" y="<?=$height*0.5?>"  visibility="hidden" <?=$attribs['collect_initial']?> text-anchor="middle"><?=gettext("Collecting initial data, please wait"); ?>...</text>
132 6afa3a82 Scott Ullrich
  </g>
133
  <script type="text/ecmascript">
134
    <![CDATA[
135
136
/**
137
 * getURL is a proprietary Adobe function, but it's simplicity has made it very
138
 * popular. If getURL is undefined we spin our own by wrapping XMLHttpRequest.
139
 */
140
if (typeof getURL == 'undefined') {
141
  getURL = function(url, callback) {
142
    if (!url)
143 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("No URL for getURL"); ?>';
144 6afa3a82 Scott Ullrich
145
    try {
146
      if (typeof callback.operationComplete == 'function')
147
        callback = callback.operationComplete;
148
    } catch (e) {}
149
    if (typeof callback != 'function')
150 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("No callback function for getURL"); ?>';
151 6afa3a82 Scott Ullrich
152
    var http_request = null;
153
    if (typeof XMLHttpRequest != 'undefined') {
154
      http_request = new XMLHttpRequest();
155 41b1ff89 Phil Davis
    } else if (typeof ActiveXObject != 'undefined') {
156 6afa3a82 Scott Ullrich
      try {
157
        http_request = new ActiveXObject('Msxml2.XMLHTTP');
158
      } catch (e) {
159
        try {
160
          http_request = new ActiveXObject('Microsoft.XMLHTTP');
161
        } catch (e) {}
162
      }
163
    }
164
    if (!http_request)
165 8454080a Carlos Eduardo Ramos
      throw '<?=gettext("Both getURL and XMLHttpRequest are undefined"); ?>';
166 6afa3a82 Scott Ullrich
167
    http_request.onreadystatechange = function() {
168
      if (http_request.readyState == 4) {
169
        callback( { success : true,
170
                    content : http_request.responseText,
171
                    contentType : http_request.getResponseHeader("Content-Type") } );
172
      }
173
    }
174
    http_request.open('GET', url, true);
175
    http_request.send(null);
176
  }
177
}
178
179
var SVGDoc = null;
180
var last_ifin = 0;
181
var last_ifout = 0;
182
var last_ugmt = 0;
183 5b237745 Scott Ullrich
var max = 0;
184 6afa3a82 Scott Ullrich
var plot_in = new Array();
185
var plot_out = new Array();
186 5b237745 Scott Ullrich
187 6afa3a82 Scott Ullrich
var max_num_points = <?=$nb_plot?>;  // maximum number of plot data points
188
var step = <?=$width?> / max_num_points ;
189 5b237745 Scott Ullrich
var unit = 'bits';
190
var scale_type = '<?=$scale_type?>';
191
192
function init(evt) {
193 6afa3a82 Scott Ullrich
  SVGDoc = evt.target.ownerDocument;
194
  SVGDoc.getElementById("switch_unit").addEventListener("mousedown", switch_unit, false);
195
  SVGDoc.getElementById("switch_scale").addEventListener("mousedown", switch_scale, false);
196 5b237745 Scott Ullrich
197 6afa3a82 Scott Ullrich
  fetch_data();
198 5b237745 Scott Ullrich
}
199
200
function switch_unit(event)
201
{
202 8454080a Carlos Eduardo Ramos
  SVGDoc.getElementById('switch_unit').firstChild.data = '<?=gettext("Switch to"); ?> ' + unit + '/s';
203 6afa3a82 Scott Ullrich
  unit = (unit == 'bits') ? 'bytes' : 'bits';
204 5b237745 Scott Ullrich
}
205
206
function switch_scale(event)
207
{
208 8454080a Carlos Eduardo Ramos
  scale_type = (scale_type == 'up') ? '<?=gettext("follow"); ?>' : '<?=gettext("up"); ?>';
209 6afa3a82 Scott Ullrich
  SVGDoc.getElementById('switch_scale').firstChild.data = 'AutoScale (' + scale_type + ')';
210 5b237745 Scott Ullrich
}
211
212 6afa3a82 Scott Ullrich
function fetch_data() {
213
  getURL('<?=$fetch_link?>', plot_data);
214 5b237745 Scott Ullrich
}
215
216 6afa3a82 Scott Ullrich
function plot_data(obj) {
217
  // Show datetimelegend
218
  var now = new Date();
219 3bae4ee4 Charlie Marshall
  var time = LZ(now.getHours()) + ":" + LZ(now.getMinutes()) + ":" + LZ(now.getSeconds());
220
  SVGDoc.getElementById('time').firstChild.data = time;
221
  var date = (now.getMonth()+1) + "/" + now.getDate() + "/" + now.getFullYear();
222
  SVGDoc.getElementById('date').firstChild.data = date;
223 6afa3a82 Scott Ullrich
224
  if (!obj.success)
225
    return handle_error();  // getURL failed to get data
226
227
  var t = obj.content.split("|");
228
  var ugmt = parseFloat(t[0]);  // ugmt is an unixtimestamp style
229 73567959 Darren Embry
  var ifin = parseInt(t[1], 10);    // number of bytes received by the interface
230
  var ifout = parseInt(t[2], 10);   // number of bytes sent by the interface
231 6afa3a82 Scott Ullrich
  var scale;
232
233
  if (!isNumber(ifin) || !isNumber(ifout))
234
    return handle_error();
235
236
  var diff_ugmt  = ugmt - last_ugmt;
237 67c04e80 Seth Mos
  var diff_ifin  = ifin - last_ifin;
238
  var diff_ifout = ifout - last_ifout;
239
240 6afa3a82 Scott Ullrich
  if (diff_ugmt == 0)
241
    diff_ugmt = 1;  /* avoid division by zero */
242
243
  last_ugmt = ugmt;
244
  last_ifin = ifin;
245
  last_ifout = ifout;
246 9228de6c jim-p
  var graphTimerId = 0;
247 6afa3a82 Scott Ullrich
  switch (plot_in.length) {
248
  	case 0:
249
  		SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'visible');
250
		plot_in[0] = diff_ifin / diff_ugmt;
251
		plot_out[0] = diff_ifout / diff_ugmt;
252 9228de6c jim-p
		setTimeout('fetch_data()',<?=1000*($time_interval + $init_delay)?>);
253 6afa3a82 Scott Ullrich
		return;
254
	case 1:
255
    	SVGDoc.getElementById("collect_initial").setAttributeNS(null, 'visibility', 'hidden');
256
    	break;
257
    case max_num_points:
258
		// shift plot to left if the maximum number of plot points has been reached
259
		var i = 0;
260
		while (i < max_num_points) {
261
		  plot_in[i] = plot_in[i+1];
262
		  plot_out[i] = plot_out[++i];
263 5b237745 Scott Ullrich
		}
264 6afa3a82 Scott Ullrich
		plot_in.length--;
265
		plot_out.length--;
266
  }
267
268
  plot_in[plot_in.length] = diff_ifin / diff_ugmt;
269
  plot_out[plot_out.length]= diff_ifout / diff_ugmt;
270
  var index_plot = plot_in.length - 1;
271
272
  SVGDoc.getElementById('graph_in_txt').firstChild.data = formatSpeed(plot_in[index_plot], unit);
273
  SVGDoc.getElementById('graph_out_txt').firstChild.data = formatSpeed(plot_out[index_plot], unit);
274
275
  /* determine peak for sensible scaling */
276
  if (scale_type == 'up') {
277
    if (plot_in[index_plot] > max)
278
      max = plot_in[index_plot];
279
    if (plot_out[index_plot] > max)
280
      max = plot_out[index_plot];
281 41b1ff89 Phil Davis
  } else if (scale_type == 'follow') {
282 6afa3a82 Scott Ullrich
    i = 0;
283
    max = 0;
284
    while (i < plot_in.length) {
285
      if (plot_in[i] > max)
286
        max = plot_in[i];
287
      if (plot_out[i] > max)
288
        max = plot_out[i];
289
      i++;
290
    }
291
  }
292
293
  var rmax;  // max, rounded up
294
295
  if (unit == 'bits') {
296
    /* round up max, such that
297
         100 kbps -> 200 kbps -> 400 kbps -> 800 kbps -> 1 Mbps -> 2 Mbps -> ... */
298
    rmax = 12500;
299
    i = 0;
300
    while (max > rmax) {
301
      i++;
302
      if (i && (i % 4 == 0))
303
        rmax *= 1.25;
304
      else
305
        rmax *= 2;
306
    }
307
  } else {
308
    /* round up max, such that
309
         10 KB/s -> 20 KB/s -> 40 KB/s -> 80 KB/s -> 100 KB/s -> 200 KB/s -> 400 KB/s -> 800 KB/s -> 1 MB/s ... */
310
    rmax = 10240;
311
    i = 0;
312
    while (max > rmax) {
313
      i++;
314
      if (i && (i % 4 == 0))
315
        rmax *= 1.25;
316
      else
317
        rmax *= 2;
318 2c5fda82 Jose Luis Duran
319 6afa3a82 Scott Ullrich
      if (i == 8)
320
        rmax *= 1.024;
321
    }
322
  }
323
324
  scale = <?=$height?> / rmax;
325
326
  /* change labels accordingly */
327
  SVGDoc.getElementById('grid_txt1').firstChild.data = formatSpeed(3*rmax/4,unit);
328
  SVGDoc.getElementById('grid_txt2').firstChild.data = formatSpeed(2*rmax/4,unit);
329
  SVGDoc.getElementById('grid_txt3').firstChild.data = formatSpeed(rmax/4,unit);
330
331
  var path_in = "M 0 " + (<?=$height?> - (plot_in[0] * scale));
332
  var path_out = "M 0 " + (<?=$height?> - (plot_out[0] * scale));
333
  for (i = 1; i < plot_in.length; i++)
334
  {
335
    var x = step * i;
336
    var y_in = <?=$height?> - (plot_in[i] * scale);
337
    var y_out = <?=$height?> - (plot_out[i] * scale);
338
    path_in += " L" + x + " " + y_in;
339
    path_out += " L" + x + " " + y_out;
340
  }
341
342
  SVGDoc.getElementById('error').setAttributeNS(null, 'visibility', 'hidden');
343
  SVGDoc.getElementById('graph_in').setAttributeNS(null, 'd', path_in);
344
  SVGDoc.getElementById('graph_out').setAttributeNS(null, 'd', path_out);
345
346
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
347 5b237745 Scott Ullrich
}
348
349 6afa3a82 Scott Ullrich
function handle_error() {
350
  SVGDoc.getElementById("error").setAttributeNS(null, 'visibility', 'visible');
351
  setTimeout('fetch_data()',<?=1000*$time_interval?>);
352 5b237745 Scott Ullrich
}
353
354
function isNumber(a) {
355 6afa3a82 Scott Ullrich
  return typeof a == 'number' && isFinite(a);
356 5b237745 Scott Ullrich
}
357
358 6afa3a82 Scott Ullrich
function formatSpeed(speed, unit) {
359
  if (unit == 'bits')
360
    return formatSpeedBits(speed);
361
  if (unit == 'bytes')
362
    return formatSpeedBytes(speed);
363 5b237745 Scott Ullrich
}
364
365
function formatSpeedBits(speed) {
366 6afa3a82 Scott Ullrich
  // format speed in bits/sec, input: bytes/sec
367
  if (speed < 125000)
368 6c83f226 Vinicius Coque
    return Math.round(speed / 125) + " <?=gettext("Kbps"); ?>";
369 6afa3a82 Scott Ullrich
  if (speed < 125000000)
370 6c83f226 Vinicius Coque
    return Math.round(speed / 1250)/100 + " <?=gettext("Mbps"); ?>";
371 6afa3a82 Scott Ullrich
  // else
372 6c83f226 Vinicius Coque
  return Math.round(speed / 1250000)/100 + " <?=gettext("Gbps"); ?>";  /* wow! */
373 5b237745 Scott Ullrich
}
374 6afa3a82 Scott Ullrich
375 5b237745 Scott Ullrich
function formatSpeedBytes(speed) {
376 6afa3a82 Scott Ullrich
  // format speed in bytes/sec, input:  bytes/sec
377
  if (speed < 1048576)
378 6c83f226 Vinicius Coque
    return Math.round(speed / 10.24)/100 + " <?=gettext("KB/s"); ?>";
379 6afa3a82 Scott Ullrich
  if (speed < 1073741824)
380 6c83f226 Vinicius Coque
    return Math.round(speed / 10485.76)/100 + " <?=gettext("MB/s"); ?>";
381 6afa3a82 Scott Ullrich
  // else
382 6c83f226 Vinicius Coque
  return Math.round(speed / 10737418.24)/100 + " <?=gettext("GB/s"); ?>";  /* wow! */
383 5b237745 Scott Ullrich
}
384 6afa3a82 Scott Ullrich
385 5b237745 Scott Ullrich
function LZ(x) {
386 6afa3a82 Scott Ullrich
  return (x < 0 || x > 9 ? "" : "0") + x;
387 5b237745 Scott Ullrich
}
388 6afa3a82 Scott Ullrich
389
    ]]>
390
  </script>
391 985a897f Scott Ullrich
</svg>