CodeIgniter HMVC – Protecting your modules
If you have a module in CodeIgniter with HMVC by wiredesignz, you’ll know that all of your modules can be accessed via a browser URL. Here’s a quick snippet that you can use to protect controllers that you don’t want users to directly access, without breaking injection functionality.
/**
* Prevent direct access to this controller via URL
*
* @access public
* @param string $method name of method to call
* @param array $params Parameters that would normally get passed on to the method
* @return void
*/
public function _remap($method, $params = array())
{
// get controller name
$controller = mb_strtolower(get_class($this));
// if requested controller and this controller have the same name
if($controller = mb_strtolower($this->uri->segment(1)))
{
// show 404 error
show_404();
}
// check if method exists
if(method_exists($this, $method))
{
// call method and pass any parameters we recieved onto it.
return call_user_func_array(array($this, $method), $params);
}
// method doesn't exist, show error
show_404();
}
Just paste that method into your controller, and CodeIgniter will check the URI to see if the controller was called directly, otherwise it will operate normally (that’s why I passed $method to it).
Setting Library 2.0.0 Release
I’ve gone ahead and rewrote my CI Setting library. This library works like CI_Config, only it uses a database instead of configuration files to store settings. I made it a separate library, rather than extend the CI core library, because CI_Config loads before the database, and I didn’t want to deal with that mess. This was simpler. I’ve done a solution that added database directly to CI_Config, but it was messy, and less configurable by its very nature. Anyway, here’s the code.
Configuration File:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
$config['table'] = 'settings';
/* End of file setting.php */
/* Location: ./application/config/development/setting.php */
Library:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Setting Library
*
* Retrieves settings from a database much like the config library retrieves
* them from files. Complete rewrite from the old one.
*
* NEW
* ===
*
* Added overrides so that you can specify configs or options on a case
* by case basis, allowing you to reuse this library with other controllers
* and models, which may or may not use the same keywords. Also added the
* ability to specify an alternative database.
*
* @author Mark LaDoux
* @copyright Copyright © 2013 Mark LaDoux
* @version 2.0.0
*/
class Setting
{
/**
* Config File
*
* @access protected
* @var string
*/
protected $config_file = null;
/**
* Database table
*
* @access protected
* @var string
*/
protected $table = null;
/**
* Retrieve object from CodeIgniter instance
*
* @param object $param
* @return object
*/
public function __get($param)
{
$object =& get_instance()->$param;
return $object;
}
/**
* Load library dependencies and configurations
*
* @access public
* @return void
*/
public function __construct($cfg = array())
{
// check overrides
if(! is_array($cfg))
{
// overrides are formatted incorrectly, show an error.
show_error(
"Setting library expects an array for manual configuration",
503
);
}
// load database
if(isset($cfg['database']))
{
// allow setting library to be configured to use an alternative
// database. Please refer to CI user guide on as to what to set
// to this key.
$this->load->database($cfg['database']);
}
else
{
// load database based on default configurations.
$this->load->database();
}
// load configuration
if(isset($cfg['config_file']))
{
// allow for the loading of alternative configurations
$this->config->load($cfg['config_file'], true, true);
$this->config_file = $cfg['config_file'];
}
else
{
// load the default configuration file
$this->config->load('setting', true, true);
$this->config_file = 'setting';
}
// perform overrides
if (isset($cfg['table'])) {
// load overriden value
$this->table = $cfg['table'];
}
else
{
// load value from a configuration file.
$this->table = $this->config->item('table', $this->config_file);
}
// check to make sure class is configured
if($this->table === null)
{
show_error(
"Setting library is not configured!",
503);
}
}
/**
* Retrieve a value from a database
*
* @access public
* @param string $key
* @return mixed
*/
public function get($key, $check = false)
{
// select the data
$this->db->where('item', $key);
$this->db->limit(1);
// run the query
$query = $this->db->get($this->table);
if($check === true)
{
// check results
$output = ($query->num_rows() > 0) ? true : false;
}
else
{
// get results
if($query->num_rows() == 0)
{
$output = null;
}
else
{
$result = $query->row();
$output = $this->_decode($result->value);
}
}
// free up memory
$query->free_result();
// return output
return $output;
}
/**
* Prepares data for entry into the database, and determines if it needs
* to go through an update or an insert process.
*
* @access public
* @param array $data
* @return void
*/
public function set($data = array())
{
if(! is_array($data))
{
show_error('Setting class expects item => value pairs to be in an array',
503
);
}
// cycle through the values
foreach ($data as $item => $value)
{
// determine if item exists in DB
$check = $this->get($item, true);
// encode value for entry
$clean = $this->_encode($value);
if($check)
{
// update existing item => value pair
$this->_update($item, $clean);
}
else
{
// insert new item => value pair
$this->_insert($item, $clean);
}
}
}
/**
* Encode data so it can go into the database
*
* @access protected
* @param mixed $data
* @return string
*/
protected function _encode($data)
{
// serialize any arrays
if(is_array($data))
{
$out = serialize($data);
}
// transform values that won't enter the database normally
if($data === false) $out = '{{false}}';
if($data === true) $out = '{{true}}';
if($data === null) $out = '{{null}}';
if($data == '') $out = '{{empty}}';
// return output
return $out;
}
/**
* Decode data retrieved from database
*
* @access protected
* @param string $data
* @return mixed
*/
protected function _decode($data)
{
// unserialize any arrays
$check = @unserialize($data);
if(is_array($check)) $out = $check;
// transform encoded values back into their true values
if($data == '{{false}}') $out = false;
if($data == '{{true}}') $out = true;
if($data == '{{null}}') $out = null;
if($data == '{{empty}}') $out = '';
// return output
return $out;
}
/**
* Insert a new item into the database
*
* @access protected
* @param string $item
* @param string $value
* @return void
*/
protected function _insert($item, $value)
{
// set key => value pairs
$data['item'] = $item;
$data['value'] = $value;
// insert data into the database
$this->db->insert($this->table, $data);
}
/**
* Update the value of an existing item in the database
*
* @access protected
* @param string $item
* @param string $value
* @return void
*/
protected function _update($item, $value)
{
// set key => value pairs
$data['value'] = $value;
// locate the existing record
$this->db->where('item', $item);
// update the value
$this->db->update($this->table, $data);
}
}
/* End of file setting.php */
/* Location: ./application/libraries/setting.php */
I hearby give permission to use or modify this software however you wish, so long as you retain the copyright and credit me. I do not claim that it’s perfect, and I won’t be held responsible for any problems or damages that it may cause you. If you do find an issue with it, please do share with me. I’ll write up the sql for it later and share it soon, but keep in mind, you only need two fields, one for the item name, and one for the item value.
Server Upgrades Complete
I upgraded the server today, and magically, everything worked afterwards. At least it appears that way thus far. If you find any glitches, just drop me a message on my about page so that I can fix them!
Cash Flow
So, I’m kind of low on the cash flow lately. I’m working on a few plans to try and get a good revenue stream coming in. Hopefully something will work out, because my computer needs an upgrade and my domain needs renewing. I think I have the domain handled now, though, so I’m not too worried about that. I just don’t know if that money is going to be here before or after it expires, because I can’t remember exactly when it expires. I’m hoping before.
I’m currently working on a website for a company called “Naked Inside”, so that has me pretty busy right now. I’ll have to put off some of the tutorials until after that project is up and running. I have a few ideas for what to do in that regards, though, and I can’t wait to get back to it. I need to do a little research first, and double check to make sure I haven’t forgotten anything and that the information is still valid.
I got distracted helping out a friend, and don’t remember what else was supposed to go into this post anymore. I’m sure I’ll be able to come up with something after I get some sleep. Till then, I hope you all have a good day.
More Linux
In response to the awesome feedback I’ve gotten on my few Linux tutorials, I’ve decided that I’m going to start doing a lot more of them. I only posted them on a whim, but I’ve got loads more up in my noggin that I can add. Stay tuned as I work out my next project. If you want to learn how to do something specific, go ahead and post a comment below! I won’t do everything, but I’ll do what I can.
Working on Code Again
Well, I’m back to coding again. I’ve got a website to put together, and about a month to do it in. I’m having a lot of fun on this project, but I won’t tell you what it is for privacy reasons. I do see a lot of new code coming out of this project, and I have plans on releasing some of it. One thing that I’ve noticed, my brain gets bogged down a lot faster than it used too. I think that that will ease up as I get re-acquainted with long hours in front of my text editor. I’m also considering trying my hand at graphics. We’ll see what happens. I guess I’ve just gotten lazy playing minecraft.
It’s been pretty nice weather outside, so I’ve taken to sitting in the front room with my laptop and leaving the door open to let the fresh air flow in. I hope this weather lasts, it’s been very nice. The only issues I’ve had is when the neighbors break out into arguments over this or that. It makes it very difficult to concentrate when the people outside are arguing over <insert inane subject I don’t give a shit about here> outside my door. It’s only going to get worse when the pool is finally warm enough that they start letting the kids in. It’s just outside my door, so the noise will be unbearable. Thankfully, I can’t hear them if I close the door and turn on some music.
Downtime
Sorry about the downtime. I’m not sure how long the site was offline. Apparently the file system my database server uses to store its files had gotten mounted read-only. Anyway, I remounted the file system in the correct mode, and ensured that it was configured in my fstab properly, so it should not happen again.
Got a Bus Pass
So, I went out and got myself a new bus pass. I’ve not had one yet, but I figured it’d save me some money and I’d go more places. The bus can be pretty expensive in cities. Anyway, I went and saw the great cathedral in St Paul yesterday. It has some beautiful architecture. I’m thinking next time I go out, I’ll bring a camera so I can take some pictures to share with you all. There are many interesting sites that I’d like to share with my friends and family back home. If other people enjoy them too, well the more the merrier!
Going out and seeing the sites has inspired me with some new ideas for a pet project I’m working on. I’m working on a science fiction piece, and I’ve been stuck for months. Anyway, I’ve thought of an idea for an engine for the star ships. I’m calling it a “star drive”. Yeah, I know it’s not very original, but it does describe what the drive is pretty accurately. It’s essentially a star in a can. How it works is you feed the engine with hydrogen, and it then proceeds to utilize thermonuclear fusion on the fuel material producing heavier and heavier elements. This of course will all be contained within a tokomak, or similar magnetic containment field. A device I call a ferrometer will monitor the wavelengths of light emitted by the ongoing reaction, measuring the iron content of the fusing materials. When the Iron levels get to a certain point, the reactor will begin to shut down via some cooling process. I need to do a bit more research to determine the best method for cooling down a fusion reactor without causing catastrophic consequences. I’m definitely going to have to make up some things and just not describe them very well.
Well, I guess that’s enough spoilers. I’m going to see what I can do about getting some pictures for my future posts. Hope you come back to read them!
Internet Go Boom!
Well, it appears that we forgot to pay the internet bill, so I’m writing this entry without the aid of an internet connection to post with. Don’t worry, I’ll upload it tomorrow when we get it turned back on. There are some bright sides to my situation. Since there is no internet access for distracting websites, I can concentrate on working on my projects. I’ve got all my tunes and manuals installed on my system locally in case of this type of emergency.
I decided that I would work on my CMS project. Of course, I’ve got a local copy of Apache installed, and I had just updated all my libraries so that I could be current. I just popped on iTunes, and put my obscenely large collection of Nerdcore music on shuffle. I picked up my keyboard, opened Sublime Text, and started hacking away at all the stuff that I’ve been neglecting. I even managed to come up with an awesome idea for an automated installation system. I was planning on doing one for a while, and wanted to hold of coding till I had an idea that was solid. I wanted to make sure I planned the install framework, so that I could make sure that I made all the adjustable values and default values accordingly. My install system uses a custom CodeIgniter environment setting, that will load configuration files based on the system being in installation mode. I figure I’ll probably develop the baseline of the site, and get to work on the authentication/authorization system.
I also used this time to do some household chores that I’ve been putting off, catch up on Assassins Creed, and watch a few movies that I’ve not seen yet. All in all, this experience isn’t as horrible as it could have been, as I made sure that I had plenty of projects to distract myself with.