コード例 #1
0
    async def createPyramid(self, ipfsop, pyramidName, category, ipnsKeyName,
                            description, ipnsLifetime, extra):
        try:
            logUser.info(
                'Multihash pyramid {pyr}: generating IPNS key ...'.format(
                    pyr=pyramidName))
            ipnsKey = await ipfsop.keyGen(ipnsKeyName)

            if ipnsKey:
                self.marks.pyramidNew(pyramidName,
                                      category,
                                      self.iconCid,
                                      ipnskey=ipnsKey['Id'],
                                      lifetime=ipnsLifetime,
                                      type=self.pyramidType,
                                      description=description,
                                      extra=extra)
                logUser.info(
                    'Multihash pyramid {pyr}: created'.format(pyr=pyramidName))
            else:
                raise Exception('Could not generate IPNS key')
        except aioipfs.APIError as err:
            messageBox('IPFS error while creating pyramid: {}'.format(
                err.message))
        except Exception as err:
            messageBox('Error creating pyramid: {}'.format(str(err)))
コード例 #2
0
    async def scan(self, ipfsop):
        log.debug('Scanning hashmarks MFS library')

        listing = await ipfsop.filesList(self.profile.pathHMarksLibrary)

        for file in listing:
            await ipfsop.sleep()

            uid = file['Name']
            marksHash = file['Hash']

            if marksHash in self._loaded:
                continue

            fPath = os.path.join(self.profile.pathHMarksLibrary, uid)

            try:
                marksCiphered = await self.loadFromPath(fPath)

                marks = IPFSMarks(None, data=marksCiphered.root)
                self.hashmarksLoaded.emit(uid, marks)
                self._loaded.append(marksHash)
            except BaseException as err:
                log.debug('Could not load hashmarks from CID {0}: {1}'.format(
                    marksHash, str(err)))
            else:
                logUser.info('Loaded hashmarks from peer {0}'.format(uid))
                await asyncio.sleep(1)
コード例 #3
0
ファイル: clipboard.py プロジェクト: atavacron/galacteek
    async def encodeClipboardItems(self, ipfsop, encrypt=False):
        logUser.info('QR: encoding clipboard stack (encrypted: {enc})'.format(
            enc=encrypt))

        encoder = IPFSQrEncoder()

        for item in self.tracker.items:
            if item.ipfsPath.valid:
                logUser.info('QR: adding item: {item}'.format(
                    item=str(item.ipfsPath)))
                encoder.add(str(item.ipfsPath))

        logUser.info('QR: encoding ..')

        qrName = 'ipfsqr.{}.png'.format(int(time.time()))
        imgPath = self.app.tempDir.filePath(qrName)

        try:
            image = await encoder.encodeAll(loop=self.app.loop,
                                            executor=self.app.executor)
            image.save(imgPath)
        except:
            # :-/
            logUser.info('QR: encoding error ..')
            return
        else:
            logUser.info('QR: encoding successfull!')

        if ipfsop.ctx.currentProfile:
            await ipfsop.ctx.currentProfile.qrImageEncoded.emit(
                encrypt, imgPath)
コード例 #4
0
ファイル: clipboard.py プロジェクト: atavacron/galacteek
    async def dropEventLocalFile(self, ipfsop, url):
        """
        Handle a drop event with a file:// URL
        """

        maxFileSize = megabytes(64)
        try:
            path = url.toLocalFile()
            fileInfo = QFileInfo(path)

            if fileInfo.isFile():
                file = QFile(path)

                if file.open(QIODevice.ReadOnly):
                    size = file.size()

                    if size and size < maxFileSize:
                        logUser.info('Importing file: {0}'.format(path))
                        entry = await ipfsop.addPath(path)
                        if entry:
                            self.tracker.clipboardProcess(entry['Hash'])

                    file.close()
            if fileInfo.isDir():
                # Don't check for directory size
                async def entryAdded(entry):
                    logUser.info('{path}: imported'.format(
                        path=entry.get('Name')))

                entry = await ipfsop.addPath(path, callback=entryAdded)
                if entry:
                    self.tracker.clipboardProcess(entry['Hash'])
        except Exception:
            pass
