About | Buy | Forum | Industry Watch | Learning Curve | Products | Search | Twitter | Xnews
Home » Industry Watch » The Technological

Adobe on Drugs?

Abode and common sense security: never the twain meet?



Creative Suite beta users have run into snags when updating: things don't want to leave the trash. But as it turns out this is only the tip of the iceberg. Sidestepping the question why users don't RTFM which says you cannot toss stuff in the trash the field is left open for Adobe to answer a few questions themselves.

  • Why are users required to submit their administrator password when installing Adobe applications?
  • Do these applications only run under the administrator account like they're wont to do on Windows?
  • What is installed where? Why is there no install log and why does the uninstaller run with a binary?
  • Why do you say people must back up their ENTIRE HARD DRIVES before uninstalling? What's so dangerous?

Adobe also have a Bad Habit™ of leaving EVERYTHING world writable. The Technological suggest Adobe send their programmers on Unix and security courses ASAP.

'remember it is OK if it fails'

# encoding: utf-8
import os, sys, types, re, glob, time, traceback
import codecs, encodings, encodings.utf_8, encodings.ascii, encodings.cp437, encodings.cp850, encodings.cp1252
import textwrap

VERSION = '1.0.3'
LOGFILENAME = 'AdobeCS3Clean.log'

gPlatform = ''
gWinIsVista = False;
gLogPath = ''
gStdInEncoding = ''
gMsiZapPath = ''
gScriptpath = os.path.abspath(sys.argv[0])
gScriptdir = os.path.dirname(gScriptpath)
gScriptname = os.path.basename(gScriptpath)
os.chdir(gScriptdir)

if sys.platform in ['win32', 'win64']:
    import win32con, win32api, pywintypes
    import encodings.mbcs

    gPlatform = 'win'
    (majorversion , notneeded4 , notneeded1 , notneeded2 , notneeded3 )= win32api.GetVersionEx()
    if(majorversion >= 6):
        gWinIsVista = True

    gLogPath = os.path.join(os.environ['HOMEDRIVE'], os.environ['HOMEPATH'], LOGFILENAME)
    gStdInEncoding = sys.stdin.encoding
    # Unless stdin is using an encoding we've explicity imported, revert to using
    # getfilesystemencoding() Also...
    # Win J system stdin uses cp932 encoding. However, Python installed under an English
    # OS does not contain the necessary parts to import 'encodings.cp932' in order to
    # work with cx_freeze. To make building easier, we switch to using
    # getfilesystemencoding() which will work under Win J. Otherwise we'd have to probably
    # build under a J OS... or something.
    if (gStdInEncoding != 'cp437'
        and gStdInEncoding != 'cp850'
        and gStdInEncoding != 'cp1252'):
        gStdInEncoding = sys.getfilesystemencoding()
elif sys.platform in ['darwin','osx']:
    gPlatform = 'osx'
    gLogPath = os.path.join(os.environ['HOME'], LOGFILENAME)
    gStdInEncoding = sys.getfilesystemencoding()
else:
    raise RuntimeError(GetStr('notifyUnsupportedPlatform'))

gLogFile = open(gLogPath, 'a')
# this allows windows to recognize the logfile as utf8 encoded
gLogFile.write(codecs.BOM_UTF8)

