SIP filters: toward SIP filters
authorJason Etheridge <jason@EquinoxOLI.org>
Mon, 4 Jul 2022 22:11:48 +0000 (18:11 -0400)
committerJason Etheridge <jason@EquinoxOLI.org>
Tue, 5 Jul 2022 03:21:31 +0000 (23:21 -0400)
Signed-off-by: Jason Etheridge <jason@EquinoxOLI.org>
Sip.pm
Sip/MsgType.pm

diff --git a/Sip.pm b/Sip.pm
index cf9e575..a1c3be5 100644 (file)
--- a/Sip.pm
+++ b/Sip.pm
@@ -69,11 +69,11 @@ sub timestamp {
 }
 
 #
-# add_field(field_id, value)
+# add_field(field_id, value, filters)
 #    return constructed field value
 #
 sub add_field {
-    my ($field_id, $value) = @_;
+    my ($field_id, $value, $filters) = @_;
     my ($i, $ent);
 
     if (!defined($value)) {
@@ -97,17 +97,44 @@ sub add_field {
         $value = substr($value, 0, 255);
     }
 
+    # on the fly field munging...
+    if (defined $filters) {
+        # filters v1 = $VAR1 = { 'field' => { 'identifier' => 'AE',  'replace_with' => 'John Doe' } };
+        # filters v1 = $VAR1 = { 'field' => { 'identifier' => 'AE',  'remove' => 'true' } };
+        # filters v1 = $VAR1 = { 'field' => [ { 'identifier' => 'AE', 'replace_with' => 'John Doe' }, { 'replace_with' => 'Jane Doe', 'identifier' => 'AE' } ] };
+        my $field_configs = $filters->{field};
+        $field_configs = [$field_configs] unless ref $field_configs eq 'ARRAY';
+        my @relevant_field_configs = grep { $_->{identifier} eq $field_id } @$field_configs;
+        if (@relevant_field_configs) {
+
+            # for now, since we can't do anything complicated, let's just take the first matching field configuration
+            my $field_config = $relevant_field_configs[0];
+
+            # custom field value
+            if (defined $field_config->{replace_with}) {
+                $value = $field_config->{replace_with};
+            }
+
+            # whole field stripping (id and value)
+            my $remove = $field_config->{remove};
+            if (defined($remove) && (($remove =~ /true|y|yes/i) || $remove != 0)) { # test truthiness
+                return '';
+            }
+
+        }
+    }
+
     return $field_id . $value . $field_delimiter;
 }
 #
-# maybe_add(field_id, value):
+# maybe_add(field_id, value, filters):
 #    If value is defined and non-empty, then return the
 #    constructed field value, otherwise return the empty string.
 #    NOTE: if zero is a valid value for your field, don't use maybe_add!
 #
 sub maybe_add {
-    my ($fid, $value) = @_;
-    return (defined($value) && $value) ? add_field($fid, $value) : '';
+    my ($fid, $value, $filters) = @_;
+    return (defined($value) && $value) ? add_field($fid, $value, $filters) : '';
 }
 
 #
index c3cd3e0..bdf3f0c 100644 (file)
@@ -433,6 +433,7 @@ sub handle {
     return($self->{handler}->($self, $server));
 }
 
+#
 ##
 ## Message Handlers
 ##
@@ -461,40 +462,40 @@ sub build_patron_status {
 
        # while the patron ID we got from the SC is valid, let's
        # use the one returned from the ILS, just in case...
-       $resp .= add_field(FID_INST_ID, $fields->{(FID_INST_ID)});
-       $resp .= add_field(FID_PATRON_ID, $patron->id);
-       $resp .= add_field(FID_PERSONAL_NAME, $patron->name);
+       $resp .= add_field(FID_INST_ID, $fields->{(FID_INST_ID)}, $server->{filters});
+       $resp .= add_field(FID_PATRON_ID, $patron->id, $server->{filters});
+       $resp .= add_field(FID_PERSONAL_NAME, $patron->name, $server->{filters});
        if ($protocol_version >= 2) {
-           $resp .= add_field(FID_VALID_PATRON, 'Y');
+           $resp .= add_field(FID_VALID_PATRON, 'Y', $server->{filters});
            # Patron password is a required field.
-               $resp .= add_field(FID_VALID_PATRON_PWD, sipbool($patron->check_password($patron_pwd)));
-           $resp .= maybe_add(FID_CURRENCY, $patron->currency);
-           $resp .= maybe_add(FID_FEE_AMT, $patron->fee_amount);
+               $resp .= add_field(FID_VALID_PATRON_PWD, sipbool($patron->check_password($patron_pwd)), $server->{filters});
+           $resp .= maybe_add(FID_CURRENCY, $patron->currency, $server->{filters});
+           $resp .= maybe_add(FID_FEE_AMT, $patron->fee_amount, $server->{filters});
 
                # Relais extensions
                if ($server->{institution}->relais_extensions_to_msg24()) {
-                       $resp .= maybe_add(FID_HOME_ADDR,  $patron->address   );
-                       $resp .= maybe_add(FID_EMAIL,      $patron->email_addr);
-                       $resp .= maybe_add(FID_HOME_PHONE, $patron->home_phone);
+                       $resp .= maybe_add(FID_HOME_ADDR,  $patron->address   , $server->{filters});
+                       $resp .= maybe_add(FID_EMAIL,      $patron->email_addr, $server->{filters});
+                       $resp .= maybe_add(FID_HOME_PHONE, $patron->home_phone, $server->{filters});
                }
 
        }
 
-       $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg);
-       $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line);
+       $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg, $server->{filters});
+       $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line, $server->{filters});
     } else {
        # Invalid patron id.  Report that the user has no privs.,
        # no personal name, and is invalid (if we're using 2.00)
        $resp .= 'YYYY' . (' ' x 10) . $lang . Sip::timestamp();
-       $resp .= add_field(FID_INST_ID, $fields->{(FID_INST_ID)});
+       $resp .= add_field(FID_INST_ID, $fields->{(FID_INST_ID)}, $server->{filters});
 
        # the patron ID is invalid, but it's a required field, so
        # just echo it back
-       $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)});
-       $resp .= add_field(FID_PERSONAL_NAME, '');
+       $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)}, $server->{filters});
+       $resp .= add_field(FID_PERSONAL_NAME, '', $server->{filters});
 
        if ($protocol_version >= 2) {
-           $resp .= add_field(FID_VALID_PATRON, 'N');
+           $resp .= add_field(FID_VALID_PATRON, 'N', $server->{filters});
        }
     }
 
@@ -578,29 +579,29 @@ sub handle_checkout {
        $resp .= Sip::timestamp;
 
        # Now for the variable fields
-       $resp .= add_field(FID_INST_ID,  $inst);
-       $resp .= add_field(FID_PATRON_ID, $patron_id);
-       $resp .= add_field(FID_ITEM_ID,  $item_id);
-       $resp .= add_field(FID_TITLE_ID, $item->title_id);
-       $resp .= add_field(FID_DUE_DATE, $item->due_date);
+       $resp .= add_field(FID_INST_ID,  $inst, $server->{filters});
+       $resp .= add_field(FID_PATRON_ID, $patron_id, $server->{filters});
+       $resp .= add_field(FID_ITEM_ID,  $item_id, $server->{filters});
+       $resp .= add_field(FID_TITLE_ID, $item->title_id, $server->{filters});
+       $resp .= add_field(FID_DUE_DATE, $item->due_date, $server->{filters});
 
-       $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-       $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+       $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+       $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
        if ($protocol_version >= 2) {
            if ($ils->supports('security inhibit')) {
-               $resp .= add_field(FID_SECURITY_INHIBIT, $status->security_inhibit);
+               $resp .= add_field(FID_SECURITY_INHIBIT, $status->security_inhibit, $server->{filters});
            }
-           $resp .= maybe_add(FID_MEDIA_TYPE, $item->sip_media_type);
-           $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
+           $resp .= maybe_add(FID_MEDIA_TYPE, $item->sip_media_type, $server->{filters});
+           $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties, $server->{filters});
 
            # Financials
            if ($status->fee_amount) {
-               $resp .= add_field(FID_FEE_AMT,  $status->fee_amount);
-               $resp .= maybe_add(FID_CURRENCY, $status->sip_currency);
-               $resp .= maybe_add(FID_FEE_TYPE, $status->sip_fee_type);
+               $resp .= add_field(FID_FEE_AMT,  $status->fee_amount, $server->{filters});
+               $resp .= maybe_add(FID_CURRENCY, $status->sip_currency, $server->{filters});
+               $resp .= maybe_add(FID_FEE_TYPE, $status->sip_fee_type, $server->{filters});
                $resp .= maybe_add(FID_TRANSACTION_ID,
-                                  $status->transaction_id);
+                                  $status->transaction_id, $server->{filters});
            }
        }
 
