Regression introduced by d84741a4bfb6ed2531ec7154479c147d2c9a737c. The mentioned commit actually is a good thing, because we now get the output from the X session. Unfortunately, for the i3wm test, the i3-config-wizard prints out the raw keyboard symbols directly coming from xcb, so the output isn't necessarily proper UTF-8. As the XML::Writer already expects valid UTF-8 input, we assume that everything that comes into sanitise() will be UTF-8 from the start. So we just decode() it using FB_DEFAULT as the check argument so that every invalid character is replaced by the unicode replacement character: https://en.wikipedia.org/wiki/Specials_(Unicode_block)#Replacement_character We simply re-oncode it again afterwards and return it, so we should always get out valid UTF-8 in the log XML. For more information about FB_DEFAULT and FB_CROAK, have a look at: http://search.cpan.org/~dankogai/Encode-2.84/Encode.pm#Handling_Malformed_Data Signed-off-by: aszlig <aszlig@redmoonstudios.org>
		
			
				
	
	
		
			73 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
			
		
		
	
	
			73 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Perl
		
	
	
	
	
	
package Logger;
 | 
						|
 | 
						|
use strict;
 | 
						|
use Thread::Queue;
 | 
						|
use XML::Writer;
 | 
						|
use Encode qw(decode encode);
 | 
						|
 | 
						|
sub new {
 | 
						|
    my ($class) = @_;
 | 
						|
    
 | 
						|
    my $logFile = defined $ENV{LOGFILE} ? "$ENV{LOGFILE}" : "/dev/null";
 | 
						|
    my $log = new XML::Writer(OUTPUT => new IO::File(">$logFile"));
 | 
						|
    
 | 
						|
    my $self = {
 | 
						|
        log => $log,
 | 
						|
        logQueue => Thread::Queue->new()
 | 
						|
    };
 | 
						|
    
 | 
						|
    $self->{log}->startTag("logfile");
 | 
						|
    
 | 
						|
    bless $self, $class;
 | 
						|
    return $self;
 | 
						|
}
 | 
						|
 | 
						|
sub close {
 | 
						|
    my ($self) = @_;
 | 
						|
    $self->{log}->endTag("logfile");
 | 
						|
    $self->{log}->end;
 | 
						|
}
 | 
						|
 | 
						|
sub drainLogQueue {
 | 
						|
    my ($self) = @_;
 | 
						|
    while (defined (my $item = $self->{logQueue}->dequeue_nb())) {
 | 
						|
        $self->{log}->dataElement("line", sanitise($item->{msg}), 'machine' => $item->{machine}, 'type' => 'serial');
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub maybePrefix {
 | 
						|
    my ($msg, $attrs) = @_;
 | 
						|
    $msg = $attrs->{machine} . ": " . $msg if defined $attrs->{machine};
 | 
						|
    return $msg;
 | 
						|
}
 | 
						|
 | 
						|
sub nest {
 | 
						|
    my ($self, $msg, $coderef, $attrs) = @_;
 | 
						|
    print STDERR maybePrefix("$msg\n", $attrs);
 | 
						|
    $self->{log}->startTag("nest");
 | 
						|
    $self->{log}->dataElement("head", $msg, %{$attrs});
 | 
						|
    $self->drainLogQueue();
 | 
						|
    eval { &$coderef };
 | 
						|
    my $res = $@;
 | 
						|
    $self->drainLogQueue();
 | 
						|
    $self->{log}->endTag("nest");
 | 
						|
    die $@ if $@;
 | 
						|
}
 | 
						|
 | 
						|
sub sanitise {
 | 
						|
    my ($s) = @_;
 | 
						|
    $s =~ s/[[:cntrl:]\xff]//g;
 | 
						|
    $s = decode('UTF-8', $s, Encode::FB_DEFAULT);
 | 
						|
    return encode('UTF-8', $s, Encode::FB_CROAK);
 | 
						|
}
 | 
						|
 | 
						|
sub log {
 | 
						|
    my ($self, $msg, $attrs) = @_;
 | 
						|
    chomp $msg;
 | 
						|
    print STDERR maybePrefix("$msg\n", $attrs);
 | 
						|
    $self->drainLogQueue();
 | 
						|
    $self->{log}->dataElement("line", $msg, %{$attrs});
 | 
						|
}
 | 
						|
 | 
						|
1;
 |