#! /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
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: