Jul 18, 2012

AJAX, JQuery, CodeIgniter and PHP

This is an extension of an earlier blog of mine, but this time I have built it using the CodeIgniter PHP framework. I have also spiced it up with a dynamic JQuery form (kudos to Charlie Griefer and this blog post for the code!)

If you want to get your hands dirty doing something a little harder then I suggest you check out my earlier blog on creating a login system with CodeIgniter.

If you are just getting started, have a look at my other blog posts, 'Ubuntu, LAMP and CodeIgniter' and the 'Extended JQuery Tutorial'.

Getting started

I am going to assume that you are working with a fresh installation of CodeIgniter that simply displays the welcome message. I am going to start from there so we don't get into any confusion!

First, unzip the CodeIgniter source into your web-server's root directory (if you followed my LAMP guide above, this will default to /var/www/). Rename the extracted folder to test (so in the default example, the CodeIgniter framework will be stored in /var/www/test/).

Now delete ALL the php files in /var/www/test/application/controllers and /var/www/test/application/views. We are going to start completely fresh!

The final step is to configure the framework to use our new controller (once we create it...), so edit the file /var/www/test/application/config/routes.php with the following line:
$route['default_controller'] = "home";
Now to make our main controller....

The Home page controller

  1. Create a file in /var/www/test/application/controllers named home.php
  2. Add in the following code:
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    class Home extends CI_Controller {

        /**
         * Index Page for the home controller.
         *
         * Maps to the following URL
         *         http://example.com/
    index.php
         *    - or - 
         *         http://example.com/index.php/home
         *    - or -
         * Since this controller is set as the default controller in
         * config/routes.php, it's displayed at http://example.com/
         *
         * So any other public methods not prefixed with an underscore will
         * map to /index.php/home/<method_name>
         * @see http://codeigniter.com/user_guide/general/urls.html
         */
        public function index()
        {
            $this->load->view('view');
        }
    }

    /* End of file ajax.php */
    /* Location: ./application/controllers/home.php */
  3. That's it. All this does is load up our view, which is our next step.

The Home page view

  1. Create a file in /var/www/test/application/views named view.php
  2. Add in the following code:

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Test</title>

    <!-- JQuery code hosted by Google -->
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js"></script>

    <!-- Adding and Deleting form buttons -->
    <script type="text/javascript" src="form.js"></script>

    <!-- AJAX functionality -->
    <script type="text/javascript" src="ajax.js"></script>
    </head>

    <body>

    <form id="myForm">
    <div id="input1" style="margin-bottom:4px;" class="clonedInput">
    Name: <input type="text" class="name" name="name1" id="name1" />
    </div>

    <div>
    <input type="button" id="btnAdd" value="add another name" />
    <input type="button" id="btnDel" value="remove name" />
    <input type="button" name="submit" class="button" id="submit" value="Send" />
    </div>

    <div id="display">
    </div>
    </form>

    </body>
    </html>
  3. Our basic HTML page includes three JavaScript files (One is the JQuery API, the other two we write ourselves; see below). We have a form with an input text box and three buttons. The first two buttons add and remove input boxes from our form, while the last button performs our AJAX operation.

form.js - Dynamically adding form elements

  1. Create a file called form.js in /var/www/test/
  2. Add the following code:
    $(document).ready(function() {
                $('#btnAdd').click(function() {
                   

                    // how many "duplicatable" input fields we currently have

                    var num     = $('.clonedInput').length;                // the numeric ID of the new input field being added
                    var newNum  = new Number(num + 1);
     
                    // create the new element via clone(),
                    // and manipulate it's ID using newNum value
                    var newElem = $('#input' + num).clone().attr('id', 'input' + newNum);
     
                    // manipulate the name/id values of the input inside the new element
                    newElem.children(':first').attr('id', 'name' + newNum).attr('name', 'name' + newNum);
     
                    // insert the new element after the last "duplicatable" input field
                    $('#input' + num).after(newElem);
     
                    // enable the "remove" button
                    $('#btnDel').attr('disabled','');
     
                    // business rule: you can only add 5 names
                    if (newNum == 5)
                        $('#btnAdd').attr('disabled','disabled');
                });
     
                $('#btnDel').click(function() {
                   
    // how many "duplicatable" input fields we currently have
                    var num = $('.clonedInput').length;

                   
    // remove the last element
                    $('#input' + num).remove();
     
                    // enable the "add" button
                    $('#btnAdd').attr('disabled','');
     
                    // if only one element remains, disable the "remove" button
                    if (num-1 == 1)
                        $('#btnDel').attr('disabled','disabled');
                });
     
                $('#btnDel').attr('disabled','disabled');
            });
  3. This function attaches a JavaScript function to the add and remove button. The code is pretty well commented by Charlie Griefer, so if you want to know more I suggest you go visit his blog post.

ajax.js - AJAX with JQuery

  1.  Create a file called ajax.js in /var/www/test/
  2. Add the following code:
    $(document).ready(function() {
        // This will run when the item of id 'submit' is clicked
        $("#submit").click(function() {

        // Grabs the text input
    from the form
        var name = [];
        $(".name").each(function() { name.push($(this).val()) });

        // Create the key-value pair for POST

        var dataString = 'string=' + name.join(' ') + '';

        // This creates the AJAX connection
        $.ajax({
           type: "POST",
           url: "index.php/ajax",
           data: dataString,
           dataType: 'json',
           success: function(obj) {
              $('#display').html(obj.message);
           }
        });
        return false;
        });
    });
  3. This will send all of our dynamically generated form elements to index.php/ajax (which we will now create). Hopefully the code and comments are self explanatory; if you have any problems just shout out in the comments!

The AJAX controller

  1. Create a file in /var/www/test/application/controllers named ajax.php
  2. Add the following code:
    <?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

    class Ajax extends CI_Controller {


       /**

        * Index Page for this controller.
        *
        * Maps to the following URL
        * http://example.com/index.php/ajax
        * - or -
        * http://example.com/index.php/ajax/index
        *
        * So any other public methods not prefixed with an underscore will
        * map to /index.php/ajax/<method_name>
        * @see http://codeigniter.com/user_guide/general/urls.html
       */
       public function index()
       {
           $txtValue = "We have recieved: " . $this->input->post('string');

           echo json_encode(array('message' => $txtValue));

       }
    }

    /* End of file ajax.php */

    /* Location: ./application/controllers/ajax.php */
  3. You should now be able to run this on your web-server and have a dynamic form that sends and recieves AJAX!

References:

Jul 11, 2012

Ubuntu 12.04, LAMP and CodeIgniter 2

This guide aims to install and use CodeIgniter on an Ubuntu machine. We will assume you have the default Ubuntu installation.

  1. Install Apache 2:
    sudo apt-get install apache2
  2. Install MySQL:
    sudo apt-get install mysql-server mysql-client
  3. Install PHP5 and the necessary libraries:
    sudo apt-get install php5-cli php5-mysql libapache2-mod-php5
  4. Download the CodeIgniter framework:
    wget http://codeigniter.com/download.php -O ~/CodeIgniter.zip
  5. Extract the framework to the default Apache2 web directory:
    sudo unzip ~/CodeIgniter.zip /var/www/
  6. You should now be able to navigate to your extracted folder from your web-browser. Hint: you will need to open firefox to http://localhost/<name-of-folder> which you can get by executing the following command:
    ls /var/www

References

Jul 8, 2012

Securing Ubuntu 12.04

I have been extended my knowledge of Linux System Administration (in particular, securing Linux systems), and as such the first thing I did when I installed Ubuntu 12.04 LTS was to lock it down.

Installing Ubuntu is outside the scope of this blog post, so if you don't have Ubuntu yet I suggest you follow the official documentation.

Networking

