telnet._pike
Go to the documentation of this file.
1 /* Copyright (C) 2000-2004 Thomas Bopp, Thorsten Hampel, Ludger Merkens
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * $Id: telnet.pike,v 1.2 2009/05/04 19:16:48 astra Exp $
18  */
19 inherit "/net/coal/login";
20 inherit "/net/base/readline";
21 inherit "/net/base/cmd";
22 #include <macros.h>
23 #include <config.h>
24 #include <database.h>
25 #include <events.h>
26 #include <client.h>
27 #include <attributes.h>
28 #include <classes.h>
29 class telnet : public login,readline,cmd{
30 public:
31 
32 
33 
34 
35 
36 #define MODE_CONNECT 0
37 #define MODE_LOGIN 1
38 #define MODE_PASS 2
39 #define MODE_CMD 3
40 #define MODE_MORE_INPUT 4
41 
42  int iMode;
43 mapping mMode= ([ "cmd":0 ]);
44  int passwdtries;
45  object tmpUser;
46  int iCreate;
47  mapping(string:string) mCreate = ([]);
48 
49 void create(object f)
50 {
51  ::create(f);
52  iMode = MODE_CONNECT;
53 }
54 
55 /**
56  * creates an new user and activates him. adduser is called in Mode_Create several times.
57  */
58 int cmd_adduser(string cmd, string|void args)
59 {
60  if (iMode == MODE_CMD) {
61  iMode = MODE_MORE_INPUT;
62  iCreate = 1;
63  mCreate["name"] = args;
64  send_message("Weitere Daten werden zum Anlegen des Nutzers \"" + args + "\" benötigt.\n");
65  send_message("Passwort des Nutzers:");
66  } else {
67  switch (iCreate) {
68  case 0:
69  mCreate["name"] = args;
70  iCreate = 1;
71  send_message("Passwort des Nutzers:");
72  break;
73  case 1:
74  mCreate["pw"] = cmd;
75  iCreate = 2;
76  send_message("E-Mail des Nutzers:");
77  break;
78  case 2:
79  mCreate["email"] = cmd;
80  LOG("now fetching factory\n");
81  object factory = _Server->get_factory(CLASS_USER);
82  LOG("Now executing factory\n");
83  object user = factory->execute(mCreate);
84  LOG("Factory executed");
85  if (user == 0) {
86  send_message("Ein Fehler ist aufgetreten. Nutzer wurde nicht angelegt\n");
87  } else {
88  LOG("Now activating user.\n");
89  if (user->activate_user(factory->get_activation())) {
90  send_message("Nutzer wurde angelegt und aktiviert.\n");
91  } else {
92  send_message("Nutzer wurde angelegt, aber nicht aktiviert!\n");
93  }
94  }
95  iMode = MODE_CMD;
96  iCreate = 0;
97  break;
98  }
99  }
100  return 1;
101 }
102 
103 void addlink(object to)
104 {
105  mapping (string:object) mName = ([]);
106  mName["link_to"] = to;
107  object factory = _Server->get_factory(CLASS_LINK);
108  object link = factory->execute(mName);
109  if (link == 0) {
110  send_message("Ein Fehler ist aufgetreten. Der Link konnte nicht angelegt werden.\n");
111  } else {
112  send_message("Der Link wurde angelegt. Seine ID ist " + link->get_object_id() );
113  }
114 
115 }
116 
117 void create_object(string type, string name)
118 {
119  mixed err;
120  object newobject;
121  mapping (string:string) mName = ([]);
122  mName["name"] = name;
123  object factory = _Server->get_factory(type);
124  if(!factory)
125  {
126  send_message("Es gibt keine Klasse vom typ '"+type+"'.\n");
127  return;
128  }
129  err = catch{ newobject = factory->execute(mName); };
130  if (newobject == 0)
131  {
132  send_message("Ein Fehler ist aufgetreten. Das Objekt konnte nicht angelegt werden:\n"+err[0]+"\n");
133  LOG(sprintf("%O", err));
134  }
135  else
136  {
137  send_message("Das Objekt wurde angelegt. Seine ID ist " + newobject->get_object_id() );
138  newobject->move(oUser->get_environment());
139  }
140 }
141 
142 
143 /**
144  * Shows the inventory of the given object
145  * grouped by the object classes
146  *
147  * @param object obj - the target object
148  * @return the inventory formatted as string
149  */
150 protected:
151  string show_inventory(object obj) {
152  string res = "";
153 
154  // NOT COMPLETE !(see also "classes.h")
155  mapping classes_names = ([ CLASS_USER:CLASS_NAME_USER,
156  CLASS_OBJECT:CLASS_NAME_OBJECT,
157  CLASS_CONTAINER:CLASS_NAME_CONTAINER,
158  CLASS_ROOM:CLASS_NAME_ROOM,
159  CLASS_DOCUMENT:CLASS_NAME_DOCUMENT,
160  CLASS_LINK:CLASS_NAME_LINK,
161  CLASS_GROUP:CLASS_NAME_GROUP,
162  CLASS_EXIT:CLASS_NAME_EXIT,
163  CLASS_IMAGE:"Image",
164  CLASS_MESSAGEBOARD:"Messageboard",
165  CLASS_GHOST:CLASS_NAME_GHOST,
166  CLASS_TRASHBIN:CLASS_NAME_TRASHBIN,
167  /*,CLASS_SHADOW:"Shadow"*/ ]);
168 
169  int flag = 0;
170  int counter = 0;
171 
172  if (arrayp(obj->get_inventory())) {
173  res = res +"\nThis is the inventory of "
174  + obj->get_identifier() +":\n";
175  res += "----------------------------------------------------\n";
176  foreach (indices(classes_names), int cl) {
177  array inventory_class =
178  obj->get_inventory_by_class(cl);
179  flag = 0;
180 
181  if (arrayp(inventory_class) && sizeof(inventory_class)>0) {
182  res += " " + classes_names[cl] +":\n";
183  foreach (inventory_class, object inv_obj) {
184  counter++;
185  string ident = inv_obj->get_identifier();
186  int id = inv_obj->get_object_id();
187  if (flag!=0)
188  res += ", \n";
189  res += sprintf (" %s[%d]", ident, id);
190  flag = 1;
191  }
192  res += "\n\n";
193  }
194  }
195  if (counter == 0)
196  res += "\n No objects in the inventory.\n";
197  }
198  else
199  res = res +"\""+obj->get_identifier()+"\" has no inventory.\n";
200 
201  return res;
202 }
203 
204 public:
205 
206 
207 protected:
208  void send_room(object room)
209 {
210  if ( objectp(room) ) {
211  send_message(
212  "[#"+room->get_object_id() + ","+_FILEPATH->object_to_filename(room)+"]\n"+
213  "You are in a large area called " + room->get_identifier() + ".\n"+
214  "There are the following exits:\n");
215  array inv = room->get_inventory();
216  foreach(inv, object o) {
217  if ( o->get_object_class() & CLASS_EXIT )
218  send_message(o->get_identifier()+",");
219  }
220  send_message("\nThere are the following people:\n");
221  array users = room->get_inventory_by_class(CLASS_USER);
222  foreach(users, object u) {
223  send_message(u->get_identifier()+",");
224  }
225  send_message("\n");
226  }
227  else {
228  send_message("You are in the big black void.\n");
229  }
230 }
231 
232 public:
233 
234 protected:
235  void enter_room(object room, void|object from)
236 {
237  if ( objectp(from) )
238  oUser->dispose_event(EVENT_SAY|EVENT_LEAVE_INVENTORY|EVENT_ENTER_INVENTORY, from);
239 
240  oUser->listen_to_event(EVENT_SAY, room);
241  oUser->listen_to_event(EVENT_LEAVE_INVENTORY, room);
242  oUser->listen_to_event(EVENT_ENTER_INVENTORY, room);
243 }
244 
245 public:
246 
247 void notify(int event, mixed ... args)
248 {
249  LOG("SAY: "+sprintf("%O\n", args));
250  object user = this_user();
251  LOG("oUser="+sprintf("%O", oUser));
252  LOG("user="+sprintf("%O", user));
253  if ( !objectp(oUser) || !objectp(user) )
254  return;
255  LOG("sending event response !");
256 
257  switch(event) {
258  case EVENT_TELL:
259  send_message(user->get_identifier() + " tells you: " + args[2]+"\n");
260  break;
261  case EVENT_SAY:
262  if ( user == oUser )
263  send_message("You say: "+args[2]+"\n");
264  else
265  send_message(user->get_identifier() + " says: "+args[2]+"\n");
266  break;
267  case EVENT_ENTER_INVENTORY:
268  if ( args[1] == oUser ) {
269  send_message("You move to " + args[0]->get_identifier()+"\n");
270  }
271  else {
272  send_message(args[1]->get_identifier() + " enters the room.\n");
273  send_message("%O:%O\n", args[1]->get_status(), args[1]->get_status()& CLIENT_FEATURES_MOVE);
274  }
275  break;
276  case EVENT_LEAVE_INVENTORY:
277  send_message(args[1]->get_identifier() + " leaves the room.\n");
278  break;
279  }
280 }
281 
282 int cmd_delete(string cmd, string args)
283 {
284  int id;
285  sscanf(args,"#%i",id);
286 
287  object oTmp=find_object(id);
288  if (objectp(oTmp))
289  {
290  mixed err = catch { oTmp->delete(); };
291  if (err!=0) send_message("Failed to delete Object #"+id+"\r\n");
292  else send_message("Deleted Object #"+id+"\r\n");
293  }
294  else send_message("Unable to find Object #"+id+"\r\n");
295  return 1;
296 }
297 
298 int cmd_take(string cmd, string args)
299 {
300  int id;
301  sscanf(args,"#%i",id);
302 
303  object oTmp=find_object(id);
304  if (objectp(oTmp))
305  {
306  mixed err = catch { oTmp->move(oUser); };
307  if (err!=0) send_message("Cannot take object #"+id+"\r\n");
308  else send_message("Object #"+id+" is now in your inventory!\r\n");
309  }
310  else send_message("Can't find Object #"+id+"\r\n");
311  return 1;
312 }
313 
314 int cmd_drop(string cmd, string args)
315 {
316  int id;
317  sscanf(args,"#%i",id);
318 
319  object oTmp=find_object(id);
320 
321  if(objectp(oTmp))
322  {
323  //check if object is in user's inventory
324  array oaInv = oUser->get_inventory();
325  foreach( oaInv, object item )
326  {
327  if ( item->get_object_id() == id )
328  {
329  mixed err = catch { oTmp->move(oUser->get_environment()); };
330  if (err!=0) send_message("Cannot drop object #"+id+"\r\n");
331  else send_message("Dropped Object #"+id+"\r\n");
332  return 1;
333  }
334  }
335  // foreach did not find object in user's inventory
336  send_message("Object #"+id+" is not in your inventory!\r\n");
337  }
338  else send_message("Can't find Object #"+id+"\r\n");
339  return 1;
340 }
341 
342 int cmd_quit(string cmd, string args)
343 {
344  if(readln)
345  oUser->set_attribute("telnet_history", readln->readline->historyobj->encode()/"\n");
346  send_message("Bye %s, see you again soon!\n", oUser->get_identifier());
347  oUser->disconnect();
348  disconnect();
349  return -1;
350 }
351 
352 int cmd_look(string cmd, string args)
353 {
354  //send_room(oUser->get_environment());
355  object oRoom = oUser->get_environment();
356  send_message(show_inventory(oRoom));
357  return 1;
358 }
359 
360 int cmd_inv(string cmd, string args)
361 {
362  int oid;
363  object obj;
364  if ( sscanf(args, "#%d",oid) == 1)
365  obj = find_object(oid);
366  else {
367  obj = oUser;
368  LOG("Inventory of User");
369  }
370 
371  send_message(show_inventory(obj));
372  return 1;
373 }
374 
375 int cmd_say(string cmd, string args)
376 {
377  object env = oUser->get_environment();
378  env->message(args);
379  return 1;
380 }
381 
382 int cmd_tell(string cmd, string args)
383 {
384  string user, msg;
385  object target;
386 
387  if ( sscanf(args, "%s %s", user, msg) != 2 ) {
388  send_message("Usage is tell <user> <message>.\n");
389  return 1;
390  }
391  target = _Persistence->lookup_user(user);
392  if ( !objectp(target) ){
393  send_message("Failed to find user '"+user+"'.\n");
394  return 1;
395  }
396  target->message(msg);
397  send_message("You told " + user + ": "+msg+"\n");
398  return 1;
399 }
400 
401 int cmd_move(string cmd, string args)
402 {
403  object env = oUser->get_environment();
404  object exit;
405  int id;
406  if(args == "home")
407  {
408  send_message("Going home now...");
409  exit = oUser->query_attribute(USER_WORKROOM);
410  }
411  else if ( sscanf(args, "#%d", id) == 1 )
412  exit = find_object(id);
413  else if(sizeof(args))
414  exit = env->get_object_byname(args);
415  else
416  send_message(cmd + " where?\n");
417 
418  if ( objectp(exit) )
419  {
420  mixed err = catch { oUser->move(exit); };
421  if ( err != 0 )
422  {
423  send_message("Failed to move there...\n");
424  }
425  else
426  {
427  enter_room(oUser->get_environment(), env);
428  //send_room(oUser->get_environment());
429  send_message(show_inventory(oUser->get_environment()));
430  }
431  }
432  else if(sizeof(args))
433  send_message("The exit '" + args + "' was not found.\n");
434  return 1;
435 }
436 
437 
438 int cmd_create(string cmd, string args)
439 {
440  array tmp=args/" ";
441  create_object(tmp[0], tmp[1..]*" ");
442  return 1;
443 }
444 
445 int cmd_addroom(string cmd, string args)
446 {
447  create_object("Room", args);
448  return 1;
449 }
450 
451 int cmd_addcontainer(string cmd, string args)
452 {
453  create_object("Container", args);
454  return 1;
455 }
456 
457 int cmd_addlink(string cmd, string args)
458 {
459  int objectid;
460  object room;
461  if ( sscanf(args, "#%d",objectid) == 1) {
462  room = find_object(objectid);
463  addlink (room);
464  } else {
465  send_message("Es gibt keinen Raum mit der Angegebenen ID.");
466  }
467  return 1;
468 }
469 
470 int cmd_execute_cmd(string cmd, string args)
471 {
472  send_message("\n"+execute(" "+args)+"\n");
473  return 1;
474 }
475 
476 // copied from masterlist.pike
477 
478 int cmd_load(string cmd, string args)
479 {
480  int iOID;
481  sscanf(args,"#%i",iOID);
482 
483  find_object(iOID)->get_identifier();
484  return 1;
485 }
486 
487 int cmd_upgrade(string cmd, string args)
488 {
489  string option;
490  int iOID, force;
491  [option, iOID] = array_sscanf(args,"%s#%i");
492 
493  if(option=="--force " || option=="-f ")
494  force=1;
495 
496  object pOID;
497  program target;
498 
499  pOID = find_object(iOID);
500 
501  if(!pOID && master()->programs[option])
502  target=master()->programs[option];
503  else if (pOID->status() <= PSTAT_DISK) {
504  send_message("Use Load instead\n");
505  return 0;
506  }
507 
508  target=object_program(pOID->get_object());
509 
510  if(!target) {
511  send_message("could not find program\n");
512  return 0;
513  }
514  else
515  send_message("upgrading...\n");
516 
517  mixed res = master()->upgrade(target, force);
518  if(res==-1)
519  send_message("Upgrade failed, try --force\n");
520  else
521  send_message("Result: %s\n", (string)res);
522 
523  return 1;
524 }
525 
526 mapping(string:function) run_commands = ([ "l":cmd_look,
527  "look":cmd_look,
528  "inv":cmd_inv,
529  "say":cmd_say,
530  "tell":cmd_tell,
531  "go":cmd_move,
532  "move":cmd_move,
533  "delete":cmd_delete,
534  "take":cmd_take,
535  "drop":cmd_drop,
536  "adduser":cmd_adduser,
537  "addroom":cmd_addroom,
538  "addcontainer":cmd_addcontainer,
539  "addlink":cmd_addlink,
540  "create":cmd_create,
541  "upgrade":cmd_upgrade,
542  "load":cmd_load,
543  "cmd":cmd_execute_cmd,
544  "man":cmd_man,
545  "?":cmd_help,
546  "help":cmd_help,
547  "quit":cmd_quit
548  ]);
549 
550 protected:
551  int handle_command(string cmd)
552 {
553  string args = "";
554  sscanf(cmd, "%s %s", cmd, args);
555  mMode->cmd=run_commands[cmd];
556  if(run_commands[cmd])
557  return run_commands[cmd](cmd, args);
558  else return 0;
559 }
560 
561 public:
562 
563 protected:
564  void process_command(string cmd)
565 {
566  switch ( iMode ) {
567 
568  case MODE_CONNECT:
569  send_message("Welcome to sTeam\n: ");
570  send_message("Login: ");
571  iMode=MODE_LOGIN;
572  break;
573  case MODE_LOGIN:
574  tmpUser = _Persistence->lookup_user(cmd);
575  if ( !objectp(tmpUser) )
576  {
577  send_message("User '"+cmd+"' does not exist !\n");
578  send_message("Login: ");
579  }
580  else {
581  if(readln)
582  readln->set_secret( 1 );
583  send_message("Password for "+cmd+": ");
584  iMode = MODE_PASS;
585  }
586  break;
587  case MODE_PASS:
588  if ( objectp(tmpUser) && tmpUser->check_user_password(cmd) ) {
589  send_message("Hi, " + tmpUser->get_identifier() + " - last seen "+
590  "you on " +
591  ctime(tmpUser->query_attribute(USER_LAST_LOGIN)));
592  login_user(tmpUser);
593  iMode = MODE_CMD;
594  enter_room(tmpUser->get_environment());
595  //send_room(tmpUser->get_environment());
596  send_message(show_inventory(tmpUser->get_environment()));
597  if(readln)
598  readln->set_secret( 0 );
599  tmpUser->listen_to_event(EVENT_TELL, tmpUser);
600  if(readln)
601  {
602  array history=tmpUser->query_attribute("telnet_history");
603  if(!arrayp(history))
604  history=({});
605  readln->readline->historyobj=readln->readline->History(512, history+({ "" }));
606  if(sizeof(history))
607  readln->readline->historyobj->delta_history(sizeof(history));
608  }
609  }
610  else
611  {
612  passwdtries++;
613  if(passwdtries<3)
614  send_message("Wrong password, please try again: ");
615  else
616  {
617  tmpUser->disconnect();
618  disconnect();
619  }
620  }
621  break;
622  case MODE_MORE_INPUT:
623  mMode->cmd(cmd);
624  break;
625  case MODE_CMD:
626  if ( strlen(cmd) != 0 && !handle_command(cmd) )
627  send_message("The command %O was not understood.\n", cmd);
628  send_message("["+_FILEPATH->object_to_path(oUser)+"] > ");
629  break;
630  }
631 }
632 
633 public:
634 
635 int get_client_features() { return CLIENT_FEATURES_ALL; }
636 string get_socket_name() { return "telnet"; }
637 
638 // allow user to store stuff somewhere
639 mapping temp_cmd=([]);
640 
641 int cmd_man(string cmd, string args)
642 {
643  string filename = "server/net/manpages/" + args + ".man";
644  if(Stdio.exist(filename))
645  {
646  write ("\n" + Stdio.read_file(filename) + "\n");
647  }
648  else
649  {
650  write("There is no command \"" + args + "\"\n");
651  write("usage : man <command>\n");
652  }
653 
654  return 1;
655 }
656 
657 int cmd_help(string cmd, string args)
658 {
659  send_message("\nthe following commands are available:\n%s\n",
660  sort(indices(run_commands))*" ");
661  return 1;
662 }
663 
664 
665 
666 };