From a205ffec778bd42eb084bcffec6884063263f634 Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Fri, 22 Mar 2013 13:33:44 -0700 Subject: [PATCH] SIM/KI inventory for Huawei HLR export, #21514 --- FS/FS/part_export.pm | 11 +++ FS/FS/part_export/huawei_hlr.pm | 110 +++++++++++++++++++++ httemplate/browse/part_export.cgi | 15 +++ httemplate/elements/progress-init.html | 2 +- .../misc/part_export/huawei_hlr-import_sim.html | 52 ++++++++++ .../part_export/process/huawei_hlr-import_sim.html | 10 ++ 6 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 httemplate/misc/part_export/huawei_hlr-import_sim.html create mode 100644 httemplate/misc/part_export/process/huawei_hlr-import_sim.html diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm index 3eee37f71..15ce9c059 100644 --- a/FS/FS/part_export.pm +++ b/FS/FS/part_export.pm @@ -601,6 +601,17 @@ DEFAULTSREF is a hashref with the same keys where true values indicate the setting is a default (and thus can be displayed in the UI with less emphasis, or hidden by default). +=item actions + +Adds one or more "action" links to the export's display in +browse/part_export.cgi. Should return pairs of values. The first is +the link label; the second is the Mason path to a document to load. +The document will show in a popup. + +=cut + +sub actions { } + =cut =item weight diff --git a/FS/FS/part_export/huawei_hlr.pm b/FS/FS/part_export/huawei_hlr.pm index d231567c1..007981880 100644 --- a/FS/FS/part_export/huawei_hlr.pm +++ b/FS/FS/part_export/huawei_hlr.pm @@ -5,8 +5,12 @@ use Tie::IxHash; use FS::Record qw(qsearch qsearchs dbh); use FS::part_export; use FS::svc_phone; +use FS::inventory_class; +use FS::inventory_item; use IO::Socket::INET; use Data::Dumper; +use MIME::Base64 qw(decode_base64); +use Storable qw(thaw); use strict; @@ -18,6 +22,20 @@ tie my %options, 'Tie::IxHash', 'pwd' => { label=>'Operator password' }, 'tplid' => { label=>'Template number' }, 'hlrsn' => { label=>'HLR serial number' }, + 'k4sno' => { label=>'K4 serial number' }, + 'cardtype' => { label => 'Card type', + type => 'select', + options=> ['SIM', 'USIM'] + }, + 'alg' => { label => 'Authentication algorithm', + type => 'select', + options=> ['COMP128_1', + 'COMP128_2', + 'COMP128_3', + 'MILENAGE' ], + }, + 'opcvalue' => { label=>'OPC value (for MILENAGE only)' }, + 'opsno' => { label=>'OP serial number (for MILENAGE only)' }, 'timeout' => { label=>'Timeout (seconds)', default => 120 }, 'debug' => { label=>'Enable debugging', type=>'checkbox' }, ; @@ -33,6 +51,10 @@ set on the service, and the template must exist. END ); +sub actions { + 'Import SIMs' => 'misc/part_export/huawei_hlr-import_sim.html' +} + sub _export_insert { my( $self, $svc_phone ) = (shift, shift); # svc_phone::check should ensure phonenum and sim_imsi are numeric @@ -227,4 +249,92 @@ sub command { \%return; } +sub process_import_sim { + my $job = shift; + my $param = thaw(decode_base64(shift)); + $param->{'job'} = $job; + my $exportnum = delete $param->{'exportnum'}; + my $export = __PACKAGE__->by_key($exportnum); + my $file = delete $param->{'uploaded_files'}; + $file =~ s/^file://; + my $dir = $FS::UID::cache_dir .'/cache.'. $FS::UID::datasrc; + open( $param->{'filehandle'}, '<', "$dir/$file" ) + or die "unable to open '$file'.\n"; + my $error = $export->import_sim($param); +} + +sub import_sim { + # import a SIM list + local $FS::UID::AutoCommit = 1; # yes, 1 + my $self = shift; + my $param = shift; + my $job = $param->{'job'}; + my $fh = $param->{'filehandle'}; + my @lines = $fh->getlines; + + my @command = 'ADD KI'; + push @command, ('HLRSN', $self->option('hlrsn')) if $self->option('hlrsn'); + + my @args = ('OPERTYPE', 'ADD'); + push @args, ('K4SNO', $self->option('k4sno')) if $self->option('k4sno'); + push @args, ('CARDTYPE', $self->option('cardtype'), + 'ALG', $self->option('alg')); + push @args, ('OPCVALUE', $self->option('opcvalue'), + 'OPSNO', $self->option('opsno')) + if $self->option('alg') eq 'MILENAGE'; + + my $agentnum = $param->{'agentnum'}; + my $classnum = $param->{'classnum'}; + my $class = FS::inventory_class->by_key($classnum) + or die "bad inventory class $classnum\n"; + my %existing = map { $_->item, 1 } + qsearch('inventory_item', { 'classnum' => $classnum }); + + my $socket = $self->login; + my $num=0; + my $total = scalar(@lines); + foreach my $line (@lines) { + $num++; + $job->update_statustext(int(100*$num/$total).',Provisioning IMSIs...') + if $job; + + chomp $line; + my ($imsi, $iccid, $pin1, $puk1, $pin2, $puk2, $acc, $ki) = + split(' ', $line); + # the only fields we really care about are the IMSI and KI. + if ($imsi !~ /^\d{15}$/ or $ki !~ /^[0-9A-Z]{32}$/) { + warn "misspelled line in SIM file: $line\n"; + next; + } + if ($existing{$imsi}) { + warn "IMSI $imsi already in inventory, skipped\n"; + next; + } + + # push IMSI/KI to the HLR + my $return = $self->command($socket, + @command, + 'IMSI', $imsi, + 'KIVALUE', $ki, + @args + ); + if ( $return->{success} ) { + # add to inventory + my $item = FS::inventory_item->new({ + 'classnum' => $classnum, + 'agentnum' => $agentnum, + 'item' => $imsi, + }); + my $error = $item->insert; + if ( $error ) { + die "IMSI $imsi added to HLR, but not to inventory:\n$error\n"; + } + } else { + die "IMSI $imsi could not be added to HLR:\n".$return->{error}."\n"; + } + } #foreach $line + $self->logout($socket); + return; +} + 1; diff --git a/httemplate/browse/part_export.cgi b/httemplate/browse/part_export.cgi index 91238a0fd..876633afc 100755 --- a/httemplate/browse/part_export.cgi +++ b/httemplate/browse/part_export.cgi @@ -38,6 +38,21 @@ function part_export_areyousure(href) { <% $part_export->label_html %> (edit | delete) +% if ( my @actions = $part_export->actions ) { +