@@ -609,35 +610,35 @@ sub handle_checkout {
        # Checkout Response: not ok, no renewal, don't know mag. media,
        # no desensitize
        $resp = sprintf("120%sUN%s", sipbool($status->renew_ok), Sip::timestamp);
-       $resp .= add_field(FID_INST_ID, $inst);
-       $resp .= add_field(FID_PATRON_ID, $patron_id);
-       $resp .= add_field(FID_ITEM_ID, $item_id);
+       $resp .= add_field(FID_INST_ID, $inst, $server->{filters});
+       $resp .= add_field(FID_PATRON_ID, $patron_id, $server->{filters});
+       $resp .= add_field(FID_ITEM_ID, $item_id, $server->{filters});
 
        # If the item is valid, provide the title, otherwise
        # leave it blank
-       $resp .= add_field(FID_TITLE_ID, $item ? $item->title_id : '');
+       $resp .= add_field(FID_TITLE_ID, $item ? $item->title_id : '', $server->{filters});
        # Due date is required.  Since it didn't get checked out,
        # it's not due, so leave the date blank
-       $resp .= add_field(FID_DUE_DATE, '');
+       $resp .= add_field(FID_DUE_DATE, '', $server->{filters});
 
-       $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-       $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+       $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+       $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
        if ($protocol_version >= 2) {
            # Is the patron ID valid?
-           $resp .= add_field(FID_VALID_PATRON, sipbool($patron));
+           $resp .= add_field(FID_VALID_PATRON, sipbool($patron), $server->{filters});
 
            if ($patron && exists($fields->{FID_PATRON_PWD})) {
                # Password provided, so we can tell if it was valid or not
                $resp .= add_field(FID_VALID_PATRON_PWD,
-                                  sipbool($patron->check_password($fields->{(FID_PATRON_PWD)})));
+                                  sipbool($patron->check_password($fields->{(FID_PATRON_PWD)})), $server->{filters});
            }
             # For the patron to accept a fee in chargeable loans, we
             # need to return fee information.
            if ($status->fee_amount) {
-               $resp .= add_field(FID_FEE_AMT,  $status->fee_amount);
-               $resp .= maybe_add(FID_CURRENCY, $status->sip_currency);
-               $resp .= maybe_add(FID_FEE_TYPE, $status->sip_fee_type);
+               $resp .= add_field(FID_FEE_AMT,  $status->fee_amount, $server->{filters});
+               $resp .= maybe_add(FID_CURRENCY, $status->sip_currency, $server->{filters});
+               $resp .= maybe_add(FID_FEE_TYPE, $status->sip_fee_type, $server->{filters});
             }
        }
     }
@@ -687,36 +688,36 @@ sub handle_checkin {
     }
     $resp .= $status->alert ? 'Y' : 'N';
     $resp .= Sip::timestamp;
-    $resp .= add_field(FID_INST_ID, $inst_id);
-    $resp .= add_field(FID_ITEM_ID, $item_id);
+    $resp .= add_field(FID_INST_ID, $inst_id, $server->{filters});
+    $resp .= add_field(FID_ITEM_ID, $item_id, $server->{filters});
 
     if ($item) {
-        $resp .= add_field(FID_PERM_LOCN, $item->permanent_location);
-        $resp .= maybe_add(FID_TITLE_ID, $item->title_id);
+        $resp .= add_field(FID_PERM_LOCN, $item->permanent_location, $server->{filters});
+        $resp .= maybe_add(FID_TITLE_ID, $item->title_id, $server->{filters});
     }
 
     if ($protocol_version >= 2) {
-        $resp .= maybe_add(FID_SORT_BIN, $status->sort_bin);
+        $resp .= maybe_add(FID_SORT_BIN, $status->sort_bin, $server->{filters});
         if ($patron) {
-            $resp .= add_field(FID_PATRON_ID, $patron->id);
+            $resp .= add_field(FID_PATRON_ID, $patron->id, $server->{filters});
         }
         if ($item) {
-            $resp .= maybe_add(FID_MEDIA_TYPE,           $item->sip_media_type     );
-            $resp .= maybe_add(FID_ITEM_PROPS,           $item->sip_item_properties);
-            $resp .= maybe_add(FID_COLLECTION_CODE,      $item->collection_code    );
-            $resp .= maybe_add(FID_CALL_NUMBER,          $item->call_number        );
-            $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc    );
-            $resp .= maybe_add(FID_HOLD_PATRON_ID,       $item->hold_patron_bcode  );
-            $resp .= maybe_add(FID_HOLD_PATRON_NAME,     $item->hold_patron_name   );
+            $resp .= maybe_add(FID_MEDIA_TYPE,           $item->sip_media_type     , $server->{filters});
+            $resp .= maybe_add(FID_ITEM_PROPS,           $item->sip_item_properties, $server->{filters});
+            $resp .= maybe_add(FID_COLLECTION_CODE,      $item->collection_code    , $server->{filters});
+            $resp .= maybe_add(FID_CALL_NUMBER,          $item->call_number        , $server->{filters});
+            $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc    , $server->{filters});
+            $resp .= maybe_add(FID_HOLD_PATRON_ID,       $item->hold_patron_bcode  , $server->{filters});
+            $resp .= maybe_add(FID_HOLD_PATRON_NAME,     $item->hold_patron_name   , $server->{filters});
             if ($server->{institution}->phone_ext_to_msg10()) {
-                $resp .= maybe_add(FID_HOME_PHONE,           $item->hold_patron_phone  );
+                $resp .= maybe_add(FID_HOME_PHONE,           $item->hold_patron_phone  , $server->{filters});
             }
         }
     }
 
