INCLUDE_DATA
Feed on
Posts
Comments

Since version 18 Firefox now disables older versions of the Java plugin and the user has to click on the applet or the red brick icon in the address bar, then click Activate to make the plugin load. This is a good thing, but it can be annoying. Even though you may have the latest version of Java installed there may still be an old Java plugin lying around making your browser insecure and causing Firefox to block Java from loading every time.

I found this excellent article on Mikes Musings regarding the Firefox plugin loading mechanism: http://mike.kaply.com/2012/02/16/how-firefox-loads-plugins/

Using that information I discovered that JavaFX contained an old NPAPI plugin which was causing this.

These are the registry paths I found that Firefox uses to determine what plugins to load:

HKEY_CURRENT_USER\Software\MozillaPlugins
HKEY_LOCAL_MACHINE\SOFTWARE\MozillaPlugins
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\MozillaPlugins

After uninstalling JavaFX Firefox loads the Java applet without prompting.

Tomcat start/stop script

You could just link to catalina.sh and get the basic stop/start functionality working but it has some drawbacks:

  • Sometimes tomcat doesn’t stop gracefully and you have to reach for ps, grep and kill
  • You have to sometimes pass in some configuration options to Tomcat to enable JMX, increase the max memory it can use, etc.
  • The catalina.sh script doesn’t include the commands to make chkconfig and update-rc.d work.
  • It doesn’t let you run Tomcat as a different user.
  • The restart argument does not work

I started with the script from Yoryos here and modified it to suit my needs a little better: http://blog.valotas.com/2011/05/tomcat-initd-script.html

This script allows you to keep the configuration separate so you don’t have to edit catalina.sh directly. It also handles killing Tomcat in case it doesn’t gracefully shut down.

This script should be put in /etc/init.d/tomcat

On Debian-based systems run this to register the script:
update-rc.d tomcat defaults

On RedHat-based OSes use this to register the script:
chkconfig --add tomcat

#!/bin/bash
#
# tomcat This shell script takes care of starting and stopping Tomcat
# It also handles killing Tomcat in case it doesn’t stop gracefully
# It uses a PID file to determine the process ID so it should work with multiple Tomcat instances on one server
#
# chkconfig: - 80 20
#
### BEGIN INIT INFO
# Provides: tomcat
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Description: Tomcat service
# Short-Description: start and stop tomcat
### END INIT INFO

## Source function library.
#. /etc/rc.d/init.d/functions

# Begin configuration section

export JAVA_HOME=/opt/jdk1.6.0

# These options are used when Tomcat is started
export CATALINA_OPTS=”-Xmx512m -XX:-UseGCOverheadLimit \
-Dcom.sun.management.jmxremote=true \
-Dcom.sun.management.jmxremote.port=511 \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false”

export LD_LIBRARY_PATH=/usr/local/apr/lib

# Set this to the path where this Tomcat is installed
TOMCAT_HOME=/opt/tomcat

# Number of seconds to wait after nicely requesting stop
SHUTDOWN_WAIT=10

# This should be a different file for each tomcat
CATALINA_PID=/var/run/tomcat.pid

RUNASUSER=root

# End configuration section

export PATH=$JAVA_HOME/bin:$PATH
export CATALINA_PID

start() {
pid=`cat $CATALINA_PID 2>/dev/null`
if [ -n "$pid" ]
then
echo “Tomcat is already running (pid: $pid)”
else
# Start tomcat
echo “Starting tomcat”
touch $CATALINA_PID
chown $RUNASUSER $CATALINA_PID
/bin/su -p -s /bin/sh $RUNASUSER $TOMCAT_HOME/bin/catalina.sh start
fi

return 0
}

stop() {
pid=`cat $CATALINA_PID 2>/dev/null`
if [ -n "$pid" ]
then
/bin/su -p -s /bin/sh $RUNASUSER $TOMCAT_HOME/bin/catalina.sh stop
echo -n “Stopping Tomcat”

let kwait=$SHUTDOWN_WAIT
count=0;
until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
do
echo -n “.”;
sleep 1
let count=$count+1;
done

echo “”

if [ $count -gt $kwait ]; then
echo “process is still running after $SHUTDOWN_WAIT seconds, killing process”
kill $pid
sleep 3

# if it’s still running use kill -9
if [ `ps -p $pid | grep -c $pid` -gt '0' ]; then
echo “process is still running, using kill -9″
kill -9 $pid
sleep 3
fi

fi

if [ `ps -p $pid | grep -c $pid` -gt '0' ]; then
echo “process is still running, I give up”
else
# success, delete PID file
rm $CATALINA_PID
fi
else
echo “Tomcat is not running”
fi
return 0
}

