Avoid potential negative array index access to cached text.
[LibreOffice.git] / vcl / unx / gtk3_kde5 / kde5_filepicker_ipc.cxx
blob7f0bfff985b5c2cdb03f8fe84ed0f82ba0f075be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "kde5_filepicker_ipc.hxx"
22 #include <QUrl>
23 #include <QApplication>
24 #include <QDebug>
26 #include <iostream>
28 #include "kde5_filepicker.hxx"
30 void readIpcArg(std::istream& stream, QString& string)
32 const auto buffer = readIpcStringArg(stream);
33 string = QString::fromUtf8(buffer.data(), buffer.size());
36 void sendIpcArg(std::ostream& stream, const QString& string)
38 const auto utf8 = string.toUtf8();
39 sendIpcStringArg(stream, utf8.size(), utf8.data());
42 static void sendIpcArg(std::ostream& stream, const QStringList& list)
44 stream << static_cast<uint32_t>(list.size()) << ' ';
45 for (const auto& entry : list)
47 sendIpcArg(stream, entry);
51 static void readCommandArgs(Commands command, QList<QVariant>& args)
53 switch (command)
55 case Commands::SetTitle:
57 QString title;
58 readIpcArgs(std::cin, title);
59 args.append(title);
60 break;
62 case Commands::SetWinId:
64 sal_uIntPtr winId = 0;
65 readIpcArgs(std::cin, winId);
66 QVariant aWinIdVariant;
67 aWinIdVariant.setValue(winId);
68 args.append(aWinIdVariant);
69 break;
71 case Commands::SetMultiSelectionMode:
73 bool multiSelection = false;
74 readIpcArgs(std::cin, multiSelection);
75 args.append(multiSelection);
76 break;
78 case Commands::SetDefaultName:
80 QString name;
81 readIpcArgs(std::cin, name);
82 args.append(name);
83 break;
85 case Commands::SetDisplayDirectory:
87 QString dir;
88 readIpcArgs(std::cin, dir);
89 args.append(dir);
90 break;
92 case Commands::AppendFilter:
94 QString title, filter;
95 readIpcArgs(std::cin, title, filter);
96 args.append(title);
97 args.append(filter);
98 break;
100 case Commands::SetCurrentFilter:
102 QString title;
103 readIpcArgs(std::cin, title);
104 args.append(title);
105 break;
107 case Commands::SetValue:
109 sal_Int16 controlId = 0;
110 sal_Int16 nControlAction = 0;
111 bool value = false;
112 readIpcArgs(std::cin, controlId, nControlAction, value);
113 args.append(controlId);
114 args.append(nControlAction);
115 args.append(value);
116 break;
118 case Commands::GetValue:
120 sal_Int16 controlId = 0;
121 sal_Int16 nControlAction = 0;
122 readIpcArgs(std::cin, controlId, nControlAction);
123 args.append(controlId);
124 args.append(nControlAction);
125 break;
127 case Commands::EnableControl:
129 sal_Int16 controlId = 0;
130 bool enabled = false;
131 readIpcArgs(std::cin, controlId, enabled);
132 args.append(controlId);
133 args.append(enabled);
134 break;
136 case Commands::SetLabel:
138 sal_Int16 controlId = 0;
139 QString label;
140 readIpcArgs(std::cin, controlId, label);
141 args.append(controlId);
142 args.append(label);
143 break;
145 case Commands::GetLabel:
147 sal_Int16 controlId = 0;
148 readIpcArgs(std::cin, controlId);
149 args.append(controlId);
150 break;
152 case Commands::AddCheckBox:
154 sal_Int16 controlId = 0;
155 bool hidden = false;
156 QString label;
157 readIpcArgs(std::cin, controlId, hidden, label);
158 args.append(controlId);
159 args.append(hidden);
160 args.append(label);
161 break;
163 case Commands::Initialize:
165 bool saveDialog = false;
166 readIpcArgs(std::cin, saveDialog);
167 args.append(saveDialog);
168 break;
170 default:
172 // no extra parameters/arguments
173 break;
178 static void readCommands(FilePickerIpc* ipc)
180 while (!std::cin.eof())
182 uint64_t messageId = 0;
183 Commands command;
184 readIpcArgs(std::cin, messageId, command);
186 // retrieve additional command-specific arguments
187 QList<QVariant> args;
188 readCommandArgs(command, args);
190 emit ipc->commandReceived(messageId, command, args);
192 // stop processing once 'Quit' command has been sent
193 if (command == Commands::Quit)
195 return;
200 FilePickerIpc::FilePickerIpc(KDE5FilePicker* filePicker, QObject* parent)
201 : QObject(parent)
202 , m_filePicker(filePicker)
204 // required to be able to pass those via signal/slot
205 qRegisterMetaType<uint64_t>("uint64_t");
206 qRegisterMetaType<Commands>("Commands");
208 connect(this, &FilePickerIpc::commandReceived, this, &FilePickerIpc::handleCommand);
210 // read IPC commands and their args in a separate thread, so this does not block everything else;
211 // 'commandReceived' signal is emitted every time a command and its args have been read;
212 // thread will run until the filepicker process is terminated
213 m_ipcReaderThread = std::make_unique<std::thread>(readCommands, this);
216 FilePickerIpc::~FilePickerIpc()
218 // join thread that reads commands
219 m_ipcReaderThread->join();
222 bool FilePickerIpc::handleCommand(uint64_t messageId, Commands command, QList<QVariant> args)
224 switch (command)
226 case Commands::SetTitle:
228 QString title = args.takeFirst().toString();
229 m_filePicker->setTitle(title);
230 return true;
232 case Commands::SetWinId:
234 sal_uIntPtr winId = args.takeFirst().value<sal_uIntPtr>();
235 m_filePicker->setWinId(winId);
236 return true;
238 case Commands::Execute:
240 sendIpcArgs(std::cout, messageId, m_filePicker->execute());
241 return true;
243 case Commands::SetMultiSelectionMode:
245 bool multiSelection = args.takeFirst().toBool();
246 m_filePicker->setMultiSelectionMode(multiSelection);
247 return true;
249 case Commands::SetDefaultName:
251 QString name = args.takeFirst().toString();
252 m_filePicker->setDefaultName(name);
253 return true;
255 case Commands::SetDisplayDirectory:
257 QString dir = args.takeFirst().toString();
258 m_filePicker->setDisplayDirectory(dir);
259 return true;
261 case Commands::GetDisplayDirectory:
263 sendIpcArgs(std::cout, messageId, m_filePicker->getDisplayDirectory());
264 return true;
266 case Commands::GetSelectedFiles:
268 QStringList files;
269 for (auto const& url_ : m_filePicker->getSelectedFiles())
271 auto url = url_;
272 if (url.scheme() == QLatin1String("webdav")
273 || url.scheme() == QLatin1String("webdavs"))
275 // translate webdav and webdavs URLs into a format supported by LO
276 url.setScheme(QLatin1String("vnd.sun.star.") + url.scheme());
278 else if (url.scheme() == QLatin1String("smb"))
280 // clear the user name - the GIO backend does not support this apparently
281 // when no username is available, it will ask for the password
282 url.setUserName({});
284 files << url.toString();
286 sendIpcArgs(std::cout, messageId, files);
287 return true;
289 case Commands::AppendFilter:
291 QString title = args.takeFirst().toString();
292 QString filter = args.takeFirst().toString();
293 m_filePicker->appendFilter(title, filter);
294 return true;
296 case Commands::SetCurrentFilter:
298 QString title = args.takeFirst().toString();
299 m_filePicker->setCurrentFilter(title);
300 return true;
302 case Commands::GetCurrentFilter:
304 sendIpcArgs(std::cout, messageId, m_filePicker->getCurrentFilter());
305 return true;
307 case Commands::SetValue:
309 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
310 sal_Int16 nControlAction = args.takeFirst().value<sal_Int16>();
311 bool value = args.takeFirst().toBool();
312 m_filePicker->setValue(controlId, nControlAction, value);
313 return true;
315 case Commands::GetValue:
317 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
318 sal_Int16 nControlAction = args.takeFirst().value<sal_Int16>();
319 sendIpcArgs(std::cout, messageId, m_filePicker->getValue(controlId, nControlAction));
320 return true;
322 case Commands::EnableControl:
324 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
325 bool enabled = args.takeFirst().toBool();
326 m_filePicker->enableControl(controlId, enabled);
327 return true;
329 case Commands::SetLabel:
331 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
332 QString label = args.takeFirst().toString();
333 m_filePicker->setLabel(controlId, label);
334 return true;
336 case Commands::GetLabel:
338 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
339 sendIpcArgs(std::cout, messageId, m_filePicker->getLabel(controlId));
340 return true;
342 case Commands::AddCheckBox:
344 sal_Int16 controlId = args.takeFirst().value<sal_Int16>();
345 bool hidden = args.takeFirst().toBool();
346 QString label = args.takeFirst().toString();
347 m_filePicker->addCheckBox(controlId, label, hidden);
348 return true;
350 case Commands::Initialize:
352 bool saveDialog = args.takeFirst().toBool();
353 m_filePicker->initialize(saveDialog);
354 return true;
356 case Commands::EnablePickFolderMode:
358 m_filePicker->enableFolderMode();
359 return true;
361 case Commands::Quit:
363 QCoreApplication::quit();
364 return false;
367 qWarning() << "unhandled command " << static_cast<uint16_t>(command);
368 QCoreApplication::exit(1);
369 return false;
372 #include <kde5_filepicker_ipc.moc>
374 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */