fixed issue causing hyprctl to output ill-formed json when strings include characters needing escaping

This commit is contained in:
Daniel Gerblick 2022-07-18 14:47:28 -04:00
parent dc1f34c5fa
commit f2c0e6ef02
3 changed files with 47 additions and 22 deletions

View file

@ -38,11 +38,11 @@ R"#({
"active": "%s" "active": "%s"
},)#", },)#",
m->ID, m->ID,
m->szName.c_str(), escapeJSONStrings(m->szName).c_str(),
(int)m->vecPixelSize.x, (int)m->vecPixelSize.y, (int)m->vecPixelSize.x, (int)m->vecPixelSize.y,
m->refreshRate, m->refreshRate,
(int)m->vecPosition.x, (int)m->vecPosition.y, (int)m->vecPosition.x, (int)m->vecPosition.y,
m->activeWorkspace, g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName.c_str(), m->activeWorkspace, escapeJSONStrings(g_pCompositor->getWorkspaceByID(m->activeWorkspace)->m_szName).c_str(),
(int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y, (int)m->vecReservedTopLeft.x, (int)m->vecReservedTopLeft.y, (int)m->vecReservedBottomRight.x, (int)m->vecReservedBottomRight.y,
m->scale, m->scale,
(int)m->transform, (int)m->transform,
@ -89,11 +89,11 @@ R"#({
w.get(), w.get(),
(int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y, (int)w->m_vRealPosition.vec().x, (int)w->m_vRealPosition.vec().y,
(int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y, (int)w->m_vRealSize.vec().x, (int)w->m_vRealSize.vec().y,
w->m_iWorkspaceID, (w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName.c_str() : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID)).c_str()), w->m_iWorkspaceID, escapeJSONStrings(w->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID) ? g_pCompositor->getWorkspaceByID(w->m_iWorkspaceID)->m_szName : std::string("Invalid workspace " + std::to_string(w->m_iWorkspaceID))).c_str(),
(int)w->m_bIsFloating, (int)w->m_bIsFloating,
w->m_iMonitorID, w->m_iMonitorID,
g_pXWaylandManager->getAppIDClass(w.get()).c_str(), escapeJSONStrings(g_pXWaylandManager->getAppIDClass(w.get())).c_str(),
g_pXWaylandManager->getTitle(w.get()).c_str(), escapeJSONStrings(g_pXWaylandManager->getTitle(w.get())).c_str(),
w->getPID() w->getPID()
); );
} }
@ -130,8 +130,8 @@ R"#({
"hasfullscreen": %i "hasfullscreen": %i
},)#", },)#",
w->m_iID, w->m_iID,
w->m_szName.c_str(), escapeJSONStrings(w->m_szName).c_str(),
g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName.c_str(), escapeJSONStrings(g_pCompositor->getMonitorFromID(w->m_iMonitorID)->szName).c_str(),
g_pCompositor->getWindowsOnWorkspace(w->m_iID), g_pCompositor->getWindowsOnWorkspace(w->m_iID),
(int)w->m_bHasFullscreenWindow (int)w->m_bHasFullscreenWindow
); );
@ -175,11 +175,11 @@ R"#({
PWINDOW, PWINDOW,
(int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y, (int)PWINDOW->m_vRealPosition.vec().x, (int)PWINDOW->m_vRealPosition.vec().y,
(int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y, (int)PWINDOW->m_vRealSize.vec().x, (int)PWINDOW->m_vRealSize.vec().y,
PWINDOW->m_iWorkspaceID, (PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName.c_str()), PWINDOW->m_iWorkspaceID, escapeJSONStrings(PWINDOW->m_iWorkspaceID == -1 ? "" : g_pCompositor->getWorkspaceByID(PWINDOW->m_iWorkspaceID)->m_szName).c_str(),
(int)PWINDOW->m_bIsFloating, (int)PWINDOW->m_bIsFloating,
PWINDOW->m_iMonitorID, PWINDOW->m_iMonitorID,
g_pXWaylandManager->getAppIDClass(PWINDOW).c_str(), escapeJSONStrings(g_pXWaylandManager->getAppIDClass(PWINDOW)).c_str(),
g_pXWaylandManager->getTitle(PWINDOW).c_str(), escapeJSONStrings(g_pXWaylandManager->getTitle(PWINDOW)).c_str(),
PWINDOW->getPID() PWINDOW->getPID()
); );
} else { } else {
@ -199,7 +199,7 @@ std::string layersRequest(HyprCtl::eHyprCtlOutputFormat format) {
R"#("%s": { R"#("%s": {
"levels": { "levels": {
)#", )#",
mon->szName.c_str() escapeJSONStrings(mon->szName).c_str()
); );
int layerLevel = 0; int layerLevel = 0;
@ -225,7 +225,7 @@ R"#( {
layer->geometry.y, layer->geometry.y,
layer->geometry.width, layer->geometry.width,
layer->geometry.height, layer->geometry.height,
layer->szNamespace.c_str() escapeJSONStrings(layer->szNamespace).c_str()
); );
} }
@ -285,7 +285,7 @@ R"#( {
"name": "%s" "name": "%s"
},)#", },)#",
&m, &m,
m.mouse->name escapeJSONStrings(m.mouse->name).c_str()
); );
} }
@ -308,13 +308,13 @@ R"#( {
"active_keymap": "%s" "active_keymap": "%s"
},)#", },)#",
&k, &k,
k.keyboard->name, escapeJSONStrings(k.keyboard->name).c_str(),
k.currentRules.rules.c_str(), escapeJSONStrings(k.currentRules.rules).c_str(),
k.currentRules.model.c_str(), escapeJSONStrings(k.currentRules.model).c_str(),
k.currentRules.layout.c_str(), escapeJSONStrings(k.currentRules.layout).c_str(),
k.currentRules.variant.c_str(), escapeJSONStrings(k.currentRules.variant).c_str(),
k.currentRules.options.c_str(), escapeJSONStrings(k.currentRules.options).c_str(),
KM escapeJSONStrings(KM).c_str()
); );
} }
@ -336,7 +336,7 @@ R"#( {
},)#", },)#",
&d, &d,
d.pTabletParent, d.pTabletParent,
d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "" escapeJSONStrings(d.pTabletParent ? d.pTabletParent->wlrDevice ? d.pTabletParent->wlrDevice->name : "" : "").c_str()
); );
} }
@ -347,7 +347,7 @@ R"#( {
"name": "%s" "name": "%s"
},)#", },)#",
&d, &d,
d.wlrDevice ? d.wlrDevice->name : "" escapeJSONStrings(d.wlrDevice ? d.wlrDevice->name : "").c_str()
); );
} }

