async def handleRequest(self, request): rUrl = request.requestUrl() if not rUrl.isValid(): return self.urlInvalid(request) domain = rUrl.host() uPath = rUrl.path() if not domain or len(domain) > 512 or not domainValid(domain): log.info('EthDNS: invalid domain request') return self.urlInvalid(request) pathRaw = await self.ethResolver.resolveEnsDomain(domain) path = IPFSPath(pathRaw, autoCidConv=True) if path and path.valid: await ensDomainResolved.emit(domain, path) sPath = path.child(uPath) if uPath else path log.debug('EthDNS: {domain} resolved to {res}'.format( domain=domain, res=sPath.ipfsUrl)) return request.redirect(QUrl(sPath.dwebUrl)) else: log.info('EthDNS: {domain} resolve failed'.format(domain=domain)) return self.urlNotFound(request)
async def startVideoCall(self, ipfsop, rvTopic): rootPath = IPFSPath(ipfsop.ctx.resources['app-videocall']['Hash']) offerPath = rootPath.child('offer.html') offerPath.fragment = rvTopic tab = self.app.mainWindow.addBrowserTab() tab.browseFsPath(offerPath)
async def dagCompact(self, ipfsPath: IPFSPath, context=None): """ Compact a DAG """ try: # Note: we still do the schemas inlining (when # a @context is referenced with IPLD) to # support DAGs which weren't upgraded yet dag = await self.operator.ldInline( await self.operator.dagGet(str(ipfsPath)) ) assert dag is not None if not context: # Get the @context we'll compact with context = await self.operator.dagGet( str(ipfsPath.child('@context')) ) compacted = await jsonld.compact( dag, context, { 'base': gLdBaseUri, 'documentLoader': self.ldLoader, 'compactArrays': True } ) except Exception as err: self.operator.debug(f'Error expanding : {err}') raise err except aioipfs.APIError as err: self.operator.debug(f'IPFS error expanding : {err.message}') raise err else: return compacted
async def urlProxiedPath(self, rUrl): domain = rUrl.host() uPath = rUrl.path() if not domain or len(domain) > 512 or not domainValid(domain): return None pathRaw = await self.ethResolver.resolveEnsDomain(domain) path = IPFSPath(pathRaw, autoCidConv=True) if path and path.valid: return path.child(uPath) if uPath else path
def browseManualPage(self, pagePath, fragment=None): manual = self.registry.get(self.defaultManualLang) if not manual: return False manualPath = IPFSPath(manual['Hash']) if not manualPath.valid: return False ipfsPath = manualPath.child(pagePath) ipfsPath.fragment = fragment ensure(self.app.resourceOpener.open(ipfsPath))
async def renderDirectory(self, request, ipfsop, path): ipfsPath = IPFSPath(path) indexPath = ipfsPath.child('index.html') try: data = await ipfsop.catObject(str(indexPath)) except aioipfs.APIError as exc: dec = APIErrorDecoder(exc) if dec.errNoSuchLink(): return await self.directoryListing(request, ipfsop, path) return self.urlInvalid(request) else: return data
async def open(self, ipfsop, pathRef, mimeType=None, openingFrom=None, pyramidOrigin=None, minWebProfile='ipfs', schemePreferred=None, tryDecrypt=False, fromEncrypted=False, editObject=False, pin=False, burnAfterReading=False, useWorkspace=None): """ Open the resource referenced by rscPath according to its MIME type :param pathRef: IPFS object's path (can be str or IPFSPath) :param openingFrom str: UI component making the open request :param minWebProfile str: Minimum Web profile to use :param tryDecrypt bool: Try to decrypt the object or not :param editObject bool: Set Text Editor in edit mode for text files :param MIMEType mimeType: MIME type """ ipfsPath = None statInfo = None if isinstance(pathRef, IPFSPath): ipfsPath = pathRef elif isinstance(pathRef, str): url = QUrl(pathRef) if isEnsUrl(url): return self.openEnsUrl(url, pin=pin) if isUrlSupported(url): return self.openUrl(url) ipfsPath = IPFSPath(pathRef, autoCidConv=True) else: raise ValueError(f'Invalid input value: {pathRef}') if not ipfsPath.valid: return False rscPath = ipfsPath.objPath if self.app.mainWindow.pinAllGlobalChecked: ensure( ipfsop.ctx.pinner.queue(rscPath, False, None, qname='default')) rscShortName = ipfsPath.shortRepr() if ipfsPath.isIpfs: # Try to reuse metadata from the multihash store rscMeta = await self.app.multihashDb.get(rscPath) if rscMeta: cachedMime = rscMeta.get('mimetype') cachedStat = rscMeta.get('stat') if cachedMime: mimeType = MIMEType(cachedMime) if cachedStat: statInfo = StatInfo(cachedStat) wsSwitch = True mtConfig = self.cObjectOpener.mimeTypes.default if mimeType is None: ltBefore = loopTime() mimeType = await detectMimeType(rscPath) spent = loopTime() - ltBefore if spent > mtConfig.slowObjectTimer: # We won't switch workspaces wsSwitch = False if mimeType and mimeType.valid: logUser.info('{path} ({type}): opening'.format(path=rscPath, type=str(mimeType))) else: logUser.info(iResourceCannotOpen(rscPath)) return hashmark = await hashmarksByPath(rscPath) if hashmark and not useWorkspace: await hashmark._fetch_all() useWorkspace = self.app.mainWindow.stack.wsHashmarkTagRulesRun( hashmark) if mimeType == mimeTypeDagUnknown: indexPath = ipfsPath.child('index.html') stat = await ipfsop.objStat(indexPath.objPath, timeout=8) if stat: # Browse the index return self.app.mainWindow.addBrowserTab( minProfile=minWebProfile, pinBrowsed=pin).browseFsPath( indexPath, schemePreferred=schemePreferred) # Otherwise view the DAG view = DAGViewer(rscPath, self.app.mainWindow) self.app.mainWindow.registerTab(view, iDagViewer(), current=True, icon=getIcon('ipld.png'), tooltip=rscPath) return if mimeType.type == 'application/octet-stream' and not fromEncrypted: # Try to decode it with our key if it's a small file if statInfo is None: statInfo = StatInfo(await ipfsop.objStat(rscPath, timeout=5)) profile = ipfsop.ctx.currentProfile if profile and statInfo.valid and \ (statInfo.dataSmallerThan(megabytes(8)) or tryDecrypt): data = await ipfsop.catObject(ipfsPath.objPath, timeout=30) if not data: # XXX return decrypted = await profile.rsaAgent.decrypt(data) if decrypted: # # "Good evening, 007" # # Create a short-lived IPFS offline file (not announced) # with the decrypted content and open it # logUser.info('{path}: RSA OK'.format(path=rscPath)) # This one won't be announced or pinned entry = await ipfsop.addBytes(decrypted, offline=True, pin=False) if not entry: logUser.info( '{path}: cannot import decrypted file'.format( path=rscPath)) return # Open the decrypted file return ensure( self.open(entry['Hash'], fromEncrypted=True, burnAfterReading=True)) else: logUser.debug( '{path}: decryption impossible'.format(path=rscPath)) if mimeType.isText or editObject: tab = TextEditorTab(parent=self.app.mainWindow, editing=editObject, pyramidOrigin=pyramidOrigin) tab.editor.display(ipfsPath) self.objectOpened.emit(ipfsPath) return self.app.mainWindow.registerTab( tab, rscShortName, icon=getMimeIcon('text/x-generic'), tooltip=rscPath, current=True, workspace=WS_EDIT) if mimeType.isImage or mimeType.isAnimation: tab = ImageViewerTab(self.app.mainWindow) ensure(tab.view.showImage(rscPath)) self.objectOpened.emit(ipfsPath) return self.app.mainWindow.registerTab( tab, rscShortName, icon=getMimeIcon('image/x-generic'), tooltip=rscPath, current=True) if mimeType.isVideo or mimeType.isAudio: tab = self.app.mainWindow.getMediaPlayer() if tab: tab.playFromPath(rscPath) return if mimeType == 'application/pdf' and 0: # not usable yet tab = WebTab(self.app.mainWindow) tab.attach(DWebView(page=PDFViewerPage(rscPath))) self.objectOpened.emit(ipfsPath) return self.app.mainWindow.registerTab( tab, rscShortName, icon=getMimeIcon('application/pdf'), tooltip=rscPath, current=True) if mimeType.isHtml: self.objectOpened.emit(ipfsPath) return self.app.mainWindow.addBrowserTab( minProfile=minWebProfile, pinBrowsed=pin, workspace=useWorkspace, wsSwitch=wsSwitch).browseFsPath( ipfsPath, schemePreferred=schemePreferred) if mimeType.isDir: indexPath = ipfsPath.child('index.html') stat = await ipfsop.objStat(indexPath.objPath, timeout=8) if stat: self.objectOpened.emit(ipfsPath) return self.app.mainWindow.addBrowserTab( minProfile=minWebProfile, pinBrowsed=pin, workspace=useWorkspace, wsSwitch=wsSwitch).browseFsPath( ipfsPath, schemePreferred=schemePreferred) else: return await self.app.mainWindow.exploreIpfsPath(ipfsPath) if mimeType.isBitTorrent: wStack = self.app.mainWindow.stack with wStack.workspaceCtx(WS_FILES, show=True) as ws: btClient = await ws.getTorrentClient() return await btClient.addTorrentFromIpfs(ipfsPath) if openingFrom in ['filemanager', 'qa', 'didlocal']: await self.needUserConfirm.emit(ipfsPath, mimeType, True) else: await self.needUserConfirm.emit(ipfsPath, mimeType, False)