We will first deal with locking down our machines network access. By restricting how our machine communicates with others we narrow down the attack vectors available.

  1. The first thing we should do is turn on a firewall. Ubuntu comes with ufw pre-installed so we will just use that (I have covered this in a previous blog post).
    sudo ufw enable
    Check its status with:
    sudo ufw allow ssh
  2. Enable any services you will need. For instance a web server will need the HTTP port of 80 open.
    sudo ufw allow ssh

    # You can specify a port directly
    sudo ufw allow 80
    # You can also specify whether it is TCP or UDP
    sudo ufw allow 80/tcp
    # Finally, you can specify whether it is incoming or outgoing
    sudo ufw allow in 80
    sudo reject out 1337
  3. Sysctl allows you to configure the Linux kernel during runtime. We will edit the file /etc/sysctl to harden our network interface; open the file in your favorite editor and make the following changes:
    #IP spoofing/forging protection by turning on the reverse path filter
    net.ipv4.conf.all.rp_filter=1
    net.ipv4.conf.default.rp_filter=1

    # Protect against ICMP attacks
    net.ipv4.icmp_echo_ignore_broadcasts=1
    net.ipv4.icmp_ignore_bogus_error_responses=1

    # Turn off IPv4 features that are easy to abuse
    net.ipv4.conf.all.accept_source_route=0
    net.ipv6.conf.all.accept_source_route=0
    net.ipv4.conf.default.accept_source_route=0
    net.ipv6.conf.default.accept_source_route=0
    net.ipv4.conf.all.send_redirects=0
    net.ipv4.conf.default.send_redirects=0
    net.ipv4.conf.all.accept_redirects=0
    net.ipv6.conf.all.accept_redirects=0
    net.ipv4.conf.all.secure_redirects=0

    # Block SYN attacks
    net.ipv4.tcp_syncookies=1
    net.ipv4.tcp_max_syn_backlog=2048
    net.ipv4.tcp_synack_retries=2
    net.ipv4.tcp_syn_retries=2

    # Log Martians
    net.ipv4.conf.all.log_martians=1

    # Ignore directed ICMP pings
    net.ipv4.icmp_echo_ignore_all=1

    # Don't perform IP forwarding
    net.ipv4.ip_forward=0

    #####
    # IPv6
    #####

    # Number of router solicitations to send until assume no routers present
    net.ipv6.conf.default.router_solicitations=0

    # Do not accept router preferences
    net.ipv6.conf.default.accept_ra_rtr_pref=0

    # Do not accept prefix info from router
    net.ipv6.conf.default.accept_ra_pinfo=0

    # Do not accept Hop limit settings from router
    net.ipv6.conf.default.accept_ra_defrtr=0

  4. Reload sysctl with your changes:
    sudo sysctl -p
  5. Secure your TCP Wrapper by editing the /etc/hosts.deny file, ensuring the following line is the only one uncommented:
    ALL: ALL
  6. Allow your TCP Wrapper services (like SSH) by editing the /etc/hosts.allow file. The basic syntax is:
    <service>: <host/network>
  7. Prevent IP Spoofing via DNS by editing the file /etc/host.conf and adding the following lines:
    order bind,hosts
    nospoof on
  8. If you have not already done so, update your system so that there are no security vulnerabilities:
    sudo apt-get update
    sudo apt-get upgrade
  9. Install nmap, a tool for network discovery and security auditing:
    sudo apt-get install nmap
  10. Perform a local nmap TCP scan of your machine and ensure that all ports that are open are supposed to be open.
    sudo nmap -v -sT localhost
    Perform a SYN scan, which is another way a hacker can probe your system:
    sudo nmap -v -sS localhost
    Perform a UDP scan to determine which UDP services are operational:
    sudo nmap -v -sU localhost
  11. Perform the same NMap tests but on another host. If you followed the above instructions you may want to add -PN to the command so that nmap ignores the fact that your machine does not respond to pings. Note that this scan may take some time...

 

Filesystem

We will now protect our file-system.  

Note: you will get the best security by putting your system directories into their own partition. This will allow you to specify the mount options for each directory. This guide will only cover the default install.

  1. Protect your shared memory by editing /etc/fstab as follows:
    tmpfs  /dev/shm  tmpfs  defaults,noexec,nosuid  0  0
  2. Bind /var/tmp to /tmp so that we limited what applications can do with that system directory. Edit /etc/fstab as follows:
    /tmp  /var/tmp  none  rw,noexec,nosuid,nodev,bind  0  0

 

Startup Applications

