async def ipIdentifierInit(self, ipfsop, ipid: IPIdentifier): # Register the blog as an IP service on the DID blogPath = IPFSPath(joinIpns(self.keyRootId)).child('blog') await ipid.addServiceRaw( { 'id': ipid.didUrl(path='/blog'), 'type': IPService.SRV_TYPE_DWEBBLOG, 'serviceEndpoint': blogPath.ipfsUrl }, publish=False) # Register the Atom feed as an IP service on the DID feedPath = IPFSPath(joinIpns(self.keyRootId)).child('dfeed.atom') await ipid.addServiceRaw( { 'id': ipid.didUrl(path='/feed'), 'type': IPService.SRV_TYPE_ATOMFEED, 'serviceEndpoint': feedPath.ipfsUrl, 'description': 'Dweb Atom feed' }, publish=False) await ipid.addServiceCollection('default') entry = await self.ctx.app.importQtResource('/share/icons/helmet.png') if entry: defAvatar = IPFSPath(entry['Hash']) await ipid.avatarSet(defAvatar.objPath)
async def resolve(self, ipfsop, resolveTimeout=None): resolveTimeout = resolveTimeout if resolveTimeout else \ cGet('resolve.timeout') if self.local: hours = cGet('resolve.cacheLifetime.local.hours') else: hours = cGet('resolve.cacheLifetime.default.hours') maxLifetime = hours * 3600 useCache = 'always' cache = 'always' self.message('DID resolve: {did} (using cache: {usecache})'.format( did=self.ipnsKey, usecache=useCache)) return await ipfsop.nameResolveStreamFirst( joinIpns(self.ipnsKey), count=1, timeout=resolveTimeout, useCache=useCache, cache=cache, cacheOrigin='ipidmanager', maxCacheLifetime=maxLifetime )
async def validateQr(self, ipfsop, qrCid, iMsg): validCodes = 0 try: codes = await self.app.rscAnalyzer.decodeQrCodes(qrCid) if not codes: # QR decoder not available, or invalid QR return False if len(codes) not in range(2, 4): return False for code in codes: if isinstance(code, IPFSPath): if code.isIpns and str(code) == joinIpns(iMsg.peer): validCodes += 1 if code.isIpfs: computed = await ipfsop.hashComputeString( iMsg.iphandle) if computed['Hash'] == stripIpfs(code.objPath): validCodes += 1 elif isinstance(code, str) and ipidFormatValid(code) and \ code == iMsg.personDid: validCodes += 1 except Exception as e: log.debug('QR decode error: {}'.format(str(e))) return False else: # Just use 3 min codes here when we want the DID to be required return validCodes >= 2 return False
async def handleRequest(self, ipfsop, request, uid): rUrl = request.requestUrl() scheme = rUrl.scheme() host = rUrl.host() if not host: return self.urlInvalid(request) if scheme == SCHEME_IPFS: # hostname = base32-encoded CID or FQDN # # We keep a list (deque) of CIDs that have been validated. # If you hit a page which references a lot of other resources # for instance, this should be faster than regexp if domainValid(host): ipfsPathS = joinIpns(host) + rUrl.path() else: if host not in self.validCids: if not ipfsRegSearchCid32(host): return self.urlInvalid(request) self.validCids.append(host) ipfsPathS = joinIpfs(host) + rUrl.path() elif scheme == SCHEME_IPNS: ipfsPathS = joinIpns(host) + rUrl.path() else: return self.urlInvalid(request) ipfsPath = IPFSPath(ipfsPathS) if not ipfsPath.valid: return self.urlInvalid(request) try: with async_timeout.timeout(self.requestTimeout): return await self.fetchFromPath(ipfsop, request, ipfsPath, uid) except asyncio.TimeoutError: return self.reqFailed(request) except Exception as err: # Any other error traceback.print_exc() self.debug(f'Unknown error while serving request: {err}') return self.reqFailed(request)
async def ipIdentifierInit(self, ipfsop, ipid: IPIdentifier): # Register the blog as an IP service on the DID blogPath = IPFSPath(joinIpns(self.keyRootId)).child('blog') await ipid.addServiceRaw({ 'id': ipid.didUrl(path='/blog'), 'type': IPService.SRV_TYPE_DWEBBLOG, 'serviceEndpoint': blogPath.ipfsUrl }, publish=False) # Register the Atom feed as an IP service on the DID feedPath = IPFSPath(joinIpns(self.keyRootId)).child('dfeed.atom') await ipid.addServiceRaw({ 'id': ipid.didUrl(path='/feed'), 'type': IPService.SRV_TYPE_ATOMFEED, 'serviceEndpoint': feedPath.ipfsUrl, 'description': 'Dweb Atom feed' }, publish=False) await ipid.addServiceCollection('default')
async def resolve(self, ipfsop, resolveTimeout=30): useCache = 'always' if self.local else 'never' maxLifetime = 86400 * 7 if self.local else 60 * 10 self.message('DID resolve: {did} (using cache: {usecache})'.format( did=self.ipnsKey, usecache=useCache)) return await ipfsop.nameResolveStreamFirst( joinIpns(self.ipnsKey), timeout=resolveTimeout, useCache=useCache, maxCacheLifetime=maxLifetime)
async def nsCacheSet(self, path, resolved, origin=None): self.cache[path] = { 'resolved': resolved, 'resolvedLast': int(time.time()), 'cacheOrigin': origin } # Cache v1 v1 = ipnsKeyCidV1(stripIpns(path)) if v1: self.cache[joinIpns(v1)] = { 'resolved': resolved, 'resolvedLast': int(time.time()), 'cacheOrigin': origin } await self.nsCacheSave()
async def async_loader(client, url): """ :param url: the URL to retrieve. :return: the RemoteDocument. """ try: if url.startswith('ipschema://'): o = urlparse(url) kList = await client.key.list() ipnsKey = None for key in kList['Keys']: if key['Name'] == o.netloc: ipnsKey = key['Id'] if ipnsKey is None: path = None else: path = IPFSPath(joinIpns(ipnsKey)).child(o.path) else: path = IPFSPath(url) if not path.valid: raise Exception('Not a valid path') if path and path.valid: data = await client.cat(path.objPath) return { 'document': json.loads(data.decode()), 'documentUrl': url, 'contextUrl': None } except aioipfs.APIError as e: log.debug(str(e)) raise e except JsonLdError as e: log.debug(str(e)) raise e except Exception as cause: raise JsonLdError( 'Could not retrieve a JSON-LD document from the URL.', 'jsonld.LoadDocumentError', code='loading document failed', cause=cause)
async def encodeIpHandleQr(self, ipfsop, iphandle, format='raw', filename=None): encoder = IPFSQrEncoder() try: entry = await ipfsop.addString(iphandle, only_hash=True) if not entry: return encoder.add(entry['Hash']) encoder.add(self.profile.userInfo.personDid) encoder.add(joinIpns(ipfsop.ctx.node.id)) return await encoder.encodeAndStore(format=format) except Exception: # TODO pass
async def encodeIpHandleQr(self, ipfsop, iphandle, did, format='png', filename=None): encoder = IPFSQrEncoder() try: entry = await ipfsop.addString(iphandle, pin=True, only_hash=True) if not entry: return await ipfsop.sleep() encoder.add(joinIpfs(entry['Hash'])) encoder.add(joinIpns(ipfsop.ctx.node.id)) if didIdentRe.match(did): encoder.add(did) return await encoder.encodeAndStore(format=format) except Exception: pass
async def async_loader(client, url, options={}): """ :param url: the URL to retrieve. :return: the RemoteDocument. """ try: o = urlparse(url) if o.scheme in ['ipschema', 'ips']: ipsKey = o.netloc if ipsKey == 'galacteek.ld.contexts': # Compat ipsKey = 'galacteek.ld' if not o.path or o.path == '/': return { 'contentType': 'application/ld+json', 'document': {}, 'documentUrl': url, 'contextUrl': None } raise JsonLdError(f'Invalid context path for URL: {url}', 'jsonld.InvalidUrl', {'url': url}, code='loading document failed') kList = await client.key.list() ipnsKey = None for key in kList['Keys']: if key['Name'] == ipsKey: ipnsKey = key['Id'] path = None if ipnsKey is None else IPFSPath( joinIpns(ipnsKey)).child(o.path) else: path = IPFSPath(url) if not path.valid: raise Exception(f'Not a valid path: {url}') if path and path.valid: data = await asyncio.wait_for(client.cat(path.objPath), 10) obj = orjson.loads(data.decode()) assert obj is not None return { 'contentType': 'application/ld+json', 'document': obj, 'documentUrl': url, 'contextUrl': None } except asyncio.TimeoutError as terr: log.debug(str(terr)) raise terr except aioipfs.APIError as e: log.debug(str(e)) raise e except JsonLdError as e: log.debug(str(e)) raise e except Exception as cause: raise JsonLdError( 'Could not retrieve a JSON-LD document from the URL.', 'jsonld.LoadDocumentError', code='loading document failed', cause=cause)
def sitePath(self): return IPFSPath(joinIpns(self.ipnsKey))