1 <%= include( '/elements/header.html', 'RADIUS Sessions',
2 include('/elements/menubar.html',
3 'Main menu' => $p, # popurl(2),
14 #sort of false laziness w/cust_pay.cgi
17 if ( $cgi->param('beginning')
18 && $cgi->param('beginning') =~ /^([ 0-9\-\/]{0,10})$/ ) {
19 $beginning = str2time($1);
21 if ( $cgi->param('ending')
22 && $cgi->param('ending') =~ /^([ 0-9\-\/]{0,10})$/ ) {
23 $ending = str2time($1) + 86399;
25 if ( $cgi->param('begin') && $cgi->param('begin') =~ /^(\d+)$/ ) {
28 if ( $cgi->param('end') && $cgi->param('end') =~ /^(\d+)$/ ) {
32 my $cgi_svc_acct = '';
33 if ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
34 $cgi_svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $1 } );
35 } elsif ( $cgi->param('username') =~ /^([^@]+)\@([^@]+)$/ ) {
36 my %search = { 'username' => $1 };
37 my $svc_domain = qsearchs('svc_domain', { 'domain' => $2 } );
39 $search{'domsvc'} = $svc_domain->svcnum;
41 delete $search{'username'};
43 $cgi_svc_acct = qsearchs( 'svc_acct', \%search )
45 } elsif ( $cgi->param('username') =~ /^(.+)$/ ) {
46 $cgi_svc_acct = qsearchs( 'svc_acct', { 'username' => $1 } );
50 if ( $cgi->param('ip') =~ /^((\d+\.){3}\d+)$/ ) {
54 my $prefix = $cgi->param('prefix');
56 if ( $prefix =~ /^(\d+)$/ ) {
58 $prefix = "011$prefix" unless $prefix =~ /^1/;
64 # field formatting subroutines
67 my %user2svc_acct = ();
68 my $user_format = sub {
69 my ( $user, $session, $part_export ) = @_;
72 if ( exists $user2svc_acct{$user} ) {
73 $svc_acct = $user2svc_acct{$user};
76 if ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
78 if ( $user =~ /^([^@]+)\@([^@]+)$/ ) {
79 $search{'username'} = $1;
82 $search{'username'} = $user;
83 $domain = $session->{'realm'};
85 my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
87 $search{'domsvc'} = $svc_domain->svcnum;
89 delete $search{'username'};
91 } elsif ( $part_export->exporttype eq 'sqlradius' ) {
92 $search{'username'} = $user;
94 die 'unknown export type '. $part_export->exporttype.
95 " for $part_export\n";
99 grep { qsearchs( 'export_svc', {
100 'exportnum' => $part_export->exportnum,
101 'svcpart' => $_->cust_svc->svcpart,
103 } qsearch( 'svc_acct', \%search );
105 warn 'multiple svc_acct records for user $user found; '.
106 'using first arbitrarily'
107 if scalar(@svc_acct) > 1;
108 $user2svc_acct{$user} = $svc_acct = shift @svc_acct;
114 my $svcnum = $svc_acct->svcnum;
115 qq(<A HREF="${p}view/svc_acct.cgi?$svcnum"><B>$user</B></A>);
122 my $customer_format = sub {
123 my( $unused, $session ) = @_;
124 return ' ' unless exists $user2svc_acct{$session->{'username'}};
125 my $svc_acct = $user2svc_acct{$session->{'username'}};
126 my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
127 return ' ' unless $cust_pkg;
128 my $cust_main = $cust_pkg->cust_main;
130 qq!<A HREF="${p}view/cust_main.cgi?!. $cust_main->custnum. '">'.
131 $cust_pkg->cust_main->name. '</A>';
134 my $time_format = sub {
136 return ' ' if $time == 0;
137 my $pretty = time2str('%T%P %a %b %o %Y', $time );
138 $pretty =~ s/ (\d)(st|dn|rd|th)/$1$2/;
142 my $duration_format = sub {
144 my $hour = int($seconds/3600);
145 my $min = int( ($seconds%3600) / 60 );
146 my $sec = $seconds%60;
147 '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0>'.
148 '<TR><TD ALIGN="right">'.
149 ( $hour ? "<B>$hour</B>h" : ' ' ).
150 '</TD><TD ALIGN="right">'.
151 ( ( $hour || $min ) ? "<B>$min</B>m" : ' ' ).
152 '</TD><TD ALIGN="right">'.
154 '</TD></TR></TABLE>';
157 my $octets_format = sub {
159 my $megs = $octets / 1048576;
160 sprintf('<B>%.3f</B> megs', $megs);
161 #my $gigs = $octets / 1073741824
162 #sprintf('<B>%.3f</B> gigabytes', $gigs);
169 tie my %fields, 'Tie::IxHash',
172 attrib => 'UserName',
184 fmt => $customer_format,
187 'framedipaddress' => {
188 name => 'IP Address',
189 attrib => 'Framed-IP-Address',
190 fmt => sub { my $ip = shift;
191 length($ip) ? $ip : ' ';
196 name => 'Start time',
197 attrib => 'Acct-Start-Time',
202 name => 'End time',
203 attrib => 'Acct-Stop-Time',
207 'acctsessiontime' => {
209 attrib => 'Acct-Session-Time',
210 fmt => $duration_format,
213 'acctinputoctets' => {
214 name => 'Upload', # (from user)',
215 attrib => 'Acct-Input-Octets',
216 fmt => $octets_format,
219 'acctoutputoctets' => {
220 name => 'Download', # (to user)',
221 attrib => 'Acct-Output-Octets',
222 fmt => $octets_format,
226 $fields{$_}->{fmt} ||= sub { length($_[0]) ? shift : ' '; }
227 foreach keys %fields;
230 # and finally, display the thing
233 foreach my $part_export (
234 #grep $_->can('usage_sessions'), qsearch( 'part_export' )
235 qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ),
236 qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } )
240 my $efields = tie my %efields, 'Tie::IxHash', %fields;
241 delete $efields{'framedipaddress'} if $part_export->option('hide_ip');
242 if ( $part_export->option('hide_data') ) {
243 delete $efields{$_} foreach qw(acctinputoctets acctoutputoctets);
245 if ( $part_export->option('show_called_station') ) {
246 $efields->Splice(1, 0,
247 'calledstationid' => {
248 'name' => 'Destination',
249 'attrib' => 'Called-Station-ID',
251 sub { length($_[0]) ? shift : ' '; },
259 <%= $part_export->exporttype %> to <%= $part_export->machine %><BR>
260 <%= include( '/elements/table.html' ) %>
262 <% foreach my $field ( keys %efields ) { %>
264 <%= $efields{$field}->{name} %><BR>
265 <FONT SIZE=-2><%= $efields{$field}->{attrib} %></FONT>
269 <% foreach my $session (
270 @{ $part_export->usage_sessions(
271 $beginning, $ending, $cgi_svc_acct, $ip, $prefix, ) }
275 <% foreach my $field ( keys %efields ) { %>
276 <TD ALIGN="<%= $efields{$field}->{align} %>">
277 <%= &{ $efields{$field}->{fmt} }( $session->{$field},