Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

DbSimple: мысли имеют право на существование, но нерелевантны (Dark-Demon)
Author Message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sun Feb 04, 2007 3:23 am ()
   Post subject:
Reply with quote


М

Выделено из темы «DbSimple v2.x: лаконичная работа с различными СУБД»,
расположенной в форуме Конструктор (05 Февраля 2007, 00:36).
Back to top
View user's profile Send private message Send e-mail
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Sun Feb 04, 2007 3:23 am (спустя 1 секунду; написано за 19 минут 1 секунду)
   Post subject:
Reply with quote

Quote:
Вообще, у меня есть такое убеждение, что необходимость получения метаданных базы свидетельствует об ошибке в архитектуре системы.
и? а если исправлять логику системы нет времени и/или возможности?
хорошая система в идеале не должна быть подвязана к конкретным именам. наприер, в SQLite есть ключевое слово ROWID, которое означает ключевое поле независимо от того, как оно названо в конкретной таблице. и это очень удобно.

по сабжу: библиотека довольно неплохо смотрится на фоне конкурентов, но её уже начинает постигать их основная беда - монструозность.

про плейсхолдеты: да, несомненно, вещь довольно мощная, но не слишком наглядная. мы сначала в запросе указываем метки, а потом массивом указываем значения, которые надо туда подставить. тобишь аналогия с таким sql кодом:
Code (SQL): скопировать код в буфер обмена
INSERT INTO TABLE (a,b,c,d,e) value (1000000,'ewecerfer','32d343dd',434353,'43434443')
в итоге, чтобы определить, какое значение куда будет продставлено - приходится считать, на каком месте оно находится.

недавно я размышлял над проблемой автоэкранирования и мне пришла в голову предельно простая, но от этого не менее эффективная идея, которую я реализовал в своём классе: pastebin.mozilla-russia.org/700
суть её заключается в том, что каждый второй переданный функции параметр, пропускается через функцию escape, а каждый первый вставляется как есть, после чего они сливаются в одну строку.
например:
Code (php): скопировать код в буфер обмена
$_db->get2d('select * from table where name=',$_GET['name'],' limit 10');
и этот код является безопасным! (с поправкой на то, что $_GET['name'] не является массивом, но об этом ниже)
это идентично:
Code (php): скопировать код в буфер обмена
$_db->get2d('select * from table where name='.$_db->escape($_GET['name']).' limit 10');
кроме того, все параметры можно передать ввиде одного массива, что позволяет динамически строить запрос:
Code (php): скопировать код в буфер обмена
$q= Array (www.php.net/array)();
$q[]= 'select * from table where name=';
$q[]= isset (www.php.net/isset)($_GET['name'])?$_GET['name']:Array (www.php.net/array)('guest');
$q[]= ' limit 10';
$_db->get2d($q);
функция escape число (даже если оно передаётся ввиде строки) оставляет как есть, строку экранирует и заключает в кавычки, а если передаётся массив, то выбирает первое значение массива, не изменяя его (значения) (это сделано для обхода автоэкранирования - в некоторых случаях необходимо).
например, следующий код не является безопасным:
Code (php): скопировать код в буфер обмена
$_db->get2d('select * from table where name=',Array (www.php.net/array)($_GET['name']),' limit 10');
надеюсь, моя идея покажется вам полезной.

ps: буду признателен, если поможете ещё более упростить и унифицировать код моего класса. :)
Back to top
View user's profile Send private message
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Sun Feb 04, 2007 5:48 am (спустя 2 часа 25 минут; написано за 2 минуты 32 секунды)
   Post subject:
Reply with quote

Quote:
В библиотеке сейчас реализован второй вариант. Первый вариант - довольно серьезное изменение; если ДК согласится, можете предложить свою реализацию с учетом обратной совместимости для включения в релиз.
вот, и ОС (обратная совместимость) очень сильно стопорит развитие...
на мой взгляд ОС не должна быть тормазом - нужно совершенствоваться. для ОС нужно создавать специальные врапперы, либо генерировать нотисы, чтобы программист мог без труда перейти на новую версию.
Back to top
View user's profile Send private message
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Sun Feb 04, 2007 6:17 am (спустя 28 минут; написано за 44 секунды)
   Post subject:
