Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> отправка почты через proxy 
:(
    Опции темы
kernell.cpp
Дата 12.10.2004, 11:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



Как отправить почту через прокси, используя smtp и не имея прокси клиента (например, ISA)?

PM MAIL   Вверх
Step
Дата 12.10.2004, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



никак, прокся должна предусматривать тунелирования, а для этого она должна быть настроенна на твой ящик

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

хотя если стоит вингейт то для твоей проги он прозрачен, отпровляй как обычно


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
kernell.cpp
Дата 12.10.2004, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



А если своего клиента написать?
Я имею ввиду, что proxy-сервер установлен на серваке, а на узлах нет клиентской части. У пользователей explorer настроен на проксю и http нормально работает, а вот, smtp - нет.

Это сообщение отредактировал(а) kernell.cpp - 12.10.2004, 11:42
PM MAIL   Вверх
Step
Дата 12.10.2004, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



smtp
и pop3
отличаються от фтп и шттп и шттпс тем что в протоколе не предусмотренна передача адреса для конекта результатом чего являеться не возможность создания прокси-сервера(ну тут надо бы уточнить, но я опущу этот момент) для этих протоколов


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


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


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
Step
Дата 12.10.2004, 12:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



Могу подсказать пути написания тунеля


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
_hunter
Дата 12.10.2004, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

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



это и я с удовольствием послушаю


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Step
Дата 12.10.2004, 12:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



я бы вам код дал, но сегодня он погиб в 9 утра - райд массив дал глюк....

чуть по позже раскажу


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
_hunter
Дата 12.10.2004, 12:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Участник Клуба
Сообщений: 8564
Регистрация: 24.6.2003
Где: Europe::Ukraine:: Kiev

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



ок ( мне не к спеху, но для общего образования -- самое оно )


--------------------
Tempora mutantur, et nos mutamur in illis...
PM ICQ   Вверх
Step
Дата 12.10.2004, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



ищите на следущей недели в факю или в рассылки..
Добавлено @ 12:54
я кстати свой тунель буду переделывать


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
kernell.cpp
Дата 12.10.2004, 13:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



2step:
Будешь писать код - кинь, пожалуйста, на почту. ([email protected])
Да, кстати, может можно попробовать через другой протокол, например - IMAP?


Это сообщение отредактировал(а) kernell.cpp - 12.10.2004, 13:06
PM MAIL   Вверх
Step
Дата 12.10.2004, 13:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



smile.gif я подумаю


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
kernell.cpp
Дата 12.10.2004, 13:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



Есть полезная ссылка, может кому пригодится.
http://www.codeproject.com/internet/nishcsmtpproxymt.asp
М
 
Проверьте ссылку, похоже она не рабочая

PM MAIL   Вверх
kernell.cpp
Дата 13.10.2004, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



Короче, даю код без комментов, просто нет времени расписывать. Прога позволяет слать мыло через прокси и не только, кто разберется - молодец!
Вот - ашник, в кот объявлены классы.

#include <winsock2.h>
#include <process.h>

#define OK_SUCCESS 0
#define ERR_RUNNING 1
#define ERR_WSAFAIL 2
#define ERR_INVALIDSOCKET 3
#define ERR_BIND 4
#define ERR_LISTEN 5
#define ERR_HOST 6
#define ERR_CONNECT 7
#define ERR_STOPPED 8


class CSmtpProxyMT
{
private:
struct SSmtp
{
char SmtpServer[250];
char ClientIP[20];
int SmtpPort;
int LocalPort;
SOCKET LocalSocket;
CSmtpProxyMT* pCSmtpProxyMT;
public:
void CopyStruct(SSmtp *pSSmtp);
};
struct socket_pair
{
SOCKET src;
SOCKET dest;
BOOL IsClient;
CSmtpProxyMT* pCSmtpProxyMT;
};

protected:
BOOL AcceptFlag;
SSmtp m_SSmtp;
SOCKET SmtpServerSocket;
char ProxySignature[2048];

public:
int StopProxy();
int StartProxy(char *server, int port, int localport);
CSmtpProxyMT();
virtual ~CSmtpProxyMT();
BOOL SetSignature(char *sig);

private:
static void AddToEnd(char* buff, char* b, char* sig);
static int InsertTextSignature(char*,char*);
static BOOL FoundBoundary(char *boundary, char *buff);
static BOOL IsEndOfData(char*);
static char * MakeUpper(char * );
static BOOL IsDataCommand(char *);
DWORD SmtpProxyThreadMain();
static DWORD SmtpProxyThread(DWORD arg);
void StartProxyThread(CSmtpProxyMT* m_pCSmtpProxyMT);
static DWORD SmtpClientThread(DWORD arg);
void StartClientThread(SSmtp *pSSmtp);
static DWORD SmtpDataThread(DWORD arg);
static void StartDataThread(socket_pair *pspair);

};

Добавлено @ 14:44
Вот - код:

#include "stdafx.h"
#include "SmtpProxyMT.h"


CSmtpProxyMT::CSmtpProxyMT()
{
AcceptFlag=false;
}

CSmtpProxyMT::~CSmtpProxyMT()
{

}

int CSmtpProxyMT::StartProxy(char *server, int port, int localport)
{
if(AcceptFlag)
return ERR_RUNNING;
strcpy(m_SSmtp.SmtpServer,server);
m_SSmtp.SmtpPort=port;
m_SSmtp.LocalPort=localport;
AcceptFlag=true;
StartProxyThread(this);
return 0;
}

void CSmtpProxyMT::StartProxyThread(CSmtpProxyMT* m_pCSmtpProxyMT)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpProxyThread,
(void*)m_pCSmtpProxyMT,0,(unsigned int*)&threadid);

}

