tag:blogger.com,1999:blog-41860745659610604372019-01-14T07:22:13.252-07:00The Abstracts of My BrainA developer's programming notes and solutionsMichael Corrigannoreply@blogger.comBlogger122125tag:blogger.com,1999:blog-4186074565961060437.post-18254397500706433212019-01-09T10:57:00.004-07:002019-01-09T11:39:38.093-07:00LTI Signature Fails - Carriage Returns, Newlines, and OAuth Signatures<b>Problem: </b><br /><br />While writing an LTI integration tool, I decided to run a battery of true LTI payloads from various LMS systems and see if I could produce the same signature. While running these payloads via automation, I found that some payloads would fail to produce the same signature. After ensuring that my encoding was using the agreed standard RFC 3986, I looked to narrow in on a specific LMS like Moodle or Blackboard. The signature fails were not confined to a specific LMS, but rather all contained the same single non-visible character.<br /><br /><br /><b>Solution:</b><br /><br />The payloads failing to produce a correct signature happened to contain a carriage return (<span style="font-family: "courier new" , "courier" , monospace;">\r</span>) followed by a new line(<span style="font-family: "courier new" , "courier" , monospace;">\n</span>). The <span style="font-family: "courier new" , "courier" , monospace;">\r\n</span> line termination sequence is commonly used by Microsoft. Suspicious of the carriage return, I removed it from the payloads, then reprocessed the signatures. It was successful. So now understanding what caused the problem, I decided to narrow in to the why.<br /><br /><b>LTI Process (Simple Version)</b><br />The LTI flow originates from the LMS also known as the Tool Consumer (TC), the TC will generate a payload of data consisting of key/value pairs and then sign the data using a shared secret. This signature uses OAuth. Once the data has been created it is generally injected into a user's browser page inside a form element of type POST and an action pointing to the Tool Provider's (TP) endpoint. Once this data is in the form, it will be submitted either automatically or manually. The receipient, which is the TP, takes this payload of data and verifies the data has not been changed by using the shared secret to recreate the signature. If the signature matches the one provided, the data can be trusted.<br /><br /><b>Dirty Little Microsoft Browser</b><br />The problem we see is actually caused by the browser attempting to format the data as it is injected into the form and newlines are preceded by a carriage return. This actually makes sense if the browser is going to display the data to the user, as Windows uses these carriage returns.<br /><br />At some point, it appears that the issue was corrected for Edge, but current LTI payloads make me suspect that it is still an issue. (See: https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/16221536/)<br /><br /><b>Coding Defensively</b><br />Unfortunately, we can't just always remove carriage returns prior to signing our payload. This is because a lot of data in the payload is, in fact, entered by an user who might be using a browser that uses carriage returns. In this case, the data will most likely be signed with the carriage returns in place as few implementations clean up these returns prior to signing.<br /><br />In order to handle these carriage return injections, we are going to have to check both possibilities. First, we assume that the data provided is correct for signing. The payloads may not contain carriage returns or the possibly no newlines at all. If this fails, we second try to remove only carriage returns that are immediately followed by a newline character.<br /><br /><br /><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-69388253142424903172017-02-10T13:55:00.000-07:002017-02-10T13:55:01.457-07:00Android: HAXM hypervisor Error<b>Problem:</b><br /><br />While building my project in Android Studio, I got the following error:<br /><br /><span style="font-family: Courier New, Courier, monospace;">emulator: ERROR: Unfortunately, there's an incompatibility between HAXM hypervisor and VirtualBox 4.3.30+ which doesn't allow multiple hypervisors to co-exist.</span><br /><br /><br /><b>Solution:</b><br /><br />This turned out to be due to some vagrant instances I was running on my system. After halting my vagrant machines, Android Studio was able to build the project properly.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-91121909591095086742016-12-23T23:28:00.001-07:002016-12-23T23:28:28.034-07:00Adobe Encore CS6 - internal software error: Vobulator\TitlePlanner\CVOBUPlanner.cpp, line 332<b>Problem:</b><br />While working on a DVD for a local commercial I assisted with, I came across a strange error while trying to build the project.<br /><br /><span style="font-family: Courier New, Courier, monospace;">internal software error: Vobulator\TitlePlanner\CVOBUPlanner.cpp, line 332</span><br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://2.bp.blogspot.com/-lst-kMbvv4I/WF4Vdn883WI/AAAAAAAAH7A/Mn6snv_YHbUza9rwo_qJtu6Fmz0rAvRAgCLcB/s1600/Encore332.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://2.bp.blogspot.com/-lst-kMbvv4I/WF4Vdn883WI/AAAAAAAAH7A/Mn6snv_YHbUza9rwo_qJtu6Fmz0rAvRAgCLcB/s1600/Encore332.JPG" /></a></div><br /><b><br /></b><b>Solution:</b><br />After reading forums and various websites and trying their suggested tips (removing overlapping chapter markers, etc). I decided to determine the problem through the process of elimination. I first determined the issue had to do with some photos that I had Encore using for a Slideshow. I removed them each trying to determine the error and then tried some different settings for the Slideshow component.<br /><br />It turned out the issue was that my slide duration was less than 6 seconds long and Encore did not like that. Once I changed my slide duration to be 6 seconds, the project built properly.<br /><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-36348716686167813482016-09-12T16:04:00.004-06:002016-09-12T16:04:50.305-06:00Salesforce REST API: Unable to read request: No content to map to Object due to end of inputWhile working on an integration with the Salesforce REST API, I was working with their batch API and ran into this error message:<br /><br /><pre class="xdebug-var-dump" dir="ltr"><span style="color: #cc0000;">Unable to read request: No content to map to Object due to end of input</span></pre><pre class="xdebug-var-dump" dir="ltr"><span style="color: #cc0000;"><br /></span></pre><pre class="xdebug-var-dump" dir="ltr"><span style="font-family: Times; white-space: normal;">At first I assumed this was because I wasn't passing something I should have been, but it turned out that I was passing something it didn't like. I removed fields from my payload that I wasn't completely sure about and it suddenly started working for me. </span></pre><pre class="xdebug-var-dump" dir="ltr"><span style="font-family: Times; white-space: normal;"><br /></span></pre><pre class="xdebug-var-dump" dir="ltr"><span style="font-family: Times; white-space: normal;">Hope this helps someone else in the same bind.</span></pre>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-40074141193489532512016-04-09T08:26:00.001-06:002016-04-09T08:27:23.388-06:00Composer Update Failed on Dreamhost - killed for excessive resource usage<b>Problem:</b><br />While working on a pet project, I decided to use Laravel 5 on my <a href="https://www.dreamhost.com/r.cgi?1158188" rel="nofollow" target="_blank">Dreamhost</a> shared server (where most of my prototype/hobbies go). I was able to get composer running fine with the exception of when I would try to run <span style="font-family: "courier new" , "courier" , monospace;">composer update</span>. Composer can sometimes take a bit of resources, and unfortunately <a href="https://www.dreamhost.com/r.cgi?1158188" rel="nofollow" target="_blank">Dreamhost</a> shared servers are pretty slim. I kept getting the following message.<br /><br /><blockquote class="tr_bq"><span style="font-family: "courier new" , "courier" , monospace;">Loading composer repositories with package information<br />Updating dependencies (including require-dev)<br /><br />Yikes! One of your processes (php, pid 3726) was just killed for excessive resource usage.<br />Please contact DreamHost Support for details.<br /><br />Killed</span></blockquote><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><b>Solution:</b><br />It turns out that one of the heaviest parts of running <span style="font-family: "courier new" , "courier" , monospace;">composer update</span> is the point as which the composer.lock file is updated and PHP tries to determine new packages, etc. If we generate the composer.lock file outside of <a href="https://www.dreamhost.com/r.cgi?1158188" rel="nofollow" target="_blank">Dreamhost</a> (like on your local machine) and then move the file over, we can bypass this by running <span style="font-family: "courier new" , "courier" , monospace;">composer install</span>. For this pet project, I just add the composer.lock to my source version control to make things simpler when moving the file back and forth.<br /><br />Good luck!Michael Corrigannoreply@blogger.com1tag:blogger.com,1999:blog-4186074565961060437.post-1422406786318669322016-02-26T13:33:00.001-07:002016-02-26T13:34:26.537-07:00Ionic V2 - Could not find any version that matches com.android.support:support-v4<b>Problem: </b><br />Lately I've been playing around with mobile app development using <a href="http://ionicframework.com/" target="_blank">Ionic</a> V2 (with <a href="https://cordova.apache.org/" target="_blank">Cordova</a>). While testing it on my older mobile device (Galaxy S4) I noticed that the native web view (Android browser) seems to be slow and didn't play any of the Material Design animations. I found <a href="https://crosswalk-project.org/" target="_blank">CrossWalk</a> and started trying to add it to my project:<br /><br />> <span style="font-family: "courier new" , "courier" , monospace;">ionic browser add crosswalk</span><br /><br />I was able to get older versions working (14, 15), but when trying to use CrossWalk 16, I ran into an error:<br /><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><span style="font-family: "courier new" , "courier" , monospace;">ANDROID_HOME=/home/me/android-sdk-linux</span><br /><span style="font-family: "courier new" , "courier" , monospace;">JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64</span><br /><span style="font-family: "courier new" , "courier" , monospace;">embedded</span><br /><span style="font-family: "courier new" , "courier" , monospace;">org.xwalk:xwalk_core_library:16+</span><br /><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><span style="font-family: "courier new" , "courier" , monospace;">FAILURE: Build failed with an exception.</span><br /><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><span style="font-family: "courier new" , "courier" , monospace;">* What went wrong:</span><br /><span style="font-family: "courier new" , "courier" , monospace;">A problem occurred configuring root project 'android'.</span><br /><span style="font-family: "courier new" , "courier" , monospace;">> Could not resolve all dependencies for configuration ':_armv7DebugCompile'.</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> > Could not find any version that matches com.android.support:support-v4:[13.0.0,).</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> Searched in the following locations:</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> https://repo1.maven.org/maven2/com/android/support/support-v4/maven-metadata.xml</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> https://repo1.maven.org/maven2/com/android/support/support-v4/</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> https://download.01.org/crosswalk/releases/crosswalk/android/maven2/com/android/support/support-v4/maven-metadata.xml</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> https://download.01.org/crosswalk/releases/crosswalk/android/maven2/com/android/support/support-v4/</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> file:/home/me/android-sdk-linux/extras/google/m2repository/com/android/support/support-v4/maven-metadata.xml</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> file:/home/me/android-sdk-linux/extras/google/m2repository/com/android/support/support-v4/</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> Required by:</span><br /><span style="font-family: "courier new" , "courier" , monospace;"> :android:unspecified > org.xwalk:xwalk_core_library:16.45.421.19</span><br /><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><span style="font-family: "courier new" , "courier" , monospace;">* Try:</span><br /><span style="font-family: "courier new" , "courier" , monospace;">Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.</span><br /><span style="font-family: "courier new" , "courier" , monospace;"><br /></span><span style="font-family: "courier new" , "courier" , monospace;">BUILD FAILED</span><br /><br /><b>Solution:</b><br />It turned out I didn't have everything I needed installed from the Android SDK Manager. I found that I needed to have from <i>Extra</i>:<br /><br /><ul><li>Android Support Library</li><li>Google Repository</li><li>Local Maven repository for Support Library</li></ul><br /> Once I had these installed, my build was able to succeed and the app feels slightly more responsive but I still do not get Material Design animations.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-34184983824002295442015-05-19T15:21:00.001-06:002015-05-19T15:21:36.268-06:00cURL on Windows: cURL error 60: SSL certificate problem: unable to get local issuer certificate<b>Problem:</b><br /><br />While running some unit tests on a managed project, I ran across an issue from the Guzzle library. <br /><br /><span style="font-family: Courier New, Courier, monospace;">cURL error 60: SSL certificate problem: unable to get local issuer certificate</span><br /><br /><br /><b>Solution:</b><br /><br />The latest version of cURL does not ship with a bundle of root certificates. This is due to security concerns in the past. Instead, they have you provide the root certificates that should be valid as certificate authorities. Most of us are really only concerned with the main ones likes Equifax, GlobalSign, and Verisign.<br /><br />There are several ways to solve this problem, but what I decided to do was allow PHP on my system to always reference the same PEM file instead of other methods (like telling cURL not validate the peer certificate - please note this is a bad idea!).<br /><br />In order to solve this problem, we need to obtain a version of this cacert.pem file that has not been corrupted. I found mine from <a href="http://curl.haxx.se/docs/caextract.html" target="_blank">the cURL web site</a> which links to Mozilla.orgs CAs.<br /><br />Once I had downloaded the pem file, I placed it in a common development directory on my Windows machine.<br /><br />Last, we just need to tell PHP where to look for this file. Open your php.ini file and set the following property*:<br /><br /><span style="font-family: Courier New, Courier, monospace;">openssl.cafile="C:\dev\cacert.pem"</span><br /><br /><br />Hope this solves some head scratching.<br /><br /><br /><br />*This may change if you use something other than OpenSSL.<br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-10704774916937925832015-04-13T11:29:00.003-06:002015-04-13T11:29:55.642-06:00Git shows modified files but no local changes have been made<b>Problem:</b><br /><br />I checked out updated my master branch to work on some hot fixes, but one I had pulled in the latest master branch, I found two files which were being tracked as modified. I didn't have any local changes to these files before. Where did these come from?<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-691g9QHx69s/VSv7u1np7vI/AAAAAAAAHEY/ePH0snJyM68/s1600/before_fix.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-691g9QHx69s/VSv7u1np7vI/AAAAAAAAHEY/ePH0snJyM68/s1600/before_fix.JPG" height="132" width="640" /></a></div><br /><br /><br /><br /><b>Solution:</b><br />For me this was due to git not handling case sensitive changes. Another developer had changed an upper case letter to lower case for a file name. Here is how I solved the problem.<br /><br />Rename the directory in question to something else. Git should now show the files as deleted. Specifically `git rm` the directory <b>with the old name and casing</b> (you may need to force it) and run `git status` to be sure that only the now incorrect casing directory is staged for commit. Now commit your changes.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-2YpM6QcaB0Q/VSv7vAZLAyI/AAAAAAAAHFI/ljxAqyXHhiQ/s1600/blowaway_files.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-2YpM6QcaB0Q/VSv7vAZLAyI/AAAAAAAAHFI/ljxAqyXHhiQ/s1600/blowaway_files.JPG" height="76" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-Q6ePrP3joI8/VSv7wLCcq3I/AAAAAAAAHEo/Zch8GvzvDPA/s1600/show%2Bdifferent%2Bfiles.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-Q6ePrP3joI8/VSv7wLCcq3I/AAAAAAAAHEo/Zch8GvzvDPA/s1600/show%2Bdifferent%2Bfiles.JPG" height="232" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-1lMYglTKpnc/VSv7vaDXLSI/AAAAAAAAHEg/OORPTLaFUgA/s1600/commit.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-1lMYglTKpnc/VSv7vaDXLSI/AAAAAAAAHEg/OORPTLaFUgA/s1600/commit.JPG" height="104" width="640" /></a></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-w9twsufCKeI/VSv7wxg0qZI/AAAAAAAAHEs/pj2TxLlVZFQ/s1600/staged_correct_naming.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-w9twsufCKeI/VSv7wxg0qZI/AAAAAAAAHEs/pj2TxLlVZFQ/s1600/staged_correct_naming.JPG" height="164" width="640" /></a></div><br />Manually rename the directory back to the expected format (the newest format) of it's title. Run `git status` again. If you still see one or more of those files as modified, checkout the latest version of the file. <b>Note:</b> If the directory is no longer around, manually create it with the correct casing and then checkout the files it has from your repo.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-K3gWRUTr358/VSv7v1HlMAI/AAAAAAAAHEk/z6WXLdq1bfs/s1600/file%2Bcheckouts.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-K3gWRUTr358/VSv7v1HlMAI/AAAAAAAAHEk/z6WXLdq1bfs/s1600/file%2Bcheckouts.JPG" height="18" width="640" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="http://2.bp.blogspot.com/-FBcCjevbRxQ/VSv8xHIdr8I/AAAAAAAAHFU/zioI-SdIbRY/s1600/checkout_app.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://2.bp.blogspot.com/-FBcCjevbRxQ/VSv8xHIdr8I/AAAAAAAAHFU/zioI-SdIbRY/s1600/checkout_app.JPG" height="22" width="640" /></a></div><br /><br />Now check your project state. You should have a clean state with 1 commit ahead of master.<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-aByBmBobuPQ/VSv7vBfUm5I/AAAAAAAAHEc/J0GqOuBNNgo/s1600/all_fixed.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-aByBmBobuPQ/VSv7vBfUm5I/AAAAAAAAHEc/J0GqOuBNNgo/s1600/all_fixed.JPG" height="100" width="640" /></a></div><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-82421297577987921112015-03-31T16:03:00.002-06:002015-03-31T16:03:46.286-06:00Composer Update: fatal: No such remote 'composer'<b>Problem: </b><br /><br />While working on a composer library for a client, I ran into an issue where running the command:<br /><br /><span style="font-family: Courier New, Courier, monospace;">composer update</span><br /><br />Caused an error to be printed on the screen that read:<br /><br /><span style="font-family: Courier New, Courier, monospace;">fatal: No such remote 'composer'</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: inherit;"><b>Solution:</b></span><br /><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;">After playing around with it for some time, I went to the web to see if I could find any solutions. I found <a href="https://github.com/composer/composer/issues/2108" rel="nofollow" target="_blank">this thread</a>.</span><br /><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;">The solution ended up that I needed to just remove the .git folder from the library while it resided in the vendor directory. (I actually just renamed it, but that seemed to do the same thing).</span><br /><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;"><br /></span>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-42745205220460079122015-03-09T09:10:00.001-06:002015-03-09T09:10:17.674-06:00Python - Unable to find vcvarsall.bat<b>Problem:</b><br />Working on a quick prototype using maxmind, I wanted to use my new python skills. The geoip2 module looked like a good place to start, but I had to install the maxminddb module first. Trying to install that using pip gave me the following error:<br /><br />UserWarning: Unknown distribution option: "bugtrack_url"<br />...<br />error: Unable to find vcvarsall.bat<br /><br /><br /><b>Solution:</b><br />Looking online I found a couple SO questions that were exactly the same as mine. "How to I set vcvarsall.bat?" Turns out this is because when python builds the extension is wants to build it for Windows using the same C Runtime libraries python itself was built with. Several people indicated that the solution here was to install Visual C++ 2008 Express Edition (but seeing as it is now 2014, this was somewhat difficult to find).<br /><br />To install these C Runtime libraries, download <a href="http://go.microsoft.com/?linkid=7729279" target="_blank">Visual C++ 2008 Express Edition</a>.<br /><br />Once you have it installed, you will need to restart your machine (or do something to allow the new environment variable of VS90COMNTOOLS to take).<br /><br />Now you should be able to install your new extension using pip.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-14778329229506162192015-03-09T09:09:00.000-06:002015-03-09T09:09:05.969-06:00WordPress Slow Page Loads - JetPack<b>Problem:</b><br />My wife has a WordPress blog and over time everything has been slowing down until the site pretty much stopped working all together.<br /><br /><b>Solution:</b><br />Optimizing WordPress is a very large topic with many resources online. Following a couple different web site suggestions, I decided to start with the plugins as these are known to cause issues. My wife had about 30 installed. After <a href="http://perishablepress.com/quickly-disable-or-enable-all-wordpress-plugins-via-the-database/" rel="nofollow" target="_blank">deactivating all the plugins</a>, things started working much better. I installed <a href="http://code.tutsplus.com/tutorials/how-to-analyze-your-wordpress-installations-performance--wp-26472" rel="nofollow" target="_blank">some plugins</a> to assist with determining the plugin(s) causing the trouble.<br /><br />After enabling plugins one-at-a-time and profiling the page loading using P3, I discovered that JetPack was causing the blog to have some major slow down. Little did I know, but many modules in JetPack were enabled by default and weren't being used. In fact, page load time went from <b>0.10 seconds to 1.5 seconds per page</b>.<br /><br /><b>Disable Unused JetPack Modules (or JetPack)</b><br />If you click "Learn More" you will then see a new button called Deactivate. This button will turn off this module and will help to make your blog faster. I strongly suggest choosing to deactivate only the bare minimum to reduce unnecessary resource usage. If you can, do not use the JetPack plugin. Once the developers are able to increase their code performance, it will be worth looking at again.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-66897460804168281552015-03-04T16:18:00.001-07:002015-03-04T16:18:06.663-07:00Issue Updating Vagrant 1.6.3 to 1.7.2 on Windows: Bundler reporting dependency can't be found.<b>Problem:</b><br /><br />When uninstalling the old version and installing the new version of vagrant (along with the requires system restarts), I was met by this message when trying to boot up my machines.<br /><br /><br /><pre style="background-color: #f7f7f7; border-radius: 3px; box-sizing: border-box; color: #333333; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.8999996185303px; font-stretch: normal; line-height: 1.45; margin-bottom: 16px; overflow: auto; padding: 16px; word-wrap: normal;"><code style="background: transparent; border-radius: 3px; border: 0px; box-sizing: border-box; display: inline; font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; font-size: 11.8999996185303px; line-height: inherit; margin: 0px; max-width: initial; overflow: initial; padding: 0px; word-break: normal; word-wrap: normal;">Bundler, the underlying system used to manage Vagrant plugins,<br />is reporting that a plugin or its dependency can't be found.<br />This is usually caused by manual tampering with the 'plugins.json'<br />file in the Vagrant home directory. To fix this error, please<br />remove that file and reinstall all your plugins using `vagrant<br />plugin install`.</code></pre><br /><br />Somewhat confused, I tried running the uninstall/reinstall of Vagrant again, but nothing changed.<br /><br /><br /><br /><b>Solution:</b><br /><br />Turns out that I just needed to remove the .vagrant.d folder from my Windows User directory.<br /><br />For me this was: C:\Users\Mike\.vagrant.d<br /><br />Then I installed Vagrant one last time. After a reboot, my virtual machines booted up again and I am back in business.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-40158652475100887722015-03-03T21:16:00.001-07:002015-03-03T21:18:55.917-07:00MySQL Efficiently Generating Millions of Random Registration Codes<b>Problem:</b><br /><br />While working with a company, I decided to look into how they were generating their registration codes which were used to allow users to pre-purchase access to their platform. The programming behind this was written in PHP and utilized MySQL to store the codes.<br /><br />The database structure was set up to allow for each code to be unique. The PHP code would handle each code generated one-at-a-time. First, it would generate a random number-letter combination to a set length and then it would query the database to see if such a code existed. If the query returned no results, it would then insert the new code into the table. If a match existed, it would drop the code and try a new one.<br /><br />As you can see generating many codes using this process would be highly inefficient. This meant that we would actually performs up to two queries for each code so for 100,000 codes, we would likely be 200,000+ queries against our database.<br /><br /><br /><b>Solution:</b><br /><br />Without really changing too much, we can optimize this process to running maybe 5 queries for the same 100,000 codes (and prevent an unlikely race condition when this table grew super large). First we have to think about what MySQL can do that would really save us with mass queries. MySQL can actually process a large group of inserts all at one time. The problem is that we need to then consider the duplicate codes. To handle these, we simply ignore the duplicates using MySQL <span style="font-family: Courier New, Courier, monospace;">INSERT IGNORE INTO ... </span>But we still need to generate all 100,000 codes still, right? No problem, we can ask mysql how many records actually got inserted into the database, then use our original number (100,000) and subtract the successful ones. This tells us how many we still need to generate and insert into the database. To handle this we wrap the process in a loop. It looks something like this:<br /><br /><span style="font-family: Courier New, Courier, monospace;"><?php</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">/**</span><br /><span style="font-family: Courier New, Courier, monospace;"> * Generates code, verifies code is unique and saves code in DB</span><br /><span style="font-family: Courier New, Courier, monospace;"> *</span><br /><span style="font-family: Courier New, Courier, monospace;"> * @param int $batch_id</span><br /><span style="font-family: Courier New, Courier, monospace;"> * @param int $code_count</span><br /><span style="font-family: Courier New, Courier, monospace;"> * @return string</span><br /><span style="font-family: Courier New, Courier, monospace;"> */</span><br /><span style="font-family: Courier New, Courier, monospace;"> public function add_code_batch($code_count)</span><br /><span style="font-family: Courier New, Courier, monospace;"> {</span><br /><span style="font-family: Courier New, Courier, monospace;"> $pending_codes = $</span><span style="font-family: 'Courier New', Courier, monospace;">code_count</span><span style="font-family: Courier New, Courier, monospace;">;</span><br /><span style="font-family: Courier New, Courier, monospace;"> while ($pending_codes){</span><br /><span style="font-family: Courier New, Courier, monospace;"> $mass_insert = array();</span><br /><span style="font-family: Courier New, Courier, monospace;"> for($i = 0; $i < $pending_codes; $i++){</span><br /><span style="font-family: Courier New, Courier, monospace;"> $code = $this->generate_code(); // @TODO: Add this</span><br /><span style="font-family: Courier New, Courier, monospace;"> $mass_insert[] = "('{$code}')";</span><br /><span style="font-family: Courier New, Courier, monospace;"> }</span><br /><span style="font-family: Courier New, Courier, monospace;"> // try to mass insert them all</span><br /><span style="font-family: Courier New, Courier, monospace;"> $this->db->query("INSERT IGNORE INTO `codes` (code) VALUES ".implode(',', $mass_insert));</span><br /><span style="font-family: Courier New, Courier, monospace;"> $pending_codes = $</span><span style="font-family: 'Courier New', Courier, monospace;">code_count</span><span style="font-family: Courier New, Courier, monospace;"> - $this->db->affected_rows();</span><br /><span style="font-family: Courier New, Courier, monospace;"> }</span><br /><span style="font-family: Courier New, Courier, monospace;"></span><br /><span style="font-family: Courier New, Courier, monospace;">}</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">?></span><br /><br />Keep in mind the above code may need to be modified to fit your framework and code structure (like including batch IDs or addition information). As you can see, we have drastically improved from the previous situation.<br /><br />I'm not saying that this can't be optimized more or that it is the best possible solution, but it is a step forward.<br /><br />Happy coding.<br /><br /><br /><i>Possible things to explore for better performance:</i><br /><br /><ul><li>Generating codes through SQL</li><li>How intense the code generation process is</li><li>Cost of storing codes in memory between generation and transaciton</li></ul><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-21600646909953561142014-07-10T09:39:00.000-06:002014-07-10T09:39:07.443-06:00Bitnami Moodle AWS Username and Password<b>Problem:</b><br />While working on some software that integrates with popular LMS frameworks, I wanted to have a server which I could test Moodle on. I found a community image published by Bitnami and launched an EC2 image from it. When I went to login, I was not sure the login credentials.<br /><br /><b>Solution:</b><br />After some searching, I realized that Bitnami had a page that <a href="https://bitnami.com/cloud/bitnami-applications-in-the-cloud" target="_blank">listed all their images along with the default credentials</a> for each one. I tried the one for Moodle and it worked.<br /><br />The default credentials I was look for were:<br />username: user<br />password: bitnamiMichael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-29823613318180911622014-04-17T13:46:00.002-06:002014-04-17T13:46:48.584-06:00Laravel 4: CSRF TokenMismatchException when using stored form values<b>Problem: </b><br />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.<br /><br /><b>Solution:</b><br />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.<br /><br /><span style="font-family: Courier New, Courier, monospace;">Session::regenerate();</span><br /><br /><i>Note: </i>This problem only existed when users were not logged in, otherwise regenerating the session ID might have interrupted their session.<br /><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-82311032513507193452014-03-03T10:06:00.003-07:002014-03-03T10:06:33.982-07:00Google Maps API Controls Do Not Display with Bootstrap<b>Problem:</b><br />Adding a Google Maps API control to a web page, I found that the controls were failing to render properly. They looked like this:<br /><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://1.bp.blogspot.com/-kbWfuV5STus/UxS2PSb6zXI/AAAAAAAAGLM/1H2zNmobFoI/s1600/google_maps_issue2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://1.bp.blogspot.com/-kbWfuV5STus/UxS2PSb6zXI/AAAAAAAAGLM/1H2zNmobFoI/s1600/google_maps_issue2.PNG" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><b><br /></b></div><div class="separator" style="clear: both; text-align: left;"><b>Solution:</b></div><div class="separator" style="clear: both; text-align: left;">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.</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both;"><span style="font-family: Courier New, Courier, monospace;">.gm-style img { max-width: none; }</span></div><div class="separator" style="clear: both;"><span style="font-family: Courier New, Courier, monospace;">.gm-style label { width: auto; display: inline; }</span></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/-dpeSwhbJwB8/UxS2Pa0Ez_I/AAAAAAAAGLQ/ya4Ihi94R_A/s1600/google_maps_issue_fixed.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/-dpeSwhbJwB8/UxS2Pa0Ez_I/AAAAAAAAGLQ/ya4Ihi94R_A/s1600/google_maps_issue_fixed.PNG" /></a></div><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-23341994989863574352014-02-19T10:09:00.003-07:002014-02-19T11:11:14.079-07:00Laravel 4: Model Hydrate<b>Problem:</b><br />While converting some older Laravel code, I ran into an issue where the <span style="font-family: Courier New, Courier, monospace;">hydrate</span> method had been removed. My usage was similar to this:<br /><br /><span style="font-family: 'Courier New', Courier, monospace;">$raw_result =</span><span style="font-family: 'Courier New', Courier, monospace;"> </span><span style="font-family: Courier New, Courier, monospace;">DB::query(...);</span><br /><span style="font-family: Courier New, Courier, monospace;">$hydrated_models = Model::hydrate(new Model(), $data);</span><br /><br /><br /><b>Solution:</b><br />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 <span style="font-family: Courier New, Courier, monospace;"><a href="https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L382" rel="nofollow" target="_blank">newFromBuilder</a></span> method which can be used as follows:<br /><br /><span style="font-family: Courier New, Courier, monospace;">$raw_result = DB::select(...);</span><br /><span style="font-family: Courier New, Courier, monospace;">$collection = new \Illuminate\Database\Eloquent\Collection();</span><br /><span style="font-family: Courier New, Courier, monospace;">foreach ($raw_result as $raw_obj)</span><br /><span style="font-family: Courier New, Courier, monospace;">{</span><br /><span style="font-family: Courier New, Courier, monospace;"> $model = new Model();</span><br /><span style="font-family: Courier New, Courier, monospace;"> $collection->add($model->newFromBuilder(</span><span style="font-family: 'Courier New', Courier, monospace;">$raw_obj</span><span style="font-family: 'Courier New', Courier, monospace;">));</span><br /><span style="font-family: Courier New, Courier, monospace;">}</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: inherit;">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. </span><br /><span style="font-family: inherit;"><br /></span><span style="font-family: inherit;">For example: </span><br /><span style="font-family: inherit;"><br /></span><span style="font-family: Courier New, Courier, monospace;">use Illuminate\Database\Eloquent\Collection;</span><br /><span style="font-family: Courier New, Courier, monospace;">class BaseModel extends Eloquent</span><br /><span style="font-family: Courier New, Courier, monospace;">{</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;"> /**</span><br /><span style="font-family: Courier New, Courier, monospace;"> * Hydrate method</span><br /><span style="font-family: Courier New, Courier, monospace;"> * </span><br /><span style="font-family: Courier New, Courier, monospace;"> * @param array $data</span><br /><span style="font-family: Courier New, Courier, monospace;"> * @return Illuminate\Database\Eloquent\Collection</span><br /><span style="font-family: Courier New, Courier, monospace;"> */</span><br /><span style="font-family: Courier New, Courier, monospace;"> static public function hydrate($data)</span><br /><span style="font-family: Courier New, Courier, monospace;"> {</span><br /><span style="font-family: Courier New, Courier, monospace;"> // get calling class so we can hydrate using that type</span><br /><span style="font-family: Courier New, Courier, monospace;"> $klass = get_called_class();</span><br /><span style="font-family: Courier New, Courier, monospace;"> </span><br /><span style="font-family: Courier New, Courier, monospace;"> // psuedo hydrate</span><br /><span style="font-family: Courier New, Courier, monospace;"> $collection = new Collection();</span><br /><span style="font-family: Courier New, Courier, monospace;"> foreach ($data as </span><span style="font-family: 'Courier New', Courier, monospace;">$raw_obj</span><span style="font-family: Courier New, Courier, monospace;">)</span><br /><span style="font-family: Courier New, Courier, monospace;"> {</span><br /><span style="font-family: Courier New, Courier, monospace;"> $model = new $klass;</span><br /><span style="font-family: Courier New, Courier, monospace;"> $collection->add($model->newFromBuilder(</span><span style="font-family: 'Courier New', Courier, monospace;">$raw_obj</span><span style="font-family: Courier New, Courier, monospace;">));</span><br /><span style="font-family: Courier New, Courier, monospace;"> }</span><br /><span style="font-family: Courier New, Courier, monospace;"> return $collection;</span><br /><br /><span style="font-family: Courier New, Courier, monospace;"> }</span><br /><span style="font-family: Courier New, Courier, monospace;">}</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">class User extends BaseModel</span><br /><span style="font-family: Courier New, Courier, monospace;">{</span><br /><span style="font-family: Courier New, Courier, monospace;"> /* ... */</span><br /><span style="font-family: Courier New, Courier, monospace;">}</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">// Usage of hydrate</span><br /><span style="font-family: Courier New, Courier, monospace;">$user_collection = User::hydrate($data);</span><br /><span style="font-family: inherit;"><br />Along with Model::hydrate, the DB::query method no longer exists. <a href="http://blog.corrlabs.com/2013/09/migrating-from-laravel-3-to-laravel-4.html">See more changes happening when upgrading from Laravel 3 to Laravel 4.</a></span>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-90091815245427592012014-02-04T23:55:00.001-07:002014-02-04T23:55:12.060-07:00TomatoCart: Changing text (Fixing maintenance mode message)<b>Problem:</b><br />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".<br /><br /><b>Solution:</b><br />It was simple enough, I had to edit the English language file and edit the database stored English phrase.<br /><br /><br /><ol><li>Fix the language file: <span style="font-family: Courier New, Courier, monospace;">includes/languages/en_US.xml</span></li><li>Fix the stored database value: <span style="font-family: Courier New, Courier, monospace;">SELECT * FROM languages_definitions WHERE definition_value LIKE '%latter%';</span></li><li><span style="font-family: inherit;">Clear the cache files in the admin. </span><span style="font-family: Arial, Helvetica, sans-serif;">Start > Tools > Cache Control</span></li></ol>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-58213519730086821472013-12-31T15:17:00.002-07:002013-12-31T15:17:31.015-07:00Python: xlrd - bad magic number for file header<b>Problem:</b><br />Working in <a href="http://www.pylonsproject.org/" target="_blank">Pylons</a> for a project, I built a tool to allow file uploads and one feature used <a href="https://pypi.python.org/pypi/xlrd" target="_blank">xlrd</a> to convert Excel files to CSV files. When I went to transform these files using <a href="https://pypi.python.org/pypi/xlrd" target="_blank">xlrd</a>, I got an error saying: bad magic number for file header.<br /><br /><b>Solution:</b><br />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.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-36520599239596719922013-10-29T16:44:00.002-06:002013-10-29T16:44:52.059-06:00SSH Tunnel All Network Traffic - Windows 7<b>Problem:</b><br />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.<br /><br /><b>Solution:</b><br />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).<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-qvKUULi_hRs/UnA2yCCLYlI/AAAAAAAAGFo/via8ZG4scSo/s1600/putty1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-qvKUULi_hRs/UnA2yCCLYlI/AAAAAAAAGFo/via8ZG4scSo/s1600/putty1.png" height="307" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Setup a New connection</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-F_H_ZZZYFeg/UnA2yCJ1U9I/AAAAAAAAGFw/gK0sVhXUMOk/s1600/putty2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-F_H_ZZZYFeg/UnA2yCJ1U9I/AAAAAAAAGFw/gK0sVhXUMOk/s1600/putty2.png" height="307" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Enabled compression</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-HYem6lzM-LE/UnA2yS7v0vI/AAAAAAAAGFs/7JHRMOXOD3Q/s1600/putty3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/-HYem6lzM-LE/UnA2yS7v0vI/AAAAAAAAGFs/7JHRMOXOD3Q/s1600/putty3.png" height="307" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Add a local port (dynamic) that will be used for forwarding</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-Kp9Z-GeyVks/UnA2y31YuPI/AAAAAAAAGF4/RQSwctxNj9M/s1600/putty4.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://3.bp.blogspot.com/-Kp9Z-GeyVks/UnA2y31YuPI/AAAAAAAAGF4/RQSwctxNj9M/s1600/putty4.png" height="307" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Once the port has been added</td></tr></tbody></table><br />Note: These are the minimal settings and can be configured further depending on your needs.<br /><br />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.<br /><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-WzRtz41CvZQ/UnA4jcOkFdI/AAAAAAAAGG0/sQWaMZwefNg/s1600/win0.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/-WzRtz41CvZQ/UnA4jcOkFdI/AAAAAAAAGG0/sQWaMZwefNg/s1600/win0.png" height="38" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Click the Internet Icon in the lower right</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-d6DdL4VTsaE/UnA4OLbcZXI/AAAAAAAAGGM/Nty4w6EtIdA/s1600/win1.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-d6DdL4VTsaE/UnA4OLbcZXI/AAAAAAAAGGM/Nty4w6EtIdA/s1600/win1.png" height="320" width="223" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Click the Network Sharing Center Link</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://1.bp.blogspot.com/-JAwUogyLpt4/UnA4OnYlg_I/AAAAAAAAGGQ/xBhjn37xrTQ/s1600/win2.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://1.bp.blogspot.com/-JAwUogyLpt4/UnA4OnYlg_I/AAAAAAAAGGQ/xBhjn37xrTQ/s1600/win2.png" height="320" width="139" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Click on Internet Options Link</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://4.bp.blogspot.com/-VcKRBaZ37bI/UnA4Ou0yeTI/AAAAAAAAGGU/pFLmtyqMgM8/s1600/win3.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://4.bp.blogspot.com/-VcKRBaZ37bI/UnA4Ou0yeTI/AAAAAAAAGGU/pFLmtyqMgM8/s1600/win3.png" height="320" width="250" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Click the Connections tab and then click the LAN settings button</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://3.bp.blogspot.com/-sPazA7XuK2A/UnA4O6kC0WI/AAAAAAAAGGc/NgeTN317q5w/s1600/win4.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://3.bp.blogspot.com/-sPazA7XuK2A/UnA4O6kC0WI/AAAAAAAAGGc/NgeTN317q5w/s1600/win4.png" height="280" width="320" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">Check "Use a proxy server..." and then click the "Advanced" button</td></tr></tbody></table><br /><table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody><tr><td style="text-align: center;"><a href="http://2.bp.blogspot.com/-W1SODpRE_wA/UnA4PO8pQtI/AAAAAAAAGGs/kE4-v-IPjEo/s1600/win5.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="http://2.bp.blogspot.com/-W1SODpRE_wA/UnA4PO8pQtI/AAAAAAAAGGs/kE4-v-IPjEo/s1600/win5.png" height="320" width="298" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;">If you are doing 1 socks5 proxy like I am, clear all other addresses and add the local address and forwarded port from earlier.</td></tr></tbody></table>There are a lot of additional settings, but this should work.<br /><br /><b>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.</b>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-18560201037389079182013-10-02T23:02:00.004-06:002013-10-02T23:02:54.001-06:00Laravel 4: Seeding Large CSV Files Using MySQL Load Data<b>Problem:</b><br />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.<br /><br /><b>Solution:</b><br />When trying to execute the query using DB::statement() I kept getting met with an exception from MySQL saying that I had <i>unbuffered queries active</i>. This displayed with a suggestion of using a PDOStatement. After some searching the internet and trying some things, I found a working solution.<br /><br /><span style="font-family: Courier New, Courier, monospace;">$csv = app_path().DIRECTORY_SEPARATOR."database".DIRECTORY_SEPARATOR."resources".DIRECTORY_SEPARATOR."locations.csv";</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">$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));</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: Courier New, Courier, monospace;">DB::connection()->getpdo()->exec($query);</span><br /><br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-72018507784065672502013-09-14T15:47:00.002-06:002013-10-02T08:46:10.830-06:00Dynamic Relative Date Range<b>About Dynamic Relative Date-time Range</b><br />Dynamic Relative Date-time Range (also known as a Rolling Date Range) is a string formatted representation of a period of time relative to the present time in string form (like in an HTML form). Generally DRDR would be used in reporting environments as it provides a dynamic way to allow a predetermined selection.<br /><br />Using this form allows coders and non-coders to easily read and write relative ranges. This can also be easily stored in a database for automated reporting.<br /><br />This syntax requires a language with support similar to <a href="http://us1.php.net/manual/en/datetime.formats.relative.php" rel="nofollow" target="_blank">PHP's relative date syntax</a>.<br /><br /><b>General Rules</b><br />Caret (<span style="font-family: Courier New, Courier, monospace;">^</span>) represents the range separator always separating the starting relative date from the ending relative date. When you begin with a caret or end with a caret, the omitted value is assumed as "<span style="font-family: Courier New, Courier, monospace;">now</span>".<br /><br /><b>Example</b><br /><span style="font-family: Courier New, Courier, monospace;">last-year^ == last-year^now</span><br /><br />The term "<span style="font-family: Courier New, Courier, monospace;">ago</span>" can be provided as per PHP relative date syntax documentation to indicate a previous relative date or time.<br /><br /><b>Example</b><br /><span style="font-family: Courier New, Courier, monospace;">12-months-ago^now </span><i>(or)</i> <span style="font-family: Courier New, Courier, monospace;">12-months-ago^</span><br /><br /><b>DRDR Example Formats</b><br /><span style="font-family: Courier New, Courier, monospace;">jan-1-last-year^jan-1</span><br /><span style="font-family: Courier New, Courier, monospace;">jan-1^now</span> <i>(or)</i> <span style="font-family: Courier New, Courier, monospace;">jan-1^</span><br /><span style="font-family: Courier New, Courier, monospace;">now^next-year-jan-1</span> <i>(or)</i> <span style="font-family: Courier New, Courier, monospace;">^next-year-jan-1</span><br /><span style="font-family: Courier New, Courier, monospace;">3-months</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^</span><br /><span style="font-family: Courier New, Courier, monospace;">90-days</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^</span><br /><span style="font-family: Courier New, Courier, monospace;">last-month^this-month</span><br /><span style="font-family: Courier New, Courier, monospace;">this-month^</span><br /><span style="font-family: Courier New, Courier, monospace;">last-week^this-week</span><br /><span style="font-family: Courier New, Courier, monospace;">this-week^</span><br /><span style="font-family: Courier New, Courier, monospace;">7-days</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^</span><br /><span style="font-family: Courier New, Courier, monospace;">today^</span><br /><span style="font-family: Courier New, Courier, monospace;">^next-monday</span><br /><span style="font-family: Courier New, Courier, monospace;">60-seconds</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^</span><br /><span style="font-family: Courier New, Courier, monospace;">^next-5-hours</span><br /><span style="font-family: Courier New, Courier, monospace;">^tomorrow</span><br /><span style="font-family: Courier New, Courier, monospace;">first-day-of-june^</span><br /><span style="font-family: Courier New, Courier, monospace;"><span style="line-height: 24px;">last-sat-of-July-2008^</span></span><br /><span style="font-family: Courier New, Courier, monospace;">^last-day-of-next-month</span><br /><span style="font-family: Courier New, Courier, monospace;">yesterday-noon^</span><br /><span style="font-family: Courier New, Courier, monospace;">^monday-next-week</span><br /><span style="font-family: Courier New, Courier, monospace;">last-hour^</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><br /><b>HTML Example</b><br /><span style="font-family: Courier New, Courier, monospace;"><select name="date-range"></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="90-days</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^now">Last 90 Days</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="last-month^this-month">Last Month</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="this-month^now">Month-to-Date</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="30-days</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^now">Last 30 Days</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="last-week^this-week">Last Week</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="this-week^now">Week-to-Date</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="7-days</span><span style="font-family: 'Courier New', Courier, monospace;">-ago</span><span style="font-family: 'Courier New', Courier, monospace;">^now">Last 7 Days</option></span><br /><span style="font-family: Courier New, Courier, monospace;"><option name="today^now">Today</option></span><br /><span style="font-family: Courier New, Courier, monospace;"></select></span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><b>PHP Implementation</b><br /><span style="font-family: Courier New, Courier, monospace;">list($start_range, $end_range) = explode('^', $_REQUEST['date-range']);</span><br /><span style="font-family: Courier New, Courier, monospace;">$start_datetime = strtotime(str_replace('-', ' ', $start_range ?: 'now'));</span><br /><span style="font-family: Courier New, Courier, monospace;">$end_datetime = strtotime(str_replace('-', ' ', $end_range ?: 'now'));</span><br /><span style="font-family: 'Courier New', Courier, monospace;"><br /></span><span style="font-family: inherit;"><b>Future</b></span><br /><span style="font-family: inherit;">Currently, I have plans to extends this format to include quarters, but have not yet done so. </span><br /><span style="font-family: 'Courier New', Courier, monospace;"><br /></span><span style="font-family: 'Courier New', Courier, monospace;"><br /></span>Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-65710909941236042092013-09-05T14:59:00.003-06:002014-02-19T10:11:26.367-07:00Migrating From Laravel 3 to Laravel 4I apologize that this page is not well organized. It mainly exists to serve as notes for myself. If you can make sense of this, great!<br /><br />Changes I had to make to my code when updating from Laravel 3 to Laravel 4:<br /><br /><b>General</b><br />Auth::login(int) => Auth::attempt(array()) or Auth::login(User)<br />Request::current() => Request::path()<br />URI::segment(int) => Request::segment(int)<br />URL::to_route("X") => URL::route("X")<br />Request::route()->is("X") => Request::is("X")<br />Form::token() => included by default when calling Form::open() but still accessible<br />Form (method = POST) => default method when calling Form::open()<br />Form::open_for_files(...) => Form::open(array('files' => true, ...))<br />path(...) => storage_path() || public_path || app_path() || base_path()<br />DS (constant) => DIRECTORY_SEPARATOR<br />with_errors($x) => withErrors($x)<br />with_input($x) => withInput($x)<br />Response::error() => App::abort()<br />Request::ip() => Request::getClientIp()<br />DB::query => DB::select, DB::insert, DB::update, DB::delete, DB::statement<br /><br /><b>Blade</b><br />@layout(...) => @extends(...)<br />@render(...) => @include(...)<br />@forelse => GONE, use @if(count(...)) and @foreach() [ this was nice while it lasted :( ]<br /><br /><b>Eloquent</b><br />belongs_to => belongsTo<br />has_many => hasMany<br />belongs_to_many => belongsToMany<br />has_one => hasOne<br />order_by => orderBy<br />group_by => groupBy<br />has_many_and_belongs_to => hasManyAndBelongsTo<br /><br /><b>Models</b><br />set_fieldx($val) {$this->field = $val;} => setFieldxAttribute($val) { $this->attributes['field'] = $val; }<br />get_fieldx(){return $this->field; } => getFieldxAttribute($val) { return $val; }<br />where_val() => whereVal()<br />or_where() => orWhere<br />where_in => whereIn<br />where_between => whereBetween (Note: 2nd argument should be array of min, max)<br />or_where_between => orWhereBetween (Note: 2nd argument should be array of min, max)<br />or_where_in => orWhereIn<br />where_not_in => whereNotIn<br />left_join => leftJoin<br />::hydrate() => newFromBuilder (<a href="http://blog.corrlabs.com/2014/02/laravel-4-model-hydrate.html">read more</a>)<br /><br /><b>Libraries</b><br />You can add app/libraries to the composer autoload json or<br />create package(s) using workbench and place your code in there.<br /><br />Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-10953072511970699872013-09-05T14:55:00.002-06:002013-09-05T14:55:35.254-06:00Error Running PEAR On Windows<b>Problem:</b><br />I went to verify phpunit installation on my windows machine and found that when running pear.bat, I was met with the following:<br /><br /><span style="font-family: Courier New, Courier, monospace;">$ pear.bat</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 1: @ECHO: command not found</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 3: REM: command not found</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 4: REM: command not found</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 5: REM: command not found</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 6: syntax error near unexpected token `('</span><br /><span style="font-family: Courier New, Courier, monospace;">./pear.bat: line 6: `REM Copyright (c) 1997-2010 The Authors'</span><br /><br /><b>Solution:</b><br />Reading the PEAR Documentation, I found that the program had to be 'run as Administrator'. Doing this allowed me to upgrade pear and then install phpunit.Michael Corrigannoreply@blogger.com0tag:blogger.com,1999:blog-4186074565961060437.post-75480412051680189242013-07-30T23:30:00.000-06:002013-07-31T11:18:17.336-06:00Automated SMS Messaging From Windows Command Line<b>Problem:</b><br />I saw a contest that requested that people text or call in as many times as they can within a short period of time. As the contest rules didn't state anything about automation, I decided to write a script to do my bidding.<br /><br /><b>Solution:</b><br />The final script was simple enough. By connecting my phone in debug mode to the computer, running android service, and using the following batch script, I was able to begin my bombardment in hopes of winning the contest. This simple code uses an infinite loop and within that calls instructions telling the phone to create a text message, then sends the commands to send the text message by simulating key presses, and then generates a random amount of time between 1 and 30 seconds before doing repeating the process (as an attempt to not fill up my carriers pipes).<br /><br /><span style="font-family: Courier New, Courier, monospace;">:loop</span><br /><span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>adb shell am start -a android.intent.action.SENDTO -d sms:"+15015551234" --es sms_body "I want to win" --ez exit_on_sent true</span><br /><span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>adb shell input keyevent 22</span><br /><span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>adb shell input keyevent 66</span><br /><span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>SET /A die=30*%random%/32768+1</span><br /><span style="font-family: Courier New, Courier, monospace;"><span class="Apple-tab-span" style="white-space: pre;"> </span>timeout %die%</span><br /><span style="font-family: Courier New, Courier, monospace;">goto loop</span><br /><span style="font-family: Courier New, Courier, monospace;"><br /></span><span style="font-family: inherit;">Now cross my fingers, that my carrier wont care too much... is unlimited texting really unlimited or is that within reasonable usage and what is reasonable usage?</span>Michael Corrigannoreply@blogger.com0