ID:2719
 
Okay I've always known you have to be careful with procs like input(), and with equivalent web forms that use Topic(), but knowing and really dealing with it are two different things.

LRS has been riddled with potential exploits, for the simple reason that it has taken me a while to get the right mindset about input() and Topic(). Here are some simple rules to keep in mind:

1. Everything old is new again
Code for input() is deceptively simple. You get input() on which mob they want to attack, then you attack it on the next line. What could be simpler?

But here's the point to keep in mind: Once you call input(), by the time the next line of code is called you know absolutely nothing about the state of the game. Five hours may have passed while that input() window was up, aliens may have invaded Kentucky, World War III has broken out, the mobs you listed may have gotten deleted in some other way, it may no longer be this player's turn, the game may have ended...you know nothing!

So treat each call to input() as if you had just gone into a strange time warp...on coming out the other end, you need to ask yourself what's going on, and whether any of your assumptions are correct anymore. Is it still this player's turn? Does the target mob still exist? Is this attack still legal?

2. input() doesn't stop anything from happening
You can't forget that the player is free to interact with other things while that input() window is up. If you don't want them doing that, you need to set some variables and refresh things such that they don't have access to undesired functionality until they respond to the input() window.

And on a related subject...

3. Topic() may be called anytime by anyone
Don't assume that you know who clicked the link that called Topic() or how they got there. Test that the usr is who they should be, test that it's the right person's turn for this action, and that this action is legal. Even if you only show a link at legal times, the browser page may hang around longer than expected, they may click the link multiple times before it disappears, or they may do a trick whereby they "view source" on the browser page, change the HTML, save it back to the cache and refresh the page...wala they've just given themselves any link command they wish.

Best of all is when you can have Topic() stuff handled by temporary objects that go away when the command is no longer valid. That helps avoid several exploits.

This Public Service Announcement has been brought to you by the letter G.
And the number 16.

Anyway, I've been wary about input() as well. Of course, after the input, I always checked to see if(Blah).
Of course if(Blah) may not always work...

var/Blah = input("What is blah?") as text
Blah = 0
if(Blah) src.Attack(Blah)
On a related note, it's very important that user input validation is done on the server's side -- not on the client's. As a rule of thumb, if it's on the client's side, the client has complete control over it.

In other words, never ever ever use JavaScript for security!
JavaScript is okay to help improve the UI -- not letting them submit a form if the info isn't valid, for example. However it has to be considered just a UI thing...any validation there must be redone on the server side.
Yeah. Even though it has to be redone on the server's side, it's nice to have a script set up that will tell the user, as he's filling a form out, that the email address he typed in is invalid, for example.
Seems to me the only rational course of action here is to permanently ban input() and Topic(). And clients, just to be safe.
Players are the enemy!
Here's an idea that's sure to work. Put all your calls to Input() in a wrapper proc that sets a global variable, e.g., "waitingForInput", to 1. When the wrapper proc gets the user's input, then the variable is cleared and the proc returns.

Then, just make sure the rest of your code checks this variable before doing anything. Easy as pie, plus it'll keep other players from screwing around while someone's trying to make up his mind.
The client cannot be trusted. The client is in the hands of the enemy. Never forget this. Also, players don't need to view the source and edit it to put in whatever link they wish. BYOND accepts byond://? links typed into the pink command bar, too.
Gug good idea, and I think I'll add that to the handling. (There's an equivalent now in LRS but it's not as broad).

However, have to be careful that player disconnection doesn't leave the game hanging. Might want to store the player key as the value to waitingForInputFrom, and clear that if the player's client is deleted.
It's probably not in common use by a lot of people, but I've found callbacks to be an incredibly useful tool. For example, you could create a datum to handle input() and give it a proc to call when it finishes.

For those who've never used callbacks, here's the basic idea: You set up a proc that will be called by another part of your code after a certain action is complete. You set up that action by telling it the path to the proc it should call, what src will be, and whatever arguments it needs to send. Then after that action finishes, it calls call(thesrc,theproc)(arg1,arg2,...) for you.

You know, this is such a worthwhile topic I may have to put this in part of a Dream Tutor column.