View | Details | Raw Unified | Return to bug 13871
Collapse All | Expand All

(-)a/C4/SIP/Sip/MsgType.pm (-1061 / +1038 lines)
Lines 24-40 use UNIVERSAL::can; Link Here
24
use vars qw(@ISA $VERSION @EXPORT_OK);
24
use vars qw(@ISA $VERSION @EXPORT_OK);
25
25
26
BEGIN {
26
BEGIN {
27
    $VERSION = 3.07.00.049;
27
    $VERSION   = 3.07.00.049;
28
	@ISA = qw(Exporter);
28
    @ISA       = qw(Exporter);
29
	@EXPORT_OK = qw(handle login_core);
29
    @EXPORT_OK = qw(handle login_core);
30
}
30
}
31
31
32
# Predeclare handler subroutines
32
# Predeclare handler subroutines
33
use subs qw(handle_patron_status handle_checkout handle_checkin
33
use subs qw(handle_patron_status handle_checkout handle_checkin
34
	    handle_block_patron handle_sc_status handle_request_acs_resend
34
  handle_block_patron handle_sc_status handle_request_acs_resend
35
	    handle_login handle_patron_info handle_end_patron_session
35
  handle_login handle_patron_info handle_end_patron_session
36
	    handle_fee_paid handle_item_information handle_item_status_update
36
  handle_fee_paid handle_item_information handle_item_status_update
37
	    handle_patron_enable handle_hold handle_renew handle_renew_all);
37
  handle_patron_enable handle_hold handle_renew handle_renew_all);
38
38
39
#
39
#
40
# For the most part, Version 2.00 of the protocol just adds new
40
# For the most part, Version 2.00 of the protocol just adds new
Lines 49-359 use subs qw(handle_patron_status handle_checkout handle_checkin Link Here
49
# in 2.00, so 1.00 shouldn't recognize it.
49
# in 2.00, so 1.00 shouldn't recognize it.
50
50
51
my %handlers = (
51
my %handlers = (
52
		(PATRON_STATUS_REQ) => {
52
    (PATRON_STATUS_REQ) => {
53
		    name => "Patron Status Request",
53
        name     => "Patron Status Request",
54
		    handler => \&handle_patron_status,
54
        handler  => \&handle_patron_status,
55
		    protocol => {
55
        protocol => {
56
			1 => {
56
            1 => {
57
			    template => "A3A18",
57
                template     => "A3A18",
58
			    template_len => 21,
58
                template_len => 21,
59
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
59
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_TERMINAL_PWD), (FID_PATRON_PWD) ],
60
				       (FID_TERMINAL_PWD), (FID_PATRON_PWD)],
60
            }
61
			}
61
        }
62
		    }
62
    },
63
		},
63
    (CHECKOUT) => {
64
		(CHECKOUT) => {
64
        name     => "Checkout",
65
		    name => "Checkout",
65
        handler  => \&handle_checkout,
66
		    handler => \&handle_checkout,
66
        protocol => {
67
		    protocol => {
67
            1 => {
68
			1 => {
68
                template     => "CCA18A18",
69
			    template => "CCA18A18",
69
                template_len => 38,
70
			    template_len => 38,
70
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD) ],
71
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
71
            },
72
				       (FID_ITEM_ID), (FID_TERMINAL_PWD)],
72
            2 => {
73
			},
73
                template     => "CCA18A18",
74
			2 => {
74
                template_len => 38,
75
			    template => "CCA18A18",
75
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD), (FID_ITEM_PROPS), (FID_PATRON_PWD), (FID_FEE_ACK), (FID_CANCEL) ],
76
			    template_len => 38,
76
            },
77
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
77
        }
78
				       (FID_ITEM_ID), (FID_TERMINAL_PWD),
78
    },
79
				       (FID_ITEM_PROPS), (FID_PATRON_PWD),
79
    (CHECKIN) => {
80
				       (FID_FEE_ACK), (FID_CANCEL)],
80
        name     => "Checkin",
81
			},
81
        handler  => \&handle_checkin,
82
		    }
82
        protocol => {
83
		},
83
            1 => {
84
		(CHECKIN) => {
84
                template     => "CA18A18",
85
		    name => "Checkin",
85
                template_len => 37,
86
		    handler => \&handle_checkin,
86
                fields       => [ (FID_CURRENT_LOCN), (FID_INST_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD) ],
87
		    protocol => {
87
            },
88
			1 => {
88
            2 => {
89
			    template => "CA18A18",
89
                template     => "CA18A18",
90
			    template_len => 37,
90
                template_len => 37,
91
			    fields => [(FID_CURRENT_LOCN), (FID_INST_ID),
91
                fields       => [ (FID_CURRENT_LOCN), (FID_INST_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD), (FID_ITEM_PROPS), (FID_CANCEL) ],
92
				       (FID_ITEM_ID), (FID_TERMINAL_PWD)],
92
            }
93
			},
93
        }
94
			2 => {
94
    },
95
			    template => "CA18A18",
95
    (BLOCK_PATRON) => {
96
			    template_len => 37,
96
        name     => "Block Patron",
97
			    fields => [(FID_CURRENT_LOCN), (FID_INST_ID),
97
        handler  => \&handle_block_patron,
98
				       (FID_ITEM_ID), (FID_TERMINAL_PWD),
98
        protocol => {
99
				       (FID_ITEM_PROPS), (FID_CANCEL)],
99
            1 => {
100
			}
100
                template     => "CA18",
101
		    }
101
                template_len => 19,
102
		},
102
                fields       => [ (FID_INST_ID), (FID_BLOCKED_CARD_MSG), (FID_PATRON_ID), (FID_TERMINAL_PWD) ],
103
		(BLOCK_PATRON) => {
103
            },
104
		    name => "Block Patron",
104
        }
105
		    handler => \&handle_block_patron,
105
    },
106
		    protocol => {
106
    (SC_STATUS) => {
107
			1 => {
107
        name     => "SC Status",
108
			    template => "CA18",
108
        handler  => \&handle_sc_status,
109
			    template_len => 19,
109
        protocol => {
110
			    fields => [(FID_INST_ID), (FID_BLOCKED_CARD_MSG),
110
            1 => {
111
				       (FID_PATRON_ID), (FID_TERMINAL_PWD)],
111
                template     => "CA3A4",
112
			},
112
                template_len => 8,
113
		    }
113
                fields       => [],
114
		},
114
            }
115
		(SC_STATUS) => {
115
        }
116
		    name => "SC Status",
116
    },
117
		    handler => \&handle_sc_status,
117
    (REQUEST_ACS_RESEND) => {
118
		    protocol => {
118
        name     => "Request ACS Resend",
119
			1 => {
119
        handler  => \&handle_request_acs_resend,
120
			    template =>"CA3A4",
120
        protocol => {
121
			    template_len => 8,
121
            1 => {
122
			    fields => [],
122
                template     => "",
123
			}
123
                template_len => 0,
124
		    }
124
                fields       => [],
125
		},
125
            }
126
		(REQUEST_ACS_RESEND) => {
126
        }
127
		    name => "Request ACS Resend",
127
    },
128
		    handler => \&handle_request_acs_resend,
128
    (LOGIN) => {
129
		    protocol => {
129
        name     => "Login",
130
			1 => {
130
        handler  => \&handle_login,
131
			    template => "",
131
        protocol => {
132
			    template_len => 0,
132
            2 => {
133
			    fields => [],
133
                template     => "A1A1",
134
			}
134
                template_len => 2,
135
		    }
135
                fields       => [ (FID_LOGIN_UID), (FID_LOGIN_PWD), (FID_LOCATION_CODE) ],
136
		},
136
            }
137
		(LOGIN) => {
137
        }
138
		    name => "Login",
138
    },
139
		    handler => \&handle_login,
139
    (PATRON_INFO) => {
140
		    protocol => {
140
        name     => "Patron Info",
141
			2 => {
141
        handler  => \&handle_patron_info,
142
			    template => "A1A1",
142
        protocol => {
143
			    template_len => 2,
143
            2 => {
144
			    fields => [(FID_LOGIN_UID), (FID_LOGIN_PWD),
144
                template     => "A3A18A10",
145
				       (FID_LOCATION_CODE)],
145
                template_len => 31,
146
			}
146
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_TERMINAL_PWD), (FID_PATRON_PWD), (FID_START_ITEM), (FID_END_ITEM) ],
147
		    }
147
            }
148
		},
148
        }
149
		(PATRON_INFO) => {
149
    },
150
		    name => "Patron Info",
150
    (END_PATRON_SESSION) => {
151
		    handler => \&handle_patron_info,
151
        name     => "End Patron Session",
152
		    protocol => {
152
        handler  => \&handle_end_patron_session,
153
			2 => {
153
        protocol => {
154
			    template => "A3A18A10",
154
            2 => {
155
			    template_len => 31,
155
                template     => "A18",
156
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
156
                template_len => 18,
157
				       (FID_TERMINAL_PWD), (FID_PATRON_PWD),
157
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_TERMINAL_PWD), (FID_PATRON_PWD) ],
158
				       (FID_START_ITEM), (FID_END_ITEM)],
158
            }
159
			}
159
        }
160
		    }
160
    },
161
		},
161
    (FEE_PAID) => {
162
		(END_PATRON_SESSION) => {
162
        name     => "Fee Paid",
163
		    name => "End Patron Session",
163
        handler  => \&handle_fee_paid,
164
		    handler => \&handle_end_patron_session,
164
        protocol => {
165
		    protocol => {
165
            2 => {
166
			2 => {
166
                template     => "A18A2A2A3",
167
			    template => "A18",
167
                template_len => 25,
168
			    template_len => 18,
168
                fields       => [ (FID_FEE_AMT), (FID_INST_ID), (FID_PATRON_ID), (FID_TERMINAL_PWD), (FID_PATRON_PWD), (FID_FEE_ID), (FID_TRANSACTION_ID) ],
169
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
169
            }
170
				       (FID_TERMINAL_PWD), (FID_PATRON_PWD)],
170
        }
171
			}
171
    },
172
		    }
172
    (ITEM_INFORMATION) => {
173
		},
173
        name     => "Item Information",
174
		(FEE_PAID) => {
174
        handler  => \&handle_item_information,
175
		    name => "Fee Paid",
175
        protocol => {
176
		    handler => \&handle_fee_paid,
176
            2 => {
177
		    protocol => {
177
                template     => "A18",
178
			2 => {
178
                template_len => 18,
179
			    template => "A18A2A2A3",
179
                fields       => [ (FID_INST_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD) ],
180
			    template_len => 25,
180
            }
181
			    fields => [(FID_FEE_AMT), (FID_INST_ID),
181
        }
182
				       (FID_PATRON_ID), (FID_TERMINAL_PWD),
182
    },
183
				       (FID_PATRON_PWD), (FID_FEE_ID),
183
    (ITEM_STATUS_UPDATE) => {
184
                       (FID_TRANSACTION_ID)],
184
        name     => "Item Status Update",
185
               }
185
        handler  => \&handle_item_status_update,
186
		    }
186
        protocol => {
187
		},
187
            2 => {
188
		(ITEM_INFORMATION) => {
188
                template     => "A18",
189
		    name => "Item Information",
189
                template_len => 18,
190
		    handler => \&handle_item_information,
190
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_ITEM_ID), (FID_TERMINAL_PWD), (FID_ITEM_PROPS) ],
191
		    protocol => {
191
            }
192
			2 => {
192
        }
193
			    template => "A18",
193
    },
194
			    template_len => 18,
194
    (PATRON_ENABLE) => {
195
			    fields => [(FID_INST_ID), (FID_ITEM_ID),
195
        name     => "Patron Enable",
196
				       (FID_TERMINAL_PWD)],
196
        handler  => \&handle_patron_enable,
197
			}
197
        protocol => {
198
		    }
198
            2 => {
199
		},
199
                template     => "A18",
200
		(ITEM_STATUS_UPDATE) => {
200
                template_len => 18,
201
		    name => "Item Status Update",
201
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_TERMINAL_PWD), (FID_PATRON_PWD) ],
202
		    handler => \&handle_item_status_update,
202
            }
203
		    protocol => {
203
        }
204
			2 => {
204
    },
205
			    template => "A18",
205
    (HOLD) => {
206
			    template_len => 18,
206
        name     => "Hold",
207
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
207
        handler  => \&handle_hold,
208
				       (FID_ITEM_ID), (FID_TERMINAL_PWD),
208
        protocol => {
209
				       (FID_ITEM_PROPS)],
209
            2 => {
210
			}
210
                template     => "AA18",
211
		    }
211
                template_len => 19,
212
		},
212
                fields       => [
213
		(PATRON_ENABLE) => {
213
                    (FID_EXPIRATION), (FID_PICKUP_LOCN), (FID_HOLD_TYPE), (FID_INST_ID), (FID_PATRON_ID), (FID_PATRON_PWD),
214
		    name => "Patron Enable",
214
                    (FID_ITEM_ID), (FID_TITLE_ID), (FID_TERMINAL_PWD), (FID_FEE_ACK)
215
		    handler => \&handle_patron_enable,
215
                ],
216
		    protocol => {
216
            }
217
			2 => {
217
        }
218
			    template => "A18",
218
    },
219
			    template_len => 18,
219
    (RENEW) => {
220
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
220
        name     => "Renew",
221
				       (FID_TERMINAL_PWD), (FID_PATRON_PWD)],
221
        handler  => \&handle_renew,
222
			}
222
        protocol => {
223
		    }
223
            2 => {
224
		},
224
                template     => "CCA18A18",
225
		(HOLD) => {
225
                template_len => 38,
226
		    name => "Hold",
226
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_PATRON_PWD), (FID_ITEM_ID), (FID_TITLE_ID), (FID_TERMINAL_PWD), (FID_ITEM_PROPS), (FID_FEE_ACK) ],
227
		    handler => \&handle_hold,
227
            }
228
		    protocol => {
228
        }
229
			2 => {
229
    },
230
			    template => "AA18",
230
    (RENEW_ALL) => {
231
			    template_len => 19,
231
        name     => "Renew All",
232
			    fields => [(FID_EXPIRATION), (FID_PICKUP_LOCN),
232
        handler  => \&handle_renew_all,
233
				       (FID_HOLD_TYPE), (FID_INST_ID),
233
        protocol => {
234
				       (FID_PATRON_ID), (FID_PATRON_PWD),
234
            2 => {
235
				       (FID_ITEM_ID), (FID_TITLE_ID),
235
                template     => "A18",
236
				       (FID_TERMINAL_PWD), (FID_FEE_ACK)],
236
                template_len => 18,
237
			}
237
                fields       => [ (FID_INST_ID), (FID_PATRON_ID), (FID_PATRON_PWD), (FID_TERMINAL_PWD), (FID_FEE_ACK) ],
238
		    }
238
            }
239
		},
239
        }
240
		(RENEW) => {
240
    }
241
		    name => "Renew",
241
);
242
		    handler => \&handle_renew,
243
		    protocol => {
244
			2 => {
245
			    template => "CCA18A18",
246
			    template_len => 38,
247
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
248
				       (FID_PATRON_PWD), (FID_ITEM_ID),
249
				       (FID_TITLE_ID), (FID_TERMINAL_PWD),
250
				       (FID_ITEM_PROPS), (FID_FEE_ACK)],
251
			}
252
		    }
253
		},
254
		(RENEW_ALL) => {
255
		    name => "Renew All",
256
		    handler => \&handle_renew_all,
257
		    protocol => {
258
			2 => {
259
			    template => "A18",
260
			    template_len => 18,
261
			    fields => [(FID_INST_ID), (FID_PATRON_ID),
262
				       (FID_PATRON_PWD), (FID_TERMINAL_PWD),
263
				       (FID_FEE_ACK)],
264
			}
265
		    }
266
		}
267
		);
