Infographic – Subject Of Study More Important Than Location

Random assortment of infographics:

The infographic, as described below, shows that the 20-year average annual financial return on a degree relies more on the subject of the degree rather than the university which granted the degree.

IMG_20150314_080114

Source: http://www.economist.com/news/united-states/21646220-it-depends-what-you-study-not-where

Posted in Infographics

Infographic – International Gender Education Performance Gap

Random assortment of infographics:

The infographic, as described below, shows the percentage of low achievers by gender and country.

IMG_20150314_080206

Source: http://www.economist.com/news/international/21645759-boys-are-being-outclassed-girls-both-school-and-university-and-gap

Posted in Infographics

Infographic – Unauthorized Immigrants as Share of State Population in 2012

Random assortment of infographics:

The infographic, as described below, shows the unauthorized immigrant population percentage of each state.

unauthorized_immigrant_population_by_state

Source: http://www.washingtonpost.com/blogs/govbeat/wp/2014/11/21/the-undocumented-immigrant-population-explained-in-7-maps/

Posted in Infographics

Android – AdMob Smart Banner Mediation Workaround

Background

Using the AdMob mediation network has been very convenient. There is a newer mobile ad banner type called “Smart Banners“, which AdMob created, that allows the SDK to automatically display the best banner size based on the device’s screen resolution. The Android device ecosystem has thousands of different devices with a wide variety of screen sizes. Programmatically determining the best banner size is very convenient.

Issue

While AdMob supports the Smart Banner ad type, some other ad networks do not. When using AdMob mediation, if the Smart Banner ad type is passed through to another ad network, which doesn’t support Smart Banners, then no ad will be displayed. For example, a common AdMob mediation ad partner, InMobi, does not support the Smart Banner ad type.

Solution

Create a “Smart Banner” function that determines the layout size available on the device and adjusts the ad banner request.
Millennial Media has a great function called canFit, which helps determine the best sized ad for the device. Using this function, we can emulate the Smart Banner functionality across all mediation ad networks, regardless of whether they’ve added support for the Smart Banner ad type.

//Constants for tablet sized ads (728x90)
//AdMob name: LEADERBOARD
final int IAB_LEADERBOARD_WIDTH = 728;
final int IAB_LEADERBOARD_HEIGHT = 90;
//AdMob name: FULL_BANNER
final int MED_BANNER_WIDTH = 480;
final int MED_BANNER_HEIGHT = 60;
//Constants for phone sized ads (320x50)
//AdMob name: BANNER
final int BANNER_AD_WIDTH = 320;
final int BANNER_AD_HEIGHT = 50;
 
//Finds an ad that best fits a user's device.
LinearLayout.LayoutParams adViewLayoutParams = null;
if(canFit(activity, IAB_LEADERBOARD_WIDTH)) {
    adViewLayoutParams = new LinearLayout.LayoutParams((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, IAB_LEADERBOARD_WIDTH, activity.getResources().getDisplayMetrics()),
            (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, IAB_LEADERBOARD_HEIGHT, activity.getResources().getDisplayMetrics()));
    adViewLayoutParams.gravity = Gravity.CENTER;
    adView.setAdSize(AdSize.LEADERBOARD);
} else if(canFit(activity, MED_BANNER_WIDTH)) {
    adViewLayoutParams = new LinearLayout.LayoutParams((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MED_BANNER_WIDTH, activity.getResources().getDisplayMetrics()),
            (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, MED_BANNER_HEIGHT, activity.getResources().getDisplayMetrics()));
    adViewLayoutParams.gravity = Gravity.CENTER;
    adView.setAdSize(AdSize.FULL_BANNER);
} else {
    adViewLayoutParams = new LinearLayout.LayoutParams((int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, BANNER_AD_WIDTH, activity.getResources().getDisplayMetrics()),
            (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, BANNER_AD_HEIGHT, activity.getResources().getDisplayMetrics()));
    adViewLayoutParams.gravity = Gravity.CENTER;
    adView.setAdSize(AdSize.BANNER);
}
 
