diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.cpp b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp index 3909c8397..dddd0cd92 100644 --- a/retroshare-gui/src/gui/Identity/IdentityListModel.cpp +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.cpp @@ -455,6 +455,7 @@ QVariant RsIdentityListModel::data(const QModelIndex &index, int role) const case Qt::FontRole: return fontRole(entry,index.column()) ; case Qt::ForegroundRole: return foregroundRole(entry,index.column()) ; case Qt::DecorationRole: return decorationRole(entry,index.column()) ; + case Qt::ToolTipRole: return toolTipRole(entry,index.column()) ; case FilterRole: return filterRole(entry,index.column()) ; case SortRole: return sortRole(entry,index.column()) ; @@ -465,6 +466,14 @@ QVariant RsIdentityListModel::data(const QModelIndex &index, int role) const } } +// This function checks that the ID has been signed using the old protocol that used to +// include the service string into the signed data. New RS instances will not accept these identities anymore. + +static bool checkDate_deprecated_ids(const time_t t) +{ + return t > QDateTime(QDate(2026,4,20),QTime(0,0)).toSecsSinceEpoch(); +} + bool RsIdentityListModel::passesFilter(const EntryIndex& e,int /*column*/) const { QString s ; @@ -535,7 +544,12 @@ QVariant RsIdentityListModel::toolTipRole(const EntryIndex& fmpe,int /*column*/) return QVariant( tr("\nThis identity has a insecure fingerprint (It's probably quite old).\nYou should get rid of it now and use a new one.\nThese identities are not supported anymore.") ) ; if(rsIdentity->isOwnId(id_info->id)) - return QVariant(tr("This identity is owned by you")); + { + if(!checkDate_deprecated_ids(id_info->creation_date)) + return QVariant(tr("This identity is owned by you but was created in a format\nthat is now deprecated. Just select \"edit\" from the context menu\nand press \"update\" in order to fix this.")); + else + return QVariant(tr("This identity is owned by you")); + } if(id_info->owner.isNull()) return QVariant("Anonymous identity"); @@ -662,6 +676,9 @@ QVariant RsIdentityListModel::foregroundRole(const EntryIndex& e, int /*col*/) c if(it->flags & RS_IDENTITY_FLAGS_IS_DEPRECATED) return QVariant(QColor(Qt::red)); + if(rsIdentity->isOwnId(it->id) && !checkDate_deprecated_ids(it->creation_date)) + return QVariant(QColor(Qt::red)); + return QVariant(); } QVariant RsIdentityListModel::fontRole(const EntryIndex& e, int /*col*/) const @@ -828,6 +845,7 @@ const RsIdentityListModel::HierarchicalIdentityInformation *RsIdentityListModel: it.owner = det.mPgpId; it.flags = det.mFlags; it.last_update_TS = now; + it.creation_date = det.mPublishTS; } } return ⁢ diff --git a/retroshare-gui/src/gui/Identity/IdentityListModel.h b/retroshare-gui/src/gui/Identity/IdentityListModel.h index a48cc1de4..d6b9345da 100644 --- a/retroshare-gui/src/gui/Identity/IdentityListModel.h +++ b/retroshare-gui/src/gui/Identity/IdentityListModel.h @@ -92,6 +92,7 @@ public: RsPgpId owner; uint32_t flags; std::string nickname; + rstime_t creation_date; }; // This structure encodes the position of a node in the hierarchy. The type tells which of the index fields are valid. diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp index bd310e58f..50baa1951 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.cpp +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.cpp @@ -452,6 +452,7 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList< item->setIcon(GTW_COLUMN_POPULARITY, PopularityDefs::icon(itemInfo.popularity)); item->setData(GTW_COLUMN_POPULARITY, ROLE_SORT, itemInfo.popularity); + /* Set tooltip */ if (itemInfo.adminKey) tooltip += "\n" + tr("You are admin (modify names and description using Edit menu)"); @@ -487,7 +488,14 @@ void GroupTreeWidget::fillGroupItems(QTreeWidgetItem *categoryItem, const QList< item->setData(GTW_COLUMN_DATA, ROLE_SUBSCRIBE_FLAGS, itemInfo.subscribeFlags); /* Set color */ - if (itemInfo.publishKey) { + + if(itemInfo.deprecated_format) + { + item->setData(GTW_COLUMN_DATA, ROLE_COLOR, GROUPTREEWIDGET_COLOR_WARNING); + item->setData(GTW_COLUMN_NAME, Qt::ForegroundRole, QBrush(textColorWarning())); + item->setToolTip(GTW_COLUMN_NAME,tr("This object has been created and stored \nin a format that is no longer supported. Please \"edit\" it \nand press \"Update\" to re-sign it in the new format.")); + } + else if (itemInfo.publishKey) { item->setData(GTW_COLUMN_DATA, ROLE_COLOR, GROUPTREEWIDGET_COLOR_PRIVATEKEY); item->setData(GTW_COLUMN_NAME, Qt::ForegroundRole, QBrush(textColorPrivateKey())); } else { diff --git a/retroshare-gui/src/gui/common/GroupTreeWidget.h b/retroshare-gui/src/gui/common/GroupTreeWidget.h index ab67b10f0..b208abd85 100644 --- a/retroshare-gui/src/gui/common/GroupTreeWidget.h +++ b/retroshare-gui/src/gui/common/GroupTreeWidget.h @@ -25,6 +25,7 @@ #include #include +#include "util/rstime.h" #include "util/FontSizeHandler.h" class QToolButton; @@ -35,7 +36,8 @@ class RSTreeWidget; #define GROUPTREEWIDGET_COLOR_STANDARD -1 #define GROUPTREEWIDGET_COLOR_CATEGORY 0 #define GROUPTREEWIDGET_COLOR_PRIVATEKEY 1 -#define GROUPTREEWIDGET_COLOR_COUNT 2 +#define GROUPTREEWIDGET_COLOR_WARNING 2 +#define GROUPTREEWIDGET_COLOR_COUNT 3 #define GTW_COLUMN_NAME 0 #define GTW_COLUMN_UNREAD 1 @@ -55,8 +57,8 @@ class GroupItemInfo { public: GroupItemInfo() - : popularity(0), publishKey(false), adminKey(false) - , subscribeFlags(0), max_visible_posts(0) + : popularity(0), creation_time(0),publishKey(false), adminKey(false) + , subscribeFlags(0), max_visible_posts(0), deprecated_format(false) {} public: @@ -65,12 +67,14 @@ public: QString description; int popularity; QDateTime lastpost; - QIcon icon; + rstime_t creation_time; + QIcon icon; bool publishKey; bool adminKey; quint32 subscribeFlags; quint32 max_visible_posts ; std::set context_strings; + bool deprecated_format; // this was added on 07/2026 for forcing admin re-signature of incompatible groups }; //cppcheck-suppress noConstructor @@ -78,8 +82,9 @@ class GroupTreeWidget : public QWidget { Q_OBJECT - Q_PROPERTY(QColor textColorCategory READ textColorCategory WRITE setTextColorCategory) + Q_PROPERTY(QColor textColorCategory READ textColorCategory WRITE setTextColorCategory) Q_PROPERTY(QColor textColorPrivateKey READ textColorPrivateKey WRITE setTextColorPrivateKey) + Q_PROPERTY(QColor textColorWarning READ textColorWarning WRITE setTextColorWarning) public: GroupTreeWidget(QWidget *parent = 0); @@ -128,9 +133,11 @@ public: QColor textColorCategory() const { return mTextColor[GROUPTREEWIDGET_COLOR_CATEGORY]; } QColor textColorPrivateKey() const { return mTextColor[GROUPTREEWIDGET_COLOR_PRIVATEKEY]; } + QColor textColorWarning() const { return mTextColor[GROUPTREEWIDGET_COLOR_WARNING]; } void setTextColorCategory(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_CATEGORY] = color; } void setTextColorPrivateKey(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_PRIVATEKEY] = color; } + void setTextColorWarning(QColor color) { mTextColor[GROUPTREEWIDGET_COLOR_WARNING] = color; } bool getGroupName(const QString& id, QString& name); diff --git a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp index ef2089b4c..d72d56282 100644 --- a/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp +++ b/retroshare-gui/src/gui/gxs/GxsGroupFrameDialog.cpp @@ -961,6 +961,7 @@ void GxsGroupFrameDialog::groupInfoToGroupItemInfo(const RsGxsGenericGroupData * groupItemInfo.publishKey = IS_GROUP_PUBLISHER(groupInfo->mMeta.mSubscribeFlags) ; groupItemInfo.adminKey = IS_GROUP_ADMIN(groupInfo->mMeta.mSubscribeFlags) ; groupItemInfo.max_visible_posts = groupInfo->mMeta.mVisibleMsgCount ; + groupItemInfo.creation_time = groupInfo->mMeta.mPublishTs ; #if TOGXS if (groupInfo.mGroupFlags & RS_DISTRIB_AUTHEN_REQ) { diff --git a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp index 53a1f9e27..7ea073f33 100644 --- a/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp +++ b/retroshare-gui/src/gui/gxschannels/GxsChannelDialog.cpp @@ -412,26 +412,33 @@ bool GxsChannelDialog::getGroupData(std::list& groupInfo void GxsChannelDialog::groupInfoToGroupItemInfo(const RsGxsGenericGroupData *groupData, GroupItemInfo &groupItemInfo) { - GxsGroupFrameDialog::groupInfoToGroupItemInfo(groupData, groupItemInfo); + GxsGroupFrameDialog::groupInfoToGroupItemInfo(groupData, groupItemInfo); - const RsGxsChannelGroup *channelGroupData = dynamic_cast(groupData); + const RsGxsChannelGroup *channelGroupData = dynamic_cast(groupData); - if (!channelGroupData) + if (!channelGroupData) { - std::cerr << "GxsChannelDialog::groupInfoToGroupItemInfo() Failed to cast data to GxsChannelGroupInfoData"<< std::endl; - return; - } + std::cerr << "GxsChannelDialog::groupInfoToGroupItemInfo() Failed to cast data to GxsChannelGroupInfoData"<< std::endl; + return; + } - if(channelGroupData->mImage.mSize > 0) - { - QPixmap image; - GxsIdDetails::loadPixmapFromData(channelGroupData->mImage.mData, channelGroupData->mImage.mSize, image,GxsIdDetails::ORIGINAL); - groupItemInfo.icon = image; - } - else + // Before apr.2026 the validation of admin signature was ommited and the service string (used in channels) was used in the + // creation of its signature. Since the service string is local, this breaks signature validation at distant nodes. + // This flag is here to warn users about re-signing their channel. + + if(groupItemInfo.adminKey && (channelGroupData->mMeta.mPublishTs < QDateTime(QDate(2026,4,15),QTime(0,0)).toSecsSinceEpoch())) + groupItemInfo.deprecated_format = true; + + if(channelGroupData->mImage.mSize > 0) + { + QPixmap image; + GxsIdDetails::loadPixmapFromData(channelGroupData->mImage.mData, channelGroupData->mImage.mSize, image,GxsIdDetails::ORIGINAL); + groupItemInfo.icon = image; + } + else groupItemInfo.icon = GxsIdDetails::makeDefaultGroupIcon(channelGroupData->mMeta.mGroupId, ":icons/channel.png", GxsIdDetails::ORIGINAL); - groupItemInfo.description = QString::fromUtf8(channelGroupData->mDescription.c_str()); + groupItemInfo.description = QString::fromUtf8(channelGroupData->mDescription.c_str()); } void GxsChannelDialog::clearDistantSearchResults(TurtleRequestId id) diff --git a/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss index ff513aab1..2e673f43c 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/Standard_Dark.qss @@ -2485,6 +2485,7 @@ GroupTreeWidget { qproperty-textColorCategory: rgb(3, 155, 198); qproperty-textColorPrivateKey: rgb(249,185,0); + qproperty-textColorWarning: rgb(250,91,15); } NetworkDialog { diff --git a/retroshare-gui/src/gui/qss/stylesheet/default.qss b/retroshare-gui/src/gui/qss/stylesheet/default.qss index d1c2317b3..f4e76c161 100644 --- a/retroshare-gui/src/gui/qss/stylesheet/default.qss +++ b/retroshare-gui/src/gui/qss/stylesheet/default.qss @@ -36,12 +36,12 @@ QFrame[objectName^="info_"] > QLabel } /* Specifics Buttons */ -QPushButton#applyButton:enabled,/*enabled is needed for not be overrided :https://doc.qt.io/qt-5/stylesheet-syntax.html#conflict-resolution*/ -QPushButton#createButton:enabled, -QPushButton#postButton:enabled, -QPushButton#pushButton_History:enabled, -QToolButton#addButton:enabled, -QToolButton#followButton:enabled { +QPushButton#applyButton:enabled,/*enabled is needed for not be overrided :https://doc.qt.io/qt-5/stylesheet-syntax.html#conflict-resolution*/ +QPushButton#createButton:enabled, +QPushButton#postButton:enabled, +QPushButton#pushButton_History:enabled, +QToolButton#addButton:enabled, +QToolButton#followButton:enabled { color: white; background: #0099cc; border-radius: 4px; @@ -52,12 +52,12 @@ QToolButton#followButton:enabled { padding-right: 6px; } -QPushButton#applyButton:disabled, -QPushButton#createButton:disabled, -QPushButton#postButton:disabled, -QPushButton#pushButton_History:disabled, -QToolButton#addButton:disabled, -QToolButton#followButton:disabled { +QPushButton#applyButton:disabled, +QPushButton#createButton:disabled, +QPushButton#postButton:disabled, +QPushButton#pushButton_History:disabled, +QToolButton#addButton:disabled, +QToolButton#followButton:disabled { color: white; background: #d40000; border-radius: 4px; @@ -65,12 +65,12 @@ QToolButton#followButton:disabled { padding-right: 6px; } -QPushButton#applyButton:hover, -QPushButton#createButton:hover, -QPushButton#postButton:hover, -QPushButton#pushButton_History:hover, -QToolButton#addButton:hover, -QToolButton#followButton:hover { +QPushButton#applyButton:hover, +QPushButton#createButton:hover, +QPushButton#postButton:hover, +QPushButton#pushButton_History:hover, +QToolButton#addButton:hover, +QToolButton#followButton:hover { color: white; background: #03b1f3; border-radius: 4px; @@ -252,6 +252,7 @@ GroupTreeWidget { qproperty-textColorCategory: rgb(79, 79, 79); qproperty-textColorPrivateKey: rgb(35,91,159); + qproperty-textColorWarning: rgb(250,91,15); } MessagesDialog