268
242
269
#
243
#
270
# Now, initialize some of the missing bits of %handlers
244
# Now, initialize some of the missing bits of %handlers
271
#
245
#
272
foreach my $i (keys(%handlers)) {
246
foreach my $i ( keys(%handlers) ) {
273
    if (!exists($handlers{$i}->{protocol}->{2})) {
247
    if ( !exists( $handlers{$i}->{protocol}->{2} ) ) {
274
	$handlers{$i}->{protocol}->{2} = $handlers{$i}->{protocol}->{1};
248
        $handlers{$i}->{protocol}->{2} = $handlers{$i}->{protocol}->{1};
275
    }
249
    }
276
}
250
}
277
251
278
sub new {
252
sub new {
279
    my ($class, $msg, $seqno) = @_;
253
    my ( $class, $msg, $seqno ) = @_;
280
    my $self = {};
254
    my $self = {};
281
    my $msgtag = substr($msg, 0, 2);
255
    my $msgtag = substr( $msg, 0, 2 );
282
256
283
    if ($msgtag eq LOGIN) {
257
    if ( $msgtag eq LOGIN ) {
284
	# If the client is using the 2.00-style "Login" message
258
285
	# to authenticate to the server, then we get the Login message
259
        # If the client is using the 2.00-style "Login" message
286
	# _before_ the client has indicated that it supports 2.00, but
260
        # to authenticate to the server, then we get the Login message
287
	# it's using the 2.00 login process, so it must support 2.00.
261
        # _before_ the client has indicated that it supports 2.00, but
288
		$protocol_version = 2;
262
        # it's using the 2.00 login process, so it must support 2.00.
263
        $protocol_version = 2;
289
    }
264
    }
290
    syslog("LOG_DEBUG", "Sip::MsgType::new('%s', '%s...', '%s'): seq.no '%s', protocol %s",
265
    syslog( "LOG_DEBUG", "Sip::MsgType::new('%s', '%s...', '%s'): seq.no '%s', protocol %s", $class, substr( $msg, 0, 10 ), $msgtag, $seqno, $protocol_version );
291
		$class, substr($msg, 0, 10), $msgtag, $seqno, $protocol_version);
266
292
	# warn "SIP PROTOCOL: $protocol_version";	
267
    # warn "SIP PROTOCOL: $protocol_version";
293
    if (!exists($handlers{$msgtag})) {
268
    if ( !exists( $handlers{$msgtag} ) ) {
294
		syslog("LOG_WARNING", "new Sip::MsgType: Skipping message of unknown type '%s' in '%s'",
269
        syslog( "LOG_WARNING", "new Sip::MsgType: Skipping message of unknown type '%s' in '%s'", $msgtag, $msg );
295
	       $msgtag, $msg);
296
        return;
270
        return;
297
    } elsif (!exists($handlers{$msgtag}->{protocol}->{$protocol_version})) {
271
    } elsif ( !exists( $handlers{$msgtag}->{protocol}->{$protocol_version} ) ) {
298
		syslog("LOG_WARNING", "new Sip::MsgType: Skipping message '%s' unsupported by protocol rev. '%d'",
272
        syslog( "LOG_WARNING", "new Sip::MsgType: Skipping message '%s' unsupported by protocol rev. '%d'", $msgtag, $protocol_version );
299
	       $msgtag, $protocol_version);
300
        return;
273
        return;
301
    }
274
    }
302
275
303
    bless $self, $class;
276
    bless $self, $class;
304
277
305
    $self->{seqno} = $seqno;
278
    $self->{seqno} = $seqno;
306
    $self->_initialize(substr($msg,2), $handlers{$msgtag});
279
    $self->_initialize( substr( $msg, 2 ), $handlers{$msgtag} );
307
280
308
    return($self);
281
    return ($self);
309
}
282
}
310
283
311
sub _initialize {
284
sub _initialize {
312
	my ($self, $msg, $control_block) = @_;
285
    my ( $self, $msg, $control_block ) = @_;
313
	my $fn;
286
    my $fn;
314
	my $proto = $control_block->{protocol}->{$protocol_version};
287
    my $proto = $control_block->{protocol}->{$protocol_version};
315
288
316
	$self->{name}    = $control_block->{name};
289
    $self->{name}    = $control_block->{name};
317
	$self->{handler} = $control_block->{handler};
290
    $self->{handler} = $control_block->{handler};
318
291
319
	$self->{fields}       = {};
292
    $self->{fields}       = {};
320
	$self->{fixed_fields} = [];
293
    $self->{fixed_fields} = [];
321
294
322
	chomp($msg);		# These four are probably unnecessary now.
295
    chomp($msg);    # These four are probably unnecessary now.
323
	$msg =~ tr/\cM//d;
296
    $msg =~ tr/\cM//d;
324
	$msg =~ s/\^M$//;
297
    $msg =~ s/\^M$//;
325
	chomp($msg);
298
    chomp($msg);
326
299
327
	foreach my $field (@{$proto->{fields}}) {
300
    foreach my $field ( @{ $proto->{fields} } ) {
328
		$self->{fields}->{$field} = undef;
301
        $self->{fields}->{$field} = undef;
329
	}
302
    }
330
303
331
    syslog("LOG_DEBUG", "Sip::MsgType::_initialize('%s', '%s', '%s', '%s', ...)",
304
    syslog( "LOG_DEBUG", "Sip::MsgType::_initialize('%s', '%s', '%s', '%s', ...)", $self->{name}, $msg, $proto->{template}, $proto->{template_len} );
332
		$self->{name}, $msg, $proto->{template}, $proto->{template_len});
333
305
334
    $self->{fixed_fields} = [ unpack($proto->{template}, $msg) ];   # see http://perldoc.perl.org/5.8.8/functions/unpack.html
306
    $self->{fixed_fields} = [ unpack( $proto->{template}, $msg ) ];    # see http://perldoc.perl.org/5.8.8/functions/unpack.html
335
307
336
    # Skip over the fixed fields and the split the rest of
308
    # Skip over the fixed fields and the split the rest of
337
    # the message into fields based on the delimiter and parse them
309
    # the message into fields based on the delimiter and parse them
338
    foreach my $field (split(quotemeta($field_delimiter), substr($msg, $proto->{template_len}))) {
310
    foreach my $field ( split( quotemeta($field_delimiter), substr( $msg, $proto->{template_len} ) ) ) {
339
		$fn = substr($field, 0, 2);
311
        $fn = substr( $field, 0, 2 );
340
312
341
	if (!exists($self->{fields}->{$fn})) {
313
        if ( !exists( $self->{fields}->{$fn} ) ) {
342
		syslog("LOG_WARNING", "Unsupported field '%s' in %s message '%s'",
314
            syslog( "LOG_WARNING", "Unsupported field '%s' in %s message '%s'", $fn, $self->{name}, $msg );
343
			$fn, $self->{name}, $msg);
315
        } elsif ( defined( $self->{fields}->{$fn} ) ) {
344
	} elsif (defined($self->{fields}->{$fn})) {
316
            syslog( "LOG_WARNING", "Duplicate field '%s' (previous value '%s') in %s message '%s'", $fn, $self->{fields}->{$fn}, $self->{name}, $msg );
345
		syslog("LOG_WARNING", "Duplicate field '%s' (previous value '%s') in %s message '%s'",
317
        } else {
346
			$fn, $self->{fields}->{$fn}, $self->{name}, $msg);
318
            $self->{fields}->{$fn} = substr( $field, 2 );
347
	} else {
319
        }
348
		$self->{fields}->{$fn} = substr($field, 2);
320
    }
349
	}
321
350
	}
322
    return ($self);
351
352
	return($self);
353
}
323
}
354
324
355
sub handle {
325
sub handle {
356
    my ($msg, $server, $req) = @_;
326
    my ( $msg, $server, $req ) = @_;
357
    my $config = $server->{config};
327
    my $config = $server->{config};
358
    my $self;
328
    my $self;
359
329
Lines 362-417 sub handle { Link Here
362
    # This can't be based on the account, since we need to know
332
    # This can't be based on the account, since we need to know
363
    # the field delimiter to parse a SIP login message
333
    # the field delimiter to parse a SIP login message
364
    #
334
    #
365
	if (defined($server->{config}->{delimiter})) {
335
    if ( defined( $server->{config}->{delimiter} ) ) {
366
		$field_delimiter = $server->{config}->{delimiter};
336
        $field_delimiter = $server->{config}->{delimiter};
367
	}
337
    }
368
338
369
    # error detection is active if this is a REQUEST_ACS_RESEND
339
    # error detection is active if this is a REQUEST_ACS_RESEND
370
    # message with a checksum, or if the message is long enough
340
    # message with a checksum, or if the message is long enough
371
    # and the last nine characters begin with a sequence number
341
    # and the last nine characters begin with a sequence number
372
    # field
342
    # field
373
    if ($msg eq REQUEST_ACS_RESEND_CKSUM) {
343
    if ( $msg eq REQUEST_ACS_RESEND_CKSUM ) {
374
		# Special case
344
375
		$error_detection = 1;
345
        # Special case
376
		$self = C4::SIP::Sip::MsgType->new((REQUEST_ACS_RESEND), 0);
346
        $error_detection = 1;
377
    } elsif((length($msg) > 11) && (substr($msg, -9, 2) eq "AY")) {
347
        $self = C4::SIP::Sip::MsgType->new( (REQUEST_ACS_RESEND), 0 );
378
		$error_detection = 1;
348
    } elsif ( ( length($msg) > 11 ) && ( substr( $msg, -9, 2 ) eq "AY" ) ) {
379
349
        $error_detection = 1;
380
	if (!verify_cksum($msg)) {
350
381
	    syslog("LOG_WARNING", "Checksum failed on message '%s'", $msg);
351
        if ( !verify_cksum($msg) ) {
382
	    # REQUEST_SC_RESEND with error detection
352
            syslog( "LOG_WARNING", "Checksum failed on message '%s'", $msg );
383
	    $last_response = REQUEST_SC_RESEND_CKSUM;
353
384
	    print("$last_response\r");
354
            # REQUEST_SC_RESEND with error detection
385
	    return REQUEST_ACS_RESEND;
355
            $last_response = REQUEST_SC_RESEND_CKSUM;
386
	} else {
356
            print("$last_response\r");
387
	    # Save the sequence number, then strip off the
357
            return REQUEST_ACS_RESEND;
388
	    # error detection data to process the message
358
        } else {
389
	    $self = C4::SIP::Sip::MsgType->new(substr($msg, 0, -9), substr($msg, -7, 1));
359
390
	}
360
            # Save the sequence number, then strip off the
361
            # error detection data to process the message
362
            $self = C4::SIP::Sip::MsgType->new( substr( $msg, 0, -9 ), substr( $msg, -7, 1 ) );
363
        }
391
    } elsif ($error_detection) {
364
    } elsif ($error_detection) {
392
	# We received a non-ED message when ED is supposed to be active.
365
393
	# Warn about this problem, then process the message anyway.
366
        # We received a non-ED message when ED is supposed to be active.
394
		syslog("LOG_WARNING",
367
        # Warn about this problem, then process the message anyway.
395
	       "Received message without error detection: '%s'", $msg);
368
        syslog( "LOG_WARNING", "Received message without error detection: '%s'", $msg );
396
		$error_detection = 0;
369
        $error_detection = 0;
397
		$self = C4::SIP::Sip::MsgType->new($msg, 0);
370
        $self = C4::SIP::Sip::MsgType->new( $msg, 0 );
398
    } else {
371
    } else {
399
		$self = C4::SIP::Sip::MsgType->new($msg, 0);
372
        $self = C4::SIP::Sip::MsgType->new( $msg, 0 );
400
    }
373
    }
401
374
402
	if ((substr($msg, 0, 2) ne REQUEST_ACS_RESEND) &&
375
    if (   ( substr( $msg, 0, 2 ) ne REQUEST_ACS_RESEND )
403
		$req && (substr($msg, 0, 2) ne $req)) {
376
        && $req
404
		return substr($msg, 0, 2);
377
        && ( substr( $msg, 0, 2 ) ne $req ) ) {
405
	}
378
        return substr( $msg, 0, 2 );
406
	unless ($self->{handler}) {
379
    }
407
		syslog("LOG_WARNING", "No handler defined for '%s'", $msg);
380
    unless ( $self->{handler} ) {
381
        syslog( "LOG_WARNING", "No handler defined for '%s'", $msg );
408
        $last_response = REQUEST_SC_RESEND;
382
        $last_response = REQUEST_SC_RESEND;
409
        print("$last_response\r");
383
        print("$last_response\r");
410
        return REQUEST_ACS_RESEND;
384
        return REQUEST_ACS_RESEND;
411
	}
385
    }
412
    return($self->{handler}->($self, $server));  # FIXME
386
    return ( $self->{handler}->( $self, $server ) );    # FIXME
413
	# FIXME: Use of uninitialized value in subroutine entry
387
                                                        # FIXME: Use of uninitialized value in subroutine entry
414
	# Can't use string ("") as a subroutine ref while "strict refs" in use
388
                                                        # Can't use string ("") as a subroutine ref while "strict refs" in use
415
}
389
}
416
390
417
##
391
##
Lines 425-518 sub handle { Link Here
425
# Request Patron Status requires a patron password, but
399
# Request Patron Status requires a patron password, but
426
# Block Patron doesn't (since the patron may never have
400
# Block Patron doesn't (since the patron may never have
427
# provided one before attempting some illegal action).
401
# provided one before attempting some illegal action).
428
# 
402
#
429
# ASSUMPTION: If the patron password field is present in the
403
# ASSUMPTION: If the patron password field is present in the
430
# message, then it must match, otherwise incomplete patron status
404
# message, then it must match, otherwise incomplete patron status
431
# information will be returned to the terminal.
405
# information will be returned to the terminal.
432
# 
406
#
433
sub build_patron_status {
407
sub build_patron_status {
434
    my ($patron, $lang, $fields, $server)= @_;
408
    my ( $patron, $lang, $fields, $server ) = @_;
435
409
436
    my $patron_pwd = $fields->{(FID_PATRON_PWD)};
410
    my $patron_pwd = $fields->{ (FID_PATRON_PWD) };
437
    my $resp = (PATRON_STATUS_RESP);
411
    my $resp = (PATRON_STATUS_RESP);
438
412
439
    if ($patron) {
413
    if ($patron) {
440
	$resp .= patron_status_string($patron);
414
        $resp .= patron_status_string($patron);
441
	$resp .= $lang . timestamp();
415
        $resp .= $lang . timestamp();
442
	$resp .= add_field(FID_PERSONAL_NAME, $patron->name);
416
        $resp .= add_field( FID_PERSONAL_NAME, $patron->name );
443
417
444
	# while the patron ID we got from the SC is valid, let's
418
        # while the patron ID we got from the SC is valid, let's
445
	# use the one returned from the ILS, just in case...
419
        # use the one returned from the ILS, just in case...
446
	$resp .= add_field(FID_PATRON_ID, $patron->id);
420
        $resp .= add_field( FID_PATRON_ID, $patron->id );
447
	if ($protocol_version >= 2) {
421
        if ( $protocol_version >= 2 ) {
448
	    $resp .= add_field(FID_VALID_PATRON, 'Y');
422
            $resp .= add_field( FID_VALID_PATRON, 'Y' );
449
	    # Patron password is a required field.
423
450
		$resp .= add_field(FID_VALID_PATRON_PWD, sipbool($patron->check_password($patron_pwd)));
424
            # Patron password is a required field.
451
	    $resp .= maybe_add(FID_CURRENCY, $patron->currency);
425
            $resp .= add_field( FID_VALID_PATRON_PWD, sipbool( $patron->check_password($patron_pwd) ) );
452
	    $resp .= maybe_add(FID_FEE_AMT, $patron->fee_amount);
426
            $resp .= maybe_add( FID_CURRENCY, $patron->currency );
453
	}
427
            $resp .= maybe_add( FID_FEE_AMT,  $patron->fee_amount );
454
428
        }
455
    $resp .= maybe_add( FID_SCREEN_MSG, $patron->screen_msg, $server );
429
456
    $resp .= maybe_add( FID_SCREEN_MSG, $patron->{branchcode}, $server )
430
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->screen_msg,   $server );
457
      if ( $server->{account}->{send_patron_home_library_in_af} );
431
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->{branchcode}, $server )
458
432
          if ( $server->{account}->{send_patron_home_library_in_af} );
459
	$resp .= maybe_add(FID_PRINT_LINE, $patron->print_line);
433
434
        $resp .= maybe_add( FID_PRINT_LINE, $patron->print_line );
460
    } else {
435
    } else {
461
	# Invalid patron id.  Report that the user has no privs.,
462
	# no personal name, and is invalid (if we're using 2.00)
463
	$resp .= 'YYYY' . (' ' x 10) . $lang . timestamp();
464
	$resp .= add_field(FID_PERSONAL_NAME, '');
465
436
466
	# the patron ID is invalid, but it's a required field, so
437
        # Invalid patron id.  Report that the user has no privs.,
467
	# just echo it back
438
        # no personal name, and is invalid (if we're using 2.00)
468
	$resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)});
439
        $resp .= 'YYYY' . ( ' ' x 10 ) . $lang . timestamp();
440
        $resp .= add_field( FID_PERSONAL_NAME, '' );
441
442
        # the patron ID is invalid, but it's a required field, so
443
        # just echo it back
444
        $resp .= add_field( FID_PATRON_ID, $fields->{ (FID_PATRON_ID) } );
469
445
470
	($protocol_version >= 2) and 
446
        ( $protocol_version >= 2 )
471
		$resp .= add_field(FID_VALID_PATRON, 'N');
447
          and $resp .= add_field( FID_VALID_PATRON, 'N' );
472
    }
448
    }
473
449
474
    $resp .= add_field(FID_INST_ID, $fields->{(FID_INST_ID)});
450
    $resp .= add_field( FID_INST_ID, $fields->{ (FID_INST_ID) } );
475
    return $resp;
451
    return $resp;
476
}
452
}
477
453
478
sub handle_patron_status {
454
sub handle_patron_status {
479
	my ($self, $server) = @_;
455
    my ( $self, $server ) = @_;
480
	warn "handle_patron_status server: " . Dumper(\$server);  
456
    warn "handle_patron_status server: " . Dumper( \$server );
481
	my $ils = $server->{ils};
457
    my $ils = $server->{ils};
482
	my $patron;
458
    my $patron;
483
	my $resp = (PATRON_STATUS_RESP);
459
    my $resp    = (PATRON_STATUS_RESP);
484
	my $account = $server->{account};
460
    my $account = $server->{account};
485
    my ($lang, $date) = @{$self->{fixed_fields}};
461
    my ( $lang, $date ) = @{ $self->{fixed_fields} };
486
    my $fields = $self->{fields};
462
    my $fields = $self->{fields};
487
	#warn Dumper($fields);
463
488
	#warn FID_INST_ID;
464
    #warn Dumper($fields);
489
	#warn $fields->{(FID_INST_ID)};
465
    #warn FID_INST_ID;
490
    $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_patron_status");
466
    #warn $fields->{(FID_INST_ID)};
491
    $patron = $ils->find_patron($fields->{(FID_PATRON_ID)});
467
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, "handle_patron_status" );
492
    $resp = build_patron_status($patron, $lang, $fields, $server );
468
    $patron = $ils->find_patron( $fields->{ (FID_PATRON_ID) } );
493
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
469
    $resp = build_patron_status( $patron, $lang, $fields, $server );
470
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
494
    return (PATRON_STATUS_REQ);
471
    return (PATRON_STATUS_REQ);
495
}
472
}
496
473
497
sub handle_checkout {
474
sub handle_checkout {
498
    my ($self, $server) = @_;
475
    my ( $self, $server ) = @_;
499
    my $account = $server->{account};
476
    my $account = $server->{account};
500
    my $ils = $server->{ils};
477
    my $ils     = $server->{ils};
501
    my $inst = $ils->institution;
478
    my $inst    = $ils->institution;
502
    my ($sc_renewal_policy, $no_block, $trans_date, $nb_due_date);
479
    my ( $sc_renewal_policy, $no_block, $trans_date, $nb_due_date );
503
    my $fields;
480
    my $fields;
504
    my ($patron_id, $item_id, $status);
481
    my ( $patron_id, $item_id, $status );
505
    my ($item, $patron);
482
    my ( $item, $patron );
506
    my $resp;
483
    my $resp;
507
484
508
    ($sc_renewal_policy, $no_block, $trans_date, $nb_due_date) =
485
    ( $sc_renewal_policy, $no_block, $trans_date, $nb_due_date ) = @{ $self->{fixed_fields} };
509
	@{$self->{fixed_fields}};
510
    $fields = $self->{fields};
486
    $fields = $self->{fields};
511
487
512
    $patron_id = $fields->{(FID_PATRON_ID)};
488
    $patron_id = $fields->{ (FID_PATRON_ID) };
513
    $item_id   = $fields->{(FID_ITEM_ID)};
489
    $item_id   = $fields->{ (FID_ITEM_ID) };
514
    my $fee_ack = $fields->{(FID_FEE_ACK)};
490
    my $fee_ack = $fields->{ (FID_FEE_ACK) };
515
516
491
517
    if ( $no_block eq 'Y' ) {
492
    if ( $no_block eq 'Y' ) {
518
493
Lines 521-604 sub handle_checkout { Link Here
521
        syslog( "LOG_WARNING", "received no-block checkout from terminal '%s'", $account->{id} );
496
        syslog( "LOG_WARNING", "received no-block checkout from terminal '%s'", $account->{id} );
522
497
523
        $status = $ils->checkout_no_block( $patron_id, $item_id, $sc_renewal_policy, $trans_date, $nb_due_date );
498
        $status = $ils->checkout_no_block( $patron_id, $item_id, $sc_renewal_policy, $trans_date, $nb_due_date );
524
    }
499
    } else {
525
    else {
500
526
        # Does the transaction date really matter for items that are
501
        # Does the transaction date really matter for items that are
527
        # checkout out while the terminal is online?  I'm guessing 'no'
502
        # checkout out while the terminal is online?  I'm guessing 'no'
528
        $status = $ils->checkout( $patron_id, $item_id, $sc_renewal_policy, $fee_ack );
503
        $status = $ils->checkout( $patron_id, $item_id, $sc_renewal_policy, $fee_ack );
529
    }
504
    }
530
505
531
    $item = $status->item;
506
    $item   = $status->item;
532
    $patron = $status->patron;
507
    $patron = $status->patron;
533
508
534
    if ($status->ok) {
509
    if ( $status->ok ) {
535
	# Item successfully checked out
536
	# Fixed fields
537
	$resp = CHECKOUT_RESP . '1';
538
	$resp .= sipbool($status->renew_ok);
539
	if ($ils->supports('magnetic media')) {
540
	    $resp .= sipbool($item->magnetic_media);
541
	} else {
542
	    $resp .= 'U';
543
	}
544
	# We never return the obsolete 'U' value for 'desensitize'
545
	$resp .= sipbool($status->desensitize);
546
	$resp .= timestamp;
547
548
	# Now for the variable fields
549
	$resp .= add_field(FID_INST_ID, $inst);
550
	$resp .= add_field(FID_PATRON_ID, $patron_id);
551
	$resp .= add_field(FID_ITEM_ID, $item_id);
552
	$resp .= add_field(FID_TITLE_ID, $item->title_id);
553
    if ($item->due_date) {
554
        $resp .= add_field(FID_DUE_DATE, timestamp($item->due_date));
555
    } else {
556
        $resp .= add_field(FID_DUE_DATE, q{});
557
    }
558
510
559
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
511
        # Item successfully checked out
560
	$resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
512
        # Fixed fields
513
        $resp = CHECKOUT_RESP . '1';
514
        $resp .= sipbool( $status->renew_ok );
515
        if ( $ils->supports('magnetic media') ) {
516
            $resp .= sipbool( $item->magnetic_media );
517
        } else {
518
            $resp .= 'U';
519
        }
561
520
562
	if ($protocol_version >= 2) {
521
        # We never return the obsolete 'U' value for 'desensitize'
563
	    if ($ils->supports('security inhibit')) {
522
        $resp .= sipbool( $status->desensitize );
564
		$resp .= add_field(FID_SECURITY_INHIBIT,
523
        $resp .= timestamp;
565
				   $status->security_inhibit);
524
566
	    }
525
        # Now for the variable fields
567
	    $resp .= maybe_add(FID_MEDIA_TYPE, $item->sip_media_type);
526
        $resp .= add_field( FID_INST_ID,   $inst );
568
	    $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
527
        $resp .= add_field( FID_PATRON_ID, $patron_id );
528
        $resp .= add_field( FID_ITEM_ID,   $item_id );
529
        $resp .= add_field( FID_TITLE_ID,  $item->title_id );
530
        if ( $item->due_date ) {
531
            $resp .= add_field( FID_DUE_DATE, timestamp( $item->due_date ) );
532
        } else {
533
            $resp .= add_field( FID_DUE_DATE, q{} );
534
        }
569
535
570
	    }
536
        $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
571
	}
537
        $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
538
539
        if ( $protocol_version >= 2 ) {
540
            if ( $ils->supports('security inhibit') ) {
541
                $resp .= add_field( FID_SECURITY_INHIBIT, $status->security_inhibit );
542
            }
543
            $resp .= maybe_add( FID_MEDIA_TYPE, $item->sip_media_type );
544
            $resp .= maybe_add( FID_ITEM_PROPS, $item->sip_item_properties );
545
546
        }
547
    }
572
548
573
    else {
549
    else {
574
	# Checkout failed
550
575
	# Checkout Response: not ok, no renewal, don't know mag. media,
551
        # Checkout failed
576
	# no desensitize
552
        # Checkout Response: not ok, no renewal, don't know mag. media,
577
	$resp = sprintf("120NUN%s", timestamp);
553
        # no desensitize
578
	$resp .= add_field(FID_INST_ID, $inst);
554
        $resp = sprintf( "120NUN%s", timestamp );
579
	$resp .= add_field(FID_PATRON_ID, $patron_id);
555
        $resp .= add_field( FID_INST_ID,   $inst );
580
	$resp .= add_field(FID_ITEM_ID, $item_id);
556
        $resp .= add_field( FID_PATRON_ID, $patron_id );
581
557
        $resp .= add_field( FID_ITEM_ID,   $item_id );
582
	# If the item is valid, provide the title, otherwise
558
583
	# leave it blank
559
        # If the item is valid, provide the title, otherwise
584
	$resp .= add_field(FID_TITLE_ID, $item ? $item->title_id : '');
560
        # leave it blank
585
	# Due date is required.  Since it didn't get checked out,
561
        $resp .= add_field( FID_TITLE_ID, $item ? $item->title_id : '' );
586
	# it's not due, so leave the date blank
562
587
	$resp .= add_field(FID_DUE_DATE, '');
563
        # Due date is required.  Since it didn't get checked out,
588
564
        # it's not due, so leave the date blank
589
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
565
        $resp .= add_field( FID_DUE_DATE, '' );
590
	$resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
566
591
567
        $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
592
	if ($protocol_version >= 2) {
568
        $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
593
	    # Is the patron ID valid?
569
594
	    $resp .= add_field(FID_VALID_PATRON, sipbool($patron));
570
        if ( $protocol_version >= 2 ) {
595
571
596
	    if ($patron && exists($fields->{FID_PATRON_PWD})) {
572
            # Is the patron ID valid?
597
		# Password provided, so we can tell if it was valid or not
573
            $resp .= add_field( FID_VALID_PATRON, sipbool($patron) );
598
		$resp .= add_field(FID_VALID_PATRON_PWD,
574
599
				   sipbool($patron->check_password($fields->{(FID_PATRON_PWD)})));
575
            if ( $patron && exists( $fields->{FID_PATRON_PWD} ) ) {
600
	    }
576
601
	}
577
                # Password provided, so we can tell if it was valid or not
578
                $resp .= add_field( FID_VALID_PATRON_PWD, sipbool( $patron->check_password( $fields->{ (FID_PATRON_PWD) } ) ) );
579
            }
580
        }
602
    }
581
    }
603
582
604
    if ( $protocol_version >= 2 ) {
583
    if ( $protocol_version >= 2 ) {
Lines 612-732 sub handle_checkout { Link Here
612
        }
591
        }
613
    }
592
    }
614
593
615
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
594
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
616
    return(CHECKOUT);
595
    return (CHECKOUT);
617
}
596
}
618
597
619
sub handle_checkin {
598
sub handle_checkin {
620
    my ($self, $server) = @_;
599
    my ( $self, $server ) = @_;
621
    my $account = $server->{account};
600
    my $account   = $server->{account};
622
    my $ils     = $server->{ils};
601
    my $ils       = $server->{ils};
623
    my $my_branch = $ils->institution;
602
    my $my_branch = $ils->institution;
624
    my ($current_loc, $inst_id, $item_id, $terminal_pwd, $item_props, $cancel);
603
    my ( $current_loc, $inst_id, $item_id, $terminal_pwd, $item_props, $cancel );
625
    my ($patron, $item, $status);
604
    my ( $patron, $item, $status );
626
    my $resp = CHECKIN_RESP;
605
    my $resp = CHECKIN_RESP;
627
    my ($no_block, $trans_date, $return_date) = @{$self->{fixed_fields}};
606
    my ( $no_block, $trans_date, $return_date ) = @{ $self->{fixed_fields} };
628
	my $fields = $self->{fields};
607
    my $fields = $self->{fields};
629
608
630
	$current_loc = $fields->{(FID_CURRENT_LOCN)};
609
    $current_loc = $fields->{ (FID_CURRENT_LOCN) };
631
	$inst_id     = $fields->{(FID_INST_ID)};
610
    $inst_id     = $fields->{ (FID_INST_ID) };
632
	$item_id     = $fields->{(FID_ITEM_ID)};
611
    $item_id     = $fields->{ (FID_ITEM_ID) };
633
	$item_props  = $fields->{(FID_ITEM_PROPS)};
612
    $item_props  = $fields->{ (FID_ITEM_PROPS) };
634
	$cancel      = $fields->{(FID_CANCEL)};
613
    $cancel      = $fields->{ (FID_CANCEL) };
635
    if ($current_loc) {
614
    if ($current_loc) {
636
        $my_branch = $current_loc;# most scm do not set $current_loc
615
        $my_branch = $current_loc;    # most scm do not set $current_loc
637
    }
616
    }
638
617
639
    $ils->check_inst_id($inst_id, "handle_checkin");
618
    $ils->check_inst_id( $inst_id, "handle_checkin" );
619
620
    if ( $no_block eq 'Y' ) {
640
621
641
    if ($no_block eq 'Y') {
642
        # Off-line transactions, ick.
622
        # Off-line transactions, ick.
643
        syslog("LOG_WARNING", "received no-block checkin from terminal '%s'", $account->{id});
623
        syslog( "LOG_WARNING", "received no-block checkin from terminal '%s'", $account->{id} );
644
        $status = $ils->checkin_no_block($item_id, $trans_date, $return_date, $item_props, $cancel);
624
        $status = $ils->checkin_no_block( $item_id, $trans_date, $return_date, $item_props, $cancel );
645
    } else {
625
    } else {
646
        $status = $ils->checkin($item_id, $trans_date, $return_date, $my_branch, $item_props, $cancel, $account->{checked_in_ok});
626
        $status = $ils->checkin( $item_id, $trans_date, $return_date, $my_branch, $item_props, $cancel, $account->{checked_in_ok} );
647
    }
627
    }
648
628
649
    $patron = $status->patron;
629
    $patron = $status->patron;
650
    $item   = $status->item;
630
    $item   = $status->item;
651
631
652
    $resp .= $status->ok ? '1' : '0';
632
    $resp .= $status->ok          ? '1' : '0';
653
    $resp .= $status->resensitize ? 'Y' : 'N';
633
    $resp .= $status->resensitize ? 'Y' : 'N';
654
    if ($item && $ils->supports('magnetic media')) {
634
    if ( $item && $ils->supports('magnetic media') ) {
655
		$resp .= sipbool($item->magnetic_media);
635
        $resp .= sipbool( $item->magnetic_media );
656
    } else {
636
    } else {
637
657
        # item barcode is invalid or system doesn't support 'magnetic media' indicator
638
        # item barcode is invalid or system doesn't support 'magnetic media' indicator
658
		$resp .= 'U';
639
        $resp .= 'U';
659
    }
640
    }
660
641
661
    # apparently we can't trust the returns from Checkin yet (because C4::Circulation::AddReturn is faulty)
642
    # apparently we can't trust the returns from Checkin yet (because C4::Circulation::AddReturn is faulty)
662
    # So we reproduce the alert logic here.
643
    # So we reproduce the alert logic here.
663
    if (not $status->alert) {
644
    if ( not $status->alert ) {
664
        if ($item->destination_loc and $item->destination_loc ne $my_branch) {
645
        if ( $item->destination_loc and $item->destination_loc ne $my_branch ) {
665
            $status->alert(1);
646
            $status->alert(1);
666
            $status->alert_type('04');  # no hold, just send it
647
            $status->alert_type('04');    # no hold, just send it
667
        }
648
        }
668
    }
649
    }
669
    $resp .= $status->alert ? 'Y' : 'N';
650
    $resp .= $status->alert ? 'Y' : 'N';
670
    $resp .= timestamp;
651
    $resp .= timestamp;
671
    $resp .= add_field(FID_INST_ID, $inst_id);
652
    $resp .= add_field( FID_INST_ID, $inst_id );
672
    $resp .= add_field(FID_ITEM_ID, $item_id);
653
    $resp .= add_field( FID_ITEM_ID, $item_id );
673
654
674
    if ($item) {
655
    if ($item) {
675
        $resp .= add_field(FID_PERM_LOCN, $item->permanent_location);
656
        $resp .= add_field( FID_PERM_LOCN, $item->permanent_location );
676
        $resp .= maybe_add(FID_TITLE_ID,  $item->title_id);
657
        $resp .= maybe_add( FID_TITLE_ID, $item->title_id );
677
    }
658
    }
678
659
679
    if ($protocol_version >= 2) {
660
    if ( $protocol_version >= 2 ) {
680
        $resp .= maybe_add(FID_SORT_BIN, $status->sort_bin);
661
        $resp .= maybe_add( FID_SORT_BIN, $status->sort_bin );
681
        if ($patron) {
662
        if ($patron) {
682
            $resp .= add_field(FID_PATRON_ID, $patron->id);
663
            $resp .= add_field( FID_PATRON_ID, $patron->id );
683
        }
664
        }
684
        if ($item) {
665
        if ($item) {
685
            $resp .= maybe_add(FID_MEDIA_TYPE,           $item->sip_media_type     );
666
            $resp .= maybe_add( FID_MEDIA_TYPE,           $item->sip_media_type );
686
            $resp .= maybe_add(FID_ITEM_PROPS,           $item->sip_item_properties);
667
            $resp .= maybe_add( FID_ITEM_PROPS,           $item->sip_item_properties );
687
            $resp .= maybe_add(FID_COLLECTION_CODE,      $item->collection_code    );
668
            $resp .= maybe_add( FID_COLLECTION_CODE,      $item->collection_code );
688
            $resp .= maybe_add(FID_CALL_NUMBER,          $item->call_number        );
669
            $resp .= maybe_add( FID_CALL_NUMBER,          $item->call_number );
689
            $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc    );
670
            $resp .= maybe_add( FID_DESTINATION_LOCATION, $item->destination_loc );
690
            $resp .= maybe_add(FID_HOLD_PATRON_ID,       $item->hold_patron_bcode     );
671
            $resp .= maybe_add( FID_HOLD_PATRON_ID,       $item->hold_patron_bcode );
691
            $resp .= maybe_add(FID_HOLD_PATRON_NAME,     $item->hold_patron_name   );
672
            $resp .= maybe_add( FID_HOLD_PATRON_NAME,     $item->hold_patron_name );
692
            if ($status->hold and $status->hold->{branchcode} ne $item->destination_loc) {
673
            if ( $status->hold and $status->hold->{branchcode} ne $item->destination_loc ) {
693
                warn 'SIP hold mismatch: $status->hold->{branchcode}=' . $status->hold->{branchcode} . '; $item->destination_loc=' . $item->destination_loc;
674
                warn 'SIP hold mismatch: $status->hold->{branchcode}=' . $status->hold->{branchcode} . '; $item->destination_loc=' . $item->destination_loc;
675
694
                # just me being paranoid.
676
                # just me being paranoid.
695
            }
677
            }
696
        }
678
        }
697
    }
679
    }
698
680
699
    $resp .= maybe_add(FID_ALERT_TYPE, $status->alert_type) if $status->alert;
681
    $resp .= maybe_add( FID_ALERT_TYPE, $status->alert_type ) if $status->alert;
700
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
682
    $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
701
    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
683
    $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
702
684
703
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
685
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
704
686
705
    return(CHECKIN);
687
    return (CHECKIN);
706
}
688
}
707
689
708
sub handle_block_patron {
690
sub handle_block_patron {
709
    my ($self, $server) = @_;
691
    my ( $self, $server ) = @_;
710
    my $account = $server->{account};
692
    my $account = $server->{account};
711
    my $ils = $server->{ils};
693
    my $ils     = $server->{ils};
712
    my ($card_retained, $trans_date);
694
    my ( $card_retained, $trans_date );
713
    my ($inst_id, $blocked_card_msg, $patron_id, $terminal_pwd);
695
    my ( $inst_id, $blocked_card_msg, $patron_id, $terminal_pwd );
714
    my ($fields,$resp,$patron);
696
    my ( $fields, $resp, $patron );
715
697
716
    ($card_retained, $trans_date) = @{$self->{fixed_fields}};
698
    ( $card_retained, $trans_date ) = @{ $self->{fixed_fields} };
717
    $fields = $self->{fields};
699
    $fields           = $self->{fields};
718
    $inst_id          = $fields->{(FID_INST_ID)};
700
    $inst_id          = $fields->{ (FID_INST_ID) };
719
    $blocked_card_msg = $fields->{(FID_BLOCKED_CARD_MSG)};
701
    $blocked_card_msg = $fields->{ (FID_BLOCKED_CARD_MSG) };
720
    $patron_id        = $fields->{(FID_PATRON_ID)};
702
    $patron_id        = $fields->{ (FID_PATRON_ID) };
721
    $terminal_pwd     = $fields->{(FID_TERMINAL_PWD)};
703
    $terminal_pwd     = $fields->{ (FID_TERMINAL_PWD) };
722
704
723
    # Terminal passwords are different from account login
705
    # Terminal passwords are different from account login
724
    # passwords, but I have no idea what to do with them.  So,
706
    # passwords, but I have no idea what to do with them.  So,
725
    # I'll just ignore them for now.
707
    # I'll just ignore them for now.
726
	
727
	# FIXME ???
728
708
729
    $ils->check_inst_id($inst_id, "block_patron");
709
    # FIXME ???
710
711
    $ils->check_inst_id( $inst_id, "block_patron" );
730
    $patron = $ils->find_patron($patron_id);
712
    $patron = $ils->find_patron($patron_id);
731
713
732
    # The correct response for a "Block Patron" message is a
714
    # The correct response for a "Block Patron" message is a
Lines 738-884 sub handle_block_patron { Link Here
738
    # we'll just say, "Unspecified", as per the spec.  Let the
720
    # we'll just say, "Unspecified", as per the spec.  Let the
739
    # terminal default to something that, one hopes, will be
721
    # terminal default to something that, one hopes, will be
740
    # intelligible
722
    # intelligible
741
	if ($patron) {
723
    if ($patron) {
742
		# Valid patron id
724
743
		$patron->block($card_retained, $blocked_card_msg);
725
        # Valid patron id
744
	}
726
        $patron->block( $card_retained, $blocked_card_msg );
727
    }
745
728
746
    $resp = build_patron_status( $patron, $patron->language, $fields, $server );
729
    $resp = build_patron_status( $patron, $patron->language, $fields, $server );
747
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
730
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
748
    return(BLOCK_PATRON);
731
    return (BLOCK_PATRON);
749
}
732
}
750
733
751
sub handle_sc_status {
734
sub handle_sc_status {
752
    my ($self, $server) = @_;
735
    my ( $self, $server ) = @_;
753
	($server) or warn "handle_sc_status error: no \$server argument received.";
736
    ($server) or warn "handle_sc_status error: no \$server argument received.";
754
	my ($status, $print_width, $sc_protocol_version) = @{$self->{fixed_fields}};
737
    my ( $status, $print_width, $sc_protocol_version ) = @{ $self->{fixed_fields} };
755
	my ($new_proto);
738
    my ($new_proto);
756
739
757
	if ($sc_protocol_version =~ /^1\./) {
740
    if ( $sc_protocol_version =~ /^1\./ ) {
758
		$new_proto = 1;
741
        $new_proto = 1;
759
	} elsif ($sc_protocol_version =~ /^2\./) {
742
    } elsif ( $sc_protocol_version =~ /^2\./ ) {
760
		$new_proto = 2;
743
        $new_proto = 2;
761
	} else {
744
    } else {
762
		syslog("LOG_WARNING", "Unrecognized protocol revision '%s', falling back to '1'", $sc_protocol_version);
745
        syslog( "LOG_WARNING", "Unrecognized protocol revision '%s', falling back to '1'", $sc_protocol_version );
763
		$new_proto = 1;
746
        $new_proto = 1;
764
	}
747
    }
765
748
766
	if ($new_proto != $protocol_version) {
749
    if ( $new_proto != $protocol_version ) {
767
		syslog("LOG_INFO", "Setting protocol level to $new_proto");
750
        syslog( "LOG_INFO", "Setting protocol level to $new_proto" );
768
		$protocol_version = $new_proto;
751
        $protocol_version = $new_proto;
769
	}
752
    }
770
753
771
    if ($status == SC_STATUS_PAPER) {
754
    if ( $status == SC_STATUS_PAPER ) {
772
	syslog("LOG_WARNING", "Self-Check unit '%s@%s' out of paper",
755
        syslog( "LOG_WARNING", "Self-Check unit '%s@%s' out of paper", $self->{account}->{id}, $self->{account}->{institution} );
773
	       $self->{account}->{id}, $self->{account}->{institution});
756
    } elsif ( $status == SC_STATUS_SHUTDOWN ) {
774
    } elsif ($status == SC_STATUS_SHUTDOWN) {
757
        syslog( "LOG_WARNING", "Self-Check unit '%s@%s' shutting down", $self->{account}->{id}, $self->{account}->{institution} );
775
	syslog("LOG_WARNING", "Self-Check unit '%s@%s' shutting down",
776
	       $self->{account}->{id}, $self->{account}->{institution});
777
    }
758
    }
778
759
779
    $self->{account}->{print_width} = $print_width;
760
    $self->{account}->{print_width} = $print_width;
780
    return (send_acs_status($self, $server) ? SC_STATUS : '');
761
    return ( send_acs_status( $self, $server ) ? SC_STATUS : '' );
781
}
762
}
782
763
783
sub handle_request_acs_resend {
764
sub handle_request_acs_resend {
784
    my ($self, $server) = @_;
765
    my ( $self, $server ) = @_;
785
766
786
    if (!$last_response) {
767
    if ( !$last_response ) {
787
	# We haven't sent anything yet, so respond with a
768
788
	# REQUEST_SC_RESEND msg (p. 16)
769
        # We haven't sent anything yet, so respond with a
789
   $self->write_msg(REQUEST_SC_RESEND,undef,$server->{account}->{terminator},$server->{account}->{encoding});
770
        # REQUEST_SC_RESEND msg (p. 16)
790
    } elsif ((length($last_response) < 9)
771
        $self->write_msg( REQUEST_SC_RESEND, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
791
	     || substr($last_response, -9, 2) ne 'AY') {
772
    } elsif ( ( length($last_response) < 9 )
792
	# When resending a message, we aren't supposed to include
773
        || substr( $last_response, -9, 2 ) ne 'AY' ) {
793
	# a sequence number, even if the original had one (p. 4).
774
794
	# If the last message didn't have a sequence number, then
775
        # When resending a message, we aren't supposed to include
795
	# we can just send it.
776
        # a sequence number, even if the original had one (p. 4).
796
	print("$last_response\r");	# not write_msg?
777
        # If the last message didn't have a sequence number, then
778
        # we can just send it.
779
        print("$last_response\r");    # not write_msg?
797
    } else {
780
    } else {
798
	# Cut out the sequence number and checksum, since the old
781
799
	# checksum is wrong for the resent message.
782
        # Cut out the sequence number and checksum, since the old
800
	my $rebuilt = substr($last_response, 0, -9);
783
        # checksum is wrong for the resent message.
801
   $self->write_msg($rebuilt,undef,$server->{account}->{terminator},$server->{account}->{encoding});
784
        my $rebuilt = substr( $last_response, 0, -9 );
785
        $self->write_msg( $rebuilt, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
802
    }
786
    }
803
787
804
    return REQUEST_ACS_RESEND;
788
    return REQUEST_ACS_RESEND;
805
}
789
}
806
790
807
sub login_core  {
791
sub login_core {
808
    my $server = shift or return;
792
    my $server = shift or return;
809
	my $uid = shift;
793
    my $uid    = shift;
810
	my $pwd = shift;
794
    my $pwd    = shift;
811
    my $status = 1;		# Assume it all works
795
    my $status = 1;                 # Assume it all works
812
    if (!exists($server->{config}->{accounts}->{$uid})) {
796
    if ( !exists( $server->{config}->{accounts}->{$uid} ) ) {
813
		syslog("LOG_WARNING", "MsgType::login_core: Unknown login '$uid'");
797
        syslog( "LOG_WARNING", "MsgType::login_core: Unknown login '$uid'" );
814
		$status = 0;
798
        $status = 0;
815
    } elsif ($server->{config}->{accounts}->{$uid}->{password} ne $pwd) {
799
    } elsif ( $server->{config}->{accounts}->{$uid}->{password} ne $pwd ) {
816
		syslog("LOG_WARNING", "MsgType::login_core: Invalid password for login '$uid'");
800
        syslog( "LOG_WARNING", "MsgType::login_core: Invalid password for login '$uid'" );
817
		$status = 0;
801
        $status = 0;
818
    } else {
802
    } else {
819
	# Store the active account someplace handy for everybody else to find.
803
820
		$server->{account} = $server->{config}->{accounts}->{$uid};
804
        # Store the active account someplace handy for everybody else to find.
821
		my $inst = $server->{account}->{institution};
805
        $server->{account} = $server->{config}->{accounts}->{$uid};
822
		$server->{institution} = $server->{config}->{institutions}->{$inst};
806
        my $inst = $server->{account}->{institution};
823
		$server->{policy} = $server->{institution}->{policy};
807
        $server->{institution}  = $server->{config}->{institutions}->{$inst};
824
		$server->{sip_username} = $uid;
808
        $server->{policy}       = $server->{institution}->{policy};
825
		$server->{sip_password} = $pwd;
809
        $server->{sip_username} = $uid;
826
810
        $server->{sip_password} = $pwd;
827
        my $auth_status = api_auth($uid,$pwd,$inst);
811
828
		if (!$auth_status or $auth_status !~ /^ok$/i) {
812
        my $auth_status = api_auth( $uid, $pwd, $inst );
829
			syslog("LOG_WARNING", "api_auth failed for SIP terminal '%s' of '%s': %s",
813
        if ( !$auth_status or $auth_status !~ /^ok$/i ) {
830
						$uid, $inst, ($auth_status||'unknown'));
814
            syslog( "LOG_WARNING", "api_auth failed for SIP terminal '%s' of '%s': %s", $uid, $inst, ( $auth_status || 'unknown' ) );
831
			$status = 0;
815
            $status = 0;
832
		} else {
816
        } else {
833
			syslog("LOG_INFO", "Successful login/auth for '%s' of '%s'", $server->{account}->{id}, $inst);
817
            syslog( "LOG_INFO", "Successful login/auth for '%s' of '%s'", $server->{account}->{id}, $inst );
834
			#
818
835
			# initialize connection to ILS
819
            #
836
			#
820
            # initialize connection to ILS
837
			my $module = $server->{config}->{institutions}->{$inst}->{implementation};
821
            #
838
			syslog("LOG_DEBUG", 'login_core: ' . Dumper($module));
822
            my $module = $server->{config}->{institutions}->{$inst}->{implementation};
823
            syslog( "LOG_DEBUG", 'login_core: ' . Dumper($module) );
824
839
            # Suspect this is always ILS but so we don't break any eccentic install (for now)
825
            # Suspect this is always ILS but so we don't break any eccentic install (for now)
840
            if ($module eq 'ILS') {
826
            if ( $module eq 'ILS' ) {
841
                $module = 'C4::SIP::ILS';
827
                $module = 'C4::SIP::ILS';
842
            }
828
            }
843
			$module->use;
829
            $module->use;
844
			if ($@) {
830
            if ($@) {
845
				syslog("LOG_ERR", "%s: Loading ILS implementation '%s' for institution '%s' failed",
831
                syslog( "LOG_ERR", "%s: Loading ILS implementation '%s' for institution '%s' failed", $server->{service}, $module, $inst );
846
						$server->{service}, $module, $inst);
832
                die("Failed to load ILS implementation '$module' for $inst");
847
				die("Failed to load ILS implementation '$module' for $inst");
833
            }
848
			}
834
849
835
            # like   ILS->new(), I think.
850
			# like   ILS->new(), I think.
836
            $server->{ils} = $module->new( $server->{institution}, $server->{account} );
851
			$server->{ils} = $module->new($server->{institution}, $server->{account});
837
            if ( !$server->{ils} ) {
852
			if (!$server->{ils}) {
838
                syslog( "LOG_ERR", "%s: ILS connection to '%s' failed", $server->{service}, $inst );
853
			    syslog("LOG_ERR", "%s: ILS connection to '%s' failed", $server->{service}, $inst);
839
                die("Unable to connect to ILS '$inst'");
854
			    die("Unable to connect to ILS '$inst'");
840
            }
855
			}
841
        }
856
		}
842
    }
857
	}
843
    return $status;
858
	return $status;
859
}
844
}
860
845
861
sub handle_login {
846
sub handle_login {
862
    my ($self, $server) = @_;
847
    my ( $self, $server ) = @_;
863
    my ($uid_algorithm, $pwd_algorithm);
848
    my ( $uid_algorithm, $pwd_algorithm );
864
    my ($uid, $pwd);
849
    my ( $uid,           $pwd );
865
    my $inst;
850
    my $inst;
866
    my $fields;
851
    my $fields;
867
    my $status = 1;		# Assume it all works
852
    my $status = 1;    # Assume it all works
868
853
869
    $fields = $self->{fields};
854
    $fields = $self->{fields};
870
    ($uid_algorithm, $pwd_algorithm) = @{$self->{fixed_fields}};
855
    ( $uid_algorithm, $pwd_algorithm ) = @{ $self->{fixed_fields} };
871
856
872
    $uid = $fields->{(FID_LOGIN_UID)}; # Terminal ID, not patron ID.
857
    $uid = $fields->{ (FID_LOGIN_UID) };    # Terminal ID, not patron ID.
873
    $pwd = $fields->{(FID_LOGIN_PWD)}; # Terminal PWD, not patron PWD.
858
    $pwd = $fields->{ (FID_LOGIN_PWD) };    # Terminal PWD, not patron PWD.
874
859
875
    if ($uid_algorithm || $pwd_algorithm) {
860
    if ( $uid_algorithm || $pwd_algorithm ) {
876
		syslog("LOG_ERR", "LOGIN: Unsupported non-zero encryption method(s): uid = $uid_algorithm, pwd = $pwd_algorithm");
861
        syslog( "LOG_ERR", "LOGIN: Unsupported non-zero encryption method(s): uid = $uid_algorithm, pwd = $pwd_algorithm" );
877
		$status = 0;
862
        $status = 0;
863
    } else {
864
        $status = login_core( $server, $uid, $pwd );
878
    }
865
    }
879
	else { $status = login_core($server,$uid,$pwd); }
880
866
881
   $self->write_msg(LOGIN_RESP . $status,undef,$server->{account}->{terminator},$server->{account}->{encoding});
867
    $self->write_msg( LOGIN_RESP . $status, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
882
    return $status ? LOGIN : '';
868
    return $status ? LOGIN : '';
883
}
869
}
884
870
Lines 890-988 sub handle_login { Link Here
890
# and we're going to believe it.
876
# and we're going to believe it.
891
#
877
#
892
sub summary_info {
878
sub summary_info {
893
    my ($ils, $patron, $summary, $start, $end) = @_;
879
    my ( $ils, $patron, $summary, $start, $end ) = @_;
894
    my $resp = '';
880
    my $resp = '';
895
    my $summary_type;
881
    my $summary_type;
882
896
    #
883
    #
897
    # Map from offsets in the "summary" field of the Patron Information
884
    # Map from offsets in the "summary" field of the Patron Information
898
    # message to the corresponding field and handler
885
    # message to the corresponding field and handler
899
    #
886
    #
900
    my @summary_map = (
887
    my @summary_map = (
901
        { func => $patron->can(   "hold_items"), fid => FID_HOLD_ITEMS             },
888
        { func => $patron->can("hold_items"),    fid => FID_HOLD_ITEMS },
902
        { func => $patron->can("overdue_items"), fid => FID_OVERDUE_ITEMS          },
889
        { func => $patron->can("overdue_items"), fid => FID_OVERDUE_ITEMS },
903
        { func => $patron->can("charged_items"), fid => FID_CHARGED_ITEMS          },
890
        { func => $patron->can("charged_items"), fid => FID_CHARGED_ITEMS },
904
        { func => $patron->can(   "fine_items"), fid => FID_FINE_ITEMS             },
891
        { func => $patron->can("fine_items"),    fid => FID_FINE_ITEMS },
905
        { func => $patron->can( "recall_items"), fid => FID_RECALL_ITEMS           },
892
        { func => $patron->can("recall_items"),  fid => FID_RECALL_ITEMS },
906
        { func => $patron->can("unavail_holds"), fid => FID_UNAVAILABLE_HOLD_ITEMS },
893
        { func => $patron->can("unavail_holds"), fid => FID_UNAVAILABLE_HOLD_ITEMS },
907
    );
894
    );
908
895
909
    if (($summary_type = index($summary, 'Y')) == -1) {
896
    if ( ( $summary_type = index( $summary, 'Y' ) ) == -1 ) {
910
        return '';  # No detailed information required
897
        return '';    # No detailed information required
911
    }
898
    }
912
899
913
    syslog("LOG_DEBUG", "Summary_info: index == '%d', field '%s'",
900
    syslog( "LOG_DEBUG", "Summary_info: index == '%d', field '%s'", $summary_type, $summary_map[$summary_type]->{fid} );
914
        $summary_type, $summary_map[$summary_type]->{fid});
915
901
916
    my $func = $summary_map[$summary_type]->{func};
902
    my $func     = $summary_map[$summary_type]->{func};
917
    my $fid  = $summary_map[$summary_type]->{fid};
903
    my $fid      = $summary_map[$summary_type]->{fid};
918
    my $itemlist = &$func($patron, $start, $end);
904
    my $itemlist = &$func( $patron, $start, $end );
919
905
920
    syslog("LOG_DEBUG", "summary_info: list = (%s)", join(", ", @{$itemlist}));
906
    syslog( "LOG_DEBUG", "summary_info: list = (%s)", join( ", ", @{$itemlist} ) );
921
    foreach my $i (@{$itemlist}) {
907
    foreach my $i ( @{$itemlist} ) {
922
        $resp .= add_field($fid, $i->{barcode});
908
        $resp .= add_field( $fid, $i->{barcode} );
923
    }
909
    }
924
910
925
    return $resp;
911
    return $resp;
926
}
912
}
927
913
928
sub handle_patron_info {
914
sub handle_patron_info {
929
    my ($self, $server) = @_;
915
    my ( $self, $server ) = @_;
930
    my $ils = $server->{ils};
916
    my $ils = $server->{ils};
931
    my ($lang, $trans_date, $summary) = @{$self->{fixed_fields}};
917
    my ( $lang, $trans_date, $summary ) = @{ $self->{fixed_fields} };
932
    my $fields = $self->{fields};
918
    my $fields = $self->{fields};
933
    my ($inst_id, $patron_id, $terminal_pwd, $patron_pwd, $start, $end);
919
    my ( $inst_id, $patron_id, $terminal_pwd, $patron_pwd, $start, $end );
934
    my ($resp, $patron);
920
    my ( $resp, $patron );
935
921
936
    $inst_id      = $fields->{(FID_INST_ID)};
922
    $inst_id      = $fields->{ (FID_INST_ID) };
937
    $patron_id    = $fields->{(FID_PATRON_ID)};
923
    $patron_id    = $fields->{ (FID_PATRON_ID) };
938
    $terminal_pwd = $fields->{(FID_TERMINAL_PWD)};
924
    $terminal_pwd = $fields->{ (FID_TERMINAL_PWD) };
939
    $patron_pwd   = $fields->{(FID_PATRON_PWD)};
925
    $patron_pwd   = $fields->{ (FID_PATRON_PWD) };
940
    $start        = $fields->{(FID_START_ITEM)};
926
    $start        = $fields->{ (FID_START_ITEM) };
941
    $end          = $fields->{(FID_END_ITEM)};
927
    $end          = $fields->{ (FID_END_ITEM) };
942
928
943
    $patron = $ils->find_patron($patron_id);
929
    $patron = $ils->find_patron($patron_id);
944
930
945
    $resp = (PATRON_INFO_RESP);
931
    $resp = (PATRON_INFO_RESP);
946
    if ($patron) {
932
    if ($patron) {
947
        $resp .= patron_status_string($patron);
933
        $resp .= patron_status_string($patron);
948
        $resp .= (defined($lang) and length($lang) ==3) ? $lang : $patron->language;
934
        $resp .= ( defined($lang) and length($lang) == 3 ) ? $lang : $patron->language;
949
        $resp .= timestamp();
935
        $resp .= timestamp();
950
936
951
        $resp .= add_count('patron_info/hold_items',
937
        $resp .= add_count( 'patron_info/hold_items',    scalar @{ $patron->hold_items } );
952
            scalar @{$patron->hold_items});
938
        $resp .= add_count( 'patron_info/overdue_items', scalar @{ $patron->overdue_items } );
953
        $resp .= add_count('patron_info/overdue_items',
939
        $resp .= add_count( 'patron_info/charged_items', scalar @{ $patron->charged_items } );
954
            scalar @{$patron->overdue_items});
940
        $resp .= add_count( 'patron_info/fine_items',    scalar @{ $patron->fine_items } );
955
        $resp .= add_count('patron_info/charged_items',
941
        $resp .= add_count( 'patron_info/recall_items',  scalar @{ $patron->recall_items } );
956
            scalar @{$patron->charged_items});
942
        $resp .= add_count( 'patron_info/unavail_holds', scalar @{ $patron->unavail_holds } );
957
        $resp .= add_count('patron_info/fine_items',
943
958
            scalar @{$patron->fine_items});
944
        $resp .= add_field( FID_INST_ID, ( $ils->institution_id || 'SIP2' ) );
959
        $resp .= add_count('patron_info/recall_items',
960
            scalar @{$patron->recall_items});
961
        $resp .= add_count('patron_info/unavail_holds',
962
            scalar @{$patron->unavail_holds});
963
964
        $resp .= add_field(FID_INST_ID,       ($ils->institution_id || 'SIP2'));
965
945
966
        # while the patron ID we got from the SC is valid, let's
946
        # while the patron ID we got from the SC is valid, let's
967
        # use the one returned from the ILS, just in case...
947
        # use the one returned from the ILS, just in case...
968
        $resp .= add_field(FID_PATRON_ID,     $patron->id);
948
        $resp .= add_field( FID_PATRON_ID,     $patron->id );
969
        $resp .= add_field(FID_PERSONAL_NAME, $patron->name);
949
        $resp .= add_field( FID_PERSONAL_NAME, $patron->name );
970
950
971
        # TODO: add code for the fields
951
        # TODO: add code for the fields
972
        #   hold items limit
952
        #   hold items limit
973
        #   overdue items limit
953
        #   overdue items limit
974
        #   charged items limit
954
        #   charged items limit
975
955
976
        $resp .= add_field(FID_VALID_PATRON, 'Y');
956
        $resp .= add_field( FID_VALID_PATRON, 'Y' );
977
        if (defined($patron_pwd)) {
957
        if ( defined($patron_pwd) ) {
958
978
            # If patron password was provided, report whether it was right or not.
959
            # If patron password was provided, report whether it was right or not.
979
            $resp .= add_field(FID_VALID_PATRON_PWD,
960
            $resp .= add_field( FID_VALID_PATRON_PWD, sipbool( $patron->check_password($patron_pwd) ) );
980
                sipbool($patron->check_password($patron_pwd)));
981
        }
961
        }
982
962
983
        $resp .= maybe_add(FID_CURRENCY,   $patron->currency);
963
        $resp .= maybe_add( FID_CURRENCY, $patron->currency );
984
        $resp .= maybe_add(FID_FEE_AMT,    $patron->fee_amount);
964
        $resp .= maybe_add( FID_FEE_AMT,  $patron->fee_amount );
985
        $resp .= add_field(FID_FEE_LMT,    $patron->fee_limit);
965
        $resp .= add_field( FID_FEE_LMT, $patron->fee_limit );
986
966
987
        # TODO: zero or more item details for 2.0 can go here:
967
        # TODO: zero or more item details for 2.0 can go here:
988
        #          hold_items
968
        #          hold_items
Lines 991-1468 sub handle_patron_info { Link Here
991
        #          fine_items
971
        #          fine_items
992
        #        recall_items
972
        #        recall_items
993
973
994
        $resp .= summary_info($ils, $patron, $summary, $start, $end);
974
        $resp .= summary_info( $ils, $patron, $summary, $start, $end );
995
975
996
        $resp .= maybe_add(FID_HOME_ADDR,  $patron->address);
976
        $resp .= maybe_add( FID_HOME_ADDR,  $patron->address );
997
        $resp .= maybe_add(FID_EMAIL,      $patron->email_addr);
977
        $resp .= maybe_add( FID_EMAIL,      $patron->email_addr );
998
        $resp .= maybe_add(FID_HOME_PHONE, $patron->home_phone);
978
        $resp .= maybe_add( FID_HOME_PHONE, $patron->home_phone );
999
979
1000
        # SIP 2.0 extensions used by Envisionware
980
        # SIP 2.0 extensions used by Envisionware
1001
        # Other terminals will ignore unrecognized fields (unrecognized field identifiers)
981
        # Other terminals will ignore unrecognized fields (unrecognized field identifiers)
1002
        $resp .= maybe_add(FID_PATRON_BIRTHDATE, $patron->birthdate);
982
        $resp .= maybe_add( FID_PATRON_BIRTHDATE, $patron->birthdate );
1003
        $resp .= maybe_add(FID_PATRON_CLASS,     $patron->ptype);
983
        $resp .= maybe_add( FID_PATRON_CLASS,     $patron->ptype );
1004
984
1005
        # Custom protocol extension to report patron internet privileges
985
        # Custom protocol extension to report patron internet privileges
1006
        $resp .= maybe_add(FID_INET_PROFILE,     $patron->inet_privileges);
986
        $resp .= maybe_add( FID_INET_PROFILE, $patron->inet_privileges );
1007
987
1008
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->screen_msg, $server );
988
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->screen_msg,   $server );
1009
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->{branchcode}, $server )
989
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->{branchcode}, $server )
1010
          if ( $server->{account}->{send_patron_home_library_in_af} );
990
          if ( $server->{account}->{send_patron_home_library_in_af} );
1011
991
1012
        $resp .= maybe_add(FID_PRINT_LINE,       $patron->print_line);
992
        $resp .= maybe_add( FID_PRINT_LINE, $patron->print_line );
1013
    } else {
993
    } else {
994
1014
        # Invalid patron ID:
995
        # Invalid patron ID:
1015
        # no privileges, no items associated,
996
        # no privileges, no items associated,
1016
        # no personal name, and is invalid (if we're using 2.00)
997
        # no personal name, and is invalid (if we're using 2.00)
1017
        $resp .= 'YYYY' . (' ' x 10) . $lang . timestamp();
998
        $resp .= 'YYYY' . ( ' ' x 10 ) . $lang . timestamp();
1018
        $resp .= '0000' x 6;
999
        $resp .= '0000' x 6;
1019
1000
1020
        $resp .= add_field(FID_INST_ID,       ($ils->institution_id || 'SIP2'));
1001
        $resp .= add_field( FID_INST_ID, ( $ils->institution_id || 'SIP2' ) );
1002
1021
        # patron ID is invalid, but field is required, so just echo it back
1003
        # patron ID is invalid, but field is required, so just echo it back
1022
        $resp .= add_field(FID_PATRON_ID,     $fields->{(FID_PATRON_ID)});
1004
        $resp .= add_field( FID_PATRON_ID, $fields->{ (FID_PATRON_ID) } );
1023
        $resp .= add_field(FID_PERSONAL_NAME, '');
1005
        $resp .= add_field( FID_PERSONAL_NAME, '' );
1024
1006
1025
        if ($protocol_version >= 2) {
1007
        if ( $protocol_version >= 2 ) {
1026
            $resp .= add_field(FID_VALID_PATRON, 'N');
1008
            $resp .= add_field( FID_VALID_PATRON, 'N' );
1027
        }
1009
        }
1028
    }
1010
    }
1029
1011
1030
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1012
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1031
    return(PATRON_INFO);
1013
    return (PATRON_INFO);
1032
}
1014
}
1033
1015
1034
sub handle_end_patron_session {
1016
sub handle_end_patron_session {
1035
    my ($self, $server) = @_;
1017
    my ( $self, $server ) = @_;
1036
    my $ils = $server->{ils};
1018
    my $ils = $server->{ils};
1037
    my $trans_date;
1019
    my $trans_date;
1038
    my $fields = $self->{fields};
1020
    my $fields = $self->{fields};
1039
    my $resp = END_SESSION_RESP;
1021
    my $resp   = END_SESSION_RESP;
1040
    my ($status, $screen_msg, $print_line);
1022
    my ( $status, $screen_msg, $print_line );
1041
1023
1042
    ($trans_date) = @{$self->{fixed_fields}};
1024
    ($trans_date) = @{ $self->{fixed_fields} };
1043
1025
1044
    $ils->check_inst_id($fields->{(FID_INST_ID)}, 'handle_end_patron_session');
1026
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, 'handle_end_patron_session' );
1045
1027
1046
    ($status, $screen_msg, $print_line) = $ils->end_patron_session($fields->{(FID_PATRON_ID)});
1028
    ( $status, $screen_msg, $print_line ) = $ils->end_patron_session( $fields->{ (FID_PATRON_ID) } );
1047
1029
1048
    $resp .= $status ? 'Y' : 'N';
1030
    $resp .= $status ? 'Y' : 'N';
1049
    $resp .= timestamp();
1031
    $resp .= timestamp();
1050
1032
1051
    $resp .= add_field(FID_INST_ID, $server->{ils}->institution);
1033
    $resp .= add_field( FID_INST_ID, $server->{ils}->institution );
1052
    $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)});