gEnglishStringSet = {
    'appName':    'CS3 Clean-up',
    'queryChooseScrubbingLevel':    'Choose clean-up level',
    'yesNoPrompt':              ' [y/n]',
    'promptOKUninstall':        'Run Add/Remove Programs for "%s"',
    'warnUninstallMayFail':        'Running %s uninstaller, remember it is OK if it fails\n',
    'promptOKZap':            'Confirm MSIZap of "%s"',
    'notifyRunZap':            'Running MsiZap for "%s"\n',
    'promptOKRegRemove':        'Confirm registry removal of "%s"',
    'notifyDeleteProd':        'Deleting uninstall key product code for "%s"\n',
    'notifyUnsupportedPlatform':    'Unsupported platform',
    'notifyBeginOutput':        '*** BEGIN output of %s\n',
    'notifyFailResult':             'FAILURE: Operation "%s" failed with result code %s\n',
    'notifyEndOutput':        '*** END output of %s\n',
    'notifyAutoConfirm':        'Auto confirm of: %s\n',
    'notifyInvalidResponse':    '"%s" is not a valid response. Please enter one of "%s"\n',
    'confirmRenameDir':        'Rename directory "%s" to "%s"?',
    'confirmRemoveDir':        'Remove directory "%s"?',
    'confirmRemoveFile':        'Remove file "%s"?',
    'notifyRenaming':    'Renaming "%s" to "%s"\n',
    'notifyRemoving':        'Removing "%s"\n',
    'notifyMSIZapNotFound':    '''\
The Microsoft Windows Installer CleanUp Utility is required to
complete the cleaning.  This utility is not installed on your
machine.  Please read the AdobeCS3CleanReadMe.pdf for more
information on obtaining this utility.\n\n''',
    'confirmDelRegTree':        'Delete registry tree %s\%s?',
    'notifyDelRegTree':        'Removing registry tree %s\%s\n',
    'queryNonDefaultInstall':    'Did you install to any non-default locations?',
    'queryAdditionalDir':        'Additional directory (or skip)',
    'notifyInvalidDir':        '\nERROR: Invalid directory: %s\n\n',
    'queryAskApproval':        'Do you want to be asked for approval before each operation?',

    'queryPreviewMode':        '''\
Do you want to see a preview of all changes that will be made, but not
actually make any changes at this time?''',

    'queryVerbose':            'Would you like verbose output?',
    'queryTryAddRemove':        'Do you want to try Add/Remove programs uninstallers?',
    'queryBackupRegistry':        'Do you want to backup your registry?',
    'queryGo':            'By typing "GO" you acknowledge this risk (QUIT to cancel)',
    'notifyBeginRegBkp':        'BEGIN registry backup to %s\n',
    'notifyEndRegBkp':        'END registry backup\n',
    'notifyBeginExcTB':        '*** BEGIN EXCEPTION TRACEBACK\n',
    'notifyEndExcTB':        '*** END EXCEPTION TRACEBACK\n',
    'notifyCompleted':        'Completed, press Enter to exit',
    'notifyPreviewCompleted':        'Completed Preview, press Enter to exit',
    'notifyLooking':        'Looking for %s\n',
    'notifyLookingReg':        'Looking for registry entries %s\\%s\\%s\n',


    'notifyInstallDirs':        '''\
The application install directories are:

    %s

If you wish to add a custom install directory please enter the path
below. Otherwise type "skip".
''',


    'notifyBeginBlock':        '''\
#######################################################
### BEGIN %s
### %s
#######################################################
''',

    'msgScrubLevel':    '''\
There are several clean-up options. It is recommended that you begin
with the lowest number and work your way up until the applications
install correctly.

Level 1: %s

Level 2: %s
''',
    'scrubLevel1Win':    'Remove CS3 Applications. Does NOT remove Acrobat 8. Deletes all program files & cleans registry.',
    'scrubLevel2Win':    'Remove CS3 Applications & Acrobat 8. Deletes all program files & cleans registry.',
    'scrubLevel1Mac':    'Remove CS3 Applications. Does NOT remove Acrobat 8. Deletes all program files.',
    'scrubLevel2Mac':    'Remove CS3 Applications & Acrobat 8. Deletes all program files.',
    'scrubLevel3':    'Remove CS3, Acrobat 8, and Adobe shared technology.  CS2 and earlier Adobe applications may no longer run.',
    'scrubLevel4':    'Remove all Adobe (and some Macromedia) applications. This will force a reinstall of all Adobe and Macromedia software.',

    'msgSummary1':            '''\
WARNING: Run at your own risk. Be sure that all your fonts, data and
plug-ins, including Version Cue repositories, are backed up.

Adobe CS3 Pre-Removal Summary:

    Clean-up level:\t\t%s (%s)

    Preview only:\t\t%s

    Application Install Dirs:\t%s

    Logfile path:\t\t%s
''',


    'msgSummary2':            '''

    Backup registry:\t\t%s
''',

    'queryWarnBackup':    '''\
It is strongly recommended that you backup all your data, including
fonts, Version Cue repositories and plug-in files, and run uninstall
before running this script.

Do you wish to cancel at this time so you can backup your data or run
uninstall?''',

    'queryEULA':    '''\
License agreement

By using software of Adobe Systems Incorporated or its subsidiaries
("Adobe"); you agree to the following terms and conditions. If you do
not agree with such terms and conditions; do not use the software.
The terms of an end user license agreement accompanying a particular
software file upon installation or download of the software shall
supersede the terms presented below.

The export and re-export of Adobe software products are controlled by
the United States Export Administration Regulations and such software
may not be exported or re-exported to Cuba; Iran; Iraq; Libya; North
Korea; Sudan; or Syria or any country to which the United States
embargoes goods. In addition; Adobe software may not be distributed
to persons on the Table of Denial Orders; the Entity List; or the
List of Specially Designated Nationals.

By downloading or using an Adobe software product you are certifying
that you are not a national of Cuba; Iran; Iraq; Libya; North Korea;
Sudan; or Syria or any country to which the United States embargoes
goods and that you are not a person on the Table of Denial Orders;
the Entity List; or the List of Specially Designated Nationals.

If the software is designed for use with an application software
product (the "Host Application") published by Adobe; Adobe grants you
a non-exclusive license to use such software with the Host
Application only; provided you possess a valid license from Adobe for
the Host Application. Except as set forth below; such software is
licensed to you subject to the terms and conditions of the End User
License Agreement from Adobe governing your use of the Host
Application.  You are not permitted to redistribute the software.

DISCLAIMER OF WARRANTIES: YOU AGREE THAT ADOBE HAS MADE NO EXPRESS
WARRANTIES TO YOU REGARDING THE SOFTWARE AND THAT THE SOFTWARE IS
BEING PROVIDED TO YOU "AS IS" WITHOUT WARRANTY OF ANY KIND. ADOBE
DISCLAIMS ALL WARRANTIES WITH REGARD TO THE SOFTWARE; EXPRESS OR
IMPLIED; INCLUDING; WITHOUT LIMITATION; ANY IMPLIED WARRANTIES OF
FITNESS FOR A PARTICULAR PURPOSE; MERCHANTABILITY; MERCHANTABLE
QUALITY OR NONINFRINGEMENT OF THIRD PARTY RIGHTS. Some states or
jurisdictions do not allow the exclusion of implied warranties; so
the above limitations may not apply to you.

LIMIT OF LIABILITY: IN NO EVENT WILL ADOBE BE LIABLE TO YOU FOR ANY
LOSS OF USE; INTERRUPTION OF BUSINESS; OR ANY DIRECT; INDIRECT;
SPECIAL; INCIDENTAL; OR CONSEQUENTIAL DAMAGES OF ANY KIND (INCLUDING
LOST PROFITS) REGARDLESS OF THE FORM OF ACTION WHETHER IN CONTRACT;
TORT (INCLUDING NEGLIGENCE); STRICT PRODUCT LIABILITY OR OTHERWISE;
EVEN IF ADOBE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
Some states or jurisdictions do not allow the exclusion or
limitation of incidental or consequential damages; so the above
limitation or exclusion may not apply to you.

Do you agree to the above conditions?''',

} # end english strings