コード例 #5
0
ファイル: resource.py プロジェクト: pinnaculum/galacteek
    async def openBlock(self, ipfsop, pathRef, mimeType=None):
        """
        Open the raw block referenced by pathRef

        XXX: needs improvements, this only works for images for now
        """

        ipfsPath = None

        if isinstance(pathRef, IPFSPath):
            ipfsPath = pathRef
        elif isinstance(pathRef, str):
            ipfsPath = IPFSPath(pathRef)
        else:
            raise ValueError('Invalid input value')

        if not ipfsPath.valid:
            return False

        blockStat = await ipfsop.waitFor(ipfsop.client.block.stat(pathRef), 5)

        if not blockStat or not isinstance(blockStat, dict):
            messageBox('Block is bad')

        blockSize = blockStat.get('Size')

        if blockSize > megabytes(16):
            return

        logUser.info('Block {path}: Opening'.format(path=pathRef))

        blockData = await ipfsop.client.block.get(pathRef)

        rscPath = ipfsPath.objPath
        rscShortName = rscPath
        mimeType = await detectMimeTypeFromBuffer(blockData[:1024])

        if mimeType and mimeType.valid:
            logUser.info('Block: {path} ({type}): opening'.format(
                path=rscPath, type=str(mimeType)))
        else:
            return messageBox(iResourceCannotOpen(rscPath))

        if mimeType.isImage:
            tab = ImageViewerTab(self.app.mainWindow)
            ensure(tab.view.showImage(rscPath, fromBlock=True))
            self.objectOpened.emit(ipfsPath)
            return self.app.mainWindow.registerTab(
                tab,
                rscShortName,
                icon=getMimeIcon('image/x-generic'),
                tooltip=rscPath,
                current=True)
コード例 #6
0
    async def handleRequest(self, ipfsop, request, uid):
        rUrl = request.requestUrl()
        domain = rUrl.host()

        if not domain or len(domain) > 512 or not domainValid(domain):
            logUser.info('EthDNS: invalid domain request')
            return self.urlInvalid(request)

        path = await self.urlProxiedPath(rUrl)

        if path and path.valid:
            return await self.fetchFromPath(ipfsop, request, path, uid)
        else:
            logUser.info(
                'EthDNS: {domain} resolve failed'.format(domain=domain))
            return self.urlNotFound(request)
コード例 #7
0
    async def start(self):
        if not self._web3:
            self._web3 = self.getWeb3()

        if self.web3 is None:
            log.debug('Web3 invalid')
            return

        if await self.connected():
            logUser.info('Ethereum: connected to {}'.format(
                self.params.rpcUrl))
            await self.ethConnected.emit(True)

            self._watchTask = ensure(self._e(self.watchTask))
            ensure(self.loadAutoDeploy())
            # await self.loadContracts()
        else:
            await self.ethConnected.emit(False)
コード例 #8
0
ファイル: application.py プロジェクト: atavacron/galacteek
    async def startIpfsdTask(self, ipfsd):
        started = await ipfsd.start()

        if started is False:
            return self.systemTrayMessage('IPFS', iIpfsDaemonProblem())

        running = False

        logUser.info(iIpfsDaemonStarted())

        # Use asyncio.wait_for to wait for the proto.eventStarted
        # event to be fired.

        for attempt in range(1, 32):
            logUser.info(iIpfsDaemonWaiting(attempt))

            with async_timeout.timeout(1):
                try:
                    await ipfsd.proto.eventStarted.wait()
                except asyncio.CancelledError:
                    continue
                except asyncio.TimeoutError:
                    # Event not set yet, wait again
                    log.debug('IPFSD: timeout occured while waiting for '
                              'daemon to start (attempt: {0})'.format(attempt))
                    continue
                else:
                    # Event was set, good to go
                    logUser.info(iIpfsDaemonReady())
                    running = True
                    break

        if running is True:
            ensure(self.updateIpfsClient())
        else:
            logUser.info(iIpfsDaemonInitProblem())
