Wednesday, September 23, 2015

Tech: Adding depth to Firefox rendered pages by over-riding white backgrounds with alpha channel

This is one of those interesting but accidental things.  I was intending to figure out a way to get translucency on Firefox with OS X so that my Tron background theme would show through web pages in the same way it does for my Terminal windows.  That brought me to some interesting discussion about ways to override the background through user scripts.  Specifically a script credited to "Howard Smith" with no OP URL*

// ==UserScript==
// @name        tronBG
// @namespace   hightidetech
// @description change the default bgcolor of websites
// @version     1
// @grant       none
// ==/UserScript==
(function () {
    function noWhiteBackgroundColor() {
        function changeBackgroundColor(x)  {  // auto change colors too close to white
            var backgroundColorRGB=window.getComputedStyle(x,null).backgroundColor;  // get background-color
            if(backgroundColorRGB!="transparent")  {  // convert hex color to rgb color to compare
                var RGBValuesArray = backgroundColorRGB.match(/\d+/g); //get rgb values
                var red   = RGBValuesArray[0];
                var green = RGBValuesArray[1];
                var blue  = RGBValuesArray[2];

                // ============================================================================
                // Set the base colors you require: 
                // use: http://www.colorpicker.com
                // to find the rgb values of the base colour you wish to suppress white backgrounds with:
                // Default gray provided:
                // ============================================================================

                var red_needed   = 220;
                var green_needed = 220;
                var blue_needed  = 255;


                if (red>=220&&green>=220&&blue>=220) {   // white range detection

                   if      (red>=250&&red<=255&&green>=250&&green<=255&&blue>=250&&blue<=255) {
                      red_needed   += 0;
                      green_needed += 0; }

                   else if (red>=240&&red<=255&&green>=240&&green<=255&&blue>=240&&blue<=255) {
                      red_needed   += 6;
                      green_needed += 3; }  

                   else if (red>=230&&red<=255&&green>=230&&green<=255&&blue>=230&&blue<=255) {
                      red_needed   += 10;
                      green_needed += 5; }

                   else if (red>=220&&red<=255&&green>=220&&green<=255&&blue>=220&&blue<=255) {
                      red_needed   += 14;
                      green_needed += 7; } 

                   x.style.backgroundColor="rgba( " +red_needed+ ", " +green_needed+ ", " +blue_needed+ ", " +opacity+ ")"; // the background-color you want 
                   }
                }
            }
        var allElements=document.getElementsByTagName("*");  // get all elements on a page
        for(var i=0; i
            changeBackgroundColor(allElements[i]);}
    }
    window.addEventListener("DOMContentLoaded",noWhiteBackgroundColor, false); 
})() ;

Once loaded up in to greasemonkey this will essentially turn all of your white background pages to a spiffy shade of lavender.  So, I tried to due the same thing for Tron blue** by changing the RGB values in the variable declarations to:

                var red_needed   = 24;
                var green_needed = 202;
                var blue_needed  = 230;

The results were pretty interesting but way too bright for my taste, possibly even a worse contrast of the white on black.  However, moving from RGB to RGBA which has a way to specify opacity, the rendered results are much more interesting depending on how the original page is styled.  To do this, simply add another variable and change the method call below it to use rgba.

                var red_needed   = 24;
                var green_needed = 202;
                var blue_needed  = 230;
                var opacity      = 0.5;
                ...
                x.style.backgroundColor="rgba( " +red_needed+ ", " +green_needed+ ", " +blue_needed+ ", " +opacity+ ")";

Although there is still some white blockiness here and there, the result is much more interesting providing a layering effect to many of today's most frequently visited web sites; and of course if you don't like Tron blue feel free to try something else more to your taste.



*http://superuser.com/a/808537
**http://www.colourlovers.com/color/18CAE6/Tron_Blue



Friday, September 18, 2015

Tech: Crobee "almost" Cool Playstation 4 (PS4) bluetooth adapter/dongle...

There is this saying that something that if something looks too good to be true than it usually is.  I'm sad to say that seems to be the case here with my first ever Groupon purchase, the PS4 Bluetooth Adapter/Dongle offered through Crobee.Cool.  https://www.groupon.com/deals/gs-ps4-bluetooth-adapter-playstation-4-bluetooth-dongle .