case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo “Tomcat is running with pid: $pid”
else
echo “Tomcat is not running”
fi
;;
esac
exit 0

UW imapd error

I was getting the following error in my log file and I couldn’t connect to my imap server using Thunderbird.

Mar 1 13:35:19 ltps imapd[12525]: imap service init from 192.168.1.42
Mar 1 13:35:19 ltps imapd[12525]: Unable to accept SSL connection, host=dave [192.168.1.42]
Mar 1 13:35:19 ltps imapd[12525]: SSL error status: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number

It turned out being interference from avast anti virus on my desktop causing this. Turn off it’s IMAP checking to work around this.

Sometimes during development Tomcat will stop responding and won’t gracefully shutdown. I then have to figure out which java process is Tomcat and kill it. Usually the easiest way is to find out which process is using the port Tomcat is running on.

Here is a powershell script that finds all processes running on port 80 and kills them. This assumes the process is listening on 0.0.0.0 which means all IP’s and network interfaces.


netstat -ano | ? {$_ -like “*0.0.0.0:80 *”} |
% {
$_ -match “\d+$”;
echo $matches[0];
taskkill /F /PID $matches[0]
}

I could not figure out how to get this to work. I think it’s because I didn’t understand that the $ signs were being used to call a macro. I would like to document this in detail here for others in case you’re in the same boat.

Here is the command I’m using.

define command{
command_name check_service_cluster
command_line /usr/lib/nagios/plugins/check_cluster –service -c $ARG1$ -d “$ARG2$” -v
}

When using this command ARG1 indicates the threshold for non-ok data points at which a critical alert is returned. It uses the special threshold syntax.
An example:
@2:2 This means if there are exactly 2 data points in non-ok state return critical

ARG2 should be a comma-separated list of service statuses. The number 0 = OK. The number 2 = CRITICAL. A macro like the following will return the status of a service:
$SERVICESTATEID:host1:service1$

The following are two macros for two services separated by a comma:
$SERVICESTATEID:host1:service1$,$SERVICESTATEID:host2:service1$

The following check_command argument will monitor two services. The @2:2 means it will fail if 2 services are in a non-OK state. The service name is service1 and it will look on host1 and host2.
check_service_cluster!@2:2!$SERVICESTATEID:host1:service1$,$SERVICESTATEID:host2:service1$

I would like to start hacking on these remotes. They are universal programmable remotes with Wi-Fi, a USB connector, a color screen, a built-in simple web browser and they run on Windows Mobile.

One of the features I really liked on my ESPN Remote is the ability to view TV listings on the small screen, then click a button to tune to the channel. Unfortunately this service was recently discontinued.

Some of the things that I think can be accomplished:
- Re-create the TV listing service by redirecting requests to the click365 service and answering the queries with a local web server.
- Install other Windows Mobile programs on the remote.
- Make a web app to control everything in your house via home automation software like MisterHouse.
- Remotely control iTunes via Wi-Fi like the iPhone does.
- Backup all the configuration that has been done to make it work with all my devices.
- Share the programmed IR signals on the remote with other users so that it’s easier to program the remote to work with your devices. This can all be compiled in a database similar to the Logitech Harmony database.
- Control entertainment center devices remotely via the remote and maybe make things switch on/off on a schedule.

Does anybody know how to get into these devices and start hacking on them? What I know so far is as follows.

The remote is running the Windows CE Web Server on ports 80 and 443. I have no idea what any URL’s are that can be accessed though. If we can get to the file system on the remote we could maybe see what URL’s are valid.

Usually you can install ActiveSync or Windows Mobile Device Center and when you connect the device via USB to your PC it lets you browse the files on the device. While these remotes have a USB connector it does not connect with ActiveSync. There must be something disabled on the device causing this. Edit: Looks like this explains how

If there is any interest by other people we could create a project on Google Code or SourceForge and start documenting our work.

I’ve always thought that if you specify multiple A records with the same host name in your DNS settings it will only serve to balance the load of your site across these IP addresses. This is done by your operating system randomly choosing one IP from the list and remembering it for a set period of time. This should be the TTL of the domain but there are rogue DNS servers out there that will remember them for longer.

This article, however, suggests that this technique can also be used for fail-over. In other words, your computer will try one IP, but if it fails to connect to it, fall back to another IP configured for the same name and the user will not  see an error. It should also then remember that this IP is the valid one and use it in the near future. I got really excited after reading this, but remained skeptical, so I decided to try it myself.

My tests with IE7 and Firefox 3 were unsuccessful.

If you lower the TTL on the domain to around 60 seconds you will see something along these lines: Every 60 seconds (about) if you ping the host name it will give you a different IP address. Whichever IP ping returns is the same IP the browser tries. If this is the IP that is currently down it will fail. If you wait 60 seconds ping will return the other IP and the browser connection will work. You must sometimes also restart the browser to make it use the IP the OS is returning.

