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)}))
def getInfo(request, response): try: nsp = Nsps.getByTitleId(request.bits[2]) t = {'id': request.bits[2]} 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)}))
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 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, fs = fs) index = blockchain.new_transaction(entry) blockchain.new_block() return True return False
def getInfo(request, response): try: response.headers['Content-Type'] = 'application/json' 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)}))
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
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[-2]) end = int(request.bits[-1]) #chunkSize = 0x1000000 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 start < 0 or end <= 0: return Server.Response400( request, response, 'Invalid range request %d - %d' % (start, end)) 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 status = Status.create( size, 'Downloading ' + os.path.basename(nsp.path)) while i < size: chunk = f.read(min(size - i, chunkSize)) i += len(chunk) status.add(len(chunk)) if chunk: pass response.write(chunk) else: break status.close() except BaseException as e: Print.error('NSP download exception: ' + str(e)) traceback.print_exc(file=sys.stdout) if response.bytesSent == 0: response.write(b'')
else: Print.info('Title key is INVALID %s - %s' % (args.verify[0], args.verify[1])) if args.restore: nut.initTitles() nut.initFiles() prev = Config.extractVersion Config.extractVersion = True for path in expandFiles(args.file): try: f = Fs.factory(str(path)) f.setPath(str(path)) if f and f.titleId: dt = Nsps.getByTitleId(f.titleId) if dt and int(dt.version) >= int( f.getFileVersion()): f.moveDupe() continue f.open(str(path), 'r+b') f.restore() f.close() Print.info('restored %s' % f._path) if args.output: newPath = os.path.join(args.output, os.path.basename(f._path)) Print.info('moving %s -> %s' % (path, newPath)) shutil.move(f._path, newPath)
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