Модераторы: LSD, AntonSaburov

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> JSP — с чего начать? 
V
    Опции темы
Stampede
Дата 29.7.2007, 01:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Ага, посмотрю попозже. Щас только с пейнтбола, указательный палец все еще спусковой крючок пытается на мышке нащупать smile


--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
diablero
Дата 29.7.2007, 11:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Цитата(diablero @  28.7.2007,  21:10 Найти цитируемый пост)
при редиректе на home.shtml ничего не происходит

Я понял почему такая проблема. Кукисы не удалялись.
Все работает только при одном условии, если после того как "выйти", нажать обновить.


Это сообщение отредактировал(а) diablero - 29.7.2007, 11:51


--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
batigoal
Дата 29.7.2007, 12:04 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Нелетучий Мыш
****


Профиль
Группа: Участник Клуба
Сообщений: 6423
Регистрация: 28.12.2004
Где: Санктъ-Петербургъ

Репутация: 16
Всего: 151



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


--------------------
"Чтобы правильно задать вопрос, нужно знать большую часть ответа" (Р. Шекли)
ЖоржЖЖ
PM WWW   Вверх
Stampede
Дата 30.7.2007, 19:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(diablero @  29.7.2007,  02:48 Найти цитируемый пост)
Все работает только при одном условии, если после того как "выйти", нажать обновить.


Вот, вот это очень важный момент. Почему я и категорически настаиваю, чтобы по POST обязательно шел редирект именно на страницу подтверждения. Дело в том, что у разных браузеров - различная умолчальная политика кэширования страниц, и если мы хотим предсказуемого поведения, то должны явно управлять кэшированием на клиенте. Делается это выставлением заголовков ответа HTTP. Нам нужно, чтобы страница подтверждения никогда не кэшировалась. Для этого в соответствующем воркере (да-да, нам понадобится специальный воркер) нужно будет выставить такие заголовки:

Код

response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-control", "no-cache, no-store");
response.addDateHeader("Expires", 0);


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

Для выхода лучше написать отдельный LogoutWorker, потому что логика там совсем другая, и не нужно мешатьь ее в одну кучу с логикой для логина.

Да, и вот еще. Метод Worker.getTemplateName() был введен нами в интерфейс Worker вынужденно, за неимением лучшего места. Но теперь, с введением класса Page, будет намного логичнее переместить этот метод имено туда.

Я понимаю, что все это выглядит сейчас несколько запутанно. Ничего не поделаешь: такова природа вебной коммуникации. Но зато ты сейчас работаешь фактически напрямую с HTTP, а не прячешься от него за ширмой туманных директив JSP, и мало-помалу у тебя в голове уляжется, что и как там происходит.

В общем, потерпи - обещаю, просветление уже близко smile

batigoal:

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


--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
Maksym
Дата 30.7.2007, 20:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


.
***


Профиль
Группа: Участник Клуба
Сообщений: 1456
Регистрация: 19.8.2005
Где: Odessa, Black Sea

Репутация: 24
Всего: 62



Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
Но зато ты сейчас работаешь фактически напрямую с HTTP, а не прячешься от него за ширмой туманных директив JSP

Я, наблюдая за сериалом, получаю огромное удовольствие именно от этого smile вопрос в том насколько удастся, не теряя этой супер гибкости, зафреймвочить все рутинные вещи.. уверен что все будет ок smile но интересно куда ты нас заведешь..
и насколько результирующая архитектура будет компонентной.. вот, например, захочу я внедрить в страницы элемент с ajax-поведением.. но, боюсь, я забегаю вперед..
Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
обещаю, просветление уже близко

 smile 

PM MAIL   Вверх
diablero
Дата 30.7.2007, 20:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
 Для этого в соответствующем воркере (да-да, нам понадобится специальный воркер) нужно будет выставить такие заголовки:

Тут я не понял кудаsmile Вставил пока для проверки в HomeWorker, все тип-топ.
Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
Для выхода лучше написать отдельный LogoutWorker

Сделал.
Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
Да, и вот еще. Метод Worker.getTemplateName() был введен нами в интерфейс Worker вынужденно, за неимением лучшего места. Но теперь, с введением класса Page, будет намного логичнее переместить этот метод имено туда.

Сделал, добавил сеттер. Чтобы можно было подменять шаблон.
Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
В общем, потерпи - обещаю, просветление уже близко

Терпения у меня вагон и маленькая тележкаsmile

Добавлено через 7 минут и 36 секунд
to модераторам
Какая-то ерунда иногда происходит при загрузке страницы форума, она иногда грузиться, грузиться, закачивается примерно пол метра и все. Нажимаешь обновить и она грузиться нормально.  


--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
Stampede
Дата 30.7.2007, 22:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(diablero @  30.7.2007,  11:56 Найти цитируемый пост)
Цитата(Stampede @  30.7.2007,  19:27 Найти цитируемый пост)
 Для этого в соответствующем воркере (да-да, нам понадобится специальный воркер) нужно будет выставить такие заголовки:

Тут я не понял кудаsmile Вставил пока для проверки в HomeWorker, все тип-топ.


Знач объясняю. Там на самом деле все достаточно просто. У нас будет специальная страница, доступная по адресу /confirmation.shtml. Это не совсем обычная страница, так как она будет использоваться во всех сценариях обработки форм (то, что называется web flow). Основное ее назначение - свести к минимуму сюрпризы, связанные с особенностями вебного взаимодействия: причуды браузеров, причуды пользователей, перемещения по кнопкам взад-вперед, работа из нескольких окон/закладок, и пр.

Так вот, чтобы все это исключить (или хотя бы свести к минимуму), нужно сделать так, чтобы содержимое /confirmation.shtml не кэшировалось в браузере, а каждый раз запрашивалось с сервера. С этой целью мы заводим специальный ConfirmationWorker, который делает две вещи: переопределяет templateName на confirmation.vm, и выставляет заголовки управления кэшированием.

Пару слов о содержимом confirmation.vm. Понятно, что текст подтверждения будет зависеть от выполненного юзером действия. Например:
  • Вход: Здравствуйте, diablero! Рады видеть вас вновь на нашем сайте.
    Перейти на страницу профиля.
  • Выход: До свидания. Надеемся увидеть вас снова.
    Перейти на главную страницу.
  • Пост: Спасибо, diablero, ваша статья "Технико-тактические характеристики вооружения армии Тамерлана" успешно сохранена.
    Перейти на страницу статьи.

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

Действие выполнено.
Перейти на главную страницу.

Далее, еще один момент. Я пытался сэкономить тебе один набор УРЛ-маппинг-воркер-шаблон, но сейчас вижу, что получилось в итоге хуже. Поэтому давай поправим, пока не поздно.

Идея в том, чтобы сделать форму для логина отдельной страницей, а не помещать ее в шапку основного шаблона. Предлагаю сделать так:

УРЛ: /form/login.shtml
Воркер: ru.selfexpression.workers.LoginFormWorker
Шаблон: templates/form/login.vm

Логики в воркере практически никакой не будет, кроме задания шаблона.

Действия по сабмиту (LoginWorker) остаются в основном без изменений, но в случае неуспешного логина выставляется redirectionUrl равный /form/login.shtml. То есть юзеру предлагается повторить ввод.

Попутно отмечу, что раз мы задаем адрес для переадресации, никаких шаблонов указывать не надо, поскольку до рендеринга дело все равно не дойдет.


Цитата(Maksym @  30.7.2007,  11:17 Найти цитируемый пост)
вот, например, захочу я внедрить в страницы элемент с ajax-поведением.. но, боюсь, я забегаю вперед.


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



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
diablero
Дата 30.7.2007, 23:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Цитата(Stampede @  30.7.2007,  22:03 Найти цитируемый пост)
Идея в том, чтобы сделать форму для логина отдельной страницей, а не помещать ее в шапку основного шаблона.

А у меня сделанно отдельной страницей.
Код

public class LoginWorker extends AbstractWorker implements Worker {
    protected Page page;

    public Page execute(HttpServletRequest request, HttpServletResponse response) {
        page = new Page(request, response);

        String userName = request.getParameter("userName");
        String password = request.getParameter("password");
        Infinite infinite = Infinite.getInstance();
        UserManager manager = infinite.getUserManger();
        User user;
        try {
            user = manager.login(userName, password);
            page.setLongLivedCookie("userName", user.getName());
            page.setLongLivedCookie("password", user.getPassword());
            page.setTemplateName("template.vm");
            page.setRedirectUrl("/home.shtml");
        } catch (Exception e) {
            page.put("flag", "login");
            page.put("error", "true");
            page.setTemplateName("login.vm");
        }
        return page;
    }
}

Мы же договаривались:
Цитата(Stampede)

чтобы сделать в шапке избирательное приветствие: либо "Привет, diablero! | Выход", либо "Имя: | Пароль: | Войти".

Поэтому в HomeWorker'е:
Код

        super.execute(request, response);
        page = new Page(request, response);
        if (user != null) {
            page.put("user", user);
            page.put("flag", "unlogin");
        }
        page.put("logincontent", "confirmation.vm");
        page.put("content", "home.vm");
        return page;


Полный текст на предыдущей странице. В связи с последними изменениями confirmation.vm теперь у меня login.vm

Цитата(Stampede @  30.7.2007,  22:03 Найти цитируемый пост)
Так вот, чтобы все это исключить (или хотя бы свести к минимуму), нужно сделать так, чтобы содержимое /confirmation.shtml не кэшировалось в браузере, а каждый раз запрашивалось с сервера. С этой целью мы заводим специальный ConfirmationWorker, который делает две вещи: переопределяет templateName на confirmation.vm, и выставляет заголовки управления кэшированием.

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


Это сообщение отредактировал(а) diablero - 30.7.2007, 23:19


--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
Stampede
Дата 31.7.2007, 00:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(diablero @  30.7.2007,  14:05 Найти цитируемый пост)
Т.е. после того как юзер ввел имя и пароль или вышел его отправляем к ConfirmationWorker. Но это дело не меняет, на главной странице нужно жмакать обновить.


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

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

Cache-Control: no-cache

Соответственно, предлагаю в методе ControllerServlet.service(), непосредственно перед началом вывода текста HTML добавить:

Код

response.addHeader("Cache-Control", "no-cache");


А в ConfirmationWorker исправить на:

Код

response.addHeader("Pragma", "no-cache");
response.addHeader("Cache-Сontrol", "no-store");
response.addDateHeader("Expires", 0);


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

LoginWorker, как ты его привел в последнем посте, сделан не по заданию. Я ведь говорил, что это невизуальный ресурс: по нему не должно возвращаться никакого ХТМЛа, а должен только идти редирект: или на страницу подтверждения, или обратно на форму логина. Перечитай пожалуйста внимательно мой предыдущий пост.



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
diablero
Дата 31.7.2007, 15:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Цитата(Stampede @  31.7.2007,  00:32 Найти цитируемый пост)
В результате множества экспериментов с разными браузерами получилось так, что искомое поведение реализует такой заголовок:
Cache-Control: no-cache


Сделал как ты предложил, IE адекватно и правильно все обрабатывает, в отличии Opera'ы 8.5. Если открывать оперой, то как и раньше нужно при выходе обновлять главную страницу.

LoginWorker сделал по заданию, как оказалось, так код логичнее и правильнееsmile


--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
Stampede
Дата 31.7.2007, 16:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(diablero @  31.7.2007,  06:58 Найти цитируемый пост)
IE адекватно и правильно все обрабатывает, в отличии Opera'ы 8.5.


А попробуй, в порядке эксперимента, заменить Cache-Control: no-cache на Pragma: no-cache. Есть у меня одно подозрение.

Как только с этим разберемся, добавим еще немного косметики и будем подводить пятую жЫрную черту.

Добавлено через 3 минуты и 23 секунды
Так, минуточку, а ты в Firefox'е тестируешь? Firebug поставил?

Если нет, то надо обязательно. Все будешь видеть как на ладони.


--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
diablero
Дата 31.7.2007, 19:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Цитата(Stampede @  31.7.2007,  16:41 Найти цитируемый пост)
А попробуй, в порядке эксперимента, заменить Cache-Control: no-cache на Pragma: no-cache. Есть у меня одно подозрение.

Нет, так не работает, даже IE.
Цитата(Stampede @  31.7.2007,  16:41 Найти цитируемый пост)
Так, минуточку, а ты в Firefox'е тестируешь?

да
Цитата(Stampede @  31.7.2007,  16:41 Найти цитируемый пост)
Firebug поставил?

нет



--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
Stampede
Дата 31.7.2007, 19:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Цитата(diablero @  31.7.2007,  10:14 Найти цитируемый пост)
Firebug поставил?

нет


Ну так поставь. Делов-то - один гугл-сёрч и один тык мышкой.

Заодно проверишь, как выглядит ответ сервера, и в частности, меня интересует заголовок Date. Он вообще присутствует? Если нет, попробуй выставить его вручную (например, в самом начале метода service()).



--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
Stampede
Дата 31.7.2007, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Гносеолог
**


Профиль
Группа: Участник Клуба
Сообщений: 963
Регистрация: 25.4.2005
Где: Calgary, Alberta, Canada

Репутация: 66
Всего: 144



Вот, кажЫсь нашел:

Цитата

Well, I guess I'll update it a bit, then. Here's how Opera works, as far as I could understand the implementor:

1) Cache directives in META elements are ignored
2) The Cache-Control directives have the following meanings:
2a) if there's no "Cache-Control" header, cache the page to disk and use internal heuristics:
2a1) if it's a query URL (contains a "?"), treat as 'Cache-Control: no-cache', otherwise
2ab) use user settings
2b) no-cache -> revalidate, expires according to user settings
2b1) private, no-cache -> expire immediately
2c) no-store -> cache to RAM only (no effect on revalidation), expires according to user settings or when closing the program
2d) max-age -> expire page after set age
2e) must-revalidate -> treated as if no "Cache-Control" header was sent*
2f) everything else -> treated as if no "Cache-Control" header was sent

Источник: http://lists.drupal.org/archives/developme...4/msg00604.html



Так что попробуй вот это: Cache-Control: private, no-cache

Но убедись, что страница не перезагружается по кнопкам вперед/назад. Если перезагружается, будем искать другие комбинации.

ЗЫ. Терпеть не могу оставлять взведенные грабли за спиной. Никогда не знаешь, когда рванут smile

Update:

Вот еще похоже в чем дело. Досмотрел до конца статью по ссылке: там чувак упоминает заголовок Last-Modified. Ну точно! Я щас глянул на свой сайт из Оперы: он возвращает Cache-Control: no-cache. НО! У меня кроме того выставляется также Last-Modified: <текущее время>!

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

Это сообщение отредактировал(а) Stampede - 31.7.2007, 22:14


--------------------
"If you want something done right, do it yourself"
По секрету: выучить английский - реально!
PM WWW   Вверх
diablero
Дата 1.8.2007, 01:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 337
Регистрация: 3.12.2006
Где: Аркхэм

Репутация: 2
Всего: 5



Не помню уже откуда взял, но кто-то писал что даже такая комбинация из под оперы не работает.
Код

response.addHeader("Date", "\""+ java.util.Calendar.getInstance().getTime().getTime()+"\"");
response.addHeader("Last-Modified", "\""+ java.util.Calendar.getInstance().getTime().getTime()+"\"");
response.setIntHeader("max-age", 0); //IE only;
response.addHeader("Cache-Control","no-store");
response.addHeader("Cache-Control","must-revalidate");
response.addHeader("Pragma", "no-cache"); //HTTP 1.0
response.addHeader ("Expires", "0"); //prevents caching at the proxy server
response.addHeader("cache-Control", "private"); //IE5.x only;

Я перебрал уже кучу вариантов. Пока все дохло.
Цитата(Stampede @  31.7.2007,  21:30 Найти цитируемый пост)
 Я щас глянул на свой сайт из Оперы: он возвращает Cache-Control: no-cache. НО! У меня кроме того выставляется также Last-Modified: <текущее время>!

Может еще что есть?


Днем на свежую голову продолжу...

Это сообщение отредактировал(а) diablero - 1.8.2007, 01:09


--------------------
Есть два варианта решения проблемы - реальный и фантастический. Реальный - это когда прилетят инопланетяне и все за нас сделают ...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java EE (J2EE) и Spring | Следующая тема »


 




[ Время генерации скрипта: 0.1826 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.