Пример #1
0
def getTitleImage(request, response):
    if len(request.bits) < 3:
        return Server.Response404(request, response)

    id = request.bits[2]
    try:
        width = int(request.bits[3])
    except:
        return Server.Response404(request, response)

    if width < 32 or width > 1024:
        return Server.Response404(request, response)

    if not Titles.contains(id):
        return Server.Response404(request, response)

    path = Titles.get(id).iconFile(width) or Titles.get(id).frontBoxArtFile(
        width)

    if not path:
        return Server.Response404(request, response)

    response.setMime(path)
    response.headers['Cache-Control'] = 'max-age=31536000'

    if os.path.isfile(path):
        with open(path, 'rb') as f:
            response.write(f.read())

    return Server.Response500(request, response)
Пример #2
0
def importRegion(region='US', language='en'):
    if not region in Config.regionLanguages(
    ) or language not in Config.regionLanguages()[region]:
        Print.error('Could not locate %s/%s !' % (region, language))
        return False

    for region2 in Config.regionLanguages():
        for language2 in Config.regionLanguages()[region2]:
            for nsuId, regionTitle in Titles.data(region2, language2).items():
                if not regionTitle.id:
                    continue
                title = Titles.get(regionTitle.id, None, None)
                title.importFrom(regionTitle, region2, language2)

    for region2 in Config.regionLanguages():
        for language2 in Config.regionLanguages()[region2]:
            if language2 != language:
                continue
            for nsuId, regionTitle in Titles.data(region2, language2).items():
                if not regionTitle.id:
                    continue
                title = Titles.get(regionTitle.id, None, None)
                title.importFrom(regionTitle, region2, language2)

    for nsuId, regionTitle in Titles.data(region, language).items():
        if not regionTitle.id:
            continue

        title = Titles.get(regionTitle.id, None, None)
        title.importFrom(regionTitle, region, language)

    Titles.loadTxtDatabases()
    Titles.save()
Пример #3
0
    def fileName(self):
        bt = None
        if not self.titleId in Titles.keys():
            if not Title.getBaseId(self.titleId) in Titles.keys():
                Print.info('could not find title key for ' + self.titleId +
                           ' or ' + Title.getBaseId(self.titleId))
                return None
            bt = Titles.get(Title.getBaseId(self.titleId))
            t = Title()
            t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' +
                      bt.name)
        else:
            t = Titles.get(self.titleId)

            if not t:
                Print.error('could not find title id ' + str(self.titleId))
                return None

            try:
                if not t.baseId in Titles.keys():
                    Print.info('could not find baseId for ' + self.path)
                    return None
            except BaseException as e:
                print('exception: could not find title id ' +
                      str(self.titleId) + ' ' + str(e))
                return None
            bt = Titles.get(t.baseId)

        if t.isDLC:
            format = Config.paths.getTitleDLC(not self.hasValidTicket)
        elif t.isDemo:
            if t.idExt != 0:
                format = Config.paths.getTitleDemoUpdate(
                    not self.hasValidTicket)
            else:
                format = Config.paths.getTitleDemo(not self.hasValidTicket)
        elif t.idExt != 0:
            format = Config.paths.getTitleUpdate(not self.hasValidTicket)
        else:
            format = Config.paths.getTitleBase(not self.hasValidTicket)

        format = format.replace('{id}', self.cleanFilename(t.id))
        format = format.replace('{region}',
                                self.cleanFilename(t.getRegion() or ''))
        format = format.replace('{name}', self.cleanFilename(t.getName()
                                                             or ''))
        format = format.replace('{version}', str(self.getVersion() or 0))
        format = format.replace('{baseId}', self.cleanFilename(bt.id))
        format = format.replace('{baseName}',
                                self.cleanFilename(bt.getName() or ''))
        '''
		if self.hasValidTicket:
			format = os.path.splitext(format)[0] + '.nsp'
		else:
			format = os.path.splitext(format)[0] + '.nsx'
		'''

        return format
