Archive | Mail RSS feed for this section

IMAPS Server

9 May

Q: How to have an imaps server ?

R.
a) Install one

b) or use stunnel :
   Assuming there is an imap (143) server on localhost
        stunnel  -d 993 -r 143 -f

c) or use stunnel on inetd
   imaps stream  tcp nowait cyrus /usr/sbin/stunnel -s cyrus -p /etc/ssl/certs/imapd.pem -r localhost:imap2

Dspam

5 May

My database got too big and I wanted to make it run faster.

I added some indexes to the dspam database, in <dspam-src>/src/tools.mysql_drv/mysql_objects-speed.sql:

> alter table dspam_token_data add index(spam_hits);

>alter table dspam_token_data add index(innocent_hits);

>alter table dspam_token_data add index(last_hit);

 

I then dropped my current database (probably not the best idea, but adding indexes on the fly was very very slow). And reloaded the new schema *as well as* the 'virtual_users.sql' – you will need this *or* 'virtual_user_aliases.sql'.

 To test it I used:

>echo "asdf " | /usr/local/bin/dspam –stdout –deliver=spam,innocent –mode=tum –feature=chained,noise –enable-signature-headers –user amavis

 This should return some sort of stat on the innocence of the mail. If it throws an error you might have loaded in the wrong user sql ('virtual_users.sql'/'virtual_user_aliases.sql') above, just drop the table and load in the other one.

 Finally, check 'dspam/bin/dspam_stats -H' this should have some out put on how much spam is going through the server, if this doesn't work you probably have misconfigured something. You can also check the token data in the mysql db.

Spam Stats

26 Apr

SpamAssassin stats for April 2006. Over 35% of all mail is spam! Looks like an outage on upstream mail relay over the weekend.

April 2006 Spam Stats

Amavis/Clamav stats for April 2006

April 2006 Virus Stats

Horde/Turba – allowing public LDAP addresses to be added to private addressbooks

30 Oct

Below is a description of what i had to do to Turba to allow it to save both local addresses and LDAP addresses to an SQL addressbook:

The diff command used (from the turba directory) was:
diff -burN –exclude=*.dist –exclude=config –exclude=*.back –exclude=*.modified –exclude=*.sql ~/turba-1.2/ ./ > ../turba.diff

——————————————————————————————————————–
Turba Patches
Turba 1.2

THIS PATCH IS FOR TURBA 1.2 STABLE

This patch allows for adding LDAP addresses to SQL addressbooks.

Both normal ‘Search’ and ‘Advanced Search’ results can be added to the addressbook.

It is backwards compatible to address entry entered before this patch.

Chuck told me that it would be better to patch against CVS HEAD,unfortunately my boss asked me to write it against 1.2 STABLE. So this patch is for 1.2 STABLE.

Basically:

I have changed the turba_member field in turba_objects.

Rather than just having a serialized array of object_id’s, i.e.:

a:3:{i:0;s:32:”876d1826fdb03265df3243272a5f4420″;i:1;s:32:”16469607fe47e22d129464135ee79160″;}

This is really just: array(XXX,YYY)

I now have serialized array of arrays, with each inner array containing the source where the entry is from, i.e:

a:2:{i:0;a:2:{i:0;s:8:”imvsldap”;i:1;s:47:”uid=iisjsoo,ou=Users,dc=imvs,dc=sa,dc=gov,dc=au”;}

i:1;a:2:{i:0;s:8:”localsql”;i:1;s:32:”4cf194f308531d497fc909be896e6f05″;}}