//Method from MillenialMedia
private static boolean canFit(Activity activity, int adWidth) {
    int adWidthPx = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, adWidth, activity.getResources().getDisplayMetrics());
    DisplayMetrics metrics = activity.getResources().getDisplayMetrics();
    return metrics.widthPixels >= adWidthPx;
}

The code is also available on a GitHub gist: https://gist.github.com/joeykrim/5dbd7a685b8d057182e4

Sources

AdMob Smart Banners
MillenialMedia Android SDK

Posted in Technology

CrashPlan – Ubuntu 14.04 GUI Crash after Installation

Background

CrashPlan has been an affordable and secure solution for backing up local content into their centralized cloud server. The GUI is based on Java, allowing it to run on multiple platforms, including Linux and specifically Ubuntu.

Issue

On Ubuntu 14.04, the Java-based GUI would crash when being opened for the first time after installation. It was unclear whether the issue was with the installation or with some other dependency.

Solution

In the end, adding the line, “-Dorg.eclipse.swt.browser.DefaultType=mozilla” to the end of the default executed command line resolved the issue. The default command line is located in /usr/local/crashplan/bin/run.conf and the additional tag can be added at the end of the GUI_JAVA_OPTS section.

Sources

http://support.code42.com/CrashPlan/Latest/Troubleshooting/CrashPlan_App_Closes_In_Some_Linux_Installations

Posted in Technology

PHP Pagination – Two small tweaks

Background

PHP and MySQL are very powerful. I had a web site with roughly 100,000 rows coming from the joining of three tables that would take at least a few seconds to be output to the web browser and displayed to the end user. The delay was noticeable.
There seemed to be two solutions, either look into ways that will speed up the processing, such as caching, or reduce the amount of output. Given the nature of the product, reducing the output made the most sense and using pagination seemed ideal.
In searching for guides on best practices for using PHP pagination of MySQL content, I found a few great ones, linked at the end under Sources.

Issues

While the guides were great, I had three concerns. First, when there are many pages, being able to quickly move to the first and last page can be important, rather than slowly clicking each page one at a time. Second, I wanted to ensure that the code being executed was efficient, as it will be executed on each page load. Third, when using $_SERVER[‘PHP_SELF’], I wanted to prevent any type of XSS or other exploit.

Solutions

For navigation, I added a link for the first page and the last page that appear whenever the user is on any page above page 6 or below 5 pages from the last page. There is an added convenience in allowing the user to quickly and easily jump to the first or last page.

if ($page_number > 6) {
    $paginationCtrls .= '<a href="' . $_SERVER['PHP_SELF'] . '/page/1">1</a> nbsp; ... nbsp; ';
}
if ($page_number < $last_page - 5) {
    $paginationCtrls .= ' ...   <a href="' . $_SERVER['PHP_SELF'] . '/page/' . $last_page . '">' . $last_page . '</a> nbsp; ';
}

Also available in a gist on GitHub: https://gist.github.com/joeykrim/3ef874119a0fbed7b90b

For looking at code efficiency, there were two sections of for loops that were looping over numbers which were not being used based on the inside if statement. By changing the for loop, not only did it save looping over under-needed numbers, but it also allowed the inside if statement to be removed. Both examples below:
Before

for($i = $pagenum-4; $i < $pagenum; $i++){
    if($i > 0){
        $paginationCtrls .= '<a href="'.$_SERVER['PHP_SELF'].'?pn='.$i.'">'.$i.'</a> nbsp; ';
    }
}

After

for ($i = max($page_number - 4, 1); $i < $page_number; $i++) {
    $paginationCtrls .= '<a href="' . $_SERVER['PHP_SELF'] . '/page/' . $i . '">' . $i . '</a> nbsp; ';
}

Before

for($i = $pagenum+1; $i < = $last; $i++){
	$paginationCtrls .= '<a href="'.$_SERVER['PHP_SELF'].'?pn='.$i.'">'.$i.'</a> nbsp; ';
	if($i >= $pagenum+4){
		break;
	}
}

After

