mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Bazaar/Protect : Almost completed web authentication package
git-svn-id: svn://ultimatepp.org/upp/trunk@2773 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
278689a015
commit
5a09fb48d5
14 changed files with 693 additions and 168 deletions
|
|
@ -3,13 +3,17 @@ description "Software copy protection module\377";
|
|||
uses
|
||||
Core,
|
||||
ScgiServer,
|
||||
Cypher;
|
||||
Cypher,
|
||||
MySql;
|
||||
|
||||
file
|
||||
ProtectStatus.h,
|
||||
ProtectStatus.cpp,
|
||||
Protect.h,
|
||||
Protect.cpp,
|
||||
ProtectDB.sch,
|
||||
ProtectDB.h,
|
||||
ProtectDB.cpp,
|
||||
ProtectServer.h,
|
||||
ProtectServer.cpp,
|
||||
ProtectClient.h,
|
||||
|
|
|
|||
|
|
@ -4,12 +4,8 @@ NAMESPACE_UPP
|
|||
|
||||
ProtectClient::ProtectClient()
|
||||
{
|
||||
// unconnected at startup
|
||||
connected = false;
|
||||
|
||||
// generates client id
|
||||
dword rnd = Random();
|
||||
clientID = HexString((byte const *)&rnd, sizeof(dword));
|
||||
clientID = -1;
|
||||
|
||||
// defaults to Snow2 Cypher
|
||||
cypher = new Snow2;
|
||||
|
|
@ -38,7 +34,6 @@ VectorMap<String, Value> ProtectClient::SendMap(VectorMap<String, Value> const &
|
|||
// copy vectormap adding client id and a magic number
|
||||
VectorMap<String, Value>dataMap(v, 1);
|
||||
dataMap.Add("APPID", "ProtectClient");
|
||||
dataMap.Add("CLIENTID", clientID);
|
||||
|
||||
// sets cypher key (and create a random IV)
|
||||
cypher->SetKey(key);
|
||||
|
|
@ -54,21 +49,8 @@ VectorMap<String, Value> ProtectClient::SendMap(VectorMap<String, Value> const &
|
|||
// if contents start with "ERROR", just fetch the error desc
|
||||
// and put it in result map
|
||||
VectorMap<String, Value> resMap;
|
||||
if(contents.StartsWith("ERROR="))
|
||||
{
|
||||
int i = contents.Find("\r");
|
||||
String s;
|
||||
if(i >= 0)
|
||||
s = contents.Mid(6, i - 6);
|
||||
else
|
||||
s = contents.Mid(6);
|
||||
int errCode = atoi(~s);
|
||||
resMap.Add("ERROR", errCode);
|
||||
resMap.Add("ERRORMSG", ProtectMessage(errCode));
|
||||
return resMap;
|
||||
}
|
||||
// otherwise, if lastContents don't start with IV field
|
||||
// signals it
|
||||
|
||||
// if contents don't start with IV field signals it
|
||||
if(!contents.StartsWith("IV="))
|
||||
{
|
||||
resMap.Add("ERROR", PROTECT_MISSING_IV);
|
||||
|
|
@ -110,22 +92,27 @@ bool ProtectClient::Connect(void)
|
|||
lastError = 0;
|
||||
|
||||
// if already connected, disconnect first
|
||||
if(!Disconnect())
|
||||
return false;
|
||||
Disconnect();
|
||||
|
||||
// send a connect packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_CONNECT));
|
||||
v.Add("REASON", PROTECT_CONNECT);
|
||||
v.Add("EMAIL", userEMail);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
if(res.Find("ERROR") >= 0)
|
||||
{
|
||||
lastError = res.Get("ERROR");
|
||||
clientID = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
connected = true;
|
||||
int i = res.Find("CLIENTID");
|
||||
if(i < 0)
|
||||
clientID = -1;
|
||||
else
|
||||
clientID = (int)res[i];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -134,22 +121,22 @@ bool ProtectClient::Disconnect(void)
|
|||
{
|
||||
lastError = 0;
|
||||
|
||||
if(!connected)
|
||||
return true;
|
||||
|
||||
// sends a disconnect packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_DISCONNECT));
|
||||
v.Add("REASON", PROTECT_DISCONNECT);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// we're probably disconnected anyways....
|
||||
clientID = -1;
|
||||
|
||||
// check for errors
|
||||
if(res.Find("ERROR") >= 0)
|
||||
{
|
||||
lastError = res.Get("ERROR");
|
||||
return false;
|
||||
}
|
||||
|
||||
connected = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -160,13 +147,15 @@ bool ProtectClient::Refresh(void)
|
|||
|
||||
// sends a refresh packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_REFRESH));
|
||||
v.Add("REASON", PROTECT_REFRESH);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
if(res.Find("ERROR") >= 0)
|
||||
{
|
||||
lastError = res.Get("ERROR");
|
||||
clientID = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -180,7 +169,8 @@ String ProtectClient::GetKey(void)
|
|||
|
||||
// sends a getkey packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_GETKEY));
|
||||
v.Add("REASON", PROTECT_GETKEY);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
|
|
@ -204,7 +194,8 @@ bool ProtectClient::GetLicenseInfo(void)
|
|||
|
||||
// sends a getinfo packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_GETLICENSEINFO));
|
||||
v.Add("REASON", PROTECT_GETLICENSEINFO);
|
||||
v.Add("CLIENTID", (int)clientID);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
|
|
@ -214,13 +205,14 @@ bool ProtectClient::GetLicenseInfo(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
if(res.Find("EMAIL") >= 0) userEMail = res.Get("USEREMAIL");
|
||||
if(res.Find("USERNAME") >= 0) userName = res.Get("USERNAME");
|
||||
if(res.Find("USERADDRESS") >= 0) userAddress = res.Get("USERADDRESS");
|
||||
if(res.Find("USERCOUNTRY") >= 0) userCountry = res.Get("USERCOUNTRY");
|
||||
if(res.Find("USERPHONE") >= 0) userPhone = res.Get("USERPHONE");
|
||||
if(res.Find("USERFAX") >= 0) userFax = res.Get("USERFAX");
|
||||
if(res.Find("USERCELL") >= 0) userCell = res.Get("USERCELL");
|
||||
if(res.Find("EMAIL") >= 0) userEMail = res.Get("EMAIL");
|
||||
if(res.Find("USERNAME") >= 0) userName = res.Get("NAME");
|
||||
if(res.Find("ADDRESS") >= 0) userAddress = res.Get("ADDRESS");
|
||||
if(res.Find("COUNTRY") >= 0) userCountry = res.Get("COUNTRY");
|
||||
if(res.Find("ZIP") >= 0) userZIP = res.Get("ZIP");
|
||||
if(res.Find("PHONE") >= 0) userPhone = res.Get("PHONE");
|
||||
if(res.Find("FAX") >= 0) userFax = res.Get("FAX");
|
||||
if(res.Find("CELL") >= 0) userCell = res.Get("CELL");
|
||||
if(res.Find("EXPIRETIME") >= 0) expireTime = res.Get("EXPIRETIME");
|
||||
if(res.Find("NUMLICENSES") >= 0) numLicenses = res.Get("NUMLICENSES");
|
||||
|
||||
|
|
@ -234,14 +226,15 @@ bool ProtectClient::Register(void)
|
|||
|
||||
// sends a register packet to server
|
||||
VectorMap<String, Value>v;
|
||||
v.Add("REASON", ProtectReasonStr(PROTECT_REGISTER));
|
||||
v.Add("REASON", PROTECT_REGISTER);
|
||||
v.Add("EMAIL", userEMail);
|
||||
v.Add("USERNAME", userName);
|
||||
v.Add("USERADDRESS", userAddress);
|
||||
v.Add("USERCOUNTRY", userCountry);
|
||||
v.Add("USERPHONE", userPhone);
|
||||
v.Add("USERFAX", userFax);
|
||||
v.Add("USERCELL", userCell);
|
||||
v.Add("NAME", userName);
|
||||
v.Add("ADDRESS", userAddress);
|
||||
v.Add("COUNTRY", userCountry);
|
||||
v.Add("ZIP", userZIP);
|
||||
v.Add("PHONE", userPhone);
|
||||
v.Add("FAX", userFax);
|
||||
v.Add("CELL", userCell);
|
||||
VectorMap<String, Value> res = SendMap(v);
|
||||
|
||||
// check for errors
|
||||
|
|
|
|||
|
|
@ -22,14 +22,8 @@ class ProtectClient
|
|||
// in Cypher package
|
||||
One<Cypher>cypher;
|
||||
|
||||
// flag stating a succesfull connection
|
||||
bool connected;
|
||||
|
||||
// client id -- generated as random dword on creation
|
||||
String clientID;
|
||||
|
||||
// license ID -- got from server upon registration
|
||||
String licenseID;
|
||||
// client id -- got from server upon connection
|
||||
dword clientID;
|
||||
|
||||
// user data
|
||||
String userEMail;
|
||||
|
|
@ -78,9 +72,6 @@ class ProtectClient
|
|||
int GetLastError(void) { return lastError; }
|
||||
String GetLastErrorMsg(void) { return ProtectMessage(lastError); }
|
||||
|
||||
// checks whether we're connected to server
|
||||
bool IsConnected(void) { return connected; }
|
||||
|
||||
// create a persistent link to server
|
||||
bool Connect(void);
|
||||
|
||||
|
|
|
|||
149
bazaar/Protect/ProtectDB.cpp
Normal file
149
bazaar/Protect/ProtectDB.cpp
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#include "ProtectDB.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#include <Sql/sch_schema.h>
|
||||
#include <Sql/sch_source.h>
|
||||
|
||||
ProtectDB::ProtectDB()
|
||||
{
|
||||
connected = false;
|
||||
upgraded = false;
|
||||
}
|
||||
|
||||
ProtectDB::~ProtectDB()
|
||||
{
|
||||
if(connected)
|
||||
Disconnect();
|
||||
}
|
||||
|
||||
// connect/disconnect
|
||||
bool ProtectDB::Connect(void)
|
||||
{
|
||||
if(!session.Connect(userName, password, dbName, host))
|
||||
return false;
|
||||
connected = true;
|
||||
SQL = session;
|
||||
|
||||
// upgrade database on first connect
|
||||
if(!upgraded)
|
||||
{
|
||||
SqlSchema sch(MY_SQL);
|
||||
All_Tables(sch);
|
||||
SqlPerformScript(sch.Upgrade());
|
||||
SqlPerformScript(sch.Attributes());
|
||||
SQL.ClearError();
|
||||
upgraded = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProtectDB::Disconnect(void)
|
||||
{
|
||||
if(!connected)
|
||||
return true;
|
||||
session.Close();
|
||||
connected = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
// get data -- email is the key -- non repeatable
|
||||
VectorMap<String, Value> ProtectDB::Get(String const &mail)
|
||||
{
|
||||
VectorMap<String, Value> res = Default();
|
||||
|
||||
SQL * Select(SqlAll()).From(USERS).Where(EMAIL == mail);
|
||||
// we've unique key, so...
|
||||
if(SQL.Fetch())
|
||||
for(int i = 0; i < res.GetCount(); i++)
|
||||
res[i] = SQL[res.GetKey(i)];
|
||||
else
|
||||
res.Clear();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// set/append data
|
||||
bool ProtectDB::Set(VectorMap<String, Value> const &d)
|
||||
{
|
||||
String eMail = d.Get("EMAIL");
|
||||
|
||||
// fill missing fields with default values
|
||||
VectorMap<String, Value>data = Default(d);
|
||||
|
||||
SQL * Select(SqlAll()).From(USERS).Where(EMAIL == eMail);
|
||||
if(SQL.Fetch())
|
||||
{
|
||||
SQL * Update(USERS)
|
||||
(NAME , data.Get("NAME"))
|
||||
(ADDRESS , data.Get("ADDRESS"))
|
||||
(COUNTRY , data.Get("COUNTRY"))
|
||||
(ZIP , data.Get("ZIP"))
|
||||
(PHONE , data.Get("PHONE"))
|
||||
(FAX , data.Get("FAX"))
|
||||
(CELL , data.Get("CELL"))
|
||||
(LICENSES , data.Get("LICENSES"))
|
||||
(EXPIRATION , data.Get("EXPIRATION"))
|
||||
(ACTIVATIONKEY , data.Get("ACTIVATIONKEY"))
|
||||
(ACTIVATIONSENT , data.Get("ACTIVATIONSENT"))
|
||||
(ACTIVATED , data.Get("ACTIVATED"))
|
||||
.Where(EMAIL == eMail);
|
||||
}
|
||||
else
|
||||
{
|
||||
SQL * Insert(USERS)
|
||||
(EMAIL , eMail)
|
||||
(NAME , data.Get("NAME"))
|
||||
(ADDRESS , data.Get("ADDRESS"))
|
||||
(COUNTRY , data.Get("COUNTRY"))
|
||||
(ZIP , data.Get("ZIP"))
|
||||
(PHONE , data.Get("PHONE"))
|
||||
(FAX , data.Get("FAX"))
|
||||
(CELL , data.Get("CELL"))
|
||||
(LICENSES , data.Get("LICENSES"))
|
||||
(EXPIRATION , data.Get("EXPIRATION"))
|
||||
(ACTIVATIONKEY , data.Get("ACTIVATIONKEY"))
|
||||
(ACTIVATIONSENT , data.Get("ACTIVATIONSENT"))
|
||||
(ACTIVATED , data.Get("ACTIVATED"))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
// get default record
|
||||
VectorMap<String, Value> ProtectDB::Default(VectorMap<String, Value> const &base)
|
||||
{
|
||||
VectorMap<String, Value> res(base, 1);
|
||||
res.FindAdd("EMAIL", "");
|
||||
res.FindAdd("NAME", "");
|
||||
res.FindAdd("ADDRESS", "");
|
||||
res.FindAdd("COUNTRY", "");
|
||||
res.FindAdd("ZIP", "");
|
||||
res.FindAdd("PHONE", "");
|
||||
res.FindAdd("FAX", "");
|
||||
res.FindAdd("CELL", "");
|
||||
res.FindAdd("LICENSES", 1);
|
||||
res.FindAdd("EXPIRATION", GetSysTime() + 24*60*60*30);
|
||||
dword r = Random();
|
||||
res.FindAdd("ACTIVATIONKEY", HexString((byte *)&r, sizeof(r)));
|
||||
res.FindAdd("ACTIVATIONSENT", GetSysTime());
|
||||
res.FindAdd("ACTIVATED", false);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
MySqlSession session;
|
||||
// substitute your 'username' and 'password' here:
|
||||
if(!session.Connect("username", "password", "mysql", "localhost")) {
|
||||
printf("Can't connect with MySql\n");
|
||||
return;
|
||||
}
|
||||
Sql sql(session);
|
||||
sql.Execute("use mysql");
|
||||
sql.Execute("show tables");
|
||||
while(sql.Fetch())
|
||||
Cout() << (String)sql[0] << '\n';
|
||||
*/
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
61
bazaar/Protect/ProtectDB.h
Normal file
61
bazaar/Protect/ProtectDB.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef _Protect_ProtectDB_h_
|
||||
#define _Protect_ProtectDB_h_
|
||||
|
||||
#include <MySql/MySql.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define SCHEMADIALECT <MySql/MySqlSchema.h>
|
||||
#define MODEL <Protect/ProtectDB.sch>
|
||||
#include "Sql/sch_header.h"
|
||||
|
||||
// encapsulation of Protect database
|
||||
class ProtectDB
|
||||
{
|
||||
private:
|
||||
|
||||
// host, db name, username and password
|
||||
String host;
|
||||
String dbName;
|
||||
String userName;
|
||||
String password;
|
||||
|
||||
// connected flag
|
||||
bool connected;
|
||||
|
||||
// database upgraded flag
|
||||
bool upgraded;
|
||||
|
||||
// database session
|
||||
MySqlSession session;
|
||||
|
||||
protected:
|
||||
|
||||
public:
|
||||
|
||||
ProtectDB();
|
||||
~ProtectDB();
|
||||
|
||||
// setting of connection data
|
||||
ProtectDB &SetHost(String const &_host) { host = _host; return *this; }
|
||||
ProtectDB &SetDBName(String const &_dbName) { dbName = _dbName; return *this; }
|
||||
ProtectDB &SetUserName(String const &_name) { userName = _name; return *this; }
|
||||
ProtectDB &SetPassword(String const &_pwd) { password = _pwd; return *this; }
|
||||
|
||||
// connect/disconnect
|
||||
bool Connect(void);
|
||||
bool Disconnect(void);
|
||||
bool IsConnected(void) { return connected; }
|
||||
|
||||
// get data -- email is the key -- non repeatable
|
||||
VectorMap<String, Value>Get(String const &mail);
|
||||
|
||||
// set/append data
|
||||
bool Set(VectorMap<String, Value> const &data);
|
||||
|
||||
// get default record
|
||||
VectorMap<String, Value> Default(VectorMap<String, Value> const &base = VectorMap<String, Value>());
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
#endif
|
||||
15
bazaar/Protect/ProtectDB.sch
Normal file
15
bazaar/Protect/ProtectDB.sch
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
TABLE_(USERS)
|
||||
STRING_ (EMAIL, 50) PRIMARY_KEY
|
||||
STRING_ (NAME, 200)
|
||||
STRING_ (ADDRESS, 200)
|
||||
STRING_ (COUNTRY, 50)
|
||||
STRING_ (ZIP, 20)
|
||||
STRING_ (PHONE, 50)
|
||||
STRING_ (FAX, 50)
|
||||
STRING_ (CELL, 50)
|
||||
TIME_ (EXPIRATION)
|
||||
INT_ (LICENSES)
|
||||
STRING_ (ACTIVATIONKEY, 200)
|
||||
DATE_ (ACTIVATIONSENT)
|
||||
BOOL_ (ACTIVATED)
|
||||
END_TABLE
|
||||
|
|
@ -2,6 +2,65 @@
|
|||
|
||||
NAMESPACE_UPP
|
||||
|
||||
// email validation helper
|
||||
bool ValidateEMail(const char *address)
|
||||
{
|
||||
int count = 0;
|
||||
const char *c, *domain;
|
||||
static const char *rfc822_specials = "()<>@,;:\\\"[]";
|
||||
|
||||
// first we validate the name portion (name@domain)
|
||||
for (c = address; *c; c++)
|
||||
{
|
||||
if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == '\"'))
|
||||
{
|
||||
while (*++c)
|
||||
{
|
||||
if (*c == '\"')
|
||||
break;
|
||||
if (*c == '\\' && (*++c == ' '))
|
||||
continue;
|
||||
if (*c < ' ' || *c >= 127)
|
||||
return false;
|
||||
}
|
||||
if (!*c++)
|
||||
return false;
|
||||
if (*c == '@')
|
||||
break;
|
||||
if (*c != '.')
|
||||
return false;
|
||||
continue;
|
||||
}
|
||||
if (*c == '@')
|
||||
break;
|
||||
if (*c <= ' ' || *c >= 127)
|
||||
return false;
|
||||
if (strchr(rfc822_specials, *c))
|
||||
return false;
|
||||
}
|
||||
if (c == address || *(c - 1) == '.')
|
||||
return false;
|
||||
|
||||
// next we validate the domain portion (name@domain)
|
||||
if (!*(domain = ++c))
|
||||
return false;
|
||||
do
|
||||
{
|
||||
if (*c == '.')
|
||||
{
|
||||
if (c == domain || *(c - 1) == '.')
|
||||
return false;
|
||||
count++;
|
||||
}
|
||||
if (*c <= ' ' || *c >= 127)
|
||||
return false;
|
||||
if (strchr(rfc822_specials, *c))
|
||||
return false;
|
||||
}
|
||||
while (*++c);
|
||||
return (count >= 1);
|
||||
}
|
||||
|
||||
// constructor - defaults to port 8787 and connection timeout of 5 minutes (300 sec.)
|
||||
ProtectServer::ProtectServer(int port, int timeout) : ScgiServer(port)
|
||||
{
|
||||
|
|
@ -12,45 +71,73 @@ ProtectServer::ProtectServer(int port, int timeout) : ScgiServer(port)
|
|||
clientTimeout = timeout;
|
||||
}
|
||||
|
||||
void ProtectServer::SendError(int msg)
|
||||
{
|
||||
clientSock.Write("ERROR=" + FormatInt(msg) + "\r\n");
|
||||
}
|
||||
|
||||
// polls clients and remove those which connection has expired
|
||||
void ProtectServer::CheckExpiredClients(void)
|
||||
{
|
||||
int64 curTime = GetSysTime().Get();
|
||||
for(int iClient = clients.GetCount() - 1; iClient >= 0; iClient--)
|
||||
if(clients[iClient].Get() < curTime)
|
||||
clients.Remove(iClient);
|
||||
Time curTime = GetSysTime();
|
||||
for(int iClient = clientLinks.GetCount() - 1; iClient >= 0; iClient--)
|
||||
if(clientLinks[iClient].time < curTime)
|
||||
{
|
||||
String eMail = clientLinks[iClient].eMail;
|
||||
clientLinks.Remove(iClient);
|
||||
registeredConnections.Get(eMail)--;
|
||||
if(registeredConnections.Get(eMail) <= 0)
|
||||
registeredConnections.RemoveKey(eMail);
|
||||
}
|
||||
}
|
||||
|
||||
// checks client list to see if a client is connected
|
||||
bool ProtectServer::IsClientConnected(String const &clientID)
|
||||
// and refresh its expire time on the way
|
||||
bool ProtectServer::IsClientConnected(dword clientID)
|
||||
{
|
||||
int iClient = clients.Find(clientID);
|
||||
int iClient = clientLinks.Find(clientID);
|
||||
if(iClient >= 0)
|
||||
{
|
||||
clients[iClient] = GetSysTime() + clientTimeout;
|
||||
clientLinks[iClient].time = GetSysTime() + clientTimeout;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// connects a client or refresh its expiration time
|
||||
void ProtectServer::ConnectClient(String const &clientID)
|
||||
// connects a client -- returns a new clientID
|
||||
// doesn't check anything, that one must be done elsewhere
|
||||
dword ProtectServer::ConnectClient(String const &eMail)
|
||||
{
|
||||
int i = clients.FindAdd(clientID);
|
||||
clients[i] = GetSysTime() + clientTimeout;
|
||||
// generates an unique random clientID
|
||||
dword id;
|
||||
do
|
||||
{
|
||||
id = Random();
|
||||
}
|
||||
while(clientLinks.Find(id) >= 0);
|
||||
|
||||
// adds to clientLinks and to registered emails count
|
||||
clientLinks.Add(id, TimeMail(GetSysTime() + clientTimeout, eMail));
|
||||
int i = registeredConnections.Find(eMail);
|
||||
if(i >= 0)
|
||||
registeredConnections[i]++;
|
||||
else
|
||||
registeredConnections.Add(eMail, 1);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
// disconnects a client or refresh its expiration time
|
||||
void ProtectServer::DisconnectClient(String const &clientID)
|
||||
void ProtectServer::DisconnectClient(dword clientID)
|
||||
{
|
||||
int i = clients.Find(clientID);
|
||||
int i = clientLinks.Find(clientID);
|
||||
if(i >= 0)
|
||||
clients.Remove(i);
|
||||
{
|
||||
String eMail = clientLinks[i].eMail;
|
||||
clientLinks.Remove(i);
|
||||
i = registeredConnections.Find(eMail);
|
||||
if(i >= 0)
|
||||
{
|
||||
registeredConnections[i]--;
|
||||
if(registeredConnections[i] <= 0)
|
||||
registeredConnections.Remove(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -61,38 +148,35 @@ void ProtectServer::OnAccepted()
|
|||
|
||||
void ProtectServer::OnRequest()
|
||||
{
|
||||
int err = 0;
|
||||
VectorMap<String, Value> data;
|
||||
VectorMap<String, Value> results;
|
||||
|
||||
clientSock.Write("Content-Type: text/plain\r\n\r\n");
|
||||
|
||||
// ignore requests without post data
|
||||
if(!HasPostData())
|
||||
{
|
||||
SendError(PROTECT_BAD_REQUEST);
|
||||
return;
|
||||
}
|
||||
|
||||
err = PROTECT_BAD_REQUEST;
|
||||
// post data should contain at least an IV field and a DATA field
|
||||
if(post.Find("IV") < 0 || post.Find("DATA") < 0)
|
||||
else if(post.Find("IV") < 0 || post.Find("DATA") < 0)
|
||||
err = PROTECT_MISSING_IV;
|
||||
else
|
||||
{
|
||||
SendError(PROTECT_MISSING_IV);
|
||||
return;
|
||||
}
|
||||
|
||||
// gets IV and setup the cypher to decrypt DATA field
|
||||
String IV = ScanHexString(post.GetString("IV"));
|
||||
cypher->SetKey(key, IV);
|
||||
|
||||
// decrypts DATA field and build its vectormap
|
||||
VectorMap<String, Value> data;
|
||||
String decoded;
|
||||
try
|
||||
{
|
||||
decoded = (*cypher)(ScanHexString(post.GetString("DATA")));
|
||||
LoadFromXML(data, decoded);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
SendError(PROTECT_BAD_DATA);
|
||||
return;
|
||||
// gets IV and setup the cypher to decrypt DATA field
|
||||
String IV = ScanHexString(post.GetString("IV"));
|
||||
cypher->SetKey(key, IV);
|
||||
|
||||
// decrypts DATA field and build its vectormap
|
||||
String decoded;
|
||||
try
|
||||
{
|
||||
decoded = (*cypher)(ScanHexString(post.GetString("DATA")));
|
||||
LoadFromXML(data, decoded);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
err = PROTECT_BAD_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
// Get request reason and process it
|
||||
|
|
@ -103,28 +187,19 @@ void ProtectServer::OnRequest()
|
|||
// GETKEY gets application key
|
||||
// REGISTER registers app for timed demo
|
||||
// GETLICENSEINFO gets info about license (name, expiration date, app version....)
|
||||
if(data.Find("REASON") < 0 || data.Find("CLIENTID") < 0)
|
||||
if(!err && data.Find("REASON") < 0)
|
||||
err = PROTECT_MISSING_REASON;
|
||||
if(!err)
|
||||
results = ProcessRequest(data.Get("REASON"), data);
|
||||
|
||||
// if previous error, sets it into result packet
|
||||
if(err)
|
||||
{
|
||||
SendError(PROTECT_BAD_DATA);
|
||||
return;
|
||||
results.Add("ERROR", err);
|
||||
results.Add("ERRORMSG", ProtectMessage(err));
|
||||
}
|
||||
String ClientID = data.Get("CLIENTID");
|
||||
int reason = ProtectReason(data.Get("REASON"));
|
||||
if(reason < PROTECT_CONNECT || reason > PROTECT_GETLICENSEINFO)
|
||||
{
|
||||
SendError(PROTECT_BAD_DATA);
|
||||
return;
|
||||
}
|
||||
if(reason != PROTECT_CONNECT && reason != PROTECT_REGISTER && !IsClientConnected(ClientID))
|
||||
{
|
||||
SendError(PROTECT_NOT_CONNECTED);
|
||||
return;
|
||||
}
|
||||
VectorMap<String, Value> results = ProcessRequest(reason, data);
|
||||
if(reason == PROTECT_CONNECT && results.Find("ERROR") < 0)
|
||||
ConnectClient(ClientID);
|
||||
else if(reason == PROTECT_DISCONNECT)
|
||||
DisconnectClient(ClientID);
|
||||
else if(results.Find("ERROR") >= 0)
|
||||
results.Add("ERRORMSG", ProtectMessage(results.Get("ERROR")));
|
||||
|
||||
// encodes results and send back to client
|
||||
cypher->SetKey(key);
|
||||
|
|
@ -144,19 +219,182 @@ void ProtectServer::OnClosed()
|
|||
VectorMap<String, Value> ProtectServer::ProcessRequest(int reason, VectorMap<String, Value> const &v)
|
||||
{
|
||||
VectorMap<String, Value> res;
|
||||
dword clientID;
|
||||
VectorMap<String, Value> userRec;
|
||||
String eMail;
|
||||
int numConnections;
|
||||
|
||||
switch(reason)
|
||||
{
|
||||
case PROTECT_REGISTER:
|
||||
{
|
||||
// we need an eMail to register
|
||||
if(v.Find("EMAIL") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_EMAIL);
|
||||
return res;
|
||||
}
|
||||
eMail = v.Get("EMAIL");
|
||||
if(!ValidateEMail(~eMail))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_INVALID_EMAIL);
|
||||
return res;
|
||||
}
|
||||
|
||||
// avoid hacking of source packet stripping eventually
|
||||
// added licenseinfo, expiration, etc
|
||||
VectorMap<String, Value>vs(v, 1);
|
||||
vs.RemoveKey("LICENSES");
|
||||
vs.RemoveKey("EXPIRATION");
|
||||
vs.RemoveKey("ACTIVATIONKEY");
|
||||
vs.RemoveKey("ACTIVATIONSENT");
|
||||
vs.RemoveKey("ACTIVATED");
|
||||
|
||||
// try to get user record from database, if any
|
||||
userRec = db.Get(eMail);
|
||||
|
||||
// if not found, new registration
|
||||
if(!userRec.GetCount())
|
||||
{
|
||||
// new registration
|
||||
db.Set(vs);
|
||||
if(SendActivationMail(userRec))
|
||||
res.Add("STATUS", "ACTIVATION RESENT");
|
||||
else
|
||||
res.Add("ERROR", PROTECT_MAIL_SEND_ERROR);
|
||||
}
|
||||
// otherwise, we shall check if activated
|
||||
else if(!userRec.Get("ACTIVATED"))
|
||||
{
|
||||
// already registered but still not activated
|
||||
// resend activation mail
|
||||
if(SendActivationMail(userRec))
|
||||
res.Add("STATUS", "ACTIVATION RESENT");
|
||||
else
|
||||
res.Add("ERROR", PROTECT_MAIL_SEND_ERROR);
|
||||
}
|
||||
// otherwise we shall check if license expired
|
||||
else if(userRec.Get("EXPIRATION") <= GetSysTime())
|
||||
{
|
||||
// signals expiration and leave
|
||||
res.Add("ERROR", PROTECT_MAIL_ALREADY_USED);
|
||||
}
|
||||
// otherwise, just tell user that's already registered
|
||||
else
|
||||
{
|
||||
res.Add("STATUS", "ALREADY REGISTERED");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PROTECT_CONNECT:
|
||||
// we need email to connect
|
||||
if(v.Find("EMAIL") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_EMAIL);
|
||||
return res;
|
||||
}
|
||||
eMail = v.Get("EMAIL");
|
||||
// get the user data from database
|
||||
userRec = db.Get(eMail);
|
||||
|
||||
// if no mail data, product is unregistered
|
||||
if(!userRec.GetCount())
|
||||
{
|
||||
res.Add("ERROR", PROTECT_UNREGISTERED);
|
||||
return res;
|
||||
}
|
||||
|
||||
// product is registered, now we check if activation mail was sent
|
||||
if(!userRec.Get("ACTIVATED"))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_LICENSE_NOT_ACTIVATED);
|
||||
SendActivationMail(userRec);
|
||||
return res;
|
||||
}
|
||||
|
||||
// ok, product registered and activated... is license expired ?
|
||||
if(userRec.Get("EXPIRATION") < GetSysTime())
|
||||
{
|
||||
res.Add("ERROR", PROTECT_LICENSE_EXPIRED);
|
||||
return res;
|
||||
}
|
||||
|
||||
// all ok, we shall finally check if number of licenses has overrun
|
||||
// first, we get number of current connections with same email
|
||||
numConnections = registeredConnections.Find(eMail);
|
||||
if(numConnections < 0)
|
||||
numConnections = 0;
|
||||
else
|
||||
numConnections = registeredConnections[numConnections];
|
||||
if(numConnections >= (int)userRec.Get("LICENSES"))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_LICENSES_NUMBER_EXCEEDED);
|
||||
return res;
|
||||
}
|
||||
|
||||
// all OK, connect client and return connection ID
|
||||
clientID = ConnectClient(eMail);
|
||||
res.Add("CLIENTID", (int)clientID);
|
||||
|
||||
break;
|
||||
|
||||
case PROTECT_DISCONNECT :
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_CLIENTID);
|
||||
return res;
|
||||
}
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
DisconnectClient(clientID);
|
||||
break;
|
||||
|
||||
case PROTECT_GETKEY:
|
||||
res.Add("KEY", "THIS IS A DUMMY KEY");
|
||||
// we need the conneciton ID
|
||||
if(v.Find("CLIENTID") < 0)
|
||||
{
|
||||
res.Add("ERROR", PROTECT_MISSING_CLIENTID);
|
||||
return res;
|
||||
}
|
||||
// we shall be connected
|
||||
clientID = (int)v.Get("CLIENTID");
|
||||
if(!IsClientConnected(clientID))
|
||||
{
|
||||
res.Add("ERROR", PROTECT_NOT_CONNECTED);
|
||||
return res;
|
||||
}
|
||||
// all ok, return the key
|
||||
res.Add("KEY", appKey);
|
||||
break;
|
||||
|
||||
default:
|
||||
res.Add("ERROR", PROTECT_UNKNOWN_REASON);
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
// sends activation mail to user
|
||||
bool ProtectServer::SendActivationMail(VectorMap<String, Value> const &userData)
|
||||
{
|
||||
smtp.To(userData.Get("EMAIL"));
|
||||
smtp.Subject("APPLICATION ACTIVATION");
|
||||
smtp.Text("http://www.timberstruct.it?DATA=" + (String)userData.Get("ACTIVATIONKEY"));
|
||||
return smtp.Send();
|
||||
}
|
||||
|
||||
// runs the server
|
||||
void ProtectServer::Run(void)
|
||||
{
|
||||
// try to connect to db
|
||||
if(!db.Connect())
|
||||
{
|
||||
Cout() << "Error connecting to database\n";
|
||||
return;
|
||||
}
|
||||
|
||||
// runs the SCGI server
|
||||
ScgiServer::Run();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <Cypher/Cypher.h>
|
||||
|
||||
#include "ProtectStatus.h"
|
||||
#include "ProtectDB.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
|
|
@ -13,11 +14,28 @@ class ProtectServer : public ScgiServer
|
|||
{
|
||||
private:
|
||||
|
||||
struct TimeMail : Moveable<TimeMail>
|
||||
{
|
||||
Time time;
|
||||
String eMail;
|
||||
TimeMail(Time const &t, String const &m) : time(t), eMail(m) {};
|
||||
TimeMail() {};
|
||||
};
|
||||
|
||||
// database for user auth
|
||||
ProtectDB db;
|
||||
|
||||
// mailer for activation mails
|
||||
SmtpMail smtp;
|
||||
|
||||
// clients timeout value -- defaults to 5 minutes (300 seconds)
|
||||
int clientTimeout;
|
||||
|
||||
// list of all connected clients with their expiration dates
|
||||
VectorMap<String, Time> clients;
|
||||
// list of all connected clients with their expiration dates and emails
|
||||
VectorMap<dword, TimeMail> clientLinks;
|
||||
|
||||
// number of succesful connections per registered email
|
||||
VectorMap<String, int> registeredConnections;
|
||||
|
||||
// encryption engine
|
||||
One<Cypher> cypher;
|
||||
|
|
@ -34,21 +52,24 @@ class ProtectServer : public ScgiServer
|
|||
|
||||
// checks client list to see if a client is connected
|
||||
// as a side effect, refresh its connection time
|
||||
bool IsClientConnected(String const &clientID);
|
||||
bool IsClientConnected(dword clientID);
|
||||
|
||||
// connects a client or refresh its expiration time
|
||||
void ConnectClient(String const &clientID);
|
||||
// connects a client -- return an ID
|
||||
dword ConnectClient(String const &eMail);
|
||||
|
||||
// disconnects a client or refresh its expiration time
|
||||
void DisconnectClient(String const &clientID);
|
||||
|
||||
// sends error message
|
||||
void SendError(int msg);
|
||||
void DisconnectClient(dword clientID);
|
||||
|
||||
// process client request
|
||||
// takes a VectorMap<String, Value> on input from client
|
||||
// produces a response VectorMap<String, Value> to be returned
|
||||
virtual VectorMap<String, Value> ProcessRequest(int reason, VectorMap<String, Value> const &v);
|
||||
|
||||
// Application key to be returned on auth success
|
||||
String appKey;
|
||||
|
||||
// sends activation mail to user
|
||||
bool SendActivationMail(VectorMap<String, Value> const &userData);
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -61,6 +82,19 @@ public:
|
|||
|
||||
// sets encryption key
|
||||
ProtectServer &SetKey(String const &_key) { key = _key; return *this; }
|
||||
|
||||
// gets database
|
||||
ProtectDB &GetDB(void) { return db; }
|
||||
|
||||
// gets mailer
|
||||
SmtpMail &GetSmtp(void) { return smtp; }
|
||||
|
||||
// sets application key (to be returned on auth success)
|
||||
ProtectServer &SetAppKey(String const &k) { appKey = k; return *this; }
|
||||
String GetAppKey(void) { return appKey; }
|
||||
|
||||
// runs the server
|
||||
void Run(void);
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -9,14 +9,21 @@ const char *__ProtectMessages[] =
|
|||
tt_("HTTP SERVER ERROR"),
|
||||
tt_("BAD REQUEST"),
|
||||
tt_("MISSING INITIALIZATION VECTOR ON DATA"),
|
||||
tt_("MISSING EMAIL ON DATA"),
|
||||
tt_("ILL-FORMED EMAIL ADDRESS"),
|
||||
tt_("MISSING CONNECTION REASON ON DATA"),
|
||||
tt_("UNKNOWN CONNECTION REASON"),
|
||||
tt_("MISSING CLIENT ID ON DATA"),
|
||||
tt_("BAD REQUEST DATA"),
|
||||
tt_("NOT CONNECTED TO SERVER"),
|
||||
tt_("SERVER CONNECTION EXPIRED"),
|
||||
tt_("TESTING LICENSE EXPIRED"),
|
||||
tt_("LICENSE STILL NOT ACTIVATED, RE-SENDING ACTIVATION EMAIL"),
|
||||
tt_("UNREGISTERED APPLICATION"),
|
||||
tt_("LICENSES NUMBER EXCEEDED"),
|
||||
tt_("EMAIL ALREADY USED AND EXPIRED"),
|
||||
tt_("INVALID APPLICATION VERSION, PLEASE UPGRADE")
|
||||
tt_("INVALID APPLICATION VERSION, PLEASE UPGRADE"),
|
||||
tt_("ERROR SENDING ACTIVATION EMAIL")
|
||||
};
|
||||
|
||||
String ProtectMessage(int m)
|
||||
|
|
|
|||
|
|
@ -11,14 +11,21 @@ typedef enum {
|
|||
PROTECT_HTTP_ERROR, // error on HTTP communication with server
|
||||
PROTECT_BAD_REQUEST, // missing POST data on request
|
||||
PROTECT_MISSING_IV, // missing Initialization Vector on POST data
|
||||
PROTECT_MISSING_EMAIL, // missing mandatory EMAIL field in POST DATA
|
||||
PROTECT_INVALID_EMAIL, // ill-formed email address
|
||||
PROTECT_MISSING_REASON, // missing connection's reason
|
||||
PROTECT_UNKNOWN_REASON, // unknown connection's reason
|
||||
PROTECT_MISSING_CLIENTID, // missing client connection ID in POST DATA
|
||||
PROTECT_BAD_DATA, // missing mandatory fields in POST DATA
|
||||
PROTECT_NOT_CONNECTED, // not connected to server -- must connect first
|
||||
PROTECT_CONNECTION_EXPIRED, // server connection timeout -- should refresh more often
|
||||
PROTECT_LICENSE_EXPIRED, // testing license expired
|
||||
PROTECT_LICENSE_NOT_ACTIVATED, // license requested but still not activated by user
|
||||
PROTECT_UNREGISTERED, // product unregistered
|
||||
PROTECT_LICENSES_NUMBER_EXCEEDED, // number of product licenses exceeded (too many apps running)
|
||||
PROTECT_MAIL_ALREADY_USED, // e-mail already used (and expired), can't register
|
||||
PROTECT_INVALID_APP_VERSION // your license isn't valid for this APP version, should upgrade
|
||||
PROTECT_INVALID_APP_VERSION, // your license isn't valid for this APP version, should upgrade
|
||||
PROTECT_MAIL_SEND_ERROR // smtp error sending email
|
||||
} ProtectStatus;
|
||||
|
||||
// gets human-readable error message
|
||||
|
|
@ -26,7 +33,7 @@ extern String ProtectMessage(int m);
|
|||
|
||||
// server request reasons
|
||||
typedef enum {
|
||||
PROTECT_UNKNOWN_REASON, // internal error
|
||||
PROTECT_BAD_REASON, // internal error
|
||||
PROTECT_CONNECT, // establish connection to server
|
||||
PROTECT_DISCONNECT, // frees server connection
|
||||
PROTECT_REFRESH, // refreshes server connection (to restart timeout)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#ifndef _Protect_icpp_init_stub
|
||||
#define _Protect_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#include "ScgiServer/init"
|
||||
#include "Cypher/init"
|
||||
#include "MySql/init"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -34,11 +34,7 @@ ProtectClientDemo::ProtectClientDemo()
|
|||
|
||||
quitButton <<= Breaker();
|
||||
|
||||
// urlEdit <<= "www.timberstruct.it/scgi/testing";
|
||||
urlEdit <<= "localhost/scgi/testing";
|
||||
keyEdit <<= "aabbccddeeff00112233445566778899";
|
||||
emailEdit <<= "demo@timberstruct.it";
|
||||
licenseIDEdit <<= "21309602655597975";
|
||||
emailEdit <<= "test@testme.net";
|
||||
}
|
||||
|
||||
ProtectClientDemo::~ProtectClientDemo()
|
||||
|
|
@ -51,14 +47,19 @@ void ProtectClientDemo::onAction(int reason)
|
|||
responseText <<= "";
|
||||
|
||||
// setup client url and key
|
||||
client.SetURL(urlEdit);
|
||||
client.SetKey(ScanHexString(keyEdit));
|
||||
client.SetURL("localhost/scgi/testing");
|
||||
// client.SetURL("www.timberstruct.it/scgi/testing");
|
||||
client.SetKey(ScanHexString("aabbccddeeff00112233445566778899"));
|
||||
|
||||
// builds data vector map
|
||||
VectorMap<String, Value> userData;
|
||||
|
||||
userData.Add("EMAIL", ~emailEdit);
|
||||
userData.Add("LICENSEID", ~licenseIDEdit);
|
||||
// sets user data
|
||||
client.SetUserName(~nameEdit);
|
||||
client.SetUserAddress(~addressEdit);
|
||||
client.SetUserCountry(~countryEdit);
|
||||
client.SetUserZip(~zipEdit);
|
||||
client.SetUserPhone(~phoneEdit);
|
||||
client.SetUserFax(~faxEdit);
|
||||
client.SetUserCell(cellEdit);
|
||||
client.SetUserEMail(~emailEdit);
|
||||
|
||||
String res;
|
||||
String key;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,28 @@
|
|||
LAYOUT(ProtectClientDemoLayout, 552, 416)
|
||||
ITEM(LineEdit, responseText, SetEditable(false).SetFrame(NullFrame()).LeftPosZ(4, 544).TopPosZ(136, 276))
|
||||
ITEM(EditString, keyEdit, LeftPosZ(116, 432).TopPosZ(32, 19))
|
||||
ITEM(Button, quitButton, SetLabel(t_("Quit")).LeftPosZ(480, 68).TopPosZ(84, 20))
|
||||
ITEM(Label, dv___3, SetLabel(t_("Communication Key:")).LeftPosZ(4, 108).TopPosZ(32, 20))
|
||||
ITEM(EditString, urlEdit, LeftPosZ(116, 432).TopPosZ(8, 19))
|
||||
ITEM(Label, dv___5, SetLabel(t_("Server response :")).LeftPosZ(4, 256).TopPosZ(112, 20))
|
||||
ITEM(Label, dv___6, SetLabel(t_("Server Url :")).LeftPosZ(4, 108).TopPosZ(8, 20))
|
||||
ITEM(EditString, licenseIDEdit, LeftPosZ(344, 204).TopPosZ(56, 19))
|
||||
ITEM(Label, dv___8, SetLabel(t_("LicenseID :")).HSizePosZ(272, 212).TopPosZ(56, 20))
|
||||
ITEM(Label, dv___9, SetLabel(t_("EMail:")).LeftPosZ(4, 40).TopPosZ(56, 20))
|
||||
ITEM(EditString, emailEdit, LeftPosZ(52, 200).TopPosZ(56, 19))
|
||||
ITEM(Button, refreshButton, SetLabel(t_("Refresh")).LeftPosZ(156, 68).TopPosZ(84, 20))
|
||||
ITEM(Button, disconnectButton, SetLabel(t_("Disconnect")).LeftPosZ(232, 68).TopPosZ(84, 20))
|
||||
ITEM(Button, getInfoButton, SetLabel(t_("Get Info")).HSizePosZ(384, 100).TopPosZ(84, 20))
|
||||
ITEM(Button, registerButton, SetLabel(t_("Register")).LeftPosZ(4, 68).TopPosZ(84, 20))
|
||||
ITEM(Button, getKeyButton, SetLabel(t_("Get Key")).HSizePosZ(308, 176).TopPosZ(84, 20))
|
||||
ITEM(Button, connectButton, SetLabel(t_("Connect")).LeftPosZ(80, 68).TopPosZ(84, 20))
|
||||
LAYOUT(ProtectClientDemoLayout, 552, 456)
|
||||
ITEM(Label, dv___0, SetLabel(t_("Name:")).LeftPosZ(4, 48).TopPosZ(4, 20))
|
||||
ITEM(Label, dv___1, SetLabel(t_("Address:")).LeftPosZ(4, 48).TopPosZ(28, 20))
|
||||
ITEM(Label, dv___2, SetLabel(t_("Country:")).LeftPosZ(344, 52).TopPosZ(28, 20))
|
||||
ITEM(Label, dv___3, SetLabel(t_("Zip:")).LeftPosZ(344, 52).TopPosZ(52, 20))
|
||||
ITEM(Label, dv___4, SetLabel(t_("Phone:")).HSizePosZ(4, 500).TopPosZ(76, 20))
|
||||
ITEM(Label, dv___5, SetLabel(t_("Fax:")).LeftPosZ(176, 48).TopPosZ(76, 20))
|
||||
ITEM(Label, dv___6, SetLabel(t_("Cell:")).LeftPosZ(344, 48).TopPosZ(76, 20))
|
||||
ITEM(Label, dv___7, SetLabel(t_("EMail:")).LeftPosZ(4, 40).TopPosZ(100, 20))
|
||||
ITEM(Label, dv___8, SetLabel(t_("Server response :")).LeftPosZ(4, 256).TopPosZ(152, 20))
|
||||
ITEM(EditString, nameEdit, LeftPosZ(56, 492).TopPosZ(4, 19))
|
||||
ITEM(LineEdit, addressEdit, LeftPosZ(56, 280).TopPosZ(28, 44))
|
||||
ITEM(EditString, countryEdit, LeftPosZ(400, 148).TopPosZ(28, 19))
|
||||
ITEM(EditString, zipEdit, LeftPosZ(400, 148).TopPosZ(52, 19))
|
||||
ITEM(EditString, phoneEdit, LeftPosZ(56, 112).TopPosZ(76, 19))
|
||||
ITEM(EditString, faxEdit, LeftPosZ(228, 108).TopPosZ(76, 19))
|
||||
ITEM(EditString, cellEdit, LeftPosZ(400, 148).TopPosZ(76, 19))
|
||||
ITEM(EditString, emailEdit, LeftPosZ(56, 200).TopPosZ(100, 19))
|
||||
ITEM(Button, registerButton, SetLabel(t_("Register")).LeftPosZ(4, 68).TopPosZ(124, 20))
|
||||
ITEM(Button, connectButton, SetLabel(t_("Connect")).LeftPosZ(80, 68).TopPosZ(124, 20))
|
||||
ITEM(Button, refreshButton, SetLabel(t_("Refresh")).LeftPosZ(156, 68).TopPosZ(124, 20))
|
||||
ITEM(Button, disconnectButton, SetLabel(t_("Disconnect")).LeftPosZ(232, 68).TopPosZ(124, 20))
|
||||
ITEM(Button, getKeyButton, SetLabel(t_("Get Key")).HSizePosZ(308, 176).TopPosZ(124, 20))
|
||||
ITEM(Button, getInfoButton, SetLabel(t_("Get Info")).HSizePosZ(384, 100).TopPosZ(124, 20))
|
||||
ITEM(Button, quitButton, SetLabel(t_("Quit")).LeftPosZ(480, 68).TopPosZ(124, 20))
|
||||
ITEM(LineEdit, responseText, SetEditable(false).SetFrame(NullFrame()).LeftPosZ(4, 544).TopPosZ(176, 276))
|
||||
END_LAYOUT
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,21 @@ CONSOLE_APP_MAIN
|
|||
{
|
||||
ProtectServer server;
|
||||
|
||||
// setup database
|
||||
server
|
||||
.SetAppKey(ScanHexString("AABBCCDDEEFF00112233445566778899"))
|
||||
.GetDB()
|
||||
.SetHost("localhost")
|
||||
.SetDBName("protect_demo")
|
||||
.SetUserName("protect_user")
|
||||
.SetPassword("protect")
|
||||
;
|
||||
server
|
||||
.GetSmtp()
|
||||
.Host("localhost")
|
||||
.Port(25)
|
||||
;
|
||||
|
||||
// setup key
|
||||
server.SetKey(ScanHexString("aabbccddeeff00112233445566778899"));
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue