From a53c66e8a449d17f4f4484ef299b7500a8a5612b Mon Sep 17 00:00:00 2001 From: Jean Raby Date: Thu, 18 Apr 2013 14:35:56 -0400 Subject: [PATCH] Install openchange_user_cleanup in usr/sbin/ Instead of usr/share/doc/sogo/ --- Scripts/openchange_cleanup.py | 306 --------------------------- packaging/debian-multiarch/rules | 1 + packaging/debian-multiarch/sogo.docs | 1 - packaging/debian/rules | 1 + packaging/debian/sogo.docs | 1 - packaging/rhel/sogo.spec | 9 +- 6 files changed, 9 insertions(+), 310 deletions(-) delete mode 100755 Scripts/openchange_cleanup.py diff --git a/Scripts/openchange_cleanup.py b/Scripts/openchange_cleanup.py deleted file mode 100755 index ae44d46c1..000000000 --- a/Scripts/openchange_cleanup.py +++ /dev/null @@ -1,306 +0,0 @@ -#!/usr/bin/env python - -import getopt -import imaplib -import ldb -import plistlib -import os -import re -import shutil -import subprocess -import sys - -imaphost = '127.0.0.1' -imapport = 143 - -sambaprivate = '/var/lib/samba/private' -mapistorefolder = "%s/mapistore" % (sambaprivate) -sogoSysDefaultsFile = "/etc/sogo/sogo.conf" -sogoUserDefaultsFile = os.path.expanduser("~sogo/GNUstep/Defaults/.GNUstepDefaults") - -# - takes a username and optionally its password -# - removes the entry in samba's ldap tree via ldbedit (NOTYET) -# - remove the user's directory under mapistore/ and mapistore/SOGo -# - cleanup Junk Folders and Sync Issues imap folders -# - Delete the socfs_ table for the username. - -def usage(): - print """ -%s [-i imaphost] ] [-p imapport] [-s sambaprivate] username [password] - -i imaphost IMAP host to connect to [%s] - -p imappost IMAP port to use [%d] - -s sambaprivate samba private directory [%s] -""" % (os.path.basename(sys.argv[0]), imaphost, imapport, sambaprivate) - -def main(): - global sambaprivate - global mapistorefolder - global imaphost - global imapport - try: - opts, args = getopt.getopt(sys.argv[1:], "i:p:s:") - except getopt.GetoptError, err: - print str(err) - usage() - sys.exit(2) - - for o, a in opts: - if o == "-i": - imaphost = a - elif o == "-p": - imapport = a - elif o == "-s": - sambaprivate = a - mapistorefolder = "%s/mapistore" % (sambaprivate) - else: - assert False, "unhandled option" - - argslen = len(args) - if (argslen == 2): - username = args[0] - userpass = args[1] - elif (argslen == 1): - username = args[0] - userpass = username - print "Using username as password" - else: - usage() - print "Specify a user (and optionally the password)" - sys.exit(2) - - # cleanup starts here - try: - imapCleanup(imaphost, imapport, username, userpass) - except Exception as e: - print "Error during imapCleanup, continuing: %s" % str(e) - - try: - mapistoreCleanup(mapistorefolder, username) - except (shutil.Error, OSError) as e: - print "Error during mapistoreCleanup, continuing: %s" % str(e) - - try: - ldbCleanup(sambaprivate, username) - except ldb.LdbError as e: - print "Error during ldbCleanup, continuing: %s" % str(e) - - try: - sqlCleanup(username) - except Exception as e: - print "Error during sqlCleanup, continuing: %s" % str(e) - -def getsep(client): - seq = None - (code, data) = client.list("", "") - if code == "OK" and data is not None: - # yes this is ugly but it works on cyrus and dovecot. - # (\\Noinferiors \\HasNoChildren) "/" INBOX - m = re.search(".*\s+[\"\']?(.)[\"\']?\s+[\"\']?.*[\"\']?$", data[0]) - sep = m.group(1) - return sep - -def extractmb(si): - inparen = False - inquote = False - part = [] - parts = [] - - for char in si: - if inparen: - if char == ")": - inparen = False - parts.append("".join(part)) - else: - part.append(char) - elif inquote: - if char == "\"": - inquote = False - parts.append("".join(part)) - else: - part.append(char) - else: - if char == "(": - inparen = True - elif char == "\"": - inquote = True - elif char == " ": - part = [] - else: - part.append(char) - - return parts[-1] - -def cleanupmb(mb, sep, client): - (code, data) = client.list("%s%s" % (mb, sep), "%") - if code == "OK": - for si in data: - if si is not None: - submb = extractmb(si) - cleanupmb(submb, sep, client) - else: - raise Exception, "Failure while cleaning up '%s'" % mb - client.unsubscribe(mb) - (code, data) = client.delete(mb) - if code == "OK": - print "mailbox '%s' deleted" % mb - else: - print "mailbox '%s' coult NOT be deleted (code = '%s')" % (mb, code) - -def imapCleanup(imaphost, imapport, username, userpass): - print "Starting IMAP cleanup" - client = imaplib.IMAP4(imaphost, imapport) - (code, data) = client.login(username, userpass) - if code != "OK": - raise Exception, "Login failure" - - print "Logged in as '%s'" % username - - sep = getsep(client) - if not sep: - client.logout() - return - - for foldername in ("Sync Issues", "Junk E-mail", - "INBOX%sSync Issues" % sep, "INBOX%sJunk E-mail" % sep): - (code, data) = client.list(foldername, "%") - if code == "OK": - for si in data: - if si is not None: - mb = extractmb(si) - cleanupmb(mb, sep, client) - client.logout() - -def mapistoreCleanup(mapistorefolder, username): - print "Starting MAPIstore cleanup" - - # delete the user's folder under the mapistore and under mapistore/SOGo - mapistoreUserDir = "%s/%s" % (mapistorefolder, username) - for dirpath, dirnames, filenames in os.walk(mapistoreUserDir): - for f in filenames: - if f != "password": - os.unlink("%s/%s" % (dirpath,f)) - break #one level only - - shutil.rmtree("%s/SOGo/%s" % (mapistorefolder, username), ignore_errors=True) - -def ldbCleanup(sambaprivate, username): - conn = ldb.Ldb("%s/openchange.ldb" % (sambaprivate)) - # find the DN of the user - entries = conn.search(None, expression="(cn=%s)" % (username), scope=ldb.SCOPE_SUBTREE) - if not entries: - print "cn = %s not found in openchange.ldb" %(username) - return - - for entry in entries: - # search again, but with the user's DN as a base - subentries = conn.search(entry.dn.extended_str(), expression="(distinguishedName=*)", scope=ldb.SCOPE_SUBTREE) - for subentry in subentries: - print "Deleting %s" % (subentry.dn) - conn.delete(subentry.dn) - -def mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username): - try: - import MySQLdb - except ImportError: - msg ="""The python 'MySQLdb' module is not available -On Debian based distro, install it using 'apt-get install python-mysqlbd' -On RHEL, install it using 'yum install MySQL-python'""" - raise Exception(msg) - - conn = MySQLdb.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, db=dbname) - c=conn.cursor() - tablename="socfs_%s" % (username) - c.execute("TRUNCATE TABLE %s" % tablename) - print "Table %s emptied" - - -def postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, username): - try: - import pg - except ImportError: - msg ="""The python 'pg' module is not available -On Debian based distro, install it using 'apt-get install python-pygresql' -On RHEL, install it using 'yum install python-pgsql'""" - raise Exception(msg) - - conn = pg.connect(host=dbhost, port=int(dbport), user=dbuser, passwd=dbpass, dbname=dbname) - tablename = "socfs_%s" % username - conn.query("DELETE FROM %s" % tablename) - print "Table '%s' emptied" % tablename - -def getOCSFolderInfoURL(): - global sogoSysDefaultsFile, sogoUserDefaultsFile - - OCSFolderInfoURL = "" - - # read defaults from defaults files - # order is important, user defaults must have precedence - for f in [sogoSysDefaultsFile, sogoUserDefaultsFile]: - if os.path.exists(f): - # FIXME: this is ugly, we should have a python plist parser - # plistlib only supports XML plists. - # the following magic replaces this shell pipeline: - # sogo-tool dump-defaults -f %s | awk -F\\" '/ OCSFolderInfoURL =/ {print $2}' - p1 = subprocess.Popen(["sogo-tool", "dump-defaults", "-f", f], stdout=subprocess.PIPE) - p2 = subprocess.Popen(["awk", "-F\"", "/ OCSFolderInfoURL =/ {print $2}"], stdin=p1.stdout, stdout=subprocess.PIPE) - p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. - tmp = p2.communicate()[0] - - if tmp: OCSFolderInfoURL = tmp - - return OCSFolderInfoURL - -def asCSSIdentifier(inputString): - cssEscapingCharMap = {"_" : "_U_", - "." : "_D_", - "#" : "_H_", - "@" : "_A_", - "*" : "_S_", - ":" : "_C_", - "," : "_CO_", - " " : "_SP_", - "'" : "_SQ_", - "&" : "_AM_", - "+" : "_P_"} - - newChars = [] - - for c in inputString: - if c in cssEscapingCharMap: - newChars.append(cssEscapingCharMap[c]) - else: - newChars.append(c) - - return "".join(newChars) - -def sqlCleanup(username): - print "Starting SQL cleanup" - OCSFolderInfoURL = getOCSFolderInfoURL() - if OCSFolderInfoURL is None: - raise Exception("Couldn't fetch OCSFolderInfoURL or it is not set. the socfs_%s table should be truncated manually" % (username)) - - # postgresql://sogo:sogo@127.0.0.1:5432/sogo/sogo_folder_info - m = re.search("(.+)://(.+):(.+)@(.+):(\d+)/(.+)/(.+)", OCSFolderInfoURL) - - if not m: - raise Exception("Unable to parse OCSFolderInfoURL: %s" % OCSFolderInfoURL) - - proto = m.group(1) - dbuser = m.group(2) - dbpass = m.group(3) - dbhost = m.group(4) - dbport = m.group(5) - dbname = m.group(6) - # 7 is folderinfo table - - encodedUserName = asCSSIdentifier(username) - - if (proto == "postgresql"): - postgresqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, encodedUserName) - elif (proto == "mysql"): - mysqlCleanup(dbhost, dbport, dbuser, dbpass, dbname, encodedUserName) - else: - raise Exception("Unknown sql proto: %s" % (proto)) - -if __name__ == "__main__": - main() diff --git a/packaging/debian-multiarch/rules b/packaging/debian-multiarch/rules index 688c6d399..80d3ba19b 100755 --- a/packaging/debian-multiarch/rules +++ b/packaging/debian-multiarch/rules @@ -78,6 +78,7 @@ install-arch: build-arch install -D -m 644 Scripts/logrotate debian/tmp/etc/logrotate.d/sogo install -d -m 750 debian/tmp/etc/sogo/ install -D -m 640 Scripts/sogo.conf debian/tmp/etc/sogo/sogo.conf + install -D -m 755 Scripts/openchange_user_cleanup debian/tmp/usr/sbin/openchange_user_cleanup # Build architecture dependant packages using the common target. binary-arch: build-arch install-arch diff --git a/packaging/debian-multiarch/sogo.docs b/packaging/debian-multiarch/sogo.docs index 781cb916d..aba10029f 100644 --- a/packaging/debian-multiarch/sogo.docs +++ b/packaging/debian-multiarch/sogo.docs @@ -1,6 +1,5 @@ NEWS TODO Scripts/*.sh -Scripts/*.py Scripts/updates.php Apache/SOGo-apple-ab.conf diff --git a/packaging/debian/rules b/packaging/debian/rules index 3fe7bd0c3..0910d4c6c 100755 --- a/packaging/debian/rules +++ b/packaging/debian/rules @@ -83,6 +83,7 @@ install-arch: build-arch install -D -m 644 Scripts/logrotate debian/tmp/etc/logrotate.d/sogo install -d -m 750 debian/tmp/etc/sogo install -D -m 640 Scripts/sogo.conf debian/tmp/etc/sogo/sogo.conf + install -D -m 755 Scripts/openchange_user_cleanup debian/tmp/usr/sbin/openchange_user_cleanup # Build architecture dependant packages using the common target. binary-arch: build-arch install-arch diff --git a/packaging/debian/sogo.docs b/packaging/debian/sogo.docs index 781cb916d..aba10029f 100644 --- a/packaging/debian/sogo.docs +++ b/packaging/debian/sogo.docs @@ -1,6 +1,5 @@ NEWS TODO Scripts/*.sh -Scripts/*.py Scripts/updates.php Apache/SOGo-apple-ab.conf diff --git a/packaging/rhel/sogo.spec b/packaging/rhel/sogo.spec index 8cb0000f0..3bed6f84f 100644 --- a/packaging/rhel/sogo.spec +++ b/packaging/rhel/sogo.spec @@ -147,7 +147,7 @@ rm -fr ${RPM_BUILD_ROOT} # small tweak to the python script for RHEL5 # if hex(sys.hexversion) < 0x02060000 %if %{python_sys_pyver} < 33947648 - sed -i 's!/usr/bin/env python!/usr/bin/env python2.6!' Scripts/openchange_cleanup.py + sed -i 's!/usr/bin/env python!/usr/bin/env python2.6!' Scripts/openchange_user_cleanup %endif @@ -203,6 +203,7 @@ install -d ${RPM_BUILD_ROOT}/var/run/sogo install -d ${RPM_BUILD_ROOT}/var/spool/sogo install -d -m 750 -o %sogo_user -g %sogo_user ${RPM_BUILD_ROOT}/etc/sogo install -m 640 -o %sogo_user -g %sogo_user Scripts/sogo.conf ${RPM_BUILD_ROOT}/etc/sogo/ +install -m 755 Scripts/openchange_user_cleanup ${RPM_BUILD_ROOT}/%{_sbindir} cat Apache/SOGo.conf | sed -e "s@/lib/@/%{_lib}/@g" > ${RPM_BUILD_ROOT}/etc/httpd/conf.d/SOGo.conf install -m 600 Scripts/sogo.cron ${RPM_BUILD_ROOT}/etc/cron.d/sogo cp Scripts/tmpwatch ${RPM_BUILD_ROOT}/etc/cron.daily/sogo-tmpwatch @@ -239,6 +240,7 @@ rm -fr ${RPM_BUILD_ROOT} %dir %attr(0700, %sogo_user, %sogo_user) %{_var}/spool/sogo %dir %attr(0750, root, %sogo_user) %{_sysconfdir}/sogo %{_sbindir}/sogod +%{_sbindir}/openchange_user_cleanup %{_libdir}/libSOGo.so.* %{_libdir}/libSOGoUI.so.* %{_libdir}/libOGoContentStore.so* @@ -258,7 +260,7 @@ rm -fr ${RPM_BUILD_ROOT} %config(noreplace) %{_sysconfdir}/cron.d/sogo %config(noreplace) %{_sysconfdir}/httpd/conf.d/SOGo.conf %config(noreplace) %{_sysconfdir}/sysconfig/sogo -%doc ChangeLog NEWS Scripts/*sh Scripts/*py Scripts/updates.php Apache/SOGo-apple-ab.conf +%doc ChangeLog NEWS Scripts/*sh Scripts/updates.php Apache/SOGo-apple-ab.conf %files -n sogo-tool %{_sbindir}/sogo-tool @@ -337,6 +339,9 @@ fi # ********************************* changelog ************************* %changelog +* Thu Apr 17 2013 Jean Raby +- Install openchange_user_cleanup in sbindir instead of doc + * Wed Apr 10 2013 Jean Raby - use %sogo_user instead of 'sogo' - install a sample sogo.conf in /etc/sogo