Skip to content

Commit

Permalink
get ready to load ipfs URLs
Browse files Browse the repository at this point in the history
There is the issue that ipfs URLs are currently case-sensitive with
base58 hashes, but this has been recognized as a problem:
https://github.com/ipfs/ipfs/issues/337
QUrl also converts addresses to lowercase.  So we can't currently
load base58 hashes into QUrl; consequently switched load(QUrl)
to load(QString) for now.  Maybe it can be reverted when they
switch to base32 hashes.
  • Loading branch information
ec1oud committed Jun 14, 2019
1 parent 6f9b42c commit 1c7c116
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 20 deletions.
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ int main(int argc, char *argv[])
if (parser.isSet(cssOption))
w.setBrowserStyle(QUrl::fromLocalFile(parser.value(cssOption)));
if (parser.positionalArguments().count() > 0)
w.load(QUrl::fromLocalFile(parser.positionalArguments().last()));
w.load(parser.positionalArguments().last());
w.show();

return app.exec();
Expand Down
47 changes: 32 additions & 15 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <QTextCodec>
#include <QTextEdit>

static const QString ipfsScheme = QStringLiteral("ipfs");

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
Expand Down Expand Up @@ -64,25 +66,28 @@ void MainWindow::on_actionOpen_triggered()
<< "text/plain");
if (fileDialog.exec() != QDialog::Accepted)
return;
load(fileDialog.selectedUrls().first());
load(fileDialog.selectedFiles().first());
}

bool MainWindow::load(QUrl url)
bool MainWindow::load(QString url)
{
qDebug() << url;
if (url.isRelative()) {
QUrl res = url.resolved(m_mainWidget->document()->baseUrl()); // doesn't work for local files
qDebug() << url << res << res.fileName() << url.toString();
QUrl urlForm = QUrl::fromUserInput(url);
if (urlForm.isRelative()) {
QUrl res = urlForm.resolved(m_mainWidget->document()->baseUrl()); // doesn't work for local files
qDebug() << url << res << res.fileName() << urlForm.toString();
// correct for QUrl::resolved() being broken
if (res.fileName() != url.toString())
res = QUrl(res.toString() + QLatin1Char('/') + url.toString());
qDebug() << url << res << res.fileName() << url.toString();
url = res;
if (res.fileName() != urlForm.toString())
res = QUrl(res.toString() + QLatin1Char('/') + urlForm.toString());
qDebug() << url << res << res.fileName() << urlForm.toString();
urlForm = res;
ui->urlField->setText(urlForm.toString());
} else {
ui->urlField->setText(url);
}

bool success = false;
if (url.isLocalFile()) {
QString f = url.toLocalFile();
if (urlForm.isLocalFile()) {
QString f = urlForm.toLocalFile();
QFile file(f);
if (QFile::exists(f) && file.open(QFile::ReadOnly)) {
QByteArray data = file.readAll();
Expand All @@ -108,19 +113,26 @@ bool MainWindow::load(QUrl url)
else
success = false;
}
} else if (urlForm.scheme() == ipfsScheme || url.startsWith(QLatin1String("Qm"))) {
qDebug() << "ipfs get" << url;
} else {
statusBar()->showMessage(tr("remote loading is not yet implemented: \"%1\"").arg(url.toString()));
statusBar()->showMessage(tr("remote loading is not yet implemented: \"%1\"").arg(url));
return false;
}
if (success) {
m_history.push(url);
statusBar()->showMessage(tr("Opened \"%1\"").arg(url.toString()));
statusBar()->showMessage(tr("Opened \"%1\"").arg(url));
} else {
statusBar()->showMessage(tr("Could not open \"%1\"").arg(url.toString()));
statusBar()->showMessage(tr("Could not open \"%1\"").arg(url));
}
return success;
}

bool MainWindow::loadUrl(QUrl url)
{
return load(url.toString());
}

bool MainWindow::setBrowserStyle(QUrl url)
{
// TODO same url resolution as in load()
Expand Down Expand Up @@ -152,3 +164,8 @@ void MainWindow::on_browser_backwardAvailable(bool a)
Q_UNUSED(a)
// ui->actionGo_back->setEnabled(a);
}

void MainWindow::on_urlField_returnPressed()
{
load(ui->urlField->text());
}
7 changes: 5 additions & 2 deletions src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class MainWindow : public QMainWindow
~MainWindow();

public slots:
bool load(QUrl url);
bool load(QString url);
bool loadUrl(QUrl url);
bool setBrowserStyle(QUrl url);

private slots:
Expand All @@ -46,10 +47,12 @@ private slots:
void on_actionGo_back_triggered();
void on_browser_backwardAvailable(bool a);

void on_urlField_returnPressed();

private:
Ui::MainWindow *ui;
QTextEdit *m_mainWidget;
QStack<QUrl> m_history; // correct for QTextBrowser history being broken (only for markdown?)
QStack<QString> m_history; // correct for QTextBrowser history being broken (only for markdown?)
};

#endif // MAINWINDOW_H
4 changes: 2 additions & 2 deletions src/mainwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
<sender>browser</sender>
<signal>anchorClicked(QUrl)</signal>
<receiver>MainWindow</receiver>
<slot>load(QUrl)</slot>
<slot>loadUrl(QUrl)</slot>
<hints>
<hint type="sourcelabel">
<x>136</x>
Expand All @@ -135,6 +135,6 @@
</connection>
</connections>
<slots>
<slot>load(QUrl)</slot>
<slot>loadUrl(QUrl)</slot>
</slots>
</ui>

4 comments on commit 1c7c116

@lidel
Copy link

@lidel lidel commented on 1c7c116 Jun 15, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the context of this, but you can convert case sensitive CIDv0 (Base58) to case-insensitive CIDv1 in Base32 as noted in https://github.com/ipfs/ipfs/issues/337#issuecomment-435356238

The multihash inside of CID remains the same – CIDv1 just adds some things in the prefix to be more future-proof:

<cidv0> ::= <multihash-content-address>
<cidv1> ::= <multibase-prefix><cid-version><multicodec-content-type><multihash-content-address>

More: https://github.com/multiformats/cid#versions

Hope this helps :)

@ec1oud
Copy link
Owner Author

@ec1oud ec1oud commented on 1c7c116 Jun 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not quite as bad as I wrote there... it turned out that QUrl::fromUserInput() causes trouble (for one, assuming that the url can be lowercase; for another, assuming that if it's not a local file, it must be http), but otherwise it seems a QUrl can actually hold a case-sensitive path. So following links in documents actually works, for example.

Yes I know I haven't tried too hard to actually interpret the hashes yet, and I really should. I think I want to add UI for some sort of hash calculator that breaks down the parts.

Another thing is it turned out I need to use the ipfs:// scheme, because KIO maps URL schemes to "slaves". Is there anything weird about that? It doesn't seem like the URL scheme is used so consistently everywhere. I.e. I would expect random URLs around the net that point to IPFS resources would use ipfs://the-hash/path/file or just ipfs://the-hash for direct links.

@lidel
Copy link

@lidel lidel commented on 1c7c116 Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lidel
Copy link

@lidel lidel commented on 1c7c116 Jun 18, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good UX would be to show ipfs://{cid}/path or /ipfs/{cid}/path in UI where possible, but also provide user with an option to copy shareable URL pointing at a gateway (eg. http://gateway.ipfs.io/ipfs/{cid}/path), so it can be shared with people that don't run IPFS client.

Please sign in to comment.