-    $resp .= maybe_add(FID_ALERT_TYPE, $status->alert_type) if $status->alert;
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= maybe_add(FID_ALERT_TYPE, $status->alert_type, $server->{filters}) if $status->alert;
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -897,6 +898,8 @@ sub _load_ils_handler {
     $server->{institution} = $server->{config}->{institutions}->{$inst};
     $server->{policy}      = $server->{institution}->{policy};
     $server->{account}->{location} = $sc_loc if $sc_loc;
+    $server->{filters} = $server->{institution}->{implementation_config}->{filters} || {};
+
     # Set the encoding for responses messages.
     $server->{encoding} = $server->{account}->{encoding}
         || $server->{institution}->{encoding}
@@ -937,7 +940,7 @@ sub _load_ils_handler {
 # and we're going to believe it.
 #
 sub summary_info {
-    my ($ils, $patron, $summary, $start, $end) = @_;
+    my ($server, $ils, $patron, $summary, $start, $end) = @_;
     my $resp = '';
     my $itemlist;
     my $summary_type;
@@ -976,7 +979,7 @@ sub summary_info {
 
     syslog("LOG_DEBUG", "summary_info: list = (%s)", join(", ", @{$itemlist}));
     foreach my $i (@{$itemlist}) {
-        $resp .= add_field($fid, $i);
+        $resp .= add_field($fid, $i, $server->{filters});
     }
 
     return $resp;
@@ -1014,13 +1017,13 @@ sub handle_patron_info {
         $resp .= add_count('patron_info/recall_items',  scalar @{$patron->recall_items(undef,undef,1) });
         $resp .= add_count('patron_info/unavail_holds', scalar @{$patron->unavail_holds(undef,undef,1)});
 
-        $resp .= add_field(FID_INST_ID, $server->{ils}->institution);
+        $resp .= add_field(FID_INST_ID, $server->{ils}->institution, $server->{filters});
 
         # while the patron ID we got from the SC is valid, let's
         # use the one returned from the ILS, just in case...
-        $resp .= add_field(FID_PATRON_ID, $patron->id);
+        $resp .= add_field(FID_PATRON_ID, $patron->id, $server->{filters});
 
-        $resp .= add_field(FID_PERSONAL_NAME, $patron->name);
+        $resp .= add_field(FID_PERSONAL_NAME, $patron->name, $server->{filters});
 
         # TODO: add code for the fields
         #    hold items limit
@@ -1028,50 +1031,50 @@ sub handle_patron_info {
         # charged items limit
         #           fee limit
 
-        $resp .= maybe_add(FID_CURRENCY,   $patron->currency  );
-        $resp .= maybe_add(FID_FEE_AMT,    $patron->fee_amount);
-        $resp .= maybe_add(FID_HOME_ADDR,  $patron->address   );
-        $resp .= maybe_add(FID_EMAIL,      $patron->email_addr);
-        $resp .= maybe_add(FID_HOME_PHONE, $patron->home_phone);
+        $resp .= maybe_add(FID_CURRENCY,   $patron->currency  , $server->{filters});
+        $resp .= maybe_add(FID_FEE_AMT,    $patron->fee_amount, $server->{filters});
+        $resp .= maybe_add(FID_HOME_ADDR,  $patron->address   , $server->{filters});
+        $resp .= maybe_add(FID_EMAIL,      $patron->email_addr, $server->{filters});
+        $resp .= maybe_add(FID_HOME_PHONE, $patron->home_phone, $server->{filters});
 
         # Extension requested by PINES. Report the home system for
         # the patron in the 'AQ' field. This is normally the "permanent
         # location" field for an ITEM, but it's not used in PATRON info.
         # Apparently TLC systems do this.
-        $resp .= maybe_add(FID_HOME_LIBRARY, $patron->home_library);
+        $resp .= maybe_add(FID_HOME_LIBRARY, $patron->home_library, $server->{filters});
 
-        $resp .= summary_info($ils, $patron, $summary, $start, $end);
+        $resp .= summary_info($server, $ils, $patron, $summary, $start, $end);
 
-        $resp .= add_field(FID_VALID_PATRON, 'Y');
+        $resp .= add_field(FID_VALID_PATRON, 'Y', $server->{filters});
         if (defined($patron_pwd)) {
                # If the patron password was provided, report on if it was right.
             $resp .= add_field(FID_VALID_PATRON_PWD,
-                              sipbool($patron->check_password($patron_pwd)));
+                              sipbool($patron->check_password($patron_pwd)), $server->{filters});
         }
 
         # SIP 2.0 extensions used by Envisionware
         # Other types of terminals will ignore the fields, if
         # they don't recognize the codes
         if ($patron->can('sip_expire')) {
-            $resp .= maybe_add(FID_PATRON_EXPIRE, $patron->sip_expire);
+            $resp .= maybe_add(FID_PATRON_EXPIRE, $patron->sip_expire, $server->{filters});
         }
-        $resp .= maybe_add(FID_PATRON_BIRTHDATE, $patron->sip_birthdate);
-        $resp .= maybe_add(FID_PATRON_CLASS, $patron->ptype);
+        $resp .= maybe_add(FID_PATRON_BIRTHDATE, $patron->sip_birthdate, $server->{filters});
+        $resp .= maybe_add(FID_PATRON_CLASS, $patron->ptype, $server->{filters});
 
         # Custom protocol extension to report patron internet privileges
-        $resp .= maybe_add(FID_INET_PROFILE, $patron->inet_privileges);
+        $resp .= maybe_add(FID_INET_PROFILE, $patron->inet_privileges, $server->{filters});
 
-        $resp .= maybe_add(FID_PATRON_INTERNAL_ID, $patron->internal_id);   # another extension
+        $resp .= maybe_add(FID_PATRON_INTERNAL_ID, $patron->internal_id, $server->{filters});   # another extension
 
-        $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg);
-        $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line);
+        $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg, $server->{filters});
+        $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line, $server->{filters});
 
         # Custom ILS-defined protocol extensions
         if ($patron->can('extra_fields')) {
             my $extra_fields = $patron->extra_fields();
             foreach my $field (keys %$extra_fields) {
                 foreach my $value (@{$extra_fields->{ $field }}) {
-                    $resp .= maybe_add($field, $value);
+                    $resp .= maybe_add($field, $value, $server->{filters});
                 }
             }
         }
@@ -1082,14 +1085,14 @@ sub handle_patron_info {
         $resp .= 'YYYY' . (' ' x 10) . $lang . Sip::timestamp();
         $resp .= '0000' x 6;
 
-        $resp .= add_field(FID_INST_ID, $server->{ils}->institution);
+        $resp .= add_field(FID_INST_ID, $server->{ils}->institution, $server->{filters});
         # the patron ID is invalid, but it's a required field, so
         # just echo it back
-        $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)});
-        $resp .= add_field(FID_PERSONAL_NAME, '');
+        $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)}, $server->{filters});
+        $resp .= add_field(FID_PERSONAL_NAME, '', $server->{filters});
 
         if ($protocol_version >= 2) {
-            $resp .= add_field(FID_VALID_PATRON, 'N');
+            $resp .= add_field(FID_VALID_PATRON, 'N', $server->{filters});
         }
     }
 