Пример #4
0
    def fileName(self):
        bt = None
        if not self.titleId in Titles.keys():
            if not Title.getBaseId(self.titleId) in Titles.keys():
                Print.info('could not find title key for ' + self.titleId +
                           ' or ' + Title.getBaseId(self.titleId))
                return None
            bt = Titles.get(Title.getBaseId(self.titleId))
            t = Title()
            t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' +
                      bt.name)
        else:
            t = Titles.get(self.titleId)

            if not t:
                Print.error('could not find title id ' + str(self.titleId))
                return None

            try:
                if not t.baseId in Titles.keys():
                    Print.info('could not find baseId for ' + self.path)
                    return None
            except BaseException as e:
                print('exception: could not find title id ' +
                      str(self.titleId) + ' ' + str(e))
                return None
            bt = Titles.get(t.baseId)

        if t.isDLC:
            format = Config.paths.getTitleDLC(not self.hasValidTicket)
        elif t.isDemo:
            if t.idExt != 0:
                format = Config.paths.getTitleDemoUpdate(
                    not self.hasValidTicket)
            else:
                format = Config.paths.getTitleDemo(not self.hasValidTicket)
        elif t.idExt != 0:
            format = Config.paths.getTitleUpdate(not self.hasValidTicket)
        else:
            format = Config.paths.getTitleBase(not self.hasValidTicket)

        format = format.replace('{id}', self.cleanFilename(t.id))
        format = format.replace('{region}',
                                self.cleanFilename(t.getRegion() or ''))
        format = format.replace('{name}', self.cleanFilename(t.getName()
                                                             or ''))
        format = format.replace('{version}', str(self.getVersion() or 0))
        format = format.replace('{baseId}', self.cleanFilename(bt.id))

        baseName = self.cleanFilename(bt.getName() or '')
        result = format.replace('{baseName}', baseName)

        while (len(os.path.basename(result).encode('utf-8')) > 254
               and len(baseName) > 3):
            baseName = baseName[:-1]
            result = format.replace('{baseName}', baseName)

        return result
Пример #5
0
def scrapeThread(id, delta=True):
    size = len(Titles.titles) // scrapeThreads
    st = Status.create(size, 'Thread ' + str(id))
    for i, titleId in enumerate(Titles.titles.keys()):
        try:
            if (i - id) % scrapeThreads == 0:
                Titles.get(titleId).scrape(delta)
                st.add()
        except BaseException as e:
            Print.error(str(e))
    st.close()
Пример #6
0
    def unlock(self):
        #if not self.isOpen():
        #	self.open('r+b')

        if not Titles.contains(self.titleId):
            raise IOError('No title key found in database!')

        self.ticket().setTitleKeyBlock(int(Titles.get(self.titleId).key, 16))
        Print.info('setting title key to ' + Titles.get(self.titleId).key)
        self.ticket().flush()
        self.close()
        self.hasValidTicket = True
        self.move()
Пример #7
0
def download(id):
	bits = id.split(',')

	version = None
	key = None

	if len(bits) == 1:
		id = bits[0].upper()
	elif len(bits) == 2:
		id = bits[0].upper()
		key = bits[1].strip()
	elif len(bits) == 3:
		id = bits[0].upper()
		key = bits[1].strip()
		version = bits[2].strip()
	else:
		Print.info('invalid args: ' + download)
		return False

	if key == '':
		key = None

	if version == '':
		version = None

	if len(id) != 16:
		raise IOError('Invalid title id format')

	if Titles.contains(id):
		title = Titles.get(id)

		CDNSP.download_game(title.id.lower(), version or title.lastestVersion(), key or title.key, True, '', True)
	else:
		CDNSP.download_game(id.lower(), version or Title.getCdnVersion(id.lower()), key, True, '', True)
	return True
Пример #8
0
def getScreenshotImage(request, response):
    if len(request.bits) < 3:
        return Server.Response404(request, response)

    id = request.bits[2]

    try:
        i = int(request.bits[3])
    except:
        return Server.Response404(request, response)

    if not Titles.contains(id):
        return Server.Response404(request, response)

    path = Titles.get(id).screenshotFile(i)

    if not path:
        return Server.Response404(request, response)

    response.setMime(path)
    response.headers['Cache-Control'] = 'max-age=31536000'

    if os.path.isfile(path):
        with open(path, 'rb') as f:
            response.write(f.read())

    return Server.Response500(request, response)
Пример #9
0
    def isUpdateAvailable(self):
        title = self.title()

        if self.titleId and title.version != None and self.version < title.version and str(
                title.version) != '0':
            return {
                'id': title.id,
                'baseId': title.baseId,
                'currentVersion': self.version,
                'newVersion': title.version
            }

        if not title.isUpdate and not title.isDLC and Titles.contains(
                title.updateId):
            updateFile = self.getUpdateFile()

            if updateFile:
                return updateFile.isUpdateAvailable()

            updateTitle = Titles.get(title.updateId)

            if updateTitle.version and str(updateTitle.version) != '0':
                return {
                    'id': updateTitle.id,
                    'baseId': title.baseId,
                    'currentVersion': None,
                    'newVersion': updateTitle.version
                }

        return None
Пример #10
0
    def move(self):
        if not self.path:
            return False

        if not self.fileName():
            #print('could not get filename for ' + self.path)
            return False

        if os.path.abspath(self.fileName()).lower() == os.path.abspath(
                self.path).lower():
            return False
        if os.path.isfile(self.fileName()) and os.path.abspath(
                self.path) == os.path.abspath(self.fileName()):
            print('duplicate title: ')
            print(os.path.abspath(self.path))
            print(os.path.abspath(self.fileName()))
            return False

        try:
            os.makedirs(os.path.dirname(self.fileName()), exist_ok=True)
            newPath = self.fileName()
            os.rename(self.path, newPath)
            self.path = newPath
        except BaseException as e:
            print('failed to rename file! %s -> %s  : %s' %
                  (self.path, self.fileName(), e))
        #print(self.path + ' -> ' + self.fileName())

        if self.titleId in Titles.keys():
            Titles.get(self.titleId).path = self.fileName()
        return True
Пример #11
0
def downloadThread(i):
    Print.info('starting thread ' + str(i))
    global status
    while Config.isRunning:
        try:
            id = Titles.queue.shift()
            if id and Titles.contains(id):
                activeDownloads[i] = 1
                t = Titles.get(id)
                path = CDNSP.download_game(t.id.lower(), t.lastestVersion(),
                                           t.key, True, '', True)

                if os.path.isfile(path):
                    nsp = Fs.Nsp(path, None)
                    nsp.move()
                    Nsps.files[nsp.path] = nsp
                    Nsps.save()
                    status.add()
                activeDownloads[i] = 0
            else:
                time.sleep(1)
        except KeyboardInterrupt:
            pass
        except BaseException as e:
            Print.error(str(e))
    activeDownloads[i] = 0
    Print.info('ending thread ' + str(i))
Пример #12
0
def scanLatestTitleUpdates():
    initTitles()
    initFiles()

    for k, i in CDNSP.get_versionUpdates().items():
        id = str(k).upper()
        version = str(i)

        if not Titles.contains(id):
            if len(id) != 16:
                Print.info('invalid title id: ' + id)
                continue
            continue
            t = Title()
            t.setId(id)
            Titles.set(id, t)
            Print.info('Found new title id: ' + str(id))

        t = Titles.get(id)
        if str(t.version) != str(version):
            Print.info('new version detected for %s[%s] v%s' %
                       (t.name or '', t.id or ('0' * 16), str(version)))
            t.setVersion(version, True)

    Titles.save()
Пример #13
0
def exportVerifiedKeys(fileName):
	initTitles()
	with open(fileName, 'w') as f:
		f.write('id|key|version\n')
		for tid,key in blockchain.blockchain.export().items():
			title = Titles.get(tid)
			if title and title.rightsId:
				f.write(str(title.rightsId) + '|' + str(key) + '|' + str(title.version) + '\n')
Пример #14
0
    def fileName(self):
        bt = None
        if not self.titleId in Titles.keys():
            if not Title.getBaseId(self.titleId) in Titles.keys():
                Print.info('could not find title key for ' + self.titleId +
                           ' or ' + Title.getBaseId(self.titleId))
                return None
            bt = Titles.get(Title.getBaseId(self.titleId))
            t = Title()
            t.loadCsv(self.titleId + '0000000000000000|0000000000000000|' +
                      bt.name)
        else:
            t = Titles.get(self.titleId)

            if not t.baseId in Titles.keys():
                Print.info('could not find baseId for ' + self.path)
                return None
            bt = Titles.get(t.baseId)

        if t.isDLC:
            format = Config.paths.titleDLC
        elif t.isDemo:
            if t.idExt != 0:
                format = Config.paths.titleDemoUpdate
            else:
                format = Config.paths.titleDemo
        elif t.idExt != 0:
            format = Config.paths.titleUpdate
        else:
            format = Config.paths.titleBase

        format = format.replace('{id}', self.cleanFilename(t.id))
        format = format.replace('{region}', self.cleanFilename(t.region or ''))
        format = format.replace('{name}', self.cleanFilename(t.name or ''))
        format = format.replace('{version}', str(self.version or 0))
        format = format.replace('{baseId}', self.cleanFilename(bt.id))
        format = format.replace('{baseName}', self.cleanFilename(bt.name
                                                                 or ''))

        if self.hasValidTicket:
            format = os.path.splitext(format)[0] + '.nsp'
        else:
            format = os.path.splitext(format)[0] + '.nsx'

        return format
Пример #15
0
def getInfo(request, response):
    try:
        nsp = Nsps.getByTitleId(request.bits[2])
        t = Titles.get(request.bits[2]).__dict__
        t['size'] = nsp.getFileSize()
        t['mtime'] = nsp.getFileModified()
        response.write(json.dumps(t))
    except BaseException as e:
        response.write(json.dumps({'success': False, 'message': str(e)}))
Пример #16
0
def get_name(titleId):
	titleId = titleId.upper()

	if Titles.contains(titleId):
			try:
				t = Titles.get(titleId)
				return (re.sub(r'[/\\:*?!"|???]+', "", unidecode.unidecode(t.name.strip())))[:70]
			except:
				pass
	return 'Unknown Title'
Пример #17
0
def importRegion(region='US', language='en'):
    if not region in Config.regionLanguages(
    ) or language not in Config.regionLanguages()[region]:
        Print.error('Could not locate %s/%s !' % (region, language))
        return False

    for region2 in Config.regionLanguages():
        for language2 in Config.regionLanguages()[region]:
            for nsuId, regionTitle in Titles.data(region2, language2).items():
                if not regionTitle.id:
                    continue
                title = Titles.get(regionTitle.id, None, None)
                title.importFrom(regionTitle, region2, language2)

    for region2 in Config.regionLanguages():
        for language2 in Config.regionLanguages()[region]:
            if language2 != language:
                continue
            for nsuId, regionTitle in Titles.data(region2, language2).items():
                if not regionTitle.id:
                    continue
                title = Titles.get(regionTitle.id, None, None)
                title.importFrom(regionTitle, region2, language2)

    for nsuId, regionTitle in Titles.data(region, language).items():
        if not regionTitle.id:
            continue

        title = Titles.get(regionTitle.id, None, None)
        title.importFrom(regionTitle, region, language)
        '''
		for k,v in regionTitle.__dict__.items():
			if k in ('id', 'version', 'regions', 'languages', 'nsuId', 'key'):
				continue
			setattr(title, k, v)
			title.setId(title.id)
			title.setVersion(regionTitle.version)
			title.region = region
			title.language = language
		'''

    Titles.save()
Пример #18
0
    def title(self):
        if not self.titleId:
            raise IOError('NSP no titleId set')

        if self.titleId in Titles.keys():
            return Titles.get(self.titleId)

        t = Title.Title()
        t.setId(self.titleId)
        Titles.data()[self.titleId] = t
        return t
Пример #19
0
def get_name(titleId):
    titleId = titleId.upper()
    lines = titlekey_list
    if Titles.contains(titleId):
        try:
            t = Titles.get(titleId)
            return re.sub(r'[/\\:*?!"|™©®]+', "",
                          unidecode.unidecode(t.name.strip()))
        except:
            pass
    return 'Unknown Title'
