2010-07-09 11 views

Odpowiedz

30

String::ShellQuote, ale przez większość czasu nie jest to konieczne. Po prostu można uniknąć wywoływania powłoki przez ostrożne programowanie. Na przykład: system takes a list of arguments zamiast ciągu.

Najlepsza praktyka:

use IPC::System::Simple qw(systemx); 
systemx($command, @arguments); 

require IPC::System::Simple; 
use autodie qw(:all); 
system([@allowed_exit_values], $command, @arguments); 
+5

Tak, po prostu uniknąć powłokę całkowicie, jeśli w ogóle możliwe. –

+3

Dobra robota odpowiadając na [pytanie XY] (http://www.perlmonks.org/index.pl?node_id=542341) z odpowiednim rozwiązaniem. :) – Ether

+0

Czy jednak ta pomoc może być potrzebna, gdy potrzebujesz przekierowania (nie możesz użyć formy listy wywołania systemowego) * i * argumentów ze zmiennych? na przykład rozwiązanie następującej nieudanej próby 'ls 'f o o'':' my $ foo =' f o o '; my $ result = \ 'ls $ foo 2> &1\';'? – artfulrobot

3

Perl można dopasować następujące stwierdził funkcję:

dodaje apostrofów wokół sznurka i cytaty/ucieka istniejące apostrofów

http://php.net/manual/en/function.escapeshellarg.php#function.escapeshellarg

tak:

sub php_escapeshellarg { 
    my $str = @_ ? shift : $_; 
    $str =~ s/((?:^|[^\\])(?:\\\\)*)'/$1'\\''/g; 
    return "'$str'"; 
} 
+1

To nie działa. Rozważ przekazanie ciągu 'foo'bar' do funkcji. Wygeneruje następujący ciąg: '' foo \ 'bar''. Ale nie ma unikniętych pojedynczych cudzysłowów w pojedynczym cudzysłowie. – josch

0

muszę zgodzić się z @daxim. Ale są pewne okoliczności, w których nie można tego użyć, jak przekazanie polecenia przez gniazdo do programu, który nie jest perl lub nie ma dostępnego modułu IPC. Spojrzałem również na wyrażenie regularne podane przez @axeman i wydaje mi się to nieco skomplikowane. Mogę się mylić, ale myślę, że nie musisz uciekać odskoków odwrotnych w ciągu pojedynczych ciągów znaków dla polecenia. Więc może po prostu to zrobić:

sub escapeshellarg { 
    my $arg = shift; 

    $arg =~ s/'/'\\''/g; 
    return "'" . $arg . "'"; 
} 

Jeśli ktoś ma jakiś powód, dlaczego może to być niebezpieczne, chciałbym wiedzieć. Przetestowałem to używając wszelkiego rodzaju sztuczek, które mogłem wymyślić, aby powłoka wykonywała dowolny kod, bez powodzenia, co powoduje, że myślę, że to wyrażenie regularne jest takie samo jak implementacja PHP.

W implementacji PHP stwierdza, że ​​wszystko, co robi, to: dodaje pojedyncze cudzysłowy wokół ciągu i cytuje/wymyka się z istniejących pojedynczych cudzysłowów.

To jedyna rzecz, którą robi to wyrażenie regularne. Myśli?

+2

Jestem sceptyczny, zawsze wolałbym sprawdzony przez cantensantów [String :: ShellQuote] (http://p3rl.org/String::ShellQuote), który został wdrożony na wolności od lat i ma raporty o błędach i -poprawy aby pokazać to za pomocą wyrażeń regularnych użytkownika SO. Możesz porównać swój kod z własnym i dowiedzieć się, czego Ci brakuje. – daxim

+0

@daxim nie są zbyt łatwe do porównania: http://api.metacpan.org/source/ROSCH/String-ShellQuote-1.04/ShellQuote.pm – dlamblin

+0

Przepraszam, przepraszam, że przypadkowo cofnęłam twoją odpowiedź, a teraz nie mogę jej cofnąć . :( – josch

1

Ten działa na mnie w bash

sub escape_shell_param($) { 
    my ($par) = @_; 
    $par =~ s/'/'"'"'/g; # "escape" all single quotes 
    return "'$par'";  # single-quote entire string 
} 

Jest on oparty na poniższych stwierdzeń pobranych ze strony BASH Man:

  1. załączając znaków w apostrofy chroni dosłowne wartości każdy znak w cudzysłowie.
  2. Pojedynczy cudzysłów nie może występować między pojedynczymi cudzysłowami, nawet jeśli poprzedza je odwrotny ukośnik.
  3. Umieszczenie znaków w cudzysłowach zachowuje literalną wartość wszystkich znaków w cudzysłowach, z wyjątkiem $, `, \, i gdy rozszerzenie historii jest włączone,!.

Od (2.) wiemy, że odwrotny ukośnik nie może być użyty do uniknięcia pojedynczych pytań, ale z (3) sugeruje, że podwójne cudzysłowy zachowują literalną wartość pojedynczych cudzysłowów (znanych też jako ucieczka).

Należy również pamiętać, że jedynym celem cytatów jest zmiana znaczenia cytowanych znaków (nie są tworzone żadne specjalne obiekty typu string lub podobne rzeczy), a po rozwinięciu wszystkie kolejne znaki literalne są połączone. Następnie 'foo''bar' jest taki sam jak foobar.

Funkcja powyższa polega na pojedynczym zacytowaniu całego łańcucha, aby żaden znak nie miał specjalnego znaczenia. Jednak, aby umożliwić obecność znaków pojedynczego cudzysłowu, ciąg znaków jest dzielony, gdy tylko takie znaki zostaną znalezione, i wykonywane są następujące operacje: poprzedni podciąg jest sfinalizowany ('), następnie wprowadzany jest podwójny cudzysłów ("'") i rozpoczyna się następny podciąg ('). Dlatego ' jest globalnie zastępowany przez '"'"'.

Na przykład (pseudokod):

foo'bar => 'foo' + "'" + 'bar' 
Powiązane problemy