This tells me that the browser is just using whatever IP the OS is returning. It does not know that there are multiple IP’s and that it could be trying another IP. There may be browser plugins or configuration options that change this behavior. I was using the default configuration.

Now I’m back to thinking (knowing) that it simply does not work like this, whether I think it should or not.

DNS SRV records allows you to configure load balancing with weighting and programs using this  are also supposed to fail-over to other addresses configured in these SRV records. VOIP services work with SRV records but browsers do not make use of this. RFC 2782 actually tried to get this support in for HTTP but it expired in 2002 without being approved. That saddens me. Cheap fail-over for the masses using DNS remains a dream.

I recently had to complete a migration from SugarCRM to SalesForce and I wanted to share some of my experience here in hopes that you’ll find it useful. These instructions are pretty technical. If you have trouble understanding them then you’re not the right person for the task. Find someone that has experience working with databases.

We wanted to export Accounts, Opportunities, Leads, Contacts, Calls, Notes, Emails, Meetings and Tasks.

In SalesForce add a SugarID custom field and make sure to always populate this with the ID column of what you are importing from Sugar. You’ll need this information to be populated later so that you can relate/connect certain record types to each other.

Add custom fields if Sugar has a field that SalesForce does not. Make sure to make text fields long enough.

Export your data from your SugarCRM database using a database access program such as Aqua Data Studio. Data Studio allows you to run a SQL query, then save the results as an Excel worksheet.

Activate Data Loader. The Data Loader is a program in the AppExchange that allows you to export and import data from SalesForce. If you don’t have an Enterprise account then you can ask your account rep to turn it on for you temporarily. I believe we got 30 days to use it.

When dealing with large Excel files (bigger than 3mb) always open files referenced by VLOOKUP functions in advance of opening the file containing the VLOOKUP function. I’ve found that Excel is much happier if you do this. It can still take a while for it to recalculate the spreadsheet. Just be patient.

Watch out for Excel’s trigger-happy auto-formatting. Any long phone numbers get automatically converted to scientific notation and that’s what goes in the CSV file when you save. Just apply text formatting to the entire column for phone number columns.

Add extra columns in the Excel worksheet to populate information in the format the Data Loader expects. For example the date needs to be formatted the right way for the Data Loader to import it correctly. You can reformat a date in Excel by using ‘=DATE(B2, “YYYY-MM-DD HH:MM:SS”)’.

Add an OwnerID column. This is the ID of a user in SalesForce. To find out what a user’s ID is go to Setup, Users, Manage Users and click on a user. In the address bar you’ll see the user ID like ‘12345678901UsTG’; populate that in the OwnerID column. If you have multiple users make a spreadsheet to map these values and use VLOOKUP to look up the value as explained below.

To relate records to each other you must have a column in your data that contains the SalesForce ID of the related record. For example, when importing Contacts the AccountID column must contain the SalesForce ID of the related Account. One way to populate this in all your records is to use the VLOOKUP function in Excel. First import your Accounts, remembering to populate Sugar ID. Then use the Data Loader to export the SalesForce ID and Sugar ID of all your Account records to accounts.csv. Open accounts.csv in Excel. Make the Sugar ID the first column and the SalesForce ID the second column and sort the records by Sugar ID (important). In the Contacts spreadsheet add a column named ACCOUNTID1 with a value like ‘=VLOOKUP($I2,’[accounts.csv]accounts’!$A$1:$B$1000, 2,FALSE)’. If an ID can’t be found for a record then #N/A will be displayed and Data Loader will not import the record. Add another column named ACCOUNTID with value ‘=IF(ISNA(K2), “”, K2)’ where K2 is the cell with the VLOOKUP. Finally save your worksheet first as an Excel file, then as a CSV file.

In Data Loader select File, Insert, then follow the wizard to import your data. If there are errors open the CSV file with the errors, fix the problems and try to import the fixed CSV file.

All of the above listed data records can be imported using the same mechanism. We found that the types translated from Sugar to SalesForce the following way:

  • Call > Task
    Set the Status for future tasks to Not Started. Set the Status for past calls to Completed.
  • Note > Note
  • Email > Note
    In this case I prepended From, To and Subject to the Body and I also prepended “Email <DATE> ” to the subject so that you could glance at the note and see that it’s an email and when it was sent.
  • Meeting > Event

If you do mess up you can use Upsert to update/insert and avoid creating duplicate records.

Let me know if you have any questions.

I recently saw mention of a time-keeping application that takes screen shots of your desktop every 5 minutes or so. At the end of the week you can then play back your week to see what you did and figure out who to bill for what. This sounded like a great tool to me because I often forget what I was doing on a given day when reviewing my timesheet so I end up looking at my sent email for that time slot to try and jog my memory.

I figured what this program was doing is actually really simple and I could do it myself so I took a stab at it and cobbled the following script together. Unfortunately it has a couple dependencies: Imagemagick and Boxcutter. Look at the comments below for more info.

Visual Basic:
  1. ' VB Script to take time-stamped screenshot and convert to JPEG
  2. ' Setup to run from Scheduled Tasks every 5 minutes to have a record of what
  3. ' you did this week
  4. '
  5. ' NOTES
  6. ' It doesn't clean up after itself
  7. ' On my machine with 1280x800 display if it runs every 5 minutes with quality
  8. ' set to 40 it uses around 30MB every day for image storage. After 30 days
  9. ' that's 900 MB!
  10. ' You can adjust the quality to increase or decrease file size.
  11. ' Imagemagick is required. It is used to convert the BMP to JPEG.
  12. ' The convert command from Imagemagick must be on the path
  13. ' The Boxcutter program is required. You can download it from here:
  14. ' http://rasm.ods.org/boxcutter/
  15. ' Place this VBS in the same directory that you extract boxcutter.
  16.  
  17. Public Const OUTPUTPATH = "d:\screenshots"
  18. Public Const TEMPFILE = "c:\newss.bmp"
  19. Public const JPEG_QUALITY = 40
  20.  
  21. Function PadDigits(n, totalDigits)
  22. PadDigits = Right(String(totalDigits,"0") &amp; n, totalDigits)
  23. End Function
  24.  
  25. Sub DoIt()
  26.  
  27. Dim WSHShell
  28. Set WSHShell = WScript.CreateObject("WScript.Shell")
  29.  
  30. Dim oFSO
  31. Set oFSO = WScript.CreateObject("Scripting.FileSystemObject")
  32.  
  33. dim fileName, folderName, folderPath
  34. folderName = "" &amp; Year(Now) &amp; PadDigits(Month(Now), 2) &amp; PadDigits(Day(Now), 2)
  35. fileName = folderName &amp; "_" &amp; PadDigits(Hour(Now), 2) &amp; PadDigits(Minute(Now), 2) &amp; PadDigits(Second(Now), 2) &amp; ".jpg"
  36.  
  37. folderPath = OUTPUTPATH &amp; "\" &amp; folderName
  38.  
  39. ' Take screen shot
  40. ' 7 means new window is minimized
  41. call WSHShell.Run ("boxcutter.exe -f " &amp; TEMPFILE, 7)
  42. WScript.Sleep 3000
  43.  
  44. If Not oFSO.FolderExists(OUTPUTPATH) Then
  45. ' Create folder if it doesn't exist
  46. Call oFSO.Createfolder(OUTPUTPATH)
  47. End If
  48.  
  49. If Not oFSO.FolderExists(folderPath) Then
  50. ' Create folder if it doesn't exist
  51. Call oFSO.CreateFolder(folderPath)
  52. End If
  53.  
  54. ' Convert to JPEG
  55. ' 7 means new window is minimized
  56. call WSHShell.Run ("convert -quality " &amp; JPEG_QUALITY &amp; " " &amp; TEMPFILE &amp; " " &amp; folderPath &amp; "\" &amp; fileName, 7)
  57. WScript.Sleep 3000
  58.  
  59. If oFSO.FileExists(TEMPFILE) Then
  60. ' Delete bmp file
  61. Call oFSO.DeleteFile (TEMPFILE)
  62. end If
  63.  
  64. End Sub
  65.  
  66. ' actually run our Sub above
  67. DoIt

You may get an error like this from Acrobat/Reader when you try to open a PDF in your browser:

Adobe Reader could not open 'A9R3.tmp' because it is either not a supported file type or because the file has been damaged (for example, it was sent as an email attachment and wasn't correctly decoded).

On my server I have mod_deflate turned on and it compresses just about everything with gzip before sending it to the browser. This is what was causing the problem.

This issue shows up with IE6, but not IE7 or Firefox. It looks to me like the browser is supposed to decode/decompress the content before handing it to Acrobat. In the case of IE7 and Firefox the browser does it's job correctly, but IE6 does not do this. Bad browser.

To work around this issue figure out what URLs can return a PDF file, then configure Apache not to use gzip when the request for one of those URLs came from IE6. In my case I just disabled gzip for the /jasperserver path and that did the trick. Of course you can use any rule that you can come up with, just set the variable "no-gzip".

Here is what I used:

<Location /jasperserver>
BrowserMatch "MSIE 6.0" no-gzip
</Location>

Older Posts »