gJapaneseStringSet = {
    'yesNoPrompt':              ' はい[y]/いいえ[n]',
    'queryChooseScrubbingLevel':    'レベルを選択してください',
    'promptOKUninstall':        '"%s"プログラムの追加/削除を実行しますか?',
    'warnUninstallMayFail':        '%sアンインストーラを実行中、正常にアンインストールできなくてもかまいません\n',
    'promptOKZap':            '"%s"についてMsiZapを承認する',
    'notifyRunZap':            '"%s"についてMsiZapを実行中\n',
    'promptOKRegRemove':        '"%s"レジストリの削除を承認する',
    'notifyDeleteProd':        '"%s"のアンインストールキープロダクトコードを削除中\n',
    'notifyUnsupportedPlatform':    'サポートしていないプラットフォーム',
    'notifyBeginOutput':        '*** %sの表示開始\n',
    'notifyFailResult':             '失敗:  "%s" 操作は正しく作動しませんでした。コード:%s\n',
    'notifyEndOutput':        '*** %sの表示終了\n',
    'notifyAutoConfirm':        '%sを自動的に承認する\n',
    'notifyInvalidResponse':    '"%s"は有効な返答ではありません。つぎの "%s"から1つ入力します\n',
    'confirmRemoveDir':        '"%s"ディレクトリを削除しますか?',
    'confirmRemoveFile':        '"%s"を削除しますか?',
    'notifyRemoving':        '削除中 "%s"\n',
    'notifyMSIZapNotFound':    'クリーンアップを完了するには、Microsoft Windows Installer CleanUpユーティリティが必要です。このユーティリティはシステムにはインストールされません。ユーティリティの取得については、「クリーンアップスクリプトについて.pdf」に記載されている情報をよくお読みください。\n\n',
    'confirmDelRegTree':        '%s\%sレジストリツリーを削除しますか?',
    'notifyDelRegTree':        '%s\%sレジストリツリーを削除中\n',
    'queryNonDefaultInstall':    'デフォルトのインストール場所以外にインストールしましたか?',
    'queryAdditionalDir':        '追加のディレクトリ(またはskip)を入力します',
    'notifyInvalidDir':        '\nエラー:無効なディレクトリ: %s\n\n',
    'queryAskApproval':        '1つ1つの操作について確認しますか?',
    'queryPreviewMode':        '今回は実際には何も変更せずに変更されるすべての内容をプレビュー表示しますか?',
    'queryVerbose':            '詳しい記述がほしいですか',
    'queryTryAddRemove':        'プログラムの追加/削除インストーラを使用しますか?',
    'queryBackupRegistry':        'レジストリをバックアップしますか?',
    'queryGo':            'リスクを承認しスクリプトを実行するには [GO] と入力します。(キャンセルするには [QUIT] と入力します。)',
    'notifyBeginRegBkp':        'レジストリのバックアップ開始 %s\n',
    'notifyEndRegBkp':        'レジストリのバックアップ終了\n',
    'notifyBeginExcTB':        '*** EXCEPTIONの記録開始\n',
    'notifyEndExcTB':        '*** EXCEPTIONの記録終了\n',
    'notifyCompleted':        '完了、[Enter]キーを押して終了します。',
    'notifyPreviewCompleted':        'プレビューの完了、[Enter]キーを押して終了します。',
    'notifyLooking':        '%sを検索中です\n',
    'notifyLookingReg':        '%s\\%s\\%sレジストリを検索中です\n',


    'notifyInstallDirs':        '''\
通常のアプリケーションのインストールディレクトリは下記のとおりです:

    %s

他のディレクトリにインストールした場合には、次にパスを入力します。必要ない場合には、[skip]と入力します
''',


    'notifyBeginBlock':        '''\
#######################################################
### 開始 %s
### %s
#######################################################
''',

    'msgScrubLevel':    '''\
クリーンアップには次のレベルが用意されています。
最初はレベル1を実行し、希望のアプリケーションが正常にインストールされるまで、次のレベルを順に実行していきます

レベル1: %s

レベル2: %s
''',

    'scrubLevel1Win':    'CS3アプリケーションを削除しますが、Acrobat 8は削除しません。プログラムファイルを削除し、レジストリをきれいにします。',
    'scrubLevel2Win':    'CS3アプリケーションおよびAcrobat 8を削除します。プログラムファイルを削除し、レジストリをきれいにします。',
    'scrubLevel1Mac':    'CS3アプリケーションを削除しますが、Acrobat 8は削除しません。プログラムファイルを削除します。',
    'scrubLevel2Mac':    'CS3アプリケーションおよびAcrobat 8を削除します。プログラムファイルを削除します。',
    'scrubLevel3':    'CS3アプリケーション、Acrobat  8、および共有ファイルを削除します。CS2およびそれ以前のアプリケーションが起動しなくなる可能性があります。',
    'scrubLevel4':    'すべてのAdobe(および幾つかのMacromedia)アプリケーションを削除します。実行後すべてのAdobeおよびMacromediaアプリケーションを再インストールする必要があります',

    'msgSummary1':            '''\
注意:この操作にはリスクが伴うことを承知の上で実行してください。
Version Cue関連フォルダを含む、ご使用のフォント、データ、プラグインのすべてがバックアップされていることを確認してください。

Adobe CS3削除前の要約:

    クリーンアップレベル: %s (%s)

    プレビューのみ; %s

    アプリケーションのインストールディレクトリ: %s

    ログファイルのパス: %s
''',
    'msgSummary2':            '''

    レジストリのバックアップ: %s
''',

    'queryWarnBackup':    '''\
このスクリプトを実行する前に必ずフォント、Version Cue関連フォルダ、およびプラグインファイルを含むすべてのデータをバックアップしてください。またアンインストーラも実行してください。
データのバックアップまたはアンインストールのためにこのスクリプトをキャンセルしますか?''',

    'queryEULA':    '''\
使用許諾条件

お客様がAdobe Systems Incorporatedまたはその子会社(以下「アドビ」)の本ソフトウェア(以下「本ソフトウエア」)をダウンロードされることにより、お客樣には下記の使用許諾契約の諸条件に同意いただいたものとみなさせていただきます。同意いただけない場合には、本ソフトウエアをダウンロードまたは使用することはできませんのでご注意ください。ダウンロードまたはインストール後において特定のソフトウェアにエンドユーザ使用許諾契約の条件が別途付されている場合は、かかる条件がそのソフトウェアについて優先して適用されるものとします。

アドビのソフトウエア製品の輸出および再輸出は米国輸出管理規則により規制されており、キューバ、イラン、イラク、リビア、北朝鮮、スーダンもしくはシリアまたはその他米国政府が輸出を禁ずる国への輸出および再輸出は許可されません。さらに、アドビのソフトウエア製品はTOD(Table Of Denial Order)、Entity Listまたは List of Specially Designated Nationalsの取引禁止対象者リストの対象者へ頒布することは許可されておりません。

本ソフトウエアをダウンロードすることにより、お客樣にはキューバ、イラン、イラク、リビア、北朝鮮、スーダンもしくはシリアまたはその他米国政府が輸出を禁ずる国の国民でないこと、TOD、Entity Listまたは List of Specially Designated Nationalsの取引禁止対象者リストの対象者ではないことを証していただきます。

本ソフトウエアが他のアドビ製品(以下「ホストソフトウエア」)との併用を予定している場合、アドビは本ソフトウェアを専らホストソフトウエアと併用するために使用できる非排他的な権利を許諾します。ただし、かかる許諾はお客様がホストソフトウエアの正規ライセンスを有していることを条件とします。下記に定める規定を除き、本ソフトウエアの使用条件はホストソフトウェアの使用について適用されるアドビのエンドユーザ使用許諾契約の規定によるものとします。お客様は本ソフトウェアを再配布することはできません。

保証の放棄:本ソフトウェアは現状有姿にてお客様に提供されるものです。アドビおよびサプライヤーは、本ソフトウェアに関し明示または黙示を問わず何らの保証も致しません。特に、商品性、特定の目的に対する適合性または第三者の権利を侵害しない旨の保証は、一切行いません。本項はお客様の法律上の権利行使を制限するものではありません。

限定責任:本ソフトウェアのインストールまたは使用に関連してお客様に直接的または間接的に発生する一切の損害(ハードウェア、他のソフトウェアの破損、不具合等を含む。また、通常損害、特別損害、結果損害を問わない)および第三者からなされる請求についてアドビまたはサプライヤーは一切責任を負担しません。但し、法律上この責任限定の適用が制限される範囲においてはこの限りではありません。

上記の条件に同意しますか''',
} # end english strings


gStringSet = gEnglishStringSet

### sanity check strings:
esskeys = gEnglishStringSet.keys()
esskeys.sort()
jsskeys = gJapaneseStringSet.keys()
jsskeys.sort()
for k in esskeys:
    numFields = gEnglishStringSet[k].count('%')
    assert gEnglishStringSet[k].count('%s') == numFields
    #assert gJapaneseStringSet[k].count('%') == numFields
    #assert gJapaneseStringSet[k].count('%s') == numFields

def DoQuit(prompt = None):
    if prompt:
        GenericPromptUser(prompt, None)
    gLogFile.close()
    sys.exit()

def GetStr(which):
    if gStringSet.has_key(which):
        return gStringSet[which].decode('utf-8')
    else:
        # just being careful not to crash; no localization is better than that.
        return gEnglishStringSet[which].decode('utf-8')

def GetScrubLevelDesc(level):
    if gPlatform == 'win':
        if level == 1:
            key = 'scrubLevel1Win'
        elif level == 2:
            key = 'scrubLevel2Win'
        elif level == 3:
            key = 'scrubLevel3'
        elif level == 4:
            key = 'scrubLevel4'
    else:
        if level == 1:
            key = 'scrubLevel1Mac'
        elif level == 2:
            key = 'scrubLevel2Mac'
        elif level == 3:
            key = 'scrubLevel3'
        elif level == 4:
            key = 'scrubLevel4'
    return GetStr(key)


