1 <& /elements/header.html, 'RADIUS Sessions' &>
4 % # and finally, display the thing
7 % foreach my $part_export ( @part_export ) {
11 % my $efields = tie my %efields, 'Tie::IxHash', %fields;
12 % delete $efields{'framedipaddress'} if $part_export->option('hide_ip');
13 % if ( $part_export->option('hide_data') ) {
14 % delete $efields{$_} foreach qw(acctinputoctets acctoutputoctets);
17 <FONT CLASS="fsinnerbox-title">
18 <% $part_export->exportname || $part_export->exporttype |h %>
19 <% $part_export->machine ? ' to '. $part_export->machine : '' |h %>
22 <& /elements/table-grid.html &>
23 % my $bgcolor1 = '#eeeeee';
24 % my $bgcolor2 = '#ffffff';
28 % foreach my $field ( keys %efields ) {
30 <TH CLASS="grid" BGCOLOR="#cccccc">
31 <% $efields{$field}->{name} %><BR>
32 <FONT SIZE=-2><% $efields{$field}->{attrib} %></FONT>
38 % foreach my $session (
39 % @{ $part_export->usage_sessions( {
40 % 'stoptime_start' => $beginning,
41 % 'stoptime_end' => $ending,
42 % 'session_status' => $status,
43 % 'starttime_start' => $starttime_beginning,
44 % 'starttime_end' => $starttime_ending,
47 % 'prefix' => $prefix,
48 % 'summarize' => $summarize,
52 % if ( $bgcolor eq $bgcolor1 ) {
53 % $bgcolor = $bgcolor2;
55 % $bgcolor = $bgcolor1;
59 % foreach my $field ( keys %efields ) {
60 % my $html = &{ $efields{$field}->{fmt} }( $session->{$field},
64 % my $class = ( $html =~ /<TABLE/ ? 'inv' : 'grid' );
66 <TD CLASS="<%$class%>" BGCOLOR="<% $bgcolor %>" ALIGN="<% $efields{$field}->{align} %>">
82 unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
89 $summarize = 1 if $cgi->param('summarize') eq 'Y';
91 #sort of false laziness w/cust_pay.cgi
92 my( $beginning, $ending ) = ( '', '' );
93 if ( $cgi->param('stoptime_beginning')
94 && $cgi->param('stoptime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
95 $beginning = parse_datetime($1);
97 if ( $cgi->param('stoptime_ending')
98 && $cgi->param('stoptime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
99 $ending = parse_datetime($1); # + 86399;
101 if ( $cgi->param('begin') && $cgi->param('begin') =~ /^(\d+)$/ ) {
104 if ( $cgi->param('end') && $cgi->param('end') =~ /^(\d+)$/ ) {
109 if ( $cgi->param('session_status') =~ /^(closed|open)$/ ) {
113 my( $starttime_beginning, $starttime_ending ) = ( '', '' );
114 if ( $cgi->param('starttime_beginning')
115 && $cgi->param('starttime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
116 $starttime_beginning = parse_datetime($1);
118 if ( $cgi->param('starttime_ending')
119 && $cgi->param('starttime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
120 $starttime_ending = parse_datetime($1); # + 86399;
124 if ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
125 $cgi_svc = qsearchs( 'svc_acct', { 'svcnum' => $1 } )
126 || qsearchs( 'svc_broadband', { 'svcnum' => $1 } );
127 } elsif ( $cgi->param('username') =~ /^([^@]+)\@([^@]+)$/ ) {
128 my %search = { 'username' => $1 };
129 my $svc_domain = qsearchs('svc_domain', { 'domain' => $2 } );
131 $search{'domsvc'} = $svc_domain->svcnum;
133 delete $search{'username'};
135 $cgi_svc = qsearchs( 'svc_acct', \%search )
137 } elsif ( $cgi->param('username') =~ /^(.+)$/ ) {
138 $cgi_svc = qsearchs( 'svc_acct', { 'username' => $1 } );
141 my @part_export = ();
143 my $part_svc = $cgi_svc->cust_svc->part_svc;
145 $part_svc->part_export('sqlradius'),
146 $part_svc->part_export('sqlradius_withdomain'),
147 $part_svc->part_export('broadband_sqlradius'),
151 #grep $_->can('usage_sessions'), qsearch( 'part_export' )
152 qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ),
153 qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } ),
154 qsearch( 'part_export', { 'exporttype' => 'broadband_sqlradius' } ),
159 if ( $cgi->param('ip') =~ /^((\d+\.){3}\d+)$/ ) {
163 my $prefix = $cgi->param('prefix');
165 if ( $prefix =~ /^(\d+)$/ ) {
167 $prefix = "011$prefix" unless $prefix =~ /^1/;
173 # field formatting subroutines
177 my $user_format = sub {
178 my ( $user, $session, $part_export ) = @_;
181 if ( exists $user2svc{$user} ) {
182 $svc = $user2svc{$user};
185 if ( $part_export->exporttype eq 'broadband_sqlradius' ) {
187 ( my $mac = $user ) =~ s/[^0-9a-f]//ig;
190 grep { qsearchs( 'export_svc', {
191 'exportnum' => $part_export->exportnum,
192 'svcpart' => $_->cust_svc->svcpart,
194 } qsearch( 'svc_broadband', {
195 mac_addr => { op=>'ILIKE', value=>$mac }
198 if ( @svc_broadband ) {
199 warn 'multiple svc_broadband records for user $user found; '.
200 'using first arbitrarily'
201 if scalar(@svc_broadband) > 1;
202 $user2svc{$user} = $svc = shift @svc_broadband;
208 if ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
210 if ( $user =~ /^([^@]+)\@([^@]+)$/ ) {
211 $search{'username'} = $1;
214 $search{'username'} = $user;
215 $domain = $session->{'realm'};
217 my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
219 $search{'domsvc'} = $svc_domain->svcnum;
221 delete $search{'username'};
223 } elsif ( $part_export->exporttype eq 'sqlradius' ) {
224 $search{'username'} = $user;
226 die 'unknown export type '. $part_export->exporttype.
227 " for $part_export\n";
229 if ( keys %search ) {
231 grep { qsearchs( 'export_svc', {
232 'exportnum' => $part_export->exportnum,
233 'svcpart' => $_->cust_svc->svcpart,
235 } qsearch( 'svc_acct', \%search );
237 warn 'multiple svc_acct records for user $user found; '.
238 'using first arbitrarily'
239 if scalar(@svc_acct) > 1;
240 $user2svc{$user} = $svc = shift @svc_acct;
248 $user = encode_entities($user);
252 #i should use svc_link, but that's expensive per-user
253 my $svcnum = $svc->svcnum;
254 my $table = $svc->table;
255 qq(<A HREF="${p}view/$table.cgi?$svcnum"><B>$user</B></A>);
263 my $customer_format = sub {
264 my( $unused, $session ) = @_;
265 return ' ' unless exists $user2svc{$session->{'username'}};
266 my $svc = $user2svc{$session->{'username'}};
267 my $cust_pkg = $svc->cust_svc->cust_pkg;
268 return ' ' unless $cust_pkg;
269 my $cust_main = $cust_pkg->cust_main;
271 qq!<A HREF="${p}view/cust_main.cgi?!. $cust_main->custnum. '">'.
272 encode_entities($cust_pkg->cust_main->name). '</A>';
275 my $time_format = sub {
277 return ' ' if $time == 0;
278 my $pretty = time2str('%T%P %a %b %o %Y', $time );
279 $pretty =~ s/ (\d)(st|dn|rd|th)/$1$2/;
283 my $time_format_or_open = sub {
285 return '<CENTER>OPEN</CENTER>' if $time == 0;
286 &{$time_format}($time);
289 my $duration_format = sub {
291 return '' if $seconds eq ''; # open session
292 my $hour = int($seconds/3600);
293 my $min = int( ($seconds%3600) / 60 );
294 my $sec = $seconds%60;
295 '<TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0>'.
296 '<TR><TD CLASS="inv" ALIGN="right">'.
297 ( $hour ? "<B>$hour</B>h" : ' ' ).
298 '</TD><TD CLASS="inv" ALIGN="right">'.
299 ( ( $hour || $min ) ? "<B>$min</B>m" : ' ' ).
300 '</TD><TD CLASS="inv" ALIGN="right">'.
302 '</TD></TR></TABLE>';
305 my $octets_format = sub {
307 #my $megs = $octets / 1048576;
308 #sprintf('<B>%.3f</B> megs', $megs);
309 my $gigs = $octets / 1073741824;
310 sprintf('<B>%.3f</B> gigs', $gigs);
313 my $mac_format = sub {
315 if ( $value =~ /^\s*(([\dA-F]{2}[\-:]){5}[\dA-F]{2})/i
316 and my $vendor = Net::MAC::Vendor::lookup($1)
319 return encode_entities($value).
320 ' <span style="white-space: nowrap">('.
321 encode_entities($vendor->[0]).
324 length($value) ? encode_entities($value) : ' ';
335 tie %fields, 'Tie::IxHash',
338 attrib => 'UserName',
345 fmt => $customer_format,
348 'acctsessiontime' => {
350 attrib => 'Acct-Session-Time',
351 fmt => $duration_format,
354 'acctinputoctets' => {
355 name => 'Upload', # (from user)',
356 attrib => 'Acct-Input-Octets',
357 fmt => $octets_format,
360 'acctoutputoctets' => {
361 name => 'Download', # (to user)',
362 attrib => 'Acct-Output-Octets',
363 fmt => $octets_format,
370 tie %fields, 'Tie::IxHash',
373 attrib => 'UserName',
385 fmt => $customer_format,
388 'framedipaddress' => {
389 name => 'IP Address',
390 attrib => 'Framed-IP-Address',
391 fmt => sub { my $ip = shift;
392 length($ip) ? $ip : ' ';
396 'callingstationid' => {
397 name => 'Source or MAC',
398 attrib => 'Calling-Station-Id',
402 'calledstationid' => {
403 name => 'Destination',
404 attrib => 'Called-Station-ID',
409 name => 'Start time',
410 attrib => 'Acct-Start-Time',
415 name => 'End time',
416 attrib => 'Acct-Stop-Time',
417 fmt => $time_format_or_open,
420 'acctsessiontime' => {
422 attrib => 'Acct-Session-Time',
423 fmt => $duration_format,
426 'acctinputoctets' => {
427 name => 'Upload', # (from user)',
428 attrib => 'Acct-Input-Octets',
429 fmt => $octets_format,
432 'acctoutputoctets' => {
433 name => 'Download', # (to user)',
434 attrib => 'Acct-Output-Octets',
435 fmt => $octets_format,
440 $fields{$_}->{fmt} ||= sub { length($_[0]) ? encode_entities(shift) : ' '; }
441 foreach keys %fields;