/************************************************ ** Chatroom for MBCI Students ** Coded by Travis Smith ** Restrictions are present on the following: ** Names cannot contain: > < / \ ( ) ** Names restricted to users: Travis - 05MB390 ** Justin - 05MB301 ** ** Moderation commands limited to admins ** Functionality limited to students ** Teachers who attempt to use this program will recieve an error message ** ** All functionality can be disabled at any time ** ** Added in 1.9x: ** Username Detection works flawlessly ** Minor logging changes ** Last logon recorded ** ** Added in 1.8x: ** Screen name registration ** Still case sensitive ** Encrypted Username/Password encryption ** Logging of all logins for monitoring purposes ** ** ** Admins: ** 05MB390 Travis ** 05MB301 ** 05MB330 ** 05MB355 ** 05MB361 ** 05MB336 David ************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include void Register(); void GetUserName(); void Intro(); void stagger(String &S); void AddSelf(void); void RemoveSelf(void); void GetLastLogon(); #pragma startup GetLastLogon 68 #pragma startup Intro 69 #pragma startup AddSelf 70 //perform startup operations and add name to user list #pragma exit RemoveSelf //remove self from the user list void RemoveTemps() { struct ffblk ffblk; int done; String name; done = findfirst("*.tmp",&ffblk,FA_DIREC); while (!done) { name=ffblk.ff_name; remove(name.c_str()); done = findnext(&ffblk); } } String hash(String S) { long Num; unsigned char ch; String New=""; for (int i=0; i='a') && (S[Letter]<='z')) S[Letter]=S[Letter]-'a'+'A'; return S; } //-------------------------------- //------------------------------------------------------------------------------ void wait1() /* similar to wait() but without the keypressed condition */ { long curr_time; curr_time = biostime(0, 0L); while (biostime(0, 0L)<=curr_time) ; //do nothing } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void stagger(String &S) /* Send a string to cout letter by letter */ { for (int i=0; i<=S.length();i++) { cout << S.substr(i, 1); wait1(); } } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ String EnterPass(String &S) { int Sentinel; String Total; char Character; char BackSpace='\b'; char Enter='\r'; do{ Character=getch(); cout << "*"; /*backspace checking - complete*/ if ((Character==BackSpace) & Total.length()>0) { cout << BackSpace << BackSpace; String Sub=(Total.substr(Total.length(), 1)); Total = (Total.substr(0, (Total.length()-1))); Total+=Sub; } else if ((Character==BackSpace) & Total.length()<1) { cout << BackSpace; } /*'enter' checking - complete*/ else if ((Character==Enter) & (Total.length()==0)){ cout << BackSpace << endl; Character=BackSpace; } else if ((Character==Enter) & (Total.length()>0)){ cout << BackSpace; break; } else Total+=Character; }while((Character != Enter)); cout << endl; S=Total; return S; } /* Universal Variables */ String ver="1.91"; //current version String LastLogon="never"; String UserName=""; //Novell Login Name String Last; //Last message added to chat window int Line; //current send line for AddChat() String Name; //user selected screen name int SendLines; int Gag=0; //Gag check variable. Default=0 int Obs=0; //Observer Variable, not yet in effect int Admin; //Admin Variable. Default=0 long curr_time = biostime(0, 0L); //Time Variable String Total="05MB390 05MB301 05MB330 05MB355 05MB361 05MB336"; //-------------------------------- //-------------------------------- void wait() /*Delay no longer differs based on processor speed*/ /*Delay is based on the curr_time variable to control rate program checks at*/ { long curr_Time = biostime(0, 0L); while (biostime(0, 0L)<=curr_Time+7 & (!kbhit())) //if the selected amount of time has not passed and a key was not pressed ; //do nothing curr_Time = biostime(0, 0L); } //-------------------------------- void waitshort() /*Delay no longer differs based on processor speed*/ /*Delay is based on the curr_time variable to control rate program checks at*/ { long curr_Time = biostime(0, 0L); while (biostime(0, 0L)<=curr_Time & (!kbhit())) //if the selected amount of time has not passed and a key was not pressed ; //do nothing curr_Time = biostime(0, 0L); } //-------------------------------- void Info(String UserName, String ver, int Admin) /* Version, UserName, and command information displayed to user as requested from their access level*/ { /* Normal User */ if (UserName.length()>0) { cout << "\nCommand -- Functionality -- Usage\n" << "--User commands \n" << " /users -- lists all people in chat -- /users\n" << " /me -- emote text -- /me says hi\n" << " /emote -- emote text -- /emote says hi\n" << " /code -- encrypt your message -- /code hello\n" << " /exit -- close chat\n" << " /quit -- close chat\n"; } /* Administrator */ if (Admin==1) { cout << "\n--Admin Commands\n" << " /unban -- unbans all banned users -- /unban\n" << " /ban -- ban's 's Login Name (Permanent) -- /ban 05MB390\n" << " /getuser -- displays 's login name -- /getuser Travis\n" << " /gag -- disable from talking -- /gag Tom\n" << " /ungag -- allow to talk again -- /ungag Tom\n" << " /kick -- kick user from chat (Temporary) -- /kick Morgan\n"; } /* Owner */ if (UserName=="05MB390") { cout << "\n--Owner commands\n"; cout << " /abort override -- shut down entire chat\n"; cout << " /force -- Force a server message -- /force AAAA!!!\n"; } cout << "Press Any Key To Continue."; getch(); } //-------------------------------- void Intro() { GetUserName(); cout << "Chat "; waitshort(); cout << "Room "; waitshort(); cout << ver; waitshort(); cout << " By Travis Smith \n"; waitshort(); cout << "-- You are "; waitshort(); cout << UserName << "\n"; cout << "-- Your last logon was " << LastLogon << "\n"; cout << "Attempting to connect to server...\n"; wait(); cout << "Connection successfully established!\n"; wait(); cout << "Error: Authorization Required!\n"; wait(); Register(); cout << "Encrypting Data...\n"; wait(); wait(); cout << "Sending Login Information...\n"; wait();wait(); cout << "Receiving Data...\n"; wait(); wait(); cout << "Login Accepted\n"; wait(); cout << "Loading Chat Room "; wait();wait();wait();wait(); clrscr(); } //-------------------------------- void Register() { GetUserName(); String Password, Guess; char choice; FILE *Reg; //START Start: stagger("Enter Name: "); getline(cin, Name); //---- if (Name.length()>20) { cout << "Error: Invalid Name!\n"; goto Start; } if (Name.find("Travis")!=npos & UserName!="05MB390"){ cout << "Error: Invalid Name!\n"; goto Start; } if (Name.find("<")!=npos | Name.find(">")!=npos | Name.find("\\")!=npos | Name.find("/")!=npos | Name.find("(")!=npos | Name.find(")")!=npos){ cout << "Error: Invalid Name!\n"; goto Start; } //-- /*Check availability*/ String FName, FPass; ifstream Read("DB.dat", ios::in); while (getline(Read, FName)) { if (Name==unhash(FName)) { getline(Read, FName); Password=unhash(FName); goto Password; } getline(Read, FName); //skip password } Read.close(); //REGISTER Register: stagger("Error: This name does not exist!\n" "Would you like to register it (Y/N)? "); cin >> choice; switch (choice) { case 'y': case 'Y': break; default: cin.ignore(100, '\n'); goto Start; } cout << "Enter requested password: "; EnterPass(Password); Reg=fopen("db.dat", "a+"); Name=hash(Name); Password=hash(Password); fprintf(Reg, "%s\n%s\n", Name.c_str(), Password.c_str()); fclose(Reg); Name=unhash(Name); Password=unhash(Password); goto End; //PASSWORD Password: stagger("Name Verified.\nEnter Pass: "); EnterPass(Guess); if (Guess==Password) { stagger("Password Verified.\n"); goto End; } stagger("Error: Incorrect Password!\n"); goto Start; //END End: } //-------------------------------- void GetUserName(void) /* Function does a directory search in the C:\Documents and Settings folder for any folder containing "MB" and uses it as the Login Name Teacher logins do not contain "MB" and consequently return a blank value allowing for identification of staff, allowing according action. ***EDIT*** Borland C++ Builder 6 used to detect username through a Windows API function Username transferred to text file for reading ********** */ { _dos_setfileattr("H:/UserName.dat", _A_HIDDEN); /* struct ffblk ffblk; int done; String name; done = findfirst("C:\\DOCUME~1\\*",&ffblk,FA_DIREC); while (!done) { name=ffblk.ff_name; if (name.find("MB")!=npos & UserName=="") { UserName=name; } done = findnext(&ffblk); }*/ fstream InFile("H:/UserName.dat", ios::in); getline(InFile, UserName); UserName=Uppercase(UserName); if (UserName.length()==4) { //if teacher (4 characters) username is found, abort program stagger("Error: Unable to detect student username!\nYou cannot use this program unless you are a student."); abort(); } } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- int BanUser(String &ToBan) /* Sends 's Login Name to banned.dat */ { String S; int Ban=1; if (Total.find(ToBan)!=npos & UserName!="05MB390") { //if name to ban is an admin, deny rights Ban=0; gotoxy(1, Line); cout << "Error: You cannot ban an administrator!"; Line++; } if (Total.find(ToBan)==npos){ //if allowed, send login name to banned.dat FILE *BanUser=fopen("Banned.dat", "a+"); fprintf(BanUser, "%s", hash(ToBan).c_str()); fclose(BanUser); return 1; //retu } } //-------------------------------- //-------------------------------- //-------------------------------- void UnBanUser(String &Name) /* Unbans all users who have been banned */ { remove("banned.dat"); } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- void SendChat(String S, int Event) /* SendChat is the heart of the program. Messages are sent based on usernames and event flags. Every "/" command has it's own event, and each is handled differently in the manipulation of the message. Following is an index of said events. */ /************************* ** EVENT INDEX ** -------------------- ** 0=Normal message ** 1=Join/Leave ** 2=List Users ** 3=Emote ** 4=Abort ** 5=Code ** 6=Ban ** 7=Unban ** 8=Blank ** 9=Quit ** 10=Gag ** 11=UnGag ** 12=Unchanged Message ** 13=Kick ** 14=Forced message **************************/ { String Temp, Temp2; int Banned; /* Event /quit | /exit */ if (Event==9){ RemoveSelf(); abort(); } /* Event /abort override */ if (Event==4) { ofstream ShutDown("control.txt", ios::out); ShutDown << "1"; ShutDown.close(); } String ToSend; cout.setf(ios::left); cout.precision(80); /* Event Enter | Exit */ if (Event==1) ToSend=S; /* Event /users */ else if (Event==2) { ifstream Read("users.dat", ios::nocreate); gotoxy(1, Line); while (getline(Read, S)){ cout << "-- " << S << " is in the chat\n"; Line++; getline(Read, S); } Read.close(); } /* Event /me | /emote */ else if (Event==3) { ToSend=""; if (Admin==1) ToSend+="<"; if (Admin==0) ToSend+="*"; ToSend+=Name; ToSend+=S.substr(S.find(" "), S.length()); if (Admin==1) ToSend+=">"; if (Admin==0) ToSend+="*"; } /* Event /code */ else if (Event==5) { ToSend=""; if (Admin==1) ToSend+="<"; ToSend+=Name; if (Admin==1) ToSend+="> "; if (Admin==0) ToSend+=": "; ToSend+=hash(S.substr(6, S.length()-6)); } /* Event no "/" command */ else { //---- Event==0 ToSend=""; if (Admin==1) ToSend+="<"; if (UserName=="05MB390") ToSend="("; ToSend+=Name; if (Admin==1 & UserName!="05MB390") ToSend+="> "; if (UserName=="05MB390") ToSend+=") "; if (Admin==0) ToSend+=": "; ToSend+=S; } /* Event /gag */ if (Event==10) { ToSend="User.Gag: "; ToSend+=S.substr(5, S.length()-5); } /* Event /ungag */ if (Event==11) { ToSend="User.UnGag: "; ToSend+=S.substr(7, S.length()-7); } /* Event /abort override */ if (Event==4) ToSend="Program has been de-activated.\n"; /* Event /ban */ if (Event==6) { Banned=BanUser(S); if (Banned==1){ ToSend=S; ToSend+=" has been banned from chat."; } if (Banned==-1) { ToSend=S; ToSend+=" cannot be banned."; } if (S.find("MB")==npos) ToSend="Error: Invalid name."; gotoxy(1, 21); clreol(); gotoxy(80, 21); cout << "="; } /* Event /unban */ if (Event==7) { UnBanUser(S); ToSend="All users have been unbanned."; } /* Event /kick */ if (Event==13) { ToSend="User.Kick: "; ToSend+=S.substr(6, S.length()-6); } /* Event message sent from program */ if (Event==12) ToSend=S; /* Event /force */ if (Event==14) ToSend=S.substr(7, S.length()-7); /* Condition: Event!=8 */ /* Condition: User is not gagged */ /* Event: Send message to Chat.box based on previous event modifiers */ if (Event!=8) { fstream Write("Chat.Box", ios::out); Write << ToSend.c_str(); Write.close(); } } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- void AddChat() { String S, ToSend; if (biostime(0, 0L)>=curr_time+10) { gotoxy(1, Line); fstream ReadText("Chat.Box", ios::in); getline(ReadText, S); ReadText.close(); if (S!=Last) { //gag checking if (S.find("User.Gag: ")!=npos) { //if gag cmd found if (S.find(Name)!=npos & Admin==0) { //if your name is found Gag=1; //enable gag mode cout << "You have been gagged"; //display confirmation } if (S.find(Name)!=npos & Admin==1) { //if you are an admin and someone tries to gag you cout << "Someone tried to gag you!"; //display error SendChat("Error: You cannot gag an administrator", 12); //send error } else cout << S.substr(10, S.length()-10) << " has been gagged."; //else, send confirmation } if (S.find("User.UnGag: ")!=npos) { //if ungag cmd found if (S.find(Name)!=npos) { //if your name is found Gag=0; //disable gag mode cout << "You have been ungagged"; //disable confirmation } else cout << S.substr(12, S.length()-12) << " has been ungagged."; //other confirmation } //end gag checking //start kick checking if (S.find("User.Kick: ")!=npos) { //if kick cmd found if (S.find(Name)!=npos & Admin==0) { //if your name is found RemoveSelf(); //remove yourself from active users cout << "You have been kicked out of the channel!"; //display confirmation abort(); //shut down app window } if (S.find(Name)!=npos & Admin==1) { //if you are an admin and someone tries to gag you cout << "Someone tried to kick you!"; //display error SendChat("Error: You cannot kick an administrator", 12); //send error } else cout << S.substr(10, S.length()-10) << " has been kicked out of the channel."; //else, send confirmation } //end kick checking if (S.substr(0, 5)!=("User.")) //if gag and kick cmds not found cout << S << endl; //display line if (S.length()>80) { Line++; } Last=S; Line++; } curr_time = biostime(0, 0L); } } //---------- void AddLast() { String S; gotoxy(1, 1); fstream ReadText("Chat.Box", ios::in); while (getline(ReadText, S)) { cout << S << endl; Last=S; Line=1; Line++; } ReadText.close(); } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- void RemoveSelf(void) { String ToSend, S, Total; ToSend="-- "; ToSend+=Name; ToSend+=" has left the chat room"; SendChat(ToSend, 1); fstream DelMe("users.dat", ios::in|ios::out); while (getline(DelMe, S)) { if (S!=Name) { Total+=S; Total+="\n"; } if (S==Name) { getline(DelMe, S); } } DelMe.close(); remove("users.dat"); DelMe.open("users.dat", ios::out); DelMe << Total; DelMe.close(); } // // // // // void Check(void) { ifstream check; check.open("control.txt", ios::nocreate); String S; getline(check, S); if (S=="1") { check.close(); RemoveSelf(); abort(); } else { check.close(); } //check for ban check.open("banned.dat", ios::in); while (getline(check, S)) { if (unhash(S)==UserName) { check.close(); for (unsigned int i=0; i<=64000; i++) { gotoxy(random(80)+1, random(19)+1); cout << random(2); i++; } gotoxy(15, 1); cout << " "; gotoxy(15, 2); cout << " You have been banned "; gotoxy(15, 3); cout << " "; RemoveSelf(); abort(); } } } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- void AddSelf(void) { struct date d; getdate(&d); struct time t; gettime(&t); String S, N, Flags; GetUserName(); ifstream Read1("users.dat", ios::in); while (getline(Read1, S)){ getline(Read1, S); if (S==UserName) abort(); } Read1.close(); Admin=0; if (UserName=="05MB390") Admin=1; if (UserName=="05MB330") Admin=1; if (UserName=="05MB355") Admin=1; if (UserName=="05MB361") Admin=1; if (UserName=="05MB336") Admin=1; Check(); Line=1; String JoinMSG="-- "; Info(UserName, ver, Admin); if (UserName=="05MB390") cout << "\nYou Are An Owner"; if (Admin==1) cout << "\nYou Are An Admin"; if (Admin==0 & UserName.length()>0) cout << "\nYou Are A Normal User"; cout << endl; Read1.open("users.dat", ios::in); while (getline(Read1, S)){ getline(Read1, S); if (S==UserName) abort(); } Read1.close(); clrscr(); JoinMSG+=Name; JoinMSG+=" has joined the chat room with flags: "; if (Admin==1) Flags="Admin"; if (Admin==0 & Gag==0) Flags="Normal User"; if (UserName=="05MB390") Flags="Owner"; if (UserName=="") Flags="Observer"; JoinMSG+=Flags; SendChat(JoinMSG, 1); FILE *AddMe=fopen("Users.dat", "a+"); fprintf(AddMe, "%s\n%s\n", Name.c_str(), UserName.c_str()); fclose(AddMe); AddChat(); ifstream Read("users.dat", ios::nocreate); gotoxy(1, 2); while (getline(Read, S)){ cout << "-- " << S << " is in the chat\n"; Line++; getline(Read, S); } Read.close(); /////////////////////////////////////////////////////////////////////////////////////////// FILE *stream=fopen("Totals.txt", "a+"); fprintf(stream, "[%02d/%02d/%04d %02d:%02d:%02d] %s (%s) Logged On -- Version %s\n", d.da_day, d.da_mon, d.da_year, t.ti_hour, t.ti_min, t.ti_sec, Name.c_str(), UserName.c_str(), ver.c_str()); fclose(stream); } //-------------------------------- void GetLastLogon() { struct date d; getdate(&d); struct time t; gettime(&t); fstream GetLogonTime("H:/Logon.$", ios::in); getline(GetLogonTime, LastLogon); GetLogonTime.close(); if (LastLogon.length()<1) LastLogon="Not Recorded"; /* chsize example */ int handle; handle = open("H:/Logon.$", O_TRUNC); /* truncate the file to 0 bytes in size */ chsize(handle, 0); /* close the file */ close(handle); FILE *LogonTime=fopen("H:/Logon.$", "w+"); fprintf(LogonTime, "%02d:%02d:%02d %02d/%02d/%04d", t.ti_hour, t.ti_min, t.ti_sec, d.da_day, d.da_mon, d.da_year); fclose(LogonTime); _dos_setfileattr("H:/Logon.$", _A_HIDDEN); } //-------------------------------- //-------------------------------- //-------------------------------- //-------------------------------- int main() { int Event=0; String ToSend, S; int i; char KeyPressed, ch='_'; idle: gotoxy(1, 20); cout << "================================================================================\r\n"; gotoxy(1, 22); cout << "================================================================================\r\n"; gotoxy(80, 21); cout << "="; gotoxy(1, 21); while (true) { while (!kbhit()) { if (Line>=19) { clrscr(); AddLast(); gotoxy(1, 20); cout << "================================================================================\r\n"; gotoxy(1, 21); cout << ToSend; gotoxy(1, 22); cout << "================================================================================\r\n"; gotoxy(80, 21); cout << "="; gotoxy(1, 21); Line=2; } AddChat(); Check(); wait(); } KeyPressed=getch(); switch (KeyPressed) { case '`': break; case '\r': if (ToSend.substr(0, 6)=="/users") Event=2; if (ToSend.substr(0, 3)=="/me") Event=3; if (ToSend.substr(0, 6)=="/emote") Event=3; if (ToSend.substr(0, 15)=="/abort override" & UserName=="05MB390") Event=4; if (ToSend.substr(0, 5)=="/code") Event=5; if (ToSend.substr(0, 4)=="/ban" & (Admin==1)) { ToSend=ToSend.substr(5, ToSend.length()-5); ToSend=Uppercase(ToSend); gotoxy(1, 21); cout << " "; Event=6; } if(ToSend.substr(0, 6)=="/unban" & (Admin==1)) { ToSend=ToSend.substr(7, ToSend.length()-7); gotoxy(1, 21); cout << " "; Event=7; } if (ToSend.substr(0, 8)=="/getuser" & Admin==1) { ifstream Read("users.dat", ios::nocreate); while (getline(Read, S)){ if (S.find(ToSend.substr(9, ToSend.length()-9))!=npos) { getline(Read, S); gotoxy(1, Line); cout << "Login Name for " << ToSend.substr(9, ToSend.length()-9) << ": " << S; Line++; } } Read.close(); Event=8; //show nothing } if (ToSend.substr(0, 5)=="/exit") Event=9; if (ToSend.substr(0, 5)=="/quit") Event=9; if (ToSend.substr(0, 4)=="/gag" & Admin==1) Event=10; if (ToSend.substr(0, 6)=="/ungag" & Admin==1) Event=11; if (ToSend.substr(0, 5)=="/kick" & Admin==1) Event=13; if (ToSend.substr(0, 6)=="/force" & UserName=="05MB390") Event=14; //------ if (Gag==1 & Admin==0) Event=8; SendChat(ToSend, Event); Event=0; gotoxy(1, 21); for (i=0; i