Ejemplo n.º 1
0
Archivo: nut.py Proyecto: carlchina/nut
def organize():
    initTitles()
    initFiles()

    #scan()
    Print.info('organizing')
    for k, f in Nsps.files.items():
        #print('moving ' + f.path)
        #Print.info(str(f.hasValidTicket) +' = ' + f.path)
        f.move()

    for id, t in Titles.data().items():
        files = t.getFiles()
        if len(files) > 1:
            #Print.info("%d - %s - %s" % (len(files), t.id, t.name))
            latest = t.getLatestFile()

            if not latest:
                continue

            for f in files:
                if f.path != latest.path:
                    f.moveDupe()

    Print.info('removing empty directories')
    Nsps.removeEmptyDir('.', False)
    Nsps.save()
Ejemplo n.º 2
0
Archivo: nut.py Proyecto: carlchina/nut
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))
Ejemplo n.º 3
0
Archivo: nut.py Proyecto: carlchina/nut
def initFiles():
    global isInitFiles
    if isInitFiles:
        return

    isInitFiles = True

    Nsps.load()
Ejemplo n.º 4
0
def scan():
	global hasScanned

	if hasScanned:
		return
	hasScanned = True
	initTitles()
	initFiles()

	Nsps.scan(Config.paths.scan)
	Titles.save()
Ejemplo n.º 5
0
Archivo: nut.py Proyecto: ScuttleSE/nut
def organize():
	initTitles()
	initFiles()

	#scan()
	print('organizing')
	for k, f in Nsps.files.items():
		#print(str(f.hasValidTicket) +' = ' + f.path)
		f.move()
	print('removing empty directories')
	Nsps.removeEmptyDir('.', False)
	Nsps.save()
Ejemplo n.º 6
0
Archivo: nut.py Proyecto: ScuttleSE/nut
def initTitles():
	global isInitTitles
	if isInitTitles:
		return

	isInitTitles = True

	Titles.load()

	loadTitleWhitelist()
	loadTitleBlacklist()

	Nsps.load()
Ejemplo n.º 7
0
Archivo: Api.py Proyecto: carlchina/nut
def getInstall(request, response):
    nsp = Nsps.getByTitleId(request.bits[2])

    try:
        url = ('%s:%s@%s:%d/api/download/%s/title.nsp' %
               (request.user.id, request.user.password, Config.server.hostname,
                Config.server.port, request.bits[2]))
        Print.info('Installing ' + url)
        file_list_payloadBytes = url.encode('ascii')

        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        #sock.settimeout(1)
        sock.connect((request.user.switchHost, request.user.switchPort))
        #sock.settimeout(99999)

        sock.sendall(
            struct.pack('!L', len(file_list_payloadBytes)) +
            file_list_payloadBytes)
        while len(sock.recv(1)) < 1:
            time.sleep(0.05)
        sock.close()
        response.write(
            json.dumps({
                'success': True,
                'message': 'install successful'
            }))
    except BaseException as e:
        response.write(json.dumps({'success': False, 'message': str(e)}))
Ejemplo n.º 8
0
	def suggest(self, titleId, titleKey):
		if not titleId or not titleKey:
			raise IndexError('Missing values')

		titleId = titleId.upper()
		nsp = Nsps.getByTitleId(titleId)

		if not nsp:
			raise IOError('Title not found: ' + titleId)

		nsp.open()

		for f in nsp:
			if type(f) == Fs.Nca and f.header.contentType == Type.Content.PROGRAM:
				for fs in f.sectionFilesystems:
					if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR:
						f.seek(0)
						ncaHeader = f.read(0x400)

						sectionHeaderBlock = fs.buffer

						f.seek(fs.offset)
						pfs0Header = f.read(0x10)

						entry = KeyEntry(titleId, titleKey.upper(), ncaHeader, sectionHeaderBlock, pfs0Header, fs.offset)

						index = blockchain.new_transaction(entry)

						blockchain.new_block()

						return True

		return False
Ejemplo n.º 9
0
def getDownload(request, response):
    nsp = Nsps.getByTitleId(request.bits[2])
    #Print.info('Downloading ' + nsp.path)
    response.attachFile(os.path.basename(nsp.path))

    chunkSize = 0x10000

    with open(nsp.path, "rb") as f:
        f.seek(0, 2)
        size = f.tell()
        if 'Range' in request.headers:
            start, end = request.headers.get('Range').strip().strip(
                'bytes=').split('-')

            if end == '':
                end = size - 1
            else:
                end = int(end) + 1

            if start == '':
                start = size - end
            else:
                start = int(start)

            if start >= size or end > size or start < 0 or end <= 0:
                return Server.Response400(request, response,
                                          'Invalid range request')

            response.setStatus(206)

        else:
            start = 0
            end = size

        f.seek(start, 0)

        response.setMime(nsp.path)
        response.setHeader('Accept-Ranges', 'bytes')
        response.setHeader('Content-Range',
                           'bytes %s-%s/%s' % (start, end - 1, size))
        response.setHeader('Content-Length', str(end - start))
        #Print.info(response.headers['Content-Range'])
        response.sendHeader()

        if not response.head:
            size = end - start

            i = 0

            while i < size:
                chunk = f.read(min(size - i, chunkSize))
                i += len(chunk)

                if chunk:
                    pass
                    response.write(chunk)
                else:
                    break
Ejemplo n.º 10
0
Archivo: Api.py Proyecto: carlchina/nut
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)}))
Ejemplo n.º 11
0
def verifyKey(titleId=None, titleKey=None):
    try:
        if not titleId:
            titleId = request.args.get('titleId')

        if not titleKey:
            titleKey = request.args.get('titleKey')

        # Check that the required fields are in the POST'ed data
        required = ['titleId', 'titleKey']
        if not titleId or not titleKey:
            return False

        titleId = titleId.upper()

        if blockchain.hasTitle(titleId):
            if blockchain.hasTitle(titleId) == titleKey:
                return True
            else:
                return False

        nsp = Nsps.getByTitleId(titleId)

        if not nsp:
            return False

        nsp.open()

        for f in nsp:
            if type(
                    f
            ) == Fs.Nca and f.header.contentType == Type.Content.PROGRAM:
                for fs in f.sectionFilesystems:
                    if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR:
                        f.seek(0)
                        ncaHeader = f.read(0x400)

                        sectionHeaderBlock = fs.buffer

                        f.seek(fs.offset)
                        pfs0Header = f.read(0x10)

                        entry = KeyEntry(titleId, titleKey.upper(), ncaHeader,
                                         sectionHeaderBlock, pfs0Header,
                                         fs.offset)

                        index = blockchain.new_transaction(entry)

                        blockchain.new_block()
                        nsp.close()
                        return True
        nsp.close()

        return False
    except BaseException as e:
        nsp.close()
        return False
Ejemplo n.º 12
0
def new_suggestion():
    try:
        titleId = request.args.get('titleId')
        titleKey = request.args.get('titleKey')

        # Check that the required fields are in the POST'ed data
        required = ['titleId', 'titleKey']
        if not titleId or not titleKey:
            return 'Missing values', 400

        titleId = titleId.upper()
        nsp = Nsps.getByTitleId(titleId)

        if not nsp:
            return 'Title not found', 400

        nsp.open()

        for f in nsp:
            if type(
                    f
            ) == Fs.Nca and f.header.contentType == Type.Content.PROGRAM:
                for fs in f.sectionFilesystems:
                    if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR:
                        f.seek(0)
                        ncaHeader = f.read(0x400)

                        sectionHeaderBlock = fs.buffer

                        f.seek(fs.offset)
                        pfs0Header = f.read(0x10)

                        entry = KeyEntry(titleId, titleKey.upper(), ncaHeader,
                                         sectionHeaderBlock, pfs0Header,
                                         fs.offset)

                        index = blockchain.new_transaction(entry)

                        blockchain.new_block()

                        response = {
                            'message':
                            f'Transaction will be added to Block {index}'
                        }
                        return jsonify(response), 201

        return 'Verification failed: unable to locate correct title rights partition', 400
    except BaseException as e:
        return str(e), 400
Ejemplo n.º 13
0
Archivo: nut.py Proyecto: carlchina/nut
def scan():
    global hasScanned

    #if hasScanned:
    #	return
    hasScanned = True
    initTitles()
    initFiles()

    refreshRegions()
    importRegion(Config.region, Config.language)

    r = Nsps.scan(Config.paths.scan)
    Titles.save()
    return r