if gPlatform == 'win':

    class RegKey:
        def __init__(self, parent, keyname, writable=False):
            if not parent:
                self.name = keyname
                self.key =  {
                    'HKCR': win32con.HKEY_CLASSES_ROOT,
                    'HKLM': win32con.HKEY_LOCAL_MACHINE,
                    'HKCU': win32con.HKEY_CURRENT_USER,
                    'HKU': win32con.HKEY_USERS,
                    }[keyname]
            else:
                self.name = parent.name + '\\' + keyname
                self.key = win32api.RegOpenKeyEx(parent.key, keyname, 0, (win32con.KEY_READ, win32con.KEY_WRITE)[writable])

        def __del__(self):
            win32api.RegCloseKey(self.key)

        def DeepSubKeyExists(self, subkeypath):
            try:
                k = win32api.RegOpenKeyEx(self.key, subkeypath, 0, win32con.KEY_READ)
                win32api.RegCloseKey(k)
                return True
            except pywintypes.error, e:
                if e[0] == 2:
                    return False
                else:
                    raise

        def GetSubKey(self, subkeyname, writable=False):
            return RegKey(self, subkeyname, writable)

        def HasSubKey(self, subkeyname):
            return subkeyname in self.GetSubKeyNames()

        def HasSubSubKey(self, subkeyname, subsubkeyname):
            if not subkeyname in self.GetSubKeyNames():
                return False
            subkey = self.GetSubKey(subkeyname)
            return subsubkeyname in subkey.GetSubKeyNames()

        def GetSubKeyNames(self):
            (numsubkeys, numvalues, modtime) = win32api.RegQueryInfoKey(self.key)
            return  [ win32api.RegEnumKey(self.key, i) for i in range(numsubkeys)]

        def PatternGetSubKeyNames(self, pat):
            return [ x for x in self.GetSubKeyNames() if re.match(pat, x)]

        def FindSubKeyNamesWithProps(self, valname, dataconstraint):
            res = []
            for skn in self.GetSubKeyNames():
                subkey = RegKey(self, skn)
                valdata = subkey.GetValueData(valname)
                if valdata and type(valdata) == types.StringType:
                    if Matches(valdata, dataconstraint):
                        res.append(skn)
            return res

        def DeleteSubKey(self, subkeyname):
            subkey = RegKey(self, subkeyname, False)
            for sskn in subkey.GetSubKeyNames():
                subkey.DeleteSubKey(sskn)
            del subkey
            win32api.RegDeleteKey(self.key, subkeyname)

        def DeleteSubKeyIfExists(self, subkeyname):
            if self.HasSubKey(subkeyname):
                self.DeleteSubKey(subkeyname)

        def DeleteSubSubKey(self, subkeyname, subsubkeyname):
            RegKey(self, subkeyname, False).DeleteSubKey(subsubkeyname)

        def DeleteSubSubKeyIfExists(self, subkeyname, subsubkeyname):
            if self.HasSubSubKey(subkeyname, subsubkeyname):
                self.DeleteSubSubKey(subkeyname, subsubkeyname)

        def IsEmpty(self):
            (numsubkeys, numvalues, modtime) = win32api.RegQueryInfoKey(self.key)
            return numsubkeys == 0 and numvalues == 0

        def DeleteSubKeyIfExistsAndIsEmpty(key, subkeyname):
            if subkeyname in key.GetSubKeyNames():
                if RegKey(key, subkeyname).IsEmpty():
                    key.DeleteSubKey(subkeyname)

        def GetValueData(self, valname):
            try:
                res = win32api.RegQueryValueEx(self.key, valname)[0]
                #if type(res) == types.StringType:
                #    res = res.decode('mbcs')
                return res
            except:
                return None

    def GetUninstallRegKey():
        return RegKey(RegKey(None, 'HKLM'), 'SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall')

    def GetDisplayNameForProductCode(productcode):
        uninst = GetUninstallRegKey()
        key = RegKey(uninst, productcode)
        return key.GetValueData('DisplayName')

    def GetUninstallStringForProductCode(productcode):
        uninst = GetUninstallRegKey()
        key = RegKey(uninst, productcode)
        if key.GetValueData('SystemComponent'):
            return None
        else:
            return key.GetValueData('UninstallString')

    def GetSoftwareAdobeRegKey(machinekey):
        return RegKey(RegKey(None, machinekey), 'SOFTWARE\\Adobe')

    def Uninstall(productcode):
        cmd = GetUninstallStringForProductCode(productcode)
        if not cmd:
            return False
        else:
            if os.path.isfile(cmd):
                cmd = 'call "%s"' % cmd
            prodname = GetDisplayNameForProductCode(productcode)
            if GetConfirmation(GetStr('promptOKUninstall') % prodname):
                UserMessage(GetStr('warnUninstallMayFail')% prodname)
                if not gPreview:
                    SysCall(cmd)
                return True
            return False

    def GetMsiZapPath():
        path = os.path.join(os.environ['ProgramFiles'], 'Windows Installer Clean Up', 'MsiZap.exe')
        if not os.path.isfile(path):
            UserMessage(GetStr('notifyMSIZapNotFound'))
            DoQuit(GetStr('notifyCompleted'))
        return path

    def MsiZap(productcode):
        UserMessage('Product Code to be zapped: %s \n' %productcode)
        prodname = GetDisplayNameForProductCode(productcode)
        prodname = prodname.decode('mbcs')
        if not GetConfirmation(GetStr('promptOKZap') % prodname):
            return
        UserMessage(GetStr('notifyRunZap') % prodname)
        if not gPreview:
            cmd1 = 'call "%s" TWA! %s' % (gMsiZapPath, productcode)
            cmd2 = 'call "%s" TW! %s' % (gMsiZapPath, productcode)
            if not gWinIsVista:
                SysCall(cmd1)
                SysCall(cmd2)
            else:
                os.system(cmd1)
                os.system(cmd2)

    def WhackProductCodeKey(productcode):
        prodname = GetDisplayNameForProductCode(productcode)
        prodname = prodname.decode('mbcs')
        if not GetConfirmation(GetStr('promptOKRegRemove') % prodname):
            return
        UserMessage(GetStr('notifyDeleteProd') % prodname)
        if not gPreview:
            GetUninstallRegKey().DeleteSubKey(productcode)

    def GetProductCodes(constraints):
        res = []
        uninstallkey = GetUninstallRegKey()
        for level, constraint in constraints:
            if gScrubLevel >= level:
                res.extend(uninstallkey.FindSubKeyNamesWithProps('DisplayName', constraint))
        return res


    def UninstallAll(constraints):
        triedonce = []
        keepgoing = True
        while keepgoing:
            keepgoing = False
            for pc in GetProductCodes(constraints):
                 # try to uninstall, may be a no-op, may remove product codes other
                 # than just itself; hence the careful loop
                 if pc in triedonce:
                     continue
                 triedonce.append(pc)
                 if Uninstall(pc):
                    keepgoing = True
                    break

    def MsiZapAll(constraints):
        triedonce = []
        keepgoing = True
        while keepgoing:
            keepgoing = False
            for pc in GetProductCodes(constraints):
                 # try to zap, may be a no-op, may remove product codes other
                 # than just itself; hence the careful loop
                 if pc in triedonce:
                     continue
                 triedonce.append(pc)
                 MsiZap(pc)

    def WhackProductCodeKeyAll(constraints):
        for pc in GetProductCodes(constraints):
            WhackProductCodeKey(pc)

    def RemoveAllApplications(constraints):
        #if gTryUninstallers:
        #    UninstallAll(constraints)
        MsiZapAll(constraints)
        WhackProductCodeKeyAll(constraints)


