Bug 330010

Summary: KDEPIM .desktop file parser considers invalid the strings containing commas
Product: [Frameworks and Libraries] Akonadi Reporter: Alexander Potashev <aspotashev>
Component: serverAssignee: kdepim bugs <kdepim-bugs>
Status: RESOLVED FIXED    
Severity: normal CC: dvratil, krammer, montel
Priority: NOR    
Version: 1.11.0   
Target Milestone: ---   
Platform: Gentoo Packages   
OS: Linux   
Latest Commit: Version Fixed In: 1.11.1

Description Alexander Potashev 2014-01-15 23:11:29 UTC
When a field in .desktop file is set to a string containing commas and this string is not enclosed in double quotes, then Akonadi parser does not consider it as a valid string.

See details in this thread: http://lists.kde.org/?l=kde-i18n-doc&m=138972868202971&w=2

Reproducible: Always

Steps to Reproduce:
1. Write a value for "Comment" field in .desktop file for a resource/agent, e.g. openxchangeresource.desktop, to be a string with comma(s) and remove the enclosing double quotes.
2. Go to System Settings -> Personal Information (Akonadi Resources) and click "Add...". Find the agent/resource that you changed the .desktop file for.
Actual Results:  
When the "Name" field in .desktop file contains a comma, then "System Settings" crashes.

When the "Comment" field in .desktop file containts a comma, then whole Comment is not below the agent/resource name.

Expected Results:  
Strings with commas in .desktop files should be properly treated as strings with commas.

The .desktop file parser used for example in KDE Control Modules (KCM) don't suffers from this issue. See details in the above mentioned discussion thread "Double quotes in Comment field for Akonadi agents/resources are required".
Comment 1 Laurent Montel 2014-01-16 06:17:14 UTC
Could you provide a backtrace when it crashs please ?
I can't reproduce it.
Comment 2 Alexander Potashev 2014-01-16 21:06:45 UTC
(In reply to comment #1)
> Could you provide a backtrace when it crashs please ?
> I can't reproduce it.

Sorry, this crash happens only in a strange usage scenario as follows:
1. Edit /usr/share/akonadi/agents/openxchangeresource.desktop and make the string "Name=" valid (double quotes with commas) and make the string for your locale invalid (set "Name[ru]=" ("ru" here for Russian) to something with commas but without quotes).
2. Run SystemSettings, go to "Personal Infomation // Akonadi Resources" and click "Add...".
3. Enter "ope" in the search box.
4. Edit /usr/share/akonadi/agents/openxchangeresource.desktop again and make the string "Name=" invalid by removing the double quotes.
5. Go back to the search box in the resource/agent creation dialog and remove "e" by pressing Backspace, then enter "e" to restore it.

---
Application: Параметры системы (systemsettings), signal: Segmentation fault
Using host libthread_db library "/lib64/libthread_db.so.1".
[KCrash Handler]
#6  0x00007f637cfe218d in QSortFilterProxyModel::parent(QModelIndex const&) const () from /usr/lib64/qt4/libQtGui.so.4
#7  0x00007f637bda1503 in QPersistentModelIndex::parent() const () from /usr/lib64/qt4/libQtCore.so.4
#8  0x00007f637cfb61c6 in QItemSelectionModelPrivate::_q_rowsAboutToBeInserted(QModelIndex const&, int, int) () from /usr/lib64/qt4/libQtGui.so.4
#9  0x00007f637cfbb359 in QItemSelectionModel::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) () from /usr/lib64/qt4/libQtGui.so.4
#10 0x00007f637bdc20c1 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib64/qt4/libQtCore.so.4
#11 0x00007f637be0e794 in QAbstractItemModel::rowsAboutToBeInserted(QModelIndex const&, int, int) () from /usr/lib64/qt4/libQtCore.so.4
#12 0x00007f637bda7e58 in QAbstractItemModel::beginInsertRows(QModelIndex const&, int, int) () from /usr/lib64/qt4/libQtCore.so.4
#13 0x00007f637cfe4565 in QSortFilterProxyModelPrivate::insert_source_items(QVector<int>&, QVector<int>&, QVector<int> const&, QModelIndex const&, Qt::Orientation, bool) () from /usr/lib64/qt4/libQtGui.so.4
#14 0x00007f637cfe9d34 in QSortFilterProxyModelPrivate::handle_filter_changed(QVector<int>&, QVector<int>&, QModelIndex const&, Qt::Orientation) () from /usr/lib64/qt4/libQtGui.so.4
#15 0x00007f637cfea014 in QSortFilterProxyModelPrivate::filter_changed(QModelIndex const&) () from /usr/lib64/qt4/libQtGui.so.4
#16 0x00007f637cfea425 in QSortFilterProxyModel::setFilterFixedString(QString const&) () from /usr/lib64/qt4/libQtGui.so.4
#17 0x00007f637d75a0fe in KFilterProxySearchLine::Private::slotSearchLineActivate() () from /usr/lib64/libkdeui.so.5
#18 0x00007f637bdc20c1 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib64/qt4/libQtCore.so.4
#19 0x00007f637bdc70b9 in QObject::event(QEvent*) () from /usr/lib64/qt4/libQtCore.so.4
#20 0x00007f637ca59d04 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#21 0x00007f637ca5ead3 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#22 0x00007f637d78dd56 in KApplication::notify(QObject*, QEvent*) () from /usr/lib64/libkdeui.so.5
#23 0x00007f637bdae25c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4
#24 0x00007f637bddf382 in QTimerInfoList::activateTimers() () from /usr/lib64/qt4/libQtCore.so.4
#25 0x00007f637bddcbad in timerSourceDispatch(_GSource*, int (*)(void*), void*) () from /usr/lib64/qt4/libQtCore.so.4
#26 0x00007f637bddcbd1 in idleTimerSourceDispatch(_GSource*, int (*)(void*), void*) () from /usr/lib64/qt4/libQtCore.so.4
#27 0x00007f6374d93b63 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#28 0x00007f6374d93ea8 in g_main_context_iterate.isra.23 () from /usr/lib64/libglib-2.0.so.0
#29 0x00007f6374d93f64 in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0
#30 0x00007f637bddd46f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#31 0x00007f637cafcc6e in QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtGui.so.4
#32 0x00007f637bdacce2 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#33 0x00007f637bdacf37 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#34 0x00007f637cf07236 in QDialog::exec() () from /usr/lib64/qt4/libQtGui.so.4
#35 0x00007f63622b65ac in ResourcesManagementWidget::addClicked() () from /usr/lib64/kde4/kcm_akonadi_resources.so
#36 0x00007f637bdc20c1 in QMetaObject::activate(QObject*, QMetaObject const*, int, void**) () from /usr/lib64/qt4/libQtCore.so.4
#37 0x00007f637d0c50c2 in QAbstractButton::clicked(bool) () from /usr/lib64/qt4/libQtGui.so.4
#38 0x00007f637ce04a2e in QAbstractButtonPrivate::emitClicked() () from /usr/lib64/qt4/libQtGui.so.4
#39 0x00007f637ce05d6b in QAbstractButtonPrivate::click() () from /usr/lib64/qt4/libQtGui.so.4
#40 0x00007f637ce05fdc in QAbstractButton::mouseReleaseEvent(QMouseEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#41 0x00007f637caaa6cc in QWidget::event(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#42 0x00007f637ca59d04 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#43 0x00007f637ca5f3a3 in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#44 0x00007f637d78dd56 in KApplication::notify(QObject*, QEvent*) () from /usr/lib64/libkdeui.so.5
#45 0x00007f637bdae25c in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4
#46 0x00007f637ca5acd2 in QApplicationPrivate::sendMouseEvent(QWidget*, QMouseEvent*, QWidget*, QWidget*, QWidget**, QPointer<QWidget>&, bool) () from /usr/lib64/qt4/libQtGui.so.4
#47 0x00007f637cad6898 in QETWidget::translateMouseEvent(_XEvent const*) () from /usr/lib64/qt4/libQtGui.so.4
#48 0x00007f637cad568a in QApplication::x11ProcessEvent(_XEvent*) () from /usr/lib64/qt4/libQtGui.so.4
#49 0x00007f637cafcfd2 in x11EventSourceDispatch(_GSource*, int (*)(void*), void*) () from /usr/lib64/qt4/libQtGui.so.4
#50 0x00007f6374d93b63 in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0
#51 0x00007f6374d93ea8 in g_main_context_iterate.isra.23 () from /usr/lib64/libglib-2.0.so.0
#52 0x00007f6374d93f64 in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0
#53 0x00007f637bddd46f in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#54 0x00007f637cafcc6e in QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtGui.so.4
#55 0x00007f637bdacce2 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#56 0x00007f637bdacf37 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4
#57 0x00007f637bdb1e05 in QCoreApplication::exec() () from /usr/lib64/qt4/libQtCore.so.4
#58 0x000000000040bfb5 in main ()
Comment 3 Daniel Vrátil 2014-01-17 13:10:47 UTC
Git commit f28b675e7361b96c32a136c7eda7e4ef864eb432 by Dan Vrátil.
Committed on 17/01/2014 at 14:06.
Pushed by dvratil into branch '1.11'.

Fix parsing of .desktop files entries with comma in value

We are using QSettings to parse .desktop files. QSettings however treats
a value with comma as a QStringList which is not compatible with KConfig's
behavior, because KConfig treats everything as a string by default.

This patch adds a small workaround for this QSettings behaviour and joins
the list back to a single string when a string value is expected.

For translators this means that Comment entries in Akonadi agents' .desktop
files don't have to be enclosed in double quotes anymore.
FIXED-IN: 1.11.1

M  +31   -5    server/control/agenttype.cpp
M  +3    -0    server/control/agenttype.h

http://commits.kde.org/akonadi/f28b675e7361b96c32a136c7eda7e4ef864eb432
Comment 4 Alexander Potashev 2014-01-17 21:45:19 UTC
Dan,
Let's hope there are no languages in which there should be no space after a comma. According to the current .desktop files for Akonadi agents, it is so for the languages we already have translations to.

(In reply to comment #3)
> Git commit f28b675e7361b96c32a136c7eda7e4ef864eb432 by Dan Vrátil.
> Committed on 17/01/2014 at 14:06.
> Pushed by dvratil into branch '1.11'.
> 
> Fix parsing of .desktop files entries with comma in value
> 
> We are using QSettings to parse .desktop files. QSettings however treats
> a value with comma as a QStringList which is not compatible with KConfig's
> behavior, because KConfig treats everything as a string by default.
> 
> This patch adds a small workaround for this QSettings behaviour and joins
> the list back to a single string when a string value is expected.
> 
> For translators this means that Comment entries in Akonadi agents' .desktop
> files don't have to be enclosed in double quotes anymore.
> FIXED-IN: 1.11.1
> 
> M  +31   -5    server/control/agenttype.cpp
> M  +3    -0    server/control/agenttype.h
> 
> http://commits.kde.org/akonadi/f28b675e7361b96c32a136c7eda7e4ef864eb432
Comment 5 Daniel Vrátil 2014-01-20 12:39:57 UTC
It's better to have space after comma than completely broken translations :) The workaround with wrapping the translation into quotes still works though, so translators could use it. Anyway I'm aware that the fix is not ideal (it's more of a hack) and I hope that once we start depending on KDE Frameworks, I'll be able to use the KService framework to parse the desktop files correctly, like the rest of KDE.
Comment 6 Kevin Krammer 2014-02-10 14:51:51 UTC
@Dan: I think Razor/LXQt have a utility library that contains a .desktop parser. Should be license compatible, maybe only a single class to copy
Comment 7 Elvis Angelaccio 2016-02-29 11:00:52 UTC
Git commit 393a20b6f9e154069da09c2a2f929f1a4e886d3d by Elvis Angelaccio.
Committed on 29/02/2016 at 10:51.
Pushed by elvisangelaccio into branch 'master'.

Parse .desktop files using KDesktopFile

This replaces the parsing done by QSettings. Since KConfig supports localized
entries out of the box, there is no need anymore for custom code like the overloads
with a language string as argument.
Related: bug 358658

Differential Revision: D994

M  +1    -0    autotests/akonadicontrol/CMakeLists.txt
M  +8    -14   autotests/akonadicontrol/agenttypetest.cpp
M  +2    -5    autotests/akonadicontrol/data/googlecontactsresource.desktop
M  +1    -0    src/akonadicontrol/CMakeLists.txt
M  +6    -9    src/akonadicontrol/agentmanager.cpp
M  +5    -7    src/akonadicontrol/agentmanager.h
M  +21   -46   src/akonadicontrol/agenttype.cpp
M  +2    -2    src/akonadicontrol/agenttype.h
M  +2    -8    src/core/agentmanager.cpp
M  +0    -15   src/interfaces/org.freedesktop.Akonadi.AgentManager.xml

http://commits.kde.org/akonadi/393a20b6f9e154069da09c2a2f929f1a4e886d3d