for ($i = $page_number + 1; $i < = min($last_page, $page_number + 4); $i++) {
        $paginationCtrls .= '<a href="' . $_SERVER['PHP_SELF'] . '/page/' . $i . '">' . $i . '</a> nbsp; ';
}

Also available in a gist on GitHub: https://gist.github.com/joeykrim/ba58ae2f82d586523786

Third, while the function $_SERVER[‘PHP_SELF’] is very useful for determining the URL that was used for the currently displayed page, it is taking the input directly from the user’s web browser, and therefore the user. Whenever user input is handled in PHP, it is best to sanitize that input and using a function, such as htmlspecialchars, is one solution.

Final Output Example

php_pagination_example

Source

https://www.developphp.com/video/PHP/Pagination-MySQLi-Google-Style-Paged-Results-Tutorial
http://www.onlinetuting.com/pagination-in-php-mysqli/
http://stackoverflow.com/questions/10272282/how-to-secure-serverphp-self

Posted in Technology

Ubuntu – Securing SSH or OpenSSH

Background

Concern that having SSH/OpenSSH running with the default configuration (/etc/ssh/sshd_config) exposes an attack vector increasing the risk of Ubuntu being compromised.

Issue

The more externally available services running on a system, the greater the risk of attracting unwanted visitors. The default configuration of SSH is fairly flexible in order to accommodate most users, but the universal flexibility comes at the cost of security.

Solution

Four important modifications: change the port, use keys rather than passwords, disable password-based authentication, and disable root login. All of these modifications are made in the /etc/ssh/sshd_config file, as outlined below:

  • Change the default port from 22 to another port: Port 12345
  • Setup ssh keys for user accounts: Great guide
  • Disable password-based authentication for all accounts: PasswordAuthentication no
  • Disable root login access, or at least restrict root login access to key-based authentication: PermitRootLogin no

Sources

Disabling password-based authentication: http://www.linux.org/threads/how-to-force-ssh-login-via-public-key-authentication.4253/
Setting up ssh keys for user accounts: https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys–2
More options: https://help.ubuntu.com/community/SSH/OpenSSH/Configuring

Posted in Technology

Crashplan – Route over wlan on Linux

Background:

Have a faster internet connection over wlan0 than eth0. Prefer to route Crashplan backup traffic over wlan0 rather than the default eth0.

Challenge:

The Java GUI for Linux, doesn’t provide controls for selecting the network interface, although the Mac and Windows clients do.
Using the route command worked well for http traffic, but didn’t seem sufficient for directing Crashplan’s application traffic.

Solution:

Editing the Crashplan configuration xml files and specifically excluding the eth0 interface. A helpful utility to confirm traffic is flowing over the correct network interface is: iptraf. The exact lines to add into the configuration file, crashplan/conf/my.service.xml are below:

    <networkinterfacesexcluded>
      <patternlist>
        <windows></windows>
        <macintosh></macintosh>
        <linux>
          <pattern regex="eth0"></pattern>
        </linux>
        <solaris></solaris>
      </patternlist>
    </networkinterfacesexcluded>

Also, adding route commands seemed to help facilitate:

j@j:/etc/rc2.d$ sudo route add -net 216.17.8.0 netmask 255.255.255.0 gw <local gateway ip>
j@j:/etc/rc2.d$ sudo route add -net 38.81.66.0 netmask 255.255.255.0 gw <local gateway ip>
Posted in Technology

Cryptocurrency – Beginners Guide

Background:

In the Spring 2014 semester, I researched cryptocurrencies and created a beginners guide, under the direction of Professor Simon Johnson.

Outcome:

Attached (PDF): Beginners Guide to Cryptocurrencies

Posted in Consumer, Monetary Policy, Technology

Infographic – Concerns of threats around the world

Random assortment of infographics:

The infographic, as described below, shows countries color coded by the type of threat people worry about most.

pew-threats-2

Source: http://www.pewresearch.org/fact-tank/2014/10/16/what-is-the-greatest-threat-to-the-world-depends-on-where-you-live/