Although it took an unexpectedly long time to get through shipping and handling after my initial purchase, when the unit arrived it was professionally packaged, and had a surprise mic that would plug directly in to the controller to go wireless.  That was immediately suspicious because my use case was simply to have an existing bluetooth headset work for the chat channel during gaming while the other gaming sounds continued through the external TV speakers.

The instructions too were a bit misleading because they indicated the dongle would immediately go in to pairing mode upon being plugged in.  But there is a button affixed to the top that clearly needs to be depressed to enter in to pairing mode.

Trying out the mic, it worked great, but echoes obviously because it picks up the sound of the TV w/o using ear phones.  Put two TVs in the same room and that is a surefire recipe for a headache and lots of complaints on the other end of the chat.

The USB dongle does eventually get recognized by the Playstation 4 as an audio accessory, so everything looked like it was good to go.  The only problem was that the dongle was not actually discoverable over bluetooth.  Initially I tried with my Powerbeats2 wireless headphones, then a Sony PS3 bluetooth headset, then my Apple Mac and the PS4 itself, and none of them could actually discover the bluetooth ID for the dongle.

Since it is a final sale and the support appears to be non-existent, I thought I'd post to save anyone else the same frustration of an unmet expectation.


Friday, September 04, 2015

Tech: MS Excel trick - How to transpose "FirstName LastName" to "LastName, FirstName"

For me, Excel is becoming a "data fixup" glue of sorts that I used to use simple Unix commands for.  The chief reason for this is that many of the tools producing the data have export functions to native Excel file formats, so it is easy enough to put output of disparate tools in to multiple tabs of the same workbook and fix them up locally.  But this also presents certain challenges working within the confines of Excel formula's, which like Perl can be very hard to understand what is happening in a complex formula if each part is not well documented.

Thus, the reason behind this post.  While trying to determine if all of the employees of interest from one sheet had completed each of 5 mandatory training modules tracked in another, the first thing I had to do was transpose how the name was represented from one to the other so that I could do a match.

In this instance I want to take "Jane Doe" to "Doe, Jane" .

First, to get the last name we use the RIGHT function assuming the first name is in Column A Row 2:

=RIGHT(A2,LEN(A2)-FIND(" ", A2,1))

Concatenating a trailing comma is as simple as using "&"

=RIGHT(A2,LEN(A2)-FIND(" ", A2,1)) & ", "

Now we use the LEFT function to get the first name:

=LEFT(A2,FIND(" ",A2,1)-1)

Put it all together and we have the following:

=RIGHT(A2,LEN(A2)-FIND(" ", A2,1)) & ", " & LEFT(A2,FIND(" ",A2,1)-1)

All this is really doing is extracting out the substring on either side of the whitespace character and allowing you to manipulate that text independently of the rest.  Obviously if there is another separator, you would specify that instead to do the same thing.

Monday, March 02, 2015

Opinion: Sony Playstation VS Apple iDevice Support Transactions

My interaction with Live Chat on Sony Playstation tonight made me wonder how theoretically different, and more pleasant the interaction might have been had it been with Apple.

It all starts out with Sony's Service Policy stated in big capital lettering as though Sony is yelling at you before you've even told them what is wrong (with their product):

From http://www.playstation.com/en-us/support/warranties/ps4/

A VALID PROOF OF PURCHASE IN THE FORM OF A BILL OF SALE OR RECEIPT FROM AN AUTHORIZED RETAILER WITH THE DATE OF THE ORIGINAL PURCHASE MUST BE PRESENTED TO OBTAIN WARRANTY SERVICE.

This same warranty page points to www.us.playstation.com/support  in order to obtain a return authorization code.  From that page there is actually no obvious way to proceed until you select Support -> Contact Support from the upper right corner and are alerted to a 15 minute average wait time for "Live" chat.  My chat script follows with highlighted opportunities to be more like Apple and less like Comcast Residential Service.




Sony: Hello, My name is [Sony] how may I assist you today?
Sony: Are you still there?
You: I am
You: have a hardware problem with my PS4 controller
You: left analog stick clicks by does not work consistently when depressed
Sony: I'm sorry to hear you are having an issue. I understand how frustrating it can be.
Sony: Although you have entered information about a SEN account before this chat, could you please provide the following to confirm the *exact* account you need assistance with?

-  First and Last Name on account
-  Sign-In ID (email address)
-  Online ID
You: Rob, foobarbaz@yahoo.com, MyScreenName
Sony: Thank you, Rob. One moment while I access your account.
Sony: May I ask, since when this issue started?
You: Its gotten gradually worse over the course of the last two weeks
You: Difficult to actually run in Destiny now!
Sony: My apologies for the inconvenience. Tell me, did you purchase it recently?
You: and my left thumb is going to fall off ;-)
Sony: When did you purchase it?
You: It was purchased as a gift around October of 2014
Sony: I see, in that case we can create a service request but due to quality purposes the proof of purchase will be required, Rob. Our best recommendation will be to gather it and provide us with it so that we can create the service case for you.
You: Shouldn't the POS Bar code be sufficient?
You: it came in a system bundle
Sony: I do understand your concern, but in this case we have strict guidelines to follow, my best advice will be to gather that information, once you have it feel free to contact us back and any agent will be more than glad to check on the case.
You: and I'm pretty sure that I completed the registration when I used it the first time
Sony: Is there anything else I can assist you with today?
Now it is important to understand that the carbon copy warranty legalese does not include logic in the CYA, nor consumer friendliness, but anyone who can read at a second grade level would see:
will be free from material defects in material and workmanship for a period of one year from the original date of purchase (the "Warranty Period")
While I don't have the original sales receipt because my friends that pitched in together to buy it for me knew that I would never want to return it, I do have the original box and inner box that has clearly displayed the model number P-27452255-E which Google search readily identifies as the prerelease version of the special edition glacier white Destiny bundle.  Not playing favorites,  Amazon shows the release date of this version to be September 9th, 2014.  So, in order for me to be eligible for warranty coverage the following must be true:

1 year > todays date - purchase date

Let's use the purchase date as the date of the release because that really is the oldest it "can" be as warranty coverage should not start when you've paid for something so much as when you've actually received the product from the reseller (i.e. on the date of release).

365 days > March 2, 2015 days between September 9, 2014
365 days > 174 days

So, essentially, Sony is refusing to warranty a product they know had to be sold less than a year from today based on the Model number, and is actually denying service less than half way in to the warranty period because my product was a gift and not purchased by myself and they painted themselves in to an illogical and inflexible service policy that doesn't take in to account new product release dates as a consideration for valid serviceability.  Its no surprise then that Apple support asks for the serial number of the device first.  



Wednesday, November 19, 2014

Tech: Quick Start Apache Server w/ PHP on OSX Mavericks

1. Set up the built-in Apache server to enable PHP
$ sudo cp /private/etc/apache2/httpd.conf /private/etc/apache2/httpd.conf.pre-php-enable
$ sudo sed -e 's/^#\(LoadModule php5_module.*\)/\1/' /private/etc/apache2/httpd.conf.pre-php-enable > /private/etc/apache2/httpd.conf
2. Create a useable version of the PHP ini file
$ sudo cp /private/etc/php.ini.default /private/etc/php.ini
3. Create a user-specific Apache config file
$ sudo echo '
<Directory "/Users/$LOGNAME/Sites/">
Options Indexes Multiviews
AllowOverride AuthConfig Limit
Order allow,deny
Allow from all
</Directory>
' > /etc/apache2/users/$LOGNAME.conf
4. Start the server
$ sudo apachectl start
5. Create a test file
$ echo 'echo "Hello World!";?>' > $HOME/Sites/hw.php
6. Validate everything is working
$ curl http://localhost/~$LOGNAME/hw.php
Hello World!
7. Launch Xcode to do more interesting edits
$ open -a /Applications/Xcode.app $HOME/Sites/hw.php

 Biblio:

Wednesday, July 17, 2013

Tech: Getting rid of pesky Mal/Bad Src-C Malware showing up in OSX Spotlight Cache...

For months, I ignored the Sophos warnings in the Quarantine Manager warning me about Mal/Bad Src-C showing up in the OSX Spotlight cache.  I was unsuccessful in ever finding the source for the index on my local disk, and then I happened across this Sophos community article.  Agile 's comment was particularly relevant to the behavior I was seeing:

    "SAV is detecting cached files which no longer exist on your computer, and therefore no longer exist in the Quarantine Manager"

So, the logical thing to do is drop the cache.  Since this was on my work machine, I first had to grant myself root access.  This is also useful if you actually want to look at the contents of the Spotlight cache.  There is a nice Apple KB article published about how to do just that if you already have admin privs. If you have an older version of OSX be sure to reference the article.  For Lion, the latest version referenced as of this writing, I've included the steps below for ease of use:


OS X Lion
  1. From the Apple menu choose System Preferences....
  2. From the View menu choose Users & Groups.
  3. Click the lock and authenticate as an administrator account.
  4. Click Login Options....
  5. Click the "Edit..." or "Join..." button at the bottom right.
  6. Click the "Open Directory Utility..." button.
  7. Click the lock in the Directory Utility window.
  8. Enter an administrator account name and password, then click OK.
  9. Choose Enable Root User from the Edit menu.
  10. Enter the root password you wish to use in both the Password and Verify fields, then click OK.

OK, now all we have to do is stop the Spotlight indexing as root

$ su -
Password:
~ root# mdutil -i off /
/:

Indexing disabled.

With the indexing turned off it's time to drop the cache

# mdutil -E /
/:
Indexing disabled.

Now turn indexing back on

# mdutil -i on /
/:
Indexing enabled. 

Depending on the size of the local disk(s) and categories selected to index, the rebuild could take a while.  Select the magnifying glass in the upper right corner of the screen, and you should be able to see a status bar for the estimated indexing time.

Once the indexing is complete, re-run Sophos local disk scan and make sure the spotlight files are gone for good.  If they come back then you are not running in to the stale cache issue that I was.  With any luck the Quarantine Manager will have two entries, one for the source file and one for the Spotlight index.  If not, try turning off Messages and Chats categories in the Spotlight preferences and run through the above procedure again.  If that does the trick, then its likely that you have an email containing the malware as an attachment so be careful what you click.



Sunday, December 09, 2012

Tech: Setting up and Running a Siege-based Sustained Load Test...

So its been a while since I had to do any kind of load test, and as chance would have it, I needed to generate around 2,000 hits/s against a remote server sustained for a couple of days.  It turned out to be a bit more complicated than I expected so I decided to share my setup with others and aggregate some disparate information.

1. First, to get the siege source, download it from joedog (yes, its legit).
curl -C - -O http://www.joedog.org/pub/siege/siege-latest.tar.gz

2. Extract and uncompress the tarball

tar -xvf siege-latest.tar.gz

3. cd to the new directory (version 2.7 in this instance)

cd siege-2.70/

4. Make sure that the user you are logged in as can write to /usr/local where the program will be installed to, and then execute the following commands in order

./configure; make; make install;

OSX HINT: install the XCode Command Line Tools before building siege by launching XCode -> Preferences -> Downloads .  Then select Install next to Command Line Tools .

5. Create the siege config file in your home directory

/usr/local/siege.config

6. Edit the values in $HOME/.siegerc, specifically the value for failures should be quite high generating this kind of load from a single app server

failures = 1000000

7. Run a test to make sure everything is working properly

siege -c1 -r1 'http://www.google.com'

========

8. Next make sure you have enough File Descriptors to be able to handle the network socket connections:

sudo echo "username soft nofile        2048" >> /etc/security/network.conf
sudo echo "username hard nofile         5020" >> /etc/security/network.conf

9. Verify the changes by logging back in as "username" and verify using

ulimit -n
2048

========

10. Now create a few scripts (startsiege, stopsiege, trimlogs):

#!/bin/bash

#############
#startsiege
#  this script works from a loop that will restart siege if the current process terminates 
#  prematurely due to a high number of errors (such as File Descriptors being exhausted).
#  It also looks for the presence of a file called "bar" to help exit cleanly if the stop script was used
############


echo "Preparing for assault...";
#Create data pipe for nohup output
pipeHandle="./siegepipe";
if [ -e "$pipeHandle" ];
then
  echo -n "File handle exits...";
else
  echo -n "Creating new file handle for data pipe...";
  mknod ./siegepipe p;
fi
echo "Continuing...";

#Create a log dir if one does not exist
if [ -d ./log ]; then
  echo -n "Log dir exists...";
else
  echo -n "Creating new log dir...";
  mkdir ./log;
fi
echo "Continuing...";

#Redirect output from the pipe to a file
nohup cat < ./siegepipe >./log/siege.log > /dev/null 2>&1 &
catPID=$!;
echo "$catPID" > ./cat.pid;

#Start the siege process
echo -n "File Descriptors: ";
ulimit -n
echo "Initiating assault...";
grep foo bar > /dev/null 2>&1;
while (($? != 0)); do
  date;
  nohup siege -c2000 -t4H 'http://crackme.edgeplatform.com/?cacheH=on&test=monkey' >./log/siege.log &
  #nohup siege -c2000 -t4H 'http://crackme.edgeplatform.com/?cacheH=on&test=monkey' >./log/siege.log > /dev/null 2>&1 &
  siegePID=$!;
  echo "$siegePID" > ./siege.pid;
  wait $siegePID;
  grep foo bar > /dev/null 2>&1;
 if [[ $? = 0 ]]; then
   rm bar;
   exit 0;
 else
   echo "Aborted due to errors...Cleaning Up.";
   echo "Rotating log...";
   mv ./log/siege.log ./log/siege.log$$;
   echo "Re-establishing output redirect...";
   kill -9 $catPID;
   nohup cat < ./siegepipe >./log/siege.log > /dev/null 2>&1 &
   catPID=$!;
   echo "$catPID" > ./cat.pid;
   echo "Starting a new assault...";
   grep foo bar > /dev/null 2>&1;
 fi
done;



#!/bin/bash


#############
#stopsiege
#  This script creates the file bar used by the start script to exit cleanly, and kills
#  the process id of siege
############

echo "foo" > bar;
echo "Stopping Assault...";
kill -9 `cat ./siege.pid`;
echo "Stopped...";
echo -n "Cleaning up...";
# Stop Output Reidrect
kill -9 `cat ./cat.pid`;
# Remove pipe
rm ./siegepipe;
# Remove logs
rm -rf ./log/siege.log*;

rmdir ./log;
# Remove PID files
rm ./siege.pid ./cat.pid;
echo "Done...";




#! /bin/bash


#############
#trimlogs
  This script trims any logs that are over 15 minutes in age 
# in case there is a sudden error runup
############

while (true); do
  echo "Trimming archived error logs older than 15 minutes...";
  find ./log -name "siege.log[0-9]*" -cmin +15 -exec rm -v '{}' ';' ;
  sleep 900;
done;




========

To run simply use ./startsiege

 $ ./startsiege
Preparing for assault...
Creating new file handle for data pipe...Continuing...
File Descriptors: 2048
Initiating assault...
Mon Dec 10 12:18:10 PST 2012
nohup: redirecting stderr to stdout
Aborted due to errors...Cleaning Up.
Rotating log...
Re-establishing output redirect...
Starting a new assault...
./startsiege: line 49: 15049 Killed                  nohup cat < ./siegepipe > ./log/siege.log > /dev/null 2>&1
Mon Dec 10 13:04:30 PST 2012
nohup: redirecting stderr to stdout
Aborted due to errors...Cleaning Up.
Rotating log...
Re-establishing output redirect...
Starting a new assault...
./startsiege: line 49: 17156 Killed                  nohup cat < ./siegepipe > ./log/siege.log > /dev/null 2>&1
Mon Dec 10 13:51:46 PST 2012
nohup: redirecting stderr to stdout


To trim logs while siege is running, use ./trimlogs from a separate shell

 $ ./trimlogs
Trimming archived error logs older than 15 minutes...
removed `./log/siege.log15047'

To stop, use ./stopsiege

$ ./stopsiege
Stopping Assault...
Stopped...
Cleaning up...Done...


========

Thats all there is to it!  You have increased the file descriptors to reduce errors, created error handling that will restart the process if it dies unexpectedly, and trimmed the error logs that get generated when the process is nohup'd.