Ejemplo n.º 14
0
Archivo: Api.py Proyecto: carlchina/nut
def getDownload(request, response, start=None, end=None):
    try:
        nsp = Nsps.getByTitleId(request.bits[2])
        response.attachFile(nsp.titleId + '.nsp')

        if len(request.bits) >= 5:
            start = int(request.bits[3])
            end = int(request.bits[4])

        chunkSize = 0x400000

        with open(nsp.path, "rb") as f:
            f.seek(0, 2)
            size = f.tell()
            if 'Range' in request.headers:
                start, end = request.headers.get('Range').strip().strip(
                    'bytes=').split('-')

                if end == '':
                    end = size - 1
                else:
                    end = int(end) + 1

                if start == '':
                    start = size - end
                else:
                    start = int(start)

                if start >= size or end > size or start < 0 or end <= 0:
                    return Server.Response400(request, response,
                                              'Invalid range request')

                response.setStatus(206)

            else:
                if start == None:
                    start = 0
                if end == None:
                    end = size

            if end >= size:
                end = size

                if end <= start:
                    response.write(b'')
                    return

            print('ranged request for %d - %d' % (start, end))
            f.seek(start, 0)

            response.setMime(nsp.path)
            response.setHeader('Accept-Ranges', 'bytes')
            response.setHeader('Content-Range',
                               'bytes %s-%s/%s' % (start, end - 1, size))
            response.setHeader('Content-Length', str(end - start))
            #Print.info(response.headers['Content-Range'])
            response.sendHeader()

            if not response.head:
                size = end - start

                i = 0

                while i < size:
                    chunk = f.read(min(size - i, chunkSize))
                    i += len(chunk)

                    if chunk:
                        pass
                        response.write(chunk)
                    else:
                        break
    except BaseException as e:
        Print.error('NSP download exception: ' + str(e))
    if response.bytesSent == 0:
        response.write(b'')
Ejemplo n.º 15
0
def verifyKey(titleId=None, titleKey=None):
    try:
        if not titleId:
            titleId = request.args.get('titleId')

        if not titleKey:
            titleKey = request.args.get('titleKey')

        # Check that the required fields are in the POST'ed data
        required = ['titleId', 'titleKey']
        if not titleId or not titleKey:
            return False

        titleId = titleId.upper()

        if blockchain.hasTitle(titleId):
            if blockchain.hasTitle(titleId) == titleKey:
                return True
            else:
                return False

        nsp = Nsps.getByTitleId(titleId)

        if not nsp:
            Print.info('404 ' + titleId)
            return False

        nsp.open()

        for f in nsp:
            if type(
                    f
            ) == Fs.Nca and f.header.contentType == Type.Content.PROGRAM:
                for fs in f.sectionFilesystems:
                    if fs.fsType == Type.Fs.PFS0 and fs.cryptoType == Type.Crypto.CTR:
                        f.seek(0)
                        ncaHeader = f.read(0x400)

                        sectionHeaderBlock = fs.buffer

                        f.seek(fs.offset)
                        pfs0Header = f.read(0x10)

                        entry = KeyEntry(titleId, titleKey.upper(), ncaHeader,
                                         sectionHeaderBlock, pfs0Header,
                                         fs.offset)

                        index = blockchain.new_transaction(entry)

                        blockchain.new_block()
                        nsp.close()
                        return True

        for f in nsp:
            if type(f) == Fs.Nca:
                for fs in f.sectionFilesystems:
                    if fs.fsType == Type.Fs.ROMFS and fs.cryptoType == Type.Crypto.CTR:
                        f.seek(0)
                        ncaHeader = f.read(0x400)

                        sectionHeaderBlock = fs.buffer

                        levelOffset = int.from_bytes(
                            sectionHeaderBlock[0x18:0x20],
                            byteorder='little',
                            signed=False)
                        levelSize = int.from_bytes(
                            sectionHeaderBlock[0x20:0x28],
                            byteorder='little',
                            signed=False)

                        offset = fs.offset + levelOffset

                        f.seek(offset)
                        pfs0Header = f.read(levelSize)

                        entry = KeyEntry(titleId, titleKey.upper(), ncaHeader,
                                         sectionHeaderBlock, pfs0Header,
                                         offset)

                        index = blockchain.new_transaction(entry)

                        blockchain.new_block()
                        nsp.close()
                        return True

        nsp.close()

        return False
    except BaseException as e:
        print('key exception: ' + str(e))
        nsp.close()
        return False