Posted in Infographics

Infographic – External sovereign defaults since 1800

Random assortment of infographics:

The infographic, as described below, shows a list of countries with the number of defaults mapped over a timeline indicating when the default occurred.

IMG_20140803_213256

Source: http://www.economist.com/blogs/graphicdetail/2014/07/daily-chart-23

Posted in Fiscal Policy, Infographics

Infographic – GDP of the US split in half and mapped to regions

Random assortment of Infographics:

The infographic, as described below, shows the GDP of the United Stats split in half, with each half mapped to a geographic region.

United States Economic Activity, Split in Half

Source: https://visual.ly/united-states-economic-activity-split-half?utm_source=visually_embed

Posted in Infographics

Infographic – Child Mortality Rates from 1751-2011

Random Assortment of Infographics:

The infographic, as described below, shows the number of children dying before the age of five, per 1,000 live births over the last ~260 years (1751-2011) in Sweden, UK, Germany, India, and Ghana.

IMG_20140802_214041

 

Source: http://www.ourworldindata.org/data/population-growth-vital-statistics/child-mortality/

Posted in Infographics

Infographic – Average number of hours per week spent on

Random Assortment of Infographics:

The below infographic, as titled, shows the average number of hours per week spent on various activities by Mothers and Fathers over the last ~45 years. The three main categories of activities are: child care, housework, and paid work. Mothers and Fathers are categorized as adults aged 18-64 with at least one child under 18 living in the household.

Source: http://www.economist.com/news/united-states/21608779-there-large-class-divide-how-americans-raise-their-children-rich-parents-can

Posted in Infographics

Sony Vaio Pro 13 Ultrabook – Audio over HDMI

Background:

Purchased a great Sony Vaio Pro 13 ultrabook with excellent hardware running Windows 8 and now updated to 8.1. The IntelĀ® HD Graphics 4400 hardware controls the HDMI output and the audio over the HDMI output.

Issue:

Using the built-in HDMI output provides video, but no audio. Also, unable to locate audio options for HDMI in the Sound settings control panel of Windows 8.1. The Sony Vaio update tool confirms all the latest software drivers and other patches have been installed, but the issue of no audio over HDMI remains.

Solution:

After reading through many online posts and blog articles, the root cause appears to be related to the specific Intel Graphics Drivers being used by Sony on this specific model laptop. The Sony Vaio update tool confirmed that the Intel Graphics Drivers 10.18.10.3304 with a date of 9/9/2013 is the latest version. A community post on Sony’s forum shows that other people with a Sony Vaio Pro 13 laptop also experience no audio over HDMI, but they were able to resolve the issue by downloading updated Intel Graphics Drivers from a link on Sony’s web site: http://dlv.update.sony.net/pub/vaio/download/EP0000317186/EP0000317186.exe. The newer Intel Graphics Drivers are version 15.33.5.64.3316 with a date of 10/4/13.
After installing these “updated” Intel Graphics Drivers, I’m able to receive audio over the HDMI connection and I’m able to adjust that option in the Sound settings of the Windows 8.1 control panel.
The only potential concern might be that Sony does not provide future updates for the graphics drivers as my version might be out of sync with the version expected by the Sony Vaio update tool.

Sources:

Community post and thread on Sony’s forum
Alternative update drivers from Sony – untested

Posted in Consumer, Technology Tagged with: , , , , , ,

Ubuntu – VirtualBox Repository Configuration

Background

VirtualBox is a great product and has routine updates. Setting up the repositories for automatic updates and installs seemed to be more challenging than most other software packages.

Issue

Originally, after following the simple directions on VirtualBox’s web site, I received this error:

"Error: W: Failed to fetch http://download.virtualbox.org/virtualbox/debian/dists/precise/Release Unable to find expected entry 'contrib/source/Sources' in Release file (Wrong sources.list entry or malformed file)".

I read that by following VirtualBox’s directions, two resposities were added, one for software and one for source code, but as the source code isn’t distributed from Oracle in the respository, it should be disabled.
After disabling the respository, I still wasn’t seen the latest update and had to further research the issue.

Solution

I found the most comprehensive solution on a Ubuntu community page, which gave one long command that performs all the correct steps to properly setup the VirtualBox repository:

sudo sh -c "echo 'deb http://download.virtualbox.org/virtualbox/debian '$(lsb_release -cs)' contrib non-free' > /etc/apt/sources.list.d/virtualbox.list" && wget -q http://download.virtualbox.org/virtualbox/debian/oracle_vbox.asc -O- | sudo apt-key add - && sudo apt-get update && sudo apt-get install virtualbox-4.3 dkms

The above commands add the VirtualBox repository download link for the distribution’s specific name (lsb_release -cs) to virtualbox.list, then downloads the public key to verify the authenticity of the VirtualBox downloads, adds the key to local storage, refreshes the package list and installs the latest version of VirtualBox plus DKMS for keeping the modules updated.

Sources

Remove sources from repository list
Comprehensive solution
VirtualBox Directions

Posted in Technology

Chrome – Recently Visited Tabs Disappeared

Background:

Google Chrome is very good at maintaining a history of open tabs, which allows for a great multitasking web browsing experience.

Issue:

Since Chrome frequently and correctly restores tabs, many users might not realize a strong dependence on this feature until it breaks. Over the last three years, there have been only a few occasions when Chrome has crashed and wasn’t able to successfully restore the previously opened tabs. After building a dependence on always having the same tabs restored, suddenly not having access to these tabs can be devastating.

Solution:

Chrome stores the currently open tabs as well as the last session’s open tabs in a few important files labeled: Current Session and Current Tabs as well as Last Session and Last Tabs. On Ubuntu, these files are stored in the local user’s home directory.

~/.config/google-chrome/Default

If Chrome isn’t displaying the correct tabs from the last sessions, a quick fix is to rename Last Session and Last Tabs to Current Session and Current tabs, then restart Chrome.
If that quick fix doesn’t work, the issue might be more serious as Chrome only keeps track of the current session and one previous session. To extend the history, routine backups can be kept and these Session and Tabs files can be restored from a backup.

Posted in Consumer, Technology Tagged with: , , , , , , , ,

WordPress – Allowed Memory Size Exhausted

Background:

WordPress is a great blogging platform that has many powerful features. The hosting environment WordPress operates under can provide constraints and limitations.

Issue:

After upgrading a plugin for WordPress, I immediately encountered the error, “Fatal error: Allowed memory size of x bytes exhausted in…php on line x). All WordPress web pages would display the same fatal error.
A user might expect, that if WordPress is encountering a fatal error with a plugin, the plugin would be disabled. This process is not automated.

Solution – Short-term:

Disabling the WordPress plugin required manually editing the WordPress database and disabling all plugins. Under the table containing the name “options” and under the column named “option_name” with the value of “active_plugins”, I erased the option_value. The option_value contains a setting of which plugins are activated and which are not. By removing the values in option_value, all plugins will be disabled. This approach allows plugins to be re-activated one by one until the fatal error is encountering, thus allowing the troubling plugin to be identified.
MySQL database command to view the option_value:

SELECT * FROM `options` WHERE option_name='active_plugins'

MySQL database command to reset and disable all plugins:

UPDATE `options` SET `option_value`='' WHERE option_name='active_plugins'

Solution – Long-term:

WordPress is powered by PHP and hosting environments set limits on the amount of memory PHP can consume for each customer or instance. If WordPress is legitimately in need of more memory, it will be best to increase the PHP memory limit for the user or instance. The method of increasing the memory limit varies based on the way PHP has been configured on the server. Some common solutions are to add or edit a file called php.ini or php5.ini with a line, “memory_limit = 128M”. Common values for the memory limit include: 32M, 64M, and 128M.
For a shared hosting environment, the most reliable approach is to contact the system administrator.

Conclusion:

When encountering a fatal error involving memory consumption, a likely root cause could be a plugin. The easiest route to identify whether a plugin is the root cause is to disable all plugins. If disabling all the plugins resolves the memory exhaustion issue, re-enabling one-by-one will identify the offending plugin.

