ScClientDM.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401
  1. {
  2. [zhangyin] 2011-08-12
  3. 新的多线路服务器投入使用,因同步数据太麻烦,暂采用简化办法。
  4. 新程序只连接新服务器,老服务器依然运行,供老版本程序使用。
  5. 每天自动或手动将老服务器的新增用户复制到新服务器。
  6. 如果老服务器的新增用户与新服务器已有用户重名,则按如下条件判断:
  7. 1、名称一样,密码不同,判断为不同的用户;
  8. 2、名称密码都一样,判断为同一用户。
  9. 加入矩阵随机替换加密方式
  10. 其形式如下:第一行为明文,第一列为密钥
  11. 先把密码一行一行地写成矩形块,
  12. 如明文密码为:ABCD,写成矩阵为:
  13. A B C D
  14. A A B C D
  15. B B C D A
  16. C C D A B
  17. D D A B C
  18. 密钥为随机数:a[i] := Random(Lenth(ABCD))
  19. 比如生成的密钥为 2231
  20. 然后依据密钥按行读出(密钥指定了每行读值的位置)如上面第一次读取数据: 查找第一行的第2个位置并读出,每行的读取位置就是算法的密钥。
  21. 密钥2231下此密文为BCAD
  22. 其实就是构造一个不可逆的矩阵空间,这个空间上的运算是基本的矩阵变换。
  23. 数据库中密文保存形式为[密钥]:[密文](上面的为2231BCAD),用户每次登陆都会生成不同的密钥,故每次密文不一样
  24. 没有解密过程:(根据原始密码(明文)生成的矩阵不可逆)(每个密码生成一个特定的矩阵: 检查密码是要两方面的数据:
  25. 1. 用户原始密码生成的矩阵
  26. 2. 根据矩阵生成的密文与数据库中保存的密文对比);
  27. 这样在数据库中不直接存放明文(存放密钥跟加密后的密文)。
  28. 注:当用户密码丢失后,由于矩阵不可逆,不能再找回密码,只有根据这个账号重新申请用户账号(确定用户可以用账号
  29. 跟邮箱确定。重新申请密码后返回给用户)
  30. }
  31. unit ScClientDM;
  32. interface
  33. uses
  34. SysUtils, Classes, DB, ADODB, Windows, IniFiles, ScConsts, WinSock, StdCtrls;
  35. type
  36. EClientData = class(Exception);
  37. TClientData = class(TDataModule)
  38. acServer: TADOConnection;
  39. aqQuery: TADOQuery;
  40. aqQuery2: TADOQuery;
  41. acThread: TADOConnection;
  42. aqThread: TADOQuery;
  43. private
  44. { Private declarations }
  45. FUserID: Integer;
  46. FOnlineID: Integer;
  47. function ConnectServer: Boolean;
  48. // 为减轻服务器负担,一定要在完成操作后断开服务器;
  49. procedure CloseConnection;
  50. function GetConnectString: string;
  51. // 返回值:-2:用户取消登录;-1:无法连接服务器;0:成功;1:密码错误;2:用户名错误;
  52. // 3:授权码错误(首次登录);4:授权已过期;5:用户被禁用
  53. // 6:用户登录次数超限;7:服务器在线人数超限; 8:尚未获得授权
  54. // 9:申请被拒绝
  55. function InnerLogin: Integer;
  56. function ConnectServerThread: Boolean;
  57. // 修改用户信息并重新申请账号
  58. function ReRequest(AUserID: Integer): Boolean;
  59. public
  60. { Public declarations }
  61. function Login: Boolean;
  62. // 为减轻服务器负担,一定要在完成操作后断开服务器;
  63. procedure CloseConnectionThread;
  64. function CheckServer: Boolean;
  65. // 前提是用户已登录,所以不用再检查,直接改
  66. function ChangePWD: Boolean;
  67. // 未登陆时修改密码
  68. function ChangePWDBeforeLogin: Boolean;
  69. // 检查用户名是否存在
  70. function UserExists(AUserName: string): Boolean;
  71. // 输入用户资料
  72. function InputUserInfo(AUserID: Integer = -1): Boolean;
  73. // 登出
  74. function Logout: Boolean;
  75. // 加密方法
  76. function EncryptionBySecret(ASecretCode: string): string;
  77. // 通过密钥加密
  78. function EncryptionByKey(KeyArr: array of Integer; APWD: String): string;
  79. function DecryptByKey(ASource: string; APWD: string): String;
  80. // 16位随机字符
  81. function Get16Char(ALength: Integer): string;
  82. function AddSpaceToString(aSource: string): string;
  83. end;
  84. // 个人认为原始代码写得太啰嗦,对该类重新进行简化和封装 chenshilong, 2011-05-13 11:13:28
  85. TScUserConfigInfo = class(TObject)
  86. private
  87. FIniFile: TIniFile;
  88. FUserName: string;
  89. FPassWord: string;
  90. FNewPassWord: string;
  91. FNewPassWord1: string;
  92. FNewPassWord2: string;
  93. FFirstLogon: Boolean;
  94. FRememberUser: Boolean;
  95. FVersion: Integer;
  96. public
  97. constructor Create; virtual;
  98. destructor Destroy; override;
  99. property UserName: string read FUserName write FUserName;
  100. property PassWord: string read FPassWord write FPassWord;
  101. property NewPassWord: string read FNewPassWord write FNewPassWord;
  102. property NewPassWord1: string read FNewPassWord1 write FNewPassWord1;
  103. property NewPassWord2: string read FNewPassWord2 write FNewPassWord2;
  104. property FirstLogon: Boolean read FFirstLogon write FFirstLogon;
  105. property RememberUser: Boolean read FRememberUser write FRememberUser;
  106. property Version: Integer read FVersion write FVersion;
  107. procedure LoadFromFile;
  108. procedure SaveToFile;
  109. // 是否记忆用户名和密码
  110. procedure RememberUserInfo(ARemember: Boolean);
  111. function LockStr(AStr: String): WideString;
  112. function AHostToIP(AName: string; var Aip: string): Boolean;
  113. end;
  114. function ClientData: TClientData;
  115. var UserConfigInfo: TScUserConfigInfo;
  116. implementation
  117. uses
  118. Forms, Controls, S4CryptUtils, ScLoginFrm, DateUtils, ScUtils, ScProgressFrm,
  119. ScUserInfoFrm, ShellAPI, ScLicenseCodeFrm, Math, ScModifyPwdFrm;
  120. {$R *.dfm}
  121. const
  122. // server.smartcost
  123. arrPWD: array [0..19] of Byte = ($00, $00, $00, $10, $8C, $8B, $9C, $90, $8D, $8B, $92,
  124. $9E, $D1, $8C, $9A, $8D, $8D, $89, $8C, $9A);
  125. SctUser = 'User';
  126. SctVersion = 'Version';
  127. var
  128. g_ClientData: TClientData = nil;
  129. function ClientData: TClientData;
  130. begin
  131. if g_ClientData = nil then
  132. g_ClientData := TClientData.Create(nil);
  133. Result := g_ClientData;
  134. end;
  135. { TClientData }
  136. function TClientData.ChangePWD: Boolean;
  137. var
  138. strPWD: string;
  139. I: Integer;
  140. ReturnCopy: string;
  141. endWord: Char;
  142. begin
  143. Result := False;
  144. if SetupPassWord(strPWD) then
  145. begin
  146. for I := 1 to Length(strPWD) do
  147. begin
  148. ReturnCopy := Copy(strPWD, I, 1);
  149. endWord := ReturnCopy[1];
  150. if Ord(endWord) >= 128 then
  151. begin
  152. MessageWarning(0, '请不要在密码中输入汉字。');
  153. Result := False;
  154. Exit;
  155. end;
  156. end;
  157. ShowFloatProgress('正在与服务器通信,请稍候……', 100);
  158. Screen.Cursor := crHourGlass;
  159. try
  160. if ConnectServer then
  161. begin
  162. try
  163. aqQuery.SQL.Clear;
  164. aqQuery.SQL.Add(Format('Update ScUsers Set Pwd = ''%s'' Where ID = %d', [strPWD, FUserID]));
  165. aqQuery.SQL.Add(Format('Update ScUsers Set EPwd = '''' Where ID = %d', [FUserID]));
  166. aqQuery.SQL.Add(Format('Update ScUsers Set NEPwd = '''' Where ID = %d', [FUserID]));
  167. aqQuery.SQL.Add(Format('Update ScUsers Set NPwd = '''' Where ID = %d', [FUserID]));
  168. // 如果修改行数小于0,则说明服务器上没有本用户登录数据,检测失败
  169. Result := aqQuery.ExecSQL > 0;
  170. aqQuery.Close;
  171. finally
  172. CloseConnection;
  173. end;
  174. end;
  175. finally
  176. Screen.Cursor := crDefault;
  177. CloseFloatProgress;
  178. end;
  179. end;
  180. end;
  181. // 连接服务器进行状态检查
  182. // 是否检查用户名、密码????
  183. function TClientData.ChangePWDBeforeLogin: Boolean;
  184. var
  185. strName, strPWD, strNewPWD1, strNewPWD2, QueryStr: string;
  186. IsUserExist: Boolean;
  187. Len, AUserID, i: Integer;
  188. ArrKey: array of Integer;
  189. begin
  190. if ShowModifyPwdForm(strName, strPWD, strNewPWD1, strNewPWD2) then
  191. begin
  192. if strNewPWD1 <> strNewPWD2 then
  193. begin
  194. Result := False;
  195. MessageWarning(0, '两次输入新密码不一致!请重新输入。');
  196. Exit;
  197. end;
  198. try
  199. CreateProgressForm(100, '连接服务器,请稍候>>>');
  200. if ConnectServer then
  201. begin
  202. AddProgressForm(30, '服务器已连接,正在修改密码...');
  203. try
  204. aqQuery.SQL.Clear;
  205. aqQuery.SQL.Add(Format('Select *, GetDate() As Now From ScUsers Where Name=''%s''', [strName]));
  206. aqQuery.Open;
  207. // 检查用户名是否正确
  208. if aqQuery.RecordCount = 0 then
  209. begin
  210. Result := False;
  211. MessageWarning(0, '服务器上无此用户,请确认用户名是否输入正确。');
  212. Exit;
  213. end;
  214. AddProgressForm(30, '服务器已连接,正在检查用户...');
  215. // 可能有重名用户(原因见本单元顶部)
  216. IsUserExist := False;
  217. if aqQuery.RecordCount > 1 then
  218. begin
  219. aqQuery.First;
  220. while not aqQuery.Eof do
  221. begin
  222. // 判断密码
  223. QueryStr := aqQuery.FieldByName('EPWD').AsString;
  224. // 二代密码中无三代中的密钥跟密文区别符空格.所以要先加上
  225. if (Pos(' ', QueryStr) = 0) and (QueryStr <> '') then
  226. begin
  227. QueryStr := AddSpaceToString(QueryStr);
  228. end;
  229. // 这里是最老的版本第一次使用新版本时,为登陆直接修改密码的情况
  230. if (CompareStr(strPWD, aqQuery.FieldByName('Pwd').AsString) = 0) and (aqQuery.FieldByName('Pwd').AsString <> '') then
  231. begin
  232. // 当名称与密码相同时,判断为同一用户
  233. IsUserExist := True;
  234. AUserID := aqQuery.FieldByName('ID').AsInteger;
  235. Break;
  236. end
  237. // 二代密码第一次登陆新版本修改密码的情况
  238. else if (DecryptByKey(QueryStr, strPWD) = QueryStr) and (aqQuery.FieldByName('EPWD').AsString <> '')then
  239. begin
  240. // 当名称与密码相同时,判断为同一用户
  241. IsUserExist := True;
  242. AUserID := aqQuery.FieldByName('ID').AsInteger;
  243. Break;
  244. end;
  245. aqQuery.Next;
  246. end;
  247. end
  248. else if aqQuery.RecordCount = 1 then
  249. begin
  250. // 判断密码
  251. QueryStr := aqQuery.FieldByName('EPWD').AsString;
  252. // 二代密码中无三代中的密钥跟密文区别符空格.所以要先加上
  253. if (Pos(' ', QueryStr) = 0) and (QueryStr <> '') then
  254. begin
  255. QueryStr := AddSpaceToString(QueryStr);
  256. end;
  257. // 这里是最老的版本第一次使用新版本时,为登陆直接修改密码的情况
  258. if (CompareStr(strPWD, aqQuery.FieldByName('Pwd').AsString) = 0) and (aqQuery.FieldByName('Pwd').AsString <> '') then
  259. begin
  260. // 当名称与密码相同时,判断为同一用户
  261. IsUserExist := True;
  262. AUserID := aqQuery.FieldByName('ID').AsInteger;
  263. end
  264. // 二代密码第一次登陆新版本修改密码的情况
  265. else if (DecryptByKey(QueryStr, strPWD) = QueryStr) and (aqQuery.FieldByName('EPWD').AsString <> '')then
  266. begin
  267. // 当名称与密码相同时,判断为同一用户
  268. IsUserExist := True;
  269. AUserID := aqQuery.FieldByName('ID').AsInteger;
  270. end;
  271. end;
  272. AddProgressForm(30, '服务器已连接,正在检查原密码...');
  273. if not IsUserExist then
  274. begin
  275. Result := False;
  276. MessageWarning(0, '原密码错误,请确认。');
  277. Exit;
  278. end
  279. else
  280. begin
  281. // 所有的修改密码过后都将其当做最老版本来处理,即Pwd有数据
  282. // 其余三个字段无数据
  283. AddProgressForm(10, '服务器已连接,正在修改成新密码...');
  284. aqQuery.SQL.Clear;
  285. aqQuery.SQL.Add(Format('Update ScUsers Set Pwd = ''%s'' Where ID = %d', [strNewPWD1, AUserID]));
  286. aqQuery.SQL.Add(Format('Update ScUsers Set EPwd = '''' Where ID = %d', [AUserID]));
  287. aqQuery.SQL.Add(Format('Update ScUsers Set NEPwd = '''' Where ID = %d', [AUserID]));
  288. aqQuery.SQL.Add(Format('Update ScUsers Set NPwd = '''' Where ID = %d', [AUserID]));
  289. aqQuery.ExecSQL;
  290. end;
  291. UserConfigInfo.FUserName := strName;
  292. UserConfigInfo.FPassWord := strNewPWD1;
  293. finally
  294. CloseConnection;
  295. end;
  296. end
  297. else
  298. begin
  299. Result := False;
  300. MessageWarning(0, '无法连接服务器,请检查网络设置。');
  301. end;
  302. finally
  303. CloseFloatProgress;
  304. end;
  305. end;
  306. end;
  307. function TClientData.CheckServer: Boolean;
  308. begin
  309. Result := False;
  310. if ConnectServerThread then
  311. begin
  312. try
  313. aqThread.SQL.Clear;
  314. aqThread.SQL.Add(Format('Update ScOnlineUsers Set UpdateTime = GetDate() Where ID = %d', [FOnlineID]));
  315. // 如果修改行数小于0,则说明服务器上没有本用户登录数据,检测失败
  316. Result := aqThread.ExecSQL > 0;
  317. aqThread.Close;
  318. finally
  319. CloseConnectionThread;
  320. end;
  321. end;
  322. end;
  323. procedure TClientData.CloseConnection;
  324. begin
  325. if acServer.Connected = True then
  326. acServer.Close;
  327. end;
  328. procedure TClientData.CloseConnectionThread;
  329. begin
  330. if acThread.Connected = True then
  331. acThread.Close;
  332. end;
  333. function TClientData.ConnectServer: Boolean;
  334. begin
  335. if acServer.Connected then
  336. begin
  337. Result := True;
  338. Exit;
  339. end;
  340. acServer.ConnectionString := GetConnectString;
  341. try
  342. acServer.Open;
  343. except
  344. end;
  345. // 联机失败,则重试一次
  346. if not acServer.Connected then
  347. begin
  348. try
  349. acServer.Open;
  350. except
  351. end;
  352. end;
  353. Result := acServer.Connected;
  354. end;
  355. function TClientData.ConnectServerThread: Boolean;
  356. begin
  357. acThread.ConnectionString := GetConnectString;
  358. try
  359. acThread.Open;
  360. except
  361. end;
  362. // 联机失败,则重试一次
  363. if not acThread.Connected then
  364. begin
  365. try
  366. acThread.Open;
  367. except
  368. end;
  369. end;
  370. Result := acThread.Connected;
  371. end;
  372. function TClientData.EncryptionByKey(KeyArr: array of Integer;
  373. APWD: string): string;
  374. var
  375. CiphertextArr: array of string;
  376. StrArr: array of string;
  377. Ciphertext: string;
  378. LenStr, i, j: Integer;
  379. begin
  380. Ciphertext := '';
  381. LenStr := Length(APWD);
  382. SetLength(CiphertextArr, LenStr);
  383. SetLength(StrArr, LenStr);
  384. // 解析明文:StrArr
  385. for i := 0 to LenStr - 1 do
  386. begin
  387. StrArr[i] := Copy(APWD, i + 1, 1);
  388. end;
  389. // 构造密文表:CiphertextArr
  390. for i := 0 to LenStr - 1 do
  391. begin
  392. for j := 0 to LenStr - 1 do
  393. begin
  394. if j + i >= LenStr then
  395. begin
  396. CiphertextArr[i] := CiphertextArr[i] + StrArr[i + j - LenStr];
  397. end
  398. else
  399. CiphertextArr[i] := CiphertextArr[i] + StrArr[i + j];
  400. end;
  401. end;
  402. // 加密
  403. // 初始化密文头: 密钥
  404. for i := 0 to LenStr - 1 do
  405. begin
  406. Ciphertext := Ciphertext + IntToStr(KeyArr[i]) + ' ';
  407. end;
  408. // 加上密文尾: 根据密钥查找密文表得出.
  409. for i := 0 to LenStr - 1 do
  410. begin
  411. Ciphertext := Ciphertext + Copy(CiphertextArr[i], KeyArr[i], 1);
  412. end;
  413. Result := Ciphertext;
  414. end;
  415. function TClientData.EncryptionBySecret(ASecretCode: string): string;
  416. var
  417. KeyArr: array of Integer;
  418. LenStr, i, j: Integer;
  419. begin
  420. LenStr := Length(ASecretCode);
  421. SetLength(KeyArr, LenStr);
  422. // 随机构造密钥:KeyArr
  423. for i := 0 to LenStr - 1 do
  424. begin
  425. Randomize;
  426. KeyArr[i] := Random(LenStr);
  427. if KeyArr[i] = 0 then
  428. begin
  429. KeyArr[i] := 1;
  430. end;
  431. end;
  432. // 加密
  433. Result := EncryptionByKey(KeyArr, ASecretCode);
  434. end;
  435. function TClientData.Get16Char(ALength: Integer): string;
  436. const
  437. CodeBuf: array[0..35] of Char = ('0', '1', '2', '3', '4', '5',
  438. '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
  439. 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
  440. 'W', 'X', 'Y', 'Z');
  441. var
  442. Temp: string;
  443. Num: Integer;
  444. begin
  445. Temp := '';
  446. while Length(Temp) < ALength do
  447. begin
  448. Randomize;
  449. Num := Random(36);
  450. Temp := Temp + CodeBuf[Num];
  451. end;
  452. Result := Temp;
  453. end;
  454. function TClientData.GetConnectString: string;
  455. var
  456. strPWD: string;
  457. arrResult: array of Byte;
  458. iOutputLength: Integer;
  459. slstServer: TStringList;
  460. I: Integer;
  461. strIP: string;
  462. begin
  463. iOutputLength := GetOutputLength(arrPWD);
  464. SetLength(arrResult, iOutputLength);
  465. Decrypt_Simple(arrPWD, Length(arrPWD), arrResult, iOutputLength);
  466. SetString(strPWD, PChar(@arrResult[0]), iOutputLength);
  467. slstServer := TStringList.Create;
  468. slstServer.LoadFromFile(ExtractFilePath(Application.ExeName) + 'Data\ServerList');
  469. for I := 0 to slstServer.Count - 1 do
  470. begin
  471. if UserConfigInfo.AHostToIP(slstServer[I], strIP) then
  472. slstServer[I] := strIP;
  473. end;
  474. Result := 'Provider=SQLOLEDB.1;Persist Security Info=True;'
  475. + 'Data Source=' + slstServer[0] +';User ID=sa;Password=' + strPWD + ';Network Library=dbmssocn';
  476. // + 'Data Source=192.168.1.3;User ID=sa;Password=' + strPWD;
  477. slstServer.Free;
  478. end;
  479. function TClientData.InnerLogin: Integer;
  480. var
  481. strName, strPWD, strVer, strLicenseCode, tmpPWD, Key, Char16, ReturnCopy, QueryStr: string;
  482. ArrKey: array of Integer;
  483. dtNow, dtLicense: TDateTime;
  484. bNew, bFirstLogon, NoSpaceFlag, bLogin, bNoUser, IsAllChinese: Boolean;
  485. gGUID: TGUID;
  486. iLoginLimit, iOnlineLimit, iOnlineUsers, iServerID, Len, i, ChineseCount: Integer;
  487. endWord: Char;
  488. begin
  489. Result := -2;
  490. bLogin := False;
  491. // 登录
  492. if ShowLoginForm(strName, strPWD) then
  493. begin
  494. CreateProgressForm(100, '连接服务器,请稍候>>>');
  495. AddProgressForm(10, '正在连接服务器,该过程可能需要较长时间...');
  496. RefreshProgressTime(1000); // 3分钟
  497. try
  498. if ConnectServer then
  499. begin
  500. try
  501. AddProgressForm(20, '服务器已连接,正在检查在线情况...');
  502. // 先查询ScOnlineLimit和ScOnlineUsers表,判断登录人数是否超过限制
  503. aqQuery.Close;
  504. aqQuery.SQL.Clear;
  505. aqQuery.SQL.Add('Select * From ScOnlineLimit');
  506. aqQuery.Open;
  507. aqQuery.First;
  508. iOnlineLimit := aqQuery.FieldByName('OnlineLimit').AsInteger;
  509. aqQuery.Close;
  510. aqQuery.SQL.Clear;
  511. aqQuery.SQL.Add('Select Count(*) As OnlineCount From ScOnlineUsers');
  512. aqQuery.Open;
  513. aqQuery.First;
  514. iOnlineUsers := aqQuery.FieldByName('OnlineCount').AsInteger;
  515. aqQuery.Close;
  516. if iOnlineUsers > iOnlineLimit then
  517. begin
  518. Result := 7;
  519. Exit;
  520. end;
  521. AddProgressForm(10, '服务器已连接,正在验证用户名和密码...');
  522. aqQuery.Close;
  523. aqQuery.SQL.Clear;
  524. aqQuery.SQL.Add(Format('Select *, GetDate() As Now From ScUsers Where Name=''%s''', [strName]));
  525. aqQuery.Open;
  526. // 检查用户名是否正确
  527. if aqQuery.RecordCount = 0 then
  528. begin
  529. Result := 2;
  530. Exit;
  531. end;
  532. // [zhangyin] 2011-08-12
  533. // 可能有重名用户(原因见本单元顶部)
  534. if aqQuery.RecordCount > 1 then
  535. begin
  536. bNoUser := True;
  537. aqQuery.First;
  538. while not aqQuery.Eof do
  539. begin
  540. // 判断密码
  541. QueryStr := aqQuery.FieldByName('EPWD').AsString;
  542. // 二代密码中无三代中的密钥跟密文区别符空格.所以要先加上
  543. if (Pos(' ', QueryStr) = 0) and (QueryStr <> '')then
  544. begin
  545. QueryStr := AddSpaceToString(QueryStr);
  546. end;
  547. // 这里是最老的版本第一次使用新版本时的情况
  548. if (CompareStr(strPWD, aqQuery.FieldByName('Pwd').AsString) = 0) and (aqQuery.FieldByName('Pwd').AsString <> '') then
  549. begin
  550. bNoUser := False;
  551. Break;
  552. end
  553. // 二代密码第一次登陆新版本的情况
  554. else if (DecryptByKey(QueryStr, strPWD) = QueryStr) and (aqQuery.FieldByName('EPWD').AsString <> '')then
  555. begin
  556. bNoUser := False;
  557. Break;
  558. end;
  559. aqQuery.Next;
  560. end;
  561. // 返回密码错误
  562. if bNoUser then
  563. begin
  564. Result := 1;
  565. Exit;
  566. end;
  567. end;
  568. AddProgressForm(10, '服务器已连接,正在检查登录权限...');
  569. // 检查该用户是否重复登陆
  570. FUserID := aqQuery.FieldByName('ID').AsInteger;
  571. iLoginLimit := aqQuery.FieldByName('LoginLimit').AsInteger;
  572. // 登录限制>0,则表示限制该ID登录次数
  573. if iLoginLimit > 0 then
  574. begin
  575. aqQuery2.Close;
  576. aqQuery2.SQL.Clear;
  577. aqQuery2.SQL.Add(Format('Select * From ScOnlineUsers Where UserID = %d', [FUserID]));
  578. aqQuery2.Open;
  579. // 发现重复在线信息
  580. if aqQuery2.RecordCount > 0 then
  581. begin
  582. // 检查本机重复在线情况
  583. aqQuery2.First;
  584. while not aqQuery2.Eof do
  585. begin
  586. gGUID := StringToGUID(aqQuery2.FieldByName('LocalGUID').AsString);
  587. // 本机存在重复,因Exe本身会检查重复运行情况,所以不再进行判断
  588. if IsLocalGUID(gGuid) then
  589. begin
  590. bLogin := True;
  591. FOnlineID := aqQuery2.FieldByName('ID').AsInteger;
  592. Break;
  593. end;
  594. aqQuery2.Next;
  595. end;
  596. // 登录次数超限
  597. if (not bLogin) and (iLoginLimit <= aqQuery2.RecordCount) then
  598. begin
  599. Result := 6;
  600. aqQuery2.Close;
  601. Exit;
  602. end;
  603. end;
  604. aqQuery2.Close;
  605. end
  606. // 登录限制0,则表示不限制该ID登录次数
  607. else
  608. begin
  609. gGUID := GetLocalGUID;
  610. aqQuery2.Close;
  611. aqQuery2.SQL.Clear;
  612. aqQuery2.SQL.Add(Format('Select * From ScOnlineUsers Where LocalGUID = ''%s''', [GUIDToString(gGUID)]));
  613. aqQuery2.Open;
  614. // 发现重复在线信息
  615. if aqQuery2.RecordCount > 0 then
  616. begin
  617. bLogin := True;
  618. FOnlineID := aqQuery2.FieldByName('ID').AsInteger;
  619. end;
  620. aqQuery2.Close;
  621. end;
  622. // 检查用户是否被禁用
  623. if not aqQuery.FieldByName('Enabled').AsBoolean then
  624. begin
  625. Result := 5;
  626. Exit;
  627. end;
  628. // 检查用户申请是否被拒绝
  629. if aqQuery.FieldByName('Denied').AsBoolean then
  630. begin
  631. Result := 9;
  632. Exit;
  633. end;
  634. // 检查密码
  635. AddProgressForm(10, '服务器已连接,正在检查密码...');
  636. if aqQuery.FieldByName('EPwd').AsString <> '' then
  637. begin
  638. // 判断密码
  639. QueryStr := aqQuery.FieldByName('EPwd').AsString;
  640. // 二代密码中无三代中的密钥跟密文区别符空格.所以要先加上
  641. if Pos(' ', QueryStr) = 0 then
  642. begin
  643. QueryStr := AddSpaceToString(QueryStr);
  644. NoSpaceFlag := True;
  645. end;
  646. if DecryptByKey(QueryStr, strPWD) <> QueryStr then
  647. begin
  648. Result := 1;
  649. Exit;
  650. end;
  651. // 重新加密
  652. // 修改过后的密文存入NEPwd
  653. // 每次登陆,随机修改密码
  654. // 修改过后的密文在次出入数据库
  655. // 判断是否全是汉字
  656. IsAllChinese := True;
  657. ChineseCount := 0;
  658. for i := 1 to Length(strPWD) do
  659. begin
  660. ReturnCopy := Copy(strPWD, i, 1);
  661. endWord := ReturnCopy[1];
  662. if Ord(endWord) < 128 then
  663. begin
  664. IsAllChinese := False;
  665. end
  666. else
  667. ChineseCount := ChineseCount + 1;
  668. end;
  669. // 对汉字个数占密码长度大于1/3,这样会出现很长时间的循环,现有的办法无法处理,这种情况
  670. // 返回总部重置密码,这种情况只在这次之前注册的用户会出现,这次之后注册的用户中
  671. // 密码没有汉字 2012.3.29
  672. if (ChineseCount > (Length(strPWD) div 3)) and (not IsAllChinese)then
  673. begin
  674. Result := 10;
  675. Exit;
  676. end;
  677. tmpPWD := EncryptionBySecret(strPWD);
  678. ReturnCopy := Copy(tmpPWD, Length(tmpPWD), 1);
  679. endWord := ReturnCopy[1];
  680. // 在不是全是汉字的情况下,处理中文拆字符出现',导致下面SQL语句出错(排除全是汉字的情况)
  681. if not IsAllChinese then
  682. begin
  683. while (Ord(endWord) >= 128) do
  684. begin
  685. tmpPWD := EncryptionBySecret(strPWD);
  686. ReturnCopy := Copy(tmpPWD, Length(tmpPWD), 1);
  687. endWord := ReturnCopy[1];
  688. end;
  689. end;
  690. aqQuery.Close;
  691. aqQuery.SQL.Clear;
  692. aqQuery.SQL.Add(Format('Update ScUsers Set EPwd = ''%s'' where ID = %d',[tmpPWD, FUserID]));
  693. aqQuery.ExecSQL;
  694. // 处理处理Pwd
  695. aqQuery.Close;
  696. aqQuery.SQL.Clear;
  697. aqQuery.SQL.Add(Format('Select * from ScUsers where ID = %d',[FUserID]));
  698. aqQuery.Open;
  699. if aqQuery.FieldByName('Pwd').AsString <> '' then
  700. begin
  701. aqQuery.Close;
  702. aqQuery.SQL.Clear;
  703. aqQuery.SQL.Add(Format('Update ScUsers Set Pwd = '''' where ID = %d',[FUserID]));
  704. aqQuery.ExecSQL;
  705. end;
  706. end
  707. else
  708. begin
  709. if CompareStr(strPWD, aqQuery.FieldByName('Pwd').AsString) <> 0 then
  710. begin
  711. Result := 1;
  712. Exit;
  713. end;
  714. // 每次登陆,随机修改密码
  715. // 修改过后的密文在次出入数据库
  716. IsAllChinese := True;
  717. ChineseCount := 0;
  718. for i := 1 to Length(strPWD) do
  719. begin
  720. ReturnCopy := Copy(strPWD, i, 1);
  721. endWord := ReturnCopy[1];
  722. if Ord(endWord) < 128 then
  723. begin
  724. IsAllChinese := False;
  725. end
  726. else
  727. ChineseCount := ChineseCount + 1;
  728. end;
  729. // 对汉字个数占密码长度大于1/3,这样会出现很长时间的循环,现有的办法无法处理,这种情况
  730. // 返回总部重置密码,这种情况只在这次之前注册的用户会出现,这次之后注册的用户中
  731. // 密码没有汉字 2012.3.29
  732. if (ChineseCount > (Length(strPWD) div 3)) and (not IsAllChinese)then
  733. begin
  734. Result := 10;
  735. Exit;
  736. end;
  737. tmpPWD := EncryptionBySecret(strPWD);
  738. ReturnCopy := Copy(tmpPWD, Length(tmpPWD), 1);
  739. endWord := ReturnCopy[1];
  740. // 在不是全是汉字的情况下,处理中文拆字符出现',导致下面SQL语句出错(排除全是汉字的情况)
  741. if not IsAllChinese then
  742. begin
  743. while (Ord(endWord) >= 128) do
  744. begin
  745. tmpPWD := EncryptionBySecret(strPWD);
  746. ReturnCopy := Copy(tmpPWD, Length(tmpPWD), 1);
  747. endWord := ReturnCopy[1];
  748. end;
  749. end;
  750. aqQuery.Close;
  751. aqQuery.SQL.Clear;
  752. aqQuery.SQL.Add(Format('Update ScUsers Set EPwd = ''%s'' where ID = %d',[tmpPWD, FUserID]));
  753. aqQuery.SQL.Add(Format('Update ScUsers Set Pwd = '''' where ID = %d',[FUserID]));
  754. aqQuery.ExecSQL;
  755. end;
  756. // 检查授权日期
  757. aqQuery.Close;
  758. aqQuery.SQL.Clear;
  759. aqQuery.SQL.Add(Format('Select *, GetDate() As Now From ScUsers Where ID = %d', [FUserID]));
  760. aqQuery.Open;
  761. if not aqQuery.FieldByName('LicenseDate').IsNull then
  762. begin
  763. dtLicense := DateOf(aqQuery.FieldByName('LicenseDate').AsDateTime);
  764. dtNow := DateOf(aqQuery.FieldByName('Now').AsDateTime);
  765. if dtNow > dtLicense then
  766. begin
  767. Result := 4;
  768. Exit;
  769. end;
  770. end;
  771. // 首次登陆,则检查授权码
  772. { bNew := aqQuery.FieldByName('New').AsBoolean;
  773. if bNew then
  774. begin
  775. if aqQuery.FieldByName('LicenseCode').AsString = '' then
  776. begin
  777. Result := 8;
  778. Exit;
  779. end;
  780. strLicenseCode := ScInputBox('输入授权码', '您是首次登录,请输入授权码(不分大小写)', '');
  781. if strLicenseCode = '' then
  782. if MessageQuest('如果您尚未获得授权码,请进入纵横产品论坛获取您的授权码。' +
  783. #13#10'点“确定”将转入纵横论坛。') then
  784. begin
  785. ShellExecute(0, nil, 'http://bbs.smartcost.com.cn', nil, nil, SW_SHOWNORMAL);
  786. Exit;
  787. end;
  788. if not SameText(strLicenseCode, aqQuery.FieldByName('LicenseCode').AsString) then
  789. begin
  790. Result := 3;
  791. Exit;
  792. end;
  793. end; }
  794. aqQuery.Close;
  795. // 首次登录成功,修改New字段状态
  796. if bNew then
  797. begin
  798. aqQuery.Close;
  799. aqQuery.SQL.Clear;
  800. aqQuery.SQL.Add(Format('Update ScUsers Set New = 0 Where Name = ''%s''', [strName]));
  801. aqQuery.ExecSQL;
  802. aqQuery.Close;
  803. end;
  804. AddProgressForm(10, '登录验证成功,正在记录登录信息...');
  805. // 至此登录验证成功,下面需要记录登录信息,修改在线状态表。
  806. strVer := 'VerBE';
  807. if bLogin then
  808. begin
  809. aqQuery.Close;
  810. aqQuery.SQL.Clear;
  811. aqQuery.SQL.Add(Format('Update ScOnlineUsers Set LoginTime = GetDate(), '
  812. + 'UpdateTime = GetDate(), %s = 1, Mac = ''%s'' Where ID = %d', [strVer, MacAddress, FOnlineID]));
  813. aqQuery.ExecSQL;
  814. aqQuery.Close;
  815. end
  816. else
  817. begin
  818. gGUID := GetLocalGUID;
  819. aqQuery.Close;
  820. aqQuery.SQL.Clear;
  821. aqQuery.SQL.Add(Format('Insert Into ScOnlineUsers (UserID, LoginTime, UpdateTime, LocalGUID, %s, Mac) '
  822. + 'Values (%d, GetDate(), GetDate(), ''%s'', 1, ''%s'') ',
  823. [strVer, FUserID, GUIDToString(gGUID), MacAddress]));
  824. aqQuery.ExecSQL;
  825. aqQuery.Close;
  826. // 新增在线状态需要根据本机GUID获得在线ID备用
  827. aqQuery.SQL.Clear;
  828. aqQuery.SQL.Add(Format('Select ID From ScOnlineUsers Where LocalGUID=''%s''', [GUIDToString(gGUID)]));
  829. aqQuery.Open;
  830. FOnlineID := aqQuery.FieldByName('ID').AsInteger;
  831. aqQuery.Close;
  832. // 记录登录log
  833. aqQuery.SQL.Clear;
  834. aqQuery.SQL.Add(Format('Insert Into ScUserLog (UserID, LoginTime, Mac) '
  835. + 'Values (%d, GetDate(), ''%s'') ',
  836. [FUserID, MacAddress]));
  837. aqQuery.ExecSQL;
  838. aqQuery.Close;
  839. end;
  840. Result := 0;
  841. // 登录成功
  842. UserConfigInfo.FUserName := strName;
  843. UserConfigInfo.FPassWord := strPWD;
  844. UserConfigInfo.RememberUserInfo(UserConfigInfo.RememberUser);
  845. finally
  846. CloseConnection;
  847. end;
  848. end
  849. else Result := -1;
  850. finally
  851. CloseFloatProgress;
  852. end;
  853. end;
  854. end;
  855. // 字符串格式是:项名称|值|字段名|是否必填(0/1)
  856. function TClientData.InputUserInfo(AUserID: Integer): Boolean;
  857. var
  858. strName, strPWD, strCode, strDate: string;
  859. slstMain, slstSub: TStringList;
  860. gNewGUID: TGUID;
  861. strFields, strValues: string;
  862. iID, I, J, iExeKind: Integer;
  863. begin
  864. Result := False;
  865. slstMain := TStringList.Create;
  866. slstSub := TStringList.Create;
  867. slstSub.Delimiter := '|';
  868. strFields := '';
  869. strValues := '';
  870. try
  871. if ConnectServer then
  872. begin
  873. try
  874. aqQuery.SQL.Clear;
  875. aqQuery.SQL.Add(Format('Select * From ScUsers Where ID = %d', [AUserID]));
  876. aqQuery.Open;
  877. strName := aqQuery.FieldByName('Name').AsString;
  878. strPWD := aqQuery.FieldByName('PWD').AsString;
  879. aqQuery.Close;
  880. aqQuery.SQL.Clear;
  881. aqQuery.SQL.Add(Format('Select * From ScUserInfo Where ID = %d', [AUserID]));
  882. aqQuery.Open;
  883. // 是新申请用户
  884. if (AUserID = -1) or (aqQuery.RecordCount = 0) then
  885. begin
  886. slstMain.Add('真实姓名||Name|1');
  887. slstMain.Add('单位名称||Company|1');
  888. slstMain.Add('联系地址||Address|1');
  889. slstMain.Add('所在省份||Province|1');
  890. slstMain.Add('电话号码||PhoneNum|1');
  891. slstMain.Add('手机号码||MobileNum|0');
  892. slstMain.Add('传真号码||FaxNum|0');
  893. slstMain.Add('QQ号码||QQ|1');
  894. // slstMain.Add('MSN||MSN|0');
  895. slstMain.Add('电子邮件||EMail|1');
  896. end
  897. else
  898. begin
  899. aqQuery.First;
  900. slstMain.Add(Format('真实姓名|%s|Name|1', [aqQuery.FieldByName('Name').AsString]));
  901. slstMain.Add(Format('单位名称|%s|Company|1', [aqQuery.FieldByName('Company').AsString]));
  902. slstMain.Add(Format('联系地址|%s|Address|1', [aqQuery.FieldByName('Address').AsString]));
  903. slstMain.Add(Format('所在省份|%s|Province|1', [aqQuery.FieldByName('Province').AsString]));
  904. slstMain.Add(Format('QQ号码|%s|QQ|1', [aqQuery.FieldByName('QQ').AsString]));
  905. slstMain.Add(Format('电话号码|%s|PhoneNum|1', [aqQuery.FieldByName('PhoneNum').AsString]));
  906. slstMain.Add(Format('手机号码|%s|MobileNum|0', [aqQuery.FieldByName('MobileNum').AsString]));
  907. slstMain.Add(Format('传真号码|%s|FaxNum|0', [aqQuery.FieldByName('FaxNum').AsString]));
  908. // slstMain.Add(Format('MSN|%s|MSN|0', [aqQuery.FieldByName('MSN').AsString]));
  909. slstMain.Add(Format('电子邮件|%s|EMail|1', [aqQuery.FieldByName('EMail').AsString]));
  910. end;
  911. aqQuery.Close;
  912. if ShowUserInfoForm(strName, strPWD, slstMain, AUserID = -1) then
  913. begin
  914. ShowFloatProgress('正在提交数据,请稍候……', 100);
  915. Screen.Cursor := crHourGlass;
  916. try
  917. // 是新申请用户
  918. if AUserID = -1 then
  919. begin
  920. CreateGUID(gNewGUID);
  921. // lengshumei 2009-12-3
  922. Randomize;
  923. // strCode := IntToHex(RandomRange($132, $FFE), 3) + IntToHex(RandomRange($21, $EF), 2)
  924. // + IntToHex(RandomRange($01A, $FEF), 3);
  925. // 授权期限到 365天*5年 后
  926. strDate := DateToStr(now + 1825);
  927. iExeKind := 4; // 清单编制
  928. // 向ScUsers表插入记录
  929. aqQuery.SQL.Clear;
  930. // aqQuery.SQL.Add(Format('Insert Into ScUsers (Name, Pwd, New, Enabled, CanChangePWD, LicenseCode, LicenseDate, LoginLimit, NewGUID, ExeKind) '
  931. // + 'Values (''%s'', ''%s'', %d, %d, %d, ''%s'', ''%s'', %d, ''%s'', %d)',
  932. // [strName, strPwd, 1, 1, 1, strCode, strDate, 1, GUIDToString(gNewGUID), iExeKind]));
  933. aqQuery.SQL.Add(Format('Insert Into ScUsers (Name, Pwd, New, Enabled, CanChangePWD, LicenseDate, LoginLimit, NewGUID, ExeKind) '
  934. + 'Values (''%s'', ''%s'', %d, %d, %d, ''%s'', %d, ''%s'', %d)',
  935. [strName, strPwd, 1, 1, 1, strDate, 1, GUIDToString(gNewGUID), iExeKind]));
  936. aqQuery.ExecSQL;
  937. // 根据GUID获得用户ID
  938. aqQuery.SQL.Clear;
  939. aqQuery.SQL.Add(Format('Select ID From ScUsers Where NewGUID = ''%s''', [GUIDToString(gNewGUID)]));
  940. aqQuery.Open;
  941. if aqQuery.RecordCount = 0 then
  942. raise EClientData.Create('提交数据失败,请检查网络设置');
  943. // 获得用户ID
  944. aqQuery.First;
  945. iID := aqQuery.FieldByName('ID').AsInteger;
  946. end
  947. else
  948. iID := AUserID;
  949. // 检查是否原来就存在用户资料
  950. aqQuery.SQL.Clear;
  951. aqQuery.SQL.Add(Format('Select * From ScUserInfo Where ID = %d', [iID]));
  952. aqQuery.Open;
  953. if aqQuery.RecordCount = 0 then
  954. begin
  955. aqQuery.Close;
  956. // 向ScUserInfo表插入用户资料
  957. for I := 0 to slstMain.Count - 1 do
  958. begin
  959. slstSub.Clear;
  960. slstSub.DelimitedText := slstMain[I];
  961. if strFields <> '' then
  962. strFields := strFields + ', ';
  963. strFields := strFields + slstSub[2];
  964. if strValues <> '' then
  965. strValues := strValues + ' ,';
  966. strValues := strValues + '''' + slstSub[1] + '''';
  967. end;
  968. aqQuery.SQL.Clear;
  969. aqQuery.SQL.Add(Format('Insert Into ScUserInfo (ID, %s, RegDate) Values (%d, %s, GetDate())',
  970. [strFields, iID, strValues]));
  971. Result := aqQuery.ExecSQL > 0;
  972. end
  973. else
  974. begin
  975. aqQuery.Close;
  976. // 修改ScUserInfo表原有用户资料
  977. for I := 0 to slstMain.Count - 1 do
  978. begin
  979. slstSub.Clear;
  980. slstSub.DelimitedText := slstMain[I];
  981. if strValues <> '' then
  982. strValues := strValues + ', ';
  983. strValues := strValues + slstSub[2] + '=''' + slstSub[1] + '''';
  984. end;
  985. aqQuery.SQL.Clear;
  986. aqQuery.SQL.Add(Format('Update ScUserInfo Set %s, RegDate = GetDate() Where ID = %d',
  987. [strValues, iID]));
  988. Result := aqQuery.ExecSQL > 0;
  989. end;
  990. finally
  991. CloseFloatProgress;
  992. Screen.Cursor := crDefault;
  993. end;
  994. end;
  995. finally
  996. CloseConnection;
  997. end;
  998. end;
  999. finally
  1000. slstMain.Free;
  1001. slstSub.Free;
  1002. end;
  1003. // if Result then
  1004. // ShowLicenseCode(strCode);
  1005. end;
  1006. function TClientData.Login: Boolean;
  1007. begin
  1008. Result := False;
  1009. // 返回值:-2:用户取消登录;-1:无法连接服务器;0:成功;1:密码错误;2:用户名错误;
  1010. // 3:授权码错误(首次登录);4:授权已过期;5:用户被禁用
  1011. // 6:用户登录次数超限;7:服务器在线人数超限; 8:尚未获得授权
  1012. // 9:申请被拒绝
  1013. case InnerLogin of
  1014. -2: {no hint};
  1015. -1: MessageWarning(0, '无法连接服务器,请检查网络设置。');
  1016. 0: Result := True;
  1017. 1: MessageWarning(0, '密码错误!请重试。');
  1018. //ShowLoginForm(Fusername, fpassword);
  1019. 2: MessageWarning(0, '用户名错误。');
  1020. // 3: MessageWarning(0, '授权码错误。');
  1021. 4: MessageWarning(0, '授权已过期。');
  1022. 5: MessageWarning(0, Format('用户未被启用。如有问题,请联系纵横客服。', [LoadServiceQQ]));
  1023. 6: MessageWarning(0, '您已在别的地方登录,故本次登陆失败。'#13#10 +
  1024. '有疑问请电:0756-3850888。');
  1025. 7: MessageHint(0, '服务器在线人数超限,请稍后重试。');
  1026. // 8: MessageHint(0, Format('您尚未获得授权。如有问题,请联系纵横客服。', [LoadServiceQQ]));
  1027. 9:
  1028. if MessageWarning(0, '您的申请未审核通过,因为您填写的资料信息不足。'#13#10 +
  1029. '需要修改您的资料,并重新提交申请吗?', '提示', MB_YESNO) = IDYES then
  1030. ReRequest(FUserID);
  1031. 10: MessageWarning(0, Format('您的密码中不合规范。请联系纵横客服重置密码,客服电话。', [LoadServiceQQ]));
  1032. end;
  1033. end;
  1034. function TClientData.Logout: Boolean;
  1035. var
  1036. bCanDelete: Boolean;
  1037. bVer1, bVer2, bVer3: Boolean;
  1038. strVer: string;
  1039. begin
  1040. Result := False;
  1041. if ConnectServer then
  1042. begin
  1043. try
  1044. // 先查询是否有其它版本的Exe在运行, 如有,则只修改版本标记,如无,则删除在线记录
  1045. aqQuery.SQL.Clear;
  1046. aqQuery.SQL.Add(Format('Select * From ScOnlineUsers Where ID = %d', [FOnlineID]));
  1047. aqQuery.Open;
  1048. bVer1 := aqQuery.FieldByName('Ver1').AsBoolean;
  1049. bVer2 := aqQuery.FieldByName('Ver2').AsBoolean;
  1050. bVer3 := aqQuery.FieldByName('Ver3').AsBoolean;
  1051. aqQuery.Close;
  1052. {$IFDEF _ScBills}
  1053. bCanDelete := not (bVer2 or bVer3);
  1054. strVer := 'Ver1';
  1055. {$ENDIF}
  1056. {$IFDEF _ScBudget}
  1057. {$IFDEF _ScEstimate}
  1058. bCanDelete := not (bVer1 or bVer2);
  1059. strVer := 'Ver3';
  1060. {$ELSE}
  1061. bCanDelete := not (bVer1 or bVer3);
  1062. strVer := 'Ver2';
  1063. {$ENDIF}
  1064. {$ENDIF}
  1065. {$IFDEF _beOnLine}
  1066. bCanDelete := not (bVer1 or bVer2 or bVer3);
  1067. strVer := 'VerBE';
  1068. {$ENDIF}
  1069. if bCanDelete then
  1070. begin
  1071. // 删除在线数据
  1072. aqQuery.SQL.Clear;
  1073. aqQuery.SQL.Add(Format('Delete From ScOnlineUsers Where ID = %d', [FOnlineID]));
  1074. // 如果修改行数小于0,则说明服务器上没有本用户登录数据,检测失败
  1075. Result := aqQuery.ExecSQL > 0;
  1076. aqQuery.Close;
  1077. // 记录登录log
  1078. aqQuery.SQL.Clear;
  1079. aqQuery.SQL.Add(Format('Insert Into ScUserLog (UserID, LogoutTime, Mac) '
  1080. + 'Values (%d, GetDate(), ''%s'') ',
  1081. [FUserID, MacAddress]));
  1082. aqQuery.ExecSQL;
  1083. aqQuery.Close;
  1084. end
  1085. else
  1086. begin
  1087. // 修改版本信息
  1088. aqQuery.SQL.Clear;
  1089. aqQuery.SQL.Add(Format('Update ScOnlineUsers Set %s = 0 Where ID = %d', [strVer, FOnlineID]));
  1090. // 如果修改行数小于0,则说明服务器上没有本用户登录数据,检测失败
  1091. Result := aqQuery.ExecSQL > 0;
  1092. aqQuery.Close;
  1093. end;
  1094. finally
  1095. CloseConnection;
  1096. end;
  1097. end;
  1098. end;
  1099. function TClientData.ReRequest(AUserID: Integer): Boolean;
  1100. begin
  1101. Result := InputUserInfo(AUserID);
  1102. if Result then
  1103. MessageHint(0, '您的申请已经成功提交,请联系QQ:549244533获取授权码。');
  1104. end;
  1105. function TClientData.DecryptByKey(ASource: string; APWD: string): String;
  1106. var
  1107. Longth, flag, flag1, i: Integer;
  1108. TmpSouce: string;
  1109. beforStr: string;
  1110. AfterStr: string;
  1111. intArr: array of Integer;
  1112. begin
  1113. Result := '';
  1114. if (Length(ASource) < 20) and (Pos(' ', ASource) = 0) then
  1115. begin
  1116. Longth := Length(APWD);
  1117. SetLength(intArr, Longth);
  1118. for i := 1 to Longth do
  1119. begin
  1120. intArr[i - 1] := StrToInt(Copy(ASource, i, 1));
  1121. end;
  1122. end
  1123. else
  1124. begin
  1125. TmpSouce := ASource;
  1126. Longth := 0;
  1127. while Pos(' ', TmpSouce) > 0 do
  1128. begin
  1129. flag := Pos(' ', TmpSouce);
  1130. Longth := Longth + 1;
  1131. beforStr := Copy(TmpSouce, 1, flag - 1);
  1132. AfterStr := Copy(TmpSouce, flag + 1, Length(TmpSouce) - flag);
  1133. TmpSouce := '';
  1134. TmpSouce := beforStr + AfterStr;
  1135. end;
  1136. SetLength(intArr, Longth);
  1137. Longth := 0;
  1138. flag1 := 1;
  1139. while Pos(' ', ASource) > 0 do
  1140. begin
  1141. flag := Pos(' ', ASource);
  1142. Longth := Longth + 1;
  1143. beforStr := Copy(ASource, 1, flag - 1);
  1144. intArr[Longth -1] := StrToInt(Copy(beforStr, flag1 , Length(beforStr) -flag1 +1));
  1145. AfterStr := Copy(ASource, flag + 1, Length(ASource) - flag);
  1146. ASource := '';
  1147. ASource := beforStr + AfterStr;
  1148. flag1 := flag;
  1149. end;
  1150. end;
  1151. Result := EncryptionByKey(intArr, APWD);
  1152. end;
  1153. function TClientData.UserExists(AUserName: string): Boolean;
  1154. begin
  1155. Result := True;
  1156. ShowFloatProgress('正在与服务器通信,请稍候……', 100);
  1157. Screen.Cursor :=crHourGlass;
  1158. try
  1159. if ConnectServer then
  1160. begin
  1161. try
  1162. aqQuery.SQL.Clear;
  1163. aqQuery.SQL.Add(Format('Select * From ScUsers Where Name = ''%s''', [AUserName]));
  1164. // 如果修改行数小于0,则说明服务器上没有本用户登录数据,检测失败
  1165. aqQuery.Open;
  1166. Result := aqQuery.RecordCount > 0;
  1167. aqQuery.Close;
  1168. finally
  1169. CloseConnection;
  1170. end;
  1171. end
  1172. else
  1173. raise EClientData.Create('连接服务器失败');
  1174. finally
  1175. Screen.Cursor := crDefault;
  1176. CloseFloatProgress;
  1177. end;
  1178. end;
  1179. { TUserConfigInfo }
  1180. constructor TScUserConfigInfo.Create;
  1181. begin
  1182. FIniFile := TIniFile.Create(ExtractFilePath(Application.ExeName) + 'OnlineUser.ini');
  1183. LoadFromFile;
  1184. end;
  1185. destructor TScUserConfigInfo.Destroy;
  1186. begin
  1187. FIniFile.Free;
  1188. inherited;
  1189. end;
  1190. procedure TScUserConfigInfo.LoadFromFile;
  1191. var
  1192. OutPutPassWordLength: Integer;
  1193. sPassWord: string;
  1194. bInPutPassWord, bOutPutPassWord: array of Byte;
  1195. begin
  1196. Fversion := FIniFile.ReadInteger(SctVersion, 'Version', 0);
  1197. FUserName := FIniFile.ReadString(SctUser, 'UserName', '');
  1198. sPassWord := FIniFile.ReadString(SctUser, 'PassWord', '');
  1199. if FVersion = 0 then
  1200. FPassWord := sPassWord
  1201. else
  1202. FPassWord := LockStr(sPassWord);
  1203. // FFirstLogon := FIniFile.ReadBool(SctUser, 'FirstLogon', True);
  1204. FRememberUser := FIniFile.ReadBool(SctUser, 'RememberUser', True);
  1205. end;
  1206. procedure TScUserConfigInfo.RememberUserInfo(ARemember: Boolean);
  1207. var
  1208. bInPutPassWord, bOutPutPassWord: array of Byte;
  1209. OutPutPassWordLength, i: Integer;
  1210. sPassWord: string;
  1211. begin
  1212. FRememberUser := ARemember;
  1213. FIniFile.WriteBool(SctUser, 'RememberUser', ARemember);
  1214. if ARemember then
  1215. begin
  1216. FIniFile.WriteString(SctUser, 'UserName', FUserName);
  1217. sPassWord := LockStr(FPassWord);
  1218. FIniFile.WriteString(SctUser, 'PassWord', sPassWord);
  1219. end
  1220. else
  1221. begin
  1222. FIniFile.WriteString(SctUser, 'UserName', '');
  1223. FIniFile.WriteString(SctUser, 'PassWord', '');
  1224. end;
  1225. FIniFile.WriteInteger(SctVersion, 'Version', 90401);
  1226. end;
  1227. procedure TScUserConfigInfo.SaveToFile;
  1228. var
  1229. bInPutPassWord, bOutPutPassWord: array of Byte;
  1230. OutPutPassWordLength: Integer;
  1231. sPassWord: string;
  1232. begin
  1233. FIniFile.WriteString(SctUser, 'UserName', FUserName);
  1234. sPassWord := LockStr(FPassWord);
  1235. FIniFile.WriteString(SctUser, 'PassWord', sPassWord);
  1236. // FIniFile.WriteBool(SctUser, 'FirstLogon', FFirstLogon);
  1237. FIniFile.WriteBool(SctUser, 'RememberUser', FRememberUser);
  1238. FIniFile.WriteInteger(SctVersion, 'Version', 90401);
  1239. end;
  1240. function TScUserConfigInfo.LockStr(AStr: String): WideString;
  1241. var
  1242. I: Integer;
  1243. STemp, sCompare: String;
  1244. const
  1245. sStr: String = 'UXtnGjc4dIBkosvCPQSrDYFZJhTewliyLMaH70uW95xbVzOKq3E1Rmpf8AN62g';
  1246. begin
  1247. Result := '';
  1248. for I := 1 to Length(AStr) do
  1249. begin
  1250. sCompare := '';
  1251. sCompare := sCompare + AStr[I];
  1252. if Pos(sCompare, sStr)>0 then
  1253. Stemp := Stemp + sStr[63 - Pos(sCompare, sStr)]
  1254. else
  1255. Stemp := Stemp + AStr[I];
  1256. end;
  1257. Result := STemp;
  1258. end;
  1259. function TScUserConfigInfo.AHostToIP(AName: string;
  1260. var Aip: string): Boolean;
  1261. var
  1262. Wsdata: TWSAData;
  1263. HostName: array[0..255] of Char;
  1264. HostEnt: PHostEnt;
  1265. Addrs: PChar;
  1266. begin
  1267. WSAStartup($0101,Wsdata);
  1268. try
  1269. gethostname(HostName, SizeOf(HostName));
  1270. StrPCopy(HostName, AName);
  1271. HostEnt := gethostbyname(HostName);
  1272. if Assigned(HostEnt) then
  1273. begin
  1274. if Assigned(HostEnt^.h_addr_list) then
  1275. begin
  1276. Addrs := HostEnt^.h_addr_list^;
  1277. if Assigned(Addrs) then
  1278. begin
  1279. Aip := Format('%d.%d.%d.%d', [byte(Addrs[0]), byte(Addrs[1]), byte(Addrs[2]), byte(Addrs[3])]);
  1280. Result := True;
  1281. end
  1282. else
  1283. Result := False;
  1284. end
  1285. else
  1286. Result := False;
  1287. end
  1288. else
  1289. Result := False
  1290. finally
  1291. WSACleanup;
  1292. end;
  1293. end;
  1294. function TClientData.AddSpaceToString(aSource: string): string;
  1295. var i, Len: Integer;
  1296. begin
  1297. i := 2;
  1298. Len := Length(aSource);
  1299. while i <= Len do
  1300. begin
  1301. Insert(' ', aSource, i);
  1302. i := i + 2;
  1303. end;
  1304. Result := aSource;
  1305. end;
  1306. initialization
  1307. UserConfigInfo := TScUserConfigInfo.Create;
  1308. finalization
  1309. if g_ClientData <> nil then
  1310. g_ClientData.Free;
  1311. UserConfigInfo.Free;
  1312. end.