Annotation of sbbs/src/sbbs3/useredit/mainformunit.pas, revision 1.1.1.1

1.1       root        1: { Synchronet User Editor (Delphi 5 for Win32 project) }
                      2: 
                      3: { $Id: MainFormUnit.pas,v 1.9 2003/02/20 00:11:25 rswindell Exp $ }
                      4: 
                      5: {****************************************************************************
                      6:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
                      7:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
                      8:  *                                                                                                                                                     *
                      9:  * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html         *
                     10:  *                                                                                                                                                     *
                     11:  * This program is free software; you can redistribute it and/or                       *
                     12:  * modify it under the terms of the GNU General Public License                         *
                     13:  * as published by the Free Software Foundation; either version 2                      *
                     14:  * of the License, or (at your option) any later version.                                      *
                     15:  * See the GNU General Public License for more details: gpl.txt or                     *
                     16:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
                     17:  *                                                                                                                                                     *
                     18:  * Anonymous FTP access to the most recent released source is available at     *
                     19:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
                     20:  *                                                                                                                                                     *
                     21:  * Anonymous CVS access to the development source and modification history     *
                     22:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
                     23:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
                     24:  *     (just hit return, no password is necessary)                                                     *
                     25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
                     26:  *                                                                                                                                                     *
                     27:  * For Synchronet coding style and modification guidelines, see                                *
                     28:  * http://www.synchro.net/source.html                                                                          *
                     29:  *                                                                                                                                                     *
                     30:  * You are encouraged to submit any modifications (preferably in Unix diff     *
                     31:  * format) via e-mail to [email protected]                                                                      *
                     32:  *                                                                                                                                                     *
                     33:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
                     34:  ****************************************************************************}
                     35: 
                     36: { User Data function Notes:
                     37: 
                     38:     The Tag member of the Edit boxes is used to indicate modified data.
                     39:     GetUserXxxx() calls GetXxxxField() sets the Tag to 0.
                     40:     PutUserXxxx() only gets PutXxxxField() if Tag = 1.
                     41:     GetXxxxField() and PutXxxxField() do not care about TEdits or Tags.
                     42: }
                     43: 
                     44: unit MainFormUnit;
                     45: 
                     46: interface
                     47: 
                     48: uses
                     49:   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
                     50:   StdCtrls, Menus, ComCtrls, ExtCtrls, Buttons, ActnList, ImgList, CheckLst,
                     51:   ToolWin, Registry;
                     52: 
                     53: type
                     54:   TForm1 = class(TForm)
                     55:     MainMenu: TMainMenu;
                     56:     FileMenuItem: TMenuItem;
                     57:     Panel: TPanel;
                     58:     FileExitMenuItem: TMenuItem;
                     59:     FileDeleteMenuItem: TMenuItem;
                     60:     PageControl: TPageControl;
                     61:     PersonalTabSheet: TTabSheet;
                     62:     Label2: TLabel;
                     63:     NameEdit: TEdit;
                     64:     Label1: TLabel;
                     65:     ComputerEdit: TEdit;
                     66:     NetmailAddress: TLabel;
                     67:     NetmailEdit: TEdit;
                     68:     Label7: TLabel;
                     69:     NoteEdit: TEdit;
                     70:     HandleLabel: TLabel;
                     71:     HandleEdit: TEdit;
                     72:     Label5: TLabel;
                     73:     PasswordEdit: TEdit;
                     74:     Label6: TLabel;
                     75:     BirthdateEdit: TEdit;
                     76:     Label8: TLabel;
                     77:     ModemEdit: TEdit;
                     78:     Label16: TLabel;
                     79:     SexEdit: TEdit;
                     80:     Label18: TLabel;
                     81:     PhoneEdit: TEdit;
                     82:     SecurityTabSheet: TTabSheet;
                     83:     Label10: TLabel;
                     84:     LevelEdit: TEdit;
                     85:     Label11: TLabel;
                     86:     ExpireEdit: TEdit;
                     87:     StatsTabSheet: TTabSheet;
                     88:     TopPanel: TPanel;
                     89:     NumberLabel: TLabel;
                     90:     NumberEdit: TEdit;
                     91:     TotalStaticText: TStaticText;
                     92:     AliasLabel: TLabel;
                     93:     AliasEdit: TEdit;
                     94:     Label24: TLabel;
                     95:     CommentEdit: TEdit;
                     96:     FileNewUserMenuItem: TMenuItem;
                     97:     Label25: TLabel;
                     98:     ExemptionsEdit: TEdit;
                     99:     Label26: TLabel;
                    100:     RestrictionsEdit: TEdit;
                    101:     Label27: TLabel;
                    102:     CreditsEdit: TEdit;
                    103:     Label28: TLabel;
                    104:     MinutesEdit: TEdit;
                    105:     Label29: TLabel;
                    106:     FreeCreditsEdit: TEdit;
                    107:     FileSaveUserMenuItem: TMenuItem;
                    108:     ActionList: TActionList;
                    109:     SaveUser: TAction;
                    110:     NewUser: TAction;
                    111:     RefreshUser: TAction;
                    112:     ImageList: TImageList;
                    113:     DeleteUser: TAction;
                    114:     FileRefreshUserMenuItem: TMenuItem;
                    115:     GroupBox1: TGroupBox;
                    116:     TimeOnEdit: TEdit;
                    117:     Label22: TLabel;
                    118:     Label23: TLabel;
                    119:     TimeOnTodayEdit: TEdit;
                    120:     Label30: TLabel;
                    121:     ExtraTimeEdit: TEdit;
                    122:     Label31: TLabel;
                    123:     LastCallTimeEdit: TEdit;
                    124:     GroupBox2: TGroupBox;
                    125:     Label20: TLabel;
                    126:     LogonsEdit: TEdit;
                    127:     Label21: TLabel;
                    128:     LogonsTodayEdit: TEdit;
                    129:     GroupBox3: TGroupBox;
                    130:     Label17: TLabel;
                    131:     FirstOnEdit: TEdit;
                    132:     Label19: TLabel;
                    133:     LastOnEdit: TEdit;
                    134:     GroupBox4: TGroupBox;
                    135:     Label32: TLabel;
                    136:     PostsTotalEdit: TEdit;
                    137:     Label33: TLabel;
                    138:     PostsTodayEdit: TEdit;
                    139:     GroupBox5: TGroupBox;
                    140:     Label34: TLabel;
                    141:     Label35: TLabel;
                    142:     EmailTotalEdit: TEdit;
                    143:     EmailTodayEdit: TEdit;
                    144:     Label36: TLabel;
                    145:     FeedbackEdit: TEdit;
                    146:     GroupBox6: TGroupBox;
                    147:     Label37: TLabel;
                    148:     UploadedFilesEdit: TEdit;
                    149:     Label38: TLabel;
                    150:     UploadedBytesEdit: TEdit;
                    151:     GroupBox7: TGroupBox;
                    152:     Label39: TLabel;
                    153:     Label40: TLabel;
                    154:     DownloadedFilesEdit: TEdit;
                    155:     DownloadedBytesEdit: TEdit;
                    156:     GroupBox8: TGroupBox;
                    157:     Label12: TLabel;
                    158:     Flags1Edit: TEdit;
                    159:     Label13: TLabel;
                    160:     Flags2Edit: TEdit;
                    161:     Label14: TLabel;
                    162:     Flags3Edit: TEdit;
                    163:     Label15: TLabel;
                    164:     Flags4Edit: TEdit;
                    165:     GroupBox9: TGroupBox;
                    166:     AddressEdit: TEdit;
                    167:     LocationEdit: TEdit;
                    168:     ZipCodeEdit: TEdit;
                    169:     DeactivateUser: TAction;
                    170:     N1: TMenuItem;
                    171:     FileDeactivateUserMenuItem: TMenuItem;
                    172:     SettingsTabSheet: TTabSheet;
                    173:     GroupBox10: TGroupBox;
                    174:     Label3: TLabel;
                    175:     RowsEdit: TEdit;
                    176:     GroupBox11: TGroupBox;
                    177:     GroupBox13: TGroupBox;
                    178:     GroupBox15: TGroupBox;
                    179:     ShellEdit: TEdit;
                    180:     ExpertCheckBox: TCheckBox;
                    181:     ChatCheckListBox: TCheckListBox;
                    182:     TerminalCheckListBox: TCheckListBox;
                    183:     LogonCheckListBox: TCheckListBox;
                    184:     ToolBar: TToolBar;
                    185:     ToolButton1: TToolButton;
                    186:     ToolButton2: TToolButton;
                    187:     ToolButton3: TToolButton;
                    188:     ToolButton4: TToolButton;
                    189:     ToolButton5: TToolButton;
                    190:     FindEdit: TEdit;
                    191:     ToolButton6: TToolButton;
                    192:     FindNextButton: TButton;
                    193:     FindButton: TButton;
                    194:     ScrollBar: TScrollBar;
                    195:     Label42: TLabel;
                    196:     LeechEdit: TEdit;
                    197:     Status: TEdit;
                    198:     ToolButton7: TToolButton;
                    199:     MsgFileSettingsTabSheet: TTabSheet;
                    200:     GroupBox16: TGroupBox;
                    201:     Label41: TLabel;
                    202:     MessageCheckListBox: TCheckListBox;
                    203:     EditorEdit: TEdit;
                    204:     GroupBox12: TGroupBox;
                    205:     Label4: TLabel;
                    206:     Label9: TLabel;
                    207:     TempFileExtEdit: TEdit;
                    208:     ProtocolEdit: TEdit;
                    209:     FileCheckListBox: TCheckListBox;
                    210:     GroupBox14: TGroupBox;
                    211:     QWKCheckListBox: TCheckListBox;
                    212:     ExtendedCommentTabSheet: TTabSheet;
                    213:     Memo: TMemo;
                    214:     procedure FormShow(Sender: TObject);
                    215:     procedure ScrollBarChange(Sender: TObject);
                    216:     procedure NumberEditKeyPress(Sender: TObject; var Key: Char);
                    217:     procedure FileExitMenuItemClick(Sender: TObject);
                    218:     procedure EditChange(Sender: TObject);
                    219:     procedure SaveUserExecute(Sender: TObject);
                    220:     procedure NewUserExecute(Sender: TObject);
                    221:     procedure DeleteUserExecute(Sender: TObject);
                    222:     procedure FormClose(Sender: TObject; var Action: TCloseAction);
                    223:     procedure DeactivateUserExecute(Sender: TObject);
                    224:     procedure FindButtonClick(Sender: TObject);
                    225:     procedure FindEditKeyPress(Sender: TObject; var Key: Char);
                    226:   private
                    227:     { Private declarations }
                    228:   public
                    229:     { Public declarations }
                    230:     data_dir: AnsiString;
                    231:     users: Integer;
                    232:     user_misc: Integer;
                    233:     user_chat: Integer;
                    234:     user_qwk: Integer;
                    235:     function LastUser: Integer;
                    236:     procedure GetUserData(usernumber: Integer);
                    237:     procedure PutUserData(usernumber: Integer);
                    238:   end;
                    239: 
                    240: var
                    241:   Form1: TForm1;
                    242: 
                    243: implementation
                    244: 
                    245: const ETX=#3; { End Of Text character, all fields use for padding/terminator }
                    246: const CR=#13; { Carriage-return }
                    247: const LF=#10; { Line-feed }
                    248: 
                    249: const                                      { String lengths                                                }
                    250:     LEN_ALIAS          =25;    { User alias                                                        }
                    251:     LEN_NAME           =25;    { User name                                                                 }
                    252:     LEN_HANDLE         =8;     { User chat handle                                                  }
                    253:     LEN_NOTE           =30;    { User note                                                                 }
                    254:     LEN_COMP           =30;    { User computer description                                 }
                    255:     LEN_COMMENT        =60;    { User comment                                                      }
                    256:     LEN_NETMAIL        =60;    { NetMail forwarding address                        }
                    257:     LEN_PASS           =8;         { User password                                                         }
                    258:     LEN_PHONE          =12;    { User phone number                                                 }
                    259:     LEN_BIRTH          =8;         { Birthday in xx/xx/YY format                           }
                    260:     LEN_ADDRESS        =30;    { User address                                                      }
                    261:     LEN_LOCATION       =30;    { Location (City, State)                                    }
                    262:     LEN_ZIPCODE        =10;    { Zip/Postal code                                                   }
                    263:     LEN_MODEM          =8;         { User modem type description                           }
                    264:     LEN_FDESC          =58;    { File description                                                  }
                    265:     LEN_FCDT           =9;         { 9 digits for file credit values               }
                    266:     LEN_TITLE          =70;    { Message title                                                     }
                    267:     LEN_MAIN_CMD       =40;    { Storage in user.dat for custom commands       }
                    268:     LEN_XFER_CMD       =40;
                    269:     LEN_SCAN_CMD       =40;
                    270:     LEN_MAIL_CMD       =40;
                    271:     LEN_CID            =25;    { Caller ID (phone number)                                  }
                    272:     LEN_ARSTR          =40;    { Max length of Access Requirement string       }
                    273:     LEN_CHATACTCMD     =9;         { Chat action command                                           }
                    274:     LEN_CHATACTOUT     =65;    { Chat action output string                                 }
                    275: 
                    276: 
                    277: { This is a list of offsets into the USER.DAT file for different variables
                    278:   that are stored (for each user) }
                    279: const
                    280:     U_ALIAS    =0;                                     { Offset to alias }
                    281:     U_NAME             =U_ALIAS+LEN_ALIAS;         { Offset to name }
                    282:     U_HANDLE   =U_NAME+LEN_NAME;
                    283:     U_NOTE             =U_HANDLE+LEN_HANDLE+2;
                    284:     U_COMP             =U_NOTE+LEN_NOTE;
                    285:     U_COMMENT  =U_COMP+LEN_COMP+2;
                    286: 
                    287:     U_NETMAIL  =U_COMMENT+LEN_COMMENT+2;
                    288: 
                    289:     U_ADDRESS  =U_NETMAIL+LEN_NETMAIL+2;
                    290:     U_LOCATION =U_ADDRESS+LEN_ADDRESS;
                    291:     U_ZIPCODE  =U_LOCATION+LEN_LOCATION;
                    292: 
                    293:     U_PASS             =U_ZIPCODE+LEN_ZIPCODE+2;
                    294:     U_PHONE    =U_PASS+8;                          { Offset to phone-number }
                    295:     U_BIRTH    =U_PHONE+12;                { Offset to users birthday  }
                    296:     U_MODEM     =U_BIRTH+8;
                    297:     U_LASTON   =U_MODEM+8;
                    298:     U_FIRSTON  =U_LASTON+8;
                    299:     U_EXPIRE    =U_FIRSTON+8;
                    300:     U_PWMOD     =U_EXPIRE+8;
                    301: 
                    302:     U_LOGONS    =U_PWMOD+8+2;
                    303:     U_LTODAY    =U_LOGONS+5;
                    304:     U_TIMEON    =U_LTODAY+5;
                    305:     U_TEXTRA   =U_TIMEON+5;
                    306:     U_TTODAY    =U_TEXTRA+5;
                    307:     U_TLAST     =U_TTODAY+5;
                    308:     U_POSTS     =U_TLAST+5;
                    309:     U_EMAILS    =U_POSTS+5;
                    310:     U_FBACKS    =U_EMAILS+5;
                    311:     U_ETODAY   =U_FBACKS+5;
                    312:     U_PTODAY   =U_ETODAY+5;
                    313: 
                    314:     U_ULB       =U_PTODAY+5+2;
                    315:     U_ULS       =U_ULB+10;
                    316:     U_DLB       =U_ULS+5;
                    317:     U_DLS       =U_DLB+10;
                    318:     U_CDT              =U_DLS+5;
                    319:     U_MIN              =U_CDT+10;
                    320: 
                    321:     U_LEVEL    =U_MIN+10+2;    { Offset to Security Level    }
                    322:     U_FLAGS1   =U_LEVEL+2;     { Offset to Flags }
                    323:     U_TL               =U_FLAGS1+8;    { Offset to unused field }
                    324:     U_FLAGS2   =U_TL+2;
                    325:     U_EXEMPT   =U_FLAGS2+8;
                    326:     U_REST             =U_EXEMPT+8;
                    327:     U_ROWS             =U_REST+8+2;    { Number of Rows on user's monitor }
                    328:     U_SEX              =U_ROWS+2;              { Sex, Del, ANSI, color etc.       }
                    329:     U_MISC             =U_SEX+1;               { Miscellaneous flags in 8-byte hex }
                    330:     U_OLDXEDIT =U_MISC+8;              { External editor (Version 1 method)  }
                    331:     U_LEECH    =U_OLDXEDIT+2;  { two hex digits - leech attempt count }
                    332:     U_CURSUB   =U_LEECH+2;     { Current sub (internal code  }
                    333:     U_CURDIR   =U_CURSUB+8;    { Current dir (internal code  }
                    334:     U_CMDSET   =U_CURDIR+8;    { unused }
                    335:     U_MAIN_CMD =U_CMDSET+2+2;  { unused }
                    336:     U_XFER_CMD =U_MAIN_CMD+LEN_MAIN_CMD;               { unused }
                    337:     U_SCAN_CMD =U_XFER_CMD+LEN_XFER_CMD+2;     { unused }
                    338:     U_MAIL_CMD =U_SCAN_CMD+LEN_SCAN_CMD;               { unused }
                    339:     U_FREECDT  =U_MAIL_CMD+LEN_MAIL_CMD+2;
                    340:     U_FLAGS3   =U_FREECDT+10;  { Flag set #3 }
                    341:     U_FLAGS4   =U_FLAGS3+8;    { Flag set #4 }
                    342:     U_XEDIT    =U_FLAGS4+8;    { External editor (code)  }
                    343:     U_SHELL    =U_XEDIT+8;     { Command shell (code)  }
                    344:     U_QWK              =U_SHELL+8;     { QWK settings }
                    345:     U_TMPEXT   =U_QWK+8;               { QWK extension }
                    346:     U_CHAT             =U_TMPEXT+3;    { Chat settings }
                    347:     U_NS_TIME  =U_CHAT+8;              { New-file scan date/time }
                    348:     U_PROT             =U_NS_TIME+8;   { Default transfer protocol }
                    349:     U_UNUSED   =U_PROT+1;
                    350:     U_LEN              =(U_UNUSED+28+2);
                    351: 
                    352: { Bit values for user_misc             }
                    353: const
                    354:     DELETED    =(1 shl 0);         { Deleted user }
                    355:     ANSI               =(1 shl 1);             { Supports ANSI terminal emulation  }
                    356:     UCOLOR             =(1 shl 2);             { Send color codes                                  }
                    357:     RIP                =(1 shl 3);             { Supports RIP terminal emulation       }
                    358:     UPAUSE             =(1 shl 4);             { Pause on every screen full            }
                    359:     SPIN               =(1 shl 5);             { Spinning cursor - Same as K_SPIN  }
                    360:     INACTIVE   =(1 shl 6);             { Inactive user slot                            }
                    361:     EXPERT             =(1 shl 7);             { Expert menu mode                                  }
                    362:     ANFSCAN    =(1 shl 8);             { Auto New file scan                            }
                    363:     CLRSCRN    =(1 shl 9);             { Clear screen before each message  }
                    364:     QUIET              =(1 shl 10);            { Quiet mode upon logon                     }
                    365:     BATCHFLAG  =(1 shl 11);            { File list allow batch dl flags        }
                    366:     NETMAIL    =(1 shl 12);            { Forward e-mail to fidonet addr        }
                    367:     CURSUB             =(1 shl 13);            { Remember current sub-board/dir        }
                    368:     ASK_NSCAN  =(1 shl 14);            { Ask for newscanning upon logon        }
                    369:     NO_EXASCII =(1 shl 15);            { Don't send extended ASCII         }
                    370:     ASK_SSCAN  =(1 shl 16);            { Ask for messages to you at logon  }
                    371:     AUTOTERM   =(1 shl 17);            { Autodetect terminal type                  }
                    372:     COLDKEYS   =(1 shl 18);            { No hot-keys                                           }
                    373:     EXTDESC    =(1 shl 19);            { Extended file descriptions            }
                    374:     AUTOHANG   =(1 shl 20);            { Auto-hang-up after transfer           }
                    375:     WIP                =(1 shl 21);            { Supports WIP terminal emulation       }
                    376:     AUTOLOGON  =(1 shl 22);            { AutoLogon via IP                                      }
                    377: 
                    378: { Bit values for user_chat             }
                    379: const
                    380:     CHAT_ECHO  =(1 shl 0);     { Multinode chat echo                                           }
                    381:     CHAT_ACTION =(1 shl 1);    { Chat actions                                                      }
                    382:     CHAT_NOPAGE =(1 shl 2);    { Can't be paged                            }
                    383:     CHAT_NOACT =(1 shl 3);     { No activity alerts                                            }
                    384:     CHAT_SPLITP =(1 shl 4);    { Split screen private chat                                 }
                    385: 
                    386: { Bits for user_qwk }
                    387: const
                    388:     QWK_FILES  =(1 shl 0);             { Include new files list                        }
                    389:     QWK_EMAIL  =(1 shl 1);             { Include unread e-mail                     }
                    390:     QWK_ALLMAIL =(1 shl 2);            { Include ALL e-mail                            }
                    391:     QWK_DELMAIL =(1 shl 3);            { Delete e-mail after download      }
                    392:     QWK_BYSELF =(1 shl 4);             { Include messages from self            }
                    393:     QWK_UNUSED =(1 shl 5);             { Currently unused                                  }
                    394:     QWK_EXPCTLA =(1 shl 6);            { Expand ctrl-a codes to ascii      }
                    395:     QWK_RETCTLA =(1 shl 7);            { Retain ctrl-a codes                           }
                    396:     QWK_ATTACH =(1 shl 8);             { Include file attachments                  }
                    397:     QWK_NOINDEX =(1 shl 9);            { Do not create index files in QWK  }
                    398:     QWK_TZ             =(1 shl 10);            { Include "@TZ" time zone in msgs   }
                    399:     QWK_VIA    =(1 shl 11);            { Include "@VIA" seen-bys in msgs   }
                    400:     QWK_NOCTRL =(1 shl 12);            { No extraneous control files           }
                    401: 
                    402: {$R *.DFM}
                    403: 
                    404: { Returns total number of users in database }
                    405: function TForm1.LastUser: Integer;
                    406: var Str: AnsiString;
                    407:     f: TFileStream;
                    408: begin
                    409:     Str:=data_dir+'user/user.dat';
                    410:     try
                    411:         f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
                    412:         Result := f.Size div U_LEN;
                    413:         f.Free;
                    414:     except
                    415:         Result := 0;
                    416:     end;
                    417: end;
                    418: 
                    419: procedure SaveChanges;
                    420: begin
                    421:     if Application.MessageBox('Save Changes','User Modified',MB_YESNO)=IDYES
                    422:     then
                    423:         Form1.SaveUserExecute(Form1)
                    424:     else
                    425:         Form1.GetUserData(Form1.ScrollBar.Position);
                    426: end;
                    427: 
                    428: { ************* }
                    429: { GET USER DATA }
                    430: { ************* }
                    431: 
                    432: { Parses a single text data field }
                    433: function GetTextField(buf : PChar; maxlen : Integer): AnsiString;
                    434: var str: AnsiString;
                    435:     len: Integer;
                    436:     term: PChar;
                    437: begin
                    438:     term:=StrScan(buf,ETX);      { Look for end-of-text marker }
                    439:     if term = nil then
                    440:         len:=maxlen   { not found? }
                    441:     else
                    442:         len:=Term-buf;
                    443:     if len > maxlen then len:=maxlen;
                    444:     SetString(str,buf,len);
                    445:     Result:=str;
                    446: end;
                    447: 
                    448: { Get a 16-bit decimal integer field }
                    449: function GetShortIntField(buf : PChar): AnsiString;
                    450: begin
                    451:     Result:=GetTextField(buf,5);
                    452: end;
                    453: 
                    454: { Get a 32-bit decimal integer field }
                    455: function GetLongIntField(buf : PChar): AnsiString;
                    456: begin
                    457:     Result:=GetTextField(buf,10);
                    458: end;
                    459: 
                    460: { Parses a flag field returning string with flag letters and spaces }
                    461: { This function can be used for exemptions and restrictions too }
                    462: function GetFlagsField(buf : PChar): AnsiString;
                    463: var str: AnsiString;
                    464:     flagstr: AnsiString;
                    465:     flags: Integer;
                    466:     i: Integer;
                    467: begin
                    468:     str:='0x'+GetTextField(buf,8);
                    469:     flags:=StrToIntDef(str,0);
                    470:     for i:=0 to 25 do
                    471:         if flags AND (1 shl i) <> 0 then
                    472:             flagstr:=flagstr+Char(65+i)
                    473:         else
                    474:             flagstr:=flagstr+' ';
                    475:     Result:=TrimRight(flagstr);
                    476: end;
                    477: 
                    478: { Get a hexadecimal integer field (of any size) }
                    479: function GetHexField(buf : PChar; maxlen : Integer): Integer;
                    480: var str: AnsiString;
                    481: begin
                    482:     str:='0x'+GetTextField(buf,maxlen);
                    483:     Result:=StrToIntDef(str,0);
                    484: end;
                    485: 
                    486: { Convert a hexadecimal time field (in unix format) to xx/xx/YY }
                    487: function GetDateField(buf : PChar): AnsiString;
                    488: var str: AnsiString;
                    489:     date: TDateTime;
                    490:     time: Integer;
                    491: begin
                    492:     str:='0x'+GetTextField(buf,8);
                    493:     time:=StrToIntDef(str,0);
                    494:     if time=0 then begin
                    495:         Result:='00/00/00';
                    496:         Exit;
                    497:     end;
                    498:     time:=time div (24*60*60);          { convert from seconds to days }
                    499:     date:=EncodeDate(1970,1,1)+time;   { convert to days since 1970 }
                    500:     Result:=DateToStr(date);
                    501: end;
                    502: 
                    503: { Reads a user data record to an Edit box and clears modified flag }
                    504: function GetUserText(Edit: Tedit; buf: PChar; maxlen: Integer) : AnsiString;
                    505: begin
                    506:     Edit.Text:=GetTextField(buf,maxlen);
                    507:     Edit.Tag:=0; { clear modified flag }
                    508:     Edit.MaxLength:=maxlen;
                    509:     Result:=Edit.Text;
                    510: end;
                    511: 
                    512: { Reads a user data record to an Edit box and clears modified flag }
                    513: function GetUserShortInt(Edit: Tedit; buf: PChar) : AnsiString;
                    514: begin
                    515:     GetUserText(Edit,buf,5);
                    516:     Result:=Edit.Text;
                    517: end;
                    518: 
                    519: { Reads a user data record to an Edit box and clears modified flag }
                    520: function GetUserLongInt(Edit: Tedit; buf: PChar) : AnsiString;
                    521: begin
                    522:     GetUserText(Edit,buf,10);
                    523:     Result:=Edit.Text;
                    524: end;
                    525: 
                    526: { Reads and parses a single user record, filling in edit boxes, etc. }
                    527: procedure TForm1.GetUserData(usernumber: Integer);
                    528: var Str: AnsiString;
                    529:     f: TFileStream;
                    530:     buf: array[0..U_LEN] of Char;
                    531: begin
                    532:     { Open file and read user record }
                    533:     Str:=data_dir+'user/user.dat';
                    534:     try
                    535:         f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
                    536:     except
                    537:         Exit;
                    538:     end;
                    539:     f.Seek((usernumber-1)*U_LEN,soFromBeginning);
                    540:     f.Read(buf,U_LEN);
                    541:     f.Free;
                    542: 
                    543:     { ********************** }
                    544:     { Parse user data buffer }
                    545:     { ********************** }
                    546: 
                    547:     { Personal }
                    548:     GetUserText(AliasEdit,buf+U_ALIAS,LEN_ALIAS);
                    549:     GetUserText(NameEdit,buf+U_NAME,LEN_NAME);
                    550:     GetUserText(HandleEdit,buf+U_HANDLE,LEN_HANDLE);
                    551:     GetUserText(ComputerEdit,buf+U_COMP,LEN_COMP);
                    552:     GetUserText(NetMailEdit,buf+U_NETMAIL,LEN_NETMAIL);
                    553:     GetUserText(AddressEdit,buf+U_ADDRESS,LEN_ADDRESS);
                    554:     GetUserText(LocationEdit,buf+U_LOCATION,LEN_LOCATION);
                    555:     GetUserText(NoteEdit,buf+U_NOTE,LEN_NOTE);
                    556:     GetUserText(BirthDateEdit,buf+U_BIRTH,LEN_BIRTH);
                    557:     GetUserText(PasswordEdit,buf+U_PASS,LEN_PASS);
                    558:     GetUserText(ModemEdit,buf+U_MODEM,LEN_MODEM);
                    559:     GetUserText(ZipCodeEdit,buf+U_ZIPCODE,LEN_ZIPCODE);
                    560:     GetUserText(SexEdit,buf+U_SEX,1);
                    561:     GetUserText(PhoneEdit,buf+U_PHONE,LEN_PHONE);
                    562:     GetUserText(CommentEdit,buf+U_COMMENT,LEN_COMMENT);
                    563: 
                    564:     { Settings }
                    565:     GetUserText(RowsEdit,buf+U_ROWS,2);
                    566:     GetUserText(ShellEdit,buf+U_SHELL,8);
                    567:     GetUserText(EditorEdit,buf+U_XEDIT,8);
                    568:     GetUserText(ProtocolEdit,buf+U_PROT,1);
                    569:     GetUserText(TempFileExtEdit,buf+U_TMPEXT,3);
                    570: 
                    571:     { Read 'misc' bit-field }
                    572:     user_misc:=GetHexField(buf+U_MISC,8);
                    573:     ExpertCheckBox.Checked:=user_misc AND EXPERT <> 0;
                    574:     ExpertCheckBox.Tag:=0;
                    575: 
                    576:     TerminalCheckListBox.Checked[0]:=user_misc AND AUTOTERM <> 0;
                    577:     TerminalCheckListBox.Checked[1]:=user_misc AND NO_EXASCII = 0;
                    578:     TerminalCheckListBox.Checked[2]:=user_misc AND ANSI <> 0;
                    579:     TerminalCheckListBox.Checked[3]:=user_misc AND UCOLOR <> 0;
                    580:     TerminalCheckListBox.Checked[4]:=user_misc AND RIP <> 0;
                    581:     TerminalCheckListBox.Checked[5]:=user_misc AND WIP <> 0;
                    582:     TerminalCheckListBox.Checked[6]:=user_misc AND UPAUSE <> 0;
                    583:     TerminalCheckListBox.Checked[7]:=user_misc AND COLDKEYS = 0;
                    584:     TerminalCheckListBox.Checked[8]:=user_misc AND SPIN <> 0;
                    585:     TerminalCheckListBox.Tag:=0;
                    586: 
                    587:     MessageCheckListBox.Checked[0]:=user_misc AND NETMAIL <> 0;
                    588:     MessageCheckListBox.Checked[1]:=user_misc AND CLRSCRN <> 0;
                    589:     MessageCheckListBox.Tag:=0;
                    590: 
                    591:     FileCheckListBox.Checked[0]:=user_misc AND ANFSCAN <> 0;
                    592:     FileCheckListBox.Checked[1]:=user_misc AND EXTDESC <> 0;
                    593:     FileCheckListBox.Checked[2]:=user_misc AND BATCHFLAG <> 0;
                    594:     FileCheckListBox.Checked[3]:=user_misc AND AUTOHANG <> 0;
                    595:     FileCheckListBox.Tag:=0;
                    596: 
                    597:     LogonCheckListBox.Checked[0]:=user_misc AND ASK_NSCAN <> 0;
                    598:     LogonCheckListBox.Checked[1]:=user_misc AND ASK_SSCAN <> 0;
                    599:     LogonCheckListBox.Checked[2]:=user_misc AND CURSUB <> 0;
                    600:     LogonCheckListBox.Checked[3]:=user_misc AND QUIET <> 0;
                    601:     LogonCheckListBox.Checked[4]:=user_misc AND AUTOLOGON <> 0;
                    602:     LogonCheckListBox.Tag:=0;
                    603: 
                    604:     { Read 'QWK' bit-field }
                    605:     user_qwk:=GetHexField(buf+U_QWK,8);
                    606:     QWKCheckListBox.Checked[0]:=user_qwk AND QWK_FILES <> 0;
                    607:     QWKCheckListBox.Checked[1]:=user_qwk AND QWK_EMAIL <> 0;
                    608:     QWKCheckListBox.Checked[2]:=user_qwk AND QWK_ALLMAIL <> 0;
                    609:     QWKCheckListBox.Checked[3]:=user_qwk AND QWK_DELMAIL <> 0;
                    610:     QWKCheckListBox.Checked[4]:=user_qwk AND QWK_BYSELF <> 0;
                    611:     QWKCheckListBox.Checked[5]:=user_qwk AND QWK_EXPCTLA <> 0;
                    612:     QWKCheckListBox.Checked[6]:=user_qwk AND QWK_RETCTLA = 0;
                    613:     QWKCheckListBox.Checked[7]:=user_qwk AND QWK_ATTACH <> 0;
                    614:     QWKCheckListBox.Checked[8]:=user_qwk AND QWK_NOINDEX <> 0;
                    615:     QWKCheckListBox.Checked[9]:=user_qwk AND QWK_TZ <> 0;
                    616:     QWKCheckListBox.Checked[10]:=user_qwk AND QWK_VIA <> 0;
                    617:     QWKCheckListBox.Checked[11]:=user_qwk AND QWK_NOCTRL = 0;
                    618:     QWKCheckListBox.Tag:=0;
                    619: 
                    620:     { Read 'chat' bit-field }
                    621:     user_chat:=GetHexField(buf+U_CHAT,8);
                    622:     ChatCheckListBox.Checked[0]:=user_chat AND CHAT_ECHO <> 0;
                    623:     ChatCheckListBox.Checked[1]:=user_chat AND CHAT_ACTION <> 0;
                    624:     ChatCheckListBox.Checked[2]:=user_chat AND CHAT_NOPAGE = 0;
                    625:     ChatCheckListBox.Checked[3]:=user_chat AND CHAT_NOACT = 0;
                    626:     ChatCheckListBox.Checked[4]:=user_chat AND CHAT_SPLITP <> 0;
                    627:     ChatCheckListBox.Tag:=0;
                    628: 
                    629:     { Initialize controls based on bits set/unset }
                    630:     if user_misc AND DELETED <> 0 then begin
                    631:         Status.Text := 'Deleted User';
                    632:         Status.Color := clRed;
                    633:         end
                    634:     else if user_misc AND INACTIVE <> 0 then begin
                    635:         Status.Text := 'Inactive User';
                    636:         Status.Color := clYellow;
                    637:         end
                    638:     else begin
                    639:         Status.Text := 'Active User';
                    640:         Status.Color := clMenu;
                    641:         end;
                    642: 
                    643:     { Security }
                    644:     GetUserText(LevelEdit,buf+U_LEVEL,2);
                    645:     ExpireEdit.Text:=GetDateField(buf+U_EXPIRE);
                    646:     ExpireEdit.Tag:=0;
                    647:     Flags1Edit.Text:=GetFlagsField(buf+U_FLAGS1);
                    648:     Flags1Edit.Tag:=0;
                    649:     Flags2Edit.Text:=GetFlagsField(buf+U_FLAGS2);
                    650:     Flags2Edit.Tag:=0;
                    651:     Flags3Edit.Text:=GetFlagsField(buf+U_FLAGS3);
                    652:     Flags3Edit.Tag:=0;
                    653:     Flags4Edit.Text:=GetFlagsField(buf+U_FLAGS4);
                    654:     Flags4Edit.Tag:=0;
                    655:     ExemptionsEdit.Text:=GetFlagsField(buf+U_EXEMPT);
                    656:     ExemptionsEdit.Tag:=0;
                    657:     RestrictionsEdit.Text:=GetFlagsField(buf+U_REST);
                    658:     RestrictionsEdit.Tag:=0;
                    659:     GetUserLongInt(CreditsEdit,buf+U_CDT);
                    660:     GetUserLongInt(FreeCreditsEdit,buf+U_FREECDT);
                    661:     GetUserLongInt(MinutesEdit,buf+U_MIN);
                    662: 
                    663:     { Stats }
                    664:     FirstOnEdit.Text:=GetDateField(buf+U_FIRSTON);
                    665:     FirstOnEdit.Tag:=0;
                    666:     LastOnEdit.Text:=GetDateField(buf+U_LASTON);
                    667:     LastOnEdit.Tag:=0;
                    668:     GetUserShortInt(LogonsEdit,buf+U_LOGONS);
                    669:     GetUserShortInt(LogonsTodayEdit,buf+U_LTODAY);
                    670:     GetUserShortInt(TimeOnEdit,buf+U_TIMEON);
                    671:     GetUserShortInt(LastCallTimeEdit,buf+U_TLAST);
                    672:     GetUserShortInt(TimeOnTodayEdit,buf+U_TTODAY);
                    673:     GetUserShortInt(ExtraTimeEdit,buf+U_TEXTRA);
                    674:     GetUserShortInt(PostsTotalEdit,buf+U_POSTS);
                    675:     GetUserShortInt(PostsTodayEdit,buf+U_PTODAY);
                    676:     GetUserShortInt(EmailTotalEdit,buf+U_EMAILS);
                    677:     GetUserShortInt(EmailTodayEdit,buf+U_ETODAY);
                    678:     GetUserShortInt(FeedbackEdit,buf+U_FBACKS);
                    679:     GetUserShortInt(UploadedFilesEdit,buf+U_ULS);
                    680:     GetUserLongInt(UploadedBytesEdit,buf+U_ULB);
                    681:     GetUserShortInt(DownloadedFilesEdit,buf+U_DLS);
                    682:     GetUserLongInt(DownloadedBytesEdit,buf+U_DLB);
                    683:     LeechEdit.Text:=IntToStr(GetHexField(buf+U_LEECH,2));
                    684: 
                    685:     { etc... }
                    686: 
                    687:     { Extended Comment }
                    688:     Memo.Lines.Clear();
                    689:     Str:=data_dir+Format('USER/%.4d.MSG',[usernumber]);
                    690:     if FileExists(Str) then Memo.Lines.LoadFromFile(Str);
                    691:     Memo.Tag:=0;
                    692: 
                    693:     { Update User Number }
                    694:     NumberEdit.Text:=IntToStr(ScrollBar.Position);
                    695:     SaveUser.Enabled:=false;   { no changes have been made yet }
                    696: end;
                    697: 
                    698: { ************* }
                    699: { PUT USER DATA }
                    700: { ************* }
                    701: 
                    702: { Encodes a single text data field (of any length) }
                    703: procedure PutTextField(buf : PChar; str : AnsiString; maxlen : Integer);
                    704: var len:Integer;
                    705:     i:Integer;
                    706: begin
                    707:     for i:=0 to maxlen-1 do buf[i]:=ETX;
                    708:     len:=Length(str);
                    709:     if len > maxlen then len:=maxlen;
                    710:     for i:=0 to len-1 do buf[i]:=str[i+1];
                    711: end;
                    712: 
                    713: { Encodes a flag field (A-Z) into a 32-bit Hex string }
                    714: procedure PutFlagsField(buf : PChar; str : AnsiString);
                    715: var flags: Integer;
                    716:     i:Integer;
                    717: begin
                    718:     flags:=0;
                    719:     for i:=0 to 25 do
                    720:         if Pos(Chr(65+i),str) <> 0 then
                    721:             flags:=flags OR (1 shl i);
                    722:     PutTextField(buf,IntToHex(flags,8),8);
                    723: end;
                    724: 
                    725: { Converts a date string in xx/xx/YY format into a unix time_t format in hex }
                    726: procedure PutDateField(buf : PChar; str : AnsiString);
                    727: var val: Integer;
                    728: begin
                    729:     { convert to days since 1970 }
                    730:     try
                    731:         val:=Round(StrToDate(str)-EncodeDate(1970,1,1));
                    732:     except
                    733:         val:=0;
                    734:     end;
                    735:     if val < 0 then val:=0;
                    736:     { convert from days to seconds }
                    737:     val:=val*(24*60*60);
                    738:     PutTextField(buf,IntToHex(val,8),8);
                    739: end;
                    740: 
                    741: { Writes to a 16-bit decimal integer field }
                    742: procedure PutShortIntField(buf : PChar; str : AnsiString);
                    743: begin
                    744:     PutTextField(buf, str, 5);
                    745: end;
                    746: 
                    747: { Writes to a 32-bit decimal integer field }
                    748: procedure PutLongIntField(buf : PChar; str : AnsiString);
                    749: begin
                    750:     PutTextField(buf, str, 10);
                    751: end;
                    752: 
                    753: { Writes to a hexadecimal integer field (of any length) }
                    754: procedure PutHexField(buf : PChar; val : Integer; maxlen : Integer);
                    755: begin
                    756:     PutTextField(buf,IntToHex(val,maxlen),maxlen);
                    757: end;
                    758: 
                    759: { Writes a user Edit box's contents to the buffer, if changed, resets Tag }
                    760: procedure PutUserText(Edit:Tedit; buf:PChar; maxlen:Integer);
                    761: begin
                    762:     if Edit.Tag = 1 then    { field modified, change record }
                    763:         PutTextField(buf,Edit.Text,maxlen);
                    764:     Edit.Tag:=0; { clear modified flag }
                    765: end;
                    766: 
                    767: { Writes a flag Edit box's contents to the buffer, if changed }
                    768: { This function can be used for exemptions and restrictions too }
                    769: procedure PutUserFlags(Edit:Tedit; buf:PChar);
                    770: begin
                    771:     if Edit.Tag = 1 then { field modified, change record }
                    772:         PutFlagsField(buf,Edit.Text);
                    773:     Edit.Tag:=0; { clear modified flag }
                    774: end;
                    775: 
                    776: { Writes a 16-bit integer Edit box's contents to the buffer, if changed }
                    777: procedure PutUserShortInt(Edit:Tedit; buf:PChar);
                    778: begin
                    779:     if Edit.Tag = 1 then { field modified, change record }
                    780:         PutTextField(buf,Edit.Text,5);
                    781:     Edit.Tag:=0; { clear modified flag }
                    782: end;
                    783: 
                    784: { Writes a 32-bit integer Edit box's contents to the buffer, if changed }
                    785: procedure PutUserLongInt(Edit:Tedit; buf:PChar);
                    786: begin
                    787:     if Edit.Tag = 1 then { field modified, change record }
                    788:         PutTextField(buf,Edit.Text,10);
                    789:     Edit.Tag:=0; { clear modified flag }
                    790: end;
                    791: 
                    792: { Writes a date Edit box's contents to the buffer, if changed }
                    793: procedure PutUserDate(Edit:Tedit; buf:PChar);
                    794: begin
                    795:     if Edit.Tag = 1 then { field modified, change record }
                    796:         PutDateField(buf,Edit.Text);
                    797:     Edit.Tag:=0; { clear modified flag }
                    798: end;
                    799: 
                    800: function SetBit(set_it: bool; field: Cardinal; bit: Cardinal): Cardinal;
                    801: begin
                    802:     if set_it then
                    803:        Result:=field OR bit    { set bit }
                    804:     else
                    805:         Result:=field AND NOT bit;  { clear bit }
                    806: end;
                    807: 
                    808: { Writes a complete user record. }
                    809: procedure TForm1.PutUserData(usernumber:Integer);
                    810: var Str: AnsiString;
                    811:     f: TFileStream;
                    812:     i: Integer;
                    813:     buf: array[0..U_LEN] of Char;
                    814: begin
                    815:     if AliasEdit.Tag = 1 then begin
                    816:         { Set-up buffer for NAME.DAT record }
                    817:         if user_misc AND DELETED <> 0 then
                    818:             PutTextField(buf,'',LEN_ALIAS)
                    819:         else
                    820:             PutTextField(buf,AliasEdit.Text,LEN_ALIAS);
                    821:         buf[LEN_ALIAS]:=CR;
                    822:         buf[LEN_ALIAS+1]:=LF;
                    823: 
                    824:         { Open NAME.DAT write user name }
                    825:         Str:=data_dir+'USER/NAME.DAT';
                    826:         if FileExists(Str) then
                    827:             f:=TFileStream.Create(Str,fmOpenWrite or fmShareExclusive)
                    828:         else
                    829:             f:=TFileStream.Create(Str,fmCreate or fmShareExclusive);
                    830:         f.Seek((usernumber-1)*(LEN_ALIAS+2),soFromBeginning);
                    831:         f.Write(buf,LEN_ALIAS+2);
                    832:         f.Free;
                    833:     end;
                    834: 
                    835:     { Initialize USER record buffer }
                    836:     for i:=0 to U_LEN-1 do buf[i]:=ETX;
                    837: 
                    838:     { Open file and read current user record }
                    839:     Str:=data_dir+'user/user.dat';
                    840:     if FileExists(Str) then
                    841:         f:=TFileStream.Create(Str,fmOpenReadWrite or fmShareExclusive)
                    842:     else
                    843:         f:=TFileStream.Create(Str,fmCreate or fmShareExclusive);
                    844: 
                    845:     f.Seek((usernumber-1)*U_LEN,soFromBeginning);
                    846:     f.Read(buf,U_LEN);
                    847: 
                    848:     { Update changed fields }
                    849:     PutUserText(AliasEdit,buf+U_ALIAS,LEN_ALIAS);
                    850:     PutUserText(NameEdit,buf+U_NAME,LEN_NAME);
                    851:     PutUserText(HandleEdit,buf+U_HANDLE,LEN_HANDLE);
                    852:     PutUserText(ComputerEdit,buf+U_COMP,LEN_COMP);
                    853:     PutUserText(NetMailEdit,buf+U_NETMAIL,LEN_NETMAIL);
                    854:     PutUserText(AddressEdit,buf+U_ADDRESS,LEN_ADDRESS);
                    855:     PutUserText(LocationEdit,buf+U_LOCATION,LEN_LOCATION);
                    856:        PutUserText(NoteEdit,buf+U_NOTE,LEN_NOTE);
                    857:     PutUserText(ZipCodeEdit,buf+U_ZIPCODE,LEN_ZIPCODE);
                    858:     PutUserText(PasswordEdit,buf+U_PASS,LEN_PASS);
                    859:     PutUserText(PhoneEdit,buf+U_PHONE,LEN_PHONE);
                    860:     PutUserText(BirthDateEdit,buf+U_BIRTH,LEN_BIRTH);
                    861:     PutUserText(ModemEdit,buf+U_MODEM,LEN_MODEM);
                    862:     PutUserText(SexEdit,buf+U_SEX,1);
                    863:     PutUserText(CommentEdit,buf+U_COMMENT,LEN_COMMENT);
                    864:     { etc. }
                    865: 
                    866:     { Settings }
                    867:     PutUserText(RowsEdit,buf+U_ROWS,2);
                    868:     PutUserText(ShellEdit,buf+U_SHELL,8);
                    869:     PutUserText(EditorEdit,buf+U_XEDIT,8);
                    870:     PutUserText(ProtocolEdit,buf+U_PROT,1);
                    871:     PutUserText(TempFileExtEdit,buf+U_TMPEXT,3);
                    872: 
                    873:     { Write MISC bit-field}
                    874:     if (ExpertCheckBox.Tag = 1)
                    875:         or (LogonCheckListBox.Tag = 1)
                    876:         or (TerminalCheckListBox.Tag = 1)
                    877:         or (MessageCheckListBox.Tag = 1)
                    878:         or (FileCheckListBox.Tag = 1)
                    879:         then begin
                    880:         user_misc:=SetBit(ExpertCheckBox.Checked, user_misc, EXPERT);
                    881: 
                    882:         { TerminalCeckListBox }
                    883:         user_misc:=SetBit(TerminalCheckListBox.Checked[0],user_misc,AUTOTERM);
                    884:         user_misc:=SetBit(NOT TerminalCheckListBox.Checked[1],user_misc,NO_EXASCII);
                    885:         user_misc:=SetBit(TerminalCheckListBox.Checked[2],user_misc,ANSI);
                    886:         user_misc:=SetBit(TerminalCheckListBox.Checked[3],user_misc,UCOLOR);
                    887:         user_misc:=SetBit(TerminalCheckListBox.Checked[4],user_misc,RIP);
                    888:         user_misc:=SetBit(TerminalCheckListBox.Checked[5],user_misc,WIP);
                    889:         user_misc:=SetBit(TerminalCheckListBox.Checked[6],user_misc,UPAUSE);
                    890:         user_misc:=SetBit(NOT TerminalCheckListBox.Checked[7],user_misc,COLDKEYS);
                    891:         user_misc:=SetBit(TerminalCheckListBox.Checked[8],user_misc,SPIN);
                    892: 
                    893:         { MessageCheckListBox }
                    894:         user_misc:=SetBit(MessageCheckListBox.Checked[0],user_misc,NETMAIL);
                    895:         user_misc:=SetBit(MessageCheckListBox.Checked[1],user_misc,CLRSCRN);
                    896: 
                    897:         { FileCheckListBox }
                    898:         user_misc:=SetBit(FileCheckListBox.Checked[0],user_misc,ANFSCAN);
                    899:         user_misc:=SetBit(FileCheckListBox.Checked[1],user_misc,EXTDESC);
                    900:         user_misc:=SetBit(FileCheckListBox.Checked[2],user_misc,BATCHFLAG);
                    901:         user_misc:=SetBit(FileCheckListBox.Checked[3],user_misc,AUTOHANG);
                    902: 
                    903:         { LogonCheckListBox }
                    904:         user_misc:=SetBit(LogonCheckListBox.Checked[0],user_misc,ASK_NSCAN);
                    905:         user_misc:=SetBit(LogonCheckListBox.Checked[1],user_misc,ASK_SSCAN);
                    906:         user_misc:=SetBit(LogonCheckListBox.Checked[2],user_misc,CURSUB);
                    907:         user_misc:=SetBit(LogonCheckListBox.Checked[3],user_misc,QUIET);
                    908:         user_misc:=SetBit(LogonCheckListBox.Checked[4],user_misc,AUTOLOGON);
                    909: 
                    910:         PutHexField(buf+U_MISC, user_misc, 8);
                    911:         end;
                    912: 
                    913:     if (ChatCheckListBox.Tag = 1) then begin
                    914:         user_chat:=SetBit(ChatCheckListBox.Checked[0],user_chat,CHAT_ECHO);
                    915:         user_chat:=SetBit(ChatCheckListBox.Checked[1],user_chat,CHAT_ACTION);
                    916:         user_chat:=SetBit(NOT ChatCheckListBox.Checked[2],user_chat,CHAT_NOPAGE);
                    917:         user_chat:=SetBit(NOT ChatCheckListBox.Checked[3],user_chat,CHAT_NOACT);
                    918:         user_chat:=SetBit(ChatCheckListBox.Checked[4],user_chat,CHAT_SPLITP);
                    919: 
                    920:         PutHexField(buf+U_CHAT, user_chat, 8);
                    921:         end;
                    922: 
                    923:     if (QWKCheckListBox.Tag =1) then begin
                    924:         user_qwk:=SetBit(QWKCheckListBox.Checked[0],user_qwk,QWK_FILES);
                    925:         user_qwk:=SetBit(QWKCheckListBox.Checked[1],user_qwk,QWK_EMAIL);
                    926:         user_qwk:=SetBit(QWKCheckListBox.Checked[2],user_qwk,QWK_ALLMAIL);
                    927:         user_qwk:=SetBit(QWKCheckListBox.Checked[3],user_qwk,QWK_DELMAIL);
                    928:         user_qwk:=SetBit(QWKCheckListBox.Checked[4],user_qwk,QWK_BYSELF);
                    929:         user_qwk:=SetBit(QWKCheckListBox.Checked[5],user_qwk,QWK_EXPCTLA);
                    930:         user_qwk:=SetBit(NOT QWKCheckListBox.Checked[6],user_qwk,QWK_RETCTLA);
                    931:         user_qwk:=SetBit(QWKCheckListBox.Checked[7],user_qwk,QWK_ATTACH);
                    932:         user_qwk:=SetBit(QWKCheckListBox.Checked[8],user_qwk,QWK_NOINDEX);
                    933:         user_qwk:=SetBit(QWKCheckListBox.Checked[9],user_qwk,QWK_TZ);
                    934:         user_qwk:=SetBit(QWKCheckListBox.Checked[10],user_qwk,QWK_VIA);
                    935:         user_qwk:=SetBit(NOT QWKCheckListBox.Checked[11],user_qwk,QWK_NOCTRL);
                    936: 
                    937:         PutHexField(buf+U_QWK, user_qwk, 8);
                    938:         end;
                    939: 
                    940:     { Security }
                    941:     PutUserText(LevelEdit,buf+U_LEVEL,2);
                    942:     PutUserDate(ExpireEdit,buf+U_EXPIRE);
                    943:     PutUserFlags(Flags1Edit,buf+U_FLAGS1);
                    944:     PutUserFlags(Flags2Edit,buf+U_FLAGS2);
                    945:     PutUserFlags(Flags3Edit,buf+U_FLAGS3);
                    946:     PutUserFlags(Flags4Edit,buf+U_FLAGS4);
                    947:     PutUserFlags(ExemptionsEdit,buf+U_EXEMPT);
                    948:     PutUserFlags(RestrictionsEdit,buf+U_REST);
                    949:     PutUserLongInt(CreditsEdit,buf+U_CDT);
                    950:     PutUserLongInt(FreeCreditsEdit,buf+U_FREECDT);
                    951:     PutUserLongInt(MinutesEdit,buf+U_MIN);
                    952:     { etc. }
                    953: 
                    954:     { Stats }
                    955:     PutUserDate(FirstOnEdit,buf+U_FIRSTON);
                    956:     PutUserDate(LastOnEdit,buf+U_LASTON);
                    957:     PutUserShortInt(LogonsEdit,buf+U_LOGONS);
                    958:     PutUserShortInt(LogonsTodayEdit,buf+U_LTODAY);
                    959:     PutUserShortInt(TimeOnEdit,buf+U_TIMEON);
                    960:     PutUserShortInt(TimeOnTodayEdit,buf+U_TTODAY);
                    961:     PutUserShortInt(LastCallTimeEdit,buf+U_TLAST);
                    962:     PutUserShortInt(ExtraTimeEdit,buf+U_TEXTRA);
                    963:     PutUserShortInt(PostsTotalEdit,buf+U_POSTS);
                    964:     PutUserShortInt(PostsTodayEdit,buf+U_PTODAY);
                    965:     PutUserShortInt(EmailTotalEdit,buf+U_EMAILS);
                    966:     PutUserShortInt(EmailTodayEdit,buf+U_ETODAY);
                    967:     PutUserShortInt(FeedbackEdit,buf+U_FBACKS);
                    968:     PutUserShortInt(UploadedFilesEdit,buf+U_ULS);
                    969:     PutUserLongInt(UploadedBytesEdit,buf+U_ULB);
                    970:     PutUserShortInt(DownloadedFilesEdit,buf+U_DLS);
                    971:     PutUserLongInt(DownloadedBytesEdit,buf+U_DLB);
                    972:     PutHexField(buf+U_LEECH, StrToIntDef(LeechEdit.Text,0), 2);
                    973:     { etc. }
                    974: 
                    975:     { Write user record and close file }
                    976:     f.Seek((usernumber-1)*U_LEN,soFromBeginning);
                    977:     f.Write(buf,U_LEN);
                    978:     f.Free;
                    979: 
                    980:     { Extended Comemnt }
                    981:     if Memo.Tag = 1 then begin
                    982:         Str:=data_dir+Format('USER/%.4d.MSG',[usernumber]);
                    983:         if Memo.Lines.Count<>0 then
                    984:             Memo.Lines.SaveToFile(Str)
                    985:         else
                    986:             DeleteFile(Str);
                    987:     end;
                    988: 
                    989:     SaveUser.Enabled:=false;
                    990: end;
                    991: 
                    992: { ********* }
                    993: { MAIN FORM }
                    994: { ********* }
                    995: 
                    996: { There's probably a better place to do this init stuff... constructor? }
                    997: procedure TForm1.FormShow(Sender: TObject);
                    998: begin
                    999: 
                   1000:     { Over-ride Locale settings here }
                   1001:     DateSeparator:='/';
                   1002: 
                   1003:     if (ShortDateFormat = 'M/d/yy')
                   1004:        or (ShortDateFormat = 'M/d/yyyy')
                   1005:        or (ShortDateFormat = 'MM/dd/yy')
                   1006:        or (ShortDateFormat = 'MM/dd/yyyy')
                   1007:        then
                   1008:         ShortDateFormat:='mm/dd/yy'     { American }
                   1009:     else
                   1010:         ShortDateFormat:='dd/mm/yy';    { European }
                   1011: 
                   1012:     data_dir:=ParamStr(1);
                   1013: {    if Length(data_dir)=0 then data_dir:='.\'; }
                   1014: 
                   1015:     users:=LastUser();
                   1016: 
                   1017:     if users = 0 then   { Create user if none exist }
                   1018:         users:=1;
                   1019: 
                   1020:     ScrollBar.Min:=1;
                   1021:     ScrollBar.Max:=users;
                   1022:     TotalStaticText.Caption:='of '+IntToStr(users);
                   1023:     { *********************************** }
                   1024:     { Set max lengths for edit boxes here }
                   1025:     { *********************************** }
                   1026:     { Personal }
                   1027:     AliasEdit.MaxLength:=LEN_ALIAS;
                   1028:     NameEdit.MaxLength:=LEN_NAME;
                   1029:     PhoneEdit.MaxLength:=LEN_PHONE;
                   1030:     HandleEdit.MaxLength:=LEN_HANDLE;
                   1031:     ComputerEdit.MaxLength:=LEN_COMP;
                   1032:     AddressEdit.MaxLength:=LEN_ADDRESS;
                   1033:     LocationEdit.MaxLength:=LEN_LOCATION;
                   1034:     ZipCodeEdit.MaxLength:=LEN_ZIPCODE;
                   1035:     ModemEdit.MaxLength:=LEN_MODEM;
                   1036:     CommentEdit.MaxLength:=LEN_COMMENT;
                   1037:     { Security }
                   1038:     PasswordEdit.MaxLength:=LEN_PASS;
                   1039:     PhoneEdit.MaxLength:=LEN_PHONE;
                   1040:     ModemEdit.MaxLength:=LEN_MODEM;
                   1041:     SexEdit.MaxLength:=1;
                   1042:     { Stats }
                   1043:     { etc. }
                   1044: 
                   1045:     ScrollBar.Position:=StrToIntDef(ParamStr(2),1);
                   1046:     GetUserData(ScrollBar.Position);
                   1047: 
                   1048:     PageControl.ActivePage:=PersonalTabSheet;
                   1049: end;
                   1050: 
                   1051: { Change user }
                   1052: procedure TForm1.ScrollBarChange(Sender: TObject);
                   1053: begin
                   1054:     if SaveUser.Enabled then SaveChanges();
                   1055:     users:=LastUser(); { this could change dynamically }
                   1056:     ScrollBar.Max:=users;
                   1057:     TotalStaticText.Caption:='of '+IntToStr(users);
                   1058:     GetUserData(ScrollBar.Position);
                   1059: end;
                   1060: 
                   1061: { Better than on OnChange event, waits til users hits enter key }
                   1062: procedure TForm1.NumberEditKeyPress(Sender: TObject; var Key: Char);
                   1063: var val : Integer;
                   1064: begin
                   1065:     if Key <> #13 then Exit;
                   1066:     users:=lastuser;
                   1067:     val:=StrToIntDef(NumberEdit.Text,0);
                   1068:     if (val = 0) or (val > users) then
                   1069:         NumberEdit.Text:=IntToStr(ScrollBar.Position)
                   1070:     else begin
                   1071:         ScrollBar.Position:=val;
                   1072:         GetUserData(val);
                   1073:         Key:=#0;
                   1074:     end
                   1075: end;
                   1076: 
                   1077: procedure TForm1.FileExitMenuItemClick(Sender: TObject);
                   1078: begin
                   1079:     Close;
                   1080: end;
                   1081: 
                   1082: { OnChange event for ALL User Data Edit boxes }
                   1083: procedure TForm1.EditChange(Sender: TObject);
                   1084: begin
                   1085:     SaveUser.Enabled:=true;
                   1086:     (Sender as TComponent).Tag:=1;   { Mark as modified }
                   1087: end;
                   1088: 
                   1089: { Create a New User record }
                   1090: procedure TForm1.SaveUserExecute(Sender: TObject);
                   1091: begin
                   1092:     PutUserData(StrToIntDef(NumberEdit.Text,ScrollBar.Position));
                   1093: end;
                   1094: 
                   1095: procedure TForm1.NewUserExecute(Sender: TObject);
                   1096: begin
                   1097:     if SaveUser.Enabled then SaveChanges();
                   1098: 
                   1099:     { New users's number }
                   1100:     users:=lastuser()+1;
                   1101: 
                   1102:     { Initialize fields to default values }
                   1103:     AliasEdit.Text:='New User';
                   1104:     AliasEdit.Tag := 1;
                   1105:     LevelEdit.Text:='10';
                   1106:     LevelEdit.Tag :=1;
                   1107:     FirstOnEdit.Text:=DatetoStr(Date);
                   1108:     FirstOnEdit.Tag :=1;
                   1109:     LastOnEdit.Text:=DateToStr(Date);
                   1110:     LastOnEdit.Tag :=1;
                   1111:     TerminalCheckListBox.Checked[0] := true; // AUTOTERM
                   1112:     TerminalCheckListBox.Checked[1] := true; // EXASCII
                   1113:     TerminalCheckListBox.Checked[2] := true; // ANSI
                   1114:     TerminalCheckListBox.Checked[3] := true; // COLOR
                   1115:     TerminalCheckListBox.Checked[6] := true; // UPAUSE
                   1116:     TerminalCheckListBox.Checked[7] := true; // HOTKEYS
                   1117:     FileCheckListBox.Checked[2] := true;    // BATCHFLAG
                   1118:     LogonCheckListBox.Tag:=1;
                   1119: 
                   1120:     { Create the new record }
                   1121:     PutUserData(users);
                   1122: 
                   1123:     { Set scroll bar and usernumber text }
                   1124:     ScrollBar.Max:=users;
                   1125:     ScrollBar.Position:=users;
                   1126:     NumberEdit.Text:=IntToStr(users);
                   1127: 
                   1128: end;
                   1129: 
                   1130: procedure TForm1.DeleteUserExecute(Sender: TObject);
                   1131: begin
                   1132:     user_misc:=user_misc xor DELETED;
                   1133:     LogonCheckListBox.Tag:=1;   { flag as modified }
                   1134:     AliasEdit.Tag := 1;
                   1135:     PutUserData(ScrollBar.Position);
                   1136:     GetUserData(ScrollBar.Position);
                   1137: end;
                   1138: 
                   1139: procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
                   1140: begin
                   1141:     if SaveUser.Enabled then SaveChanges();
                   1142: end;
                   1143: 
                   1144: procedure TForm1.DeactivateUserExecute(Sender: TObject);
                   1145: begin
                   1146:     user_misc:=user_misc xor INACTIVE;
                   1147:     LogonCheckListBox.Tag:=1;   { flag as modified }
                   1148:     PutUserData(ScrollBar.Position);
                   1149:     GetUserData(ScrollBar.Position);
                   1150: end;
                   1151: 
                   1152: procedure TForm1.FindButtonClick(Sender: TObject);
                   1153: var Str: AnsiString;
                   1154:     SearchStr: AnsiString;
                   1155:     f: TFileStream;
                   1156:     usernumber: Integer;
                   1157:     buf: array[0..U_LEN] of Char;
                   1158: begin
                   1159:     SearchStr:=AnsiUpperCase(FindEdit.Text);
                   1160:     usernumber:=0;
                   1161:     { Open USER.DAT to search for string }
                   1162:     Str:=data_dir+'user/user.dat';
                   1163:     if not FileExists(Str) then Exit;
                   1164:     f:=TFileStream.Create(Str,fmOpenRead or fmShareDenyNone);
                   1165:     if Sender = FindNextButton then
                   1166:         f.Seek((ScrollBar.Position)*(U_LEN),soFromBeginning);
                   1167:     while (f.Position < f.Size) and (usernumber=0) do begin
                   1168:         f.Read(buf,U_LEN);
                   1169:         SetString(Str,buf,U_LEN);
                   1170:         Str:=AnsiUpperCase(Str);
                   1171:         if Pos(SearchStr,Str) <> 0 then
                   1172:             usernumber:=f.Position div (U_LEN);
                   1173:         end;
                   1174:     f.Free;
                   1175:     if usernumber <> 0 then begin
                   1176:         ScrollBar.Position:=usernumber;
                   1177:         end;
                   1178: end;
                   1179: 
                   1180: procedure TForm1.FindEditKeyPress(Sender: TObject; var Key: Char);
                   1181: begin
                   1182:     if Key = #13 then begin
                   1183:         FindButtonClick(Sender);
                   1184:         Key:=#0;
                   1185:     end;
                   1186: end;
                   1187: 
                   1188: end.

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.