Page 175 of 175

Basic incoming data verification in PHP

Why validate?

Incoming data validation is "must have". Always be aware, that user will send you corrupted (or wrong) data. Sometimes by mistake, sometimes on purpose.

SQL injection and XSS (Cross-site scripting) are possible due to lack of data verification.

What should I validate?

E-v-e-r-y-t-h-i-n-g. Every piece of incoming data.

While we can assume that administrator may be able (and sometimes he should be) to place the HTML or Javascript in a message content, we can't say this about standard user posting message in a guestbook.

What can we lose?

Data. Logins, passwords and other stuff.In commercial products that could be a disaster.

Let's mess things up!

I've created simple test "site" (click), where you can play with content injection. Here you can download source code.

Inject h1 tag and some content:

</pre>
<h1>Injected content</h1>
<pre>

It's not hard to guess, what we will see after sending this message. H1 tag inserted into page content. Not so bad. We can inject HTML so why not CSS and Javascript? Let's try:

<pre>
<div style="text-decoration: underline;">
message
</div>
<script>alert('tadam!')</script>
</pre>

It works! Strip_tags alone is not enough. PHP has some other nice methods: addslashes i stripslashes. The add (and remove) slashes before "dangerous" signs like '"'. Thanks to those methods we will be protected against SQL Injection - because after this, even "special" chars will be treated as standard ones. If we send out Jacascript and we use strip_tags_addslashes, we will see in source code - that javascript tag has been removed and other tags are escaped.

Why we need stripslashes?

We protect ourself by adding slashes - but before we show output to user - we should remove them.

Buuu - inconvenient!

You think so? Yeah - you're right. It is a lil bit inconvienient, but do not worry, there is another option. If you use Mysql database, you can use mysql_real_escape_string. It detects dangerous stuff and "add and strip" slashes without our help.

But, what about HTML?

Hmm but what about situation when we would like to show a html code as a text? Using previous methods - we would remove all html from content. There is one method that should help use - htmlspecialchars . It will change "living" HTML into its entity equal (but safe) version, so you can display it and it will not be interpreted.

Conclusion

I've tried to show the "basics of basics" of data validation. Read, test, read, test and never feel safe :)

Handling custom 404 and 500 errors in Rails 2.3

We all need to handle 404 and 500 errors. Rails handle them differently in different environments.

In development, when we request a non existing resource, we will see:

Routing Error

No route matches “/dummy_controller/non_existing_action” with {:method=>get}

Similar situation occurs, when requesting non existing action but in an existing controller:

Unknown action

No action responded to smthn_weird. 
Actions: index, load_adverts, login and logout

Even in production when we make a request from 127.0.0.1 (aka localhost), the request is handled as local.

When we develope our software, informations like those mentioned above are useful, however sometimes we would like to do something else. There might be a situation when you would like to:

  1. redirect all 'missed' requests into a specified controller (withouth showing 404)
  2. test 404 and 500 behavior
  3. show extended info even in production mode
  4. render different error templates, depending on a module (admin, shopping, etc)
  5. do any other weird kind of stuff

So, let's overwrite Rails default behavior.

Put into config/environment.rb:

# Show 404 errors
SHOW_404 = true
# Show error template (or render extended Rails info)
SHOW_EXTENDED_404 = false
# Don't show 500 - instead render 404 
SHOW_ONLY_404 = false 

We can use those constants to manipulate Rails "error flow":

  • SHOW_404 = false - don't show 404 - use default controller and action to handle response
  • SHOW_404 = true – render 404 error
  • SHOW_EXTENDED_404 = true – show extended 404 info
  • SHOW_EXTENDED_404 = false – render default 404 template (in any of environments)
  • SHOW_ONLY_404 – don't show 500 errors - handle them like 404

Next, add into config/routes.rb (just before final "end"):

# 404 route
map.connect "*anything", :controller => "default_controller", :action => "index" if !SHOW_404

This will redirect into default controller any requests which do not fit anywhere else. It is worth mentioning here, that it is often not the desired behavior and the user can feel lost when suddenly he will see main page instead of 404 error.

When we use namespaces(modules) and we would like to handle errors differently, depending on a module, we should add:

admin.connect "*anything", :controller => "default_controller", :action => "index" if !SHOW_404
admin.connect ':action' , :controller => "module", :action => "index" if SHOW_404

and for each module also:

admin.controller_name 'controller_name', :controller => 'controller_name'

Now overwrite default error handling methods in controllers/application_controller.rb :

def rescue_action_locally(exception)
	if SHOW_EXTENDED_404
		super exception
	else
		rescue_action_in_public(exception)
	end
end

Second method:

def rescue_action_in_public(exception)
	if SHOW_EXTENDED_404
		rescue_action_locally exception
	else
		case exception
		when ActiveRecord::RecordNotFound, ActionController::UnknownAction, ActionController::RoutingError
			render_error 404
		else
			if SHOW_ONLY_404
				render_error 404
			else
				render_error 500
			end
		end
	end
end

So, we have error handling, but we still lack two things:

  1. render_error method
  2. path to the errors templates.

Copy 404.html and 500.html from public into views/shared/ and change file extension to .erb. Create in views/layouts/ custom error templates and do not forget to yield :). After that - tell Rails about those templates:

  
PATH_404 = 'shared/404'
PATH_500 = 'shared/500'
ERROR_LAYOUT = 'layouts/server_errors'

Finally render_error method:

def render_error(error_nr = 404)
	p404 = PATH_404; p500 = PATH_500
	lay404 = ERROR_LAYOUT; lay500 = ERROR_LAYOUT
	if block_given?
 		feedback = yield
 		p404 = feedback[0]
 		lay404 = feedback[1]
 	 	p500 = feedback[2]
  	 	lay500 = feedback[3]
	end

	case error_nr
	when 404 || SHOW_ONLY_404
 		render :template => p404, :layout => lay404, :status => "404"

	else
		render :template => p500, :layout => lay500, :status => "500"
	end
end

Why I use yield? I have not found a way to pass template parameters from our class into base class. Ofcourse it is possible to overwrite whole render_error in all subclasses but it is not DRY. Instead of this, you can do it like this:

def render_error(error_nr = 404)
	super do [ 'admin/shared/404', false, 'admin/shared/500', false] end
end

First argument contains error partial path, second - layout path. When there is no layout path (error template has already embed layout) - just put false.

Copyright © 2026 Closer to Code

Theme by Anders NorenUp ↑