Reply with quote

Dark-Demon wrote:
на мой взгляд ОС не должна быть тормазом - нужно совершенствоваться.
Ну значит Вы ещё просто до этого не доросли :). Вообще говоря, обратная совместимость практически всегда крайне важна, и не стоит менять интерфейс из-за каждого чиха.
Back to top
View user's profile Send private message Send e-mail
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Sun Feb 04, 2007 6:30 am (спустя 13 минут; написано за 5 минут 52 секунды)
   Post subject:
Reply with quote

Юpий Насрeтдинов, из-за каждого безусловно не стоит. поэтому при первом же чихе нужно закапать в нос (усовершенствовать апи), а не ждать, когда сдерётся вся слизистая (SQL в перемешу с плейсхолдерами, параметрами dbSimple, модификаторами, прагма-ветвлениями и прочей лабудой).
пока проект молодой - он сравнительно легко пройдёт через модернизацию. в старческом же возрасте - будет уже поздно. и появится ещё один Дмитрий Котеров, который прийдёт и скажет: "ну фсё, в топку этого монстра, будем делать действительно симпл".

хе-хе, почитал с чего всё начиналось...
Quote:
6_DbSimple version 1.x: лаконичная работа с различными СУБД [?]
Quote:
Проектирование простейшего (!) модуля для абстракции от SQL-сервера. [?]
Quote:
dacuan, все-таки насчет COUNT_TOTAL я еще немного подумал, и решил не делать. И вот почему: данная библиотека - это, как я уже говорил, не средство "выравнивания диалектов", а средство более удобного и простого обращения к SQL-серверу. Соответственно, кода для "выравнивания диалектов" в ней изначально нет и не планировалось. Поддержка COUNT_TOTAL была бы первым блоком кода такого рода, то есть - создает прецедент, причем прецедент поведения, которое в библиотеке не закладывалось изначально. По сему - быть трем функциям.
ну фсё, меняйте название :-D
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sun Feb 04, 2007 8:29 pm (спустя 13 часов 59 минут; написано за 4 минуты 22 секунды)
   Post subject:
Reply with quote

Dark-Demon wrote:
и? а если исправлять логику системы нет времени и/или возможности?
Всему свои пределы. У меня вот на руках тоже есть один проект, где завязка за метаданные базы существанна и обусловлена только исторически. В итоге там приходится использовать Creole, со всеми вытекающими неудобствами.
Dark-Demon wrote:
в итоге, чтобы определить, какое значение куда будет продставлено - приходится считать, на каком месте оно находится
Та же самая проблема, что и в sprintf. На практике она, к счастью, не очень сильно мешает, особенно если форматировать SQL-код не в одну строку, а разбивать по смыслу, чтобы в каждой строчке было всего по нескольку placeholder-ов. К тому же есть placeholder-ы ?a и ?#, их удобно использовать в insert- и update-запросах без потери читабельности:
Code (php): скопировать код в буфер обмена
$DB->query('UPDATE t SET ?a', array (www.php.net/array)(
  'f1' => 'v1',
  'f2' => 'v2',
));
Dark-Demon wrote:
каждый второй переданный функции параметр, пропускается через функцию escape, а каждый первый вставляется как есть
Не особенно универсальное решение - приходится разрывать SQL-запрос, читабельность от этого сильно падает. На мой взгляд - сильнее, чем от необходимости "считать" параметры.
Dark-Demon wrote:
ну фсё, меняйте название
В документации написано, что "simple" относится не к коду, а к интерфейсу. Код вообще смотреть не должно быть необходимости.
Ну все, читайте документацию. :-)
Back to top
View user's profile Send private message Send e-mail
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Sun Feb 04, 2007 11:41 pm (спустя 3 часа 12 минут; написано за 15 минут 10 секунд)
   Post subject:
Reply with quote

Quote:
Всему свои пределы. У меня вот на руках тоже есть один проект, где завязка за метаданные базы существанна и обусловлена только исторически. В итоге там приходится использовать Creole, со всеми вытекающими неудобствами.
именно поэтому нужен механизм, который не будет навязывать программисту какую-либо идеологию, а не говорить: "фи, у вас неправильная архитектура, идите вы на"
Quote:
Та же самая проблема, что и в sprintf.
да, и во многих других вещах. но проблемы нужно решать, а не ссылаться, что они есть везде.
Quote:
К тому же есть placeholder-ы ?a и ?#, их удобно использовать в insert- и update-запросах без потери читабельности:
это пока передаваемый им параметр только один. в более же сложных случаях они делают только хуже (если у вас, конечно, можно использовать несколько ?a, которые берут данные из разных массивов)
Quote:
Не особенно универсальное решение - приходится разрывать SQL-запрос, читабельность от этого сильно падает. На мой взгляд - сильнее, чем от необходимости "считать" параметры.
ой, да ладно :) при многострочном оформлении с читабельностью всё в порядке:
Code (php): скопировать код в буфер обмена
$_DB->get2d('select * from table
        where id= '
,_get('id'),'
        and name= '
,_get('name'),'
        limit 5, 10'
);
Quote:
В документации написано, что "simple" относится не к коду, а к интерфейсу.
я конечно, извиняюсь, но вы и с интерфейсом перемудрили. например, часть параметров (для страничного вывода, например), передаются как параметры, другая часть (параметры кэширования, например) - в комментах SQL. нафига, кстати, кэширование на этом уровне абстракции - тоже не понятно. поддержка гигантских блобов - ума не приложу, зачем их хранить в БД. реализация префиксов таблиц (это необходимо для конкретной CMS, но совершенно не нужно для такой низкоуровневой библиотеки). парсинг (пусть и не слишком глубокий) SQL (не слишком опрятное решение с выводом общего числа в отдельной переменной). организация ветвлений. пока, конечно, в зачаточном состоянии - условный блок, - но подозреваю, что к третьей версии это выльется некоторое подобие макроязыка TAGZ.
да и зря вы отвергаете симплификацию кода. в большом коде со сложными внутренними связями копаться очень нудно и лениво. обычный пользователь в такой код полезет только в случае крайней нужды, а разработчик трижды подумает прежде чем реализовать очередную фичу (и опять же, пока не достанут - не полезет :) ).

Last edited by Dark-Demon on Mon Feb 05, 2007 12:16 am; edited 2 times in total
Back to top
View user's profile Send private message
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Mon Feb 05, 2007 12:09 am (спустя 27 минут; написано за 4 минуты 25 секунд)
   Post subject:
Reply with quote

вот, читаю сейчас ветку и вижу там обсуждение кучи багов. и это неписанный закон программирования: чем сложнее система, тем больше в ней багов.

и ещё, по поводу навязывания идеологии: вы местами предлагаете совсем невменяемые решения. например использовать функцию call_user_func_array для динамических запросов (либо использовать _query, но тогда совершено не понятно, нафига было делать деление на public/private, если в итоге приходится вызывать приватные функции напрямую)
или усложнять SQL запрос, чтобы обойти ограничения плейсхолдеров:
Code (php): скопировать код в буфер обмена
$DB->select("Select * From csp_list where field LIKE CONCAT('%:', ?d, ':%')", $a);
нормальные макроязыки себе такого не позволяют!
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Mon Feb 05, 2007 12:38 am (спустя 29 минут; написано за 33 секунды)
   Post subject:
Reply with quote

Я не спорю, что во многих Ваших замечаниях есть разумное зерно.
Но у меня своя точка зрения на интерфейс библиотеки. Какая из них лучше - покажет время.
Back to top
View user's profile Send private message Send e-mail
Dark-Demon
Участник форума
Banned


Joined: 04 Feb 2007
Posts: 45
Карма: -3
   поощрить/наказать

