From 929f87254489614c28d4d1b72fb2c8ad50e0e1c0 Mon Sep 17 00:00:00 2001 From: csoler Date: Sat, 10 Nov 2012 22:59:51 +0000 Subject: [PATCH] Added new link type: EXTRA_FILE, to allow sendign links with sources included so as to trigger direct transfer. This makes possible to send files through chat without permitting tunnel access to the files. The client requests the file as a direct transfer only, using the supplied source. git-svn-id: http://svn.code.sf.net/p/retroshare/code/trunk@5799 b45a01b8-16f6-495d-af2f-9b41ad6348cc --- retroshare-gui/src/gui/RetroShareLink.cpp | 89 ++++++++++++++++++- retroshare-gui/src/gui/RetroShareLink.h | 5 +- retroshare-gui/src/gui/chat/ChatWidget.cpp | 2 +- .../src/gui/common/LinkTextBrowser.cpp | 19 +++- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/retroshare-gui/src/gui/RetroShareLink.cpp b/retroshare-gui/src/gui/RetroShareLink.cpp index 401fa4c08..5f634ca7b 100644 --- a/retroshare-gui/src/gui/RetroShareLink.cpp +++ b/retroshare-gui/src/gui/RetroShareLink.cpp @@ -48,6 +48,7 @@ #define DEBUG_RSLINK 1 #define HOST_FILE "file" +#define HOST_EXTRAFILE "extra" #define HOST_PERSON "person" #define HOST_FORUM "forum" #define HOST_CHANNEL "channel" @@ -59,6 +60,7 @@ #define FILE_NAME "name" #define FILE_SIZE "size" #define FILE_HASH "hash" +#define FILE_SOURCE "src" #define PERSON_NAME "name" #define PERSON_HASH "hash" @@ -179,6 +181,27 @@ void RetroShareLink::fromUrl(const QUrl& url) } } + if (url.host() == HOST_EXTRAFILE) { + bool ok ; + + _type = TYPE_EXTRAFILE; + _name = url.queryItemValue(FILE_NAME); + _size = url.queryItemValue(FILE_SIZE).toULongLong(&ok); + _hash = url.queryItemValue(FILE_HASH).left(40); // normally not necessary, but it's a security. + _SSLid = url.queryItemValue(FILE_SOURCE); + + if (ok) { +#ifdef DEBUG_RSLINK + std::cerr << "New RetroShareLink forged:" << std::endl ; + std::cerr << " name = \"" << _name.toStdString() << "\"" << std::endl ; + std::cerr << " hash = \"" << _hash.toStdString() << "\"" << std::endl ; + std::cerr << " size = " << _size << std::endl ; + std::cerr << " src = " << _SSLid.toStdString() << std::endl ; +#endif + check(); + return; + } + } if (url.host() == HOST_PERSON) { _type = TYPE_PERSON; _name = url.queryItemValue(PERSON_NAME); @@ -246,6 +269,21 @@ RetroShareLink::RetroShareLink() clear(); } +bool RetroShareLink::createExtraFile(const QString& name, uint64_t size, const QString& hash,const QString& ssl_id) +{ + clear(); + + _name = name; + _size = size; + _hash = hash; + _SSLid = ssl_id; + + _type = TYPE_EXTRAFILE; + + check(); + + return valid(); +} bool RetroShareLink::createFile(const QString& name, uint64_t size, const QString& hash) { clear(); @@ -463,6 +501,9 @@ void RetroShareLink::check() case TYPE_UNKNOWN: _valid = false; break; + case TYPE_EXTRAFILE: + if(!checkSSLId(_SSLid)) + _valid = false; // no break! We also test file stuff below. case TYPE_FILE: if(_size > (((uint64_t)1)<<40)) // 1TB. Who has such large files? _valid = false; @@ -538,6 +579,8 @@ QString RetroShareLink::title() const switch (_type) { case TYPE_UNKNOWN: break; + case TYPE_EXTRAFILE: + return QString("%1 (%2, Extra - Source included)").arg(hash()).arg(misc::friendlyUnit(size())); case TYPE_FILE: return QString("%1 (%2)").arg(hash()).arg(misc::friendlyUnit(size())); case TYPE_PERSON: @@ -576,6 +619,19 @@ QString RetroShareLink::toString() const return url.toString(); } + case TYPE_EXTRAFILE: + { + QUrl url; + url.setScheme(RSLINK_SCHEME); + url.setHost(HOST_EXTRAFILE); + url.addQueryItem(FILE_NAME, encodeItem(_name)); + url.addQueryItem(FILE_SIZE, QString::number(_size)); + url.addQueryItem(FILE_HASH, _hash); + url.addQueryItem(FILE_SOURCE, _SSLid); + + return url.toString(); + } + case TYPE_PERSON: { QUrl url; @@ -699,6 +755,7 @@ QString RetroShareLink::toHtmlFull() const QString RetroShareLink::toHtmlSize() const { QString size = QString("(%1)").arg(misc::friendlyUnit(_size)); + if (type() == TYPE_FILE && RsCollectionFile::isCollectionFile(name())) { FileInfo finfo; if (rsFiles->FileDetails(hash().toStdString(), RS_FILE_HINTS_EXTRA | RS_FILE_HINTS_LOCAL, finfo)) { @@ -740,6 +797,23 @@ QUrl RetroShareLink::toUrl() const return QUrl::fromEncoded(toString().toUtf8().constData()); } +bool RetroShareLink::checkSSLId(const QString& ssl_id) +{ + if(ssl_id.length() != 32) + return false ; + + QByteArray qb(ssl_id.toAscii()) ; + + for(int i=0;i47 && b<58) || (b>96 && b<103))) + return false ; + } + + return true ; +} bool RetroShareLink::checkHash(const QString& hash) { if(hash.length() != 40) @@ -816,6 +890,7 @@ static void processList(const QStringList &list, const QString &textSingular, co break; case TYPE_FILE: + case TYPE_EXTRAFILE: fileAdd.append(link.name()); break; @@ -953,15 +1028,27 @@ static void processList(const QStringList &list, const QString &textSingular, co break ; case TYPE_FILE: + case TYPE_EXTRAFILE: { #ifdef DEBUG_RSLINK std::cerr << " RetroShareLink::process FileRequest : fileName : " << link.name().toUtf8().constData() << ". fileHash : " << link.hash().toStdString() << ". fileSize : " << link.size() << std::endl; #endif needNotifySuccess = true; + std::list srcIds; + + // Add the link built-in source. This is needed for EXTRA files, where the source is specified in the link. + + if(link.type() == TYPE_EXTRAFILE) + { +#ifdef DEBUG_RSLINK + std::cerr << " RetroShareLink::process Adding built-in source " << link.SSLId().toStdString() << std::endl; +#endif + srcIds.push_back(link.SSLId().toStdString()) ; + } // Get a list of available direct sources, in case the file is browsable only. - std::list srcIds; + // FileInfo finfo ; rsFiles->FileDetails(link.hash().toStdString(), RS_FILE_HINTS_REMOTE, finfo) ; diff --git a/retroshare-gui/src/gui/RetroShareLink.h b/retroshare-gui/src/gui/RetroShareLink.h index 8b5df7544..dfc706c39 100644 --- a/retroshare-gui/src/gui/RetroShareLink.h +++ b/retroshare-gui/src/gui/RetroShareLink.h @@ -46,11 +46,12 @@ #define RSLINK_SCHEME "retroshare" #define RSLINK_SUBTYPE_CERTIFICATE_USER_REQUEST 1 +#define RSLINK_SUBTYPE_FILE_EXTRA 2 class RetroShareLink { public: - enum enumType { TYPE_UNKNOWN, TYPE_FILE, TYPE_PERSON, TYPE_FORUM, TYPE_CHANNEL, TYPE_SEARCH, TYPE_MESSAGE, TYPE_CERTIFICATE }; + enum enumType { TYPE_UNKNOWN, TYPE_FILE, TYPE_PERSON, TYPE_FORUM, TYPE_CHANNEL, TYPE_SEARCH, TYPE_MESSAGE, TYPE_CERTIFICATE,TYPE_EXTRAFILE }; public: RetroShareLink(); @@ -58,6 +59,7 @@ class RetroShareLink RetroShareLink(const QString& url); bool createFile(const QString& name, uint64_t size, const QString& hash); + bool createExtraFile(const QString& name, uint64_t size, const QString& hash, const QString& ssl_id); bool createPerson(const std::string& id); bool createForum(const std::string& id, const std::string& msgId); bool createChannel(const std::string& id, const std::string& msgId); @@ -116,6 +118,7 @@ class RetroShareLink void check(); static bool checkHash(const QString& hash); static bool checkName(const QString& name); + static bool checkSSLId(const QString& name); bool _valid; enumType _type; diff --git a/retroshare-gui/src/gui/chat/ChatWidget.cpp b/retroshare-gui/src/gui/chat/ChatWidget.cpp index 7bebd75ae..72446b521 100644 --- a/retroshare-gui/src/gui/chat/ChatWidget.cpp +++ b/retroshare-gui/src/gui/chat/ChatWidget.cpp @@ -629,7 +629,7 @@ void ChatWidget::fileHashingFinished(QList hashedFiles) QString ext = QFileInfo(hashedFile.filename).suffix(); RetroShareLink link; - link.createFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash)); + link.createExtraFile(hashedFile.filename, hashedFile.size, QString::fromStdString(hashedFile.hash),QString::fromStdString(rsPeers->getOwnId())); if (hashedFile.flag & HashedFile::Picture) { message += QString("").arg(hashedFile.filepath); diff --git a/retroshare-gui/src/gui/common/LinkTextBrowser.cpp b/retroshare-gui/src/gui/common/LinkTextBrowser.cpp index dddc6124b..96438a43d 100644 --- a/retroshare-gui/src/gui/common/LinkTextBrowser.cpp +++ b/retroshare-gui/src/gui/common/LinkTextBrowser.cpp @@ -15,5 +15,22 @@ void LinkTextBrowser::linkClicked(const QUrl &url) { // some links are opened directly in the QTextBrowser with open external links set to true, // so we handle links by our own - QDesktopServices::openUrl(url); + +#ifdef TO_DO + // If we want extra file links to be anonymous, we need to insert the actual source here. + if(url.host() == HOST_EXTRAFILE) + { + std::cerr << "Extra file link detected. Adding parent id " << _target_sslid << " to sourcelist" << std::endl; + + RetroShareLink link ; + link.fromUrl(url) ; + + link.createExtraFile( link.name(),link.size(),link.hash(), _target_ssl_id) ; + + QDesktopServices::openUrl(link.toUrl()); + } + else +#endif + QDesktopServices::openUrl(url); } +