@@ -1115,11 +1118,11 @@ sub handle_end_patron_session {
     $resp .= $status ? 'Y' : 'N';
     $resp .= Sip::timestamp();
 
-    $resp .= add_field(FID_INST_ID, $server->{ils}->institution);
-    $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)});
+    $resp .= add_field(FID_INST_ID, $server->{ils}->institution, $server->{filters});
+    $resp .= add_field(FID_PATRON_ID, $fields->{(FID_PATRON_ID)}, $server->{filters});
 
-    $resp .= maybe_add(FID_SCREEN_MSG, $screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $print_line);
+    $resp .= maybe_add(FID_SCREEN_MSG, $screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1149,11 +1152,11 @@ sub handle_fee_paid {
                           $pay_type, $fee_id, $trans_id, $currency);
 
     $resp .= ($status->ok ? 'Y' : 'N') . Sip::timestamp;
-    $resp .= add_field(FID_INST_ID, $inst_id);
-    $resp .= add_field(FID_PATRON_ID, $patron_id);
-    $resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id);
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= add_field(FID_INST_ID, $inst_id, $server->{filters});
+    $resp .= add_field(FID_PATRON_ID, $patron_id, $server->{filters});
+    $resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id, $server->{filters});
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1180,9 +1183,9 @@ sub handle_item_information {
         $resp .= "010101";
         $resp .= Sip::timestamp;
         # Just echo back the invalid item id
-        $resp .= add_field(FID_ITEM_ID, $fields->{(FID_ITEM_ID)});
+        $resp .= add_field(FID_ITEM_ID, $fields->{(FID_ITEM_ID)}, $server->{filters});
         # title id is required, but we don't have one
-        $resp .= add_field(FID_TITLE_ID, '');
+        $resp .= add_field(FID_TITLE_ID, '', $server->{filters});
     } else {
         # Valid Item ID, send the good stuff
         $resp .= $item->sip_circulation_status;
@@ -1190,34 +1193,34 @@ sub handle_item_information {
         $resp .= $item->sip_fee_type;
         $resp .= Sip::timestamp;
 
-        $resp .= add_field(FID_ITEM_ID,  $item->id);
-        $resp .= add_field(FID_TITLE_ID, $item->title_id);
+        $resp .= add_field(FID_ITEM_ID,  $item->id, $server->{filters});
+        $resp .= add_field(FID_TITLE_ID, $item->title_id, $server->{filters});
 
-        $resp .= maybe_add(FID_MEDIA_TYPE,   $item->sip_media_type);
-        $resp .= maybe_add(FID_PERM_LOCN,    $item->permanent_location);
-        $resp .= maybe_add(FID_CURRENT_LOCN, $item->current_location);
-        $resp .= maybe_add(FID_ITEM_PROPS,   $item->sip_item_properties);
+        $resp .= maybe_add(FID_MEDIA_TYPE,   $item->sip_media_type, $server->{filters});
+        $resp .= maybe_add(FID_PERM_LOCN,    $item->permanent_location, $server->{filters});
+        $resp .= maybe_add(FID_CURRENT_LOCN, $item->current_location, $server->{filters});
+        $resp .= maybe_add(FID_ITEM_PROPS,   $item->sip_item_properties, $server->{filters});
 
         if ($item->fee) {
-            $resp .= add_field(FID_CURRENCY, $item->fee_currency);
-            $resp .= add_field(FID_FEE_AMT,  $item->fee);
+            $resp .= add_field(FID_CURRENCY, $item->fee_currency, $server->{filters});
+            $resp .= add_field(FID_FEE_AMT,  $item->fee, $server->{filters});
         }
-        $resp .= maybe_add(FID_OWNER,            $item->owner);
-        $resp .= maybe_add(FID_HOLD_QUEUE_LEN,   scalar @{$item->hold_queue});
-        $resp .= maybe_add(FID_DUE_DATE,         $item->due_date);
-        $resp .= maybe_add(FID_RECALL_DATE,      $item->recall_date);
-        $resp .= maybe_add(FID_HOLD_PICKUP_DATE, $item->hold_pickup_date);
-        $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc);  # Extension for AMH sorting
-        $resp .= maybe_add(FID_CALL_NUMBER,      $item->call_number);          # Extension for AMH sorting
-        $resp .= maybe_add(FID_SCREEN_MSG,       $item->screen_msg);
-        $resp .= maybe_add(FID_PRINT_LINE,       $item->print_line);
+        $resp .= maybe_add(FID_OWNER,            $item->owner, $server->{filters});
+        $resp .= maybe_add(FID_HOLD_QUEUE_LEN,   scalar @{$item->hold_queue}, $server->{filters});
+        $resp .= maybe_add(FID_DUE_DATE,         $item->due_date, $server->{filters});
+        $resp .= maybe_add(FID_RECALL_DATE,      $item->recall_date, $server->{filters});
+        $resp .= maybe_add(FID_HOLD_PICKUP_DATE, $item->hold_pickup_date, $server->{filters});
+        $resp .= maybe_add(FID_DESTINATION_LOCATION, $item->destination_loc, $server->{filters});  # Extension for AMH sorting
+        $resp .= maybe_add(FID_CALL_NUMBER,      $item->call_number, $server->{filters});          # Extension for AMH sorting
+        $resp .= maybe_add(FID_SCREEN_MSG,       $item->screen_msg, $server->{filters});
+        $resp .= maybe_add(FID_PRINT_LINE,       $item->print_line, $server->{filters});
 
         # Custom ILS-defined protocol extensions
         if ($item->can('extra_fields')) {
             my $extra_fields = $item->extra_fields();
             foreach my $field (keys %$extra_fields) {
                 foreach my $value (@{$extra_fields->{ $field }}) {
-                    $resp .= maybe_add($field, $value);
+                    $resp .= maybe_add($field, $value, $server->{filters});
                 }
             }
         }
@@ -1254,7 +1257,7 @@ sub handle_item_status_update {
         # Invalid Item ID
         $resp .= '0';
         $resp .= Sip::timestamp;
-        $resp .= add_field(FID_ITEM_ID, $item_id);
+        $resp .= add_field(FID_ITEM_ID, $item_id, $server->{filters});
     } else {
         # Valid Item ID
         $status = $item->status_update($item_props);
@@ -1262,13 +1265,13 @@ sub handle_item_status_update {
         $resp .= $status->ok ? '1' : '0';
         $resp .= Sip::timestamp;
 
-        $resp .= add_field(FID_ITEM_ID,    $item->id);
-        $resp .= add_field(FID_TITLE_ID,   $item->title_id);
-        $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
+        $resp .= add_field(FID_ITEM_ID,    $item->id, $server->{filters});
+        $resp .= add_field(FID_TITLE_ID,   $item->title_id, $server->{filters});
+        $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties, $server->{filters});
     }
 
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1295,10 +1298,10 @@ sub handle_patron_enable {
     if (!defined($patron)) {
         # Invalid patron ID
         $resp .= 'YYYY' . (' ' x 10) . '000' . Sip::timestamp();
-        $resp .= add_field(FID_PATRON_ID, $patron_id);
-        $resp .= add_field(FID_PERSONAL_NAME,    '' );
-        $resp .= add_field(FID_VALID_PATRON,     'N');
-        $resp .= add_field(FID_VALID_PATRON_PWD, 'N');
+        $resp .= add_field(FID_PATRON_ID, $patron_id, $server->{filters});
+        $resp .= add_field(FID_PERSONAL_NAME,    '' , $server->{filters});
+        $resp .= add_field(FID_VALID_PATRON,     'N', $server->{filters});
+        $resp .= add_field(FID_VALID_PATRON_PWD, 'N', $server->{filters});
     } else {
         # valid patron
         if (!defined($patron_pwd) || $patron->check_password($patron_pwd)) {
@@ -1308,18 +1311,18 @@ sub handle_patron_enable {
         $resp .= patron_status_string($patron);
         $resp .= $patron->language . Sip::timestamp();
 
-        $resp .= add_field(FID_PATRON_ID,     $patron->id);
-        $resp .= add_field(FID_PERSONAL_NAME, $patron->name);
+        $resp .= add_field(FID_PATRON_ID,     $patron->id, $server->{filters});
+        $resp .= add_field(FID_PERSONAL_NAME, $patron->name, $server->{filters});
         if (defined($patron_pwd)) {
             $resp .= add_field(FID_VALID_PATRON_PWD,
-                       sipbool($patron->check_password($patron_pwd)));
+                       sipbool($patron->check_password($patron_pwd)), $server->{filters});
         }
-        $resp .= add_field(FID_VALID_PATRON, 'Y');
-        $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg);
-        $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line);
+        $resp .= add_field(FID_VALID_PATRON, 'Y', $server->{filters});
+        $resp .= maybe_add(FID_SCREEN_MSG, $patron->screen_msg, $server->{filters});
+        $resp .= maybe_add(FID_PRINT_LINE, $patron->print_line, $server->{filters});
     }
 
-    $resp .= add_field(FID_INST_ID, $ils->institution);
+    $resp .= add_field(FID_INST_ID, $ils->institution, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1374,24 +1377,24 @@ sub handle_hold {
     $resp .= Sip::timestamp;
 
     if ($status->ok) {
-       $resp .= add_field(FID_PATRON_ID, $status->patron->id);
+       $resp .= add_field(FID_PATRON_ID, $status->patron->id, $server->{filters});
 
        if ($status->expiration_date) {
            $resp .= maybe_add(FID_EXPIRATION,
-                              Sip::timestamp($status->expiration_date));
+                              Sip::timestamp($status->expiration_date), $server->{filters});
        }
-       $resp .= maybe_add(FID_QUEUE_POS,   $status->queue_position);
-       $resp .= maybe_add(FID_PICKUP_LOCN, $status->pickup_location);
-       $resp .= maybe_add(FID_ITEM_ID,     $status->item->id);
-       $resp .= maybe_add(FID_TITLE_ID,    $status->item->title_id);
+       $resp .= maybe_add(FID_QUEUE_POS,   $status->queue_position, $server->{filters});
+       $resp .= maybe_add(FID_PICKUP_LOCN, $status->pickup_location, $server->{filters});
+       $resp .= maybe_add(FID_ITEM_ID,     $status->item->id, $server->{filters});
+       $resp .= maybe_add(FID_TITLE_ID,    $status->item->title_id, $server->{filters});
     } else {
        # Not ok.  still need required fields
-       $resp .= add_field(FID_PATRON_ID, $patron_id);
+       $resp .= add_field(FID_PATRON_ID, $patron_id, $server->{filters});
     }
 
-    $resp .= add_field(FID_INST_ID, $ils->institution);
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= add_field(FID_INST_ID, $ils->institution, $server->{filters});
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1443,15 +1446,15 @@ sub handle_renew {
        }
     $resp .= sipbool($status->desensitize);
     $resp .= Sip::timestamp;
-    $resp .= add_field(FID_PATRON_ID, $patron->id);
-    $resp .= add_field(FID_ITEM_ID,   $item->id);
-    $resp .= add_field(FID_TITLE_ID,  $item->title_id);
-    $resp .= add_field(FID_DUE_DATE,  $item->due_date);
+    $resp .= add_field(FID_PATRON_ID, $patron->id, $server->{filters});
+    $resp .= add_field(FID_ITEM_ID,   $item->id, $server->{filters});
+    $resp .= add_field(FID_TITLE_ID,  $item->title_id, $server->{filters});
+    $resp .= add_field(FID_DUE_DATE,  $item->due_date, $server->{filters});
     if ($ils->supports('security inhibit')) {
-        $resp .= add_field(FID_SECURITY_INHIBIT, $status->security_inhibit);
+        $resp .= add_field(FID_SECURITY_INHIBIT, $status->security_inhibit, $server->{filters});
     }
-       $resp .= add_field(FID_MEDIA_TYPE, $item->sip_media_type);
-       $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties);
+       $resp .= add_field(FID_MEDIA_TYPE, $item->sip_media_type, $server->{filters});
+       $resp .= maybe_add(FID_ITEM_PROPS, $item->sip_item_properties, $server->{filters});
     } else {
        # renew failed for some reason
        # not OK, renewal not OK, Unknown media type (why bother checking?)
@@ -1460,22 +1463,22 @@ sub handle_renew {
        # If we found the patron or the item, the return the ILS
        # information, otherwise echo back the infomation we received
        # from the terminal
-    $resp .= add_field(FID_PATRON_ID, $patron ? $patron->id     : $patron_id);
-    $resp .= add_field(FID_ITEM_ID,   $item   ? $item->id       : $item_id  );
-    $resp .= add_field(FID_TITLE_ID,  $item   ? $item->title_id : $title_id );
+    $resp .= add_field(FID_PATRON_ID, $patron ? $patron->id     : $patron_id, $server->{filters});
+    $resp .= add_field(FID_ITEM_ID,   $item   ? $item->id       : $item_id  , $server->{filters});
+    $resp .= add_field(FID_TITLE_ID,  $item   ? $item->title_id : $title_id , $server->{filters});
     $resp .= add_field(FID_DUE_DATE, '');
     }
 
     if ($status->fee_amount) {
-        $resp .= add_field(FID_FEE_AMT,        $status->fee_amount);
-        $resp .= maybe_add(FID_CURRENCY,       $status->sip_currency);
-        $resp .= maybe_add(FID_FEE_TYPE,       $status->sip_fee_type);
-        $resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id);
+        $resp .= add_field(FID_FEE_AMT,        $status->fee_amount, $server->{filters});
+        $resp .= maybe_add(FID_CURRENCY,       $status->sip_currency, $server->{filters});
+        $resp .= maybe_add(FID_FEE_TYPE,       $status->sip_fee_type, $server->{filters});
+        $resp .= maybe_add(FID_TRANSACTION_ID, $status->transaction_id, $server->{filters});
     }
 
