~saiko/docker-vnstat

190c05fc7183bb233b85b985b090f622b57cb5e5 — therealfarfetchd 8 months ago master
Initial commit
A  => .gitignore +1 -0
@@ 1,1 @@
/data/vnstatd

A  => build/php/Dockerfile +6 -0
@@ 1,6 @@
FROM php:7-fpm-alpine

RUN \
  apk add --no-cache vnstat libpng-dev freetype-dev libjpeg-turbo-dev \
  && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \
  && docker-php-ext-install gd

A  => build/vnstatd/Dockerfile +9 -0
@@ 1,9 @@
FROM alpine

RUN apk add --no-cache vnstat

VOLUME /var/lib/vnstat

ENTRYPOINT ["/usr/sbin/vnstatd"]

CMD ["-n"]

A  => data/conf/default.conf +13 -0
@@ 1,13 @@
server {
    index index.php index.html;

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

A  => data/http/COPYING +341 -0
@@ 1,341 @@
GNU GENERAL PUBLIC LICENSE
               Version 2, June 1991

 Copyright (C) 1989, 1991 Free Software Foundation, Inc.
                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                Preamble

  The licenses for most software are designed to take away your
freedom to share and change it.  By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users.  This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it.  (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.)  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.

  To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have.  You must make sure that they, too, receive or can get the
source code.  And you must show them these terms so they know their
rights.

  We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.

  Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software.  If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.

  Finally, any free program is threatened constantly by software
patents.  We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary.  To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.

  The precise terms and conditions for copying, distribution and
modification follow.

            GNU GENERAL PUBLIC LICENSE
   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

  0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License.  The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language.  (Hereinafter, translation is included without limitation in
the term "modification".)  Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope.  The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.

  1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.

You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.

  2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:

    a) You must cause the modified files to carry prominent notices
    stating that you changed the files and the date of any change.

    b) You must cause any work that you distribute or publish, that in
    whole or in part contains or is derived from the Program or any
    part thereof, to be licensed as a whole at no charge to all third
    parties under the terms of this License.

    c) If the modified program normally reads commands interactively
    when run, you must cause it, when started running for such
    interactive use in the most ordinary way, to print or display an
    announcement including an appropriate copyright notice and a
    notice that there is no warranty (or else, saying that you provide
    a warranty) and that users may redistribute the program under
    these conditions, and telling the user how to view a copy of this
    License.  (Exception: if the Program itself is interactive but
    does not normally print such an announcement, your work based on
    the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole.  If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works.  But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.

In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.

  3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:

    a) Accompany it with the complete corresponding machine-readable
    source code, which must be distributed under the terms of Sections
    1 and 2 above on a medium customarily used for software interchange; or,

    b) Accompany it with a written offer, valid for at least three
    years, to give any third party, for a charge no more than your
    cost of physically performing source distribution, a complete
    machine-readable copy of the corresponding source code, to be
    distributed under the terms of Sections 1 and 2 above on a medium
    customarily used for software interchange; or,

    c) Accompany it with the information you received as to the offer
    to distribute corresponding source code.  (This alternative is
    allowed only for noncommercial distribution and only if you
    received the program in object code or executable form with such
    an offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for
making modifications to it.  For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable.  However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.

If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.

  4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License.  Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.

  5. You are not required to accept this License, since you have not
signed it.  However, nothing else grants you permission to modify or
distribute the Program or its derivative works.  These actions are
prohibited by law if you do not accept this License.  Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.

  6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions.  You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.

  7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all.  For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.

It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices.  Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.

This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.

  8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded.  In such case, this License incorporates
the limitation as if written in the body of this License.

  9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

Each version is given a distinguishing version number.  If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation.  If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.

  10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission.  For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this.  Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.

                NO WARRANTY

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.

             END OF TERMS AND CONDITIONS

        How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


Also add information on how to contact you by electronic and paper mail.

If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:

    Gnomovision version 69, Copyright (C) year name of author
    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.

You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary.  Here is a sample; alter the names:

  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
  `Gnomovision' (which makes passes at compilers) written by James Hacker.

  <signature of Ty Coon>, 1 April 1989
  Ty Coon, President of Vice

This General Public License does not permit incorporating your program into
proprietary programs.  If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library.  If this is what you want to do, use the GNU Library General
Public License instead of this License.


A  => data/http/README +52 -0
@@ 1,52 @@
0. WHAT IS IT?

This is a PHP frontend end to vnstat, a network traffic logger.
Since vnstat is console mode only I created this script to
make a 'nice' report of the data collected by vnstat.
For more information about vnstat check out http://humdi.net/vnstat/
For updates to this script check http://www.sqweek.com


1. REQUIREMENTS 

- vnstat setup and collecting data
- webserver with PHP
- php-gd extension installed for PNG graphs


2. INSTALL

Installation should be really straightforward:

Put the files from this package somewhere inside the webroot of
your webserver. Then edit the few configuration options in config.php
to suit your situation and your good to go. The various options are
explained in config.php.


3. LICENSE

vnstat PHP frontend 1.5.1
Copyright (c)2006-2008  Bjorge Dijkstra (bjd@jooz.net)

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


NOTE:
  The Truetype font file VeraBd.ttf is copyright by Bitstream Inc. 
  See vera_copyright.txt for more information.




A  => data/http/VeraBd.ttf +0 -0

A  => data/http/config.php +71 -0
@@ 1,71 @@
<?php
    //
    // vnStat PHP frontend (c)2006-2010 Bjorge Dijkstra (bjd@jooz.net)
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    //
    //
    // see file COPYING or at http://www.gnu.org/licenses/gpl.html 
    // for more information.
    //
    error_reporting(E_ALL | E_NOTICE);

    //
    // configuration parameters
    //
    // edit these to reflect your particular situation
    //
    $locale = 'en_US.UTF-8';
    $language = 'en';

    // list of network interfaces monitored by vnStat
    $iface_list = array('enp2s0');

    //
    // optional names for interfaces
    // if there's no name set for an interface then the interface identifier
    // will be displayed instead
    //    
    $iface_title['enp2s0'] = 'External';

    //
    // There are two possible sources for vnstat data. If the $vnstat_bin
    // variable is set then vnstat is called directly from the PHP script
    // to get the interface data. 
    //
    // The other option is to periodically dump the vnstat interface data to
    // a file (e.g. by a cronjob). In that case the $vnstat_bin variable
    // must be cleared and set $data_dir to the location where the dumps
    // are stored. Dumps must be named 'vnstat_dump_$iface'.
    //
    // You can generate vnstat dumps with the command:
    //   vnstat --dumpdb -i $iface > /path/to/data_dir/vnstat_dump_$iface
    // 
    $vnstat_bin = '/usr/bin/vnstat';
    $data_dir = './dumps';

    // graphics format to use: svg or png
    $graph_format='png';
    
    // Font to use for PNG graphs
    define('GRAPH_FONT',dirname(__FILE__).'/VeraBd.ttf');

    // Font to use for SVG graphs
    define('SVG_FONT', 'Verdana');

    // Default theme
    define('DEFAULT_COLORSCHEME', 'dark');

?>

A  => data/http/graph.php +303 -0
@@ 1,303 @@
<?php
    //
    // vnStat PHP frontend (c)2006-2010 Bjorge Dijkstra (bjd@jooz.net)
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    //
    //
    // see file COPYING or at http://www.gnu.org/licenses/gpl.html 
    // for more information.
    //
    require 'config.php';
    require 'localize.php';
    require 'vnstat.php';

    validate_input();

    require "./themes/$style/theme.php";

    function allocate_color($im, $colors)
    {
	return imagecolorallocatealpha($im, $colors[0], $colors[1], $colors[2], $colors[3]);
    }
            
    function init_image()
    {
        global $im, $xlm, $xrm, $ytm, $ybm, $iw, $ih,$graph, $cl, $iface, $colorscheme, $style;

        if ($graph == 'none')
            return;

        //
        // image object
        //    
        $xlm = 70;
        $xrm = 20;
        $ytm = 35;
        $ybm = 60;
        if ($graph == 'small')
        {
            $iw = 300 + $xrm + $xlm;
            $ih = 100 + $ytm + $ybm;    
        }
        else
        {
            $iw = 600 + $xrm + $xlm;
            $ih = 200 + $ytm + $ybm;
        }

        $im = imagecreatetruecolor($iw,$ih);

        //
        // colors
        //
	$cs = $colorscheme;
	$cl['image_background'] = allocate_color($im, $cs['image_background']);
	$cl['background'] = allocate_color($im, $cs['graph_background']);
	$cl['background_2'] = allocate_color($im, $cs['graph_background_2']);
        $cl['grid_stipple_1'] = allocate_color($im, $cs['grid_stipple_1']);
        $cl['grid_stipple_2'] = allocate_color($im, $cs['grid_stipple_2']);
        $cl['text'] = allocate_color($im, $cs['text']);
        $cl['border'] = allocate_color($im, $cs['border']);
        $cl['rx'] = allocate_color($im, $cs['rx']);
        $cl['rx_border'] = allocate_color($im, $cs['rx_border']);
        $cl['tx'] = allocate_color($im, $cs['tx']);
        $cl['tx_border'] = allocate_color($im, $cs['tx_border']);
	
        imagefilledrectangle($im,0,0,$iw,$ih,$cl['image_background']);
	imagefilledrectangle($im,$xlm,$ytm,$iw-$xrm,$ih-$ybm, $cl['background']);
	
	$x_step = ($iw - $xlm - $xrm) / 12;
	$depth = ($x_step / 8) + 4;
	imagefilledpolygon($im, array($xlm, $ytm, $xlm, $ih - $ybm, $xlm - $depth, $ih - $ybm + $depth, $xlm - $depth, $ytm + $depth), 4, $cl['background_2']);
	imagefilledpolygon($im, array($xlm, $ih - $ybm, $xlm - $depth, $ih - $ybm + $depth, $iw - $xrm - $depth, $ih - $ybm  + $depth, $iw - $xrm, $ih - $ybm), 4, $cl['background_2']);

	// draw title
	$text = T('Traffic data for')." $iface";
 	$bbox = imagettfbbox(10, 0, GRAPH_FONT, $text);
	$textwidth = $bbox[2] - $bbox[0];
	imagettftext($im, 10, 0, ($iw-$textwidth)/2, ($ytm/2), $cl['text'], GRAPH_FONT, $text);
		
    }

    function draw_border()
    {
        global $im,$cl,$iw,$ih;

        imageline($im,     0,    0,$iw-1,    0, $cl['border']);
        imageline($im,     0,$ih-1,$iw-1,$ih-1, $cl['border']);
        imageline($im,     0,    0,    0,$ih-1, $cl['border']);  
        imageline($im, $iw-1,    0,$iw-1,$ih-1, $cl['border']);
    }
    
    function draw_grid($x_ticks, $y_ticks)
    {
        global $im, $cl, $iw, $ih, $xlm, $xrm, $ytm, $ybm;
        $x_step = ($iw - $xlm - $xrm) / $x_ticks;
        $y_step = ($ih - $ytm - $ybm) / $y_ticks;
	
	$depth = 10;//($x_step / 8) + 4;

        $ls = array($cl['grid_stipple_1'],$cl['grid_stipple_2']);
        imagesetstyle($im, $ls);
        for ($i=$xlm;$i<=($iw-$xrm); $i += $x_step)
        {
            imageline($im, $i, $ytm, $i, $ih - $ybm, IMG_COLOR_STYLED);
	    imageline($im, $i, $ih - $ybm, $i - $depth, $ih - $ybm + $depth, IMG_COLOR_STYLED);
        }
        for ($i=$ytm;$i<=($ih-$ybm); $i += $y_step)
        {
            imageline($im, $xlm, $i, $iw - $xrm, $i, IMG_COLOR_STYLED); 
	    imageline($im, $xlm, $i, $xlm - $depth, $i + $depth, IMG_COLOR_STYLED);
        }
        imageline($im, $xlm, $ytm, $xlm, $ih - $ybm, $cl['border']);
        imageline($im, $xlm, $ih - $ybm, $iw - $xrm, $ih - $ybm, $cl['border']);
    }
    
    
    function draw_data($data)
    {
        global $im,$cl,$iw,$ih,$xlm,$xrm,$ytm,$ybm;

        sort($data);

        $x_ticks = count($data);
        $y_ticks = 10;
        $y_scale = 1;
        $prescale = 1;
        $unit = 'K';
        $offset = 0;
        $gr_h = $ih - $ytm - $ybm;
        $x_step = ($iw - $xlm - $xrm) / $x_ticks;
        $y_step = ($ih - $ytm - $ybm) / $y_ticks;
        $bar_w = ($x_step / 2) ;

        //
        // determine scale
        //
        $low = 99999999999;
        $high = 0;
        for ($i=0; $i<$x_ticks; $i++)
        {
            if ($data[$i]['rx'] < $low)
            $low = $data[$i]['rx'];
            if ($data[$i]['tx'] < $low)
            $low = $data[$i]['tx'];
            if ($data[$i]['rx'] > $high)
            $high = $data[$i]['rx'];
            if ($data[$i]['tx'] > $high)
            $high = $data[$i]['tx'];
        }

        while ($high > ($prescale * $y_scale * $y_ticks))
        {
            $y_scale = $y_scale * 2;
            if ($y_scale >= 1024)
            {
            $prescale = $prescale * 1024;
            $y_scale = $y_scale / 1024;
            if ($unit == 'K') 
                $unit = 'M';
            else if ($unit == 'M')
                $unit = 'G';
            else if ($unit == 'G')
                $unit = 'T';
            }
        }

        draw_grid($x_ticks, $y_ticks);
	
        //
        // graph scale factor (per pixel)
        //
	imagesetthickness($im, 1);
        $sf = ($prescale * $y_scale * $y_ticks) / $gr_h;

        if ($data[0] == 'nodata')
        {
            $text = 'no data available';
	    $bbox = imagettfbbox(10, 0, GRAPH_FONT, $text);
	    $textwidth = $bbox[2] - $bbox[0];
	    imagettftext($im, 10, 0, ($iw-$textwidth)/2, $ytm + 80, $cl['text'], GRAPH_FONT, $text);
        }
        else
        {
            //
            // draw bars
            //      
            for ($i=0; $i<$x_ticks; $i++)
            {
        	$x = $xlm + ($i * $x_step);
        	$y = $ytm + ($ih - $ytm - $ybm) - (($data[$i]['rx'] - $offset) / $sf);
		
		$depth = $x_step / 8;
		$space = 0;
		
		$x1 = $x;
		$y1 = $y;
		$x2 = $x + $bar_w - $space;
		$y2 = $ih - $ybm;
		
        	imagefilledrectangle($im, $x1, $y1, $x2, $y2, $cl['rx']);
		imagerectangle($im, $x1, $y1, $x2, $y2, $cl['rx_border']);
		
		imagefilledrectangle($im, $x1 - $depth, $y1 + $depth, $x2 -$depth, $y2 + $depth, $cl['rx']);
		imagerectangle($im, $x1 - $depth, $y1 + $depth, $x2 - $depth, $y2 + $depth, $cl['rx_border']);
		
		imagefilledpolygon($im, array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth), 4, $cl['rx']);
		imagepolygon($im, array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth), 4, $cl['rx_border']);
		imagefilledpolygon($im, array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth), 4, $cl['rx']);
		imagepolygon($im, array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth), 4, $cl['rx_border']);

        	$y1 = $ytm + ($ih - $ytm - $ybm) - (($data[$i]['tx'] - $offset) / $sf);
		$x1 = $x1 + $bar_w;
		$x2 = $x2 + $bar_w;

        	imagefilledrectangle($im, $x1, $y1, $x2, $y2, $cl['tx']);
		imagerectangle($im, $x1, $y1, $x2, $y2, $cl['tx_border']);
		
        	imagefilledrectangle($im, $x1 - $depth, $y1 + $depth, $x2 - $depth, $y2 + $depth, $cl['tx']);
		imagerectangle($im, $x1 - $depth, $y1 + $depth, $x2 - $depth, $y2 + $depth, $cl['tx_border']);		
		
		imagefilledpolygon($im, array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth), 4, $cl['tx']);
		imagepolygon($im, array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth), 4, $cl['tx_border']);
		imagefilledpolygon($im, array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth), 4, $cl['tx']);
		imagepolygon($im, array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth), 4, $cl['tx_border']);
            }
    
            //
            // axis labels
            //
            for ($i=0; $i<=$y_ticks; $i++)
            {
                $label = ($i * $y_scale).$unit;
		$bbox = imagettfbbox(8, 0, GRAPH_FONT, $label);
		$textwidth = $bbox[2] - $bbox[0];
		imagettftext($im, 8, 0, $xlm - $textwidth - 16, ($ih - $ybm) - ($i * $y_step) + 8 + $depth, $cl['text'], GRAPH_FONT, $label);
            }

            for ($i=0; $i<$x_ticks; $i++)
            {
                $label = $data[$i]['img_label'];
		$bbox = imagettfbbox(9, 0, GRAPH_FONT, $label);
		$textwidth = $bbox[2] - $bbox[0];
		imagettftext($im, 9, 0, $xlm + ($i * $x_step) + ($x_step / 2) - ($textwidth / 2) - $depth - 4, $ih - $ybm + 20 + $depth, $cl['text'], GRAPH_FONT, $label);
            }
        }

        draw_border();


        //
        // legend
        //
        imagefilledrectangle($im, $xlm, $ih-$ybm+39, $xlm+8,$ih-$ybm+47,$cl['rx']);
        imagerectangle($im, $xlm, $ih-$ybm+39, $xlm+8,$ih-$ybm+47,$cl['text']);
	imagettftext($im, 8,0, $xlm+14, $ih-$ybm+48,$cl['text'], GRAPH_FONT,'bytes in');

        imagefilledrectangle($im, $xlm+120 , $ih-$ybm+39, $xlm+128,$ih-$ybm+47,$cl['tx']);
        imagerectangle($im, $xlm+120, $ih-$ybm+39, $xlm+128,$ih-$ybm+47,$cl['text']);
	imagettftext($im, 8,0, $xlm+134, $ih-$ybm+48,$cl['text'], GRAPH_FONT,'bytes out'); 
    }

    function output_image()
    {
        global $page,$hour,$day,$month,$im,$iface;

        if ($page == 'summary')
            return;

        init_image();

        if ($page == 'h')
        {
            draw_data($hour);
        }
        else if ($page == 'd')
        {
            draw_data($day);
        }
        else if ($page == 'm')
        {
            draw_data($month);
        }
	
        header('Content-type: image/png');	
        imagepng($im);
    }

    get_vnstat_data();
    output_image();
?>        

A  => data/http/graph_svg.php +362 -0
@@ 1,362 @@
<?php
    //
    // vnStat PHP frontend (c)2006-2010 Bjorge Dijkstra (bjd@jooz.net)
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    //
    //
    // see file COPYING or at http://www.gnu.org/licenses/gpl.html 
    // for more information.
    //
    require 'config.php';
    require 'localize.php';
    require 'vnstat.php';

    validate_input();

    require "./themes/$style/theme.php";

    function svg_create($width, $height)
    {
	header('Content-type: image/svg+xml');
	print "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n";
	print "<svg width=\"$width\" height=\"$height\" version=\"1.2\" baseProfile=\"tiny\" xmlns=\"http://www.w3.org/2000/svg\">\n";
	print "<g style=\"shape-rendering: crispEdges\">\n";
    }

    function svg_end()
    {
	print "</g>\n";
	print "</svg>\n";
    }

    function svg_options($options)
    {
	foreach ($options as $key => $value) {
	    print "$key=\"$value\" ";
	}
    }

    function svg_group($options)
    {
	print "<g ";
	svg_options($options);
	print ">\n";
    }

    function svg_group_end()
    {
	print "</g>\n";
    }

    function svg_text($x, $y, $text, $options = array()) 
    {	
	printf("<text x=\"%F\" y=\"%F\" ", $x, $y);
	svg_options($options);
	print ">$text</text>\n";
    }

    function svg_line($x1, $y1, $x2, $y2, $options = array())
    {
	printf("<line x1=\"%F\" y1=\"%F\" x2=\"%F\" y2=\"%F\" ", $x1, $y1, $x2, $y2);
	svg_options($options);
	print "/>\n";
    }

    function svg_rect($x, $y, $w, $h, $options = array()) 
    {
	printf("<rect x=\"%F\" y=\"%F\" width=\"%F\" height=\"%F\" ", $x, $y, $w, $h);
	svg_options($options);
	print "/>\n";
    }

    function svg_poly($points, $options = array())
    {
       print "<polygon points=\"";
       for ($p = 0; $p < count($points); $p += 2) {
	  printf("%F,%F ", $points[$p], $points[$p+1]);
       }
       svg_options($options);
       print "\"/>\n";
    }

    function allocate_color($colors)
    {
	$col['rgb'] = sprintf("#%02X%02X%02X", $colors[0], $colors[1], $colors[2]);
	$col['opacity'] = sprintf("%F", (127 - $colors[3]) / 127);
	return $col;
    }
            
    function init_image()
    {
        global $xlm, $xrm, $ytm, $ybm, $iw, $ih,$graph, $cl, $iface, $colorscheme, $style;

        if ($graph == 'none')
            return;

        //
        // image object
        //    
        $xlm = 70;
        $xrm = 20;
        $ytm = 35;
        $ybm = 60;
        if ($graph == 'small')
        {
            $iw = 300 + $xrm + $xlm;
            $ih = 100 + $ytm + $ybm;    
        }
        else
        {
            $iw = 600 + $xrm + $xlm;
            $ih = 200 + $ytm + $ybm;
        }
	
	svg_create($iw, $ih);

        //
        // colors
        //
	$cs = $colorscheme;
	$cl['image_background'] = allocate_color($cs['image_background']);
	$cl['background'] = allocate_color($cs['graph_background']);
	$cl['background_2'] = allocate_color($cs['graph_background_2']);
        $cl['grid_stipple_1'] = allocate_color($cs['grid_stipple_1']);
        $cl['grid_stipple_2'] = allocate_color($cs['grid_stipple_2']);
        $cl['text'] = allocate_color($cs['text']);
        $cl['border'] = allocate_color($cs['border']);
        $cl['rx'] = allocate_color($cs['rx']);
        $cl['rx_border'] = allocate_color($cs['rx_border']);
        $cl['tx'] = allocate_color($cs['tx']);
        $cl['tx_border'] = allocate_color($cs['tx_border']);
	
        svg_rect(0, 0, $iw, $ih, array( 'stroke' => 'none', 'stroke-width' => 0, 'fill' => $cl['image_background']['rgb']) );
	svg_rect($xlm, $ytm, $iw-$xrm-$xlm, $ih-$ybm-$ytm, array( 'stroke' => 'none', 'stroke-width' => 0, 'fill' => $cl['background']['rgb']) );
	
	$depth = 12;
	svg_group( array( 'stroke' => 'none', 'stroke-width' => 0, 'fill' => $cl['background_2']['rgb'], 'fill-opacity' => $cl['background_2']['opacity']) );
	svg_poly(array($xlm, $ytm, $xlm, $ih - $ybm, $xlm - $depth, $ih - $ybm + $depth, $xlm - $depth, $ytm + $depth));
	svg_poly(array($xlm, $ih - $ybm, $xlm - $depth, $ih - $ybm + $depth, $iw - $xrm - $depth, $ih - $ybm  + $depth, $iw - $xrm, $ih - $ybm));
	svg_group_end();

	// draw title
	$text = T('Traffic data for')." $iface";
	svg_text($iw / 2, ($ytm / 2), $text, array( 'stroke' => $cl['text'], 'fill' => $cl['text']['rgb'],'stroke-width' => 0, 'font-family' => SVG_FONT, 'font-weight' => 'bold', 'text-anchor' => 'middle' ));
    }

    function draw_border()
    {
        global $cl, $iw, $ih;
	svg_rect(1, 1, $iw-2, $ih-2, array( 'stroke' => $cl['border']['rgb'], 'stroke-opacity' => $cl['border']['opacity'], 'stroke-width' => 1, 'fill' => 'none') );
    }
    
    function draw_grid($x_ticks, $y_ticks)
    {
        global $cl, $iw, $ih, $xlm, $xrm, $ytm, $ybm;
        $x_step = ($iw - $xlm - $xrm) / $x_ticks;
        $y_step = ($ih - $ytm - $ybm) / $y_ticks;
	
	$depth = 12;

	svg_group( array( 'stroke' => $cl['grid_stipple_1']['rgb'], 'stroke-opacity' => $cl['grid_stipple_1']['opacity'], 'stroke-width' => '1px', 'stroke-dasharray' => '1,1' ) );
        for ($i = $xlm; $i <= ($iw - $xrm); $i += $x_step)
        {
	    svg_line($i, $ytm, $i, $ih-$ybm);
            svg_line($i, $ih-$ybm, $i-$depth, $ih-$ybm+$depth);
        }
        for ($i = $ytm; $i <= ($ih - $ybm); $i += $y_step)
        {
            svg_line($xlm, $i, $iw - $xrm, $i); 
	    svg_line($xlm, $i, $xlm - $depth, $i + $depth);
        }
	svg_group_end();

	svg_group( array( 'stroke' => $cl['border']['rgb'], 'stroke-width' => '1px', 'stroke-opacity' => $cl['border']['opacity'] ) );
        svg_line($xlm, $ytm, $xlm, $ih - $ybm);
        svg_line($xlm, $ih - $ybm, $iw - $xrm, $ih - $ybm);
	svg_group_end();
    }
    
    
    function draw_data($data)
    {
        global $cl,$iw,$ih,$xlm,$xrm,$ytm,$ybm;

        sort($data);

        $x_ticks = count($data);
        $y_ticks = 10;
        $y_scale = 1;
        $prescale = 1;
        $unit = 'K';
        $offset = 0;
        $gr_h = $ih - $ytm - $ybm;
        $x_step = ($iw - $xlm - $xrm) / $x_ticks;
        $y_step = ($ih - $ytm - $ybm) / $y_ticks;
        $bar_w = ($x_step / 2) ;

        //
        // determine scale
        //
        $low = 99999999999;
        $high = 0;
        for ($i=0; $i<$x_ticks; $i++)
        {
            if ($data[$i]['rx'] < $low)
            $low = $data[$i]['rx'];
            if ($data[$i]['tx'] < $low)
            $low = $data[$i]['tx'];
            if ($data[$i]['rx'] > $high)
            $high = $data[$i]['rx'];
            if ($data[$i]['tx'] > $high)
            $high = $data[$i]['tx'];
        }

        while ($high > ($prescale * $y_scale * $y_ticks))
        {
            $y_scale = $y_scale * 2;
            if ($y_scale >= 1024)
            {
            $prescale = $prescale * 1024;
            $y_scale = $y_scale / 1024;
            if ($unit == 'K') 
                $unit = 'M';
            else if ($unit == 'M')
                $unit = 'G';
            else if ($unit == 'G')
                $unit = 'T';
            }
        }

        draw_grid($x_ticks, $y_ticks);
	
        //
        // graph scale factor (per pixel)
        //
        $sf = ($prescale * $y_scale * $y_ticks) / $gr_h;

        if ($data[0] == 'nodata')
        {
            $text = 'no data available';
	    svg_text($iw/2, $ytm + 80, $text, array( 'stroke' => $cl['text']['rgb'], 'fill' => $cl['text']['rgb'], 'stroke-width' => 0, 'font-family' => SVG_FONT, 'font-size' => '16pt', 'text-anchor' => 'middle') );
        }
        else
        {
            //
            // draw bars
            //      
            for ($i=0; $i<$x_ticks; $i++)
            {
        	$x = $xlm + ($i * $x_step);
        	$y = $ytm + ($ih - $ytm - $ybm) - (($data[$i]['rx'] - $offset) / $sf);
		
		$depth = ($x_ticks < 20) ? 8 : 6;
		$space = 0;
		
		$x1 = (int)$x;
		$y1 = (int)$y;
		$w = (int)($bar_w - $space);
		$h = (int)($ih - $ybm - $y);
		$x2 = (int)($x + $bar_w - $space);
		$y2 = (int)($ih - $ybm);
		
		svg_group( array( 'stroke' => $cl['rx_border']['rgb'], 'stroke-opacity' => $cl['rx_border']['opacity'], 
				  'stroke-width' => 1, 'stroke-linejoin' => 'round',
			          'fill' => $cl['rx']['rgb'], 'fill-opacity' => $cl['rx']['opacity'] ) );
        	svg_rect($x1, $y1, $w, $h);
		svg_rect($x1 - $depth, $y1 + $depth, $w, $h);
		svg_poly(array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth));
		svg_poly(array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth));
		svg_group_end();

        	$y1 = (int)($ytm + ($ih - $ytm - $ybm) - (($data[$i]['tx'] - $offset) / $sf));
		$x1 = (int)($x1 + $bar_w);
		$x2 = (int)($x2 + $bar_w);
		$w = (int)($bar_w - $space);
		$h = (int)($ih - $ybm - $y1 - 1);

		svg_group( array( 'stroke' => $cl['tx_border']['rgb'], 'stroke-opacity' => $cl['tx_border']['opacity'], 
				  'stroke-width' => 1, 'stroke-linejoin' => 'round',
			          'fill' => $cl['tx']['rgb'], 'fill-opacity' => $cl['tx']['opacity'] ) );
        	svg_rect($x1, $y1, $w, $h);
		svg_rect($x1 - $depth, $y1 + $depth, $w, $h);
		svg_poly(array($x1, $y1, $x2, $y1, $x2 - $depth, $y1 + $depth, $x1 - $depth, $y1 + $depth));
		svg_poly(array($x2, $y1, $x2, $y2, $x2 - $depth, $y2 + $depth, $x2 - $depth, $y1 + $depth));
		svg_group_end();
            }
    
            //
            // axis labels
            //
	    svg_group( array( 'fill' => $cl['text']['rgb'], 'fill-opacity' => $cl['text']['opacity'], 'stroke-width' => '0', 'font-family' => SVG_FONT, 'font-size' => '10pt', 'text-anchor' => 'end' ) );
            for ($i=0; $i<=$y_ticks; $i++)
            {
                $label = ($i * $y_scale).$unit;
		$tx = $xlm - 16;
		$ty = (int)(($ih - $ybm) - ($i * $y_step) + 8 + $depth);
		svg_text($tx, $ty, $label);
            }
	    svg_group_end();

	    svg_group( array( 'fill' => $cl['text']['rgb'], 'fill-opacity' => $cl['text']['opacity'], 'stroke-width' => '0', 'font-family' => SVG_FONT, 'font-size' => '10pt', 'text-anchor' => 'middle' ) );
            for ($i=0; $i<$x_ticks; $i++)
            {
                $label = $data[$i]['img_label'];
		svg_text($xlm + ($i * $x_step) + ($x_step / 2) - $depth - 4, $ih - $ybm + 20 + $depth, $label);
            }
	    svg_group_end();
        }

        draw_border();


        //
        // legend
        //
        svg_rect($xlm, $ih-$ybm+39, 8, 8, array( 'stroke' => $cl['text']['rgb'], 'stroke-width' => 1, 'fill' => $cl['rx']['rgb']) );
	svg_text($xlm+14, $ih-$ybm+48, T('bytes in'), array( 'fill' => $cl['text']['rgb'], 'stroke-width' => 0, 'font-family' => SVG_FONT, 'font-size' => '8pt') );

        svg_rect($xlm+120 , $ih-$ybm+39, 8, 8, array( 'stroke' => $cl['text']['rgb'], 'stroke-width' => 1, 'fill' => $cl['tx']['rgb']) );
	svg_text($xlm+134, $ih-$ybm+48, T('bytes out'), array( 'fill' => $cl['text']['rgb'], 'stroke-width' => 0, 'font-family' => SVG_FONT, 'font-size' => '8pt') );
    }

    function output_image()
    {
        global $page,$hour,$day,$month,$iface;

        if ($page == 'summary')
            return;

        init_image();

        if ($page == 'h')
        {
            draw_data($hour);
        }
        else if ($page == 'd')
        {
            draw_data($day);
        }
        else if ($page == 'm')
        {
            draw_data($month);
        }

	svg_end();
    }

    get_vnstat_data();
    output_image();
?>        

A  => data/http/index.php +196 -0
@@ 1,196 @@
<?php
    //
    // vnStat PHP frontend (c)2006-2010 Bjorge Dijkstra (bjd@jooz.net)
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    //
    //
    // see file COPYING or at http://www.gnu.org/licenses/gpl.html 
    // for more information.
    //
    require 'config.php';
    require 'localize.php';
    require 'vnstat.php';

    validate_input();

    require "./themes/$style/theme.php";

    function write_side_bar()
    {
        global $iface, $page, $graph, $script, $style;
        global $iface_list, $iface_title;   
        global $page_list, $page_title;
        
        $p = "&amp;graph=$graph&amp;style=$style";

        print "<ul class=\"iface\">\n";
        foreach ($iface_list as $if)
        {
            print "<li class=\"iface\">";
            if (isset($iface_title[$if]))
            {
                print $iface_title[$if];
            }
            else
            {
                print $if;
            }
            print "<ul class=\"page\">\n";
            foreach ($page_list as $pg)
            {
                print "<li class=\"page\"><a href=\"$script?if=$if$p&amp;page=$pg\">".$page_title[$pg]."</a></li>\n";
            }
            print "</ul></li>\n";
	    
        }
        print "</ul>\n"; 
    }
    

    function kbytes_to_string($kb)
    {
        $units = array('TB','GB','MB','KB');
        $scale = 1024*1024*1024;
        $ui = 0;

        while (($kb < $scale) && ($scale > 1))
        {
            $ui++;
            $scale = $scale / 1024;
        }   
        return sprintf("%0.2f %s", ($kb/$scale),$units[$ui]);
    }
    
    function write_summary()
    {
        global $summary,$top,$day,$hour,$month;

        $trx = $summary['totalrx']*1024+$summary['totalrxk'];
        $ttx = $summary['totaltx']*1024+$summary['totaltxk'];

        //
        // build array for write_data_table
        //
        $sum[0]['act'] = 1;
        $sum[0]['label'] = T('This hour');
        $sum[0]['rx'] = $hour[0]['rx'];
        $sum[0]['tx'] = $hour[0]['tx'];

        $sum[1]['act'] = 1;
        $sum[1]['label'] = T('This day');
        $sum[1]['rx'] = $day[0]['rx'];
        $sum[1]['tx'] = $day[0]['tx'];

        $sum[2]['act'] = 1;
        $sum[2]['label'] = T('This month');
        $sum[2]['rx'] = $month[0]['rx'];
        $sum[2]['tx'] = $month[0]['tx'];

        $sum[3]['act'] = 1;
        $sum[3]['label'] = T('All time');
        $sum[3]['rx'] = $trx;
        $sum[3]['tx'] = $ttx;

        write_data_table(T('Summary'), $sum);
        print "<br/>\n";
        write_data_table(T('Top 10 days'), $top);
    }
    
    
    function write_data_table($caption, $tab)
    {
        print "<table width=\"100%\" cellspacing=\"0\">\n";
        print "<caption>$caption</caption>\n";
        print "<tr>";
        print "<th class=\"label\" style=\"width:120px;\">&nbsp;</th>";
        print "<th class=\"label\">".T('In')."</th>";
        print "<th class=\"label\">".T('Out')."</th>";
        print "<th class=\"label\">".T('Total')."</th>";  
        print "</tr>\n";

        for ($i=0; $i<count($tab); $i++)
        {
            if ($tab[$i]['act'] == 1)
            {
                $t = $tab[$i]['label'];
                $rx = kbytes_to_string($tab[$i]['rx']);
                $tx = kbytes_to_string($tab[$i]['tx']);
                $total = kbytes_to_string($tab[$i]['rx']+$tab[$i]['tx']);
                $id = ($i & 1) ? 'odd' : 'even';
                print "<tr>";
                print "<td class=\"label_$id\">$t</td>";
                print "<td class=\"numeric_$id\">$rx</td>";
                print "<td class=\"numeric_$id\">$tx</td>";
                print "<td class=\"numeric_$id\">$total</td>";
                print "</tr>\n";
             }
        }
        print "</table>\n";
    }

    get_vnstat_data();

    //
    // html start
    //
    header('Content-type: text/html; charset=utf-8');
    print '<?xml version="1.0"?>';
?>        
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>vnStat - PHP frontend</title>
  <link rel="stylesheet" type="text/css" href="themes/<?php echo $style ?>/style.css"/>
</head>
<body>

<div id="wrap">
  <div id="sidebar"><?php write_side_bar(); ?></div>
   <div id="content">
    <div id="header"><?php print T('Traffic data for')." $iface_title[$iface] ($iface)";?></div>
    <div id="main">
    <?php
    $graph_params = "if=$iface&amp;page=$page&amp;style=$style";
    if ($page != 's')
        if ($graph_format == 'svg') {
	     print "<object type=\"image/svg+xml\" width=\"692\" height=\"297\" data=\"graph_svg.php?$graph_params\"></object>\n";
        } else {
	     print "<img src=\"graph.php?$graph_params\" alt=\"graph\"/>\n";	
        }

    if ($page == 's')
    {
        write_summary();
    }
    else if ($page == 'h')
    {   
        write_data_table(T('Last 24 hours'), $hour); 
    }
    else if ($page == 'd')
    {
        write_data_table(T('Last 30 days'), $day);	
    }
    else if ($page == 'm')
    {
        write_data_table(T('Last 12 months'), $month);   
    }
    ?>
    </div>
    <div id="footer"><a href="http://www.sqweek.com/">vnStat PHP frontend</a> 1.5.1 - &copy;2006-2010 Bjorge Dijkstra (bjd _at_ jooz.net)</div>
  </div>
</div>

</body></html>

A  => data/http/lang/cs.php +39 -0
@@ 1,39 @@
<?php

// sidebar labels
$L['summary'] = 'shrnutí';
$L['hours'] = 'hodiny';
$L['days'] = 'dny';
$L['months'] = 'měsíce';

// main table headers
$L['Summary'] = 'Shrnutí';
$L['Top 10 days'] = 'Nej 10 dní';
$L['Last 24 hours'] = 'Posledních 24 hodin';
$L['Last 30 days'] = 'Posledních 30 dní';
$L['Last 12 months'] = 'Posledních 12 měsíců';

// traffic table columns
$L['In'] = 'Stahování';
$L['Out'] = 'Odesílání';
$L['Total'] = 'Celkem';

// summary rows
$L['This hour'] = 'Tato hodina';
$L['This day'] = 'Tento den';
$L['This month'] = 'Tento měsíc';
$L['All time'] = 'Za celou dobu';

// graph text
$L['Traffic data for'] = 'Přehled pro';
$L['bytes in'] = 'bytů staženo';
$L['bytes out'] = 'bytů odesláno';

// date formats
$L['datefmt_days'] = '%d. %B';
$L['datefmt_days_img'] = '%d';
$L['datefmt_months'] = '%B %Y';
$L['datefmt_months_img'] = '%b';
$L['datefmt_hours'] = '%k%P';
$L['datefmt_hours_img'] = '%k';
$L['datefmt_top'] = '%d. %B %Y';

A  => data/http/lang/en.php +39 -0
@@ 1,39 @@
<?php

// sidebar labels
$L['summary'] = 'summary';
$L['hours'] = 'hours';
$L['days'] = 'days';
$L['months'] = 'months';

// main table headers
$L['Summary'] = 'Summary';
$L['Top 10 days'] = 'Top 10 days';
$L['Last 24 hours'] = 'Last 24 hours';
$L['Last 30 days'] = 'Last 30 days';
$L['Last 12 months'] = 'Last 12 months';

// traffic table columns
$L['In'] = 'In';
$L['Out'] = 'Out';
$L['Total'] = 'Total';

// summary rows
$L['This hour'] = 'This hour';
$L['This day'] = 'This day';
$L['This month'] = 'This month';
$L['All time'] = 'All time';

// graph text
$L['Traffic data for'] = 'Traffic data for';
$L['bytes in'] = 'bytes in';
$L['bytes out'] = 'bytes out';

// date formats
$L['datefmt_days'] = '%d %B';
$L['datefmt_days_img'] = '%d';
$L['datefmt_months'] = '%B %Y';
$L['datefmt_months_img'] = '%b';
$L['datefmt_hours'] = '%l%P';
$L['datefmt_hours_img'] = '%l';
$L['datefmt_top'] = '%d %B %Y';

A  => data/http/lang/nl.php +40 -0
@@ 1,40 @@
<?php

// sidebar labels
$L['summary'] = 'samenvatting';
$L['hours'] = 'uren';
$L['days'] = 'dagen';
$L['months'] = 'maanden';

// main table headers
$L['Summary'] = 'Samenvatting';
$L['Top 10 days'] = 'Top 10 dagen';
$L['Last 24 hours'] = 'Afgelopen 24 uur';
$L['Last 30 days'] = 'Afgelopen 30 dagen';
$L['Last 12 months'] = 'Afgelopen 12 maanden';

// traffic table columns
$L['In'] = 'In';
$L['Out'] = 'Uit';
$L['Total'] = 'Totaal';

// summary rows
$L['This hour'] = 'Dit uur';
$L['This day'] = 'Deze dag';
$L['This month'] = 'Deze maand';
$L['All time'] = 'Altijd';

// graph text
$L['Traffic data for'] = 'Data verkeer voor';
$L['bytes in'] = 'bytes in';
$L['bytes out'] = 'bytes uit';

// date formats
$L['datefmt_days'] = '%d %B';
$L['datefmt_days_img'] = '%d';
$L['datefmt_months'] = '%B %Y';
$L['datefmt_months_img'] = '%b';
$L['datefmt_hours'] = '%H:%M';
$L['datefmt_hours_img'] = '%H';
$L['datefmt_top'] = '%d %B %Y';


A  => data/http/localize.php +15 -0
@@ 1,15 @@
<?php
    // setup locale and translation
    setlocale(LC_ALL, $locale);
    require "lang/$language.php";

    function T($str)
    {
        global $L;
        if (isset($L[$str]))
            return $L[$str];
        else
            return $str;
    }

?>

A  => data/http/themes/dark/style.css +21 -0
@@ 1,21 @@
* {margin:0; padding:0;}
body {background:#2f2f2f; font-family:Verdana; font-size:12px;}
#wrap {width: 960px; background:#242424; padding:10px; margin:0 auto; border:1px solid #474747;}
#sidebar {width: 160px; float: left; padding: 3px 4px; color: #fff; background-color: #2F2F2F; border:1px solid #474747; -moz-border-radius:8px;}
#sidebar ul.iface {}
#sidebar li.iface {list-style-type:none; color:#08BB08; text-transform:uppercase; padding-bottom:10px; text-align:center;}
#sidebar a{color:#aaa;}
#sidebar ul.page {}
#sidebar li.page {list-style-type:none; text-transform:none;}
#content {margin-left: 180px; width: 780px;}
#header {padding: 3px; color: #fff; background-color: #2F2F2F; text-align: center; border:1px solid #474747; font-size:14px; font-weight:bold; -moz-border-radius:8px;}
#footer {padding: 3px; color: #fff; background-color: #2F2F2F; text-align: center; border:1px solid #474747; font-size:11px; -moz-border-radius:8px; clear:both; margin-top:10px;}
#footer a {color:#fff;}
#main {padding: 10px 10px 10px 10px; color: #fff; background-color: #2F2F2F; text-align: center; border:1px solid #474747; -moz-border-radius:8px; margin-top:10px;}
#main td {padding:1px 0;}
#main td.numeric_odd {text-align: right; color: #fff; background:#474747;}
#main td.numeric_even {text-align: right; color: #fff; background:#242424;}
#main td.label_odd {color: #fff; background:#474747;}
#main td.label_even {color: #fff; background:#242424;}
#main th.label {color: #fff; padding:2px 0; border-bottom:1px solid #fff;}
#main caption {padding: 3px 0 4px 0; color:#08BB08; text-transform:uppercase;}
\ No newline at end of file

A  => data/http/themes/dark/theme.php +16 -0
@@ 1,16 @@
<?php
    // A dark colorscheme based on a contribution by Mart Visser
    $colorscheme = array(
       'image_background'   => array(  36,  36,  36,   0 ),
       'graph_background'   => array( 220, 220, 230,   0 ),
       'graph_background_2' => array( 205, 205, 220,   0 ),
       'grid_stipple_1'     => array( 140, 140, 140,   0 ),
       'grid_stipple_2'     => array( 200, 200, 200,   0 ),
       'border'             => array(  71,  71,  71,   0 ),
       'text'               => array(  255,  255,  255,   0 ),
       'rx'                 => array(  10, 180,  10,  50 ),
       'rx_border'          => array(  0, 120,  0,  90 ),
       'tx'                  => array( 130, 130, 130,  50 ),
       'tx_border'          => array(  60,  60,  60,  90 )
     );
?>

A  => data/http/themes/espresso/style.css +170 -0
@@ 1,170 @@
body
{
	background-color: #363330;
	margin: 8px;
	padding: 0;
}

#content
{
    width: 898px;
}

#sidebar
{
    position: absolute;
    left: 8px;
    top: 8px;
    width: 160px;
    border-right: 1px solid #D3CAAA;
    border-collapse: collapse;
    float: left;
}

#sidebar ul.iface
{
    margin: 0px;
    padding: 0px;
    border-top: 1px dashed #D3CAAA;
    background-color: #363330;
    color: #D3CAAA;
}

#sidebar li.iface
{
    list-style-type: none;
    margin: 0px;
    padding: 0px;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    border-bottom: 1px dashed #D3CAAA;
}

#sidebar a
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
}

#sidebar ul.page
{
    margin: 0px;
    padding: 0px;
    border-top: 1px dashed #D3CAAA;
}

#sidebar li.page
{
    list-style-type: none;
    margin: 0px;
    padding: 4px;
    border: none;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.75em;
    font-weight: normal;
    text-align: right;
    background-color: #413D39;
    color: #D3CAAA;
}


#header
{
    width: 720px;
    margin-left: 160px;
    padding: 0px 8px 0px 8px;
    border-width: 1px 1px 1px 1px;
    border-style: dashed solid dashed solid;
    border-color: #D3CAAA;
    border-collapse: collapse;
    background-color: #363330;
    color: #D3CAAA;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    text-align: center;
}

#footer
{
    width: 720px;
    margin-left: 160px;
    padding: 2px 8px 2px 8px;
    border-width: 1px 1px 1px 1px;
    border-style: solid;
    border-color: #D3CAAA;
    border-collapse: collapse;
    background-color: #363330;
    color: #D3CAAA;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.70em;
    text-align: center;
}

#main
{
    width: 720px;
    margin-left: 160px;
    padding: 8px 8px 8px 8px;
    border-left: 1px solid #D3CAAA;
    border-right: 1px solid #D3CAAA;
    border-collapse: collapse;
}

#main td
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.8em;
}

#main td.numeric_odd
{
    text-align: right;
    background-color: #756F68;
    color: #D3CAAA;
}

#main td.numeric_even
{
    text-align: right;
    background-color: #544C4A;
    color: #D3CAAA;
}

#main td.label_odd
{
    background-color: #413D39;
    color: #D3CAAA;
}

#main td.label_even
{
    background-color: #5A514F;
    color: #D3CAAA;
}

#main th.label
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    background-color: #413D39;
    color: #D3CAAA;
}

#main caption
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1.25em;
    font-weight: bold;
    padding: 4px;
    color: #D3CAAA;
}

a
{
    text-decoration: none;
    color: #D3CAAA;
}

A  => data/http/themes/espresso/theme.php +17 -0
@@ 1,17 @@
<?php
    // A dark colorscheme based on a contribution by Márcio Bremm
    // It is based also on Espresso (gtkrc theme) by Jesse L. Kay
    $colorscheme = array(
         'image_background'   => array( 065, 061, 057,   0 ),
	 'graph_background'   => array( 117, 111, 104,  30 ),
	 'graph_background_2' => array( 128, 122, 102,  30 ),
	 'grid_stipple_1'     => array( 140, 140, 140,   0 ),
         'grid_stipple_2'     => array( 200, 200, 200,   0 ),
	 'border'             => array( 211, 202, 170,   0 ),
	 'text'               => array( 211, 202, 170,   0 ),
	 'rx'                 => array( 211, 202, 170,  50 ),
	 'rx_border'	      => array(  80,  40,  40,  90 ),
	 'tx'	              => array( 163, 156, 131,  50 ),
	 'tx_border'          => array(  60,  60,  60,  90 )
     );
?>

A  => data/http/themes/light/style.css +159 -0
@@ 1,159 @@
body 
{
    margin: 0;
    padding: 0;
}

#wrap
{
   xwidth: 868px;
}

#sidebar
{
    width: 160px;
    border-right: 1px solid #99b;
    border-collapse: collapse;
    float: left;
}

#sidebar ul.iface
{
    margin: 0;
    padding: 0;
    border-top: 1px solid #99b;    
    color: #000;
    background-color: #eef;
}

#sidebar li.iface
{
    margin: 0;
    padding: 0;
    list-style-type: none;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    xborder-top: 1px solid #99b;
    border-bottom: 1px solid #99b;
}

#sidebar a
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
}

#sidebar ul.page
{
    margin: 0;
    padding: 0;
    border-top: 1px solid #99b;
}

#sidebar li.page 
{
    margin: 0;
    padding: 4px;
    border: none;
    list-style-type: none;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.75em;
    font-weight: normal;
    text-align: right;
    color: #000;    
    background-color: #fff;
}

#content
{
    margin-left: 160px;
    width: 720px;
}


#header
{
    padding: 0px 8px 0px 8px;
    border-width: 1px;
    border-style: solid solid solid solid;
    border-color: #99b;
    border-collapse: collapse;
    color: #000;    
    background-color: #eef;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;    
    text-align: center;
}

#footer
{
    padding: 2px 8px 2px 8px;
    border: 1px solid #99b;
    border-collapse: collapse;
    color: #000;    
    background-color: #eef;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.65em;
    font-weight: bold;    
    text-align: center;
}

#main
{
    padding: 8px;
    border-left: 1px solid #99b;
    border-right: 1px solid #99b;    
    border-collapse: collapse;
}

#main td
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.8em;
}

#main td.numeric_odd
{
    text-align: right;
    color: #000;
    background-color: #eef;
}

#main td.numeric_even
{
    text-align: right;
    color: #000;    
    background-color: #fff;
}

#main td.label_odd
{
    color: #000;
    background-color: #dde;
}

#main td.label_even
{
    color: #000;
    background-color: #eee;
}

#main th.label
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    color: #000;    
    background-color: #dde;
}

#main caption
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1.25em;
    font-weight: bold;
    padding: 4px;
}

A  => data/http/themes/light/theme.php +15 -0
@@ 1,15 @@
<?php
    $colorscheme = array(
         'image_background'   => array( 255, 255, 255,   0 ),
	 'graph_background'   => array( 220, 220, 230,   0 ),
	 'graph_background_2' => array( 205, 205, 220,   0 ),
	 'grid_stipple_1'     => array( 140, 140, 140,   0 ),
         'grid_stipple_2'     => array( 200, 200, 200,   0 ),
	 'border'             => array(   0,   0,   0,   0 ),
	 'text'               => array(   0,   0,   0,   0 ),
	 'rx'                 => array( 190, 190,  20,  50 ),
	 'rx_border'	      => array(  40,  80,  40,  90 ),
	 'tx'	              => array( 130, 160, 100,  50 ),
	 'tx_border'          => array(  80,  40,  40,  90 )
     );
?>

A  => data/http/themes/red/style.css +170 -0
@@ 1,170 @@
body
{
	background-color: #D2D2D2;
	margin: 8px;
	padding: 0;
}

#content
{
    width: 898px;
}

#sidebar
{
    position: absolute;
    left: 8px;
    top: 8px;
    width: 160px;
    border-right: 1px solid #82001D;
    border-collapse: collapse;
    float: left;
}

#sidebar ul.iface
{
    margin: 0px;
    padding: 0px;
    border-top: 1px dashed #82001D;
    background-color: #D2D2D2;
    color: #82001D;
}

#sidebar li.iface
{
    list-style-type: none;
    margin: 0px;
    padding: 0px;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    border-bottom: 1px dashed #82001D;
}

#sidebar a
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
}

#sidebar ul.page
{
    margin: 0px;
    padding: 0px;
    border-top: 1px dashed #82001D;
}

#sidebar li.page
{
    list-style-type: none;
    margin: 0px;
    padding: 4px;
    border: none;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.75em;
    font-weight: normal;
    text-align: right;
    background-color: #C1C1C1;
    color: #82001D;
}


#header
{
    width: 720px;
    margin-left: 160px;
    padding: 0px 8px 0px 8px;
    border-width: 1px 1px 1px 1px;
    border-style: dashed solid dashed solid;
    border-color: #82001D;
    border-collapse: collapse;
    background-color: #D2D2D2;
    color: #82001D;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    text-align: center;
}

#footer
{
    width: 720px;
    margin-left: 160px;
    padding: 2px 8px 2px 8px;
    border-width: 1px 1px 1px 1px;
    border-style: solid;
    border-color: #82001D;
    border-collapse: collapse;
    background-color: #D2D2D2;
    color: #82001D;
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.70em;
    text-align: center;
}

#main
{
    width: 720px;
    margin-left: 160px;
    padding: 8px 8px 8px 8px;
    border-left: 1px solid #82001D;
    border-right: 1px solid #82001D;
    border-collapse: collapse;
}

#main td
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 0.8em;
}

#main td.numeric_odd
{
    text-align: right;
    background-color: #C9C9C9;
    color: #82001D;
}

#main td.numeric_even
{
    text-align: right;
    background-color: #CFCFCF;
    color: #82001D;
}

#main td.label_odd
{
    background-color: #A6A6A6;
    color: #82001D;
}

#main td.label_even
{
    background-color: #C1C1C1;
    color: #82001D;
}

#main th.label
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1em;
    font-weight: bold;
    background-color: #A6A6A6;
    color: #82001D;
}

#main caption
{
    font-family: 'Trebuchet MS', Verdana, sans-serif;
    font-size: 1.25em;
    font-weight: bold;
    padding: 4px;
    color: #82001D;
}

a
{
    text-decoration: none;
    color: #A80022;
}

A  => data/http/themes/red/theme.php +16 -0
@@ 1,16 @@
<?php
    // A red colorscheme based on a contribution by Enrico Tröger
    $colorscheme = array(
         'image_background'   => array( 225, 225, 225,   0 ),
	 'graph_background'   => array( 220, 220, 230,   0 ),
	 'graph_background_2' => array( 205, 205, 220,   0 ),
	 'grid_stipple_1'     => array( 140, 140, 140,   0 ),
         'grid_stipple_2'     => array( 200, 200, 200,   0 ),
	 'border'             => array(   0,   0,   0,   0 ),
	 'text'               => array(   0,   0,   0,   0 ),
	 'rx'                 => array( 190,  20,  20,  50 ),
	 'rx_border'	      => array(  80,  40,  40,  90 ),
	 'tx'	              => array( 130, 130, 130,  50 ),
	 'tx_border'          => array(  60,  60,  60,  90 )
     );
?>

A  => data/http/vera_copyright.txt +124 -0
@@ 1,124 @@
Bitstream Vera Fonts Copyright

The fonts have a generous copyright, allowing derivative works (as
long as "Bitstream" or "Vera" are not in the names), and full
redistribution (so long as they are not *sold* by themselves). They
can be be bundled, redistributed and sold with any software.

The fonts are distributed under the following copyright:

Copyright
=========

Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
Vera is a trademark of Bitstream, Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of the fonts accompanying this license ("Fonts") and associated
documentation files (the "Font Software"), to reproduce and distribute
the Font Software, including without limitation the rights to use,
copy, merge, publish, distribute, and/or sell copies of the Font
Software, and to permit persons to whom the Font Software is furnished
to do so, subject to the following conditions:

The above copyright and trademark notices and this permission notice
shall be included in all copies of one or more of the Font Software
typefaces.

The Font Software may be modified, altered, or added to, and in
particular the designs of glyphs or characters in the Fonts may be
modified and additional glyphs or characters may be added to the
Fonts, only if the fonts are renamed to names not containing either
the words "Bitstream" or the word "Vera".

This License becomes null and void to the extent applicable to Fonts
or Font Software that has been modified and is distributed under the
"Bitstream Vera" names.

The Font Software may be sold as part of a larger software package but
no copy of one or more of the Font Software typefaces may be sold by
itself.

THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.

Except as contained in this notice, the names of Gnome, the Gnome
Foundation, and Bitstream Inc., shall not be used in advertising or
otherwise to promote the sale, use or other dealings in this Font
Software without prior written authorization from the Gnome Foundation
or Bitstream Inc., respectively. For further information, contact:
fonts at gnome dot org.

Copyright FAQ
=============

   1. I don't understand the resale restriction... What gives?

      Bitstream is giving away these fonts, but wishes to ensure its
      competitors can't just drop the fonts as is into a font sale system
      and sell them as is. It seems fair that if Bitstream can't make money
      from the Bitstream Vera fonts, their competitors should not be able to
      do so either. You can sell the fonts as part of any software package,
      however.

   2. I want to package these fonts separately for distribution and
      sale as part of a larger software package or system.  Can I do so?

      Yes. A RPM or Debian package is a "larger software package" to begin 
      with, and you aren't selling them independently by themselves. 
      See 1. above.

   3. Are derivative works allowed?
      Yes!

   4. Can I change or add to the font(s)?
      Yes, but you must change the name(s) of the font(s).

   5. Under what terms are derivative works allowed?

      You must change the name(s) of the fonts. This is to ensure the
      quality of the fonts, both to protect Bitstream and Gnome. We want to
      ensure that if an application has opened a font specifically of these
      names, it gets what it expects (though of course, using fontconfig,
      substitutions could still could have occurred during font
      opening). You must include the Bitstream copyright. Additional
      copyrights can be added, as per copyright law. Happy Font Hacking!

   6. If I have improvements for Bitstream Vera, is it possible they might get 
       adopted in future versions?

      Yes. The contract between the Gnome Foundation and Bitstream has
      provisions for working with Bitstream to ensure quality additions to
      the Bitstream Vera font family. Please contact us if you have such
      additions. Note, that in general, we will want such additions for the
      entire family, not just a single font, and that you'll have to keep
      both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add
      glyphs to the font, they must be stylistically in keeping with Vera's
      design. Vera cannot become a "ransom note" font. Jim Lyles will be
      providing a document describing the design elements used in Vera, as a
      guide and aid for people interested in contributing to Vera.

   7. I want to sell a software package that uses these fonts: Can I do so?

      Sure. Bundle the fonts with your software and sell your software
      with the fonts. That is the intent of the copyright.

   8. If applications have built the names "Bitstream Vera" into them, 
      can I override this somehow to use fonts of my choosing?

      This depends on exact details of the software. Most open source
      systems and software (e.g., Gnome, KDE, etc.) are now converting to
      use fontconfig (see www.fontconfig.org) to handle font configuration,
      selection and substitution; it has provisions for overriding font
      names and subsituting alternatives. An example is provided by the
      supplied local.conf file, which chooses the family Bitstream Vera for
      "sans", "serif" and "monospace".  Other software (e.g., the XFree86
      core server) has other mechanisms for font substitution.


A  => data/http/vnstat.php +211 -0
@@ 1,211 @@
<?php
    //
    // vnStat PHP frontend (c)2006-2010 Bjorge Dijkstra (bjd@jooz.net)
    //
    // This program is free software; you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation; either version 2 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    // GNU General Public License for more details.
    //
    // You should have received a copy of the GNU General Public License
    // along with this program; if not, write to the Free Software
    // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    //
    //
    // see file COPYING or at http://www.gnu.org/licenses/gpl.html 
    // for more information.
    //
        
    //
    // Valid values for other parameters you can pass to the script.
    // Input parameters will always be limited to one of the values listed here.
    // If a parameter is not provided or invalid it will revert to the default,
    // the first parameter in the list.
    //
    if (isset($_SERVER['PHP_SELF']))
    {
	$script = $_SERVER['PHP_SELF'];
    }
    elseif (isset($_SERVER['SCRIPT_NAME']))
    {
	$script = $_SERVER['SCRIPT_NAME'];
    }
    else
    {
	die('can\'t determine script name!');
    }
    
    $page_list  = array('s','h','d','m');
    
    $graph_list = array('large','small','none');
    
    $page_title['s'] = T('summary');
    $page_title['h'] = T('hours');
    $page_title['d'] = T('days');
    $page_title['m'] = T('months');
    

    //
    // functions
    //
    function validate_input()
    {
        global $page,  $page_list;
        global $iface, $iface_list;
        global $graph, $graph_list;
	global $colorscheme, $style;
        //
        // get interface data
        //
        $page = isset($_GET['page']) ? $_GET['page'] : '';
        $iface = isset($_GET['if']) ? $_GET['if'] : '';
        $graph = isset($_GET['graph']) ? $_GET['graph'] : '';
        $style = isset($_GET['style']) ? $_GET['style'] : '';

        if (!in_array($page, $page_list))
        {
            $page = $page_list[0];
        }

        if (!in_array($iface, $iface_list))
        {
            $iface = $iface_list[0];
        }

        if (!in_array($graph, $graph_list))
        {
            $graph = $graph_list[0];
        }

	$tp = "./themes/$style";
        if (!is_dir($tp) || !file_exists("$tp/theme.php"))
        {
	    $style = DEFAULT_COLORSCHEME;
        }
    }
    

    function get_vnstat_data()    
    {
        global $iface, $vnstat_bin, $data_dir;
        global $hour,$day,$month,$top,$summary;

        if (!isset($vnstat_bin) || $vnstat_bin == '')
        {
	    if (file_exists("$data_dir/vnstat_dump_$iface"))
	    {
        	$vnstat_data = file("$data_dir/vnstat_dump_$iface");
	    }	    
	    else
	    {
		$vnstat_data = array();
	    }
        }
        else
        {
            $fd = popen("$vnstat_bin --dumpdb -i $iface", "r");
            $buffer = '';
            while (!feof($fd)) {
                $buffer .= fgets($fd);
            }
            $vnstat_data = explode("\n", $buffer);
            pclose($fd);
        }


        $day = array();
        $hour = array();
        $month = array();
        $top = array();

        //
        // extract data
        //
        foreach($vnstat_data as $line) 
        {
            $d = explode(';', trim($line));
            if ($d[0] == 'd')
            {
                $day[$d[1]]['time']  = $d[2];
                $day[$d[1]]['rx']    = $d[3] * 1024 + $d[5];
                $day[$d[1]]['tx']    = $d[4] * 1024 + $d[6];
                $day[$d[1]]['act']   = $d[7];
                if ($d[2] != 0)
                {
                    $day[$d[1]]['label'] = strftime(T('datefmt_days'),$d[2]);
                    $day[$d[1]]['img_label'] = strftime(T('datefmt_days_img'), $d[2]);
                }
                else
                {
                    $day[$d[1]]['label'] = '';
                    $day[$d[1]]['img_label'] = '';          
                }           
            }
            else if ($d[0] == 'm')
            {
                $month[$d[1]]['time'] = $d[2];
                $month[$d[1]]['rx']   = $d[3] * 1024 + $d[5];
                $month[$d[1]]['tx']   = $d[4] * 1024 + $d[6];
                $month[$d[1]]['act']  = $d[7];
                if ($d[2] != 0)
                {
                    $month[$d[1]]['label'] = strftime(T('datefmt_months'), $d[2]);
                    $month[$d[1]]['img_label'] = strftime(T('datefmt_months_img'), $d[2]);
                }
                else
                {
                    $month[$d[1]]['label'] = '';
                    $month[$d[1]]['img_label'] = '';            
                }
            }
            else if ($d[0] == 'h')
            {
                $hour[$d[1]]['time'] = $d[2];
                $hour[$d[1]]['rx']   = $d[3];
                $hour[$d[1]]['tx']   = $d[4];
                $hour[$d[1]]['act']  = 1;
                if ($d[2] != 0)
                {
                    $st = $d[2] - ($d[2] % 3600);
                    $et = $st + 3600;
                    $hour[$d[1]]['label'] = strftime(T('datefmt_hours'), $st).' - '.strftime(T('datefmt_hours'), $et);
                    $hour[$d[1]]['img_label'] = strftime(T('datefmt_hours_img'), $d[2]);
                }
                else
                {
                    $hour[$d[1]]['label'] = '';
                    $hour[$d[1]]['img_label'] = '';
                }
            }
            else if ($d[0] == 't')
            {   
                $top[$d[1]]['time'] = $d[2];
                $top[$d[1]]['rx']   = $d[3] * 1024 + $d[5];
                $top[$d[1]]['tx']   = $d[4] * 1024 + $d[6];
                $top[$d[1]]['act']  = $d[7];
                $top[$d[1]]['label'] = strftime(T('datefmt_top'), $d[2]);
                $top[$d[1]]['img_label'] = '';
            }
            else
            {
                $summary[$d[0]] = isset($d[1]) ? $d[1] : '';
            }
        }
        if (count($day) == 0)
            $day[0] = 'nodata';
        rsort($day);

        if (count($month) == 0)
            $month[0] = 'nodata';
        rsort($month);

        if (count($hour) == 0)
            $hour[0] = 'nodata';
        rsort($hour);
    }
?>

A  => docker-compose.yml +36 -0
@@ 1,36 @@
version: '3'
services:
  vnstatd:
    build: ./build/vnstatd
    volumes:
      - ./data/vnstatd:/var/lib/vnstat
    privileged: true
    network_mode: host
    restart: unless-stopped
  web:
    image: nginx
    volumes:
      - ./data/http:/etc/nginx/html
      - ./data/conf:/etc/nginx/conf.d
    networks:
      internal:
      export-http:
        aliases:
          - vnstat
    restart: unless-stopped
    depends_on:
      - php
  php:
    build: ./build/php
    volumes:
      - ./data/http:/etc/nginx/html
      - ./data/vnstatd:/var/lib/vnstat
    networks:
      internal:
        aliases:
          - php
    restart: unless-stopped
networks:
  internal:
  export-http:
    external: true