Postmaster Filter werden nicht geprüft

Hilfe zu Znuny Problemen aller Art
Locked
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Postmaster Filter werden nicht geprüft

Post by Mugen »

Hallo liebe Mitglieder!

Meine OTRS-Version ist 5.0.9

Das Problem mit dem ich mich an euch wende ist für mich einfach nicht mehr schlüssig.
Beim Eingang von E-Mails, zum OTRS, sollen ja die Filterregeln von
- Admin -> Email Settings -> PostMaster Filter Management
- Admin -> SystemConfig -> Core::PostMaster -> PostMaster::PreFilterModule###4-CMD (auch via Kernel/Config.pm konfigurierbar)
angewendet werden.

Wenn ich das Log beobachte, wenn eine Mail ein geht, sieht das so aus*:
procmail: [16563] Mon Sep 5 11:38:01 2016
procmail: Match on ! "^From.*@example.com"
procmail: Couldn't determine implicit lockfile from "grep"
procmail: Locking ".lock"
procmail: Executing "grep,-vi,^X-OTRS-"
procmail: Unlocking ".lock"
procmail: No match on "TO:.*@example.com"
procmail: No match on "^List-Id:.*OpenAntiVirus"
procmail: No match on "TO:.*@example.com"
procmail: Couldn't determine implicit lockfile from "/opt/otrs/bin/otrs.Console.pl"
procmail: Locking ".lock"
procmail: Executing "/opt/otrs/bin/otrs.Console.pl,Maint::PostMaster::Read"
procmail: [16563] Mon Sep 5 11:38:04 2016
procmail: Assigning "LASTFOLDER=/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read"
procmail: Unlocking ".lock"
procmail: Notified comsat: "otrs@:/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read"
From cencoredname@cencoredomain.com Mon Sep 5 11:38:01 2016
Subject: TestK
Folder: /opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read

Im Filter Management ist jedoch nur ein Spamassassin Filter und im Admin -> SystemConfig -> Core::PostMaster -> PostMaster::PreFilterModule###4-CMD ein modifiziertes CMD.pm Script konfiguriert. (Nach Anleitung https://otrs.github.io/doc/manual/admin ... ing-filter , Abschnitt Example 4.5. Example job for the filter module Kernel::System::PostMaster::Filter::CMD )
Das Problem an der ganzen Sache ist, dass die Filter wie oben gezeigt (*) nirgendwo in diesen beiden Konfigurationen erstellt wurden.
Lange Rede kurzer Sinn: Auch wenn ich das Standardmodul (CMD.pm) und einfache Filterregeln sowie das Filtermanagement nutze werden diese Regeln nicht beachtet, gescheige denn bei Matches angewendet.

Hat jemand eine Idee, woher das rühren könnte?
reneeb
Znuny guru
Posts: 5018
Joined: 13 Mar 2011, 09:54
Znuny Version: 6.0.x
Real Name: Renée Bäcker
Company: Perl-Services.de
Contact:

Re: Postmaster Filter werden nicht geprüft

Post by reneeb »

Loggen sowohl procmail als auch OTRS in das gleiche Log? Wenn nein, dann schau mal ins OTRS-Log. Hast Du das Minimum-Loglevel in der SysConfig runtergesetzt?
Perl / Znuny development: http://perl-services.de
Free Znuny add ons from the community: http://opar.perl-services.de
Commercial add ons: http://feature-addons.de
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Re: Postmaster Filter werden nicht geprüft

Post by Mugen »

MinimumLogLevel steht auf "error" und habe ich jetzt mal auf "debug" gesetzt.
Nein, sendmail (!) ist mein Mail system und schreibt in journalctl.
Sendmails Log erzählt mir auch, es kämen die gleichen Mails an, wie OTRS behauptet.

Die E-Mails kommen an, das ist nicht das Problem. Nur die Filter, die werden nicht ausgeführt.
Den Filter, der hier mit #Match on ! "^From.*@example.com"' trifft, kann ich nirgendwo finden. Das scheint irgendein Standardfilter zu sein, der mir noch da zu entweder meine Filter überschreibt (so dass sie ignoriert werden) oder auf "Nicht fortfahren" beendet.