-    $resp .= add_field(FID_INST_ID, $ils->institution);
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= add_field(FID_INST_ID, $ils->institution, $server->{filters});
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1517,13 +1520,13 @@ sub handle_renew_all {
     }
 
     $resp .= Sip::timestamp;
-    $resp .= add_field(FID_INST_ID, $ils->institution);
+    $resp .= add_field(FID_INST_ID, $ils->institution, $server->{filters});
 
-    $resp .= join('', map(add_field(FID_RENEWED_ITEMS, $_), @renewed));
-    $resp .= join('', map(add_field(FID_UNRENEWED_ITEMS, $_), @unrenewed));
+    $resp .= join('', map(add_field(FID_RENEWED_ITEMS, $_, $server->{filters}), @renewed));
+    $resp .= join('', map(add_field(FID_UNRENEWED_ITEMS, $_, $server->{filters}), @unrenewed));
 
-    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg);
-    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line);
+    $resp .= maybe_add(FID_SCREEN_MSG, $status->screen_msg, $server->{filters});
+    $resp .= maybe_add(FID_PRINT_LINE, $status->print_line, $server->{filters});
 
     $self->write_msg($resp, undef, $server->{encoding});
 
@@ -1598,7 +1601,7 @@ sub send_acs_status {
     }
 
     # Institution ID
-    $msg .= add_field(FID_INST_ID, $account->{institution});
+    $msg .= add_field(FID_INST_ID, $account->{institution}, $server->{filters});
 
     if ($protocol_version >= 2) {
     # Supported messages: we do it all
@@ -1614,10 +1617,10 @@ sub send_acs_status {
     if (length($supported_msgs) < 16) {
         syslog("LOG_ERR", 'send_acs_status: supported messages "%s" too short', $supported_msgs);
     }
-        $msg .= add_field(FID_SUPPORTED_MSGS, $supported_msgs);
+        $msg .= add_field(FID_SUPPORTED_MSGS, $supported_msgs, $server->{filters});
     }
 
-    $msg .= maybe_add(FID_SCREEN_MSG, $screen_msg);
+    $msg .= maybe_add(FID_SCREEN_MSG, $screen_msg, $server->{filters});
 
     if (defined($account->{print_width}) && defined($print_line)
              && $account->{print_width}  <  length( $print_line)) {
@@ -1625,7 +1628,7 @@ sub send_acs_status {
         $print_line = substr($print_line, 0, $account->{print_width});
     }
 
-    $msg .= maybe_add(FID_PRINT_LINE, $print_line);
+    $msg .= maybe_add(FID_PRINT_LINE, $print_line, $server->{filters});
 
     # Do we want to tell the terminal its location?