DWORD CSmtpProxyMT::SmtpProxyThread(DWORD arg)
{
CSmtpProxyMT* m_pCSmtpProxyMT=static_cast<CSmtpProxyMT*>((void*)arg);
return m_pCSmtpProxyMT->SmtpProxyThreadMain();
}

DWORD CSmtpProxyMT::SmtpProxyThreadMain()
{
WSADATA wsaData;
sockaddr_in local;
int wsaret=WSAStartup(0x101,&wsaData);
if(wsaret!=0)
{
return ERR_WSAFAIL;
}
local.sin_family=AF_INET;
local.sin_addr.s_addr=INADDR_ANY;
local.sin_port=htons((u_short)this->m_SSmtp.LocalPort);
SmtpServerSocket=socket(AF_INET,SOCK_STREAM,0);
if(SmtpServerSocket==INVALID_SOCKET)
{
return ERR_INVALIDSOCKET;
}
if(bind(SmtpServerSocket,(sockaddr*)&local,sizeof(local))!=0)
{
return ERR_BIND;
}
if(listen(SmtpServerSocket,10)!=0)
{
return ERR_LISTEN;
}

SOCKET SmtpClientSocket;
sockaddr_in from;
int fromlen=sizeof(from);

while(AcceptFlag)
{
char temp[250];
SmtpClientSocket=accept(SmtpServerSocket,
(struct sockaddr*)&from,&fromlen);
if(!AcceptFlag)
break;

sprintf(temp,"%s",inet_ntoa(from.sin_addr));
this->m_SSmtp.LocalSocket=SmtpClientSocket;
this->m_SSmtp.pCSmtpProxyMT=this;

SSmtp *pSSmtp = new SSmtp;
m_SSmtp.CopyStruct(pSSmtp);
StartClientThread(pSSmtp);

}

closesocket(SmtpServerSocket);
WSACleanup();

return 0;
}

void CSmtpProxyMT::SSmtp::CopyStruct(SSmtp *pSSmtp)
{
strcpy(pSSmtp->ClientIP,ClientIP);
pSSmtp->LocalPort=LocalPort;
pSSmtp->LocalSocket=LocalSocket;
pSSmtp->SmtpPort=SmtpPort;
strcpy(pSSmtp->SmtpServer,SmtpServer);
pSSmtp->pCSmtpProxyMT=pCSmtpProxyMT;

}
void CSmtpProxyMT::StartClientThread(SSmtp *pSSmtp)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpClientThread,
(void*)pSSmtp,0,(unsigned int*)&threadid);
}

