|
10 | 10 | """Implements Restore Utility""" |
11 | 11 |
|
12 | 12 | import json |
| 13 | +import re |
13 | 14 |
|
14 | 15 | from flask import render_template, request, current_app, Response |
15 | 16 | from flask_babel import gettext as _ |
@@ -374,7 +375,38 @@ def use_restore_utility(data, manager, server, driver, conn, filepath): |
374 | 375 | return None, utility, args |
375 | 376 |
|
376 | 377 |
|
| 378 | +def has_meta_commands(path, chunk_size=8 * 1024 * 1024): |
| 379 | + """ |
| 380 | + Quickly detect lines starting with '\' in large SQL files. |
| 381 | + Works even when lines cross chunk boundaries. |
| 382 | + """ |
| 383 | + # Look for start-of-line pattern: beginning or after newline, |
| 384 | + # optional spaces, then backslash |
| 385 | + pattern = re.compile(br'(^|\n)[ \t]*\\') |
| 386 | + |
| 387 | + with open(path, "rb") as f: |
| 388 | + prev_tail = b"" |
| 389 | + while chunk := f.read(chunk_size): |
| 390 | + data = prev_tail + chunk |
| 391 | + |
| 392 | + # Search for pattern |
| 393 | + if pattern.search(data): |
| 394 | + return True |
| 395 | + |
| 396 | + # Keep a small tail to preserve line boundary context |
| 397 | + prev_tail = data[-10:] # keep last few bytes |
| 398 | + |
| 399 | + return False |
| 400 | + |
| 401 | + |
377 | 402 | def use_sql_utility(data, manager, server, filepath): |
| 403 | + # Check the meta commands in file. |
| 404 | + if has_meta_commands(filepath): |
| 405 | + return _("Restore blocked: the selected PLAIN SQL file contains psql " |
| 406 | + "meta-commands (for example \\! or \\i). For safety, " |
| 407 | + "pgAdmin does not execute meta-commands from PLAIN restores. " |
| 408 | + "Please remove meta-commands."), None, None |
| 409 | + |
378 | 410 | utility = manager.utility('sql') |
379 | 411 | ret_val = does_utility_exist(utility) |
380 | 412 | if ret_val: |
|
0 commit comments