View file

@ -3,6 +3,7 @@
#include <algorithm> #include <algorithm>
#include "../Compositor.hpp" #include "../Compositor.hpp"
#include <sys/utsname.h> #include <sys/utsname.h>
#include <iomanip>
static const float transforms[][9] = {{ static const float transforms[][9] = {{
1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
@ -113,6 +114,29 @@ std::string getFormat(const char *fmt, ...) {
return output; return output;
} }
std::string escapeJSONStrings(const std::string& str) {
std::ostringstream oss;
for (auto &c : str) {
switch (c) {
case '"': oss << "\\\""; break;
case '\\': oss << "\\\\"; break;
case '\b': oss << "\\b"; break;
case '\f': oss << "\\f"; break;
case '\n': oss << "\\n"; break;
case '\r': oss << "\\r"; break;
case '\t': oss << "\\t"; break;
default:
if ('\x00' <= c && c <= '\x1f') {
oss << "\\u"
<< std::hex << std::setw(4) << std::setfill('0') << static_cast<int>(c);
} else {
oss << c;
}
}
}
return oss.str();
}
void scaleBox(wlr_box* box, float scale) { void scaleBox(wlr_box* box, float scale) {
box->width = std::round(box->width * scale); box->width = std::round(box->width * scale);
box->height = std::round(box->height * scale); box->height = std::round(box->height * scale);

View file

@ -5,6 +5,7 @@
void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString); void addWLSignal(wl_signal*, wl_listener*, void* pOwner, std::string ownerString);
void wlr_signal_emit_safe(struct wl_signal *signal, void *data); void wlr_signal_emit_safe(struct wl_signal *signal, void *data);
std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string std::string getFormat(const char *fmt, ...); // Basically Debug::log to a string
std::string escapeJSONStrings(const std::string& str);
void scaleBox(wlr_box*, float); void scaleBox(wlr_box*, float);
std::string removeBeginEndSpacesTabs(std::string); std::string removeBeginEndSpacesTabs(std::string);
bool isNumber(const std::string&, bool allowfloat = false); bool isNumber(const std::string&, bool allowfloat = false);