def Matches(str, constraint):
    if type(constraint) == types.StringType:
        return str == constraint
    else:
        # assume pattern
        return re.search(constraint, str) != None

def message(msg, consoleToo):
    gLogFile.write(msg.encode('utf-8'))
    if consoleToo or gVerbose:
        try:
            sys.stdout.write(msg.encode(sys.stdout.encoding))
        except:
            #fallback to using the filesystemencoding if the string failed to encode
            sys.stdout.write(msg.encode(sys.getfilesystemencoding()))


def SysCall(cmd, expectedres = 0):
    LogMessage(GetStr('notifyBeginOutput') % cmd)
    (inpipe, outpipe) = os.popen4(cmd.encode(sys.getfilesystemencoding()))
    inpipe.close()
    for line in outpipe.xreadlines():
        LogMessage('  '+line)
    res = outpipe.close()
    if res is not None and res != expectedres:
        LogMessage(GetStr('notifyFailResult') % (cmd, res))
    LogMessage(GetStr('notifyEndOutput')% cmd)

def UserMessage(msg):
    message(msg, True)

def LogMessage(msg):
    message(msg, False)

def BoolToString(bool):
    if bool:
        return 'Yes'
    return 'No'

def ClearScreen():
    if gPlatform == 'win':
        os.system('cls')
    else:
        os.system('clear')
    print

def GetConfirmation(prompt):
    if gAutoConfirm:
        LogMessage("Auto confirm of: %s\n" % prompt)
        return True
    else:
        return YesNoPromptUser(prompt)

def YesNoPromptUser(prompt, header = None):
    return GenericPromptUser(prompt + GetStr('yesNoPrompt'), {'y': True, 'yes': True, 'n': False, 'no':False}, header)

def GenericPromptUser(prompt, responsemap, header = None):
    if header:
        UserMessage(header + '\n')
    while True:
        UserMessage(prompt + ': ')
        response = sys.stdin.readline()
        gLogFile.write(response)

        try:
            response = response.decode(gStdInEncoding)
        except:
            #if decode failed, then input isn't valid
            continue

        response = response.strip()
        if not responsemap:
            return response
        response = response.lower()
        if response in responsemap.keys():
            return responsemap[response]

        responsemapKeys = responsemap.keys()
        responsemapKeys.sort()
        UserMessage(GetStr('notifyInvalidResponse') % (response, '", "'.join(responsemapKeys)))

def GenericPromptUserHidden(prompt, vresponsemap, hresponsemap, header = None):
    if header:
        UserMessage(header + '\n')
    while True:
        UserMessage(prompt + ': ')
        response = sys.stdin.readline()
        gLogFile.write(response)

        try:
            response = response.decode(gStdInEncoding)
        except:
            #if decode failed, then input isn't valid
            continue

        response = response.strip()
        if not vresponsemap:
            return response
        response = response.lower()
        if response in vresponsemap.keys():
            return vresponsemap[response]
        if response in hresponsemap.keys():
            return hresponsemap[response]

        vresponsemapKeys = vresponsemap.keys()
        vresponsemapKeys.sort()
        UserMessage(GetStr('notifyInvalidResponse') % (response, '", "'.join(vresponsemapKeys)))


def AssertLooksLikeAdobeThing(str):
    str = str.lower()
    for substr in ['adobe', 'macromedia', 'versioncue', 'flv' ,  'flash' , 'com.macromedia' , 'com.adobe' , 'acrobat' , '8.0_x86' , 'caps.db' , 'cs3' , 'backup']:
        if str.find(substr) >= 0:
            return
    assert False

def DoRenameDir(d,t):
    AssertLooksLikeAdobeThing(d)
    if not os.path.isdir(d):
        return
    if not GetConfirmation(GetStr('confirmRenameDir') % (d,t)):
        return
    UserMessage(GetStr('notifyRenaming') % (d,t))
    if not gPreview:
        cmd = os.path.join(d , 'caps.db')
        if(os.path.isfile(cmd)):
            #If file exists it means user has re-installed and he has a new caps.db so we would delete the old folder.
            if gPlatform == 'win':
                if not gWinIsVista:
                    SysCall('rmdir /S /Q "%s"' % t)
                else:
                    os.system('CleanUpRMDIR.exe "%s"' % (t))
            else:
                SysCall('rm -R "%s"' % t)
            os.rename(d,t)

def DoRemoveDir(d):
    AssertLooksLikeAdobeThing(d)
    if not GetConfirmation(GetStr('confirmRemoveDir') % d):
        return
    UserMessage(GetStr('notifyRemoving') % d)
    if not gPreview:
        if gPlatform == 'win':
            if not gWinIsVista:
                SysCall('rmdir /S /Q "%s"' % d)
            else:
                os.system('CleanUpRMDIR.exe "%s"' % (d))
        else:
            SysCall('rm -R "%s"' % d)

def DoRemoveDirIfEmpty(d):
    if os.listdir(d):
        return
    else:
        DoRemoveDir(d)

def DoRemoveFile(f):
    decodedFile = f.decode(sys.getfilesystemencoding())
    AssertLooksLikeAdobeThing(decodedFile)
    if not GetConfirmation(GetStr('confirmRemoveFile') % decodedFile):
        return
    UserMessage(GetStr('notifyRemoving') % decodedFile)
    if not gPreview:
        os.unlink(f)

def RemoveDirGlob(pathpattern):
    for path in glob.glob(os.path.expanduser(pathpattern)):
        if os.path.isdir(path):
            DoRemoveDir(path)

def RemoveDirIfEmptyGlob(pathpattern):
    for path in glob.glob(os.path.expanduser(pathpattern)):
        if os.path.isdir(path):
            DoRemoveDirIfEmpty(path)

def RemoveFileGlob(pathpattern):
    for path in glob.glob(os.path.expanduser(pathpattern)):
        if not os.path.isdir(path):
            DoRemoveFile(path)

def RemoveSubDirsInList(dir, subDirs):
    for level, subdir in subDirs:
        if gScrubLevel >= level:
            path = os.path.join(dir, subdir)
            LogMessage(GetStr('notifyLooking') % path)
            RemoveDirGlob(path)

def RemoveSubFilesInList(dir, subFiles):
    for level, subfile in subFiles:
        if gScrubLevel >= level:
            path = os.path.join(dir, subfile)
            LogMessage(GetStr('notifyLooking') % path)
            RemoveFileGlob(path)

def RemoveRegKeysInList(machinekey, subkeys):
    for level, midkeys, endkey in subkeys:
        if gScrubLevel >= level:
            LogMessage(GetStr('notifyLookingReg') % (machinekey.name, midkeys, endkey))
            if (machinekey.DeepSubKeyExists(midkeys)):
                parentkey = RegKey(machinekey, midkeys)
                for skn in parentkey.GetSubKeyNames():
                    if Matches(skn, endkey):
                        if GetConfirmation(GetStr('confirmDelRegTree') % (parentkey.name, skn)):
                            if not gPreview:
                                UserMessage(GetStr('notifyDelRegTree') % (parentkey.name, skn))
                                parentkey.DeleteSubKey(skn)


if gPlatform == 'win':
    def DoClean():
        applist = [
            (1, re.compile('^Adobe Creative Suite 3')),
            (1, 'Adobe Device Central'),
            (1, 'Adobe Dreamweaver 9'),
            (1, 'Adobe Extension Manager'),
            (1, 'Adobe Flash Video Encoder'),
            (1, 'Adobe Help Viewer'),
            (1, 'Adobe Soundbooth'),
            (1, 'Adobe ExtendScript Toolkit2'),
            (1, 'Adobe ExtendScript Toolkit 2'),
            (1, 'Adobe Setup'),
            (1, re.compile('^Adobe Color.*Settings')),
            (1, re.compile('^Adobe.*CS3')),
            (2, re.compile('^Adobe Acrobat 8.*')),
            (2, 'Adobe PDF Library Files'),
            (3, 'Adobe Camera Raw 4.0'),
            (3, 'Adobe CMaps'),
            (3, 'Adobe Color - Photoshop Specific'),
            (3, 'Adobe Color Profiles'),
            (3, 'Adobe Color Settings Files'),
            (3, 'Adobe Fonts All'),
            (3, 'Adobe WinSoft Linguistics Plugin'),
            (3, 'Adobe Type Support'),
            (3, 'Adobe Bridge Start Meeting'),
            (4, re.compile('^Adobe')),
        ]

        installDirSubDirs = [
            (1, r'Adobe\Adobe*CS3'),
            (1, r'Adobe\Adobe Device Central'),
            (1, r'Adobe\Adobe Dreamweaver 9'),
            (1, r'Adobe\Adobe Extension Manager'),
            (1, r'Adobe\Adobe Flash CS3 Video Encoder'),
            (1, r'Adobe\Adobe Help Viewer'),
            (1, r'Adobe\Adobe Soundbooth'),
            (1, r'Adobe\Adobe Utilities\ExtendScript Toolkit2'),
            (1, r'Adobe\Adobe Utilities\ExtendScript Toolkit 2'),
            (2, r'Adobe\Acrobat 8.0\Setup Files'),
            (2, r'Adobe\Acrobat 8.0\Resource'),
            (2, r'Adobe\Acrobat 8.0\PDFMaker'),
            (2, r'Adobe\Acrobat 8.0\Help'),
            (2, r'Adobe\Acrobat 8.0\Esl'),
            (2, r'Adobe\Acrobat 8.0\Designer8.0'),
            (2, r'Adobe\Acrobat 8.0\Designer 8.0'),
            (2, r'Adobe\Acrobat 8.0\Acrobat Elements'),
            (2, r'Adobe\Acrobat 8.0\Acrobat'),
            (2, r'Adobe\Acrobat 8.0'),
            (4, r'Adobe'),
        ]

        installDirSubFiles = [
        ]

        commonFilesSubDirs = [
            (1, r'Adobe\caps'),
            (1, r'Adobe\Adobe PCD'),
            (1, r'Adobe\Launch\soundbooth'),
            (1, r'Adobe\Launch\indesign\5.0'),
            (1, r'Adobe\Launch\photoshop\10.0'),
            (1, r'Adobe\Launch\illustrator\13.0'),
            (1, r'Adobe\Launch\Contribute\4.1'),
            (1, r'Adobe\Launch\Flash\9.0'),
            (1, r'Adobe\Launch\devicecentral\1.0'),
            (1, r'Adobe\Launch\estk\2.0'),
            (1, r'Adobe\Launch\estoolkit\2.0'),
            (1, r'Adobe\Launch\bridge\2.0'),
            (1, r'Adobe\*Creative Suite 3*'),
            (1, r'Adobe\*CS3*'),
            (1, r'Adobe\Plug-Ins\CS3'),
            (1, r'Adobe\TypeSupport\AMT'),
            (1, r'Adobe\TypeSupport\CMaps\AMT'),
            (1, r'Adobe\Color\AMT'),
            (1, r'Adobe\Adobe Anchor Service'),
            (1, r'Adobe\IconHandler'),
            (2, r'Adobe\Launch\acrobat\8.0'),
            (3, r'Adobe\Updater5'),
            (3, r'Adobe\Camera Raw 4'),
            (3, r'Adobe\DefaultLanguage'),
            (2, r'Adobe\PDFL\8.0'),
            (2, r'Adobe\backup'),
            (2, r'Adobe\backup_TechSupport'),
            (1, r'Adobe\Installers'),
            (3, r'Adobe\Help'),
            (3, r'Adobe\Acrobat'),
            (3, r'Adobe\Linguistics'),
            (3, r'Adobe\Plug-Ins'),
            (3, r'Adobe\Shell'),
            (3, r'Adobe\SING'),
            (3, r'Adobe\Templates'),
            (3, r'Adobe\XMP'),
            (4, r'Adobe\TypeSpt'),
            (4, r'Adobe\PDFL'),
            (4, r'Adobe\TypeSupport'),
            (4, r'Adobe\Color'),
            (4, r'Adobe\Fonts'),
            (4, r'Adobe'),
        ]

        commonFilesSubFiles = [
            (1, r'Adobe\EMLaunch.dll'),
            (1, r'Adobe\Installers\*Creative Suite 3*'),
            (1, r'Adobe\Installers\*CS3*'),
            (2, r'Adobe\backup\caps.db'),
        ]

        allUsersProfileSubDirs = [
            (1, r'Start Menu\Programs\Adobe*CS3*'),
            (1, r'Application Data\Adobe\*CS3*'),
            (2, r'Application Data\Adobe\Acrobat\8.0'),
            (2, r'Application Data\Adobe\Adobe PDF'),
            (3, r'Application Data\Adobe\Updater5'),
            (4, r'Start Menu\Programs\Adobe'),
            (4, r'Start Menu\Programs\Adobe Systems'),
            (4, r'Application Data\Adobe'),
            (4, r'Application Data\Adobe Systems'),
        ]

        allUsersProfileSubFiles = [
            (1, r'Start Menu\Programs\Adobe*CS3.lnk'),
            (1, r'Start Menu\Programs\Adobe Device Central.lnk'),
            (1, r'Start Menu\Programs\Adobe ExtendScript Toolkit2.lnk'),
            (1, r'Start Menu\Programs\Adobe ExtendScript Toolkit 2.lnk'),
            (1, r'Start Menu\Programs\Adobe Flash Video Encoder.lnk'),
            (1, r'Start Menu\Programs\Adobe Soundbooth.lnk'),
            (2, r'Start Menu\Programs\Startup\Adobe Acrobat Speed Launcher.lnk'),
            (2, r'Start Menu\Programs\Startup\Adobe Acrobat Synchronizer.lnk'),
            (2, r'Desktop\Adobe Acrobat 8 Professional.lnk'),
            (4, r'Start Menu\Programs\Adobe*'),
        ]

        userAppDataSubDirs = [
            (1, r'Adobe\*CS3*'),
            (1, r'Adobe\Photoshop\10.0'),
            (3, r'Adobe\CameraRaw'),
            (4, r'Adobe'),
        ]

        userAppDataSubFiles = [
        ]

        deleteRegKeys = [
            (1, r'Software\Adobe',                re.compile('.*CS3.*')),
            (1, r'Software\Adobe\Adobe Bridge',        'CS3'),
            (1, r'Software\Adobe\Dreamweaver',        '9'),
            (1, r'Software\Adobe\ExtendScript Toolkit',     '2.0'),
            (1, r'Software\Adobe\Flash',             '9.0'),
            (1, r'Software\Adobe\InCopy',             '5.0'),
            (1, r'Software\Adobe\InDesign',         '5.0'),
            (1, r'Software\Adobe\Photoshop',         '10.0'),
            (1, r'Software\Adobe\Premiere Pro',         '3.0'),
            (1, r'Software\Adobe',                 'MediaBrowser'),
            (1, r'Software\Adobe',                 'FLVEncoder2'),
            (2, r'Software\Adobe\Adobe Acrobat',         '8.0'),
            (2, r'Software\Adobe\Repair\Adobe Acrobat',     '8.0'),
            (2, r'Software\Adobe\Acrobat Distiller',     '8.0'),
            (2, r'Software\Adobe\Acrobat Elements',     '8.0'),
            (2, r'Software\Adobe\Acrobat PDFMaker',     '8.0'),
            (2, r'Software\Adobe\Acrobat Distiller',     '8.0'),
            (2, r'Software\Adobe\Designer',         '8.0'),
            (4, r'Software',                'Adobe'),
        ]

        # run unistallers and MSIZap.
        RemoveAllApplications(applist)

        if gScrubLevel == 1:
            #Adding another hack for fix for bug no#1513778
            #the folder called backup would be renamed to backup_TechSupport
            sourcepath = os.path.join(os.environ['CommonProgramFiles'], r'Adobe\backup')
            targetpath = os.path.join(os.environ['CommonProgramFiles'], r'Adobe\backup_TechSupport')
            DoRenameDir(sourcepath, targetpath)

        # rm -rf style deletions
        for installDir in gInstallDirs:
            RemoveSubDirsInList(installDir, installDirSubDirs)
        RemoveSubDirsInList(os.environ['CommonProgramFiles'], commonFilesSubDirs)
        RemoveSubDirsInList(os.environ['ALLUSERSPROFILE'], allUsersProfileSubDirs)
        RemoveSubDirsInList(os.environ['APPDATA'], userAppDataSubDirs);

        # file deletions
        for installDir in gInstallDirs:
            RemoveSubFilesInList(installDir, installDirSubFiles)
        RemoveSubFilesInList(os.environ['CommonProgramFiles'], commonFilesSubFiles)
        RemoveSubFilesInList(os.environ['ALLUSERSPROFILE'], allUsersProfileSubFiles)
        RemoveSubFilesInList(os.environ['APPDATA'], userAppDataSubFiles);

        for machinekey in [RegKey(None, 'HKLM'), RegKey(None, 'HKCU')]:
            RemoveRegKeysInList(machinekey, deleteRegKeys)

    def GetDefaultInstallDirs():
        return [os.environ['ProgramFiles']]