Пример #20
0
def getFiles(request, response):
    r = {}
    for path, nsp in Nsps.files.items():
        if Titles.contains(nsp.titleId):
            title = Titles.get(nsp.titleId)
            if not title.baseId in r:
                r[title.baseId] = {'base': [], 'dlc': [], 'update': []}
            if title.isDLC:
                r[title.baseId]['dlc'].append(nsp.dict())
            elif title.isUpdate:
                r[title.baseId]['update'].append(nsp.dict())
            else:
                r[title.baseId]['base'].append(nsp.dict())
    response.write(json.dumps(r))
Пример #21
0
def getAddOns(titleId):
    url = 'https://superfly.hac.%s.d4c.nintendo.net/v1/a/%s/dv' % (
        Config.cdn.environment, titleId)
    j = makeJsonRequest('GET', url, {}, '%d/a/%s/dv.json' % (shop_id, titleId))
    lst = []

    if not j:
        return lst

    for i in j:
        id = i['title_id'].upper()

        if Titles.contains(id):
            Titles.get(id).setVersion(int(i['version']))
        else:
            Print.info('New DLC found: ' + id)
            title = Title.Title()
            title.setId(id)
            title.setVersion(int(i['version']))
            Titles.set(id, title)

        lst.append(id)

    return lst
Пример #22
0
def getBannerImage(request, response):
	if len(request.bits) < 2:
		return Server.Response404(request, response)

	id = request.bits[2]

	path = Titles.get(id).bannerFile()

	response.setMime(path)
	response.headers['Cache-Control'] = 'max-age=31536000'

	if os.path.isfile(path):
		with open(path, 'rb') as f:
			response.write(f.read())

	return Server.Response500(request, response)
Пример #23
0
def refresh(titleRightsOnly = False):
	initTitles()
	initFiles()

	for k, f in Nsps.files.items():
		try:
			if titleRightsOnly:
				title = Titles.get(f.titleId)
				if title and title.rightsId:
					continue
			print(f.path)
			f.open()
			f.readMeta()
			f.close()
		except BaseException as e:
			print('exception: ' + str(e))
			pass
	Titles.save()
Пример #24
0
def scanDLC(id, showErr=True, dlcStatus=None):
    id = id.upper()
    title = Titles.get(id)
    baseDlc = Title.baseDlcId(id)
    for i in range(0x1FF):
        scanId = format(baseDlc + i, 'X').zfill(16)
        if Titles.contains(scanId):
            continue
        ver = CDNSP.get_version(scanId.lower())
        if ver != None:
            t = Title()
            t.setId(scanId)
            Titles.set(scanId, t)
            Titles.save()
            Print.info('Found new DLC ' + str(title.name) + ' : ' + scanId)
        elif showErr:
            Print.info('nothing found at ' + scanId + ', ' + str(ver))
        if dlcStatus:
            dlcStatus.add()
Пример #25
0
def getNsuIds(titleIds, type='title', region='US', shop_id=4):
    j = ids(titleIds, type, region, shop_id)
    lst = {}
    try:
        for i in j['id_pairs']:
            titleId = i['title_id'].upper()
            nsuId = int(['id'])
            lst[titleId] = nsuId

            if Titles.contains(titleId):
                Titles.get(titleId).nsuId = nsuId
            else:
                title = Title.Title()
                title.setId(titleId)
                title.nsuId = nsuId
                Titles.set(titleId, title)

    except BaseException as e:
        pass
    return lst
Пример #26
0
def refreshRegions():
    for region in Config.regionLanguages():
        for language in Config.regionLanguages()[region]:
            for i in Titles.data(region, language):
                regionTitle = Titles.data(region, language)[i]

                if regionTitle.id:
                    title = Titles.get(regionTitle.id, None, None)

                    if not hasattr(title, 'regions') or not title.regions:
                        title.regions = []

                    if not hasattr(title, 'languages') or not title.languages:
                        title.languages = []

                    if not region in title.regions:
                        title.regions.append(region)

                    if not language in title.languages:
                        title.languages.append(language)
    Titles.save()
