Exemplo n.º 1
0
    async def fetchAvatar(self, ipfsop):
        avatarServiceId = self.ipid.didUrl(path='/avatar')
        service = await self.ipid.searchServiceById(avatarServiceId)

        if service:
            avatarPath = IPFSPath(service.endpoint)

            if not avatarPath.valid:
                log.debug(f'Invalid avatar for peer {self.peerId}')

            self._avatarPath = avatarPath

            statInfo = StatInfo(
                await ipfsop.objStat(str(avatarPath),
                                     timeout=15)
            )

            if not statInfo.valid or statInfo.dataLargerThan(
                    kilobytes(768)):
                log.debug(f'Invalid avatar for peer {self.peerId}')
                return

            await ipfsop.ctx.pin(str(avatarPath), qname='ipid-avatar')

            log.debug(
                f'Getting avatar for peer {self.peerId} from {avatarPath}')

            image = await getImageFromIpfs(str(avatarPath))

            if image and not image.isNull():
                self._avatarImage = image
            else:
                log.debug(f'Could not fetch avatar for peer {self.peerId}')
Exemplo n.º 2
0
async def getIconFromIpfs(ipfsop,
                          ipfsPath,
                          scaleWidth=None,
                          sizeMax=kilobytes(256),
                          timeout=10):
    """
    We cache the icons that we got out of the IPFS repo by their path
    Max icons cached is set by 'ipfsIconsCacheMax' in the app object
    """
    app = QApplication.instance()
    iconsCache = app.ipfsIconsCache

    if ipfsPath in iconsCache:
        # Already cached
        return iconsCache[ipfsPath]

    if len(iconsCache) >= app.ipfsIconsCacheMax:
        # FIFO 1/8
        for icount in range(0, int(app.ipfsIconsCacheMax / 8)):
            out = list(iconsCache.keys())[0]
            del iconsCache[out]

    try:
        mimeType, stat = await app.rscAnalyzer(ipfsPath)
        if not mimeType or not stat:
            return None

        statInfo = StatInfo(stat)

        if not statInfo.valid or statInfo.dataLargerThan(sizeMax):
            return None
        elif not mimeType.isImage:
            return None

        imgData = await ipfsop.waitFor(ipfsop.client.cat(ipfsPath), timeout)

        if not imgData:
            return None

        icon = getIconFromImageData(imgData, scaleWidth=scaleWidth)
        if icon:
            iconsCache[ipfsPath] = icon
            return icon
    except BaseException:
        return None
Exemplo n.º 3
0
    async def analyzeImage(self, ipfsop):
        statInfo = StatInfo(self.item.stat)

        if statInfo.valid:
            size = statInfo.dataSize

            if isinstance(size, int):
                # don't scan anything larger than 4Mb
                if statInfo.dataLargerThan(megabytes(4)):
                    log.debug('{path}: Image too large, not scanning')
                    return
        else:
            # Don't trust this one
            log.debug('No object info for image, bailing out')
            return

        try:
            data = await ipfsop.catObject(self.item.path)

            if data is None:
                return

            icon = getIconFromImageData(data)
            if icon:
                self.updateIcon(icon)

            # Decode the QR codes in the image if there's any
            qrDecoder = IPFSQrDecoder()
            if not qrDecoder:
                return

            urls = qrDecoder.decode(data)
            if isinstance(urls, list):
                # Display the QR codes in a separate menu
                menu = qrCodesMenuBuilder(urls, self.app.resourceOpener,
                                          parent=self)
                self.menu.addSeparator()
                self.menu.addMenu(menu)

        except aioipfs.APIError:
            pass