elif gPlatform == 'osx':
    def DoClean():
        installDirSubDirs = [
            (1, r'Adobe*CS3'),
            (1, r'Adobe Illustrator CS3'),
            (1, r'Adobe Help Viewer 1.0'),
            (1, r'Adobe InDesign CS3'),
            (1, r'Adobe Flash CS3'),
            (1, r'Adobe Photoshop CS3'),
            (1, r'Adobe After Effects CS3'),
            (1, r'Adobe Help Viewer *.app'),
            (1, r'Adobe Device Central'),
            (1, r'Adobe Dreamweaver 9'),
            (1, r'Adobe Extension Manager'),
            (1, r'Adobe Flash CS3 Video Encoder'),
            (1, r'Utilities/Adobe Installers'),
            (1, r'Utilities/Soundbooth'),
            (1, r'Utilities/Adobe Utilities.localized/ExtendScript Toolkit*2'),
            (2, r'Adobe Acrobat 8 Professional'),
            (3, r'Utilities/Adobe Utilities.localized/Adobe Updater5'),
            (4, r'Adobe*'),
            (4, r'Utilities/Adobe*'),
        ]

        fullDirPaths = [
            (1, r'~/Library/Logs/Adobe'),

            (1, r'~/Library/Application Support/Adobe/Common/9'),
            (1, r'~/Library/Application Support/Adobe/*CS3*'),
            (1, r'~/Library/Application Support/Adobe/Adobe Device Central'),
            (1, r'~/Library/Application Support/Adobe/Contribute CS3'),
            (1, r'~/Library/Application Support/Adobe/Dreamweaver*9'),
            (1, r'~/Library/Application Support/Adobe/Fireworks 9'),
            (1, r'~/Library/Application Support/Adobe/Flash Video Encoder'),
            (1, r'~/Library/Application Support/Adobe/Online Services/Adobe Creative Suite 3.0'),
            (1, r'~/Library/Application Support/Adobe/QuickTime'),
            (2, r'~/Library/Application Support/Adobe PDF'),
            (4, r'~/Library/Application Support/Macromedia*'),
            (4, r'~/Library/Application Support/Adobe*'),

            (2, r'~/Library/Preferences/Adobe Fireworks CS3'),
            (3, r'~/Library/Preferences/Adobe Illustrator CS3*'),
            (3, r'~/Library/Preferences/Fireworks 8'),
            (4, r'~/Library/Preferences/com.macromedia*'),
            (4, r'~/Library/Preferences/com.adobe*'),
            (4, r'~/Library/Preferences/Flash 8*'),
            (4, r'~/Library/Preferences/Flash8*'),
            (4, r'~/Library/Preferences/Adobe*'),

            (2, r'~/Library/Acrobat User Data/8.0*'),

            (1, r'/Library/Application Support/Adobe/caps'),
            (1, r'/Library/Application Support/Adobe/Adobe PCD'),
            (1, r'/Library/Application Support/Adobe/XMP/Custom File Info Panels/1.0'),
            (1, r'/Library/Application Support/Adobe/Adobe Anchor Service'),
            (1, r'/Library/Application Support/Adobe/Adobe Creative Suite 3 *'),
            (1, r'/Library/Application Support/Adobe/EMLaunch.bundle'),
            (1, r'/Library/Application Support/Adobe/Help'),
            (1, r'/Library/Application Support/Adobe/Installers'),
            (1, r'/Library/Application Support/Adobe/Plug-Ins/CS3'),
            (1, r'/Library/Application Support/Adobe/TypeSupport'),
            (1, r'/Library/Application Support/Adobe/Uninstall'),
            (2, r'/Library/Application Support/Adobe/backup_TechSupport'),
            (2, r'/Library/Application Support/Adobe/Acrobat'),
            (2, r'/Library/Application Support/Adobe/PDFL/8.0'),
            (2, r'/Library/Application Support/Adobe/Adobe PDF'),
            (3, r'/Library/Application Support/Adobe/Linguistics'),
            (3, r'/Library/Application Support/Adobe/SING/AssocCache'),
            (3, r'/Library/Application Support/Adobe/Color'),
            (3, r'/Library/Application Support/Adobe/Fonts'),
            (3, r'/Library/Application Support/Adobe/Updater5'),
            (4, r'/Library/Application Support/Adobe*'),
            (4, r'/Library/Application Support/Macromedia*'),

            (1, r'/Library/Application Support/Adobe/Launch/bridge/2.0'),
            (1, r'/Library/Application Support/Adobe/Launch/estk/2.0'),
            (1, r'/Library/Application Support/Adobe/Launch/incopy/5.0'),
            (1, r'/Library/Application Support/Adobe/Launch/indesign/5.0'),
            (1, r'/Library/Application Support/Adobe/Launch/photoshop/10.0'),
            (1, r'/Library/Application Support/Adobe/Launch/illustrator/13.0'),
            (1, r'/Library/Application Support/Adobe/Launch/Contribute 4.1'),
            (1, r'/Library/Application Support/Adobe/Launch/devicecentral'),
            (1, r'/Library/Application Support/Adobe/Launch/Flash'),
            (2, r'/Library/Application Support/Adobe/Launch/acrobat/8.0'),

            (4, r'/Library/Preferences/com.macromedia*'),
            (4, r'/Library/Preferences/com.adobe*'),

            (3, r'/Library/PreferencePanes/VersionCueCS3.prefPane'),
            (2, r'/Library/Internet\ Plug-Ins/AdobePDFViewer.plugin'),
            (4, r'/Library/Logs/Adobe'),
        ]

        fullFilePaths = [
            (1, r'/Library/Application Support/Adobe/SING/TINthread.dylib'),
            (1, r'/Library/Preferences/com.adobe.versioncueCS3.plist'),
            (2, r'/Library/Application Support/Adobe/backup/caps.db'),
            (2, r'/Library/Preferences/com.adobe.AdobePDFSettings.plist'),
            (3, r'/Library/LaunchDaemons/com.adobe.versioncueCS3.plist'),
            (1, r'~/Library/Preferences/com.Adobe.After Effects.8.0.plist'),
            (1, r'~/Library/Preferences/com.adobe.bridge2.plist'),
            (1, r'~/Library/Preferences/com.adobe.ExtensionManager.plist'),
            (1, r'~/Library/Preferences/com.adobe.Installers.Setup.plist'),
            (1, r'~/Library/Preferences/com.adobe.Contribute.plist'),
            (2, r'~/Library/Preferences/com.adobe.Acrobat.Pro_*_8.0.plist'),
            (2, r'~/Library/Preferences/com.adobe.Acrobat.Uninstaller.plist'),
            (2, r'~/Library/Preferences/Flash 9*'),
            (2, r'~/Library/Preferences/Flash9*'),
            (2, r'~/Library/Preferences/Flash CS3*'),
            (2, r'~/Library/Preferences/Adobe Photoshop CS3*'),

        ]

        # rm -rf style deletions

        if gScrubLevel == 1:
            sourcepath = os.path.join(r'/Library/Application Support/Adobe/backup')
            targetpath = os.path.join(r'/Library/Application Support/Adobe/backup_TechSupport')
            DoRenameDir(sourcepath,targetpath)

        for installDir in gInstallDirs:
            RemoveSubDirsInList(installDir, installDirSubDirs)


        for level, path in fullDirPaths:
            if gScrubLevel >= level:
                RemoveDirGlob(path)

        for level, path in fullFilePaths:
            if gScrubLevel >= level:
                RemoveFileGlob(path)

    def GetDefaultInstallDirs():
        return ['/Applications']