We will now modify the start-up applications and services that turn on during boot.
  1. Display the hidden start-up applications:
    sudo sed -i 's/NoDisplay=true/NoDisplay=false/g' /etc/xdg/autostart/*.desktop
  2. Press the windows key on your keyboard, type in 'Startup Applications' and launch the program of the same name
  3. Disable the following services (Note: These may change depending on your personal situation):
    • Backup monitor
    • Bluetooth manager
    • Chat
    • Desktop Sharing
    • Gwibber
    • Orca Screen Reader
    • Personal File Sharing
    • Ubuntu One

 

Disable Guest Login

Just edit /etc/lightdm/lightdm.conf and add the following line:
allow-guest=false

 

References:

Jul 7, 2012

Make your own TRS (headphone) to RCA audio cable

I like to re-use old equipment whenever possible. Mostly because it gives me the opportunity to hack away at it until it suits my needs. This is one such case....

Most portable media players come with a 3.5mm TRS audio jack socket that is intended to play stereo sound on a sound system or headphones. Which is great, except I had an old surround sound system that only used RCA connections...

The TSR socket is the image on the left. The RSA sockets are on the right.
Let's get into the technical differences between each of these connection types:

  • The TSR cable can carry both channels of a stereo signal (the left and right channels). It can also be 'balanced', which is just a fancy way of saying that it is protected from external noise. All of these properties are possible because of the unique configuration of the plug, which is segmented into a Tip, Ring and a Sleeve (if you have been paying attention, that's where the TRS acronym originated).
    Cut away view of a TSR jack plug showing the Tip, Ring and Sleeve.
    For portable media players the TSR connection is unbalanced, with the Left channel transmitted through the Tip and the Right channel transmitted through the Ring. The Sleeve is used as a common ground for both channels.
  • RCA connections can only carry one signal and are always unbalanced.
Now we know the rough anatomy of the connectors we can now hack our own cable! For this guide, we will need one (1) TSR plug and two (2) RCA plugs. This is because the TSR will carry two channels, which we will distribute over the two RCA connectors (each RCA plug can only carry one channel).

  1. Chop off one end of the TSR cable. You can discard the other end (or keep it for later...). Strip and and solder the end.
    I just opened up my extra plug so I could see inside it (as well as know which channel is which)
  2. Chop off two RCA plugs, leaving just enough wire so that we can strip it for our connection. Strip and and solder the end.
  3. You should now have the following:
    From Left-to-Right: The stripped end of the TSR plug (you should see three wires); The TSR plug; The stripped end of the RCA plug; The RCA plug
  4. Connect the signal wire of each RCA plug to a TSR signal channel. For instance, one RCA signal wire will be connected to the TSR Tip wire for the left channel. The other RCA signal wire will be connected to the TSR Ring wire for the right channel.

    Both RCA ground wires are to be connected to the TSR sleeve wire. YOU SHOULD TEST BEFORE SOLDERING!
    Testing the set-up...
  5. Once you have tested it all out, solder the connections and viola! You now have a TSR-to-RCA cable!

Hope this helps someone out there!!!

References:

Jul 6, 2012

Access an LVM module (Ubuntu 12.04)

A computer died on me and I needed to recover some of the data. I thought it would simply be a case of popping the disk into an external hard-drive case and ripping the data out. Unfortunately, I encountered a little snag involving LVM.

My Ubuntu 12.04 machine could not recognise the LVM partition natively. Basically this meant I had to configure the machine so that I could manipulate the disk; a quick Google search revealed this post from linux-sxs.org.

To make your life easier, here are the steps:

  1. Install lvm2, which is the libraries and utilities required to manipulate LVM volumes.
    sudo apt-get install lvm2
  2. Use the following command to scan for available LVM volume groups and find the one you are looking for (in this example we are going to assume our volume group is VolumeGroup01)
    sudo vgscan
  3. Activate your volume
    sudo vgchange -ay VolumeGroup01
  4. Search for the volume that contains the partition you are looking for (we are going to assume that the volume is called LogicalVolume01)
    sudo lvs
  5. Create a mount point for your volume
    sudo mkdir /mnt/destination
  6. Mount the volume
    sudo mount /dev/VolGroup00/LogVol00 /mnt/fcroot -o ro,user

 

References: