def get_update(self): self.get_beta() data = self.data sql = [""" SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """] if data.get('appOS'): sql.append(' OR files.platform_id = %(appOS)s') if self.flags['use_version']: sql.append(') WHERE files.status > %(status)s AND ' 'versions.version = %(version)s ') else: if self.flags['multiple_status']: # Note that getting this properly escaped is a pain. # Suggestions for improvement welcome. sql.append(') WHERE files.status in (%(STATUS_PUBLIC)s,' '%(STATUS_LITE)s,%(STATUS_LITE_AND_NOMINATED)s) ') else: sql.append(') WHERE files.status = %(status)s ') sql.append('AND appmin.version_int <= %(version_int)s ') if self.compat_mode == 'ignore': pass # no further SQL modification required. elif self.compat_mode == 'normal': # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append("""AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """) # Filter out versions that don't have the minimum maxVersion # requirement to qualify for default-to-compatible. d2c_max = applications.D2C_MAX_VERSIONS.get(data['app_id']) if d2c_max: data['d2c_max_version'] = version_int(d2c_max) sql.append("AND appmax.version_int >= %(d2c_max_version)s ") # Filter out versions found in compat overrides sql.append("""AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """) else: # Not defined or 'strict'. sql.append('AND appmax.version_int >= %(version_int)s ') sql.append('ORDER BY versions.id DESC LIMIT 1;') self.cursor.execute(''.join(sql), data) result = self.cursor.fetchone() if result: row = dict(zip([ 'guid', 'type', 'disabled_by_user', 'appguid', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'strict_compat', 'releasenotes', 'version', 'premium_type'], list(result))) row['type'] = base.ADDON_SLUGS_UPDATE[row['type']] row['url'] = get_mirror(self.data['addon_status'], self.data['id'], row) data['row'] = row return True return False
def get_update(self): self.get_beta() data = self.data sql = """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ if data.get('appOS'): sql += ' OR files.platform_id = %(appOS)s' if self.flags['use_version']: sql += (') WHERE files.status > %(status)s AND ' 'versions.version = %(version)s ') else: if self.flags['multiple_status']: # Note that getting this properly escaped is a pain. # Suggestions for improvement welcome. sql += (') WHERE files.status in (%(STATUS_PUBLIC)s,' '%(STATUS_LITE)s,%(STATUS_LITE_AND_NOMINATED)s)') else: sql += ') WHERE files.status = %(status)s ' sql += """ AND (appmin.version_int <= %(version_int)s AND appmax.version_int >= %(version_int)s) ORDER BY versions.id DESC LIMIT 1; """ self.cursor.execute(sql, data) result = self.cursor.fetchone() if result: row = dict(zip([ 'guid', 'type', 'disabled_by_user', 'appguid', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'releasenotes', 'version', 'premium_type'], list(result))) row['type'] = base.ADDON_SLUGS_UPDATE[row['type']] if row['premium_type'] == base.ADDON_PREMIUM: qs = urlencode(dict((k, data.get(k, '')) for k in base.WATERMARK_KEYS)) row['url'] = (u'%s/downloads/watermarked/%s?%s' % (settings.SITE_URL, row['file_id'], qs)) else: row['url'] = get_mirror(self.data['addon_status'], self.data['id'], row) data['row'] = row return True return False
def get_update(self): data = self.data data['STATUS_PUBLIC'] = base.STATUS_PUBLIC data['STATUS_BETA'] = base.STATUS_BETA data['STATUS_DISABLED'] = base.STATUS_DISABLED data['RELEASE_CHANNEL_LISTED'] = base.RELEASE_CHANNEL_LISTED sql = [ """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN appversions appmin ON appmin.id = applications_versions.min AND appmin.application_id = %(app_id)s INNER JOIN appversions appmax ON appmax.id = applications_versions.max AND appmax.application_id = %(app_id)s INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ ] if data.get('appOS'): sql.append(' OR files.platform_id = %(appOS)s') sql.append(""" ) -- Find a reference to the user's current version, if it exists. -- These should never be inner joins. We need results even if we -- can't find the current version. LEFT JOIN versions curver ON curver.addon_id = addons.id AND curver.version = %(version)s LEFT JOIN files curfile ON curfile.version_id = curver.id WHERE versions.deleted = 0 AND versions.channel = %(RELEASE_CHANNEL_LISTED)s AND -- Note that the WHEN clauses here will evaluate to the same -- thing for each row we examine. The JOINs above narrow the -- rows matched by the WHERE clause to versions of a specific -- add-on, and the ORDER BY and LIMIT 1 clauses below make it -- unlikely that we'll be examining a large number of rows, -- so this is fairly cheap. CASE WHEN curfile.status = %(STATUS_BETA)s THEN -- User's current version is a known beta version. -- -- Serve only beta updates. Serving a full version here -- will forever kick users out of the beta update channel. -- -- If the add-on does not have full review, serve no -- updates. addons.status = %(STATUS_PUBLIC)s AND files.status = %(STATUS_BETA)s ELSE -- Anything else, including: -- -- * Add-on has full review -- * User's current version has full review, regardless -- of add-on status -- -- Serve only full-reviewed updates. files.status = %(STATUS_PUBLIC)s END """) sql.append('AND appmin.version_int <= %(version_int)s ') if self.compat_mode == 'ignore': pass # no further SQL modification required. elif self.compat_mode == 'normal': # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append("""AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """) # Filter out versions that don't have the minimum maxVersion # requirement to qualify for default-to-compatible. d2c_max = applications.D2C_MAX_VERSIONS.get(data['app_id']) if d2c_max: data['d2c_max_version'] = version_int(d2c_max) sql.append("AND appmax.version_int >= %(d2c_max_version)s ") # Filter out versions found in compat overrides sql.append("""AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """) else: # Not defined or 'strict'. sql.append('AND appmax.version_int >= %(version_int)s ') # Special case for bug 1031516. if data['guid'] == '*****@*****.**': app_version = data['version_int'] hotfix_version = data['version'] if version_int('10') <= app_version <= version_int('16.0.1'): if hotfix_version < '20121019.01': sql.append("AND versions.version = '20121019.01' ") elif hotfix_version < '20130826.01': sql.append("AND versions.version = '20130826.01' ") elif version_int('16.0.2') <= app_version <= version_int('24.*'): if hotfix_version < '20130826.01': sql.append("AND versions.version = '20130826.01' ") sql.append('ORDER BY versions.id DESC LIMIT 1;') self.cursor.execute(''.join(sql), data) result = self.cursor.fetchone() if result: row = dict( zip([ 'guid', 'type', 'disabled_by_user', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'strict_compat', 'releasenotes', 'version' ], list(result))) row['type'] = base.ADDON_SLUGS_UPDATE[row['type']] row['url'] = get_mirror(data['addon_status'], data['id'], row) row['appguid'] = applications.APPS_ALL[data['app_id']].guid data['row'] = row return True return False
def get_update(self): self.get_beta() data = self.data sql = [ """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ ] if data.get("appOS"): sql.append(" OR files.platform_id = %(appOS)s") if self.flags["use_version"]: sql.append(") WHERE files.status > %(status)s AND " "versions.version = %(version)s ") else: if self.flags["multiple_status"]: # Note that getting this properly escaped is a pain. # Suggestions for improvement welcome. sql.append( ") WHERE files.status in (%(STATUS_PUBLIC)s," "%(STATUS_LITE)s,%(STATUS_LITE_AND_NOMINATED)s) " ) else: sql.append(") WHERE files.status = %(status)s ") sql.append("AND appmin.version_int <= %(version_int)s ") if self.compat_mode == "ignore": pass # no further SQL modification required. elif self.compat_mode == "normal": # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append( """AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """ ) # Filter out versions found in compat overrides sql.append( """AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """ ) else: # Not defined or 'strict'. sql.append("AND appmax.version_int >= %(version_int)s ") sql.append("ORDER BY versions.id DESC LIMIT 1;") self.cursor.execute("".join(sql), data) result = self.cursor.fetchone() if result: row = dict( zip( [ "guid", "type", "disabled_by_user", "appguid", "min", "max", "file_id", "file_status", "hash", "filename", "version_id", "datestatuschanged", "strict_compat", "releasenotes", "version", "premium_type", ], list(result), ) ) row["type"] = base.ADDON_SLUGS_UPDATE[row["type"]] if row["premium_type"] in base.ADDON_PREMIUMS: qs = urlencode(dict((k, data.get(k, "")) for k in base.WATERMARK_KEYS)) row["url"] = u"%s/downloads/watermarked/%s?%s" % (settings.SITE_URL, row["file_id"], qs) else: row["url"] = get_mirror(self.data["addon_status"], self.data["id"], row) data["row"] = row return True return False
def get_update(self): data = self.data data.update(STATUSES_PUBLIC) data['STATUS_BETA'] = base.STATUS_BETA data['STATUS_DISABLED'] = base.STATUS_DISABLED sql = [""" SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN appversions appmin ON appmin.id = applications_versions.min AND appmin.application_id = %(app_id)s INNER JOIN appversions appmax ON appmax.id = applications_versions.max AND appmax.application_id = %(app_id)s INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """] if data.get('appOS'): sql.append(' OR files.platform_id = %(appOS)s') sql.append(""" ) -- Find a reference to the user's current version, if it exists. -- These should never be inner joins. We need results even if we -- can't find the current version. LEFT JOIN versions curver ON curver.addon_id = addons.id AND curver.version = %(version)s LEFT JOIN files curfile ON curfile.version_id = curver.id WHERE -- Note that the WHEN clauses here will evaluate to the same -- thing for each row we examine. The JOINs above narrow the -- rows matched by the WHERE clause to versions of a specific -- add-on, and the ORDER BY and LIMIT 1 clauses below make it -- unlikely that we'll be examining a large number of rows, -- so this is fairly cheap. CASE WHEN curfile.status = %(STATUS_BETA)s THEN -- User's current version is a known beta version. -- -- Serve only beta updates. Serving a full version here -- will forever kick users out of the beta update channel. -- -- If the add-on does not have full review, serve no -- updates. addons.status = %(STATUS_PUBLIC)s AND files.status = %(STATUS_BETA)s WHEN addons.status IN (%(STATUS_LITE)s, %(STATUS_LITE_AND_NOMINATED)s) AND (curfile.id IS NULL OR curfile.status IN (%(STATUS_LITE)s, %(STATUS_DISABLED)s)) THEN -- Add-on is prelim, and user's current version is either a -- known prelim, or an unknown version. -- -- Serve only prelim versions. Serving a full version here -- will prevent users from receiving further updates until -- the add-on achieves full review. files.status = %(STATUS_LITE)s ELSE -- Anything else, including: -- -- * Add-on has full review -- * User's current version has full review, regardless -- of add-on status -- -- Serve only full-reviewed updates. files.status = %(STATUS_PUBLIC)s END """) sql.append('AND appmin.version_int <= %(version_int)s ') if self.compat_mode == 'ignore': pass # no further SQL modification required. elif self.compat_mode == 'normal': # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append("""AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """) # Filter out versions that don't have the minimum maxVersion # requirement to qualify for default-to-compatible. d2c_max = applications.D2C_MAX_VERSIONS.get(data['app_id']) if d2c_max: data['d2c_max_version'] = version_int(d2c_max) sql.append("AND appmax.version_int >= %(d2c_max_version)s ") # Filter out versions found in compat overrides sql.append("""AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """) else: # Not defined or 'strict'. sql.append('AND appmax.version_int >= %(version_int)s ') # Special case for bug 1031516. if data['guid'] == '*****@*****.**': app_version = data['version_int'] hotfix_version = data['version'] if version_int('10') <= app_version <= version_int('16.0.1'): if hotfix_version < '20121019.01': sql.append("AND versions.version = '20121019.01' ") elif hotfix_version < '20130826.01': sql.append("AND versions.version = '20130826.01' ") elif version_int('16.0.2') <= app_version <= version_int('24.*'): if hotfix_version < '20130826.01': sql.append("AND versions.version = '20130826.01' ") sql.append('ORDER BY versions.id DESC LIMIT 1;') self.cursor.execute(''.join(sql), data) result = self.cursor.fetchone() if result: row = dict(zip([ 'guid', 'type', 'disabled_by_user', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'strict_compat', 'releasenotes', 'version', 'premium_type'], list(result))) row['type'] = base.ADDON_SLUGS_UPDATE[row['type']] row['url'] = get_mirror(data['addon_status'], data['id'], row) row['appguid'] = applications.APPS_ALL[data['app_id']].guid data['row'] = row return True return False
def get_update(self): self.get_beta() data = self.data sql = """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, versions.releasenotes, versions.version as version FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ if data.get('appOS'): sql += ' OR files.platform_id = %(appOS)s' if self.flags['use_version']: sql += (') WHERE files.status > %(status)s AND ' 'versions.version = %(version)s ') else: if self.flags['multiple_status']: # Note that getting this properly escaped is a pain. # Suggestions for improvement welcome. sql += (') WHERE files.status in (%(STATUS_PUBLIC)s,' '%(STATUS_LITE)s,%(STATUS_LITE_AND_NOMINATED)s)') else: sql += ') WHERE files.status = %(status)s ' sql += """ AND (appmin.version_int <= %(version_int)s AND appmax.version_int >= %(version_int)s) ORDER BY versions.id DESC LIMIT 1; """ self.cursor.execute(sql, data) result = self.cursor.fetchone() if result: row = dict( zip([ 'guid', 'type', 'disabled_by_user', 'appguid', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'releasenotes', 'version' ], list(result))) row['type'] = ADDON_SLUGS_UPDATE[row['type']] row['url'] = get_mirror(self.data['addon_status'], self.data['id'], row) data['row'] = row return True return False
def get_update(self): self.get_beta() data = self.data sql = [ """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ ] if data.get('appOS'): sql.append(' OR files.platform_id = %(appOS)s') if self.flags['use_version']: sql.append(') WHERE files.status > %(status)s AND ' 'versions.version = %(version)s ') else: if self.flags['multiple_status']: # Note that getting this properly escaped is a pain. # Suggestions for improvement welcome. sql.append(') WHERE files.status in (%(STATUS_PUBLIC)s,' '%(STATUS_LITE)s,%(STATUS_LITE_AND_NOMINATED)s) ') else: sql.append(') WHERE files.status = %(status)s ') sql.append('AND appmin.version_int <= %(version_int)s ') if self.compat_mode == 'ignore': pass # no further SQL modification required. elif self.compat_mode == 'normal': # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append("""AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """) # Filter out versions that don't have the minimum maxVersion # requirement to qualify for default-to-compatible. d2c_max = applications.D2C_MAX_VERSIONS.get(data['app_id']) if d2c_max: data['d2c_max_version'] = version_int(d2c_max) sql.append("AND appmax.version_int >= %(d2c_max_version)s ") # Filter out versions found in compat overrides sql.append("""AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """) else: # Not defined or 'strict'. sql.append('AND appmax.version_int >= %(version_int)s ') sql.append('ORDER BY versions.id DESC LIMIT 1;') self.cursor.execute(''.join(sql), data) result = self.cursor.fetchone() if result: row = dict( zip([ 'guid', 'type', 'disabled_by_user', 'appguid', 'min', 'max', 'file_id', 'file_status', 'hash', 'filename', 'version_id', 'datestatuschanged', 'strict_compat', 'releasenotes', 'version', 'premium_type' ], list(result))) row['type'] = base.ADDON_SLUGS_UPDATE[row['type']] row['url'] = get_mirror(self.data['addon_status'], self.data['id'], row) data['row'] = row return True return False
def get_update(self): data = self.data data.update(STATUSES_PUBLIC) data["STATUS_BETA"] = base.STATUS_BETA sql = [ """ SELECT addons.guid as guid, addons.addontype_id as type, addons.inactive as disabled_by_user, applications.guid as appguid, appmin.version as min, appmax.version as max, files.id as file_id, files.status as file_status, files.hash, files.filename, versions.id as version_id, files.datestatuschanged as datestatuschanged, files.strict_compatibility as strict_compat, versions.releasenotes, versions.version as version, addons.premium_type FROM versions INNER JOIN addons ON addons.id = versions.addon_id AND addons.id = %(id)s INNER JOIN applications_versions ON applications_versions.version_id = versions.id INNER JOIN applications ON applications_versions.application_id = applications.id AND applications.id = %(app_id)s INNER JOIN appversions appmin ON appmin.id = applications_versions.min INNER JOIN appversions appmax ON appmax.id = applications_versions.max INNER JOIN files ON files.version_id = versions.id AND (files.platform_id = 1 """ ] if data.get("appOS"): sql.append(" OR files.platform_id = %(appOS)s") sql.append( """ ) -- Find a reference to the user's current version, if it exists. -- These should never be inner joins. We need results even if we -- can't find the current version. LEFT JOIN versions curver ON curver.addon_id = addons.id AND curver.version = %(version)s LEFT JOIN files curfile ON curfile.version_id = curver.id WHERE -- Note that the WHEN clauses here will evaluate to the same -- thing for each row we examine. The JOINs above narrow the -- rows matched by the WHERE clause to versions of a specific -- add-on, and the ORDER BY and LIMIT 1 clauses below make it -- unlikely that we'll be examining a large number of rows, -- so this is fairly cheap. CASE WHEN curfile.status = %(STATUS_BETA)s THEN -- User's current version is a known beta version. -- -- Serve only beta updates. Serving a full version here -- will forever kick users out of the beta update channel. -- -- If the add-on does not have full review, serve no -- updates. addons.status = %(STATUS_PUBLIC)s AND files.status = %(STATUS_BETA)s WHEN addons.status IN (%(STATUS_LITE)s, %(STATUS_LITE_AND_NOMINATED)s) AND (curfile.id IS NULL OR curfile.status = %(STATUS_LITE)s) THEN -- Add-on is prelim, and user's current version is either a -- known prelim, or an unknown version. -- -- Serve only prelim versions. Serving a full version here -- will prevent users from receiving further updates until -- the add-on achieves full review. files.status = %(STATUS_LITE)s ELSE -- Anything else, including: -- -- * Add-on has full review -- * User's current version has full review, regardless -- of add-on status -- -- Serve only full-reviewed updates. files.status = %(STATUS_PUBLIC)s END """ ) sql.append("AND appmin.version_int <= %(version_int)s ") if self.compat_mode == "ignore": pass # no further SQL modification required. elif self.compat_mode == "normal": # When file has strict_compatibility enabled, or file has binary # components, default to compatible is disabled. sql.append( """AND CASE WHEN files.strict_compatibility = 1 OR files.binary_components = 1 THEN appmax.version_int >= %(version_int)s ELSE 1 END """ ) # Filter out versions that don't have the minimum maxVersion # requirement to qualify for default-to-compatible. d2c_max = applications.D2C_MAX_VERSIONS.get(data["app_id"]) if d2c_max: data["d2c_max_version"] = version_int(d2c_max) sql.append("AND appmax.version_int >= %(d2c_max_version)s ") # Filter out versions found in compat overrides sql.append( """AND NOT versions.id IN ( SELECT version_id FROM incompatible_versions WHERE app_id=%(app_id)s AND (min_app_version='0' AND max_app_version_int >= %(version_int)s) OR (min_app_version_int <= %(version_int)s AND max_app_version='*') OR (min_app_version_int <= %(version_int)s AND max_app_version_int >= %(version_int)s)) """ ) else: # Not defined or 'strict'. sql.append("AND appmax.version_int >= %(version_int)s ") sql.append("ORDER BY versions.id DESC LIMIT 1;") self.cursor.execute("".join(sql), data) result = self.cursor.fetchone() if result: row = dict( zip( [ "guid", "type", "disabled_by_user", "appguid", "min", "max", "file_id", "file_status", "hash", "filename", "version_id", "datestatuschanged", "strict_compat", "releasenotes", "version", "premium_type", ], list(result), ) ) row["type"] = base.ADDON_SLUGS_UPDATE[row["type"]] row["url"] = get_mirror(data["addon_status"], data["id"], row) data["row"] = row return True return False