Exemplo n.º 4
0
    async def registerFromIdent(self, ipfsop, sender, iMsg):
        profile = ipfsop.ctx.currentProfile

        log.debug(f'registerFromIdent ({iMsg.peer}): '
                  f'DID: {iMsg.personDid}, handle: {iMsg.iphandle}')

        try:
            inGraph = await profile.dagNetwork.byDid(iMsg.personDid)
        except Exception:
            # network dag not ready ..
            log.debug(f'registerFromIdent {iMsg.personDid}: '
                      'network DAG not loaded yet ?')
            return

        if not inGraph:
            if isinstance(iMsg, PeerIdentMessageV4) and \
                    sender != ipfsop.ctx.node.id:
                pubKeyPem = await ipfsop.rsaPubKeyCheckImport(
                    iMsg.defaultRsaPubKeyCid)

                if not pubKeyPem:
                    log.debug(
                        f'Invalid RSA pub key .. {iMsg.defaultRsaPubKeyCid}')
                    return

                sigBlob = await ipfsop.catObject(iMsg.pssSigCurDid)
                if sigBlob is None:
                    log.debug(
                        f'Cannot get pss SIG {iMsg.pssSigCurDid}')
                    return

                if not await ipfsop.ctx.rsaExec.pssVerif(
                    iMsg.personDid.encode(),
                    sigBlob,
                    pubKeyPem
                ):
                    log.debug(f'Invalid PSS sig for peer {sender}')
                    return
                else:
                    log.debug(f'Valid PSS sig for {sender} !')

            peerValidated = False
            personDid = iMsg.personDid

            if not ipidFormatValid(personDid):
                log.debug('Invalid DID: {}'.format(personDid))
                return

            inProgress = self._didAuthInp.get(personDid, False)

            if inProgress is True:
                log.debug(f'registerFromIdent {iMsg.personDid}: '
                          f'authentication in progress')
                return

            self._didAuthInp[personDid] = True

            try:
                mType, stat = await self.app.rscAnalyzer(iMsg.iphandleqrpngcid)
            except Exception:
                log.debug('Cannot stat QR: {}'.format(iMsg.iphandleqrpngcid))
                self._didAuthInp[personDid] = False
                return
            else:
                statInfo = StatInfo(stat)

                if not statInfo.valid or statInfo.dataLargerThan(
                        kilobytes(512)) or not mType or not mType.isImage:
                    log.debug('Invalid stat for QR: {}'.format(
                        iMsg.iphandleqrpngcid))
                    self._didAuthInp[personDid] = False
                    return

                if not await self.validateQr(
                        iMsg.iphandleqrpngcid, iMsg) is True:
                    log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid))
                    peerValidated = False
                    self._didAuthInp[personDid] = False
                    return
                else:
                    log.debug('Ident QR {qr} for {peer} seems valid'.format(
                        qr=iMsg.iphandleqrpngcid, peer=iMsg.peer))
                    peerValidated = True

                await ipfsop.ctx.pin(iMsg.iphandleqrpngcid)

            # Load the IPID

            loadAttempts = cGet('peers.didLoadAttempts')

            for attempt in range(0, loadAttempts):
                ipid = await self.app.ipidManager.load(
                    personDid,
                    localIdentifier=(iMsg.peer == ipfsop.ctx.node.id)
                )

                if ipid:
                    break

            if not ipid:
                log.debug(f'Cannot load DID: {personDid}')
                self._didAuthInp[personDid] = False
                return

            async with self.lock.writer_lock:
                piCtx = self.getByHandle(iMsg.iphandle)

                if not piCtx:
                    log.debug(f'Creating new PeerIdentityCtx for '
                              f'{iMsg.iphandle} ({personDid})')

                    piCtx = PeerIdentityCtx(
                        self.ctx, iMsg.peer, iMsg.iphandle,
                        ipid,
                        validated=peerValidated
                    )

                    ipid.sChanged.connectTo(partialEnsure(
                        self.onPeerDidModified, piCtx))
                    piCtx.sStatusChanged.connectTo(partialEnsure(
                        self.peerModified.emit, piCtx))

                piCtx.ident = iMsg

                if not piCtx.authFailedRecently:
                    ensure(self.didPerformAuth(piCtx, iMsg))

                self._byHandle[iMsg.iphandle] = piCtx
        else:
            # This peer is already registered in the network graph
            # What we ought to do here is just to refresh the DID document

            async with self.lock.writer_lock:
                piCtx = self.getByHandle(iMsg.iphandle)

                if piCtx:
                    self._byPeerId[piCtx.peerId] = piCtx

                    piCtx.ident = iMsg
                    await piCtx.ipid.refresh()

                    await self.peerModified.emit(piCtx)

        await self.changed.emit()
Exemplo n.º 5
0
    async def registerFromIdent(self, op, iMsg):
        # iMsg is a PeerIdentMessage

        if iMsg.peer not in self.byPeerId:
            peerValidated = False

            now = int(time.time())
            avgPing = await op.waitFor(op.pingAvg(iMsg.peer, count=2), 5)

            personDid = iMsg.personDid

            if not ipidFormatValid(personDid):
                log.debug('Invalid DID: {}'.format(personDid))
                return

            try:
                mType, stat = await self.app.rscAnalyzer(iMsg.iphandleqrpngcid)
            except Exception:
                log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid))
            else:
                statInfo = StatInfo(stat)

                if not statInfo.valid or statInfo.dataLargerThan(
                        kilobytes(512)) or not mType or not mType.isImage:
                    log.debug('Invalid stat for QR: {}'.format(
                        iMsg.iphandleqrpngcid))
                    return

                if not await self.validateQr(
                        iMsg.iphandleqrpngcid, iMsg) is True:
                    log.debug('Invalid QR: {}'.format(iMsg.iphandleqrpngcid))
                    peerValidated = False
                else:
                    log.debug('Ident QR {qr} for {peer} seems valid'.format(
                        qr=iMsg.iphandleqrpngcid, peer=iMsg.peer))
                    peerValidated = True

                ensure(op.ctx.pin(iMsg.iphandleqrpngcid))

            # Load the IPID
            ipid = await self.app.ipidManager.load(
                personDid,
                initialCid=iMsg.personDidCurCid,
                track=True
            )

            if not ipid:
                log.debug('Cannot load DID: {}'.format(personDid))
                return

            async with self.lock:
                pCtx = PeerCtx(self.ctx, iMsg.peer, iMsg, ipid,
                               pingavg=avgPing if avgPing else 0,
                               pinglast=now if avgPing else 0,
                               validated=peerValidated
                               )
                ipid.sChanged.connectTo(partialEnsure(
                    self.onPeerDidModified, pCtx))
                pCtx.sInactive.connectTo(self.onUnresponsivePeer)

                ensure(self.didPerformAuth(pCtx))

                self._byPeerId[iMsg.peer] = pCtx
                ensureLater(60, pCtx.watch)

            await self.peerAdded.emit(iMsg.peer)
        else:
            # This peer is already registered
            # What we ought to do here is just to refresh the DID document

            async with self.lock:
                pCtx = self.getByPeerId(iMsg.peer)
                if pCtx:
                    log.debug('Updating ident for peer {}'.format(iMsg.peer))
                    pCtx.ident = iMsg

                    log.debug('Refreshing DID: {}'.format(pCtx.ipid))
                    await pCtx.ipid.refresh()

                    await self.peerModified.emit(iMsg.peer)

        await self.changed.emit()
Exemplo n.º 6
0
    async def analyzeFeed(self, ipfsop):
        statInfo = StatInfo(self.item.stat)

        if statInfo.valid and not statInfo.dataLargerThan(megabytes(4)):
            pass