/* Fuse-Linux 0.1 Copyright (C) 2002 Tim Hentenaar This program is free software; you can redistribute it and/or modify\n" it under the terms of the GNU General Public License as published by\n" the Free Software Foundation; either version 2 of the License, or\n" (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* This is the public Alpha Release. It uses a simple shell-like interface. * I may implement a GUI using wxWindows.. I tried GTK+ but it dosen't work out * like i want it to. * I realize that some of this dosen't work, but it's a start. * - Tim */ #include #include #include #include #include #include #include #include #include #include #define PACKET_SIZE 1460 /* Maximum Packet Size */ struct profile_t { /* Store data from our USEROBJECT (I got most of the lengths from the DB) */ char username[16]; char password[11]; char email[61]; char figure[11]; /* I'm not sure what this is used for */ char sex[2]; /* m | f */ char address[41]; /* Address */ char city[31]; char state[20]; char zip[7]; char age[3]; /* 1 or 2 digits */ char fName[25]; /* First name */ char lName[41]; /* Last Name */ char phone[16]; char customData[255]; /* Custom Data */ }; char *version_id = "all"; bool secure_conn = false; unsigned int sock; struct profile_t profile; struct profile_t our_profile; char username[16]; char password[11]; char sbuffer[PACKET_SIZE+1]; char rbuffer[PACKET_SIZE+1]; bool loggedin = false; bool sentlogin = false; bool registered = false; bool nostatus = false; bool connected = true; sockaddr_in addr; char *server; int port; hostent *r_host; char xbuffer[100]; /* for other tasks :P */ int bytesread; char prompt[50]; char cmdbuf[1000]; int DecodeSecretKey(char *key) { int ki = 1; int x = 0; int z = 0; int a = 0; char *s = key; char *w; w = strtok(s," "); x = atoi(w); if (x < 10000) z += x + (ki % 5); ki++; while(w = strtok(NULL," ")) { if (w != NULL) { x = atoi(w); if (x < 10000) z += x + (ki % 5); ki++; } } double f = 1000.0 * sin((double)z); if (f < 0.0) f += 0.5; else f -= 0.5; int checksum = (int)ceil(f); return checksum; } void sighandle(int signum) { /* signal handler */ if(sock) close(sock); fprintf(stderr,"Exiting due to signal(%d)\n",signum); exit(1); } void sendFuseMsg(char *type, char *msg) { memset(sbuffer,'\0',sizeof(sbuffer)); // sprintf(sbuffer,"# %s \r %s \r##",type,msg); // Client recieves in this form sprintf(sbuffer,"%d %s %s",strlen(type)+strlen(msg),type,msg); send(sock,sbuffer,strlen(sbuffer),0); printf("C-> %s\n",sbuffer); } char *mkProfileData(struct profile_t pro) { // Used for REGISTER, UPDATE (USEROBJECT) char probuf[sizeof(profile_t)+110]; /* the field names are 109 bytes */ memset(probuf,'\0',sizeof(probuf)); sprintf(probuf,"name=%s\rpassword=%s\remail=%s\rfigure=%s\raddress=%s\rage=%s\rzipcode=%s\rfirstName=%s\rpostLocation=%s\rlastName=%s\rphoneNumber=%s\rcustomData=%s\r",pro.username,pro.password,pro.email,pro.figure,pro.address,pro.age,pro.zip,pro.fName,pro.city,pro.lName,pro.phone,pro.customData); char *probufp = probuf; return probufp; } void doRegister() { memset(&profile,0x20,sizeof(profile)); /* pad with spaces rather than nulls */ if (!registered) printf("Fill in the following:\n"); /* Using strncpy() to guard against an obvious overflow */ strncpy(profile.username,username,strlen(username)); strncpy(profile.password,password,strlen(password)); char ubuf[256]; memset(ubuf,0,sizeof(ubuf)); printf("Enter your Email: "); fgets(ubuf,sizeof(profile.email),stdin); strncpy(profile.email,ubuf,strlen(ubuf)-1); /* Take out \n */ memset(ubuf,0,sizeof(ubuf)); printf("Enter your Age: "); fgets(ubuf,sizeof(profile.age),stdin); strncpy(profile.age,ubuf,strlen(ubuf)-1); /* Take out \n */ memset(ubuf,0,sizeof(ubuf)); printf("Enter your First Name: "); fgets(ubuf,sizeof(profile.fName),stdin); strncpy(profile.fName,ubuf,strlen(ubuf)-1); /* Take out \n */ memset(ubuf,0,sizeof(ubuf)); printf("Enter your Last Name: "); fgets(ubuf,sizeof(profile.lName),stdin); strncpy(profile.lName,ubuf,strlen(ubuf)-1); /* Take out \n */ memset(ubuf,0,sizeof(ubuf)); printf("Enter User Text: "); fgets(ubuf,sizeof(profile.customData),stdin); strncpy(profile.customData,ubuf,strlen(ubuf)-1); /* Take out \n */ memset(ubuf,0,sizeof(ubuf)); char *profile_buf = mkProfileData(profile); if (!registered){ sendFuseMsg("REGISTER",profile_buf); registered = true; } else { sendFuseMsg("UPDATE",profile_buf); } } void shellAcceptCommand() { /* Output the prompt and wait for a command */ char *r, *s, *t; memset(prompt,'\0',sizeof(prompt)); sprintf(prompt,"[%s@fuse:%s] ",username,server); printf("%s",prompt); usleep(10); fgets(cmdbuf,sizeof(cmdbuf),stdin); /* parse the command */ if (strstr(cmdbuf,"help server")) printf("server - Connect to a FUSE Light Server\n\nserver [servername] [port]\n\n"); else if (strstr(cmdbuf,"help login")) printf("login - Login to a FUSE Light Server\n\nlogin [username] [password]\n\n"); else if (strstr(cmdbuf,"help chat")) printf("chat - Chat with another user\n\nchat [user1],[user2],[user3],... [message]\n\n"); else if (strstr(cmdbuf,"help toall")) printf("toall - Broadcast a message to all users\n\ntoall [message]\n\n"); // else if (strstr(cmdbuf,"help profile")) printf("profile - Get a user's profile\n\nprofile [username]\n\n"); else if (strstr(cmdbuf,"help update")) printf("update [username] [password] - Update profile\n\nupdate \n\n"); else if (strstr(cmdbuf,"help register")) printf("register [username] [password] - Register as a new user\n\nregister \n\n"); // else if (strstr(cmdbuf,"help")) printf("Commands:\n\thelp\tlogin\tserver\n\tchat\ttoall\tprofile\n\texit\tupdate\tregister\n\nType \"help command\" for info on an individual command.\n\n"); else { r = strtok(cmdbuf, " "); if (strstr(r,"server")) { r = strtok(NULL, " "); /* server */ s = strtok(NULL," "); /* port */ if (sock) close(sock); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == -1) { fprintf(stderr,"connect(): Invalid Socket.\n"); exit(1); } addr.sin_family = AF_INET; addr.sin_port = htons(atoi(s)); r_host = gethostbyname(r); /* resolve server */ if (!r_host) { fprintf(stderr,"gethostbyname(): Unable to resolve %s!\n",server); if (sock) close(sock); exit(1); } /* assign IP address to addr */ memcpy(&addr.sin_addr.s_addr, r_host->h_addr, r_host->h_length); /* Reuse the socket */ int yes=1; if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) { fprintf(stderr,"setsockopt(): returned -1!\n"); exit(1); } /* Non-blocking */ unsigned long block = 1; // ioctl(sock,FIONBIO,&block); /* connect */ connect(sock, (struct sockaddr *)&addr,sizeof(addr)); printf("Connected!\n"); connected = true; loggedin = false; registered = false; } else if (strstr(r,"login")) { if (!connected) { printf("You're not connected.\n"); } else { /* Login */ char *u = strtok(NULL," "); char *p = strtok(NULL," "); strncpy(username,u,strlen(u)); strncpy(password,p,strlen(p)); sprintf(xbuffer,"%s %s",username+strlen(username)-2,password+strlen(password)-2); sendFuseMsg("LOGIN",xbuffer); sentlogin = true; } } else if (strstr(r,"chat")) { r = strtok(NULL, " "); /* Userlist */ s = strtok(NULL, " "); /* Message */ char b[1000]; memset(b,0,sizeof(b)); sprintf(b,"/%s/CHAT/%s",r,s); sendFuseMsg("BROADCASTTO",b); } else if (strstr(r,"toall")) { r = strtok(NULL, " "); /* Message */ char b[1000]; memset(b,0,sizeof(b)); sprintf(b,"/TOALL/%s",r); sendFuseMsg("BROADCASTALL",b); } else if (strstr(r,"profile")) { printf("profile: not implimented yet!\n"); } else if (strstr(r,"update") || strstr(r, "register")) { char *u = strtok(NULL," "); char *p = strtok(NULL," "); strncpy(username,u,strlen(u)); strncpy(password,p,strlen(p)); doRegister(); } else if (strstr(r,"exit")) { close(sock); exit(0); } else if (strlen(r) > 1) printf("Commands:\n\thelp\tlogin\tserver\n\tchat\ttoall\tprofile\n\texit\tupdate\tregister\n\nType \"help command\" for info on an individual command.\n\n"); } } void doShell() { memset(cmdbuf,'\0',sizeof(cmdbuf)); memset(prompt,'\0',sizeof(prompt)); sprintf(prompt,"[%s@fuse:%s] ",username,server); if (!nostatus) { printf("FUSE-Linux Shell 1.0\n(C) 2002 Tim Hentenaar \nLicensed under the GNU General Public License\n"); nostatus = true; } shellAcceptCommand(); } int main(int argc, char **argv) { /* Set up signal handling */ signal(SIGHUP, SIG_IGN); signal(SIGPIPE, SIG_IGN); signal(SIGQUIT, sighandle); signal(SIGTERM, sighandle); signal(SIGSEGV, sighandle); signal(SIGKILL, sighandle); /* Print intro message */ printf("Fuse-Linux 0.1\n" "Copyright (C) 2002 Tim Hentenaar\n\n" "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2 of the License, or\n" "(at your option) any later version.\n\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n\n" ); /* Clear the buffers */ memset(rbuffer,'\0',sizeof(rbuffer)); memset(sbuffer,'\0',sizeof(sbuffer)); while(true) { /* Main Loop */ if (connected) { bytesread = recv(sock,rbuffer,sizeof(rbuffer),0); printf("S-> %s\n",rbuffer); /* for debugging */ if (bytesread > 0) { if (strstr(rbuffer,"STATUS")) { sendFuseMsg("STATUSOK"," "); } else if (strstr(rbuffer,"SECRET_KEY")) { char y[50]; char *x = strstr(rbuffer,"SECRET_KEY")+strlen("SECRET_KEY"); sprintf(y,"%d",DecodeSecretKey(x)); printf("DecodeSecretKey() = %d\n",DecodeSecretKey(x)); sendFuseMsg("KEYENCRYPTED", y); memset(y,'\0',sizeof(y)); sendFuseMsg("VERSIONCHECK",version_id); secure_conn = true; } else if (strstr(rbuffer,"ERROR")) { /* you can add error handling code here */ fprintf(stderr,"ERROR: %s\n",rbuffer+5); } else if (strstr(rbuffer,"USEROBJECT")) { /* get the data and organize it into a profile_t * then set the current profile to the new one * if the username matches ours */ char data_string[sizeof(profile_t)+110]; /* shouldn't be any longer than this */ memset(data_string,'\0',sizeof(data_string)); char *d = strtok(rbuffer+11,","); char *da; /* This should allways be first */ strncpy(profile.username,d+5, strlen(d) - 5); while ((d = strtok(NULL,",")) != NULL) { if (strstr(d,"password=")) strncpy(profile.password,d+9,strlen(d) - 9); else if (strstr(d,"email=")) strncpy(profile.email,d+6,strlen(d) - 6); else if (strstr(d,"figure=")) strncpy(profile.figure,d+7,strlen(d) - 7); else if (strstr(d,"address=")) strncpy(profile.address,d+8,strlen(d) - 8); else if (strstr(d,"age=")) strncpy(profile.age,d+4,strlen(d) - 4); else if (strstr(d,"zip=")) strncpy(profile.zip,d+4,strlen(d) - 4); else if (strstr(d,"firstName=")) strncpy(profile.age,d+10,strlen(d) - 10); else if (strstr(d,"postLocation=")) strncpy(profile.city,d+13,strlen(d) - 13); else if (strstr(d,"lastName=")) strncpy(profile.lName,d+9,strlen(d) - 9); else if (strstr(d,"phoneNumber=")) strncpy(profile.phone,d+12,strlen(d) - 12); else if (strstr(d,"customData=")) strncpy(profile.customData,d+10,strlen(d) - 10); } } else if (strstr(rbuffer,"OK")) { if (!registered) { printf("Registration sucessful!\n"); registered = true; } else if (!loggedin) { loggedin = true; /* server sends OK after login */ printf("User %s logged in!\n",username); } } else if (strstr(rbuffer,"TOALL")) { char *d = strtok(rbuffer," "); /* # */ d = strtok(NULL," "); /* CHAT\rMSG*/ d = strtok(NULL,"\r"); /*CHAT*/ d = strtok(NULL,"##"); /* MSG */ printf("\ntoall: %s\n",d); } else { sendFuseMsg("STATUSOK"," "); printf("impliment: %s\n",rbuffer); } } } doShell(); } close(sock); return 0; }