吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2028|回复: 8
收起左侧

[求助] 有两个反编译后的Python文件,求教师傅如何返回时间无限?

[复制链接]
冥界3大法王 发表于 2020-9-14 12:19
2020-09-14_121820.gif

[Python] 纯文本查看 复制代码
#! /usr/bin/env python 2.7 (62211)
#coding=utf-8
# Compiled at: 2020-07-13 15:50:03
#Powered by BugScaner
#[url]http://tools.bugscaner.com/[/url]
#如果觉得不错,请分享给你朋友使用吧!
""" process/abstract.py -- License manager support
 
Copyright (c) 1999-2012, Archaeopteryx Software, Inc.  All rights reserved.
 
"""
from __future__ import absolute_import
from __future__ import print_function
import sys, os, time, socket, tempfile, random, marshal, binascii, new, sha, logging, urllib, urllib2
logger = logging.getLogger('general')
from wingbase import destroyable
from wingbase import spawn
from wingbase import location
from wingutils import hostinfo
from wingutils import textio
from wingbase import textutils
from wingbase import fileutils
import config
from . import _
kHashLicenseFields = [
 'license', 'termdays', 'usercount', 'product', 'version', 'os',
 'restrictions', 'hostinfo']
kRequiredLicenseFields = kHashLicenseFields + ['date', 'customerdata', 'activation']
kLicenseUseCodes = [
 'T',
 'N',
 'E',
 'C',
 '6',
 'Y',
 'H']
kLicenseProdCodes = {config.kProd101: '1', 
   config.kProdPersonal: 'L', 
   config.kProdProfessional: 'N'}
kLicenseProdCode = kLicenseProdCodes[config.kProductCode]
kLicenseProdForCode = {}
for prod, code in kLicenseProdCodes.items():
    kLicenseProdForCode[code] = prod
 
kOSRequestCodes = {'win32': 'W', 
   'linux': 'L', 
   'darwi': 'M', 
   'sunos': 'N', 
   'freeb': 'F', 
   'tru64': 'T', 
   'netbs': 'E', 
   'openb': 'B'}
kVersionRequestCodes = {'2': 'X', 
   '3': '3', 
   '4': '4', 
   '5': '5', 
   '6': '6', 
   '7': '7', 
   '8': '8'}
kRequestVersionCode = kVersionRequestCodes[config.kVersion[:config.kVersion.find('.')]]
if sys.platform.startswith('linux') and os.uname()[4] in ('ppc', 'ppc64'):
    kRequestPrefix = 'RP' + kRequestVersionCode
else:
    kRequestPrefix = 'R' + kOSRequestCodes[sys.platform[:5]] + kRequestVersionCode
kActivationPrefix = 'AXX'
kHyphens = (u'-', u'\u2012', u'\u2013', u'\u2014', u'\u2015', u'\u2010', u'\u2212')
 
def LoadFromDat(filename, modname):
    """ Load code from pycontrol.dat file into a module -- this allows us 
    to do some weak code hiding. """
    file = open(filename, 'rb')
    try:
        dict = marshal.load(file)
    finally:
        file.close()
 
    if type(dict) != type({}):
        raise SystemExit(-1)
    mco = dict.get(sys.hexversion & 4294901760L)
    if mco is None:
        raise SystemExit(-1)
    co = marshal.loads(mco)
    mod = new.module(modname)
    exec co in mod.__dict__
    return mod
 
 
if sys.platform[:5] in ('win32', 'darwi') or sys.platform[:5] == 'linux' and os.uname()[4] not in ('ppc',
                                                                                                   'ppc64',
                                                                                                   'arm7l'):
    from . import ctlutil as control
else:
    try:
        from . import pycontrol as control
    except ImportError:
        dirname = os.path.dirname(__file__).replace('.zip', '')
        control = LoadFromDat(fileutils.join(dirname, 'pycontrol.dat'), 'pycontrol')
 
bulkctl = None
kLicenseOK = 1
kLicenseNotFound = 2
kLicenseCorrupt = 3
kLicenseExpired = 4
kLicenseTooManyUsers = 5
kLicenseInternalError = 6
kLicenseWrongPlatform = 7
kLicenseWrongProduct = 8
kLicenseHostMismatch = 9
 
def CreateTrialLicenseDict():
    """ Create license dict with given information for the current
    machine.  The "activation" field is omitted and needs to be
    added in a separate step before writing license to disk.  Note
    that trial licenses are unique to product level and version,
    as well as factoring in machine identity."""
    host = hostinfo.GetHostID()
    shost = hostinfo.SecureHostID(host, (kRequestVersionCode,))
    license = AddHyphens('T' + kLicenseProdCode + 'X' + textutils.SHAToBase30(shost))
    return CreateLicenseDict(license)
 
 
def CreateLicenseDict(license):
    """ Create license dict with given information for the current
    machine.  The "activation" field is omitted and needs to be
    added in a separate step before writing license to disk. """
    lic = {}
    vparts = config.kVersion.split('.')
    version = vparts[0] + '.*'
    termdays = '*'
    if license.startswith('Y') or license.startswith('H'):
        termdays = 0
        restrictions = 'Expiring annual license'
    else:
        if license.startswith('6'):
            termdays = 0
            restrictions = 'Expiring restricted use license'
        else:
            if license.startswith('T'):
                restrictions = 'Evaluation use only'
                termdays = 11
            else:
                if license.startswith('N'):
                    restrictions = 'Educational use only'
                else:
                    if license.startswith('E'):
                        restrictions = 'Non-commercial use  only'
                    else:
                        restrictions = 'None'
    lic['license'] = license
    lic['date'] = time.strftime('%m/%d/%y', time.localtime(time.time()))
    lic['termdays'] = termdays
    lic['usercount'] = 1
    lic['product'] = config.k_WingideNameMap[config.kProductCode]
    lic['version'] = version
    config._os = ''
    lic['os'] = control.get_os()
    lic['os'] = config._os
    lic['restrictions'] = restrictions
    lic['hostinfo'] = hostinfo.GetHostID()
    lic['customerdata'] = ''
    return lic
 
 
def ReadLicenseDict(filename):
    """ Read license file into a dict of values """
    iomgr = textio.CTextIOManager()
    reader = textio.CFileReader(iomgr)
    try:
        try:
            layers = reader.Read(location.CreateFromName(filename))
        except:
            return
 
        if len(layers) != 1:
            return
        items = layers[0].GetValueItems()
        lic = dict(items)
    finally:
        iomgr.destroy()
 
    if lic.has_key('hostinfo'):
        hostid = lic['hostinfo']
        try:
            hostid = textutils.BaseConvert(hostid, textutils.BASEMAX, textutils.BASE16).lower()
            hostid = binascii.unhexlify(hostid)
            hostid = marshal.loads(hostid)
        except:
            hostid = {}
 
        lic['hostinfo'] = hostid
    lic['filename'] = filename
    return lic
 
 
def WriteLicenseDict(filename, license, ignore=()):
    """ Write license file from a dict of values """
    errs = []
    for key in kRequiredLicenseFields:
        if not license.has_key(key) and key not in ignore:
            errs.append(_('License missing required %s') % key)
 
    license = license.copy()
    hostid = license['hostinfo']
    try:
        hostid = marshal.dumps(hostid)
        hexhostid = binascii.hexlify(hostid).upper()
        license['hostinfo'] = textutils.BaseConvert(hexhostid, textutils.BASE16, textutils.BASEMAX)
    except:
        errs.append(_('Failed to package host information'))
 
    if len(errs) > 0:
        return errs
    for key in license.keys():
        if key not in kRequiredLicenseFields:
            del license[key]
 
    lic = license['license']
    if lic[2] in 'LWM':
        lic = RemoveHyphens(lic)
        lic = lic[:10] + 'XXXXXXXXXX'
        license['license'] = AddHyphens(lic)
    header = ('# Wing license file', '# Editing this file will invalidate your license')
    iomgr = textio.CTextIOManager()
    writer = textio.CFileWriter(iomgr)
    layer = textio.CTextIOValueLayer(iomgr)
    layer.SetValuesFromDict(license)
    try:
        try:
            if os.path.exists(filename):
                os.chmod(filename, 384)
            errs = writer.Write(location.CreateFromName(filename), [
             layer], header)
        except:
            return [
             'Exception while writing license file']
 
        if len(errs) > 0:
            return errs
        os.chmod(filename, 256)
    finally:
        iomgr.destroy()
 
    return []
 
 
def CreateActivationRequest(license):
    """Create hash value from license that can be shipped to the license
    activation server"""
    license = license.copy()
    hostid = license['hostinfo']
    hostid = marshal.dumps(hostid)
    hexhostid = binascii.hexlify(hostid).upper()
    license['hostinfo'] = textutils.BaseConvert(hexhostid, textutils.BASE16, textutils.BASEMAX)
    hasher = sha.new()
    for key in kHashLicenseFields:
        if license['termdays'] != '*' and license['license'][0] != 'T' and key == 'termdays':
            continue
        value = license[key]
        if bulkctl is not None and key == 'license' and value[2] not in '123456789' and value.replace('-', '')[10:] == 'XXXXXXXXXX':
            lic = RemoveHyphens(value)
            value = lic[:10] + bulkctl._hash30(lic[:10])[:10]
            value = AddHyphens(value)
        hasher.update(str(value))
 
    if license['termdays'] != '*':
        hasher.update(str(license['date']))
    digest = hasher.hexdigest().upper()
    return AddHyphens(kRequestPrefix + textutils.SHAToBase30(digest))
 
 
def AddHyphens(code):
    """Insert hyphens into given license id or activation request to
    make it easier to read"""
    return code[:5] + '-' + code[5:10] + '-' + code[10:15] + '-' + code[15:]
 
 
def RemoveHyphens(code):
    """Remove hyphens from given license id or activation request"""
    for hyphen in kHyphens:
        code = code.replace(hyphen, '')
 
    return code
 
 
def __ValidateAndNormalize(code):
    """Remove hyphens and extra space/chars in a license id or activation
    request, and validate it as within the realm of possibility.  Returns
    errs, value."""
    errs = []
    code = code.strip().upper()
    code2 = ''
    badchars = set()
    for c in code:
        if c in (' ', '\t', u'\xa0') + kHyphens:
            pass
        elif c not in textutils.BASE30:
            code2 += c
            badchars.add(c)
        else:
            code2 += c
 
    if badchars:
        try:
            badchars = ('').join(badchars)
        except:
            badchars = '<could decode="" not="">'
 
        errs.append(_('Contains invalid characters: %s') % str(badchars))
    if len(code2) != 20:
        errs.append(_('Wrong length (should contain 20 non-hyphen characters)'))
    if len(errs) > 0:
        return (errs, code2)
    return ([], AddHyphens(code2))
 
 
def ValidateAndNormalizeLicenseID(id):
    errs, id2 = __ValidateAndNormalize(id)
    if len(id2) > 0 and id2[0] not in kLicenseUseCodes:
        errs.append(_('Invalid first character: Should be one of %s') % str(kLicenseUseCodes))
    if len(id2) > 1 and id2[1] != kLicenseProdCode:
        cur_product = 'Wing %s' % config.kProduct
        lic_product = kLicenseProdForCode.get(id2[1], None)
        if lic_product is None:
            lic_product = _('an unknown product')
        else:
            lic_product = 'Wing %s' % config.kProductNames[lic_product]
        errs.append(_('Your license is for %s, but you are currently running %s.  Please download the correct product from [url]https://wingware.com/downloads[/url] or upgrade your license at [url]https://wingware.com/store/upgrade'[/url]) % (
         lic_product, cur_product))
    if len(errs) > 0:
        return (errs, None)
    return ([], id2)
    return
 
 
def ValidateAndNormalizeRequest(id):
    errs, id2 = __ValidateAndNormalize(id)
    if len(errs) == 0:
        if id2[0] != 'R':
            errs.append(_('Request code should start with R'))
        if id2[1] not in kOSRequestCodes.values():
            errs.append(_('Invalid second character:  Should be one of %s') % str(kOSRequestCodes.values()))
        if id2[2] not in kVersionRequestCodes.values():
            errs.append(_('Invalid third character:  Should be one of %s') % str(kVersionRequestCodes.values()))
    if len(errs) > 0:
        return (errs, None)
    return ([], id2)
    return
 
 
def ValidateAndNormalizeActivation(id):
    errs, id2 = __ValidateAndNormalize(id)
    if id2[:3] != kActivationPrefix:
        errs.append(_("Invalid prefix:  Should be '%s'") % kActivationPrefix)
    if len(errs) > 0:
        return (errs, None)
    return ([], id2)
    return
 
 
class CLicenseManager(destroyable.CDestroyable):
    kWebAPIKey = 'AE7B2181D1B3E4657F2AD63E17708BE8'
 
    def __init__(self):
        """ Constructor """
        destroyable.CDestroyable.__init__(self, ('license-ok', ))
        self.fLicenseData = None
        self.fLicenseFile = None
        self.__fLicense = None
        self._fStartTime = time.time()
        return
 
    def _destroy_impl(self):
        """ Explicit destructor (needed to break circular refs) """
        self.__ReleaseLicense()
 
    def LicenseOK(self):
        """ Convenience function for checking license at key points.  Returns
        1 if OK and 0 if not but not detailed info """
        if not config.kAvailProfessionalSupport:
            return 1
        if self.__fLicense == None:
            return 0
        return 1
 
    def UseLicense(self, filename):
        """ Checks for valid license contained in the given filename.  If license
        is found and is valid, it is set as the license to use.  Returns status, info
        tuple.
         
        The second part of the returned tuple is extra error info.  Currently
        this is only used for some error messages as follows (None for those
        not listed).
         
        kLicenseOK            -- Tuple of users currently using the license, 
                                 in addition to the this user:  (host, 
                                 uid, user name, process id)
         
        kLicenseTooManyUsers  -- Same
         
        kLicenseCorrupt       -- String with detail
         
        kLicenseWrongPlatform -- String with detail
         
        kLicenseWrongProduct  -- String with detail
         
        """
        lic = ReadLicenseDict(filename)
        if lic == None:
            return (kLicenseNotFound, None)
        status = self.__GrabLicense(lic, filename)
        return status
 
    def _StatusToErrString(self, status):
        """ Convert status indicator to list of error strings for user """
        retval = []
        if status[0] == kLicenseOK:
            retval.append(_('License is valid.'))
            self.__AppendUserInfo(status, retval)
        else:
            if status[0] == kLicenseNotFound:
                retval.append(_('License file not found or could not be read.'))
            else:
                if status[0] == kLicenseCorrupt:
                    retval.append(_('Activation key not valid for this license:'))
                    retval.append(status[1])
                else:
                    if status[0] == kLicenseExpired:
                        retval.append(_('The license has expired.'))
                    else:
                        if status[0] == kLicenseTooManyUsers:
                            retval.append(_('The maximum number of users for this license has been reached.'))
                            self.__AppendUserInfo(status, retval)
                        else:
                            if status[0] == kLicenseWrongPlatform:
                                retval.append(_('License OS does not match current OS.'))
                                retval.append(status[1])
                            else:
                                if status[0] == kLicenseWrongProduct:
                                    retval.append(_('License does not match this product or product level.'))
                                    retval.append(status[1])
                                else:
                                    if status[0] == kLicenseHostMismatch:
                                        retval.append(_("License does not match this host's identity."))
                                    else:
                                        if status[0] == kLicenseInternalError:
                                            retval.append(_('An internal error occurred:'))
                                            retval.append(status[1])
                                        else:
                                            print('UNKNOWN LICENSE ERR', status)
                                            import traceback
                                            traceback.print_stack()
                                            retval.append(_('Unknown error'))
        return retval
 
    def __AppendUserInfo(self, status, retval):
        """ Add user info list to given string; should only be called with
        status kLicenseOK or kLicenseTooManyUsers """
        if len(status[1]) > 0:
            retval.append(_('Other users are:'))
            for host, ipaddr, uid, name, pid in status[1]:
                retval.append(_('(%s) on host %s (%s) process id %s') % (uid, host, ipaddr, pid))
 
        else:
            retval.append(_('No other users at this time.'))
        return retval
 
    def ValidateLicense(self, filename):
        """ Checks the license in given file for validity and availability """
        if not os.path.isfile(filename):
            return (kLicenseNotFound, None)
        lic = ReadLicenseDict(filename)
        if lic == None:
            return (kLicenseNotFound, None)
        license_check = self._ValidateLicenseDict(lic, filename)
        return license_check
 
    def _ValidatePlatform(self, license, license_os):
        """ Check license os; by default we require oss to match
        but descendents can override.  Should return (err, msg) tuple. """
        if license[2] == 'L':
            license_os = 'linux'
        else:
            if license[2] == 'W':
                license_os = 'windows'
            else:
                if license[2] == 'M':
                    license_os = 'macosx'
                config._os = ''
                cur_os = control.get_os()
                cur_os = config._os
                if cur_os == 'INVALID':
                    return (kLicenseWrongPlatform, _("Current OS '%s' is not supported") % cur_os)
            if not cur_os.lower().startswith(license_os.lower()):
                return (kLicenseWrongPlatform,
                 _("License OS '%s' does not match current OS '%s'") % (
                  license_os, cur_os))
        return (None, None)
 
    def _ValidateProduct(self, license_product):
        """ Check license product: By default we just accept it but descendents 
        can override this. Should return (err, msg) tuple. """
        return (None, None)
 
    def _ValidateVersion(self, license_version):
        """ Check license version: By default we just accept it but descendents 
        can override this. Should return (err, msg) tuple. """
        return (None, None)
 
    def _GetTermDaysLeft(self, lic=None):
        """ Get number of days left on license.  Returns the days, or 0 if expired,
        -1 if unlimited, or -2 on error """
        if lic is None:
            lic = self.fLicenseData
        if lic is None:
            return 0
        if lic['termdays'] != '*':
            try:
                fields = lic['date'].split('/')
                if len(fields) != 3:
                    raise ValueError
                m, d, y = [ int(s) for s in fields ]
                if m < 1 or m > 12 or d < 1 or d > 31 or y < 0:
                    raise ValueError
                if y < 100:
                    y = 2000 + y
                lic_date = time.mktime((y, m, d, 0, 0, 0, 0, 0, -1))
            except (ValueError, TypeError, OverflowError):
                return -2
 
            cur_date = time.time()
            try:
                lic_secs = int(lic['termdays']) * 24 * 60 * 60
            except ValueError:
                return -2
 
            if cur_date > lic_date + lic_secs:
                return 0
            if lic_date > cur_date + 86400:
                return 0
            return int((lic_secs - (cur_date - lic_date)) / 86400)
        return -1
        return
 
    def _ValidateLicenseDict(self, lic, filename):
        """ Check license for internal integrity and expiration """
        lic['daysleft'] = _('expired')
        for key in kRequiredLicenseFields:
            if not lic.has_key(key):
                return (kLicenseCorrupt, _('Missing a required line %s') % key)
 
        err, msg = self._ValidatePlatform(lic['license'], lic['os'])
        if err != None:
            return (err, msg)
        err, msg = self._ValidateProduct(lic['product'])
        if err != None:
            return (err, msg)
        err, msg = self._ValidateVersion(lic['version'])
        if err != None:
            return (err, msg)
        try:
            lichash = CreateActivationRequest(lic)
            act30 = lic['activation']
            hasher = sha.new()
            hasher.update(lichash)
            hasher.update(lic['license'])
            if lic['termdays'] != '*' and lic['license'][0] != 'T':
                termdays_base30 = textutils.BaseConvert(lic['termdays'], textutils.BASE10, textutils.BASE30)
                while len(termdays_base30) < 2:
                    termdays_base30 = '1' + termdays_base30
 
                hasher.update(termdays_base30)
            digest = hasher.hexdigest().upper()
            lichash = lichash[:3] + textutils.SHAToBase30(digest)
            errs, lichash = ValidateAndNormalizeRequest(lichash)
            act = act30.replace('-', '')[3:]
            hexact = textutils.BaseConvert(act, textutils.BASE30, textutils.BASE16)
            while len(hexact) < 20:
                hexact = '0' + hexact
 
            config._locale_valid = 0
            valid = control.validate(lichash, lic['os'], lic['version'][:lic['version'].find('.')], hexact)
            valid = config._locale_valid
        except:
            valid = 0
 
        if not valid:
            return (kLicenseCorrupt, _('Invalid license activation'))
        daysleft = self._GetTermDaysLeft(lic)
        if daysleft == -1:
            lic['daysleft'] = _('unlimited')
        else:
            if daysleft == -2:
                return (kLicenseCorrupt, _('Invalid date or termdays in file'))
            if daysleft == 0:
                return (kLicenseExpired, None)
            if daysleft > 12 and lic['license'][0] == 'T':
                return (kLicenseCorrupt, _('Invalid date or termdays in file'))
            lic['daysleft'] = str(daysleft) + _(' days left')
        errs = hostinfo.IDMatch(lic['hostinfo'])
        if len(errs) > 0:
            return (kLicenseHostMismatch, None)
        return (
         kLicenseOK, [])
 
    def _DeactivateLicense(self):
        """Deactivate the current license, if any, by unloading it and
        removing the activation file from disk.  Returns (success,
        filename) where filename is None or the license.act file name,
        if any."""
        license = self.fLicenseData.get('license', '')
        if license.startswith('T'):
            return (False, None)
        filename = self.fLicenseData.get('filename', None)
        if filename:
            try:
                if sys.platform == 'win32':
                    os.chmod(filename, 438)
                os.remove(filename)
            except:
                return (
                 False, filename)
 
            self.__ReleaseLicense()
            return (
             True, filename)
        return (
         False, None)
 
    def __GrabLicense(self, lic, filename):
        """ Grab one user slot in the given license, if available and
        not exceeding allowed number of users """
        status, info = self._ValidateLicenseDict(lic, filename)
        if status != kLicenseOK:
            return (status, info)
        self.__ReleaseLicense()
        self.__fLicense = lic['license']
        self.fLicenseData = lic
        self.fLicenseFile = filename
        self.emit('license-ok')
        return (
         kLicenseOK, info)
 
    def __ReleaseLicense(self):
        """ Release one users slot in current in-use license """
        if self.__fLicense == None:
            return
        self.__fLicense = None
        self.fLicenseData = None
        self.fLicenseFile = None
        return</could>





