Thursday, April 17, 2014

Laravel 4: CSRF TokenMismatchException when using stored form values

Problem: 
One of my client's Laravel web sites was having issues with logging in users where the first time, they would get the TokenMismatchException (gracefully handled, of course) and then they could log in as expected.

Solution:
My first thought was that for some reason the browser was storing the _token value along with their login credentials, so I wanted to force Laravel to regenerate the CSRF token and use one that had not already expired. While I could find no easy handle to regenerate the CSRF token, I did find that I could regenerate the session ID which would ultimately cause the same result.

Session::regenerate();

Note: This problem only existed when users were not logged in, otherwise regenerating the session ID might have interrupted their session.


Monday, March 3, 2014

Google Maps API Controls Do Not Display with Bootstrap

Problem:
Adding a Google Maps API control to a web page, I found that the controls were failing to render properly. They looked like this:



Solution:
It happens that a generic style in my Bootstrap theme was causing the issue. By adding two additional CSS rules, we can override the Bootstrap changes, and restore our controls.

.gm-style img { max-width: none; }
.gm-style label { width: auto; display: inline; }


Wednesday, February 19, 2014

Laravel 4: Model Hydrate

Problem:
While converting some older Laravel code, I ran into an issue where the hydrate method had been removed. My usage was similar to this:

$raw_result = DB::query(...);
$hydrated_models = Model::hydrate(new Model(), $data);


Solution:
While the method may have been removed, there are other methods which can be used to achieve the same outcome. One such method is the newFromBuilder method which can be used as follows:

$raw_result = DB::select(...);
$collection = new \Illuminate\Database\Eloquent\Collection();
foreach ($raw_result as $raw_obj)
{
     $model = new Model();
     $collection->add($model->newFromBuilder($raw_obj));
}

If you would like to abstract this process into a static method on the model. You can do so by creating a BaseModel extending Eloquent in which other models you want to have the hydrate method can extend. 

For example: 

use Illuminate\Database\Eloquent\Collection;
class BaseModel extends Eloquent
{

    /**
     * Hydrate method
     * 
     * @param array $data
     * @return Illuminate\Database\Eloquent\Collection
     */
    static public function hydrate($data)
    {
        // get calling class so we can hydrate using that type
        $klass = get_called_class();
        
        // psuedo hydrate
        $collection = new Collection();
        foreach ($data as $raw_obj)
        {
            $model = new $klass;
            $collection->add($model->newFromBuilder($raw_obj));
        }
        return $collection;

    }
}

class User extends BaseModel
{
    /* ... */
}

// Usage of hydrate
$user_collection = User::hydrate($data);

Along with Model::hydrate, the DB::query method no longer exists. See more changes happening when upgrading from Laravel 3 to Laravel 4.

Tuesday, February 4, 2014

TomatoCart: Changing text (Fixing maintenance mode message)

Problem:
Working with a client, I noticed that the maintenance mode message shown when the store was in maintenance mode had misspelled the word "later" as "latter".

Solution:
It was simple enough, I had to edit the English language file and edit the database stored English phrase.


  1. Fix the language file: includes/languages/en_US.xml
  2. Fix the stored database value: SELECT * FROM languages_definitions WHERE definition_value LIKE '%latter%';
  3. Clear the cache files in the admin. Start > Tools > Cache Control

Tuesday, December 31, 2013

Python: xlrd - bad magic number for file header

Problem:
Working in Pylons for a project, I built a tool to allow file uploads and one feature used xlrd to convert Excel files to CSV files. When I went to transform these files using xlrd, I got an error saying: bad magic number for file header.

Solution:
Turned out the file got corrupted as I uploaded it on Windows but did not use a binary flag when storing the file. Adding this flag fixed the issue and allowed xlrd to continue properly.

Tuesday, October 29, 2013

SSH Tunnel All Network Traffic - Windows 7

Problem:
While working on a some development, there became an issue with the ISP and they hijacked all HTTP requests to return a notice explaining that an issue needed to be resolved. I determined that HTTPS still worked as it uses SSL and therefore would be difficult (and possibly illegal) for them to hijack those requests.

Solution:
SSH is an encrypted connection and therefore was still available to use. Using PuTTY, I set up a connection as a tunnel. Once this was done, I could configure my browsers to use the local socks5 connection to one of our development boxes (make sure you trust your proxy end point as all non-secured traffic will be visible).

Setup a New connection

Enabled compression

Add a local port (dynamic) that will be used for forwarding

Once the port has been added

Note: These are the minimal settings and can be configured further depending on your needs.

This worked (with obvious increased latency due to another node between end points) and allowed me to get access to all HTTP web sites. However, I wanted to take this further for applications like Spotify without configuring each one independently. After some looking around as programs like Widecap, I determined that it would probably be something natively supported by Windows. Here is how I went about setting that.

Click the Internet Icon in the lower right

Click the Network Sharing Center Link

Click on Internet Options Link

Click the Connections tab and then click the LAN settings button

Check "Use a proxy server..." and then click the "Advanced" button

If you are doing 1 socks5 proxy like I am, clear all other addresses and add the local address and forwarded port from earlier.
There are a lot of additional settings, but this should work.

I strongly discourage trying to use this to circumvent employers from knowing of your activities, or for using this to try and remain anonymous online.

Wednesday, October 2, 2013

Laravel 4: Seeding Large CSV Files Using MySQL Load Data

Problem:
I wanted to quickly populate some tables using some large CSVs (400k+ records) but parsing the files and importing each line was out of the question and doing one mass insert would have used up a lot of memory. The only good solution is using MySQL's LOAD DATA functionality which can import the data within seconds. But figuring out how to do this with Laravel was not easy.

Solution:
When trying to execute the query using DB::statement() I kept getting met with an exception from MySQL saying that I had unbuffered queries active. This displayed with a suggestion of using a PDOStatement. After some searching the internet and trying some things, I found a working solution.

$csv = app_path().DIRECTORY_SEPARATOR."database".DIRECTORY_SEPARATOR."resources".DIRECTORY_SEPARATOR."locations.csv";

$query = sprintf("LOAD DATA INFILE '%s' INTO TABLE locations FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '\"' ESCAPED BY '\"' LINES TERMINATED BY '\\n' IGNORE 0 LINES (`location_id`, `country`, `region`, `city`, `postal_code`, `lat`, `lng`, `metro_code`, `area_code`)", addslashes($csv));

DB::connection()->getpdo()->exec($query);