1034
    $resp .= add_field( FID_PATRON_ID, $fields->{ (FID_PATRON_ID) } );
1053
1035
1054
    $resp .= maybe_add(FID_SCREEN_MSG, $screen_msg, $server);
1036
    $resp .= maybe_add( FID_SCREEN_MSG, $screen_msg, $server );
1055
    $resp .= maybe_add(FID_PRINT_LINE, $print_line);
1037
    $resp .= maybe_add( FID_PRINT_LINE, $print_line );
1056
1038
1057
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1039
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1058
1040
1059
    return(END_PATRON_SESSION);
1041
    return (END_PATRON_SESSION);
1060
}
1042
}
1061
1043
1062
sub handle_fee_paid {
1044
sub handle_fee_paid {
1063
    my ($self, $server) = @_;
1045
    my ( $self, $server ) = @_;
1064
    my $ils = $server->{ils};
1046
    my $ils = $server->{ils};
1065
    my ($trans_date, $fee_type, $pay_type, $currency) = @{ $self->{fixed_fields} };
1047
    my ( $trans_date, $fee_type, $pay_type, $currency ) = @{ $self->{fixed_fields} };
1066
    my $fields = $self->{fields};
1048
    my $fields = $self->{fields};
1067
    my ($fee_amt, $inst_id, $patron_id, $terminal_pwd, $patron_pwd);
1049
    my ( $fee_amt, $inst_id, $patron_id, $terminal_pwd, $patron_pwd );
1068
    my ($fee_id, $trans_id);
1050
    my ( $fee_id, $trans_id );
1069
    my $status;
1051
    my $status;
1070
    my $resp = FEE_PAID_RESP;
1052
    my $resp = FEE_PAID_RESP;
1071
1053
1072
    $fee_amt = $fields->{(FID_FEE_AMT)};
1054
    $fee_amt    = $fields->{ (FID_FEE_AMT) };
1073
    $inst_id = $fields->{(FID_INST_ID)};
1055
    $inst_id    = $fields->{ (FID_INST_ID) };
1074
    $patron_id = $fields->{(FID_PATRON_ID)};
1056
    $patron_id  = $fields->{ (FID_PATRON_ID) };
1075
    $patron_pwd = $fields->{(FID_PATRON_PWD)};
1057
    $patron_pwd = $fields->{ (FID_PATRON_PWD) };
1076
    $fee_id = $fields->{(FID_FEE_ID)};
1058
    $fee_id     = $fields->{ (FID_FEE_ID) };
1077
    $trans_id = $fields->{(FID_TRANSACTION_ID)};
1059
    $trans_id   = $fields->{ (FID_TRANSACTION_ID) };
1078
1060
1079
    $ils->check_inst_id($inst_id, "handle_fee_paid");
1061
    $ils->check_inst_id( $inst_id, "handle_fee_paid" );
1080
1062
1081
    $status = $ils->pay_fee($patron_id, $patron_pwd, $fee_amt, $fee_type,
1063
    $status = $ils->pay_fee( $patron_id, $patron_pwd, $fee_amt, $fee_type, $pay_type, $fee_id, $trans_id, $currency );
1082
			   $pay_type, $fee_id, $trans_id, $currency);
1083
1064
1084
    $resp .= ($status->ok ? 'Y' : 'N') . timestamp;
1065
    $resp .= ( $status->ok ? 'Y' : 'N' ) . timestamp;
1085
    $resp .= add_field(FID_INST_ID, $inst_id);
1066
    $resp .= add_field( FID_INST_ID,   $inst_id );
1086
    $resp .= add_field(FID_PATRON_ID, $patron_id);
1067
    $resp .= add_field( FID_PATRON_ID, $patron_id );
1087
    $resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id);
1068
    $resp .= maybe_add( FID_TRANSACTION_ID, $status->transaction_id );
1088
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
1069
    $resp .= maybe_add( FID_SCREEN_MSG,     $status->screen_msg, $server );
1089
    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
1070
    $resp .= maybe_add( FID_PRINT_LINE,     $status->print_line );
1090
1071
1091
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1072
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1092
1073
1093
    return(FEE_PAID);
1074
    return (FEE_PAID);
1094
}
1075
}
1095
1076
1096
sub handle_item_information {
1077
sub handle_item_information {
1097
    my ($self, $server) = @_;
1078
    my ( $self, $server ) = @_;
1098
    my $ils = $server->{ils};
1079
    my $ils = $server->{ils};
1099
    my $trans_date;
1080
    my $trans_date;
1100
    my $fields = $self->{fields};
1081
    my $fields = $self->{fields};
1101
    my $resp = ITEM_INFO_RESP;
1082
    my $resp   = ITEM_INFO_RESP;
1102
    my $item;
1083
    my $item;
1103
    my $i;
1084
    my $i;
1104
1085
1105
    ($trans_date) = @{$self->{fixed_fields}};
1086
    ($trans_date) = @{ $self->{fixed_fields} };
1087
1088
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, "handle_item_information" );
1089
1090
    $item = $ils->find_item( $fields->{ (FID_ITEM_ID) } );
1106
1091
1107
    $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_item_information");
1092
    if ( !defined($item) ) {
1108
1093
1109
    $item =  $ils->find_item($fields->{(FID_ITEM_ID)});
1094
        # Invalid Item ID
1095
        # "Other" circ stat, "Other" security marker, "Unknown" fee type
1096
        $resp .= "010101";
1097
        $resp .= timestamp;
1110
1098
1111
    if (!defined($item)) {
1099
        # Just echo back the invalid item id
1112
	# Invalid Item ID
1100
        $resp .= add_field( FID_ITEM_ID, $fields->{ (FID_ITEM_ID) } );
1113
	# "Other" circ stat, "Other" security marker, "Unknown" fee type
1101
1114
	$resp .= "010101";
1102
        # title id is required, but we don't have one
1115
	$resp .= timestamp;
1103
        $resp .= add_field( FID_TITLE_ID, '' );
1116
	# Just echo back the invalid item id
1117
	$resp .= add_field(FID_ITEM_ID, $fields->{(FID_ITEM_ID)});
1118
	# title id is required, but we don't have one
1119
	$resp .= add_field(FID_TITLE_ID, '');
1120
    } else {
1104
    } else {
1121
	# Valid Item ID, send the good stuff
1105
1122
	$resp .= $item->sip_circulation_status;
1106
        # Valid Item ID, send the good stuff
1123
	$resp .= $item->sip_security_marker;
1107
        $resp .= $item->sip_circulation_status;
1124
	$resp .= $item->sip_fee_type;
1108
        $resp .= $item->sip_security_marker;
1125
	$resp .= timestamp;
1109
        $resp .= $item->sip_fee_type;
1126
1110
        $resp .= timestamp;
1127
	$resp .= add_field(FID_ITEM_ID,  $item->id);
1111
1128
	$resp .= add_field(FID_TITLE_ID, $item->title_id);
1112
        $resp .= add_field( FID_ITEM_ID,  $item->id );
1129
1113
        $resp .= add_field( FID_TITLE_ID, $item->title_id );
1130
	$resp .= maybe_add(FID_MEDIA_TYPE,   $item->sip_media_type);
1114
1131
	$resp .= maybe_add(FID_PERM_LOCN,    $item->permanent_location);
1115
        $resp .= maybe_add( FID_MEDIA_TYPE,   $item->sip_media_type );
1132
	$resp .= maybe_add(FID_CURRENT_LOCN, $item->current_location);
1116
        $resp .= maybe_add( FID_PERM_LOCN,    $item->permanent_location );
1133
	$resp .= maybe_add(FID_ITEM_PROPS,   $item->sip_item_properties);
1117
        $resp .= maybe_add( FID_CURRENT_LOCN, $item->current_location );
1134
1118
        $resp .= maybe_add( FID_ITEM_PROPS,   $item->sip_item_properties );
1135
	if (($i = $item->fee) != 0) {
1119
1136
	    $resp .= add_field(FID_CURRENCY, $item->fee_currency);
1120
        if ( ( $i = $item->fee ) != 0 ) {
1137
	    $resp .= add_field(FID_FEE_AMT, $i);
1121
            $resp .= add_field( FID_CURRENCY, $item->fee_currency );
1138
	}
1122
            $resp .= add_field( FID_FEE_AMT,  $i );
1139
	$resp .= maybe_add(FID_OWNER, $item->owner);
1123
        }
1140
1124
        $resp .= maybe_add( FID_OWNER, $item->owner );
1141
	if (($i = scalar @{$item->hold_queue}) > 0) {
1125
1142
	    $resp .= add_field(FID_HOLD_QUEUE_LEN, $i);
1126
        if ( ( $i = scalar @{ $item->hold_queue } ) > 0 ) {
1143
	}
1127
            $resp .= add_field( FID_HOLD_QUEUE_LEN, $i );
1144
	if ($item->due_date) {
1128
        }
1145
	    $resp .= add_field(FID_DUE_DATE, timestamp($item->due_date));
1129
        if ( $item->due_date ) {
1146
	}
1130
            $resp .= add_field( FID_DUE_DATE, timestamp( $item->due_date ) );
1147
	if (($i = $item->recall_date) != 0) {
1131
        }
1148
	    $resp .= add_field(FID_RECALL_DATE, timestamp($i));
1132
        if ( ( $i = $item->recall_date ) != 0 ) {
1149
	}
1133
            $resp .= add_field( FID_RECALL_DATE, timestamp($i) );
1150
	if (($i = $item->hold_pickup_date) != 0) {
1134
        }
1151
	    $resp .= add_field(FID_HOLD_PICKUP_DATE, timestamp($i));
1135
        if ( ( $i = $item->hold_pickup_date ) != 0 ) {
1152
	}
1136
            $resp .= add_field( FID_HOLD_PICKUP_DATE, timestamp($i) );
1153
1137
        }
1154
    $resp .= maybe_add(FID_SCREEN_MSG, $item->screen_msg, $server);
1138
1155
	$resp .= maybe_add(FID_PRINT_LINE, $item->print_line);
1139
        $resp .= maybe_add( FID_SCREEN_MSG, $item->screen_msg, $server );
1140
        $resp .= maybe_add( FID_PRINT_LINE, $item->print_line );
1156
    }
1141
    }
1157
1142
1158
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1143
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1159
1144
1160
    return(ITEM_INFORMATION);
1145
    return (ITEM_INFORMATION);
1161
}
1146
}
1162
1147
1163
sub handle_item_status_update {
1148
sub handle_item_status_update {
1164
    my ($self, $server) = @_;
1149
    my ( $self, $server ) = @_;
1165
    my $ils = $server->{ils};
1150
    my $ils = $server->{ils};
1166
    my ($trans_date, $item_id, $terminal_pwd, $item_props);
1151
    my ( $trans_date, $item_id, $terminal_pwd, $item_props );
1167
    my $fields = $self->{fields};
1152
    my $fields = $self->{fields};
1168
    my $status;
1153
    my $status;
1169
    my $item;
1154
    my $item;
1170
    my $resp = ITEM_STATUS_UPDATE_RESP;
1155
    my $resp = ITEM_STATUS_UPDATE_RESP;
1171
1156
1172
    ($trans_date) = @{$self->{fixed_fields}};
1157
    ($trans_date) = @{ $self->{fixed_fields} };
1173
1158
1174
    $ils->check_inst_id($fields->{(FID_INST_ID)});
1159
    $ils->check_inst_id( $fields->{ (FID_INST_ID) } );
1175
1160
1176
    $item_id = $fields->{(FID_ITEM_ID)};
1161
    $item_id    = $fields->{ (FID_ITEM_ID) };
1177
    $item_props = $fields->{(FID_ITEM_PROPS)};
1162
    $item_props = $fields->{ (FID_ITEM_PROPS) };
1178
1163
1179
	if (!defined($item_id)) {
1164
    if ( !defined($item_id) ) {
1180
		syslog("LOG_WARNING",
1165
        syslog( "LOG_WARNING", "handle_item_status: received message without Item ID field" );
1181
			"handle_item_status: received message without Item ID field");
1182
    } else {
1166
    } else {
1183
		$item = $ils->find_item($item_id);
1167
        $item = $ils->find_item($item_id);
1184
	}
1168
    }
1185
1169
1186
    if (!$item) {
1170
    if ( !$item ) {
1187
	# Invalid Item ID
1171
1188
	$resp .= '0';
1172
        # Invalid Item ID
1189
	$resp .= timestamp;
1173
        $resp .= '0';
1190
	$resp .= add_field(FID_ITEM_ID, $item_id);
1174
        $resp .= timestamp;
1175
        $resp .= add_field( FID_ITEM_ID, $item_id );
1191
    } else {
1176
    } else {
1192
	# Valid Item ID
1193
1177
1194
	$status = $item->status_update($item_props);
1178
        # Valid Item ID
1179
1180
        $status = $item->status_update($item_props);
1195
1181
1196
	$resp .= $status->ok ? '1' : '0';
1182
        $resp .= $status->ok ? '1' : '0';
1197
	$resp .= timestamp;
1183
        $resp .= timestamp;
1198
1184
1199
	$resp .= add_field(FID_ITEM_ID, $item->id);
1185
        $resp .= add_field( FID_ITEM_ID,  $item->id );
1200
	$resp .= add_field(FID_TITLE_ID, $item->title_id);
1186
        $resp .= add_field( FID_TITLE_ID, $item->title_id );
1201
	$resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
1187
        $resp .= maybe_add( FID_ITEM_PROPS, $item->sip_item_properties );
1202
    }
1188
    }
1203
1189
1204
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
1190
    $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
1205
    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
1191
    $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
1206
1192
1207
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1193
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1208
1194
1209
    return(ITEM_STATUS_UPDATE);
1195
    return (ITEM_STATUS_UPDATE);
1210
}
1196
}
1211
1197
1212
sub handle_patron_enable {
1198
sub handle_patron_enable {
1213
    my ($self, $server) = @_;
1199
    my ( $self, $server ) = @_;
1214
    my $ils = $server->{ils};
1200
    my $ils    = $server->{ils};
1215
    my $fields = $self->{fields};
1201
    my $fields = $self->{fields};
1216
    my ($trans_date, $patron_id, $terminal_pwd, $patron_pwd);
1202
    my ( $trans_date, $patron_id, $terminal_pwd, $patron_pwd );
1217
    my ($status, $patron);
1203
    my ( $status, $patron );
1218
    my $resp = PATRON_ENABLE_RESP;
1204
    my $resp = PATRON_ENABLE_RESP;
1219
1205
1220
    ($trans_date) = @{$self->{fixed_fields}};
1206
    ($trans_date) = @{ $self->{fixed_fields} };
1221
    $patron_id = $fields->{(FID_PATRON_ID)};
1207
    $patron_id  = $fields->{ (FID_PATRON_ID) };
1222
    $patron_pwd = $fields->{(FID_PATRON_PWD)};
1208
    $patron_pwd = $fields->{ (FID_PATRON_PWD) };
1223
1209
1224
    syslog("LOG_DEBUG", "handle_patron_enable: patron_id: '%s', patron_pwd: '%s'",
1210
    syslog( "LOG_DEBUG", "handle_patron_enable: patron_id: '%s', patron_pwd: '%s'", $patron_id, $patron_pwd );
1225
	   $patron_id, $patron_pwd);
1226
1211
1227
    $patron = $ils->find_patron($patron_id);
1212
    $patron = $ils->find_patron($patron_id);
1228
1213
1229
    if (!defined($patron)) {
1214
    if ( !defined($patron) ) {
1230
	# Invalid patron ID
1215
1231
	$resp .= 'YYYY' . (' ' x 10) . '000' . timestamp();
1216
        # Invalid patron ID
1232
	$resp .= add_field(FID_PATRON_ID, $patron_id);
1217
        $resp .= 'YYYY' . ( ' ' x 10 ) . '000' . timestamp();
1233
	$resp .= add_field(FID_PERSONAL_NAME, '');
1218
        $resp .= add_field( FID_PATRON_ID,        $patron_id );
1234
	$resp .= add_field(FID_VALID_PATRON, 'N');
1219
        $resp .= add_field( FID_PERSONAL_NAME,    '' );
1235
	$resp .= add_field(FID_VALID_PATRON_PWD, 'N');
1220
        $resp .= add_field( FID_VALID_PATRON,     'N' );
1221
        $resp .= add_field( FID_VALID_PATRON_PWD, 'N' );
1236
    } else {
1222
    } else {
1237
	# valid patron
1223
1238
	if (!defined($patron_pwd) || $patron->check_password($patron_pwd)) {
1224
        # valid patron
1239
	    # Don't enable the patron if there was an invalid password
1225
        if ( !defined($patron_pwd) || $patron->check_password($patron_pwd) ) {
1240
	    $status = $patron->enable;
1226
1241
	}
1227
            # Don't enable the patron if there was an invalid password
1242
	$resp .= patron_status_string($patron);
1228
            $status = $patron->enable;
1243
	$resp .= $patron->language . timestamp();
1229
        }
1244
1230
        $resp .= patron_status_string($patron);
1245
	$resp .= add_field(FID_PATRON_ID, $patron->id);
1231
        $resp .= $patron->language . timestamp();
1246
	$resp .= add_field(FID_PERSONAL_NAME, $patron->name);
1232
1247
	if (defined($patron_pwd)) {
1233
        $resp .= add_field( FID_PATRON_ID,     $patron->id );
1248
	    $resp .= add_field(FID_VALID_PATRON_PWD,
1234
        $resp .= add_field( FID_PERSONAL_NAME, $patron->name );
1249
			       sipbool($patron->check_password($patron_pwd)));
1235
        if ( defined($patron_pwd) ) {
1250
	}
1236
            $resp .= add_field( FID_VALID_PATRON_PWD, sipbool( $patron->check_password($patron_pwd) ) );
1251
	$resp .= add_field(FID_VALID_PATRON, 'Y');
1237
        }
1252
    $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg, $server);
1238
        $resp .= add_field( FID_VALID_PATRON, 'Y' );
1253
	$resp .= maybe_add(FID_PRINT_LINE, $patron->print_line);
1239
        $resp .= maybe_add( FID_SCREEN_MSG, $patron->screen_msg, $server );
1240
        $resp .= maybe_add( FID_PRINT_LINE, $patron->print_line );
1254
    }
1241
    }
1255
1242
1256
    $resp .= add_field(FID_INST_ID, $ils->institution);
1243
    $resp .= add_field( FID_INST_ID, $ils->institution );
1257
1244
1258
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1245
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1259
1246
1260
    return(PATRON_ENABLE);
1247
    return (PATRON_ENABLE);
1261
}
1248
}
1262
1249
1263
sub handle_hold {
1250
sub handle_hold {
1264
    my ($self, $server) = @_;
1251
    my ( $self, $server ) = @_;
1265
    my $ils = $server->{ils};
1252
    my $ils = $server->{ils};
1266
    my ($hold_mode, $trans_date);
1253
    my ( $hold_mode, $trans_date );
1267
    my ($expiry_date, $pickup_locn, $hold_type, $patron_id, $patron_pwd);
1254
    my ( $expiry_date, $pickup_locn, $hold_type, $patron_id, $patron_pwd );
1268
    my ($item_id, $title_id, $fee_ack);
1255
    my ( $item_id, $title_id, $fee_ack );
1269
    my $fields = $self->{fields};
1256
    my $fields = $self->{fields};
1270
    my $status;
1257
    my $status;
1271
    my $resp = HOLD_RESP;
1258
    my $resp = HOLD_RESP;
1272
1259
1273
    ($hold_mode, $trans_date) = @{$self->{fixed_fields}};
1260
    ( $hold_mode, $trans_date ) = @{ $self->{fixed_fields} };
1274
1261
1275
    $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_hold");
1262
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, "handle_hold" );
1276
1263
1277
    $patron_id   = $fields->{(FID_PATRON_ID)  };
1264
    $patron_id   = $fields->{ (FID_PATRON_ID) };
1278
    $expiry_date = $fields->{(FID_EXPIRATION) } || '';
1265
    $expiry_date = $fields->{ (FID_EXPIRATION) } || '';
1279
    $pickup_locn = $fields->{(FID_PICKUP_LOCN)} || '';
1266
    $pickup_locn = $fields->{ (FID_PICKUP_LOCN) } || '';
1280
    $hold_type   = $fields->{(FID_HOLD_TYPE)  } || '2'; # Any copy of title
1267
    $hold_type   = $fields->{ (FID_HOLD_TYPE) } || '2';    # Any copy of title
1281
    $patron_pwd  = $fields->{(FID_PATRON_PWD) };
1268
    $patron_pwd  = $fields->{ (FID_PATRON_PWD) };
1282
    $item_id     = $fields->{(FID_ITEM_ID)    } || '';
1269
    $item_id     = $fields->{ (FID_ITEM_ID) } || '';
1283
    $title_id    = $fields->{(FID_TITLE_ID)   } || '';
1270
    $title_id    = $fields->{ (FID_TITLE_ID) } || '';
1284
    $fee_ack     = $fields->{(FID_FEE_ACK)    } || 'N';
1271
    $fee_ack     = $fields->{ (FID_FEE_ACK) } || 'N';
1285
1272
1286
    if ($hold_mode eq '+') {
1273
    if ( $hold_mode eq '+' ) {
1287
	$status = $ils->add_hold($patron_id, $patron_pwd, $item_id, $title_id,
1274
        $status = $ils->add_hold( $patron_id, $patron_pwd, $item_id, $title_id, $expiry_date, $pickup_locn, $hold_type, $fee_ack );
1288
						$expiry_date, $pickup_locn, $hold_type, $fee_ack);
1275
    } elsif ( $hold_mode eq '-' ) {
1289
    } elsif ($hold_mode eq '-') {
1276
        $status = $ils->cancel_hold( $patron_id, $patron_pwd, $item_id, $title_id );
1290
	$status = $ils->cancel_hold($patron_id, $patron_pwd, $item_id, $title_id);
1277
    } elsif ( $hold_mode eq '*' ) {
1291
    } elsif ($hold_mode eq '*') {
1278
        $status = $ils->alter_hold( $patron_id, $patron_pwd, $item_id, $title_id, $expiry_date, $pickup_locn, $hold_type, $fee_ack );
1292
	$status = $ils->alter_hold($patron_id, $patron_pwd, $item_id, $title_id,
1293
						$expiry_date, $pickup_locn, $hold_type, $fee_ack);
1294
    } else {
1279
    } else {
1295
	syslog("LOG_WARNING", "handle_hold: Unrecognized hold mode '%s' from terminal '%s'",
1280
        syslog( "LOG_WARNING", "handle_hold: Unrecognized hold mode '%s' from terminal '%s'", $hold_mode, $server->{account}->{id} );
1296
	       $hold_mode, $server->{account}->{id});
1281
        $status = $ils->Transaction::Hold;    # new?
1297
	$status = $ils->Transaction::Hold;		# new?
1282
        $status->screen_msg("System error. Please contact library staff.");
1298
	$status->screen_msg("System error. Please contact library staff.");
1299
    }
1283
    }
1300
1284
1301
    $resp .= $status->ok;
1285
    $resp .= $status->ok;
1302
    $resp .= sipbool($status->item  &&  $status->item->available($patron_id));
1286
    $resp .= sipbool( $status->item && $status->item->available($patron_id) );
1303
    $resp .= timestamp;
1287
    $resp .= timestamp;
1304
1288
1305
    if ($status->ok) {
1289
    if ( $status->ok ) {
1306
	$resp .= add_field(FID_PATRON_ID,   $status->patron->id);
1290
        $resp .= add_field( FID_PATRON_ID, $status->patron->id );
1307
1291
1308
	($status->expiration_date) and
1292
        ( $status->expiration_date )
1309
	$resp .= maybe_add(FID_EXPIRATION,
1293
          and $resp .= maybe_add( FID_EXPIRATION, timestamp( $status->expiration_date ) );
1310
			             timestamp($status->expiration_date));
1294
        $resp .= maybe_add( FID_QUEUE_POS,   $status->queue_position );
1311
	$resp .= maybe_add(FID_QUEUE_POS,   $status->queue_position);
1295
        $resp .= maybe_add( FID_PICKUP_LOCN, $status->pickup_location );
1312
	$resp .= maybe_add(FID_PICKUP_LOCN, $status->pickup_location);
1296
        $resp .= maybe_add( FID_ITEM_ID,     $status->item->id );
1313
	$resp .= maybe_add(FID_ITEM_ID,     $status->item->id);
1297
        $resp .= maybe_add( FID_TITLE_ID,    $status->item->title_id );
1314
	$resp .= maybe_add(FID_TITLE_ID,    $status->item->title_id);
1315
    } else {
1298
    } else {
1316
	# Not ok.  still need required fields
1299
1317
	$resp .= add_field(FID_PATRON_ID,   $patron_id);
1300
        # Not ok.  still need required fields
1301
        $resp .= add_field( FID_PATRON_ID, $patron_id );
1318
    }
1302
    }
1319
1303
1320
    $resp .= add_field(FID_INST_ID,     $ils->institution);
1304
    $resp .= add_field( FID_INST_ID, $ils->institution );
1321
    $resp .= maybe_add(FID_SCREEN_MSG,  $status->screen_msg, $server);
1305
    $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
1322
    $resp .= maybe_add(FID_PRINT_LINE,  $status->print_line);
1306
    $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
1323
1307
1324
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1308
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1325
1309
1326
    return(HOLD);
1310
    return (HOLD);
1327
}
1311
}
1328
1312
1329
sub handle_renew {
1313
sub handle_renew {
1330
    my ($self, $server) = @_;
1314
    my ( $self, $server ) = @_;
1331
    my $ils = $server->{ils};
1315
    my $ils = $server->{ils};
1332
    my ($third_party, $no_block, $trans_date, $nb_due_date);
1316
    my ( $third_party, $no_block, $trans_date, $nb_due_date );
1333
    my ($patron_id, $patron_pwd, $item_id, $title_id, $item_props, $fee_ack);
1317
    my ( $patron_id, $patron_pwd, $item_id, $title_id, $item_props, $fee_ack );
1334
    my $fields = $self->{fields};
1318
    my $fields = $self->{fields};
1335
    my $status;
1319
    my $status;
1336
    my ($patron, $item);
1320
    my ( $patron, $item );
1337
    my $resp = RENEW_RESP;
1321
    my $resp = RENEW_RESP;
1338
1322
1339
    ($third_party, $no_block, $trans_date, $nb_due_date) =
1323
    ( $third_party, $no_block, $trans_date, $nb_due_date ) = @{ $self->{fixed_fields} };
1340
	@{$self->{fixed_fields}};
1341
1324
1342
    $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_renew");
1325
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, "handle_renew" );
1343
1326
1344
    if ($no_block eq 'Y') {
1327
    if ( $no_block eq 'Y' ) {
1345
	syslog("LOG_WARNING",
1328
        syslog( "LOG_WARNING", "handle_renew: received 'no block' renewal from terminal '%s'", $server->{account}->{id} );
1346
            "handle_renew: received 'no block' renewal from terminal '%s'",
1347
	       $server->{account}->{id});
1348
    }
1329
    }
1349
1330
1350
    $patron_id  = $fields->{(FID_PATRON_ID)};
1331
    $patron_id  = $fields->{ (FID_PATRON_ID) };
1351
    $patron_pwd = $fields->{(FID_PATRON_PWD)};
1332
    $patron_pwd = $fields->{ (FID_PATRON_PWD) };
1352
    $item_id    = $fields->{(FID_ITEM_ID)};
1333
    $item_id    = $fields->{ (FID_ITEM_ID) };
1353
    $title_id   = $fields->{(FID_TITLE_ID)};
1334
    $title_id   = $fields->{ (FID_TITLE_ID) };
1354
    $item_props = $fields->{(FID_ITEM_PROPS)};
1335
    $item_props = $fields->{ (FID_ITEM_PROPS) };
1355
    $fee_ack    = $fields->{(FID_FEE_ACK)};
1336
    $fee_ack    = $fields->{ (FID_FEE_ACK) };
1356
1337
1357
    $status = $ils->renew($patron_id, $patron_pwd, $item_id, $title_id,
1338
    $status = $ils->renew( $patron_id, $patron_pwd, $item_id, $title_id, $no_block, $nb_due_date, $third_party, $item_props, $fee_ack );
1358
			  $no_block, $nb_due_date, $third_party,
1359
			  $item_props, $fee_ack);
1360
1339
1361
    $patron = $status->patron;
1340
    $patron = $status->patron;
1362
    $item   = $status->item;
1341
    $item   = $status->item;
1363
1342
1364
    if ($status->renewal_ok) {
1343
    if ( $status->renewal_ok ) {
1365
	$resp .= '1';
1344
        $resp .= '1';
1366
	$resp .= $status->renewal_ok ? 'Y' : 'N';
1345
        $resp .= $status->renewal_ok ? 'Y' : 'N';
1367
	if ($ils->supports('magnetic media')) {
1346
        if ( $ils->supports('magnetic media') ) {
1368
	    $resp .= sipbool($item->magnetic_media);
1347
            $resp .= sipbool( $item->magnetic_media );
1369
	} else {
1348
        } else {
1370
	    $resp .= 'U';
1349
            $resp .= 'U';
1371
	}
1350
        }
1372
	$resp .= sipbool($status->desensitize);
1351
        $resp .= sipbool( $status->desensitize );
1373
	$resp .= timestamp;
1352
        $resp .= timestamp;
1374
	$resp .= add_field(FID_PATRON_ID, $patron->id);
1353
        $resp .= add_field( FID_PATRON_ID, $patron->id );
1375
	$resp .= add_field(FID_ITEM_ID,  $item->id);
1354
        $resp .= add_field( FID_ITEM_ID, $item->id );
1376
	$resp .= add_field(FID_TITLE_ID, $item->title_id);
1355
        $resp .= add_field( FID_TITLE_ID, $item->title_id );
1377
    if ($item->due_date) {
1356
        if ( $item->due_date ) {
1378
        $resp .= add_field(FID_DUE_DATE, timestamp($item->due_date));
1357
            $resp .= add_field( FID_DUE_DATE, timestamp( $item->due_date ) );
1379
    } else {
1358
        } else {
1380
        $resp .= add_field(FID_DUE_DATE, q{});
1359
            $resp .= add_field( FID_DUE_DATE, q{} );
1381
    }
1360
        }
1382
	if ($ils->supports('security inhibit')) {
1361
        if ( $ils->supports('security inhibit') ) {
1383
	    $resp .= add_field(FID_SECURITY_INHIBIT,
1362
            $resp .= add_field( FID_SECURITY_INHIBIT, $status->security_inhibit );
1384
			       $status->security_inhibit);
1363
        }
1385
	}
1364
        $resp .= add_field( FID_MEDIA_TYPE, $item->sip_media_type );
1386
	$resp .= add_field(FID_MEDIA_TYPE, $item->sip_media_type);
1365
        $resp .= maybe_add( FID_ITEM_PROPS, $item->sip_item_properties );
1387
	$resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
1388
    } else {
1366
    } else {
1389
	# renew failed for some reason
1367
1390
	# not OK, renewal not OK, Unknown media type (why bother checking?)
1368
        # renew failed for some reason
1391
	$resp .= '0NUN';
1369
        # not OK, renewal not OK, Unknown media type (why bother checking?)
1392
	$resp .= timestamp;
1370
        $resp .= '0NUN';
1393
	# If we found the patron or the item, the return the ILS
1371
        $resp .= timestamp;
1394
    # information, otherwise echo back the information we received
1372
1395
	# from the terminal
1373
        # If we found the patron or the item, the return the ILS
1396
	$resp .= add_field(FID_PATRON_ID, $patron ? $patron->id     : $patron_id);
1374
        # information, otherwise echo back the information we received
1397
	$resp .= add_field(FID_ITEM_ID,     $item ? $item->id       : $item_id  );
1375
        # from the terminal
1398
	$resp .= add_field(FID_TITLE_ID,    $item ? $item->title_id : $title_id );
1376
        $resp .= add_field( FID_PATRON_ID, $patron ? $patron->id     : $patron_id );
1399
	$resp .= add_field(FID_DUE_DATE, '');
1377
        $resp .= add_field( FID_ITEM_ID,   $item   ? $item->id       : $item_id );
1378
        $resp .= add_field( FID_TITLE_ID,  $item   ? $item->title_id : $title_id );
1379
        $resp .= add_field( FID_DUE_DATE,  '' );
1400
    }
1380
    }
1401
1381
1402
    if ($status->fee_amount) {
1382
    if ( $status->fee_amount ) {
1403
	$resp .= add_field(FID_FEE_AMT,  $status->fee_amount);
1383
        $resp .= add_field( FID_FEE_AMT, $status->fee_amount );
1404
	$resp .= maybe_add(FID_CURRENCY, $status->sip_currency);
1384
        $resp .= maybe_add( FID_CURRENCY,       $status->sip_currency );
1405
	$resp .= maybe_add(FID_FEE_TYPE, $status->sip_fee_type);
1385
        $resp .= maybe_add( FID_FEE_TYPE,       $status->sip_fee_type );
1406
	$resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id);
1386
        $resp .= maybe_add( FID_TRANSACTION_ID, $status->transaction_id );
1407
    }
1387
    }