DWORD CSmtpProxyMT::SmtpClientThread(DWORD arg)
{
SSmtp* pSSmtp=static_cast<SSmtp*>((void*)arg);
SOCKET conn;
struct hostent *hp;
unsigned int addr;
struct sockaddr_in smtp_server;
conn=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(inet_addr((char far*)pSSmtp->SmtpServer)==INADDR_NONE)
{
hp=gethostbyname(pSSmtp->SmtpServer);
}
else
{
addr=inet_addr(pSSmtp->SmtpServer);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_HOST;
}
smtp_server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
smtp_server.sin_family=AF_INET;
smtp_server.sin_port=htons(pSSmtp->SmtpPort);

if(connect(conn,(struct sockaddr*)&smtp_server,sizeof(smtp_server)))
{
closesocket(conn);
closesocket(pSSmtp->LocalSocket);
delete pSSmtp;
return ERR_CONNECT;
}

socket_pair *fromClient=new socket_pair;
socket_pair *fromServer=new socket_pair;

fromClient->src=fromServer->dest=pSSmtp->LocalSocket;
fromClient->dest=fromServer->src=conn;
fromClient->IsClient=true;
fromServer->IsClient=false;
fromServer->pCSmtpProxyMT=fromClient->pCSmtpProxyMT=pSSmtp->pCSmtpProxyMT;
StartDataThread(fromClient);
StartDataThread(fromServer);

delete pSSmtp;
return 0;
}


void CSmtpProxyMT::StartDataThread(socket_pair *pspair)
{
SECURITY_ATTRIBUTES sa;
DWORD threadid=0;
sa.nLength=sizeof(sa);
sa.lpSecurityDescriptor=NULL;

_beginthreadex((void*)&sa,0,
(unsigned(__stdcall*)(void*))CSmtpProxyMT::SmtpDataThread,
(void*)pspair,0,(unsigned int*)&threadid);
}

DWORD CSmtpProxyMT::SmtpDataThread(DWORD arg)
{
socket_pair* pspair=static_cast<socket_pair*>((void*)arg);
char *buff=new char[10240+5120];
int n;
int data_stage=0;
BOOL ExistsBoundary=false;
char *boundary=new char[512];
BOOL alternate=false;
BOOL mixed=false;
while((n=recv(pspair->src,buff,10240,0))>0)
{
if(pspair->IsClient)
{
buff[n]=0;
if(data_stage==3)
{
char *tmpbuff=new char[10240+5120];
strcpy(tmpbuff,buff);
if(strstr(MakeUpper(tmpbuff),"MAIL FROM:")!=NULL)
{
data_stage=0;
ExistsBoundary=false;
alternate=false;
mixed=false;
}
delete tmpbuff;
}
if(data_stage==0)
if(IsDataCommand(buff))
data_stage=1;
if(data_stage==1)
{
if(!alternate)
{
if(strstr(buff,"Content-Type: multipart/alternative")!=NULL)
alternate=true;
}
if(!mixed)
{
if(strstr(buff,"Content-Type: multipart/mixed")!=NULL)
mixed=true;
}
if(!ExistsBoundary)
ExistsBoundary=FoundBoundary(boundary,buff);
if(ExistsBoundary)
{
if(alternate && !mixed)
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
int i1=strlen(buff);
AddToEnd(buff, boundary1,pspair->pCSmtpProxyMT->ProxySignature);
n+=(strlen(buff)-i1);
}
else
{
char boundary1[512+64];
strcpy(boundary1,"\r\n--");
strcat(boundary1,boundary);
strcat(boundary1,"--\r\n");
char *p1;
char *p2;
char *buff2=new char[10240+5120];
char *buff3=new char[10240+5120];
strcpy(buff2,buff);
strcpy(buff3,buff);
if((p1=strstr(buff2,boundary1))!=NULL)
{

char sig[2048+512+512+128];
strcpy(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n");
strcat(sig,"Content-Type: text/plain;\r\n\r\n");
strcat(sig,pspair->pCSmtpProxyMT->ProxySignature);
strcat(sig,"\r\n--");
strcat(sig,boundary);
strcat(sig,"\r\n\r\n");
p2=strstr(buff3,boundary1);
*p1=0;

strcat(buff2,sig);
strcat(buff2,p2);
n+=(strlen(buff2)-strlen(buff));
strcpy(buff,buff2);
}
delete buff2;
delete buff3;
}
}
if(IsEndOfData(buff))
data_stage=2;
}
if(data_stage==2)
{
if(!ExistsBoundary)
{
n+=InsertTextSignature(buff,pspair->pCSmtpProxyMT->ProxySignature);
}
data_stage=3;
}

}
send(pspair->dest,buff,n,0);
}
shutdown(pspair->src,SD_BOTH);
closesocket(pspair->src);
shutdown(pspair->dest,SD_BOTH);
closesocket(pspair->dest);
delete boundary;
delete buff;
delete pspair;
return 0;
}

