0

If I want a quoted string in my clipboard:

qDebug() << QString("Boat\nProgramming");

I then copy the output:

"Boat\nProgramming"

If I want a non-quoted string in my clipboard:

qDebug().noquote() << QString("Boat\nProgramming");

I then copy the output:

Boat
Programming

What is the proper way in Qt to register the quoted and non-quoted strings to my [Ubuntu] system's clipboard?


Backstory / Usecase:

I have built a command line application that renders me strings that I occasionally need to dump onto a website's string interpreter (Text to speech if you care) for debugging purposes. Dumping it to the clipboard instead of manually highlighting the text, copying, and pasting, really improves my workflow.

Anon
  • 2,267
  • 3
  • 34
  • 51
  • 1
    "quoted string" is very vague... You probably should write (or find) a function which would *quote* a string (and define the conventions for that). So first code your quotation function. – Basile Starynkevitch Nov 05 '16 at 08:34
  • 1
    It is not a matter of naming, but of quoting conventions (e.g. shells have different quoting conventions than C or JSON). Define and code (or find somewhere) the quotation function, then use it. – Basile Starynkevitch Nov 05 '16 at 08:38
  • BTW, what is the motivation and what is the real case scenario? You should **edit your question** to give a lot more context – Basile Starynkevitch Nov 05 '16 at 11:04
  • 1
    No, on the contrary. Motivation is essential to avoid [XY problems](http://xyproblem.info/) – Basile Starynkevitch Nov 05 '16 at 11:10

2 Answers2

4

"Quoted string" is very ambiguous. For example, in shell the dollar sign is special (and often should be escaped, as some other characters). But in HTML the <, >, &, ', " are special (and often should be escaped). In SQL statements you should only escape the double-quote and the nul character. In C, you would escape control characters and the quote and double-quote and backslash, etc... In JSON rules are slightly different.

So first code the appropriate quotation transformations. Perhaps you want to implement the following functions

QString quoted_for_shell(const QString&);
QString quoted_for_html(const QString&);
QString quoted_for_c(const QString&);

and so on.

(perhaps you should also want to code the reverse unquote transformations; BTW quotations might be tricky: how would you quote my full name in Russian, Cyrillic letters: Василий Дмитриевич Старынкевич in C since not all C implementations use UTF-8, even if they should)

Once you have implemented your quotation machinery (and that is perhaps harder and more ill-defined than you think!), you "just" want to copy QStrings to the clipboard. Then read documentation of QClipboard and perhaps the chapter on drag and drop.

BTW, beware of code injection (which is partly why quoting is really important). Think of some malicious rm -rf $HOME string etc....

Actually, clipboard processing is a delicate thing with X11. See ICCCM & EWMH. You very probably need some event loop running (notably for very long strings of many millions bytes, the selection processing has then to be incremental with several handshakes, and details could be tricky, but are handled by Qt). So you might need QApplication::exec

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
0

Here is a very barebones solution that I implemented:

// #include <QCoreApplication>
// I had to swap to QGuiApplication to get the clipboard functionality.
#include <QGuiApplication>
#include <QClipboard>
#include "whatever.h"

int main(int argc, char *argv[])
{
    QGuiApplication a(argc, argv);
    a.clipboard()->setText(QString("Boat\nProgramming")); // Quoted
    a.clipboard()->setText(QString("Boat\nProgramming")   // Non-Quoted
                           .replace("\n","\\n")
                           .replace("\t","\\t"));

    return 0;
}

As suggested by Basile Starynkevitch; these are not rigorously protected functions, but barebones solutions for small strings. Temporary in my case, and used purely for debugging purposes. Please do read his post, as he provides best practices to avoid code injection, and other security risks.

Anon
  • 2,267
  • 3
  • 34
  • 51
  • 2
    But the last thing is not quoted. What about `$` or even worse, a string like `rm -rf $HOME`; BTW using `QApplication` is probably more appropriate. But you miss a `a.exec();` statement; clipboard handling needs an event loop – Basile Starynkevitch Nov 05 '16 at 10:53
  • @BasileStarynkevitch Wait; will putting `rm -rf $HOME` in the clipboard actually execute it?! I'll try to think of another solution... – Anon Nov 05 '16 at 10:55
  • 2
    That was food for thought. You need to think carefully. – Basile Starynkevitch Nov 05 '16 at 10:56
  • @BasileStarynkevitch I couldn't figure out how to get it working in QApplication. If you toss it in your answer, I'll accept it. – Anon Nov 05 '16 at 11:00
  • BTW, did you test the above code? I'm guessing it does not work as intended (but I did not test it). – Basile Starynkevitch Nov 05 '16 at 11:00
  • 1
    Did you test that with a string of a hundred millions bytes? I'm guessing you could have surprises. – Basile Starynkevitch Nov 05 '16 at 11:06
  • @BasileStarynkevitch That is a good point; That is beyond my usecase, and this will be taken out of my code as it is purely a temporary debugging makeshift in which I control the input. I edited my answer to heed your warning. Thanks for all your input. – Anon Nov 05 '16 at 11:25
  • 1
    Stuff in the clipboard **is often one click away from being executed**. On Linux, there's this thing called middle-click paste. If you have a console open and you middle click by accident, and the pasted contents have a newline, sure as heck the command will get executed! You've just deleted your home directory :/ People who get used to this on Linux will often configure their console on other platforms to do the same thing. – Kuba hasn't forgotten Monica Nov 06 '16 at 02:43
  • @KubaOber For what it is worth; you can choose which clipboard to register to. The example above does not register to middle click. – Anon Nov 06 '16 at 02:45