1408
1388
1409
    $resp .= add_field(FID_INST_ID, $ils->institution);
1389
    $resp .= add_field( FID_INST_ID, $ils->institution );
1410
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
1390
    $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
1411
    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
1391
    $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
1412
1392
1413
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1393
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1414
1394
1415
    return(RENEW);
1395
    return (RENEW);
1416
}
1396
}
1417
1397
1418
sub handle_renew_all {
1398
sub handle_renew_all {
1399
1419
    # my ($third_party, $no_block, $nb_due_date, $fee_ack, $patron);
1400
    # my ($third_party, $no_block, $nb_due_date, $fee_ack, $patron);
1420
1401
1421
    my ($self, $server) = @_;
1402
    my ( $self, $server ) = @_;
1422
    my $ils = $server->{ils};
1403
    my $ils = $server->{ils};
1423
    my ($trans_date, $patron_id, $patron_pwd, $terminal_pwd, $fee_ack);
1404
    my ( $trans_date, $patron_id, $patron_pwd, $terminal_pwd, $fee_ack );
1424
    my $fields = $self->{fields};
1405
    my $fields = $self->{fields};
1425
    my $resp = RENEW_ALL_RESP;
1406
    my $resp   = RENEW_ALL_RESP;
1426
    my $status;
1407
    my $status;
1427
    my (@renewed, @unrenewed);
1408
    my ( @renewed, @unrenewed );
1428
1409
1429
    $ils->check_inst_id($fields->{(FID_INST_ID)}, "handle_renew_all");
1410
    $ils->check_inst_id( $fields->{ (FID_INST_ID) }, "handle_renew_all" );
1430
1411
1431
    ($trans_date) = @{$self->{fixed_fields}};
1412
    ($trans_date) = @{ $self->{fixed_fields} };
1432
1413
1433
    $patron_id    = $fields->{(FID_PATRON_ID)};
1414
    $patron_id    = $fields->{ (FID_PATRON_ID) };
1434
    $patron_pwd   = $fields->{(FID_PATRON_PWD)};
1415
    $patron_pwd   = $fields->{ (FID_PATRON_PWD) };
1435
    $terminal_pwd = $fields->{(FID_TERMINAL_PWD)};
1416
    $terminal_pwd = $fields->{ (FID_TERMINAL_PWD) };
1436
    $fee_ack      = $fields->{(FID_FEE_ACK)};
1417
    $fee_ack      = $fields->{ (FID_FEE_ACK) };
1437
1418
1438
    $status = $ils->renew_all($patron_id, $patron_pwd, $fee_ack);
1419
    $status = $ils->renew_all( $patron_id, $patron_pwd, $fee_ack );
1439
1420
1440
    $resp .= $status->ok ? '1' : '0';
1421
    $resp .= $status->ok ? '1' : '0';
1441
1422
1442
	if (!$status->ok) {
1423
    if ( !$status->ok ) {
1443
		$resp .= add_count("renew_all/renewed_count"  , 0);
1424
        $resp .= add_count( "renew_all/renewed_count",   0 );
1444
		$resp .= add_count("renew_all/unrenewed_count", 0);
1425
        $resp .= add_count( "renew_all/unrenewed_count", 0 );
1445
		@renewed = ();
1426
        @renewed   = ();
1446
		@unrenewed = ();
1427
        @unrenewed = ();
1447
	} else {
1428
    } else {
1448
		@renewed   = (@{$status->renewed});
1429
        @renewed   = ( @{ $status->renewed } );
1449
		@unrenewed = (@{$status->unrenewed});
1430
        @unrenewed = ( @{ $status->unrenewed } );
1450
		$resp .= add_count("renew_all/renewed_count"  , scalar @renewed  );
1431
        $resp .= add_count( "renew_all/renewed_count",   scalar @renewed );
1451
		$resp .= add_count("renew_all/unrenewed_count", scalar @unrenewed);
1432
        $resp .= add_count( "renew_all/unrenewed_count", scalar @unrenewed );
1452
	}
1433
    }
1453
1434
1454
    $resp .= timestamp;
1435
    $resp .= timestamp;
1455
    $resp .= add_field(FID_INST_ID, $ils->institution);
1436
    $resp .= add_field( FID_INST_ID, $ils->institution );
1456
1437
1457
    $resp .= join('', map(add_field(FID_RENEWED_ITEMS  , $_), @renewed  ));
1438
    $resp .= join( '', map( add_field( FID_RENEWED_ITEMS,   $_ ), @renewed ) );
1458
    $resp .= join('', map(add_field(FID_UNRENEWED_ITEMS, $_), @unrenewed));
1439
    $resp .= join( '', map( add_field( FID_UNRENEWED_ITEMS, $_ ), @unrenewed ) );
1459
1440
1460
    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server);
1441
    $resp .= maybe_add( FID_SCREEN_MSG, $status->screen_msg, $server );
1461
    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
1442
    $resp .= maybe_add( FID_PRINT_LINE, $status->print_line );
1462
1443
1463
    $self->write_msg($resp,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1444
    $self->write_msg( $resp, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1464
1445
1465
    return(RENEW_ALL);
1446
    return (RENEW_ALL);
1466
}
1447
}
1467
1448
1468
#
1449
#
Lines 1473-1576 sub handle_renew_all { Link Here
1473
#
1454
#
1474
1455
1475
my @message_type_names = (
1456
my @message_type_names = (
1476
			  "patron status request",
1457
    "patron status request",
1477
			  "checkout",
1458
    "checkout",
1478
			  "checkin",
1459
    "checkin",
1479
			  "block patron",
1460
    "block patron",
1480
			  "acs status",
1461
    "acs status",
1481
			  "request sc/acs resend",
1462
    "request sc/acs resend",
1482
			  "login",
1463
    "login",
1483
			  "patron information",
1464
    "patron information",
1484
			  "end patron session",
1465
    "end patron session",
1485
			  "fee paid",
1466
    "fee paid",
1486
			  "item information",
1467
    "item information",
1487
			  "item status update",
1468
    "item status update",
1488
			  "patron enable",
1469
    "patron enable",
1489
			  "hold",
1470
    "hold",
1490
			  "renew",
1471
    "renew",
1491
			  "renew all",
1472
    "renew all",
1492
			 );
1473
);
1493
1474
1494
sub send_acs_status {
1475
sub send_acs_status {
1495
    my ($self, $server, $screen_msg, $print_line) = @_;
1476
    my ( $self, $server, $screen_msg, $print_line ) = @_;
1496
    my $msg = ACS_STATUS;
1477
    my $msg = ACS_STATUS;
1497
	($server) or die "send_acs_status error: no \$server argument received";
1478
    ($server) or die "send_acs_status error: no \$server argument received";
1498
    my $account = $server->{account} or die "send_acs_status error: no 'account' in \$server object:\n" . Dumper($server);
1479
    my $account = $server->{account} or die "send_acs_status error: no 'account' in \$server object:\n" . Dumper($server);
1499
    my $policy  = $server->{policy}  or die "send_acs_status error: no 'policy' in \$server object:\n" . Dumper($server);
1480
    my $policy  = $server->{policy}  or die "send_acs_status error: no 'policy' in \$server object:\n" . Dumper($server);
1500
    my $ils     = $server->{ils}     or die "send_acs_status error: no 'ils' in \$server object:\n" . Dumper($server);
1481
    my $ils     = $server->{ils}     or die "send_acs_status error: no 'ils' in \$server object:\n" . Dumper($server);
1501
    my ($online_status, $checkin_ok, $checkout_ok, $ACS_renewal_policy);
1482
    my ( $online_status,    $checkin_ok, $checkout_ok, $ACS_renewal_policy );
1502
    my ($status_update_ok, $offline_ok, $timeout, $retries);
1483
    my ( $status_update_ok, $offline_ok, $timeout,     $retries );
1503
1484
1504
    $online_status = 'Y';
1485
    $online_status      = 'Y';
1505
    $checkout_ok = sipbool($ils->checkout_ok);
1486
    $checkout_ok        = sipbool( $ils->checkout_ok );
1506
    $checkin_ok  = sipbool($ils->checkin_ok);
1487
    $checkin_ok         = sipbool( $ils->checkin_ok );
1507
    $ACS_renewal_policy = sipbool($policy->{renewal});
1488
    $ACS_renewal_policy = sipbool( $policy->{renewal} );
1508
    $status_update_ok   = sipbool($ils->status_update_ok);
1489
    $status_update_ok   = sipbool( $ils->status_update_ok );
1509
    $offline_ok = sipbool($ils->offline_ok);
1490
    $offline_ok         = sipbool( $ils->offline_ok );
1510
    $timeout = sprintf("%03d", $policy->{timeout});
1491
    $timeout            = sprintf( "%03d", $policy->{timeout} );
1511
    $retries = sprintf("%03d", $policy->{retries});
1492
    $retries            = sprintf( "%03d", $policy->{retries} );
1512
1493
1513
    if (length($timeout) != 3) {
1494
    if ( length($timeout) != 3 ) {
1514
	syslog("LOG_ERR", "handle_acs_status: timeout field wrong size: '%s'",
1495
        syslog( "LOG_ERR", "handle_acs_status: timeout field wrong size: '%s'", $timeout );
1515
	       $timeout);
1496
        $timeout = '000';
1516
	$timeout = '000';
1517
    }
1497
    }
1518
1498
1519
    if (length($retries) != 3) {
1499
    if ( length($retries) != 3 ) {
1520
	syslog("LOG_ERR", "handle_acs_status: retries field wrong size: '%s'",
1500
        syslog( "LOG_ERR", "handle_acs_status: retries field wrong size: '%s'", $retries );
1521
	       $retries);
1501
        $retries = '000';
1522
	$retries = '000';
1523
    }
1502
    }
1524
1503
1525
    $msg .= "$online_status$checkin_ok$checkout_ok$ACS_renewal_policy";
1504
    $msg .= "$online_status$checkin_ok$checkout_ok$ACS_renewal_policy";
1526
    $msg .= "$status_update_ok$offline_ok$timeout$retries";
1505
    $msg .= "$status_update_ok$offline_ok$timeout$retries";
1527
    $msg .= timestamp();
1506
    $msg .= timestamp();
1528
1507
1529
    if ($protocol_version == 1) {
1508
    if ( $protocol_version == 1 ) {
1530
	$msg .= '1.00';
1509
        $msg .= '1.00';
1531
    } elsif ($protocol_version == 2) {
1510
    } elsif ( $protocol_version == 2 ) {
1532
	$msg .= '2.00';
1511
        $msg .= '2.00';
1533
    } else {
1512
    } else {
1534
	syslog("LOG_ERR",
1513
        syslog( "LOG_ERR", 'Bad setting for $protocol_version, "%s" in send_acs_status', $protocol_version );
1535
	       'Bad setting for $protocol_version, "%s" in send_acs_status',
1514
        $msg .= '1.00';
1536
	       $protocol_version);
1537
	$msg .= '1.00';
1538
    }
1515
    }
1539
1516
1540
    # Institution ID
1517
    # Institution ID
1541
    $msg .= add_field(FID_INST_ID, $account->{institution});
1518
    $msg .= add_field( FID_INST_ID, $account->{institution} );
1542
1519
1543
    if ($protocol_version >= 2) {
1520
    if ( $protocol_version >= 2 ) {
1544
	# Supported messages: we do it all
1521
1545
	my $supported_msgs = '';
1522
        # Supported messages: we do it all
1546
1523
        my $supported_msgs = '';
1547
	foreach my $msg_name (@message_type_names) {
1524
1548
	    if ($msg_name eq 'request sc/acs resend') {
1525
        foreach my $msg_name (@message_type_names) {
1549
		$supported_msgs .= sipbool(1);
1526
            if ( $msg_name eq 'request sc/acs resend' ) {
1550
	    } else {
1527
                $supported_msgs .= sipbool(1);
1551
		$supported_msgs .= sipbool($ils->supports($msg_name));
1528
            } else {
1552
	    }
1529
                $supported_msgs .= sipbool( $ils->supports($msg_name) );
1553
	}
1530
            }
1554
	if (length($supported_msgs) < 16) {
1531
        }
1555
	    syslog("LOG_ERR", 'send_acs_status: supported messages "%s" too short', $supported_msgs);
1532
        if ( length($supported_msgs) < 16 ) {
1556
	}
1533
            syslog( "LOG_ERR", 'send_acs_status: supported messages "%s" too short', $supported_msgs );
1557
	$msg .= add_field(FID_SUPPORTED_MSGS, $supported_msgs);
1534
        }
1535
        $msg .= add_field( FID_SUPPORTED_MSGS, $supported_msgs );
1558
    }
1536
    }
1559
1537
1560
    $msg .= maybe_add(FID_SCREEN_MSG, $screen_msg, $server);
1538
    $msg .= maybe_add( FID_SCREEN_MSG, $screen_msg, $server );
1561
1539
1562
    if (defined($account->{print_width}) && defined($print_line)
1540
    if (   defined( $account->{print_width} )
1563
	&& $account->{print_width} < length($print_line)) {
1541
        && defined($print_line)
1564
	syslog("LOG_WARNING", "send_acs_status: print line '%s' too long.  Truncating",
1542
        && $account->{print_width} < length($print_line) ) {
1565
	       $print_line);
1543
        syslog( "LOG_WARNING", "send_acs_status: print line '%s' too long.  Truncating", $print_line );
1566
	$print_line = substr($print_line, 0, $account->{print_width});
1544
        $print_line = substr( $print_line, 0, $account->{print_width} );
1567
    }
1545
    }
1568
1546
1569
    $msg .= maybe_add(FID_PRINT_LINE, $print_line);
1547
    $msg .= maybe_add( FID_PRINT_LINE, $print_line );
1570
1548
1571
    # Do we want to tell the terminal its location?
1549
    # Do we want to tell the terminal its location?
1572
1550
1573
    $self->write_msg($msg,undef,$server->{account}->{terminator},$server->{account}->{encoding});
1551
    $self->write_msg( $msg, undef, $server->{account}->{terminator}, $server->{account}->{encoding} );
1574
    return 1;
1552
    return 1;
1575
}
1553
}
1576
1554
Lines 1582-1618 sub patron_status_string { Link Here
1582
    my $patron = shift;
1560
    my $patron = shift;
1583
    my $patron_status;
1561
    my $patron_status;
1584
1562
1585
    syslog("LOG_DEBUG", "patron_status_string: %s charge_ok: %s", $patron->id, $patron->charge_ok);
1563
    syslog( "LOG_DEBUG", "patron_status_string: %s charge_ok: %s", $patron->id, $patron->charge_ok );
1586
    $patron_status = sprintf(
1564
    $patron_status = sprintf(
1587
        '%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
1565
        '%s%s%s%s%s%s%s%s%s%s%s%s%s%s',
1588
        denied($patron->charge_ok),
1566
        denied( $patron->charge_ok ),
1589
        denied($patron->renew_ok),
1567
        denied( $patron->renew_ok ),
1590
        denied($patron->recall_ok),
1568
        denied( $patron->recall_ok ),
1591
        denied($patron->hold_ok),
1569
        denied( $patron->hold_ok ),
1592
        boolspace($patron->card_lost),
1570
        boolspace( $patron->card_lost ),
1593
        boolspace($patron->too_many_charged),
1571
        boolspace( $patron->too_many_charged ),
1594
        boolspace($patron->too_many_overdue),
1572
        boolspace( $patron->too_many_overdue ),
1595
        boolspace($patron->too_many_renewal),
1573
        boolspace( $patron->too_many_renewal ),
1596
        boolspace($patron->too_many_claim_return),
1574
        boolspace( $patron->too_many_claim_return ),
1597
        boolspace($patron->too_many_lost),
1575
        boolspace( $patron->too_many_lost ),
1598
        boolspace($patron->excessive_fines),
1576
        boolspace( $patron->excessive_fines ),
1599
        boolspace($patron->excessive_fees),
1577
        boolspace( $patron->excessive_fees ),
1600
        boolspace($patron->recall_overdue),
1578
        boolspace( $patron->recall_overdue ),
1601
        boolspace($patron->too_many_billed)
1579
        boolspace( $patron->too_many_billed )
1602
    );
1580
    );
1603
    return $patron_status;
1581
    return $patron_status;
1604
}
1582
}
1605
1583
1606
sub api_auth {
1584
sub api_auth {
1607
    my ($username,$password, $branch) = @_;
1585
    my ( $username, $password, $branch ) = @_;
1608
    $ENV{REMOTE_USER} = $username;
1586
    $ENV{REMOTE_USER} = $username;
1609
    my $query = CGI->new();
1587
    my $query = CGI->new();
1610
    $query->param(userid   => $username);
1588
    $query->param( userid   => $username );
1611
    $query->param(password => $password);
1589
    $query->param( password => $password );
1612
    if ($branch) {
1590
    if ($branch) {
1613
        $query->param(branch => $branch);
1591
        $query->param( branch => $branch );
1614
    }
1592
    }
1615
    my ($status, $cookie, $sessionID) = check_api_auth($query, {circulate=>1}, 'intranet');
1593
    my ( $status, $cookie, $sessionID ) = check_api_auth( $query, { circulate => 1 }, 'intranet' );
1616
    return $status;
1594
    return $status;
1617
}
1595
}
1618
1596
1619
- 

Return to bug 13871