diff --git a/Documentation/SOGoNativeOutlookConfigurationGuide.asciidoc b/Documentation/SOGoNativeOutlookConfigurationGuide.asciidoc index 7d767ccfc..77917839c 100644 --- a/Documentation/SOGoNativeOutlookConfigurationGuide.asciidoc +++ b/Documentation/SOGoNativeOutlookConfigurationGuide.asciidoc @@ -818,9 +818,8 @@ can be ignored for now. This feature is currently not supported. remove any data associated with the user from the SOGo server and recreate a Microsoft Outlook profile. To remove any data associated to a user, use -the `openchange_user_cleanup` script distributed with SOGo. The script -can be found in `/usr/share/doc/sogo/` (`/usr/share/sogo-VERSION/` on -RHEL). +the `openchange_user_cleanup` script distributed with OpenChange. The script +can be found in `/usr/share/openchange/`. To reset a user, run the script as root: `openchange_user_cleanup username`. See the usage output for additional options. * The "Out of Office Assistant" will not currently work. This feature diff --git a/Scripts/openchange_user_cleanup b/Scripts/openchange_user_cleanup deleted file mode 100755 index 93a91c8ea..000000000 --- a/Scripts/openchange_user_cleanup +++ /dev/null @@ -1,312 +0,0 @@ -#!/usr/bin/env python - -import getopt -import imaplib -import ldb -import plistlib -import os -import re -import shutil -import subprocess -import sys -from samba.param import LoadParm - -imaphost = '127.0.0.1' -imapport = 143 - -samba_lp = LoadParm() -sambaprivate = samba_lp.get("private dir") -mapistorefolder = samba_lp.private_path("mapistore") -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 sogo_cache_folder_ 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, - "Probl&AOg-mes de synchronisation"): - (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="sogo_cache_folder_%s" % (username) - c.execute("TRUNCATE TABLE %s" % tablename) - print "Table %s emptied" % tablename - - -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 = "sogo_cache_folder_%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 = [] - - if str.isdigit(inputString[0]): - newChars.append("_") - - 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 sogo_cache_folder_%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 c349ef5f4..085b092f0 100755 --- a/packaging/debian-multiarch/rules +++ b/packaging/debian-multiarch/rules @@ -83,7 +83,6 @@ 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/rules b/packaging/debian/rules index d09f6cc6d..3792ee0f0 100755 --- a/packaging/debian/rules +++ b/packaging/debian/rules @@ -85,7 +85,6 @@ 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/rhel/sogo.spec b/packaging/rhel/sogo.spec index 4f1c484e5..925876a38 100644 --- a/packaging/rhel/sogo.spec +++ b/packaging/rhel/sogo.spec @@ -175,9 +175,9 @@ 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_user_cleanup -%endif +#%if %{python_sys_pyver} < 33947648 +# sed -i 's!/usr/bin/env python!/usr/bin/env python2.6!' Scripts/openchange_user_cleanup +#%endif # ****************************** build ******************************** @@ -244,7 +244,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} +#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 @@ -304,7 +304,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 +#%{_sbindir}/openchange_user_cleanup %{_libdir}/sogo/libSOGo.so* %{_libdir}/sogo/libSOGoUI.so* %{_libdir}/GNUstep/SOGo/AdministrationUI.SOGo