Location: spb

PostPosted: Mon Feb 05, 2007 3:55 am (спустя 3 часа 16 минут; написано за 1 минуту 31 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров, судя по моему общению с товарищем Юрием Насретдиновым (!!!Добавилась тема!!! (forum.dklab.ru/other/trash/DobavilasTema.html)) место этой темы - в мусоропроводе.

да и назвать её имхо стоит: "Не колышет", ибо "нерелевантно" означает низкий приоритет, а не полный отказ.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Mon Feb 05, 2007 3:27 pm (спустя 11 часов 31 минуту; написано за 1 минуту 34 секунды)
   Post subject:
Reply with quote


М

Нет, этой - не в Мусоропроводе точно, т.к. критика имеет право на существование, даже если я не разделяю многие утверждения.
Однако я бы порекомендовал Вам быть чуть более сдержанным и менее агрессивным и активным. Вы тут совсем недавно, а некоторые люди - многие годы. Вот и результат.
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Wed Feb 07, 2007 10:15 pm (спустя 2 дня 6 часов 48 минут; написано за 5 минут 11 секунд)
   Post subject:
Reply with quote

Дмитрий и другие участники форума выкладывают исходный код своих наработок и идеи, за что им большое спасибо.
Если существующая библиотека не устраивает, вы можете изложить свои мысли и предложения по улучшению (деликатно).
Но авторы могут не согласиться с вами, как произошло в данном случае.
Остается только написать свой программный код, или модернизировать существующий, чтобы в результате получить то, что вас устраивает.
Уже готовая рабочая библиотека показывает опыт ее использования, который вы можете учесть. Взять плюсы и постараться избавиться от минусов.
 
Собственно, я так и собираюсь поступить.
Меня тоже не все устраивает в этой библиотеке.
 
Ограничение
Code (SQL): скопировать код в буфер обмена
$DB->select("Select * From csp_list where field LIKE CONCAT('%:', ?d, ':%')", $a);
решается модернизацией библиотеки.
Необходимо добавить грамматический разбор парных кавычек и вначале обрабатывать их содержимое.
 
А вот подстановку значений через перечисление параметров метода просто так не модернизируешь.
Мне больше нравятся ассоциативные массивы и именованные placeholders.
К тому же они избавляют от DBSIMPLE_SKIP.
Quote:
суть её заключается в том, что каждый второй переданный функции параметр,
пропускается через функцию escape, а каждый первый вставляется как есть, после чего они сливаются в одну строку.
плохая идея, т.к. она тоже не избавляет от просмотра позиций, да еще приходится считать каждый второй!
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Thu Feb 08, 2007 7:17 pm (спустя 21 час 2 минуты; написано за 3 минуты 33 секунды)
   Post subject:
Reply with quote

Rin wrote:
Ограничение
$DB->select("Select * From csp_list where field LIKE CONCAT('%:', ?d, ':%')", $a);
Это не ограничение, это - безопасный стиль программирования. Я считаю, что с ним бороться не нужно совершенно - тем более, что никто не мешает написать
$DB->select("Select * From csp_list where field LIKE ?", "%:$a:%");
Rin wrote:
Мне больше нравятся ассоциативные массивы и именованные placeholders.
Моя практика показала, что именованные placeholder-ы значительно увеличивают рутину (надо аж в 4 местах указывать имена вместо двух), но не дают в то же время ощутимого прироста в читабельности.
Rin wrote:
К тому же они избавляют от DBSIMPLE_SKIP.
А вот это вообще непонятно, к чему сказано. DBSIMPLE_SKIP - это инструмент для работы с макроблоками, к именованным placeholder-ам не имеющий ровным счетом никакого отношения. Применяется он в подавляющем большинстве случаев в сложных SELECT-запросах. Вы точно уверены, что внимательно прочитали документацию?
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Fri Feb 09, 2007 12:34 pm (спустя 17 часов 16 минут; написано за 14 минут 37 секунд)
   Post subject:
Reply with quote

Сравните:
Code (php): скопировать код в буфер обмена
$DB->select("Select * From csp_list where field LIKE ?", "%:$a:%");
#или
$DB->select("Select * From csp_list where field LIKE CONCAT('%:', ?d, ':%')", $a);
#или
$DB->select("Select * From csp_list where field LIKE '%:?d:%'", $a);
Последний вариант, более наглядный, согласитесь.

Внутри кавычек для квотирования можно использовать обратный слеш, например: \?d

Если вместо перечисления параметров использовать один ассоциативный массив (<имя_метки> = <значение_метки>) и именованные метки, то мы можем проверять существование ключа для пропуска макроблоков.

Т.о. мы избавляемся от ненужного кода типа
Code (php): скопировать код в буфер обмена
(isset (www.php.net/isset)($_REQUEST['name']) ? $_REQUEST['name'] : DBSIMPLE_SKIP)
Почему вы считаете, что именованные метки-заменители нужно указывать в 4-х местах?
Максимум 2 раза, один раз в шаблоне SQL запроса, второй раз в качестве ключа ассоц. массива значений.
А вот ассоц. массив значений (или его часть) может быть получен из $_REQUEST.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Sat Feb 10, 2007 12:46 am (спустя 12 часов 11 минут; написано за 10 минут 54 секунды)
   Post subject:
Reply with quote

Rin wrote:
$DB->select("Select * From csp_list where field LIKE '%:?d:%'", $a);
Последний вариант, более наглядный, согласитесь.
Извините за сарказм, но блин. Нельзя так делать, нельзя! Потому что в строке вполне может встретиться константная последовательность "field = '?'", которая означает не "placeholder отдельно", а "вопросительный знак". Например, $DB->query("SELECT * FROM t WHERE field='?'") - найти все записи, поле field которых равно вопросику. Короче говоря, такой синтаксис порождает исключение из общего правила (особенно со слэшами). И так слэш на слэше сидит и слэшем погоняет, а Вы предлагаете еще один слой ввести. Наконец, представьте, что Вы скармливаете в query() запрос, полученный откуда-то извне (например, из файла с sql-командами обновления БД с момента предыдущего релиза). Что, будете слэшить руками все вопросики?

Короче, нет, потому что неконцептуально.
Rin wrote:
Если вместо перечисления параметров использовать один ассоциативный массив (<имя_метки> = <значение_метки>) и именованные метки, то мы можем проверять существование ключа для пропуска макроблоков.
Навскидку аргумент: нельзя этого делать, потому что пропуск ключа может свидетельствовать об ошибке в программе, а вовсе даже не о том, что надо пропустить макроблок. Налицо смешение двух слоев абстракции: слоя макроподстановок и слоя защиты от ошибки во время программирования. (Кстати, в случае нехватки значения для какого-то placeholder-а DbSimple формирует запрос с ошибкой, который очень просто отследить.) В то же время, DBSIMPLE_SKIP явно указывает, что некоторый блок должен быть опущен.
Rin wrote:
Почему вы считаете, что именованные метки-заменители нужно указывать в 4-х местах?
Code (php): скопировать код в буфер обмена
$data = array (www.php.net/array)('field' => getField());
$DB->select("SELECT * FROM table WHERE field = ?field", $data);
(Домашнее задание: подсчитать число встреч подстроки "field" в данном куске кода. Функцию getField() считать не конечной инстанцией, а всего лишь одним из примеров источника данных.)
Rin wrote:
А вот ассоц. массив значений (или его часть) может быть получен из $_REQUEST.
Плохая практика - пихать в SQL-запрос данные, пришедшие из формы без всякой обработки. А если юзер лишнее поле вставит? (Да-да, далеко не все еще используют MetaForm.) Получит ошибку в SQL. А если там уже середина скрипта к моменту этой ошибки, и он кучу всего выполнил, а тут - обломался, а транзакций нету?
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Sat Feb 10, 2007 3:35 pm (спустя 14 часов 49 минут; написано за 32 минуты 14 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Наконец, представьте, что Вы скармливаете в query() запрос, полученный откуда-то извне (например, из файла с sql-командами обновления БД с момента предыдущего релиза). Что, будете слэшить руками все вопросики?
Или релизы будут несовместимыми, или придется прослэшить знаки вопроса и пользоваться усовершенсвованным синтаксисом.
Дмитрий Котеров wrote:
Навскидку аргумент: нельзя этого делать, потому что пропуск ключа может свидетельствовать об ошибке в программе, а вовсе даже не о том, что надо пропустить макроблок.
А если все так и было задумано? Например, я хочу использовать некий фильтр, где кол-во условий заранее не известно.
Дмитрий Котеров wrote:
(Кстати, в случае нехватки значения для какого-то placeholder-а DbSimple формирует запрос с ошибкой, который очень просто отследить.) В то же время, DBSIMPLE_SKIP явно указывает, что некоторый блок должен быть опущен.
В случае с ассоц. массивами будет тоже самое.
Если placeholder стоит внутри {} макроблока, то блок может быть необязательным, иначе (за пределами макроблока), при нехватке значения, возникнет ошибка.
Дмитрий Котеров wrote:
Rin wrote:
Почему вы считаете, что именованные метки-заменители нужно указывать в 4-х местах?
Code (php): скопировать код в буфер обмена
$data = array (www.php.net/array)('field' => getField());
$DB->select("SELECT * FROM table WHERE field = ?field", $data);
(Домашнее задание: подсчитать число встреч подстроки "field" в данном куске кода. Функцию getField() считать не конечной инстанцией, а всего лишь одним из примеров источника данных.)
Это был худший вариант. При хорошо спроектированном приложении их можно свести до 2-х
Дмитрий Котеров wrote:
Rin wrote:
А вот ассоц. массив значений (или его часть) может быть получен из $_REQUEST.
Плохая практика - пихать в SQL-запрос данные, пришедшие из формы без всякой обработки. А если юзер лишнее поле вставит? (Да-да, далеко не все еще используют MetaForm.) Получит ошибку в SQL. А если там уже середина скрипта к моменту этой ошибки, и он кучу всего выполнил, а тут - обломался, а транзакций нету?
Лишнее поле проигнорируется. Просто нужно предусмотреть массив со списком допустимых полей в качестве параметра функции или предусмотреть это в синтаксисе.
Code (SQL): скопировать код в буфер обмена
  INSERT INTO t1 SET ?A:VALUES;
  INSERT INTO t1 (?k:VALUES) VALUES (?a:VALUES);
  INSERT INTO t1 (~id, ~name, ~amount) VALUES (?a:VALUES);
Back to top
View user's profile Send private message Send e-mail
Rin
Участник форума



Joined: 01 Jun 2005
Posts: 515
Карма: 185
   поощрить/наказать

Location: Москва

PostPosted: Tue Feb 20, 2007 10:14 pm (спустя 10 дней 6 часов 38 минут; написано за 36 секунд)
   Post subject:
Reply with quote

Кажется, Дмитрий в отпуске... :)
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 412
   поощрить/наказать


PostPosted: Tue Feb 20, 2007 10:22 pm (спустя 7 минут; написано за 20 секунд)
   Post subject:
Reply with quote

Нет, просто у меня больше аргументов нет, я все сказал... И остаюсь при своем мнении.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
Post a reply
Username
Subject
Господа спамеры и оптимизаторы!

Вы можете даже и не пытаться вставлять в текст поста ссылки - они все равно автоматически удаляются (вернее, тэги <a> заменяются на тэги <u>).

Но если не поверите и все же попытаетесь - как только увидите, что все безрезультатно, удалите свой пост, пожалуйста. Модераторы тоже люди, нехорошо, если они погрязнут в тоннах спама.
     

Disable BBCode in this post
Disable Smilies in this post
    HTML is OFF
BBCode is ON
Smilies are ON
You cannot post new topics in this forum. You can reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML