Сегодня на Хабре наткнулся на неплохую задачу для своих мозгов.
Нужно было реализовать функцию read_conf принимающую имя файла с содержимым:
id=www
session.timeout=120
session.server.0.host=127.0.0.1
session.server.0.port=1111
session.server.0.id=session1
session.server.1.host=127.0.0.1
session.server.1.port=1111
session.server.1.id=session2
image.width=640
image.height=480
image.watermark.small=wsmall.png
image.watermark.normal=wnormal.png
Которая приводит конфиг к такой переменной:
array(3) {
["id"]=>strong(3) "www"
["session"]=>array(2) {
["timeout"]=>string(3) "120"
["server"]=>array(2) {
[0]=>
array(3) {
["host"]=>
string(9) "127.0.0.1"
["post"]=>
string(4) "1111"
["id"]=>
string(8) "session1"
}
[1]=>
array(3) {
["host"]=>
string(9) "127.0.0.1"
["port"]=>
string(4) "1111"
["id"]=>
string(8) "session2"
}
}
}
["image"]=>
array(3) {
["width"]=>
string(3) "640"
["height"]=>
string(3) "480"
["watermark"]=>
array(2) {
["small"]=>
string(10) "wsmall.png"
["normal"]=>
string(11) "wnormal.png"
}
}
}
На задачу выделялось 10 минут.
Задача не очень сложная, если не ограничиваться временем, честно признаться мне немного не хватило 10 минут,
но я и не претендую на звания "Гуру php", да и не это важно.
Я как человек любопытный стал просматривать комментарии, чтобы найти наиболее интересные решения данной задачи.
По мнению большинства читателей топика наилучшее решение (наибольшее число позитивных отзывов за комментарий)
было следующее решение:
Гениально! Наименьшее число строк! Никакой рекурсии! Умница!
Вы тоже так подумали? Нет? И ПРАВИЛЬНО!
Ведь дырка! Ну как никто из них об этом не подумал? Теперь в конфиг можно вставить, какой угодно код, который будет выполнен запускаемым скриптом!
Не верите? Попробуйте вот такой конфиг (будет работать в Unix-подобной ОС, но для пользователей Windows можно написать свой пример).
id=www
session.timeout=120
session.server.0.host=127.0.0.1
session.server.0.port=1111
session.server.0.id=session1
session.server.1.host=127.0.0.1
session.server.1.port=1111
session.server.1.id=session2
image.width=640"\";shell_exec('ls -l > hack');\""
image.height=480
image.watermark.small=wsmall.png
image.watermark.normal=wnormal.png
Я его немного изменил, добавил вот такой кусочек "\";shell_exec('ls -l > hack');\"". И теперь имею снимок поточной директории.
Но мы можем с легкостью изменить конфиг добавив вместо 'ls -l > hack', например 'rm -Rf /'. В общем еще очень много гадости можно придумать.
Но самое главное об этом НИКТО не подумал. Такой серьезный информационный портал. Множество действительно профессиональных php-программистов. И НИКТО не сделал по этому поводу замечания. А теперь представьте, масштаб трагедии...
Как таким людям можно доверить серьезный проект? В общем я бы побоялся.
А Вы?
С ув. antonfin
P.S. Нет, все таки нашелся человек, который сделал замечания по данному вопросу. Но его комментарий не был поддержан, я бы даже сказал, что он был обвинен в ханжестве.
Нужно было реализовать функцию read_conf принимающую имя файла с содержимым:
id=www
session.timeout=120
session.server.0.host=127.0.0.1
session.server.0.port=1111
session.server.0.id=session1
session.server.1.host=127.0.0.1
session.server.1.port=1111
session.server.1.id=session2
image.width=640
image.height=480
image.watermark.small=wsmall.png
image.watermark.normal=wnormal.png
Которая приводит конфиг к такой переменной:
array(3) {
["id"]=>strong(3) "www"
["session"]=>array(2) {
["timeout"]=>string(3) "120"
["server"]=>array(2) {
[0]=>
array(3) {
["host"]=>
string(9) "127.0.0.1"
["post"]=>
string(4) "1111"
["id"]=>
string(8) "session1"
}
[1]=>
array(3) {
["host"]=>
string(9) "127.0.0.1"
["port"]=>
string(4) "1111"
["id"]=>
string(8) "session2"
}
}
}
["image"]=>
array(3) {
["width"]=>
string(3) "640"
["height"]=>
string(3) "480"
["watermark"]=>
array(2) {
["small"]=>
string(10) "wsmall.png"
["normal"]=>
string(11) "wnormal.png"
}
}
}
На задачу выделялось 10 минут.
Задача не очень сложная, если не ограничиваться временем, честно признаться мне немного не хватило 10 минут,
но я и не претендую на звания "Гуру php", да и не это важно.
Я как человек любопытный стал просматривать комментарии, чтобы найти наиболее интересные решения данной задачи.
По мнению большинства читателей топика наилучшее решение (наибольшее число позитивных отзывов за комментарий)
было следующее решение:
<?php $r = read_conf( "config.txt" ); print var_dump( $r ); function read_conf($filename) { foreach (parse_ini_file($filename) as $key=>$value) { $key = vsprintf('$result["%s"] = "%s";', array( str_replace('.', '"]["', $key), $value, )); eval($key); } return $result; } ?>
Гениально! Наименьшее число строк! Никакой рекурсии! Умница!
Вы тоже так подумали? Нет? И ПРАВИЛЬНО!
Ведь дырка! Ну как никто из них об этом не подумал? Теперь в конфиг можно вставить, какой угодно код, который будет выполнен запускаемым скриптом!
Не верите? Попробуйте вот такой конфиг (будет работать в Unix-подобной ОС, но для пользователей Windows можно написать свой пример).
id=www
session.timeout=120
session.server.0.host=127.0.0.1
session.server.0.port=1111
session.server.0.id=session1
session.server.1.host=127.0.0.1
session.server.1.port=1111
session.server.1.id=session2
image.width=640"\";shell_exec('ls -l > hack');\""
image.height=480
image.watermark.small=wsmall.png
image.watermark.normal=wnormal.png
Я его немного изменил, добавил вот такой кусочек "\";shell_exec('ls -l > hack');\"". И теперь имею снимок поточной директории.
Но мы можем с легкостью изменить конфиг добавив вместо 'ls -l > hack', например 'rm -Rf /'. В общем еще очень много гадости можно придумать.
Но самое главное об этом НИКТО не подумал. Такой серьезный информационный портал. Множество действительно профессиональных php-программистов. И НИКТО не сделал по этому поводу замечания. А теперь представьте, масштаб трагедии...
Как таким людям можно доверить серьезный проект? В общем я бы побоялся.
А Вы?
С ув. antonfin
P.S. Нет, все таки нашелся человек, который сделал замечания по данному вопросу. Но его комментарий не был поддержан, я бы даже сказал, что он был обвинен в ханжестве.
Вот код на Perl, без рекурсии. Было бы больше времени, то можно было бы сделать красивше :)
ОтветитьУдалитьsub read_conf {
my $file = shift;
my $conf = {};
open(my $fh, '<', $file) or die "ERROR: $!";
while ( my $line = <$fh> ) {
chomp($line);
my ($key, $val) = split(/=/, $line);
my @sub_keys = split(/\./, $key);
my ($parent, $i) = ( $conf, 0 );
for ( $i = 0; $i<$#sub_keys; $i++ ){
$parent = $parent->{$sub_keys[$i]} ||= {};
}
$parent->{$sub_keys[$i]} = $val;
}
close $fh;
return $conf;
}
@koorchik Мне нравиться
ОтветитьУдалитьИ как вы этой дыркой сможете воспользоваться на реальном сайте?
ОтветитьУдалить