Skip to content

Commit

Permalink
Merge pull request #1643 from contour-terminal/features/too_big_paste
Browse files Browse the repository at this point in the history
Request permission on big paste
  • Loading branch information
Yaraslaut authored Oct 26, 2024
2 parents 3f86c65 + 30df16b commit aa0ed49
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 4 deletions.
1 change: 1 addition & 0 deletions metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
<li>Expose current profile's name through env var `CONTOUR_PROFILE` (#1637)</li>
<li>Add terminal tabs (#90)</li>
<li>Add `SaveScreenshot` and `CopyScreenshot` action (#210)</li>
<li>Protect user from accidentally pasting too large input (#1198)</li>
<li>Add binding to exit normal mode with `Esc` (#1604)</li>
<li>Add config option to switch into insert mode after yank (#1604)</li>
<li>Improves window size/resize handling on HiDPI monitor settings (#1628)</li>
Expand Down
52 changes: 48 additions & 4 deletions src/contour/TerminalSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,7 @@ void TerminalSession::executeRole(GuardedRole role, bool allow, bool remember)
case GuardedRole::ShowHostWritableStatusLine:
executeShowHostWritableStatusLine(allow, remember);
break;
case GuardedRole::BigPaste: applyPendingPaste(allow, remember); break;
}
}

Expand Down Expand Up @@ -401,6 +402,7 @@ void TerminalSession::requestPermission(config::Permission allowedByConfig, Guar
case GuardedRole::ChangeFont: emit requestPermissionForFontChange(); break;
case GuardedRole::CaptureBuffer: emit requestPermissionForBufferCapture(); break;
case GuardedRole::ShowHostWritableStatusLine: emit requestPermissionForShowHostWritableStatusLine(); break;
case GuardedRole::BigPaste: emit requestPermissionForPasteLargeFile(); break;
// clang-format on
}
}
Expand Down Expand Up @@ -651,23 +653,65 @@ void TerminalSession::pasteFromClipboard(unsigned count, bool strip)
sessionLog()("pasteFromClipboard: mime data contains {} formats.", md->formats().size());
for (int i = 0; i < md->formats().size(); ++i)
sessionLog()("pasteFromClipboard[{}]: {}\n", i, md->formats().at(i).toStdString());
string const text = strip_if(normalize_crlf(clipboard->text(QClipboard::Clipboard)), strip);
if (text.empty())

auto const text = clipboard->text(QClipboard::Clipboard);

// 1 MB hard limit
if (text.size() > 1024 * 1024)
{
sessionLog()("Clipboard contains huge text. Ignoring.");
_display->post([this]() {
emit showNotification("Screenshot", QString::fromStdString("Paste is too big"));
});
return;
}
// 512 KB soft limit to ask user for permission
if (text.size() > 1024 * 512)
{
_pendingBigPaste = clipboard;
emit requestPermissionForPasteLargeFile();
sessionLog()("Clipboard contains huge text. Requesting permission.");
return;
}

string const strippedText = strip_if(normalize_crlf(clipboard->text(QClipboard::Clipboard)), strip);
sessionLog()("Size of text: {}", strippedText.size());
if (strippedText.empty())
sessionLog()("Clipboard does not contain text.");
else if (count == 1)
terminal().sendPaste(string_view { text });
terminal().sendPaste(string_view { strippedText });
else
{
string fullPaste;
for (unsigned i = 0; i < count; ++i)
fullPaste += text;
fullPaste += strippedText;
terminal().sendPaste(string_view { fullPaste });
}
}
else
sessionLog()("Could not access clipboard.");
}

void TerminalSession::applyPendingPaste(bool allow, bool remember)
{
sessionLog()("applyPendingPaste: allow={}, remember={}", allow, remember);
if (remember)
_rememberedPermissions[GuardedRole::BigPaste] = allow;

if (!_pendingBigPaste)
return;

if (!allow)
{
_pendingBigPaste = std::nullopt;
return;
}

auto* clipboard = _pendingBigPaste.value();
auto text = clipboard->text(QClipboard::Clipboard);
terminal().sendPaste(string_view { text.toStdString() });
}

void TerminalSession::onSelectionCompleted()
{
switch (_config.onMouseSelection.value())
Expand Down
5 changes: 5 additions & 0 deletions src/contour/TerminalSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum class GuardedRole : uint8_t
ChangeFont,
CaptureBuffer,
ShowHostWritableStatusLine,
BigPaste,
};

/**
Expand Down Expand Up @@ -240,6 +241,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev
void detachDisplay(display::TerminalDisplay& display);

Q_INVOKABLE void applyPendingFontChange(bool allow, bool remember);
Q_INVOKABLE void applyPendingPaste(bool allow, bool remember);
Q_INVOKABLE void executePendingBufferCapture(bool allow, bool remember);
Q_INVOKABLE void executeShowHostWritableStatusLine(bool allow, bool remember);
Q_INVOKABLE void resizeTerminalToDisplaySize();
Expand Down Expand Up @@ -395,6 +397,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev
void onBell(float volume);
void onAlert();
void requestPermissionForFontChange();
void requestPermissionForPasteLargeFile();
void requestPermissionForBufferCapture();
void requestPermissionForShowHostWritableStatusLine();
void showNotification(QString const& title, QString const& content);
Expand Down Expand Up @@ -470,6 +473,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev
};
std::optional<CaptureBufferRequest> _pendingBufferCapture;
std::optional<vtbackend::FontDef> _pendingFontChange;
std::optional<QClipboard*> _pendingBigPaste;
PermissionCache _rememberedPermissions;
std::unique_ptr<QThread> _exitWatcherThread;

Expand All @@ -494,6 +498,7 @@ struct std::formatter<contour::GuardedRole>: std::formatter<std::string_view>
case contour::GuardedRole::ChangeFont: output = "Change Font"; break;
case contour::GuardedRole::CaptureBuffer: output = "Capture Buffer"; break;
case contour::GuardedRole::ShowHostWritableStatusLine: output = "show Host Writable Statusline"; break;
case contour::GuardedRole::BigPaste: output = "paste large number of characters"; break;
}
// clang-format on
return formatter<string_view>::format(output, ctx);
Expand Down
18 changes: 18 additions & 0 deletions src/contour/ui.template/Terminal.qml.in
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,23 @@ ContourTerminal
}
}


RequestPermission {
id: requestLargeFilePaste
text: "The host application is going to paste large file, are you sure?"
onYesToAllClicked: vtWidget.session.applyPendingPaste(true, true);
onYesClicked: vtWidget.session.applyPendingPaste(true, false);
onNoToAllClicked: vtWidget.session.applyPendingPaste(false, true);
onNoClicked: vtWidget.session.applyPendingPaste(false, false);
onRejected: {
console.log("[Terminal] large file paste is rejected.", vtWidget.session)
if (vtWidget.session !== null)
vtWidget.session.applyPendingPaste(false, false);
}
}



RequestPermission {
id: requestBufferCaptureDialog
text: "The host application is requesting to capture the terminal buffer."
Expand Down Expand Up @@ -265,6 +282,7 @@ ContourTerminal
vt.requestPermissionForFontChange.connect(requestFontChangeDialog.open);
vt.requestPermissionForBufferCapture.connect(requestBufferCaptureDialog.open);
vt.requestPermissionForShowHostWritableStatusLine.connect(requestShowHostWritableStatusLine.open);
vt.requestPermissionForPasteLargeFile.connect(requestLargeFilePaste.open);
forceActiveFocus();

// TAB handling
Expand Down

0 comments on commit aa0ed49

Please sign in to comment.