#!/usr/bin/perl -w

use strict;
use DBI;

sub do_error($) {
   exit(1);
}

if(@ARGV != 3) {
	print "Usage: $0 <mysqluser> <mysqlpass> <mysqldb>\n";
	exit(1);
}

my ($user,$pass,$dbname) = @ARGV;

my $db = DBI->connect("dbi:mysql:$dbname", $user, $pass);

if (!defined($db)) {
	print "did not connect to mysql\n";
	exit(1);
}

sub decode_entryid($) {
	my ($entryid) = @_;
	return unpack("LB128LLLCCCC", $entryid);
}

sub encode_entryid($$$) {
	my ($guid, $type, $objectid) = @_;
	return pack("LB128LLLCCCC", 0, $guid, 0, $type, $objectid, 0, 0, 0, 0);
}

sub update {
    my ($storeid, $hierarchyid) = @_;

    my $sth = $db->prepare("UPDATE properties SET properties.storeid=$storeid WHERE properties.hierarchyid=$hierarchyid");
    $sth->execute();

    $sth = $db->prepare("SELECT hierarchy.id FROM hierarchy WHERE hierarchy.parent=$hierarchyid");
    $sth->execute();

    my @row;
    my $totalsize = 0;
    while(@row = $sth->fetchrow_array()) {
        update($storeid, $row[0]);
    }
}

my $res; 
my $sth;
my $rows;

$res = $db->do("set character_set_client=utf8;");
if(!$res) {
  do_error(1);
}
$res = $db->do("set character_set_connection=utf8;");
if(!$res) {
  do_error(1);
}
$res = $db->do("set character_set_results=utf8;");

if(!$res) {
  do_error(1);
}

print "Updating table structure ... (this may take up to several hours)\n";
$res = $db->do("ALTER TABLE properties ADD COLUMN (storeid integer not null), drop primary key, add primary key(storeid, tag, type, hierarchyid);");

if(!$res) {
  do_error(1);
}

print "Updating store ID structure ... (this may take up to several hours)\n";
# Add PR_SEARCH_KEY for all objects

$sth = $db->prepare("SELECT hierarchy_id FROM stores JOIN users ON users.id = stores.user_id");
if(!$sth) {
  do_error(1);
}
$sth->execute();

my @row;

while(@row = $sth->fetchrow_array()) {
    print "  Updating store " . $row[0] . "\n";

    $db->do("BEGIN");
    $db->do("UPDATE properties SET type=0x14, val_longint=val_ulong WHERE type=0x03 and tag=0x0e08 and hierarchyid=" . $row[0]);
    update($row[0],$row[0]);
    $db->do("COMMIT");
}

print "Creating Free/Busy folders ...\n";

$sth = $db->prepare("SELECT hierarchy_id, guid FROM stores WHERE user_id=1");
if(!$sth) {
  do_error(1);
}
$sth->execute();

@row = $sth->fetchrow_array();
if (scalar(@row) == 0) {
	print "Public not found.\n";
	do_error(1);
}

my ($pub_hid, $pub_guid);
$pub_hid = $row[0];
$pub_guid = unpack("B128", $row[1]);

$sth = $db->prepare("SELECT val_binary FROM properties WHERE storeid=".$pub_hid." AND tag=0x6622");
if(!$sth) {
	do_error(1);
}
$sth->execute();
@row = $sth->fetchrow_array();
if (scalar(@row) != 0) {
	print "Free/Busy folder already present.\n";
	exit(0);
}

$sth = $db->prepare("SELECT val_binary FROM properties WHERE storeid=".$pub_hid." AND tag=0x6620");
if(!$sth) {
	do_error(1);
}
$sth->execute();

@row = $sth->fetchrow_array();
if (scalar(@row) == 0) {
	print "Public root container not found.\n";
	do_error(1);
}	

my @values = decode_entryid($row[0]);
my ($pubroot) = $values[4];		# NON_IPM_SUBTREE hierarchy_id

# create 'SCHEDULE+ FREE BUSY' folder
$sth = $db->prepare("INSERT INTO hierarchy (parent, modtime, createtime, type, flags, owner) VALUES (".$pubroot.", now(), now(), 3, 1, 1)");
if(!$sth) {
	do_error(1);
}
$sth->execute();

$sth = $db->prepare("SELECT last_insert_id()");
if(!$sth) {
	do_error(1);
}
$sth->execute();
@row = $sth->fetchrow_array();
my $rid = $row[0];

$sth = $db->prepare("INSERT INTO properties (storeid, hierarchyid, tag, type, val_binary) VALUES (".$pub_hid.", ".$pub_hid.", 0x6622, 0x102, ?)");
if(!$sth) {
	do_error(1);
}
$sth->execute(encode_entryid($pub_guid, 3, $rid));

$db->do("INSERT INTO properties (storeid, hierarchyid, tag, type, val_string) VALUES (".$pubroot.", ".$rid.", 0x3001, 30, 'SCHEDULE+ FREE BUSY')");
$db->do("INSERT INTO acl (id, hierarchy_id, type, rights) VALUES (1, ".$rid.", 1, 4602)");
$db->do("INSERT INTO acl (id, hierarchy_id, type, rights) VALUES (1, ".$rid.", 2, 1025)");

# create 'Zarafa 1' folder
$sth = $db->prepare("INSERT INTO hierarchy (parent, modtime, createtime, type, flags, owner) VALUES (".$rid.", now(), now(), 3, 1, 1)");
if(!$sth) {
	do_error(1);
}
$sth->execute();

$sth = $db->prepare("SELECT last_insert_id()");
if(!$sth) {
	do_error(1);
}
$sth->execute();
@row = $sth->fetchrow_array();
$rid = $row[0];

$sth = $db->prepare("INSERT INTO properties (storeid, hierarchyid, tag, type, val_binary) VALUES (".$pub_hid.", ".$pub_hid.", 0x6625, 0x102, ?)");
if(!$sth) {
	do_error(1);
}
$sth->execute(encode_entryid($pub_guid, 3, $rid));

$db->do("INSERT INTO properties (storeid, hierarchyid, tag, type, val_string) VALUES (".$pubroot.", ".$rid.", 0x3001, 30, 'Zarafa 1')");
$db->do("INSERT INTO acl (id, hierarchy_id, type, rights) VALUES (1, ".$rid.", 1, 4096)");
$db->do("INSERT INTO acl (id, hierarchy_id, type, rights) VALUES (1, ".$rid.", 2, 1531)");


print "done.\n";