else:
    raise RuntimeError(GetStr('notifyUnsupportedPlatform'))

if __name__ == '__main__':
    gVerbose = False
    LogMessage(GetStr('notifyBeginBlock') % (gScriptname, time.ctime()))
    gInstallDirs= GetDefaultInstallDirs()

    ClearScreen()
    UserMessage(GetStr('appName') + ' v' + VERSION + '\n\n')

    gStringSet = GenericPromptUser('''\
Please choose a language:

    e: English
    j: Japanese (日本語)

>'''.decode('utf-8'), {'e':gEnglishStringSet, 'j':gJapaneseStringSet});

    ClearScreen()

    # get MsiZapPath
    if gPlatform == 'win':
        gMsiZapPath = GetMsiZapPath()

    if (not (YesNoPromptUser(GetStr('queryEULA')))):
        DoQuit()

    ClearScreen()

    if YesNoPromptUser(GetStr('queryWarnBackup')):
        DoQuit()

    ClearScreen()

    gScrubLevel = GenericPromptUserHidden(GetStr('queryChooseScrubbingLevel'), {'1':1, '2':2}, {'3':3, '4':4}, GetStr('msgScrubLevel') % (textwrap.fill(GetScrubLevelDesc(1), width=61), textwrap.fill(GetScrubLevelDesc(2), width=61)))

    ClearScreen()
    if YesNoPromptUser(GetStr('queryNonDefaultInstall')):
        while 1:
            response = GenericPromptUser(GetStr('queryAdditionalDir'), None, GetStr('notifyInstallDirs') % '\n\t'.join(gInstallDirs) )
            if response.lower() == 'skip':
                break
            if os.path.isdir(response):
                gInstallDirs.append(response)
            else:
                UserMessage(GetStr('notifyInvalidDir') % response)

    #ClearScreen()
    #gAutoConfirm = not YesNoPromptUser(GetStr('queryAskApproval'))
    gAutoConfirm = True
    ClearScreen()
    gPreview = YesNoPromptUser(GetStr('queryPreviewMode'))
    #ClearScreen()
    #gVerbose = YesNoPromptUser(GetStr('queryVerbose'))
    if gPlatform == 'win':
        ClearScreen()
        gBkpRegistry = YesNoPromptUser(GetStr('queryBackupRegistry'))

    ClearScreen()

    summary = GetStr('msgSummary1') % (gScrubLevel, textwrap.fill(GetScrubLevelDesc(gScrubLevel), width=35, subsequent_indent='\t\t\t\t'), BoolToString(gPreview), '\n                               '.join(gInstallDirs), gLogPath.decode(sys.getfilesystemencoding()))
    if gPlatform == 'win':
        summary += GetStr('msgSummary2') % (BoolToString(gBkpRegistry))
    if GenericPromptUser(GetStr('queryGo'), {'go':True,'quit':False}, summary):

        if gPlatform == 'win' and gBkpRegistry:
            bkppath = os.path.join(gScriptdir, 'RegBkp_%d'%int(time.time()))
            UserMessage(GetStr('notifyBeginRegBkp')% bkppath)
            SysCall('reg export HKLM "%s_HKLM.reg"' % bkppath)
            SysCall('reg export HKCU "%s_HKCU.reg"' % bkppath)
            UserMessage(GetStr('notifyEndRegBkp'))

        try:
            DoClean()
        except:

            type,value,tb = sys.exc_info()
            UserMessage(GetStr('notifyBeginExcTB'))
            UserMessage('\n'.join(traceback.format_exception(type, value, tb)))
            UserMessage(GetStr('notifyEndExcTB'))

        if gPreview:
            DoQuit(GetStr('notifyPreviewCompleted'))
        else:
            DoQuit(GetStr('notifyCompleted'))
About | Buy | Forum | Industry Watch | Learning Curve | Products | Search | Twitter | Xnews
Copyright © Rixstep. All rights reserved.