Hier eine Runde mit debug:
procmail: [22152] Mon Sep 5 13:58:01 2016
procmail: Match on ! "^From.*@example.com"
procmail: Couldn't determine implicit lockfile from "grep"
procmail: Locking ".lock"
procmail: Executing "grep,-vi,^X-OTRS-"
procmail: Unlocking ".lock"
procmail: No match on "TO:.*@example.com"
procmail: No match on "^List-Id:.*OpenAntiVirus"
procmail: No match on "TO:.*@example.com"
procmail: Couldn't determine implicit lockfile from "/opt/otrs/bin/otrs.Console.pl"
procmail: Locking ".lock"
procmail: Executing "/opt/otrs/bin/otrs.Console.pl,Maint::PostMaster::Read"
procmail: [22152] Mon Sep 5 13:58:04 2016
procmail: Assigning "LASTFOLDER=/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read"
procmail: Unlocking ".lock"
procmail: Notified comsat: "otrs@:/opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read"
From censoredname@censoreddomain.com Mon Sep 5 13:58:01 2016
Subject: TestM
Folder: /opt/otrs/bin/otrs.Console.pl Maint::PostMaster::Read 10230

Ich sehe da jetzt nicht viel Unterschied zu der Ausgabe mit "error" und "debug".




Nachtrag 14:25 Uhr: Offenbar sieht man vom Filtern einfach nichts.
Ich habe einen Filter im Manager erstellt, der nach dem Subject ".*(test|Test).*" sucht und in eine Lösch-Queue verschiebt. Hat auf Anhieb funktioniert.
Evtl. funktioniert das mit der "debug"-Ausgabe nicht ersichtlicher...
Dennoch funktioniert mein CMD-Modul Postmaster Filter nach wie vor nicht. (Das Skript selber erstellt eine Ausgabe, wie CMD verlangt, jedoch wird trotzdem keine Set-Anweisung ausgeführt.)
reneeb
Znuny guru
Posts: 5018
Joined: 13 Mar 2011, 09:54
Znuny Version: 6.0.x
Real Name: Renée Bäcker
Company: Perl-Services.de
Contact:

Re: Postmaster Filter werden nicht geprüft

Post by reneeb »