+ Management: +% while (@actions) { +% my $label = shift @actions; +% my $path = shift @actions; + <& /elements/popup_link.html, + 'label' => $label, + 'action' => $fsurl.$path.'?'.$part_export->exportnum, + 'actionlabel' => $label, + &><% @actions ? ' | ' : '' %> +% } +

+% } #if @actions + diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index 7a282a34c..cef54b824 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -108,7 +108,7 @@ function <%$key%>process () { function <%$key%>myCallback( jobnum ) { - overlib( OLiframeContent('<%$p%>elements/progress-popup.html?jobnum=' + jobnum + ';<%$url_or_message_link%>;formname=<%$formname%>' , 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); + overlib( OLiframeContent('<%$fsurl%>elements/progress-popup.html?jobnum=' + jobnum + ';<%$url_or_message_link%>;formname=<%$formname%>' , 444, 168, '<% $popup_name %>'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); } diff --git a/httemplate/misc/part_export/huawei_hlr-import_sim.html b/httemplate/misc/part_export/huawei_hlr-import_sim.html new file mode 100644 index 000000000..9b87b3d2a --- /dev/null +++ b/httemplate/misc/part_export/huawei_hlr-import_sim.html @@ -0,0 +1,52 @@ +<& /elements/header-popup.html, 'Import SIMs' &> +Import a file containing SIM card properties.
+Each row should contain the following fields, separated by spaces:
+IMSI, ICCID, PIN1, PUK1, PIN2, PUK2, ACC, Ki
+
+<& /elements/form-file_upload.html, + 'name' => 'ImportForm', + 'action' => 'process/huawei_hlr-import_sim.html', + 'num_files' => 1, + 'fields' => [ 'exportnum', 'classnum', 'agentnum', ], + 'message' => 'Inventory import successful', + 'onsubmit' => "document.ImportForm.submitButton.disabled=true;", +&> + + + <& /elements/file-upload.html, + 'field' => 'file', + 'label' => 'Filename', + &> + <& /elements/tr-select-agent.html, + 'disable_empty' => 1, + &> + <& /elements/tr-select-table.html, + 'table' => 'inventory_class', + 'name_col' => 'classname', + 'label' => 'Inventory class', + 'disable_empty' => 1, + &> + + + + + +
+ +
+ + + +<%init> +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my ($exportnum) = $cgi->keywords; +$exportnum =~ /^\d+$/ or die "bad exportnum '$exportnum'"; +my $part_export = FS::part_export->by_key($exportnum) + or die "export $exportnum not found"; + diff --git a/httemplate/misc/part_export/process/huawei_hlr-import_sim.html b/httemplate/misc/part_export/process/huawei_hlr-import_sim.html new file mode 100644 index 000000000..d46700d5f --- /dev/null +++ b/httemplate/misc/part_export/process/huawei_hlr-import_sim.html @@ -0,0 +1,10 @@ +<% $server->process %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my $server = new FS::UI::Web::JSRPC + 'FS::part_export::huawei_hlr::process_import_sim', $cgi; + + -- 2.11.0