[Python] 纯文本查看 复制代码
#! /usr/bin/env python 2.7 (62211)
#coding=utf-8
# Compiled at: 2020-07-13 15:49:57
#Powered by BugScaner
#[url]http://tools.bugscaner.com/[/url]
#如果觉得不错,请分享给你朋友使用吧!
""" process/wingctl.py -- Wing-specific license manager
 
Copyright (c) 1999-2012, Archaeopteryx Software, Inc.  All rights reserved.
 
"""
from __future__ import absolute_import
from __future__ import print_function
import sys, os, sha, shutil, time, traceback, urllib2, urllib, logging
logger = logging.getLogger('general')
from wingbase import fileutils
from wingutils import datatype
from wingbase import textutils
from wingbase import destroyable
from wingutils import reflect
from wingutils import urlutils
from guiutils import wgtk
from guiutils import widgets
from guiutils import dialogs
from guiutils import hypertext
from guiutils import formbuilder
import config, mainprefs, singleton
from guimgr import messages
from . import abstract
from . import _
kAccept = _('_Accept')
kDecline = _('_Decline')
 
def _ErrorDlg(title, msg, extra_buttons=[], sheet=True, parent=None, silent=False):
    if silent:
        print(title, '::', msg)
        return
    buttons = list(extra_buttons)
    buttons.append(dialogs.CButtonSpec(_('_OK'), None, wgtk.STOCK_OK))
    dlg = messages.CMessageDialog(singleton.GetSingletons(), title, msg, [], buttons)
    dlg.AllowSheetWindow(sheet)
    dlg.RunAsModal(parent)
    return
 
 
class CWingLicenseManager(abstract.CLicenseManager):
    """ Specialization of the generic license manager for use in Wing """
 
    def __init__(self, singletons):
        """ Constructor """
        abstract.CLicenseManager.__init__(self)
        self.fSingletons = singletons
        self._fExpiringLicenseCheck = False
        self.__fObtainLicenseDialog = None
        self._fPromptForSaveDialog = False
        self.__fAutoActivator = None
        self.__fTriedAutoReactivate = False
        self.__fLastSkipNotify = 0
        return
 
    def LicenseCheck(self, force=False, try_auto=True):
        """ Check whether the license being used is valid, and obtain one if not.
        Only tries to obtain or show expiration dialog if force is true or Wing
        has been running for more than ten minutes."""
        try:
            valid = self.LicenseOK()
            if not valid:
                valid = self.__FindLicenseFile()
            if not force and time.time() - self._fStartTime < 10 * 60:
                return True
            if not valid:
                self._ObtainLicense(try_auto)
            else:
                if config.kAvailProfessionalSupport:
                    self.__CheckExpiringLicense()
        finally:
            return True
 
    def __CheckForPriorAcceptance(self, eula_text, current_filename):
        """ Check if EULA was accepted.  Checks current filename if it exists
        or filename from the last version that exists """
 
        def check(accepted_filename):
            digest = self.__CalcEULADigest(accepted_filename, eula_text)
            if digest is None:
                return False
            try:
                file = open(accepted_filename, 'rb')
                try:
                    data = file.read()
                finally:
                    file.close()
 
                return bool(data == digest)
            except:
                return False
 
            return
 
        if os.path.isfile(current_filename):
            return check(current_filename)
        parts = config.kVersion.split('.')
        filename_parts = current_filename.split('.')
        if len(parts) == 0 or len(filename_parts) == 0 or parts[-1] != filename_parts[-1]:
            return False
        try:
            micro = int(parts[-1])
        except Exception:
            return False
 
        micro -= 1
        while micro >= 0:
            prior_filename = ('.').join(filename_parts[:-1] + [str(micro)])
            if os.path.isfile(prior_filename):
                return check(prior_filename)
            micro -= 1
 
        return False
 
    def AcceptEULA(self, force=False):
        """ Ask user to accept the EULA if not already done in the past. If not
        accepted, the application exits. If accepted, a flag file is created 
        and user is not asked if that file already exists and is older than
        the license file.  Use force = True to always display the dialog """
        user_dir = config.kUserSettings
        accept_file = config.kAcceptedEULAFile
        licfile = config.GetWingFilename('LICENSE.txt')
        accepted_filename = os.path.normpath(fileutils.join(user_dir, accept_file))
        if config.kPlatform == 'win32':
            accepted_filename = accepted_filename.lower()
        try:
            eula_file = open(licfile, 'r')
            try:
                eula_text = eula_file.read()
            finally:
                eula_file.close()
 
        except:
            wgtk.HideSplashScreen()
            msg = _('Unable to read End User License Agreement from %s. Please check your Wing installation.') % licfile
 
            def exit_cb():
                sys.exit(0)
 
            buttons = [dialogs.CButtonSpec(_('_Exit Wing'), exit_cb, wgtk.STOCK_CANCEL)]
            dlg = messages.CMessageDialog(self.fSingletons, _('Unable to read EULA'), msg, [], buttons)
            dlg.AllowSheetWindow(False)
            dlg.BlockingRunAsModal()
            return
 
        if not force and self.__CheckForPriorAcceptance(eula_text, accepted_filename):
            return
        accepted = {'accepted': False}
 
        def accept_cb():
            accepted['accepted'] = True
            digest = self.__CalcEULADigest(accepted_filename, eula_text)
            if digest is not None and os.path.isdir(user_dir):
                file = open(accepted_filename, 'wb')
                try:
                    file.write(digest)
                finally:
                    file.close()
 
            wgtk.UnHideSplashScreen()
            return
 
        def decline_cb():
            accepted['accepted'] = False
 
        wgtk.HideSplashScreen()
        text_styles = {}
        dlg = CEULADialog(self.fSingletons.fWinMgr, text_styles, eula_text, accept_cb, decline_cb)
        dlg.BlockingRunAsModal()
        if not accepted['accepted']:
            sys.exit(0)
 
    def _ValidateProduct(self, license_product):
        """ Check license product: By default we just accept it but descendents 
        can override this. Should return (err, msg) tuple. """
        cur_product = config.kProductCode
        lic_product = config.k_WingideNameToCodeMap.get(license_product, None)
        if lic_product == None:
            return (abstract.kLicenseCorrupt, _("License product '%s' is not a valid product code.") % license_product)
        if cur_product > lic_product:
            cur_prod_name = config.kProductNames[cur_product]
            lic_prod_name = config.kProductNames[lic_product]
            return (
             abstract.kLicenseWrongProduct,
             _('License is for Wing %s and cannot be used with Wing %s') % (lic_prod_name, cur_prod_name))
        return (None, None)
 
    def _ValidateVersion(self, license_version):
        """ Check license version: By default we just accept it but descendents 
        can override this. Should return (err, msg) tuple. """
        lic_maj, lic_min = license_version.split('.')
        prd_maj, prd_min, prd_rel = config.kVersion.split('.')
        if lic_maj < prd_maj:
            return (abstract.kLicenseWrongProduct,
             _('License is for version %s:  An upgrade is needed to run %s') % (license_version, config.kVersion))
        return (None, None)
        return
 
    def __TryLicenseFiles(self, basename):
        """Try to use the license in given license file or any additional
        activations associated with it.  Prefers valid purchased licenses
        over any found trial licenses."""
        act_file = basename
        errors = []
        dirname, filename = os.path.split(basename)
        candidates = os.listdir(dirname)
        candidates.sort()
        valid_trials = []
        for c in candidates:
            act_file = fileutils.join(dirname, c)
            if c.startswith(filename) and os.path.isfile(act_file):
                status, info = self.UseLicense(act_file)
                if status == abstract.kLicenseOK:
                    lic = abstract.ReadLicenseDict(act_file)
                    if lic['license'].startswith('T'):
                        valid_trials.append(act_file)
                    else:
                        return (
                         True, errors)
                else:
                    act_errors = self._StatusToErrString((status, info))
                    if len(act_errors) > 0:
                        act_errors.insert(0, act_file)
                        errors.extend(act_errors)
 
        if len(valid_trials) > 0:
            status, info = self.UseLicense(valid_trials[-1])
            return (
             True, errors)
        return (
         False, errors)
 
    def __FindLicenseFile(self):
        """Find valid license file, first looking in the given user
        directory for a license file and then in the global directory.
        Returns True if a valid license file is found."""
        user_file = os.path.normpath(fileutils.join(config.kUserSettings, 'license.act'))
        success, user_errors = self.__TryLicenseFiles(user_file)
        if success:
            return True
        global_file = os.path.normpath(config.GetWingFilename('license.act'))
        success, global_errors = self.__TryLicenseFiles(global_file)
        if success:
            return True
        if len(global_errors) > 0:
            user_errors.extend(global_errors)
        user_errors.insert(0, _('No valid license file was found.  The following errors occurred:'))
        logger.warn(('\n').join(user_errors))
        return False
 
    def __OKToCheckExpiration(self, lic_type):
        """Return True if OK to check expiration of given license type.  We only
        remind of the expiration date once a day for paid annual licenses and
        expiring free licenses.  Otherwise we remind once per session."""
        if lic_type not in 'YH6':
            return True
        timestamp_file = os.path.join(config.kUserSettings, 'last-expire-check')
        if os.path.exists(timestamp_file):
            try:
                f = open(timestamp_file)
                try:
                    txt = f.readline()
                finally:
                    f.close()
 
                last = float(txt.strip())
                if last > time.time():
                    last = 0
                if time.time() < last + 86400:
                    if time.time() - self.__fLastSkipNotify > 3600:
                        print('Skipping expiring license check -- done too recently')
                        self.__fLastSkipNotify = time.time()
                    return False
            except:
                print('Skipping expiring license check -- corrupt stamp file')
                reflect.ReportCurrentException(suppress_gui=True)
                try:
                    os.unlink(timestamp_file)
                except:
                    print('Cannot remove corrupted time stamp file', timestamp_file)
                    reflect.ReportCurrentException(suppress_gui=True)
 
                return False
 
        txt = str(int(time.time())) + '\n'
        try:
            f = open(timestamp_file, 'w')
            try:
                f.write(txt)
            finally:
                f.close()
 
        except IOError:
            reflect.ReportCurrentException(suppress_gui=True)
 
        return True
 
    def __TryAutoReactivate(self, license):
        """Try to reactivate an expiring annual license, in case it's already been renewed.
        Returns True if an auto reactivation attempt is initiated."""
        if license is None:
            return False
        if license[0] not in 'YH':
            return False
        if self.__fTriedAutoReactivate:
            return False
        self.__fTriedAutoReactivate = True
        if self.__fAutoActivator is not None:
            return False
        print('Attempting auto-reactivation of annual license', license)
        self.__fAutoActivator = CActivator(self.fSingletons, silent=True)
        lic = abstract.CreateLicenseDict(license)
        request = abstract.CreateActivationRequest(lic)
        self.__fAutoActivator.StartActivation(lic, request)
 
        def retry_autoactivate():
            print('Running hourly attempt to auto-reactivate annual license', license)
            self.__fTriedAutoReactivate = False
            self.__TryAutoReactivate(license)
            return False
 
        def failed():
            print('Failed auto-reactivation of annual license', license)
            print('Will retry in 1 hour')
            wgtk.timeout_add_while_alive(3600000, retry_autoactivate, self)
 
        def complete():
            self.__fAutoActivator.destroy()
            self.__fAutoActivator = None
            self.__CheckExpiringLicense(force=True)
            return
 
        self.__fAutoActivator.connect_while_alive('connect-failed', failed, self)
        self.__fAutoActivator.connect_while_alive('complete', complete, self)
        return True
 
    def __CheckExpiringLicense(self, force=False):
        """ Alert user once that they are using an expiring license """
        if self._fExpiringLicenseCheck:
            return
        daysleft = self._GetTermDaysLeft()
        if self.fLicenseData is not None:
            txt = self.fLicenseData.get('license', None)
        else:
            txt = None
        if txt is not None and txt[0] == '6':
            if daysleft > 30:
                return
        else:
            if txt is not None and txt[0] in 'YH':
                if daysleft > 45:
                    return
            else:
                if daysleft <= 0 or daysleft > 10:
                    return
        if not force and txt is not None and not self.__OKToCheckExpiration(txt[0]):
            return
        if not force and self.__TryAutoReactivate(txt):
            return
        if config.kSteam:
            title = _('Wing Pro Trial: %i Days Left') % daysleft
        else:
            title = _('Wing Pro License Expiring: %i Days Left') % daysleft
        purchase_info = _('If you are ready, please purchase a license at %s.') % config.kStoreURL
        thanks = _('Thanks for using Wing Pro!')
        purchase_label = _('_Purchase License')
        if txt is not None and txt[0] in 'YH':
            msg = _('This annual license will expire in %s days.') % str(daysleft)
            msg += '  ' + _('You can renew at [url]https://wingware.com/store/upgrade/license-ids=%s.'[/url]) % txt
            msg += '  ' + _('If you have already renewed, Wing failed to auto-activate the renewal and will try again later.')
            msg += '\n\n' + thanks
            purchase_label = _('_Renew License')
        else:
            if txt is not None and txt[0] == '6':
                msg = _('The free license you are using will expire in %s days.') % str(daysleft)
                msg += '  ' + _('If you still qualify for a free license, you may reapply at [url]https://wingware.com/store/free.'[/url])
                msg += '  ' + _('Otherwise, please purchase a license at %s') % config.kStoreURL
                msg += '\n\n' + thanks
            else:
                msg = _('The trial license you are using will expire in %s days.') % str(daysleft)
                msg += '  ' + purchase_info
                msg += '  ' + _('Otherwise, you can extend your trial twice for a total evaluation period of 30 days.  For a longer trial please email [email]support@wingware.com[/email].')
                msg += '\n\n' + thanks
        links = textutils.ParseUrlLinks(msg, strip_trailing_period=True)
        marks = []
        for start, end, url in links:
 
            def open_url(url=url):
                self.fSingletons.fWingIDEApp.ExecuteURL(url)
 
            marks.append((start, end, 'link', open_url))
 
        def purchase():
            if config.kSteam:
                self.fSingletons.fWingIDEApp.ExecuteURL(config.kStoreURL)
            else:
                if txt is not None and txt[0] in 'YH':
                    extend_url = 'https://wingware.com/store/upgrade&license-ids=%s' % txt
                    self.fSingletons.fWingIDEApp.ExecuteURL(extend_url)
                else:
                    self._ObtainLicense()
            return
 
        buttons = (
         dialogs.CButtonSpec(purchase_label, purchase, wgtk.STOCK_EXECUTE),
         dialogs.CButtonSpec(_('_Continue Working'), None, wgtk.STOCK_OK, default=True))
        dialog = messages.CMessageDialog(self.fSingletons, title, msg, marks, buttons)
        dialog.AllowSheetWindow(False)
        dialog.RunAsModal(self.fSingletons.fWinMgr.GetActiveWindow())
        self._fExpiringLicenseCheck = True
        return
 
    def _ObtainLicense(self, try_auto=True):
        """Prompt user to obtain a license, or quit if they don't get one"""
        if self._fPromptForSaveDialog:
            return
        if self.__fObtainLicenseDialog is not None:
            self.__fObtainLicenseDialog.Show()
            return
        if try_auto:
            vendor_lic = self._ReadVendorFile()
            if not vendor_lic and config.kSteam:
                if config.kSteamAppID == config.kSteamAppIDTrial:
                    self.fLicense = abstract.CreateTrialLicenseDict()
                    vendor_lic = self.fLicense['license']
                else:
                    vendor_lic = self.__GetSteamLicense()
            if vendor_lic and self.__fAutoActivator is None:
                print('Attempting auto-activation of vendor license')
                self.fSingletons.fUseMgr.Count('vendor-license-activate')
                self.__fAutoActivator = CActivator(self.fSingletons, silent=True)
                lic = abstract.CreateLicenseDict(vendor_lic)
                request = abstract.CreateActivationRequest(lic)
                self.__fAutoActivator.StartActivation(lic, request)
 
                def failed():
                    pass
 
                def complete():
                    self.__fAutoActivator.destroy()
                    self.__fAutoActivator = None
                    self.LicenseCheck(force=True, try_auto=False)
                    return
 
                self.__fAutoActivator.connect_while_alive('connect-failed', failed, self)
                self.__fAutoActivator.connect_while_alive('complete', complete, self)
                return
        if config.kSteam:
            self.__fObtainLicenseDialog = self.__SteamObtainLicense()
        else:
            self.__fObtainLicenseDialog = CObtainLicenseDialog(self.fSingletons)
 
        def closed(*args):
            self.__fObtainLicenseDialog = None
            return
 
        self.__fObtainLicenseDialog.connect_while_alive('destroy', closed, self)
        self.__fObtainLicenseDialog.RunAsModal(self.fSingletons.fWinMgr.GetActiveWindow())
        return
 
    def __GetSteamLicense(self):
        """Get Wing license using the Steam user ID"""
        print('GETTING STEAM LICENSE')
        kUrl = 'https://wingware.com/steam&protocol=1&app_id=%s&user_id=%i&action=license&noheader=1' % (
         config.kSteamAppID, config.kSteamUserID)
        try:
            svc = urlutils.safe_urlopen(kUrl)
            txt = svc.read()
            svc.close()
        except:
            print('Failed to get Steam license for app_id=%i; user_id=%i.  Exception was:' % (
             config.kSteamAppID, config.kSteamUserID))
            reflect.ReportCurrentException(suppress_gui=True)
            return
 
        lines = txt.splitlines()
        for line in lines:
            if line.startswith('OK:'):
                return line[len('OK:'):].strip()
 
        print('Failed to get Steam license for app_id=%i; user_id=%i.  Server output was:' % (
         config.kSteamAppID, config.kSteamUserID))
        print(txt)
        return
 
    def __SteamObtainLicense(self):
        """Show Obtain License dialog variant used under Steam.  This is only shown
        if the user has Wing but doesn't own it, there is an error trying to use
        wingware.com/steam to get a license, or the user is running a trial that has
        expired."""
        url = config.kStoreURL
        if config.kSteamAppID == config.kSteamAppIDTrial:
            title = _('Expired Trial')
            msg = _('The free trial period for Wing has ended.  Please purchase a license from %s') % url
        else:
            title = _('No Valid License')
            msg = _('Wing could not obtain a license for your Steam user ID.  Please try again or email [email]sales@wingware.com[/email] for help.  If you do not own a license, please purchase one from %s') % url
 
        @wgtk.call_at_idle
        def exit():
            self.fSingletons.fGuiMgr._Quit(check_save=False, no_dialogs=True)
 
        @wgtk.call_at_idle
        def show_url(url=url):
            self.fSingletons.fWingIDEApp.ExecuteURL(url)
            exit()
 
        buttons = [
         dialogs.CButtonSpec(_('_Show Store'), show_url, wgtk.STOCK_OK, default=True),
         dialogs.CButtonSpec(_('Just _Quit'), exit, wgtk.STOCK_OK)]
        dlg = messages.CMessageDialog(self.fSingletons, title, msg, [], buttons, close_cb=exit)
        dlg.fWindow.fGtkWindow.setMinimumHeight(100)
        return dlg
 
    def __CalcEULADigest(self, accepted_filename, eula_text):
        """ Calculate the digest to put in the EULA acceptance file. """
        hasher = sha.new()
        hasher.update(accepted_filename)
        hasher.update(eula_text)
        if self.fLicenseData is not None:
            for field in ('customerid', 'name', 'company', 'product', 'version'):
                hasher.update(self.fLicenseData[field])
 
        digest = '\x00\x00%s\x00\x00' % hasher.digest()
        return digest
 
    def __CreateLicenseDir(self, lic_dir):
        """Create the license dir if needed.  Returns 1 if successful, 0 if not"""
        if os.path.isdir(lic_dir):
            return 1
        try:
            os.makedirs(lic_dir)
            return 1
        except:
            return 0
 
    def _CopyInLicenseDict(self, lic, pending=False):
        """ Copy given license dict over to given user file, saving any old
        copies there by adding 1, 2, 3, ... to the file name is necessary.
        Set pending=True to write a manual activation file, otherwise
        writes the actual license file. This call assumes the license has
        already been validated (if not, it will fail later when used). On
        failure, returns a non-empty list of error strings."""
        if pending:
            filename = 'license.pending'
        else:
            filename = 'license.act'
        user_file = os.path.normpath(fileutils.join(config.kUserSettings, filename))
        act_name = user_file
        i = 1
        while os.path.exists(act_name):
            existing_lic = abstract.ReadLicenseDict(act_name)
            if existing_lic is None:
                match = False
            else:
                match = True
                for key in lic:
                    if key != 'customerdata' and existing_lic.get(key) != lic[key]:
                        match = False
                        break
 
            if match:
                break
            act_name = user_file + str(i)
            i += 1
 
        user_file = act_name
        if not self.__CreateLicenseDir(config.kUserSettings):
            errs = [
             _('Unable to create the required directory %s because the disk is read-only or a file of the same name already exists.') % config.kUserSettings]
            return errs
        if pending:
            ignore = ('activation', )
        else:
            ignore = ()
        errs = abstract.WriteLicenseDict(user_file, lic, ignore)
        if len(errs) > 0:
            return errs
        if not pending:
            self.UseLicense(user_file)
        return []
 
    def _CopyInLicense(self, license, parent_win=None, silent=False):
        """Copy the given valid license into place, in a license activation
        file, showing any errors to the user in a dialog"""
        try:
            errs = self._CopyInLicenseDict(license)
            if len(errs) > 0:
                title = _('Failed to use activated license')
                msg = _('The following errors occurred while copying the license activation file into place:\n\n')
                msg += ('\n').join(errs)
                _ErrorDlg(title, msg, parent=parent_win, silent=silent)
                return False
        except:
            title = _('Failed to use activated license')
            msg = _('The following exception occurred while copying the license activation file into place:\n\n')
            msg += traceback.format_exc()
            _ErrorDlg(title, msg, parent=parent_win, silent=silent)
            return False
 
        self.LicenseCheck()
        if self.LicenseOK():
            self._fExpiringLicenseCheck = True
            if license['license'].startswith('T'):
                title = _('Trial License Generated')
                msg = _('Your 10-day trial license has been created and activated.  If this is your first trial, you will be able to extend the license term twice for up to 30 days.\n\nThanks for trying Wing!')
                _ErrorDlg(title, msg, sheet=False, parent=parent_win, silent=silent)
                return True
            if license['license'][0] in 'YH6':
                title = _('License Activated')
                msg = _('License activation succeeded.  Your license is valid for another %s days.  Thanks for using Wing Pro!') % str(license['termdays'])
                _ErrorDlg(title, msg, sheet=False, parent=parent_win, silent=silent)
                return True
            title = _('License Activated')
            msg = _('License activation succeeded.  Thanks for using Wing Pro!')
            _ErrorDlg(title, msg, sheet=False, parent=parent_win, silent=silent)
            return True
        else:
            title = _('Unexpected License Activation Error')
            msg = _('A validated license was corrupted during copying.  Please send email to [email]support@wingware.com[/email]')
            _ErrorDlg(title, msg, parent=parent_win, silent=silent)
            return False
 
    def _ReadVendorFile(self):
        try:
            vendor_file = fileutils.join(config.kWingHome, 'resources', 'vendor')
            vendor_data = abstract.ReadLicenseDict(vendor_file)
            if vendor_data and vendor_data.has_key('license'):
                errs, lic = abstract.ValidateAndNormalizeLicenseID(vendor_data['license'])
                if errs:
                    print('Invalid preload license line:', repr(vendor_data['license']))
                else:
                    return lic
        except:
            reflect.ReportCurrentException(suppress_gui=True)
            return
 
        return
 
 
class CMultiLineLabel(wgtk.TextView):
    """ A label with better line wrapping behavior.  Qt only for now, 
    though I recall doing someng similar w/ gtk """
 
    def __init__(self, text='', char_width=-1, char_height=-1, max_char_width=-1, max_char_height=-1):
        super(CMultiLineLabel, self).__init__()
        self.setText(text)
        self.SetCharSizeRequest(char_width, char_height, max_width=max_char_width, max_height=max_char_height)
        self.setReadOnly(True)
        self.document().setDocumentMargin(0)
        self.setFrameShape(wgtk.QFrame.NoFrame)
        self.setStyleSheet('background: rgba(0,0,0,0%)')
        self.setHorizontalScrollBarPolicy(wgtk.Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(wgtk.Qt.ScrollBarAlwaysOff)
 
    def set_text(self, text):
        self.setText(text)
 
 
class CObtainLicenseDialog(dialogs.CGenericDialog):
    """Dialog used to obtain a new license"""
    kCharWidth = 60
 
    def __init__(self, singletons, lic=None):
        self.fSingletons = singletons
        self.fActivator = None
        self.fLicMgr = singletons.fLicMgr
        self.fLicense = lic
        if lic is not None:
            self.fRequest = abstract.CreateActivationRequest(lic)
        else:
            self.fRequest = None
        self.__fOptionalEntries = [
         None, None, None]
        self.__fInitialLicenseOK = self.fLicMgr.LicenseOK()
        buttons = [
         dialogs.CButtonSpec(_('Con_tinue'), self.__CB_Continue, wgtk.STOCK_OK, default=True),
         dialogs.CButtonSpec(_('_Cancel'), self.__CB_Cancel, wgtk.STOCK_CANCEL)]
        if not self.fLicMgr.LicenseOK():
            title = _('Wing Pro: No License Found')
        else:
            title = _('Purchase License')
        dialogs.CGenericDialog.__init__(self, singletons.fWinMgr, 'no-license-dialog', title, size=None, button_spec=buttons, close_cb=self.__CB_Cancel)
        self.AllowSheetWindow(False)
        return
 
    def _CreateMainPanel(self):
        vbox = wgtk.VBox()
        vbox.set_border_width(10)
        vbox.set_spacing(10)
        self.__fTitle = CMultiLineLabel(char_width=self.kCharWidth)
        vbox.pack_start(self.__fTitle, expand=False, fill=False)
        self.__fPageOne = self._CreatePageOne()
        self.__fPageTwo = self._CreatePageTwo()
        mpanel = wgtk.VBox()
        mpanel.add(self.__fPageOne)
        self.__fMainPanel = mpanel
        vbox.pack_start(mpanel, expand=True, fill=True)
        wgtk.InitialShowAll(vbox)
        self.__UpdateGUI()
        return vbox
 
    def _CreatePageOne(self):
        vbox = wgtk.VBox()
        vbox.set_spacing(5)
        radio_group = wgtk.RadioButtonGroup()
        radios = []
 
        def radio(txt, tip, w):
            return self.__CreateRadio(txt, tip, w, radio_group, radios, vbox)
 
        canned_lic = self.fLicMgr._ReadVendorFile()
        if not canned_lic:
            tip = _('Trial licenses can be obtained directly from Wing and last for 10 days.  When the license expires, you can renew it twice for a total of 30 days.  Please email [email]support@wingware.com[/email] if you need more time than that.')
            tmpstr = _('Obtain or extend a trial license')
            self.__fGetTrialArea, self.__fRadioGetTrial, ignore = radio(tmpstr, tip, None)
        else:
            self.__fGetTrialArea = None
            self.__fRadioGetTrial = None
        if not canned_lic:
            tip = _('Permanent and annual licenses can be purchased from wingware.com')
            chbox, self.__fRadioPurchase, ignore = radio(_('Purchase a license'), tip, None)
        else:
            self.__fRadioPurchase = None
        self.__fLicenseIDEntry = wgtk.Entry()
        tip = _('Wing requires that you activate each license before using it.  If you run out of activations, please email your license to [email]sales@wingware.com[/email].')
        if canned_lic:
            title = _('Activate your pre-loaded license:')
        else:
            title = _('Activate a purchased license.\nEnter license id:')
        chbox, self.__fRadioActivate, ignore = radio(title, tip, self.__fLicenseIDEntry)
        if canned_lic:
            self.__fLicenseIDEntry.set_text(canned_lic)
            self.__fLicenseIDEntry.set_editable(False)
        else:
            self.__PrefillLicenseCode()
        tip = _('You can try Wing for a short period of time without any license.  At the end of the allocated time, this dialog will reappear and you will be given the option to start a trial, purchase a license, or quit Wing after saving changes.')
        self.__fRunArea, self.__fRadioRun, ignore = radio(_('10 minute emergency session'), tip, None)
        tip = _('You have used up the time period during which Wing will run without any license.  You must now start a 30-day trial, purchase a license, or quit after saving changes.')
        self.__fExitArea, self.__fRadioExit, ignore = radio(_('Exit after saving changes'), tip, None)
        if canned_lic:
            self.__fRadioActivate.set_active(True)
        else:
            if self.__fInitialLicenseOK:
                self.__fRadioPurchase.set_active(True)
            else:
                self.__fRadioGetTrial.set_active(True)
        wgtk.timeout_add_while_alive(5000, self.__UpdateRunExitChoices, self)
        wgtk.InitialShowAll(vbox)
        for radio in radios:
            wgtk.gui_connect(radio, 'toggled', self.__UpdateGUI)
 
        return vbox
 
    def __PrefillLicenseCode(self):
        for v in range(config.kMajorVersion, 1, -1):
            settings = config.GetUserSettingsDir(v)
            if not os.path.isdir(settings):
                continue
            for fn in os.listdir(settings):
                if fn.startswith('license.act'):
                    user_file = os.path.normpath(fileutils.join(settings, fn))
                    lic = None
                    try:
                        lic = abstract.ReadLicenseDict(user_file)
                    except Exception:
                        print('Failed to read for license pre-fill:', user_file)
 
                    if lic is not None:
                        txt = lic.get('license', '')
                        if len(txt) > 0 and txt[0] != 'T':
                            print('License pre-filled from', user_file)
                            self.__fLicenseIDEntry.set_text(txt)
                            return
 
        return
 
    def _CreatePageTwo(self):
        canned_lic = self.fLicMgr._ReadVendorFile()
        vbox = wgtk.VBox()
        vbox.set_spacing(5)
        radio_group = wgtk.RadioButtonGroup()
        radios = []
 
        def radio(txt, tip, w):
            return self.__CreateRadio(txt, tip, w, radio_group, radios, vbox)
 
        title = _('Choose your preferred method of license activation:')
        label = CMultiLineLabel(title, char_width=self.kCharWidth)
        self.__fSecondaryTitle = label
        vbox.pack_start(label, expand=False, fill=True)
        tip = _('This is the easiest way to activate your license.  Wing sends your license and your request code to our server to complete the activation process.')
        proxy_config = wgtk.IconButton(_('Configure Proxy...'), wgtk.STOCK_NETWORK)
 
        def config_proxy(*args):
            self.fSingletons.fWingIDEApp._ConfigureProxy()
 
        wgtk.gui_connect(proxy_config, 'clicked', config_proxy)
        align = wgtk.HBox()
        align.pack_start(proxy_config, expand=0, fill=0)
        chbox, self.__fRadioDirect, ignore = radio(_('Recommended: Connect Wing directly to wingware.com'), tip, align)
        self.__fProxyConfigArea = align
        self.__fManualEntry = wgtk.Entry()
        wgtk.gui_connect(self.__fManualEntry, 'changed', self.__UpdateGUI)
        tip = _('If your machine does not have a network connection that can access port 80 (http) on wingware.com, you will need to activate your license manually by entering your license id and request code on a machine that does have network access.  If you cannot browse the web at all, email the information to us at [email]support@wingware.com[/email] and we will email you the activation code.')
        chbox, self.__fRadioManual, self.__fManualLabel = radio('', tip, self.__fManualEntry)
        self.__fRadioDirect.set_active(True)
        if not canned_lic:
            text = _('Optional user identity to use for lost license recovery:')
            label = CMultiLineLabel(text, char_width=self.kCharWidth)
            vbox.pack_start(label, expand=False, fill=True)
            table = wgtk.Table(3, 2)
            self.__fOptionalValueAreas = [label, table]
            for i, item in enumerate((_('Licensed user'), _('Email'), _('Phone'))):
                label = wgtk.Label(item)
                label.set_line_wrap(True)
                table.attach(label, 0, 1, i, i + 1)
                entry = wgtk.Entry()
                wgtk.gui_connect(entry, 'changed', self.__UpdateCustData)
                self.__fOptionalEntries[i] = (label, entry)
                table.attach(entry, 1, 2, i, i + 1)
 
            vbox.pack_start(table, expand=False, fill=True)
        else:
            self.__fOptionalEntries = []
            self.__fOptionalValueAreas = []
        wgtk.InitialShowAll(vbox)
        wgtk.SetVisible(self.__fProxyConfigArea, False)
        for radio in radios:
            wgtk.gui_connect(radio, 'toggled', self.__UpdateGUI)
 
        return vbox
 
    def __SetTitleMarkup(self, markup):
        self.__fTitle.setText(markup)
 
    def __CreateRadio(self, txt, tip, w, radio_group, radios, vbox):
        radio = wgtk.RadioButton()
        radios.append(radio)
        radio.set_radio_group(radio_group)
        wgtk.set_tooltip(radio, tip)
        chbox = wgtk.HBox()
        chbox.set_spacing(10)
        align = wgtk.Alignment(0.0, 0.0, 1.0, 0.0)
        align.add(radio)
        tooltip1 = wgtk.TooltipBox(tip, child=align)
        chbox.pack_start(tooltip1, expand=False, fill=True)
        cvbox = wgtk.VBox()
        label = CMultiLineLabel(txt, char_width=self.kCharWidth)
        cvbox.pack_start(label, expand=False, fill=True)
        if w is not None:
            cvbox.pack_start(w, expand=False, fill=True)
        chbox.pack_start(cvbox, expand=True, fill=True)
        vbox.pack_start(chbox, expand=False, fill=True)
        return (
         chbox, radio, label)
 
    def __UpdateGUI(self, *args):
        if self.__fMainPanel.get_children()[0] == self.__fPageOne:
            self.__UpdatePageOneGUI()
        else:
            self.__UpdatePageTwoGUI()
 
    def __UpdatePageOneGUI(self):
        wgtk.SetVisible(self.__fTitle)
        if self.fLicMgr.LicenseOK():
            self.__SetTitleMarkup('<b>' + _('To change to another license, you may now:') + '</b>')
            title = _('Change License')
        else:
            self.__SetTitleMarkup('<b>' + _('Wing is running without a valid license. You may now:') + '</b>')
            title = _('No Valid License')
        self.fWindow.SetTitle(title)
        if self.__fGetTrialArea is not None:
            wgtk.SetVisible(self.__fGetTrialArea, visible=not self.__fInitialLicenseOK)
        self.__UpdateRunExitChoices()
        return
 
    def __UpdateRunExitChoices(self, *args):
        try:
            if self.__fInitialLicenseOK:
                wgtk.SetVisible(self.__fExitArea, False)
                wgtk.SetVisible(self.__fRunArea, False)
            else:
                if time.time() - self.fLicMgr._fStartTime < 10 * 60:
                    wgtk.SetVisible(self.__fExitArea, False)
                    wgtk.SetVisible(self.__fRunArea)
                else:
                    wgtk.SetVisible(self.__fExitArea)
                    wgtk.SetVisible(self.__fRunArea, False)
            self.__fLicenseIDEntry.set_sensitive(self.__fRadioActivate.get_active())
        finally:
            return True
 
    def __UpdatePageTwoGUI(self):
        if self.fLicense is not None and self.fLicense['license'].startswith('T'):
            self.__SetTitleMarkup('<b>' + _('Your trial license has been created.  To activate it you can:') + '</b>')
            self.fWindow.SetTitle(_('Activate Trial License'))
        else:
            self.__SetTitleMarkup('<b>' + _('Please choose your preferred method of license activation:') + '</b>')
            self.fWindow.SetTitle(_('Activate License'))
        self.__fManualLabel.set_text(_('Or:  Activate manually at [url]https://wingware.com/activate.[/url]  You will need your license id %s and request code %s.  Then enter the provided activation key here:') % (
         self.fLicense['license'], self.fRequest))
        self.fLicMgr._CopyInLicenseDict(self.fLicense, pending=True)
        if self.fLicense is None:
            wgtk.SetVisible(self.__fTitle)
            wgtk.SetVisible(self.__fSecondaryTitle, False)
            for area in self.__fOptionalValueAreas:
                wgtk.SetVisible(area, False)
 
        else:
            wgtk.SetVisible(self.__fTitle, False)
            opt_sens = len(self.__fManualEntry.get_text()) == 0
            opt_show = not self.fLicense['license'].startswith('T')
            wgtk.SetVisible(self.__fSecondaryTitle, visible=opt_show)
            for i, area in enumerate(self.__fOptionalValueAreas):
                wgtk.SetVisible(area, visible=opt_show)
                if opt_show:
                    area.set_sensitive(opt_sens)
 
        self.__fManualEntry.set_sensitive(self.__fRadioManual.get_active())
        return
 
    def __CB_Continue(self):
        if self.__fMainPanel.get_children()[0] == self.__fPageOne:
            return self.__PageOneContinue()
        return self.__PageTwoContinue()
 
    def __PageOneContinue(self):
        if self.__fRadioGetTrial is not None and self.__fRadioGetTrial.get_active():
            self.fLicense = abstract.CreateTrialLicenseDict()
            self.__UpdateCustData()
            self.__ShowPage(2)
            return True
        if self.__fRadioPurchase is not None and self.__fRadioPurchase.get_active():
            title = _('Opening Browser')
            msg = _('Click OK to open [url]https://wingware.com/store[/url] in a web browser.  Once you have purchased a license, return here to activate it.')
            marks = []
            links = textutils.ParseUrlLinks(msg)
            for start, end, url in links:
 
                def open_url(url=url):
                    self.fSingletons.fWingIDEApp.ExecuteURL(url)
 
                marks.append((start, end, 'link', open_url))
 
            def doit(app=self.fSingletons.fWingIDEApp):
                app.ExecuteURL('https://wingware.com/store')
 
            buttons = [
             dialogs.CButtonSpec(_('_OK'), doit, wgtk.STOCK_OK, default=True),
             dialogs.CButtonSpec(_('_Cancel'), None, wgtk.STOCK_CANCEL)]
            dlg = messages.CMessageDialog(self.fSingletons, title, msg, marks, buttons)
            dlg.RunAsModal(self)
            return True
        if self.__fRadioActivate.get_active():
            id = self.__fLicenseIDEntry.get_text()
            errs, lic = abstract.ValidateAndNormalizeLicenseID(id)
            if len(errs) == 0 and id[0] == 'T':
                errs.append(_('You cannot enter a trial license id here'))
            if len(errs) > 0:
                msg = _('Invalid license id: %s. Please check and correct it.  Errors found were:\n\n%s') % (id, ('\n').join(errs))
                buttons = [dialogs.CButtonSpec(_('_OK'), None, wgtk.STOCK_OK)]
                dlg = messages.CMessageDialog(self.fSingletons, _('Invalid License ID'), msg, [], buttons)
                dlg.RunAsModal(self)
                return True
            self.fLicense = abstract.CreateLicenseDict(lic)
            self.__UpdateCustData()
            if id[2] in 'LWM':
                self.__StartActivation()
            else:
                self.__ShowPage(2)
            return True
        if self.__fRadioRun.get_active():
            pass
        else:
            if self.__fRadioExit.get_active():
 
                def done():
 
                    def doit():
                        singleton.GetSingletons().fGuiMgr._Quit(check_save=False, no_dialogs=True)
 
                    wgtk.idle_add(doit)
 
                self.fLicMgr._fPromptForSaveDialog = True
 
                def cancel(licmgr=self.fLicMgr):
                    licmgr._fPromptForSaveDialog = False
 
                self.fSingletons.fGuiMgr.fSaveMgr.PromptForSave(action_cb=done, parent_win=self, initial_prompt=1, cancel_cb=cancel)
            else:
                self.fLicMgr.LicenseCheck()
        return
 
    def __StartActivation(self):
        """Start activation process"""
        self.fActivator = CActivator(self.fSingletons, self)
        self.fActivator.StartActivation(self.fLicense, self.fRequest)
        self.fActivator.connect_while_alive('connect-failed', self.__CB_ConnectFailed, self)
        self.fActivator.connect_while_alive('complete', self.__CB_ActivateComplete, self)
 
    def __CB_ConnectFailed(self):
        """Called if activation connection fails"""
        wgtk.SetVisible(self.__fProxyConfigArea)
        self.fSingletons.fWingIDEApp._ShowUnableToConnectDialog(self)
 
    def __CB_ActivateComplete(self):
        """Called when activation completes"""
        self.fActivator.destroy()
        self.fActivator = None
        self.fLicMgr.LicenseCheck()
        if self.fLicMgr.LicenseOK():
            self.Close()
        return
 
    def __PageTwoContinue(self):
        if self.__fRadioDirect.get_active():
            self.__StartActivation()
            return True
        if self.__fRadioManual.get_active():
            act_text = self.__fManualEntry.get_text()
            daysleft = None
            errs, act = abstract.ValidateAndNormalizeActivation(act_text)
            if len(errs) > 0 and act_text.rfind('-') > 0:
                errs2, act2 = abstract.ValidateAndNormalizeActivation(act_text[:act_text.rfind('-')])
                if not errs2:
                    errs = []
                    act = act2
                    try:
                        daysleft = act_text[act_text.rfind('-') + 1:]
                        daysleft = textutils.BaseConvert(daysleft, textutils.BASE30, textutils.BASE10)
                        daysleft = int(daysleft)
                    except:
                        print('Failed to determine daysleft from', act_text)
                        daysleft = 0
 
            if len(errs) > 0:
                title = _('Invalid License ID')
                msg = _('Invalid activation key: %s. Please check and correct it.  Errors found were:\n\n%s') % (
                 self.__fManualEntry.get_text(), ('\n').join(errs))
                _ErrorDlg(title, msg, parent=self)
                return True
            actbase = os.path.normpath(fileutils.join(config.kUserSettings, 'license.pending'))
            i = 1
            act_file = actbase
            errs = []
            while os.path.exists(act_file) and i <= 10:
                try:
                    lic2 = abstract.ReadLicenseDict(act_file)
                except:
                    lic2 = None
 
                if lic2 is not None and lic2.get('license') == self.fLicense['license']:
                    lic2['activation'] = act
                    if daysleft is not None:
                        lic2['termdays'] = daysleft
                    err, info = self.fLicMgr._ValidateLicenseDict(lic2, None)
                    if err == abstract.kLicenseOK:
                        self.fLicense = lic2
                        try:
                            os.unlink(act_file)
                        except:
                            pass
 
                        break
                    errs.append('Pending activation ' + str(act_file) + ' -- failed:')
                    errs.extend([ '  ' + t for t in self.fLicMgr._StatusToErrString((err, info)) ])
                    errs.append('\n')
                act_file = actbase + str(i)
                i += 1
 
            self.fLicense['activation'] = act
            if daysleft is not None:
                self.fLicense['termdays'] = daysleft
            err, info = self.fLicMgr._ValidateLicenseDict(self.fLicense, None)
            if err != abstract.kLicenseOK:
                msg = _('Invalid activation key: %s. Please check and correct it.') % self.__fManualEntry.get_text()
                errs.append('Current activation -- failed:')
                errs.extend([ '  ' + t for t in self.fLicMgr._StatusToErrString((err, info)) ])
                if len(errs) > 0:
                    msg += _('  Validation errors were:\n\n%s') % ('\n').join(errs)
                title = _('Invalid License ID')
                _ErrorDlg(title, msg, parent=self)
                return True
            if not self.fLicMgr._CopyInLicense(self.fLicense, self):
                return True
        else:
            self.fLicMgr.LicenseCheck()
        return
 
    def __CB_Cancel(self):
        if self.__fMainPanel.get_children()[0] == self.__fPageOne:
            self.fLicMgr.LicenseCheck()
        else:
            self.__ShowPage(1)
            return True
 
    def __ShowPage(self, num):
        self.__fMainPanel.remove(self.__fMainPanel.get_children()[0])
        if num == 1:
            self.__fMainPanel.add(self.__fPageOne)
        else:
            self.__fMainPanel.add(self.__fPageTwo)
        self.__UpdateGUI()
 
    def __UpdateCustData(self, *args):
        if self.fLicense is None:
            return
        custdata = self._GetCustData(omit_blank=True)
        custdata = (', ').join(custdata)
        self.fLicense['customerdata'] = custdata
        self.fRequest = abstract.CreateActivationRequest(self.fLicense)
        return
 
    def _GetCustData(self, omit_blank=False):
        """Get customer data from optional fields.  This is stored in the license
        activation and also sent to the server for storage so we can look up
        lost license codes."""
        custdata = []
        for label, area in self.__fOptionalEntries:
            area = area.get_text().strip()
            if not omit_blank or len(area) > 0:
                custdata.append(area)
 
        return custdata
 
 
class CActivator(destroyable.CDestroyable):
 
    def __init__(self, singletons, parent=None, silent=False):
        destroyable.CDestroyable.__init__(self, signals=[
         'connect-failed', 'complete'])
        self.__fIdle = None
        self.fSingletons = singletons
        self.fLicMgr = singletons.fLicMgr
        self.fParent = parent
        self.__fProgress = None
        self.__fActivationIteration = 0
        self.__fSilent = silent
        return
 
    def StartActivation(self, lic, req):
        """Start the activation process, which is done asyncronously via a
        generator."""
        self.fLicense = lic
        self.fRequest = req
 
        def closed():
            self.__fProgress = None
            self.__fActivationIteration = -1
            return
 
        self.__fProgress = dialogs.CProgressDialog(self.fSingletons.fWinMgr, _('Activating'), _('Submitting activation request. Please wait'), closed)
        if not self.__fSilent:
            self.__fProgress.RunAsModal(self)
        self.__fIdle = wgtk.idle_add_while_alive(self.__CB_ActivationStep, self)
        self.__fActivationIteration = 0
        lic = self.fLicense['license']
        if lic[2] not in 'LWM':
            self.__fActivationGenerator = self.__ActivationIteration()
            self.__fProgress.fProgressBar.set_text(_('Connecting to wingware.com'))
            self.__fProgress.fProgressBar.set_fraction(0.2)
        else:
            self.__fActivationGenerator = self.__BulkActivationIteration()
            self.__fProgress.fProgressBar.set_text(_('Preparing activation'))
            self.__fProgress.fProgressBar.set_fraction(0.2)
 
    def __CB_ActivationStep(self):
        """Called by idle for each step in submitting an activation request"""
        try:
            self.__fActivationIteration = self.__fActivationGenerator.next()
        except StopIteration:
            self.__fActivationIteration = -1
        except:
            reflect.ReportCurrentException(suppress_gui=True)
            self.__fActivationIteration = -1
            self.emit('connect-failed')
 
        if self.__fActivationIteration == -1:
            if self.__fIdle is not None:
                wgtk.idle_remove(self.__fIdle)
                self.__fIdle = None
            if self.__fProgress is not None:
                self.__fProgress.Close()
                self.__fProgress = None
            self.__fActivationGenerator = None
            self.emit('complete')
            return False
        return True
        return
 
    def __ActivationIteration(self):
        """Do one iteration in the activation process"""
        while self.__fActivationIteration != -1:
            if self.__fActivationIteration == 0:
                lic = self.fLicense['license']
                url = 'https://wingware.com/activate&license=%s&request=%s&noheader=1' % (
                 lic, self.fRequest)
                if self.fParent is not None:
                    custdata = self.fParent._GetCustData()
                    custdict = {}
                    for i, cd in enumerate(custdata):
                        if not cd:
                            continue
                        if i == 0:
                            custdict['name'] = cd
                        elif i == 1:
                            custdict['email'] = cd
                        elif i == 2:
                            custdict['phone'] = cd
 
                    if custdict:
                        extra = urllib.urlencode(custdict)
                        url += '&' + extra
                svc = urlutils.safe_urlopen(url)
                yield 1
            elif self.__fActivationIteration == 1:
                self.__fProgress.fProgressBar.set_text(_('Waiting for Reply'))
                self.__fProgress.fProgressBar.set_fraction(0.4)
                txt = svc.read()
                yield 2
            elif self.__fActivationIteration == 2:
                self.__fProgress.fProgressBar.set_text(_('Reading Reply'))
                self.__fProgress.fProgressBar.set_fraction(0.6)
                svc.close()
                err, act, exceeded, need_upgrade, termdays = self.__GetActivationErrors(txt, lic)
                if err is not None:
                    title = _('Could not obtain activation key')
                    extra_buttons = []
                    if exceeded:
 
                        def show_license_page(s=self.fSingletons):
                            url = 'https://wingware.com/license&license=%s' % lic
                            s.fWingIDEApp.ExecuteURL(url)
 
                        extra_buttons.append(dialogs.CButtonSpec(_('_Add Activations'), show_license_page, pack_start=True))
                    if need_upgrade:
 
                        def show_upgrade_page(s=self.fSingletons):
                            url = 'https://wingware.com/store/upgrade&license-ids=%s' % lic
                            s.fWingIDEApp.ExecuteURL(url)
 
                        extra_buttons.append(dialogs.CButtonSpec(_('_Upgrade'), show_upgrade_page, wgtk.STOCK_GO_UP, pack_start=True))
                    _ErrorDlg(title, err, extra_buttons, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                else:
                    yield 3
            elif self.__fActivationIteration == 3:
                self.__fProgress.fProgressBar.set_text(_('Validating Activation Key'))
                self.__fProgress.fProgressBar.set_fraction(0.8)
                self.fLicense['activation'] = act
                if termdays is not None:
                    self.fLicense['termdays'] = termdays
                err, info = self.fLicMgr._ValidateLicenseDict(self.fLicense, None)
                if err != abstract.kLicenseOK:
                    msg = _('Internal activation error: %s. Please report this to [email]support@wingware.com[/email].') % info
                    errs = self.fLicMgr._StatusToErrString((err, info))
                    if len(errs) > 0:
                        msg += _('  Validation errors were:\n\n%s') % ('\n').join(errs)
                    title = _('Invalid License ID')
                    _ErrorDlg(title, msg, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                else:
                    yield 4
            elif self.__fActivationIteration == 4:
                self.__fProgress.fProgressBar.set_text(_('Writing Activation File'))
                self.__fProgress.fProgressBar.set_fraction(1.0)
                if self.fLicMgr._CopyInLicense(self.fLicense, self.fParent, self.__fSilent):
                    self.__fProgress.Close()
                yield -1
 
        return
 
    def __BulkActivationIteration(self):
        """Do one iteration in the activation process"""
        while self.__fActivationIteration != -1:
            if self.__fActivationIteration == 0:
                if abstract.bulkctl is None:
                    title = _('Invalid license')
                    err = _('The license code you provided is invalid for this product')
                    _ErrorDlg(title, err, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                yield 1
            elif self.__fActivationIteration == 1:
                self.__fProgress.fProgressBar.set_text(_('Validating License'))
                self.__fProgress.fProgressBar.set_fraction(0.2)
                if not abstract.bulkctl.check(self.fLicense['license']):
                    title = _('Invalid license')
                    err = _('The license code you provided is invalid -- please check it and try again')
                    _ErrorDlg(title, err, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                if not self.fLicMgr._ValidatePlatform(self.fLicense['license'], abstract.control.get_os()):
                    title = _('Invalid license')
                    err = _('The license code you provided not valid for this operating system')
                    _ErrorDlg(title, err, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                yield 2
            elif self.__fActivationIteration == 2:
                self.__fProgress.fProgressBar.set_text(_('Creating Activation'))
                self.__fProgress.fProgressBar.set_fraction(0.4)
                req = self.fRequest
                act = abstract.bulkctl._hash16(req)
                act30 = textutils.BaseConvert(act, textutils.BASE16, textutils.BASE30)
                while len(act30) < 17:
                    act30 = '1' + act30
 
                act30 = 'AXX' + act30
                act = abstract.AddHyphens(act30)
                yield 3
            elif self.__fActivationIteration == 3:
                self.__fProgress.fProgressBar.set_text(_('Validating Activation'))
                self.__fProgress.fProgressBar.set_fraction(0.6)
                self.fLicense['activation'] = act
                err, info = self.fLicMgr._ValidateLicenseDict(self.fLicense, None)
                if err != abstract.kLicenseOK:
                    msg = _('Internal activation error: %s. Please report this to [email]support@wingware.com[/email].') % self.__fManualEntry.get_text()
                    errs = self.fLicMgr._StatusToErrString((err, info))
                    if len(errs) > 0:
                        msg += _('  Validation errors were:\n\n%s') % ('\n').join(errs)
                    title = _('Invalid License ID')
                    _ErrorDlg(title, msg, parent=self.fParent, silent=self.__fSilent)
                    yield -1
                else:
                    yield 4
            elif self.__fActivationIteration == 4:
                self.__fProgress.fProgressBar.set_text(_('Writing Activation File'))
                self.__fProgress.fProgressBar.set_fraction(1.0)
                if self.fLicMgr._CopyInLicense(self.fLicense, self.fParent, self.__fSilent):
                    self.__fProgress.Close()
                    self.Close()
                yield -1
 
        return
 
    def __GetActivationErrors(self, txt, lic):
        """Get activation errors, if any, given a server response"""
        exceeded = False
        need_upgrade = False
        termdays = None
        if txt.find('INVALID:') >= 0:
            txt = txt[txt.find('INVALID:'):]
            if txt.find('\n') >= 0:
                txt = txt[:txt.find('\n')]
        else:
            if txt.find('AXX') >= 0:
                txt = txt[txt.find('AXX'):]
                if lic[0] in '6YH':
                    try:
                        termdays_base30 = txt[24:].strip()
                        termdays_base30 = termdays_base30[:termdays_base30.find('|')].strip()
                        termdays = textutils.BaseConvert(termdays_base30, textutils.BASE30, textutils.BASE10)
                        if termdays:
                            termdays = int(termdays)
                        else:
                            termdays = 0
                    except:
                        print('Failed to extract termdays from', txt)
                        termdays = 0
 
                    txt = txt[:23]
                else:
                    txt = txt[:23]
            if txt.startswith('INVALID'):
                try:
                    codes = txt.split('\n')[0].split(':')[1]
                except:
                    codes = 'X'
 
                errs = []
                for c in codes:
                    if c == 'M':
                        errs.append(_('Internal error (missing field)'))
                    elif c == 'L':
                        errs.append(_('Internal error (invalid license)'))
                    elif c == 'R':
                        errs.append(_('Internal error (invalid request code)'))
                    elif c == 'E':
                        if lic[0] == 'T':
                            if sys.platform.startswith('linux'):
                                errs.append(_('You have exceeded the allowed number of trial licenses on this machine. If you are working with a downloaded Linux VM, this may be due to other users of the same VM. Please email license %s to [email]support@wingware.com[/email] for help.\n\nSorry for the inconvenience, and thanks for trying Wing Pro!') % lic)
                            else:
                                errs.append(_('You have exceeded the allowed number of trial licenses on this machine. Please email your license id %s to [email]support@wingware.com[/email] if you need more time.\n\nSorry about the inconvenience, and thanks for trying Wing Pro!') % lic)
                        else:
                            errs.append(_('You have exceeded your allowed number of license activations. You can increase activation limits at [url]https://wingware.com/license[/url] or by emailing your license id %s to [email]support@wingware.com[/email].\n\nSorry for the inconvenience and thanks for using Wing Pro!') % lic)
                            exceeded = True
                    elif c == 'T':
                        errs.append(_('That license has expired.  Please contact [email]sales@wingware.com[/email].'))
                    elif c == 'A':
                        errs.append(_('This annual license has expired.  Please renew at [url]https://wingware.com/store/upgrade&license-id=%s'[/url]) % lic)
                        need_upgrade = True
                    elif c == 'O':
                        errs.append(_('That license id %s cannot be activated on additional operating systems.  Please contact [email]sales@wingware.com[/email] if you wish to upgrade your license.') % lic)
                        need_upgrade = True
                    elif c == 'U':
                        errs.append(_('We have no record of that license id %s.  Please check it and try again.') % lic)
                    elif c == 'K':
                        errs.append('That license id %s has been revoked, possibly because a replacement has been issued or due to abuse.  Please check it and try again.' % lic)
                    elif c == 'X':
                        errs.append(_('Internal error (unexpected server return value).  This may indicate network problems such as a misconfigured proxy server.'))
                    elif c == 'V':
                        errs.append(_('That license id %s can only be activated on specially patched versions of Wing.  Please contact your vendor  or [email]sales@wingware.com[/email].') % lic)
                    elif c == 'H':
                        errs.append(_('This license is not valid for this version of Wing.  Please upgrade at [url]https://wingware.com/store/upgrade&license-id=%s'[/url]) % lic)
                        need_upgrade = True
                    else:
                        errs.append(_('Unknown activation error code %s') % c)
 
                return (('\n').join(errs), None, exceeded, need_upgrade, termdays)
            errs, act = abstract.ValidateAndNormalizeActivation(txt)
            if len(errs) > 0:
                return (
                 _('Received an invalid activation key "%s" from the server.  This may indicate network problems such as a misconfigured proxy server.  Errors found were:\n\n%s') % (
                  txt[:23], ('\n').join(errs)), None, exceeded, need_upgrade)
        return (None, act.strip(), exceeded, need_upgrade, termdays)
 
 
class CEULADialog(dialogs.CGenericDialog):
    """EULA acceptance dialog"""
 
    def __init__(self, win_mgr, text_styles, eula_text, accept_cb, decline_cb):
        """Constructor:
         
        win_mgr      -- window manager to use
         
        """
        self.__fEULAText = eula_text
        self.__fTextStyles = text_styles
        button_spec = [
         dialogs.CButtonSpec(kAccept, accept_cb, wgtk.STOCK_YES, default=True),
         dialogs.CButtonSpec(kDecline, decline_cb, wgtk.STOCK_NO)]
        dialogs.CGenericDialog.__init__(self, win_mgr, 'eula-dialog', _('License Agreement'), None, button_spec)
        return
 
    def _CreateMainPanel(self):
        font1 = [
         ('weight', 'bold')]
        header = wgtk.Label(_('Wing is licensed software.  Its use is subject to the terms and conditions of the following license agreement:'))
        header.set_alignment(0.0, 0.5)
        header.set_padding(10, 10)
        header.set_line_wrap(True)
        footer = wgtk.Label(_("If you accept the terms of this license agreement, press 'Accept'.  Otherwise, press 'Decline.'"))
        footer.set_alignment(0.0, 0.5)
        footer.set_padding(10, 10)
        footer.set_line_wrap(True)
        text = unicode(self.__fEULAText, 'utf-8').encode('utf-8')
        para_list = text.split('\n\n')
        for i, para in enumerate(para_list):
            lines = para.split('\n')
            para = (' ').join([ l.strip() for l in lines ])
            para_list[i] = para
 
        text = ('\n\n').join(para_list)
        htext = hypertext.CHyperText(self.__fTextStyles, char_size_request=(80, 10,
                                                                            10), visible=True)
        htext.SetText(text)
        swin = wgtk.ScrolledWindow(hscrollbar_policy=wgtk.POLICY_NEVER, child=htext, request_child_size=True, visible=True)
        frame = wgtk.Frame()
        frame.add(swin)
        frame.set_border_width(2)
        frame.set_shadow_type(wgtk.SHADOW_IN)
        vbox = wgtk.VBox()
        vbox.pack_start(header, expand=False)
        vbox.pack_start(frame, expand=True)
        vbox.pack_start(footer, expand=False)
        wgtk.InitialShowAll(vbox)
        return vbox

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 冥界3大法王 发表于 2020-9-14 12:26
daysleft = self._GetTermDaysLeft()

改成 daysleft = 88888888 如何?
nevinhappy 发表于 2020-9-14 14:27
https://bbs.pediy.com/thread-182231.htm
然后看看:Wing Pro 8\bin\ide-2.7\src\process\__os__\win32\ctlutil.pyd

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
冥界3大法王 + 1 + 1 很好,就爱看破解过程。

查看全部评分

nevinhappy 发表于 2020-9-14 14:33
本帖最后由 nevinhappy 于 2020-9-14 14:37 编辑

下载这个:https://bbs.pediy.com/thread-255434.htm
把下面的位置改一下,就OK了!

g_version_list = ('8.0.0', '7.X.X', '6.X.X', '5.X.X')
g_version_magics = {
    '5.X.X': [7, 123, 23, 87],
    '6.X.X': [23, 161, 47, 9],
    '7.X.X': [221, 13, 93, 27],
    '8.0.0': [179, 95, 45, 245],
}

免费评分

参与人数 1热心值 +1 收起 理由
冥界3大法王 + 1 牛拜~~

查看全部评分

fanvalen 发表于 2020-9-14 14:38
冥界3大法王 发表于 2020-9-14 12:26
改成 daysleft = 88888888 如何?

可以尝试,这样就变成无限试用
aqc 发表于 2020-9-14 14:41
好东西,谢谢
 楼主| 冥界3大法王 发表于 2020-9-14 15:23
本帖最后由 冥界3大法王 于 2020-9-14 15:55 编辑
fanvalen 发表于 2020-9-14 14:38
可以尝试,这样就变成无限试用

@fanvalen
修改完了,用python命令行生成pyo文件,结果再运行就没有动静了,不知为啥,难道有自校验?

@nevinhappy
感谢 注册机






lyrong 发表于 2020-9-16 17:38
盗用别人的成品 不道德啊 ( ̄▽ ̄)"
ymhld 发表于 2020-9-17 10:41
if txt is not None and txt[0] == '6':
            if daysleft > 30:
                return
        else:
            if txt is not None and txt[0] in 'YH':
                if daysleft > 45:
                    return
            else:
                if daysleft <= 0 or daysleft > 10:

明显daysleft是剩余的天数,看看哪里有计算的,直接赋值就行了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-1-16 05:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表