Die Filter die hier zu sehen sind, sind alle aus der .procmail (siehe https://github.com/OTRS/otrs/blob/maste ... ailrc.dist). Wohin loggst Du die OTRS-Sachen? Schau mal in der SysConfig nach... Denn in der journalctl scheint ja gar nichts von OTRS geloggt zu werden.
Perl / Znuny development: http://perl-services.de
Free Znuny add ons from the community: http://opar.perl-services.de
Commercial add ons: http://feature-addons.de
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Re: Postmaster Filter werden nicht geprüft

Post by Mugen »

Also ich weiß nicht, wo das System Log als Datei liegt, also habe ich jetzt nur das, was mir die Admin-Web-Oberfläche gibt. Hier sind beim Create nur die Standardeinstellungen genommen worden.
Bei meinem kurzem Test (Suche nach Subject=".*(test|Test).*", Set Queue="To delete") sieht man aber, dass die Queue im Create tatsächlich "To delete" lautet.

Die unteren von 13:43 und 12:39 sind von anderen Events, aber könnten diese damit zu tun haben?

Code: Select all

Mon Sep 5 15:48:02 2016 	info 	OTRS-otrs.Console.pl-Maint::PostMaster::Read-10 	Sent auto response (SendAutoReply) for Ticket [2016-1815] (TicketID=35270, ArticleID=126715) to 'censoredname@censoreddomain.com>'.
Mon Sep 5 15:48:02 2016 	info 	OTRS-otrs.Console.pl-Maint::PostMaster::Read-10 	Sent email to 'censoredname@censoreddomain.com>' from 'censoredname Ticket <otrs@censoredhost.censoreddomain.de>'. HistoryType => SendAutoReply, Subject => [Ticket#2016-1815] RE: TestN;
Mon Sep 5 15:48:02 2016 	info 	OTRS-otrs.Console.pl-Maint::PostMaster::Read-10 	New Ticket [2016-1815/TestN] created (TicketID=35270,Queue=00 - Default,Priority=3 not urgent, important,State=new)

Mon Sep 5 13:43:10 2016 	error 	OTRS-CGI-10 	Need Name!
Mon Sep 5 12:39:33 2016 	error 	OTRS-CGI-10 	The field configuration is invalid
reneeb
Znuny guru
Posts: 5018
Joined: 13 Mar 2011, 09:54
Znuny Version: 6.0.x
Real Name: Renée Bäcker
Company: Perl-Services.de
Contact:

Re: Postmaster Filter werden nicht geprüft

Post by reneeb »

Da ich nicht weiß, was Dein CMD-Filter macht, kann ich sonst nichts weiter dazu sagen...
Perl / Znuny development: http://perl-services.de
Free Znuny add ons from the community: http://opar.perl-services.de
Commercial add ons: http://feature-addons.de
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Re: Postmaster Filter werden nicht geprüft

Post by Mugen »

Dachte ich mir schon, darum hier mal meine Änderungen / Arbeit:

Datei "/opt/otrs/Kernel/Config.pm" (Ausschnitt)

Code: Select all

     1	# --
     2	# Copyright (C) 2001-2016 xxx, http://otrs.com/
     3	# --
     4	# This software comes with ABSOLUTELY NO WARRANTY. For details, see
     5	# the enclosed file COPYING for license information (AGPL). If you
     6	# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
     7	# --
     8	#  Note:
     9	#
    10	#  -->> Most OTRS configuration should be done via the OTRS web interface
    11	#       and the SysConfig. Only for some configuration, such as database
    12	#       credentials and customer data source changes, you should edit this
    13	#       file. For changes do customer data sources you can copy the definitions
    14	#       from Kernel/Config/Defaults.pm and paste them in this file.
    15	#       Config.pm will not be overwritten when updating OTRS.
    16	# --
    17	
    18	package Kernel::Config;
    19	
    20	use strict;
    21	use warnings;
   218	
   219	
   220	    # Job Name: Mail-Button # OTRS-Implementation cencoredname Sep. 2016
   221	    # (Properly parsing email header)
   222	    $Self->{'PostMaster::PreFilterModule'}->{'OTRSButton'} = {
   223	        Module => 'Kernel::System::PostMaster::Filter::OTRSButton',
   224	        CMD => '/opt/otrs/my_scripts/get_Mail_header.pl',
   225		Set => { 'X-OTRS-Queue' => 'default' }
   226	        }
   227	
   228	    #
   229	    # customer satisfaction poll
   230	    #
   231	    #$Self->{TicketPollIntervall} = 10;
   232	
   233	    # ---------------------------------------------------- #
   234	    # ---------------------------------------------------- #
   235	    #                                                      #
   236	    #               End of my config options 	           #
   237	    #                                                      #
   238	    # ---------------------------------------------------- #
   239	
   240	
   241	    # ---------------------------------------------------- #
   242	    # ---------------------------------------------------- #
   243	    #                                                      #
   244	    # end of your own config options!!!                    #
   245	    #                                                      #
   246	    # ---------------------------------------------------- #
   247	    # ---------------------------------------------------- #
   248	}
   249	
   250	# ---------------------------------------------------- #
   251	# needed system stuff (don't edit this)                #
   252	# ---------------------------------------------------- #
   253	
   254	use base qw(Kernel::Config::Defaults);
   255	
   256	# -----------------------------------------------------#
   257	
   258	1;
Datei: "/opt/otrs/my_scripts/get_Mail_header.pl" (Wird vom CMD-Job/-Filter aufgerufen und erzeugt einen Output wie "$key\t;\t$value")

Code: Select all

     1	#!/usr/bin/perl
     2	
     3	use strict;
     4	use warnings;
     5	#use diagnostics;
     6	
     7	my %tmphash	= ();
     8	my @lines	= ();
     9	my $file	= $ARGV[0];
    10	
    11	if ( ! ( @ARGV ) ) {
    12		chomp(@lines = <STDIN>);
    13		}
    14	elsif ( -s $file ) {
    15		open(FH, "<", $file);
    16			chomp(@lines = <FH>);
    17			close(FH);
    18		}
    19	else {
    20		#print STDERR "File no file or a empty file!\n";
    21		exit(1);
    22		}
    23	
    24	&get_MailHeaders(
    25		\%tmphash,
    26		"From",
    27		"X-OTRS-Queue",
    28		"Subject",
    29		"X-OTRS-CustomerUser",
    30		@lines
    31		);
    32	
    33	foreach my $key ( sort(keys(%tmphash)) ) {
    34		print "$key\t;\t$tmphash{$key}\n";
    35		}
    36	
    37	sub get_MailHeaders {
    38	
    39	#	 &get_MailHeaders(
    40	#		\%targethash,
    41	#		"key_mail_of_targethash",
    42	#		"key_QueueName_of_targethash",
    43	#		"key_Subject_of_targethash",
    44	#		"key_From_Username_of_targethash",
    45	#		@header_lines_of_incoming_mail
    46	#		);
    47	
    48		my %target		= ();
    49		$target{hash}		= shift;
    50		$target{mail}		= shift;
    51		$target{queue}		= shift;
    52		$target{subject}	= shift;
    53		$target{sender}		= shift;
    54		my @file		= @_;
    55	
    56		for ( my $i = 0 ; $i < scalar(@file) ; $i++ ) {
    57			if ( $file[$i] =~ m/OTRS/ ) {	# optimize speed
    58				my $line	= $file[$i];
    59				my $linebefore	= gwioident($file[$i - 1]);
    60				if ( $line =~ m/name=OTRS_Sender_INET/ ) {
    61					$target{hash}->{$target{mail}} 		=	$linebefore;
    62					}
    63				elsif ( $line =~ m/name=OTRS_Queue/ ) {
    64					$target{hash}->{$target{queue}} 	=	$linebefore;
    65					}
    66				elsif ( $line =~ m/name=OTRS_Subject/ ) {
    67					$target{hash}->{$target{subject}} 	=	$linebefore;
    68					}
    69				elsif ( $line =~ m/name=OTRS_Sender/ ) {
    70					chomp(my @getent_passwd	= qx(/usr/bin/getent passwd));
    71					my $searcher		= $linebefore;
    72						$searcher	=~ s/(-|\s)+/.+/g;
    73					my $passuser		= (grep(/$searcher/i, @getent_passwd))[0];
    74					if ( $passuser ) {
    75						$linebefore	= (split(':', $passuser))[0];
    76						}
    77					$target{hash}->{$target{sender}} 	=	$linebefore;
    78					}
    79				}
    80			}
    81	
    82		sub gwioident {
    83			# get without identificator
    84			my $string = shift;
    85			$string =~ s/(?:X-Mailprogram-Item: )(.+)(?:;.*$)/$1/;
    86			return($string);
    87			}
    88		}
    89	#EOF
Datei: "/opt/otrs/Kernel/System/PostMaster/Filter/OTRSButton.pm" (Überarbeitete Kopie von CMD.pm; liest den output von $In in ein Array, welches dann die Ausgabe von get_Mailheader ($key\t;\t$value) aufbereitet (split) und in das Hash %Set übergibt. (Geänderte Zeilen/Abschnitte sind mit "Mycanges" markiert)

Code: Select all

     1	# --
     2	# Copyright (C) 2001-2016 xxx, http://otrs.com/
     3	# --
     4	# This software comes with ABSOLUTELY NO WARRANTY. For details, see
     5	# the enclosed file COPYING for license information (AGPL). If you
     6	# did not receive this file, see http://www.gnu.org/licenses/agpl.txt.
     7	# --
     8	# Move output of CMD to %Set for use dynamicly
     9	
    10	package Kernel::System::PostMaster::Filter::OTRSButton;
    11	
    12	use strict;
    13	use warnings;
    14	
    15	our @ObjectDependencies = (
    16	    'Kernel::Config',
    17	    'Kernel::System::Log',
    18	);
    19	
    20	sub new {
    21	    my ( $Type, %Param ) = @_;
    22	
    23	    # allocate new hash for object
    24	    my $Self = {};
    25	    bless( $Self, $Type );
    26	
    27	    # get parser object
    28	    $Self->{ParserObject} = $Param{ParserObject} || die "Got no ParserObject!";
    29	
    30	    return $Self;
    31	}
    32	
    33	sub Run {
    34	    my ( $Self, %Param ) = @_;
    35	
    36	    # get config options
    37	    my %Config;
    38	    my %Set;
    39	    if ( $Param{JobConfig} && ref( $Param{JobConfig} ) eq 'HASH' ) {
    40	        %Config = %{ $Param{JobConfig} };
    41	        if ( $Config{Set} ) {
    42	            %Set = %{ $Config{Set} };
    43	        }
    44	    }
    45	
    46	    # check CMD config param
    47	    if ( !$Config{CMD} ) {
    48	        $Kernel::OM->Get('Kernel::System::Log')->Log(
    49	            Priority => 'error',
    50	            Message  => 'Need CMD config option in PostMaster::PreFilterModule job!',
    51	        );
    52	        return;
    53	    }
    54	
    55	    # execute prog
    56	    my $TmpFile = $Kernel::OM->Get('Kernel::Config')->Get('TempDir') . "/PostMaster.Filter.CMD.$$";
    57	
    58	    ## no critic
    59	    if ( open my $Prog, '|-', "$Config{CMD} > $TmpFile" ) {
    60	        ## use critic
    61	        print $Prog $Self->{ParserObject}->GetPlainEmail();
    62	        close $Prog;
    63	    }
    64	
    65	    if ( -s $TmpFile ) {
    66	        open my $In, '<', $TmpFile;    ## no critic
    67	        my $Ret = <$In>;
    68	        chomp(my @mlines = <$In>);    ## Mycanges
    69	        close $In;
    70	
    71	    ### Mycanges start
    72	    foreach my $mline ( @mlines ) {
    73	        $mline = [ split("\t;\t", $mline) ];
    74	        $Set{$mline->[0]}    =    $mline->[1];
    75	        }
    76	    ### Mycanges end
    77	
    78	        # set new params
    79	        for ( sort keys %Set ) {
    80	            $Param{GetParam}->{$_} = $Set{$_};
    81	            $Kernel::OM->Get('Kernel::System::Log')->Log(
    82	                Priority => 'notice',
    83	                Message =>
    84	                    "Set param '$_' to '$Set{$_}' because of '$Ret' (Message-ID: $Param{GetParam}->{'Message-ID'}) ",
    85	            );
    86	        }
    87	    }
    88	
    89	    unlink $TmpFile;
    90	
    91	    return 1;
    92	}
    93	
    94	1;
reneeb
Znuny guru
Posts: 5018
Joined: 13 Mar 2011, 09:54
Znuny Version: 6.0.x
Real Name: Renée Bäcker
Company: Perl-Services.de
Contact:

Re: Postmaster Filter werden nicht geprüft

Post by reneeb »

Bau doch mal ein paar

Code: Select all

$Kernel::OM->Get('Kernel::System::Log')->Log( Priority => error => Message => "Testnachricht - #Nr" );
in Dein OTRS-Button-Modul ein (natürlich mit immer anderen Werten bei "#Nr"). Dann siehst Du vielleicht eher wo es hakt.

Hast Du das Skript mal testweise auf der Kommandozeile aufgerufen? Hast Du mal ein kleines Testskript geschrieben, das Dein Perl-Skript aufruft?
Perl / Znuny development: http://perl-services.de
Free Znuny add ons from the community: http://opar.perl-services.de
Commercial add ons: http://feature-addons.de
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Re: Postmaster Filter werden nicht geprüft

Post by Mugen »

Also:
A)

Code: Select all

cat mail.file | ./get_Mailheaders.pl
lief, das hatte ich schon lange getestet, wie gewünscht

B)