This is: array( array(localsql, XXX), array(localldap,YYY)

I had to change

* browse.php
* lib/AbstractObject.php
* lib/api.php
* lib/Group.php
* templates/browse/actions.inc
* templates/browse/contactrow.inc

Below are some notes, and things that NEED to be changed to make it work.

————————————————————————————————————–

NOTE:

In config/sources.php, you will need to add the following line to the bottom of the file, where ‘localsql’ is the name of your sql source.. (i.e. $cfgSources[‘localsql’] )

define(‘PERSONAL_ADDRESS_BOOK_SOURCE’, ‘localsql’);

Also, make sure that $cfgSources[‘localsql’] array has something that

looks like:

‘map’ => array(

‘__key’ => ‘object_id’,

‘__owner’ => ‘owner_id’,

‘__type’ => ‘object_type’,

‘__members’ => ‘object_members’,

Also,

In lib/api.php, i don’t check for ‘turba_lists’ as was in 1.2 STABLE, i couldn’t work out why this was needed, so i just assume it is a turba_list.

Diff’s follow:
################################################


diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/browse.php ./browse.php
--- /home/iisjsoo/turba-1.2/browse.php Wed Mar 5 02:33:34 2003
+++ ./browse.php Fri Aug 15 16:11:54 2003
@@ -69,13 +69,20 @@
/* Remove a contact from a list. */
$keys = Horde::getFormData('objectkeys');
if (is_array($keys)) {
-
$key = Horde::getFormData('key', false);
if ($key && $key != "**search") {
/* We are removing a contact from a list. */
$list = $driver->getObject($key);
foreach ($keys as $objectKey) {
- if (!$list->removeMember($driver->getObject($objectKey))) {
+/* iisjsoo
+ *
+ * This was changed so that it takes into account the source of the
+ * entry
+ *
+ */
+ list($objectKeySource, $objectKey) = splitSourceAndKey($objectKey);
+ $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+ if (!$list->removeMemberSource($driver->getObject($objectKey))) {
Horde::raiseMessage(_("There was an error removing this object."), HORDE_ERROR);
} else {
Horde::raiseMessage(_("Contact removed from list."), HORDE_SUCCESS);
@@ -84,6 +91,13 @@
} else {
/* We are deleting an object. */
foreach ($keys as $objectKey) {
+/* iisjsoo
+ *
+ * This was changed so that it takes into account the source of the
+ * entry
+ *
+ */
+ list($objectKeySource, $objectKey) = splitSourceAndKey($objectKey);
if (!$driver->removeObject($objectKey)) {
Horde::raiseMessage(_("There was an error deleting this object."), HORDE_ERROR);
}
@@ -110,15 +124,32 @@
break;
}

+/* iisjsoo
+ *
+ * I need to first get a driver for the PERSONAL_ADDRESS_BOOK_SOURCE and then get
+ * the object
+ *
+ */
+ list($targetKeySource, $newTargetKey) = splitSourceAndKey($targetKey);
if (!Horde::getFormData('targetNew')) {
- $target = $driver->getObject($targetKey);
+ $driver = &Turba_Source::singleton(PERSONAL_ADDRESS_BOOK_SOURCE, $cfgSources[PERSONAL_ADDRESS_BOOK_SOURCE]);
+ $target = $driver->getObject($newTargetKey);
}

+
if (!empty($target) && is_object($target) && $target->isGroup()) {
/* Adding contact to an existing list */
if (is_array($keys)) {
foreach ($keys as $objectKey) {
- $target->addMember($driver->getObject($objectKey));
+/* iisjsoo
+ *
+ * This was changed so that it takes into account the source of the
+ * entry
+ *
+ */
+ list($objectKeySource, $objectKey) = splitSourceAndKey($objectKey);
+ $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+ $target->addMemberSource($driver->getObject($objectKey),$objectKeySource);
}
$target->store();
}
@@ -135,7 +166,15 @@
if (!empty($target) && is_object($target) && $target->isGroup()) {
if (is_array($keys)) {
foreach ($keys as $objectKey) {
- $target->addMember($driver->getObject($objectKey));
+/* iisjsoo
+ *
+ * This was changed so that it takes into account the source of the
+ * entry
+ *
+ */
+ list($objectKeySource, $objectKey) = splitSourceAndKey($objectKey);
+ $driver = &Turba_Source::singleton($objectKeySource, $cfgSources[$objectKeySource]);
+ $target->addMemberSource($driver->getObject($objectKey),$objectKeySource);
}
$target->store();
}
@@ -165,13 +204,20 @@
!isset($columns[$prefs->getValue('sortby') - 1])) ?
'lastname' : $columns[$prefs->getValue('sortby') - 1];

- /* Create list of lists for Add to. */
+/* Create list of lists for Add to. */
+/* iisjsoo:
+ * this next block is new - it is used so that addresses can be added
+ * to any address books. (e.g. ldap addresses can be added to sql books)
+*/
$addToList = array();
- if (!empty($cfgSources[$source]['map']['__type'])) {
- $listList = $driver->search(array('__type' => 'Group'), null, null, 0);
+ foreach ($sources as $src=>$val) {
+ if (!empty($cfgSources[$src]['map']['__type'])) {
+ $tmp_driver = &Turba_Source::singleton($source, $cfgSources[$src]);
+ $listList = $tmp_driver->search(array('__type' => 'Group'), null, null, 0);
$listList->reset();
while ($listObject = $listList->next()) {
- $addToList[] = array('name' => $listObject->getValue('name'), 'key' => $listObject->getValue('__key'));
+ $addToList[] = array('name' => $listObject->getValue('name'), 'key' => $src."|".$listObject->getValue('__key'));
+ }
}
}

@@ -198,29 +244,44 @@

} else if (Horde::getFormData('key')) {
/* We are displaying the contents of a list */
+ $templates[] = '/browse/header.inc';
+
+ /* iisjsoo:
+ * First we will grab an array using the listMembersArray() function to
+ * give us all users in this list as well as the source they come from.
+ *
+ * Then we will go thru the list and extract the users from their sources
+ * into a Turba_List which will be passed on.
+ *
+ * Note: there could be a performance enhancement here - make only one driver
+ * for each source
+ */
+ require_once TURBA_BASE . '/lib/List.php';
+ $results = &new Turba_List();
+ $listType = 'list';
+
+ $driver = &Turba_Source::singleton(PERSONAL_ADDRESS_BOOK_SOURCE, $cfgSources[PERSONAL_ADDRESS_BOOK_SOURCE]);
$list = $driver->getObject(Horde::getFormData('key'));
- if (isset($list) && is_object($list) && $list->isGroup()) {
- $title = sprintf(_("Addresses in list: %s"), $list->getValue('name'));
- include TURBA_TEMPLATES . '/browse/header.inc';
- /* Show List Members */
- if (!is_object($results = $list->listMembers($sortcolumn, $prefs->getValue('sortdir')))) {
- Horde::raiseMessage(_("Failed to browse list"), HORDE_ERROR);
- include TURBA_BASE . '/status.php';
- } else {
- $listType = "list";
+ $results_array = $list->listMembersArray();
+ if (count($results_array) != 0) {
+ foreach ($results_array as $tmp=>$listMember) {
+ /* iisjsoo:
+ * The $results_array contains entries of the form:
+ * 'localsql'|'38183e5d7ace6910e33eb925f29181c6'
+ * 'localldap'|'uid=asddf,dn=adsf,dn=com'
+ */
+
+ $driver = &Turba_Source::singleton($listMember[0], $cfgSources[$listMember[0]]);
+ $tmp2= $driver->getObject($listMember[1]);
+ $results->insert($tmp2);
+ }
+ }
include TURBA_TEMPLATES . '/browse/actions.inc';
include TURBA_TEMPLATES . '/browse/column_headers.inc';
-
require_once TURBA_BASE . '/lib/ListView.php';
$display = &new Turba_ListView($results, TURBA_TEMPLATES . '/browse/contactrow.inc');
$numDisplayed = $display->display();
-
include TURBA_TEMPLATES . '/browse/column_footers.inc';
- }
- } else {
- Horde::raiseMessage(_("There was an error displaying the select List"), HORDE_ERROR);
- include TURBA_BASE . '/status.php';
- }
} else {
/* We are displaying the contents of the address book */
$title = sprintf(_("Contents of %s"), $cfgSources[$source]['title']);
@@ -256,3 +317,32 @@
require TURBA_TEMPLATES . '/browse/footer.inc';
$registry->shutdown();
require TURBA_TEMPLATES . '/common-footer.inc';
+
+
+/* iisjsoo
+ *
+ * Function written to take an $objectKey of form:
+ *
+ * 'localsql'|'38183e5d7ace6910e33eb925f29181c6'
+ * 'localldap'|'uid=asddf,dn=adsf,dn=com'
+ *
+ * and it returns an array of the two parts:
+ *
+ * Array([0]=>'localsql', [1]=>'38183e5d7ace6910e33eb925f29181c6')
+ * Array([0]=>'localldap', [1]=>'uid=asddf,dn=adsf,dn=com')
+ *
+ * You should probably call it like:
+ * list($objectKeySource, $objectKey) = splitSourceAndKey($objectKey);
+ */
+
+function splitSourceAndKey($objectKey) {
+ if (preg_match("/\|/", $objectKey)) {
+ $objectKeyArr = preg_split('/\|/', $objectKey);
+ $objectKeySource = $objectKeyArr[0];
+ $objectKeyKey = $objectKeyArr[1];
+ return array($objectKeySource, $objectKeyKey);
+ } else {
+ return -1;
+ }
+}
+
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/AbstractObject.php ./lib/AbstractObject.php
--- /home/iisjsoo/turba-1.2/lib/AbstractObject.php Sat Nov 2 03:42:00 2002
+++ ./lib/AbstractObject.php Thu Aug 14 16:35:05 2003
@@ -52,6 +52,14 @@
return $this->source->name;
}

+ /* iisjsoo
+ * return the type of source this is (e.g. ldap, sql)
+ */
+ function getSourceType()
+ {
+ return $this->source->driver->type;
+ }
+
/**
* Returns the value of the specified attribute.
*
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/Group.php ./lib/Group.php
--- /home/iisjsoo/turba-1.2/lib/Group.php Sat Sep 14 07:13:05 2002
+++ ./lib/Group.php Fri Aug 15 16:17:39 2003
@@ -60,6 +60,36 @@
}
}

+
+ /**
+ * iisjsoo:
+ * new function (wouldn't some OO overloading be good here?)
+ * Adds a new contact entry to this group, also takes in the name of the group
+ * to add it to.
+ *
+ * @param Turba_AbstractObject $object The object to add to the Group
+ *
+ * @since Turba 1.2
+ */
+ function addMemberSource($object, $source)
+ {
+ if ($source == "") {
+ return addMemberSource($object);
+ }
+ // Can't add itself.
+ if ($object->getValue('__key') != $this->attributes['__key']) {
+ $members = @unserialize($this->attributes['__members']);
+ if (!is_array($members)) {
+ $members = array();
+ }
+ $member_entry[] = $object->getSource();
+ $member_entry[] = $object->getValue('__key');
+ $members[] = $member_entry;
+ $this->attributes['__members'] = serialize($members);
+ }
+ }
+
+
/**
* Deletes a contact entry from this group.
*
@@ -81,6 +111,65 @@
return true;
}

+
+ /**
+ * iisjsoo: Deletes a contact entry from this group
+ * Passed the $key and $source
+ * e.g.for ldap:
+ * $key: 'uid=iisjsoo,dn=XX,dn=YY'
+ * $source: 'myldap'
+ *
+ * e.g.for sql:
+ * $key: '765ef989dc9a9d9c5'
+ * $source: 'localsql'
+ *
+ * @param Turba_AbstractObject $object The object to remove from the Group
+ *
+ * @since Turba 1.2
+ */
+ function removeMemberSource($object)
+ {
+ $members = unserialize($this->attributes['__members']);
+ $key = $object->getValue('__key');
+ $source = $object->getSource();
+ $memberToRemove = array($source,$key);
+
+ if(($i = array_search($memberToRemove, $members)) !== false) {
+// print "found and deleting
";
+ unset($members[$i]);
+ } else {
+ print "could not find the member
";
+ }
+
+
+ $this->attributes['__members'] = serialize($members);
+ $this->store();
+ return true;
+ }
+
+
+
+ /** iisjsoo
+ * Function to return a Turba_List of arrays containing the Source of
+ * an entry and the entry's Key (object_id for sql, dn for ldap)
+ * e.g.
+ * list => (array('localsql', '73ebb2f4623ec959e5c6b12608750f57'),
+ * array('localldap', 'uid=itpdfdr,ou=Users,dc=xxx,dc=xxx,dc=com,dc=au'))
+ */
+ function listMembersArray()
+ {
+ $children = unserialize($this->attributes['__members']);
+ if (!is_array($children)) {
+ $children = array();
+ }
+ reset($children);
+ $list = array();
+ foreach ($children as $member) {
+ $list[] = $member;
+ }
+ return $list; //we can't sort this yet, lets work it out later
+ }
+
/**
* Retrieve the Objects in this group
*
diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/lib/api.php ./lib/api.php
--- /home/iisjsoo/turba-1.2/lib/api.php Mon Feb 10 12:06:55 2003
+++ ./lib/api.php Fri Aug 15 16:31:46 2003
@@ -115,34 +115,27 @@
/* Is a Distribution List */
$listatt = $ob->getAttributes();
$seeninlist = array();
- $members = $ob->listMembers();
- if (get_class($members) == 'turba_list') {
- if ($members->count() == 1) {
- $ob = $members->next();
- $att = $ob->getAttributes();
- $email = '';
- foreach ($att as $key => $value) {
- if (!empty($value) && isset($attributes[$key]) &&
- $attributes[$key]['type'] == 'email') {
- $email = $value;
- }
- }
- $results[$name][] = array('name' => $listatt['name'] . ' - ' . $att['name'], 'email' => $email);
- } else {
+ $members = $ob->listMembersArray();
+
+/* iisjsoo
+ *
+ * i'm not sure how to get around this..
+ * members is no longer a 'turba_list', but an array of arrays...
+ * maybe this should just check the return value of $ob->listMembersArray()
+ */
+ if (get_class($members) == 'turba_list' || 1==1) {
$email = '';
- while ($ob = $members->next()) {
- $att = $ob->getAttributes();
- foreach ($att as $key => $value) {
- if (!empty($value) && isset($attributes[$key]) &&
- $attributes[$key]['type'] == 'email' &&
- empty($seeninlist[trim(strtolower($att['name'])) . trim(strtolower($value))])) {
-
- $email .= ($email == '') ? '' : ', ';
- $email .= '"' . $att['name'] . '" ';
- $seeninlist[trim(strtolower($att['name'])) . trim(strtolower($value))] = true;
- }
- }
+ $members = $ob->listMembersArray();
+
+ foreach($members as $key=>$val){
+ $driver = &Turba_Source::singleton($val[0], $cfgSources[$val[0]]);
+ $listMember= $driver->getObject($val[1]);
+ $emailAddress = '"'.$listMember->getValue('name').
+ '" getValue('email').'>';
+ $email .= $emailAddress .= ',';
}
+ // get rid of trailing ','
+ $email = preg_replace("/,$/","",$email);
$results[$name][] = array('name' => $listatt['name'], 'email' => $email);
}
}
@@ -151,7 +144,6 @@
}
}
}
- }
return $results;
}

diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/templates/browse/actions.inc ./templates/browse/actions.inc
--- /home/iisjsoo/turba-1.2/templates/browse/actions.inc Wed Mar 5 02:33:37 2003
+++ ./templates/browse/actions.inc Thu Aug 14 17:09:54 2003
@@ -12,7 +12,11 @@ -
+

<input type="button" class="button" onclick="ListUpdate(); Submit(); return false;" value="" />

diff -burN --exclude='*.dist' --exclude=config --exclude='*.back' --exclude='*.modified' --exclude='*.sql' /home/iisjsoo/turba-1.2/templates/browse/contactrow.inc ./templates/browse/contactrow.inc
--- /home/iisjsoo/turba-1.2/templates/browse/contactrow.inc Mon Feb 10 12:35:57 2003
+++ ./templates/browse/contactrow.inc Fri Aug 15 16:12:37 2003
@@ -66,7 +66,10 @@
?>
<tr class="" onmouseover="javascript:style.backgroundColor='';" onmouseout="javascript:style.backgroundColor='';">

- <input type="checkbox" name="objectkeys[]" value="getValue('__key')) ?>" />
+
+ <input type="checkbox" name="objectkeys[]" value="getSource()) . "|" .htmlspecialchars($ob->getValue('__key')) ?>" />
isGroup() ? Horde::img('group.gif', 'alt="' . _("Group") . '"') : '' ?>