コード例 #9
0
    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:
            logUser.info('ENS: invalid domain request')
            return self.urlInvalid(request)

        logUser.info('ENS: resolving {0}'.format(domain))

        path = await ensContentHash(domain, sslverify=self.app.sslverify)
        if path and path.valid:
            await ensDomainResolved.emit(domain, path)
            sPath = path.child(uPath) if uPath else path
            logUser.info('ENS: {domain} resolved to {res}'.format(
                domain=domain, res=sPath.ipfsUrl))
            return request.redirect(QUrl(sPath.ipfsUrl))
        else:
            logUser.info('ENS: {domain} resolve failed'.format(domain=domain))
            request.fail(QWebEngineUrlRequestJob.UrlInvalid)
コード例 #10
0
 def onMovieError(self, err):
     logUser.info(f'{self.clip.fileName()}: {self.clip.lastErrorString()}')
コード例 #11
0
ファイル: __init__.py プロジェクト: pinnaculum/galacteek
 def userLogInfo(self, msg):
     logUser.info('profile ({0}): {1}'.format(self.name, msg))
コード例 #12
0
    async def blogPost(self,
                       ipfsop,
                       title,
                       msg,
                       category=None,
                       tags=None,
                       author=None):
        async with self.edag:
            sHandle = self.profile.userInfo.spaceHandle

            username = sHandle.human
            uid = str(uuid.uuid4())
            postName = titleToPostName(title.strip().lower())

            exEntries = await self.blogEntries()
            if not postName or postName in exEntries:
                raise Exception('A blog post with this name already exists')

            now = datetime.now(timezone.utc)

            postObject = {
                'blogpost': {
                    'authordid': self.profile.userInfo.personDid,
                    'body': msg,
                    'title': title,
                    'uuid': uid,
                    'postname': postName,  # name of the post's DAG node
                    'tags': tags if tags else [],
                    'category': None,
                    'author': author if author else username,
                    'date_published': isoformat(now),
                    'date_modified': isoformat(now)
                }
            }

            # Create the DAG node for this post
            # Its view will be rendered later on

            self.dagBlog[postName] = {POST_NODEKEY: postObject}

        await ipfsop.sleep(2)
        await self.update()
        await ipfsop.sleep(1)

        result = await self.dagUser.resolve(
            posixIpfsPath.join(BLOG_NODEKEY, postName, 'view'))
        resolved = IPFSPath(result, autoCidConv=True)

        if isinstance(tags, list) and resolved.isIpfsRoot and resolved.valid:
            # Register the post by tag

            async with self.edag as dag:
                byTags = dag.root[BLOG_NODEKEY][TAGS_NODEKEY]

                for tag in tags:
                    if tag is None:
                        continue

                    planet, ptag = tag.split('#')
                    if not planet or not ptag:
                        continue

                    planet = planet.replace('@', '')

                    byTags.setdefault(planet, {})
                    byTags[planet].setdefault(ptag, {'_posts': []})

                    byTags[planet][ptag]['_posts'].append({
                        'name': postName,
                        'title': title,
                        'view': {
                            '/': stripIpfs(str(resolved))
                        }
                    })
                    byTags[planet][ptag]['index.html'] = await self.renderLink(
                        'usersite/bytag.html',
                        contained=True,
                        tag=tag,
                        tagposts=byTags[planet][ptag]['_posts'])

        logUser.info('Your blog post is online')
        return True
コード例 #13
0
ファイル: resource.py プロジェクト: pinnaculum/galacteek
    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)
コード例 #14
0
ファイル: clipboard.py プロジェクト: atavacron/galacteek
 async def entryAdded(entry):
     logUser.info('{path}: imported'.format(
         path=entry.get('Name')))