3 # This file is part of Koha.
5 # Copyright (C) 2012-2013 ByWater Solutions
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
26 use C4::SIP::Sip::Constants qw(:all);
29 use constant { LANGUAGE => '001' };
40 my $patron_identifier;
45 my $fee_acknowledged = 0;
52 "a|address|host|hostaddress=s" => \$host, # sip server ip
53 "p|port=s" => \$port, # sip server port
54 "su|sip_user=s" => \$login_user_id, # sip user
55 "sp|sip_pass=s" => \$login_password, # sip password
56 "l|location|location_code=s" => \$location_code, # sip location code
58 "patron=s" => \$patron_identifier, # patron cardnumber or login
59 "password=s" => \$patron_password, # patron's password
61 "i|item=s" => \$item_identifier,
63 "fa|fee-acknowledged" => \$fee_acknowledged,
65 "t|terminator=s" => \$terminator,
67 "m|message=s" => \@messages,
82 $terminator = ( $terminator eq 'CR' ) ? $CR : $CRLF;
84 # Set perl to expect the same record terminator it is sending
87 my ( $sec, $min, $hour, $day, $month, $year ) = localtime(time);
89 my $transaction_date = C4::SIP::Sip::timestamp();
91 my $terminal_password = $login_password;
94 print "Attempting socket connection to $host:$port...";
96 my $socket = IO::Socket::INET->new("$host:$port")
97 or die "failed! : $!\n";
103 subroutine => \&build_login_command_message,
105 login_user_id => $login_user_id,
106 login_password => $login_password,
107 location_code => $location_code,
110 patron_status_request => {
111 name => 'Patron Status Request',
112 subroutine => \&build_patron_status_request_command_message,
114 transaction_date => $transaction_date,
115 institution_id => $location_code,
116 patron_identifier => $patron_identifier,
117 terminal_password => $terminal_password,
118 patron_password => $patron_password,
120 optional => [ 'patron_password', ],
122 patron_information => {
123 name => 'Patron Information',
124 subroutine => \&build_patron_information_command_message,
126 transaction_date => $transaction_date,
127 institution_id => $location_code,
128 patron_identifier => $patron_identifier,
129 terminal_password => $terminal_password,
130 patron_password => $patron_password,
132 optional => [ 'patron_password', ],
134 item_information => {
135 name => 'Item Information',
136 subroutine => \&build_item_information_command_message,
138 transaction_date => $transaction_date,
139 institution_id => $location_code,
140 item_identifier => $item_identifier,
141 terminal_password => $terminal_password,
147 subroutine => \&build_checkout_command_message,
149 SC_renewal_policy => 'Y',
151 transaction_date => $transaction_date,
152 nb_due_date => undef,
153 institution_id => $location_code,
154 patron_identifier => $patron_identifier,
155 item_identifier => $item_identifier,
156 terminal_password => $terminal_password,
157 item_properties => undef,
158 patron_password => $patron_password,
159 fee_acknowledged => $fee_acknowledged,
163 'nb_due_date', # defaults to transaction date
172 subroutine => \&build_checkin_command_message,
175 transaction_date => $transaction_date,
176 return_date => $transaction_date,
177 current_location => $location_code,
178 institution_id => $location_code,
179 item_identifier => $item_identifier,
180 terminal_password => $terminal_password,
181 item_properties => undef,
185 'return_date', # defaults to transaction date
193 subroutine => \&build_renew_command_message,
195 third_party_allowed => 'N',
197 transaction_date => $transaction_date,
198 nb_due_date => undef,
199 institution_id => $location_code,
200 patron_identifier => $patron_identifier,
201 patron_password => $patron_password,
202 item_identifier => $item_identifier,
203 title_identifier => undef,
204 terminal_password => $terminal_password,
205 item_properties => undef,
206 fee_acknowledged => $fee_acknowledged,
209 'nb_due_date', # defaults to transaction date
220 my $data = run_command_message('login');
222 if ( $data =~ '^941' ) { ## we are logged in
223 foreach my $m (@messages) {
226 my $data = run_command_message($m);
234 sub build_command_message {
237 ##FIXME It would be much better to use exception handling so we aren't priting from subs
238 unless ( $handlers->{$message} ) {
239 say "$message is an unsupported command!";
243 my $subroutine = $handlers->{$message}->{subroutine};
244 my $parameters = $handlers->{$message}->{parameters};
245 my %optional = map { $_ => 1 } @{ $handlers->{$message}->{optional} };
247 foreach my $key ( keys %$parameters ) {
248 unless ( $parameters->{$key} ) {
249 unless ( $optional{$key} ) {
250 say "$key is required for $message";
256 return &$subroutine($parameters);
259 sub run_command_message {
262 my $command_message = build_command_message($message);
264 return unless $command_message;
266 say "SEND: $command_message";
267 print $socket $command_message . $terminator;
269 my $data = <$socket>;
276 sub build_login_command_message {
279 my $login_user_id = $params->{login_user_id};
280 my $login_password = $params->{login_password};
281 my $location_code = $params->{location_code};
285 . build_field( FID_LOGIN_UID, $login_user_id )
286 . build_field( FID_LOGIN_PWD, $login_password )
287 . build_field( FID_LOCATION_CODE, $location_code );
290 sub build_patron_status_request_command_message {
293 my $transaction_date = $params->{transaction_date};
294 my $institution_id = $params->{institution_id};
295 my $patron_identifier = $params->{patron_identifier};
296 my $terminal_password = $params->{terminal_password};
297 my $patron_password = $params->{patron_password};
303 . build_field( FID_INST_ID, $institution_id )
304 . build_field( FID_PATRON_ID, $patron_identifier )
305 . build_field( FID_TERMINAL_PWD, $terminal_password )
306 . build_field( FID_PATRON_PWD, $patron_password );
309 sub build_patron_information_command_message {
312 my $transaction_date = $params->{transaction_date};
313 my $institution_id = $params->{institution_id};
314 my $patron_identifier = $params->{patron_identifier};
315 my $terminal_password = $params->{terminal_password};
316 my $patron_password = $params->{patron_password};
325 . build_field( FID_INST_ID, $institution_id )
326 . build_field( FID_PATRON_ID, $patron_identifier )
327 . build_field( FID_TERMINAL_PWD, $terminal_password )
328 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } );
331 sub build_item_information_command_message {
334 my $transaction_date = $params->{transaction_date};
335 my $institution_id = $params->{institution_id};
336 my $item_identifier = $params->{item_identifier};
337 my $terminal_password = $params->{terminal_password};
343 . build_field( FID_INST_ID, $institution_id )
344 . build_field( FID_ITEM_ID, $item_identifier )
345 . build_field( FID_TERMINAL_PWD, $terminal_password );
348 sub build_checkout_command_message {
351 my $SC_renewal_policy = $params->{SC_renewal_policy} || 'N';
352 my $no_block = $params->{no_block} || 'N';
353 my $transaction_date = $params->{transaction_date};
354 my $nb_due_date = $params->{nb_due_date};
355 my $institution_id = $params->{institution_id};
356 my $patron_identifier = $params->{patron_identifier};
357 my $item_identifier = $params->{item_identifier};
358 my $terminal_password = $params->{terminal_password};
359 my $item_properties = $params->{item_properties};
360 my $patron_password = $params->{patron_password};
361 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
362 my $cancel = $params->{cancel} || 'N';
364 $SC_renewal_policy = $SC_renewal_policy eq 'Y' ? 'Y' : 'N';
365 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
366 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
367 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
369 $nb_due_date ||= $transaction_date;
377 . build_field( FID_INST_ID, $institution_id )
378 . build_field( FID_PATRON_ID, $patron_identifier )
379 . build_field( FID_ITEM_ID, $item_identifier )
380 . build_field( FID_TERMINAL_PWD, $terminal_password )
381 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
382 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
383 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } )
384 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
387 sub build_checkin_command_message {
390 my $no_block = $params->{no_block} || 'N';
391 my $transaction_date = $params->{transaction_date};
392 my $return_date = $params->{return_date};
393 my $current_location = $params->{current_location};
394 my $institution_id = $params->{institution_id};
395 my $item_identifier = $params->{item_identifier};
396 my $terminal_password = $params->{terminal_password};
397 my $item_properties = $params->{item_properties};
398 my $cancel = $params->{cancel} || 'N';
400 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
401 $cancel = $cancel eq 'Y' ? 'Y' : 'N';
403 $return_date ||= $transaction_date;
410 . build_field( FID_CURRENT_LOCN, $current_location )
411 . build_field( FID_INST_ID, $institution_id )
412 . build_field( FID_ITEM_ID, $item_identifier )
413 . build_field( FID_TERMINAL_PWD, $terminal_password )
414 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
415 . build_field( FID_CANCEL, $cancel, { optional => 1 } );
418 sub build_renew_command_message {
421 my $third_party_allowed = $params->{third_party_allowed} || 'N';
422 my $no_block = $params->{no_block} || 'N';
423 my $transaction_date = $params->{transaction_date};
424 my $nb_due_date = $params->{nb_due_date};
425 my $institution_id = $params->{institution_id};
426 my $patron_identifier = $params->{patron_identifier};
427 my $patron_password = $params->{patron_password};
428 my $item_identifier = $params->{item_identifier};
429 my $title_identifier = $params->{title_identifier};
430 my $terminal_password = $params->{terminal_password};
431 my $item_properties = $params->{item_properties};
432 my $fee_acknowledged = $params->{fee_acknowledged} || 'N';
434 $third_party_allowed = $third_party_allowed eq 'Y' ? 'Y' : 'N';
435 $no_block = $no_block eq 'Y' ? 'Y' : 'N';
436 $fee_acknowledged = $fee_acknowledged eq 'Y' ? 'Y' : 'N';
438 $nb_due_date ||= $transaction_date;
442 . $third_party_allowed
446 . build_field( FID_INST_ID, $institution_id )
447 . build_field( FID_PATRON_ID, $patron_identifier )
448 . build_field( FID_PATRON_PWD, $patron_password, { optional => 1 } )
449 . build_field( FID_ITEM_ID, $item_identifier )
450 . build_field( FID_TITLE_ID, $title_identifier )
451 . build_field( FID_TERMINAL_PWD, $terminal_password )
452 . build_field( FID_ITEM_PROPS, $item_properties, { optional => 1 } )
453 . build_field( FID_FEE_ACK, $fee_acknowledged, { optional => 1 } );
457 my ( $field_identifier, $value, $params ) = @_;
461 return q{} if ( $params->{optional} && !$value );
463 return $field_identifier . (($value) ? $value : '') . '|';
467 say q/sip_cli_emulator.pl - SIP command line emulator
469 Test a SIP2 service by sending patron status and patron
470 information requests.
473 sip_cli_emulator.pl [OPTIONS]
476 --help display help message
478 -a --address SIP server ip address or host name
479 -p --port SIP server port
481 -su --sip_user SIP server login username
482 -sp --sip_pass SIP server login password
484 -l --location SIP location code
486 --patron ILS patron cardnumber or username
487 --password ILS patron password
489 --item ILS item identifier ( item barcode )
491 -t --terminator SIP2 message terminator, either CR, or CRLF
494 -fa --fee-acknowledged Sends a confirmation of checkout fee
496 -m --message SIP2 message to execute
498 Implemented Messages:
499 patron_status_request