Sources:

Fatal error: Allowed memory size exhausted
How To Disable All WordPress Plugins From The Database?

Posted in Consumer, Technology

Dr Martens Great Customer Service

Background:

I’ve purchased and worn Dr. Martens shoes over the years as they’ve proven to be very durable. Although the prices are sometimes higher than other shoes, I’ve found that the shoes last for a long time. In addition, I found the soles provide excellent traction on slick and wet surfaces, as well as good traction on icy surfaces!

Issue:

During the winter of 2014 I had worn a pair of Dr. Martens that were a few years old, but in great shape. The shoes, by far, had the best traction in snow and ice. One morning, when I was putting on the shoes, I noticed the outside rubber of the soles from the toe to the middle of the foot was cracked, on both sides of the shoe and on both shoes. The crack was serious enough that a yellow material inside the sole was exposed and seemed impossible to easily mend. I was very surprised as I’ve never encountered this type of issue before and I’ve had various Dr. Martens shoes for many years and used them in many different climates.

Solution:

I reached out to Dr. Martens customer relations department via email, [email protected] I attached a few pictures of the issues with the shoes, as I found it hard to describe and hard to believe. They offered to inspect the shoes for manufacturer defects if I was willing to pay the shipping fees to send the shoes to Portland, OR. After paying roughly $25 for the proper sized box and shipping, I waited three weeks. I didn’t hear back from Dr. Martens until I found a box at my door. Inside was a pair of brand new shoes in the most similar style to my previous pair!

Conclusion:

Although the communication from Dr. Martens was minimal, I was very impressed to receive a brand new pair of Dr. Martens without any charge!

Posted in Consumer Tagged with: , ,

Android – Detect Root Access from inside an app

Background

Google Wallet used three methods to determine whether an Android device had root access configured. Google Wallet used to mark a device as “Unsupported” if root access was detected on the Android device. The code used to implement the root detection methods was reversed and posted here on pastebin.com.

Overview

Three methods were used:
1) Check if the “su” command was successful
2) Check if the file “/system/app/Superuser.apk” exists
3) Check if the system OS was built with test-keys
If any of these three methods were true, Google Wallet would mark the device as “Unsupported”.

Code Analysis

First method – Execute “su” command

The first method created an interface to the environment, where the app was running, through getting a singleton instance by invoking getRuntime() and passing the “su” command. If an IOException error was not encountered, the command was determined successful.

  private boolean canExecuteSuCommand()
  {
    try
    {
      Runtime.getRuntime().exec("su");
      i = 1;
      return i;
    }
    catch (IOException localIOException)
    {
      while (true)
        int i = 0;
    }
  }

Second method – Check for apk

The second method created an “abstract” representation of a file by using the absolute path and filename to the most popular Superuser application. A call would be made to this representation of the file to check whether the file exists. If the file exists, the command was determined successful.

  private boolean hasSuperuserApk()
  {
    return new File("/system/app/Superuser.apk").exists();
  }

Third method – OS built with test-keys

The third method would extract the operating system build information from a system properties file (/system/build.prop). The extracted build tags information was searched for the phrase “test-keys” and if “test-keys” was found in the build tags information, the command was determined successful.

  private boolean isTestKeyBuild()
  {
    String str = Build.TAGS;
    if ((str != null) && (str.contains("test-keys")));
    for (int i = 1; ; i = 0)
      return i;
  }

Summary method – Determine whether a device is rooted

The final method gathered the results from the prior three tests and if any of the three test results were successful, would return true, indicating the device is rooted.

  public boolean isRootedPhone()
  {
    int i = 0;
    if (!this.mClientConfigurationManager.getClientConfiguration().isRootedPhoneDetectionEnabled());
    while (true)
    {
      return i;
      if ((!isTestKeyBuild()) && (!hasSuperuserApk()) && (!canExecuteSuCommand()))
        continue;
      i = 1;
    }
  }
Posted in Technology Tagged with: , , ,