BOOL CSmtpProxyMT::IsDataCommand(char *str)
{
char *str1=new char[10240+5120];
BOOL rv;
strcpy(str1,str);
if(strcmp(MakeUpper(str1),"DATA\r\n")==0)
rv= true;
else
rv= false;
delete str1;
return rv;
}

char* CSmtpProxyMT::MakeUpper(char* str)
{
char* tmp=str;
while(*tmp)
{
if(islower(*tmp))
*tmp=_toupper(*tmp);
tmp++;
}
return str;
}

BOOL CSmtpProxyMT::IsEndOfData(char *str)
{
if(strstr(str,"\r\n.\r\n")!=NULL)
return true;
else
return false;
}

BOOL CSmtpProxyMT::FoundBoundary(char *boundary, char *buff)
{
char *buff1=new char[10240+5120];
strcpy(buff1,buff);
char *tmp=strstr(buff1,"boundary=\"");
if(tmp==NULL)
{
delete buff1;
return false;
}
tmp+=10;
char *tmp1=strstr(tmp,"\"\r\n");
if(tmp1==NULL)
{
delete buff1;
return false;
}
*tmp1=0;
strcpy(boundary,tmp);
delete buff1;
return true;
}

int CSmtpProxyMT::InsertTextSignature(char *buff, char* sig)
{
char *tmp=strstr(buff,"\r\n.\r\n");
*tmp=0;
strcat(buff,sig);
strcat(buff,"\r\n.\r\n");
return strlen(sig);
}


BOOL CSmtpProxyMT::SetSignature(char *sig)
{
if(strlen(sig)>2047)
return false;
strcpy(ProxySignature,sig);
return true;
}


void CSmtpProxyMT::AddToEnd(char *buff, char *b, char* sig)
{
char *newbuff1=new char[10240+5120];
char *newbuff2=new char[10240+5120];
strcpy(newbuff1,buff);
char *p1;
int skip=1;
for(int i=0;i<=1;i++)
{
p1=newbuff1;
for(int j=0;j<skip;j++)
{
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
p1++;
}
p1=strstr(p1,b);
if(p1==NULL)
{
delete newbuff1;
delete newbuff2;
return;
}
strcpy(newbuff2,p1);
*p1=0;
strcat(newbuff1,sig);
strcat(newbuff1,newbuff2);
skip++;
}

strcpy(buff,newbuff1);

delete newbuff1;
delete newbuff2;
}

int CSmtpProxyMT::StopProxy()
{
if(!AcceptFlag)
return ERR_STOPPED;
AcceptFlag=false;
closesocket(SmtpServerSocket);
return OK_SUCCESS;
}

Добавлено @ 14:50
Что необходимо сделать:
1) Надо вставить библиотеку (#pragma comment (lib, "ws2_32.lib")
2) объявляем переменную
CSmtpProxyMT *m_smtpproxy;
3) создаем объект
m_smtpproxy = new CSmtpProxyMT;
4) можно инкапсулировать сигнатуру в мыло
m_smtpproxy->SetSignature("Hello World");
5) запускаем прокси
m_smtpproxy->StartProxy("192.168.1.44",25,125);
6) останавливаем прокси
m_smtpproxy->StopProxy();

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

Это сообщение отредактировал(а) kernell.cpp - 13.10.2004, 14:54
PM MAIL   Вверх
Step
Дата 13.10.2004, 15:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5151
Регистрация: 26.9.2002
Где: дурдом.UA

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



источник дай....

врядли оно будет работать так как нету параметров конекта на внешний


--------------------
- Дурак учится на своих ошибках, умный на чужих.
 - умные учатся у дураков
PM MAIL ICQ   Вверх
kernell.cpp
Дата 13.10.2004, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 20
Регистрация: 10.8.2004

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



2Step:
В структуре SSmtp посмотри.
Источник я дал и у меня ссылка нормально работает, попробуй по ней последовательно пройти.
Добавлено @ 15:23
Да, прога письма сама не отправляет. После ее запуска можно настроить Bat и отсылать.


Это сообщение отредактировал(а) kernell.cpp - 13.10.2004, 15:17
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




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


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

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