Code: Select all

./call_gMailh.pl
ist bei

Code: Select all

open my $Prog, '|-', "$Config{CMD} > $TmpFile"
sehr ähnlich gebaut wie das Origianl:

Code: Select all

#!/usr/bin/perl

use strict;
use warnings;
use diagnostics;

my $script = "/opt/otrs/my_scripts/get_Mail_header.pl";
my $TmpFile = "/opt/otrs/my_scripts/testfiles/TMP.file";
my $mail = "/opt/otrs/my_scripts/testfiles/test6.mail";

open(FH, "<", $mail);
	chomp(my @lines = <FH>);
	close(FH);

my $lines = join("\n", @lines);

print "Mail:\n$lines\n\n\n\n";

open my $Prog, '|-', "$script > $TmpFile";
print $Prog "$lines\n";

print "Output from \$TmpFile:\n";
if ( -s $TmpFile ) {
	open(FH, "<", $TmpFile);
		while ( <FH> ) {
			print "$_";
			}
		close(FH);
	}
und erzeugt ebenfalls die Gewünschte Ausgabe, bzw. arbeitet bis zum letzten

Code: Select all

}
.


C) Jetzt wird es interessant!
Mal zum Verständnis: Ich habe jetzt in jeder Schleife, jedem if, also fast jeder dritten Zeile eine Log-Ausgabe.
Durch die Ausgabe, die nun im Log erscheint, wird deutlich, dass im original script "OTRSButton.pm" das

Code: Select all

if ( -s $TmpFile ) {
nicht betreten wird. Beim Testlauf (Siehe Punkt B) jedoch schon.
Was mich besonders wundert ist, der unlink kommt erst nach dieser If-Anweisung und für $TmpFile ist auch ein Pfad gesetzt worden:

Code: Select all

/opt/otrs/var/tmp/PostMaster.Filter.CMD.1238

Also zugegeben: Mit OOPPerl ist es bei mir nicht weit her, aber dass die If -s nicht greift ist mir völlig schleierhaft. :shock:
Mugen
Znuny newbie
Posts: 10
Joined: 05 Sep 2016, 12:05
Znuny Version: 5.0.9

Re: Postmaster Filter werden nicht geprüft

Post by Mugen »

So... Ich fürchte, das Problem liegt an gänzlich anderer Stelle:

Die Header, die beim versenden mit unserem Mail-Programm über den OTRS-Button hinzugefügt (und von meinem Skript dann gesucht) werden, sind in dem Header-Part, den OTRSButton.pm an mein skript get_Mailheader.pl übergibt nämlich nicht mal mehr ansatzweise enthalten oder irgendwo auffindbar.
Genau genommen: Es wird alles im Envelop gespeichert und der wird neu aufgebaut und die benötigten Informationen gehen dabei verloren.

Jetzt ist wohl erst mal die Frage zu klären, ob das einer der Vierenscanner rausschmeißt oder sendmail dafür verantwortlich ist.

Danke für deine Geduld, reneeb. Deine Ideen haben mir wirklich weiter geholfen, auch wenn nicht so, wie ich mir das vorgestellt habe. ;-)

Viele Grüße und noch alles Gute! :-)

Mugen
Dmowskavitto
Znuny newbie
Posts: 4
Joined: 12 Sep 2016, 11:51
Znuny Version: otrs-3.3.3-01
Real Name: Vittoria Dmowska
Company: 3D Architectural Rendering
Contact:

Re: Postmaster Filter werden nicht geprüft

Post by Dmowskavitto »

found this solution with regular expression to check the body of incoming email. Send here is an example hope is useful for others:
Create an Postmaster Filter, In the filter condition
Header 1: select Body
Value 1: (^|\n)Connection ID:.*\nNetwork ID:.*\nAddress.($|\n)
If your email template is longer (over length 100), you can open the AdminPostmasterFilter.dtl and remove Maxlength="100" of textbox of Value1. Of course you have to modify the max length of f_value (maybe 1000) in Postmaster_filter table

So, if the Connection ID is a dynamic field of your ticket, you can get its value from body of incoming email, for example
In the Set Email Headers
Header 1: select X-OTRS-DynamicField-ConnectionID
Value 1: ^Connection ID: (.*)\n

Then, I set default for rejected tickets in Core:Postmaster. But I don't know how to set sending an email to nofity for this case. Anyone know, please show me
Locked