Пример #27
0
						Print.info('min: ' + str(j.readInt64()))
				#f.flush()
				#f.close()
				'''

        if args.scrape_shogun:
            scrapeShogun()

        if args.scrape_title:
            initTitles()
            initFiles()

            if not Titles.contains(args.scrape_title):
                Print.error('Could not find title ' + args.scrape_title)
            else:
                Titles.get(args.scrape_title).scrape(False)
                Titles.save()
                #Print.info(repr(Titles.get(args.scrape_title).__dict__))
                pprint.pprint(Titles.get(args.scrape_title).__dict__)

        if args.scrape or args.scrape_delta:
            initTitles()
            initFiles()

            threads = []
            for i in range(scrapeThreads):
                t = threading.Thread(target=scrapeThread,
                                     args=[i, args.scrape_delta])
                t.start()
                threads.append(t)
Пример #28
0
 def getBaseName(self):
     baseId = getBaseId(self.id)
     if Titles.contains(baseId):
         return (Titles.get(baseId).name or '').replace('\n', ' ')
     return ''
Пример #29
0
    def open(self,
             file=None,
             mode='rb',
             cryptoType=-1,
             cryptoKey=-1,
             cryptoCounter=-1):
        super(NcaHeader, self).open(file, mode, cryptoType, cryptoKey,
                                    cryptoCounter)
        self.rewind()
        self.signature1 = self.read(0x100)
        self.signature2 = self.read(0x100)
        self.magic = self.read(0x4)
        self.isGameCard = self.readInt8()
        self.contentType = self.readInt8()

        try:
            self.contentType = Type.Content(self.contentType)
        except:
            pass

        self.cryptoType = self.readInt8()
        self.keyIndex = self.readInt8()
        self.size = self.readInt64()
        self.titleId = hx(self.read(8)[::-1]).decode('utf-8').upper()

        self.readInt32()  # padding

        self.sdkVersion = self.readInt32()
        self.cryptoType2 = self.readInt8()

        self.read(0xF)  # padding

        self.rightsId = hx(self.read(0x10))

        if self.magic not in [b'NCA3', b'NCA2']:
            raise Exception('Failed to decrypt NCA header: ' + str(self.magic))

        self.sectionHashes = []

        for i in range(4):
            self.sectionTables.append(SectionTableEntry(self.read(0x10)))

        for i in range(4):
            self.sectionHashes.append(self.sectionTables[i])

        self.masterKey = (self.cryptoType if self.cryptoType > self.cryptoType2
                          else self.cryptoType2) - 1

        if self.masterKey < 0:
            self.masterKey = 0

        self.encKeyBlock = self.getKeyBlock()
        #for i in range(4):
        #	offset = i * 0x10
        #	key = encKeyBlock[offset:offset+0x10]
        #	Print.info('enc %d: %s' % (i, hx(key)))

        if Keys.keyAreaKey(self.masterKey, self.keyIndex):
            crypto = aes128.AESECB(
                Keys.keyAreaKey(self.masterKey, self.keyIndex))
            self.keyBlock = crypto.decrypt(self.encKeyBlock)
            self.keys = []
            for i in range(4):
                offset = i * 0x10
                key = self.keyBlock[offset:offset + 0x10]
                #Print.info('dec %d: %s' % (i, hx(key)))
                self.keys.append(key)
        else:
            self.keys = [None, None, None, None, None, None, None]

        if self.hasTitleRights():
            if self.titleId.upper() in Titles.keys() and Titles.get(
                    self.titleId.upper()).key:
                self.titleKeyDec = Keys.decryptTitleKey(
                    uhx(Titles.get(self.titleId.upper()).key), self.masterKey)
            else:
                pass
                #Print.info('could not find title key!')
        else:
            self.titleKeyDec = self.key()
Пример #30
0
 def isUnlockable(self):
     return (not self.hasValidTicket) and self.titleId and Titles.contains(
         self.titleId) and Titles.get(self.titleId).key