tag:blogger.com,1999:blog-62352281833594689172024-02-19T03:07:41.259-08:00Russell DavisCoding FTWRusshttp://www.blogger.com/profile/06044594491166082413noreply@blogger.comBlogger16125tag:blogger.com,1999:blog-6235228183359468917.post-46215895871735209332011-03-14T21:47:00.000-07:002011-03-14T21:47:00.235-07:00SSH to a server through a bastion host with a single commandWith command-line SSH, it's easy, just do:<br />
<br />
<div class="code">
ssh -t <intermediate> ssh <destination></div>
<br />
With putty, the following batch file will do the trick (pass the destination host as the first argument):<br />
<br />
<div class="code">
SET DATFILE="%TEMP%\bastion.tmp"<br />
echo ssh %1 > "%DATFILE%"<br />
start putty -load "<putty session name>" <intermediate> -t -m "%DATFILE%"</div>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-64969184271929162402011-03-06T13:47:00.000-08:002011-03-06T13:47:51.946-08:00Fix for communicating with Pageant from a cygwin processAs I <a href="http://russelldavis.blogspot.com/2011/02/using-charade-to-proxy-cygwin-ssh-agent.html">mentioned previously</a>, Pageant's security measures reject messages coming from cygwin processes (and their children). I <a href="https://github.com/wesleyd/charade/pull/7#commits-pushed-0308855">submitted a patch</a> that fixes this for <a href="https://github.com/wesleyd/charade">charade</a>. The trick is to copy the security descriptor from the Pageant process so they'll be an exact match. Any app should be able to use this same technique.<br />
<br />
Sadly, the Putty folks have failed to incorporate the change into <a href="http://svn.tartarus.org/sgt/putty/windows/winpgntc.c?view=log">winpgntc.c</a>.Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-27980323244322177532011-02-12T15:45:00.000-08:002011-02-12T15:45:52.898-08:00How to fix horrible performance of Java apps in Remote DesktopRaymond Chen has a great article about <a href="http://blogs.msdn.com/b/oldnewthing/archive/2005/08/22/454487.aspx">developer "taxes"</a>. One of the taxes is <a href="http://blogs.msdn.com/b/oldnewthing/archive/2006/01/03/508694.aspx">making sure your app works well in Remote Desktop</a>. Java apps are notoriously bad about getting details like these right. IntelliJ and NetBeans (probably two of the top three IDEs) perform so horribly over Remote Desktop that they're basically unusable.<br />
<br />
I tracked the problem down to a Java property that disables use of DirectDraw. A lot of Java apps seem to do this due to a <a href="http://netbeans.org/bugzilla/show_bug.cgi?id=131233">poor implementation in earlier versions of java</a> (*sigh*). Fortunately, there's an easy fix -- the property can be changed by adding this to the command line:<br />
<br />
<div class="code">
-J-Dsun.java2d.noddraw=false</div>
<br />
<div class="zemanta-related">
<h6 class="zemanta-related-title" style="font-size: 1em; margin: 1em 0pt 0pt;">
Related articles</h6>
<ul class="zemanta-article-ul">
<li class="zemanta-article-ul-li"><a href="http://www.nofluffjuststuff.com/blog/howard_lewis_ship/2010/12/is_it_time_to_switch_back_to_intellij_">Is it time to switch back to IntelliJ?</a> (nofluffjuststuff.com)</li>
<li class="zemanta-article-ul-li"><a href="http://java.sys-con.com/node/1695241">RubyMine Welcomes All NetBeans Users</a> (java.sys-con.com)</li>
</ul>
</div>
<div class="zemanta-pixie" style="height: 15px; margin-top: 10px;">
<a class="zemanta-pixie-a" href="http://www.zemanta.com/" title="Enhanced by Zemanta"><img alt="Enhanced by Zemanta" class="zemanta-pixie-img" src="http://img.zemanta.com/zemified_e.png?x-id=50c7a2c5-1eb6-4dad-9d32-1f07644f486b" style="border: medium none; float: right;" /></a></div>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-42353990755186292132011-02-05T12:58:00.000-08:002011-02-05T12:58:14.158-08:00KeyFix4000 now available on GitHubThe source code for <a href="http://russelldavis.blogspot.com/2006/11/keyfix4000-improve-your-ms-natural.html">KeyFix4000</a> has always been available, but it's now <a href="https://github.com/russelldavis/KeyFix4000">up on GitHub</a>. Enjoy.Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-25063601596969810552011-02-03T21:19:00.000-08:002011-05-03T22:58:08.736-07:00Using charade to proxy cygwin ssh-agent requests to pageantSee <a href="https://github.com/wesleyd/charade#readme">charade’s readme</a> for some background. It’s really handy if you want to use pageant as the agent for the cygwin ssh client (in addition to putty). There are two problems I’ve encountered:<br />
<ol>
<li>Pageant’s security measures reject the proxy request due to the two processes running with different SIDs. </li>
<li>The proxy agent isn’t seen by any processes launched from your outside your shell (since the environment variables only get set in ~/.bash_profile)</li>
</ol>
Issue #1 can be solved by running both pageant and putty with cygstart – see the <a href="https://github.com/wesleyd/charade/issues#issue/5">issue page</a> for more info.<br />
<br />
Here’s my solution for issue #2. Instead of running keychain at the start of every login shell, just run it once at Windows startup, and set the environment variables system-wide using <a href="http://ss64.com/nt/setx.html">setx</a>. Here’s my shell script that does that:<br />
<br />
<div class="code">
#!/usr/bin/sh<br />
# Be sure to run this script in a login shell so that cygwin paths are properly<br />
# set, otherwise the Windows version of hostname will run and mess things up<br />
<br />
/usr/bin/keychain -q -Q<br />
<br />
# The -csh script works perfectly since we can just substitute setx for setenv<br />
alias setenv=setx<br />
. ~/.keychain/`hostname`-csh</div>
<b>Update:</b><br />
Since this is only running once at startup, keychain isn’t really needed. And to simplify a bit more, it can be done in a batch file:<br />
<br />
<div class="code">
REM Kill any existing instances first<br />
killall charade<br />
SET FN=%TEMP%\ssh-agent-init.bat<br />
REM The -csh script works perfectly since we can just substitute setenv for setx<br />
charade -c | sed 's/setenv/setx/' | sed 's/;$//' > %FN%<br />
call %FN%<br />
del %FN%</div>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com1tag:blogger.com,1999:blog-6235228183359468917.post-9331701388500135982011-01-08T21:56:00.000-08:002011-12-15T15:27:59.152-08:00A solution for sharing Perforce workspaces using AltRoots<p>Perforce lets you <a href="http://kb.perforce.com/article/1217/creating-a-shared-workspace-between-cygwin-and-windows">share workspaces between Cygwin and Windows</a>. The same technique can be used to <a href="http://shawebteam.posterous.com/blog/2009/09/29/sharing-a-workspace-with-perforce">share between Linux and Windows</a>, when sharing the data via Samba – but there’s a pretty big catch.</p><p>If you run p4 sync in Linux from outside the AltRoot location, p4 will sync to a new directory with the name of the p4 Root. Say you accidentally run p4 sync from the /etc dir – you’ll end up with a directory like /etc/S:\workspace, and your real workspace directory will now be out of sync. (This isn’t a problem with <a href="http://www.perforce.com/perforce/downloads/otherlist.html#cygwinx86">p4 for cygwin</a>, since cygwin can interpret Windows paths.)</p><p>Here’s a workaround:<br />
1) Remove the base directory from the Root and AltRoot paths<br />
2) Add the base directory to all paths in the workspace mapping<br />
3) Add / as a second AltRoot<br />
4) Create a symlink in / with the name of the base directory, pointing to the real location.</p><p>By using / as a second AltRoot, every linux directory will match, and the default root will never be used.</p><p><b>Update:</b><br />
Here's a simpler workaround that instead just results in a an error message when running p4 outside of the workspace root.<br />
</p><p>1) Set P4CLIENT to something invalid like `XXXXX - Running from invalid root`<br />
2) Set P4CONFIG to `.p4config`<br />
3) Create a file called `.p4config` in your workspace root. Inside add the line `P4CLIENT=[Name]` substituting [Name] with your real client name<br />
</p>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-60534887773347584472011-01-05T20:00:00.000-08:002011-01-05T21:21:30.483-08:00Synergy patch<a href="http://synergy-foss.org/">Synergy</a> has a nasty bug where if you switch screens with a hotkey, then switch again with the mouse, the hotkey modifier key gets stuck in the down state. I submitted a patch a few years ago, but it never got integrated since the project wasn't being maintained. Synergy has now been resurrected and merged with Synergy+, and the bug still exists. <a href="http://synergy-foss.org/pm/issues/694">Here's the patch</a> (which will need some tweaking for the new codebase).Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-60768105813403713442011-01-02T22:46:00.000-08:002011-01-04T22:05:49.829-08:00Rooting the Android emulatorThere's surprisingly little information out there about how to do this. Perhaps it's because you can already get a root shell on the emulator with adb. But if you're developing an android app that is meant to run su commands on a rooted phone, it won't just magically work in the emulator. I'll explain how to change that, so you won't have to develop and test your su-using apps directly on your phone.<br />
<br />
What a rooted phone has that the emulator lacks is a custom su binary and the SuperUser app. The app is easy - just install it with adb. The su binary is a different beast. It requires some custom steps every time you start the emulator. Luckily, it can all be easily automated. I created a batch file that launches the emulator and runs all the necessary commands. For non-Windows users, it should be trivial to convert to a bash script. Explanations are in the script's comments, so I'll let it speak for itself:<br />
<br />
<code>@echo off<br />
REM --------------------------------------------------------------------------<br />
REM Starts the android emulator and sets up the custom su executable on the<br />
REM system image. This must be done each time the emulator starts, since the<br />
REM emulator will not persist the system image when it exits (see<br />
REM <a href="http://developer.android.com/guide/developing/tools/emulator.html">http://developer.android.com/guide/developing/tools/emulator.html</a>).<br />
REM<br />
REM Usage:<br />
REM * Arguments to this command are passed on to the emulator command. You'll<br />
REM need to pass in an AVD name.<br />
REM * The android sdk tools directory must be your path.<br />
REM * You'll need to put the appropriate su binary in the same directory as<br />
REM this script. You can get it from the zip files linked here:<br />
REM <a href="http://forum.xda-developers.com/showthread.php?t=682828">http://forum.xda-developers.com/showthread.php?t=682828</a><br />
REM * You'll need to a separate, one-time install of the superuser app. Just<br />
REM run adb install with the apk in the zip file from the previous step.<br />
REM<br />
REM<br />
REM A few implementation details:<br />
REM * By default, the emulator's system image has no free space, since it's<br />
REM meant to be read-only. The -partition-size argument makes it bigger so<br />
REM there's space to work with (I gave it a somewhat arbitrary 160MB). The<br />
REM adb remount command gives write access to the system the image.<br />
REM * The emulator is launched via runhidden.js to hide the useless console<br />
REM window that pops up.<br />
REM --------------------------------------------------------------------------<br />
<br />
if (%1)==() echo "MUST SPECIFY AN AVD!" && exit /B<br />
cd /d %~dp0<br />
@echo on<br />
<br />
wscript runhidden.js "emulator -partition-size 160 %*"<br />
adb wait-for-device<br />
adb remount<br />
adb push su /system/bin<br />
adb shell chmod 6755 /system/bin/su<br />
adb shell rm /system/xbin/su<br />
adb shell ln -s /system/bin/su /system/xbin/su<br />
</code><br />
<br />
Here is the source for runhidden.js:<br />
<br />
<code>// Runs a command with it's initial window hidden. Useful for programs that<br />
// allocate a useless console (many java apps do this, and you don't always<br />
// have the ability to run them with javaw).<br />
//<br />
// Requires the entire command to be passed in as the first parameter<br />
// (because WSH doesn't provide simple access to the entire command line).<br />
WScript.CreateObject("WScript.Shell").Run(WScript.Arguments(0), 0)<br />
</code><br />
<br />
Screenshot of a superuser request in the emulator:<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgexpTcfOnK-PdbNuKHQpatkrnWDT1Zmi5ZAZA-ja7pPzc2FWnPoEFhGyguJbYeFIBwwtpg6AQ7uEYSjq37y1lWuNg9gNalEJEK15_EP_z_bd1SZdrXqHgkFYpqQQZtv3FsghWIWO01y1Y/s1600/RootedEmulator.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgexpTcfOnK-PdbNuKHQpatkrnWDT1Zmi5ZAZA-ja7pPzc2FWnPoEFhGyguJbYeFIBwwtpg6AQ7uEYSjq37y1lWuNg9gNalEJEK15_EP_z_bd1SZdrXqHgkFYpqQQZtv3FsghWIWO01y1Y/s640/RootedEmulator.PNG" width="425" /></a></div><div class="zemanta-related"><h6 class="zemanta-related-title" style="font-size: 1em; margin: 1em 0pt 0pt;"> </h6><h6 class="zemanta-related-title" style="font-size: 1em; margin: 1em 0pt 0pt;">Related articles</h6><ul class="zemanta-article-ul"><li class="zemanta-article-ul-li"><a href="http://thomascannon.net/projects/android-reversing/">Android Reverse Engineering</a> (thomascannon.net)</li>
<li class="zemanta-article-ul-li"><a href="http://www.androidpolice.com/2010/11/27/how-to-install-the-android-market-in-the-android-emulator/">How To: Install The Android Market In The Android Emulator</a> (androidpolice.com)</li>
</ul></div><div class="zemanta-pixie" style="height: 15px; margin-top: 10px;"><a class="zemanta-pixie-a" href="http://www.zemanta.com/" title="Enhanced by Zemanta"><img alt="Enhanced by Zemanta" class="zemanta-pixie-img" src="http://img.zemanta.com/zemified_e.png?x-id=d7cc51a3-ffe9-452e-9476-e010caea90e1" style="border: medium none; float: right;" /></a></div>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com1tag:blogger.com,1999:blog-6235228183359468917.post-58738332464661689142010-12-27T22:18:00.000-08:002010-12-27T22:20:38.863-08:00Quick workaround for broken handling of Play/Pause key in WinampThe Play/Pause key on the Microsoft Natural Keyboard 4000 (and other media keyboards) doesn't work properly when Microsoft's Intellitype software is running. Somehow Winamp has <a href="http://forums.winamp.com/showthread.php?t=263978">left this unfixed</a> for years. Here's a workaround:<br />
<br />
In the Intellitype settings (Control Panel -> Keyboard -> Key Settings), change the Play/Pause key to a macro that sends some other keystrokes, e.g., Ctrl+Shift+* (Intellitype makes the Alt-key hard to record, so I leave it out). Then, in Winamp's settings, enable global hotkeys and change the Playback: Play/Pause hotkey to the same value.<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFcc8r1lTNCrvENCzd9JFy_Yo-tdF_uYSDUnxhOX22YL_sUm9l9RqkfY63KIKMmmdojQzVn_syF-MrsDIZj3zuTWBcUXCapF0MgwZFmuj8mHvaqd0Vg47a22qEULVBzD8354_oFxLfFpg/s1600/winamp1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="310" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFcc8r1lTNCrvENCzd9JFy_Yo-tdF_uYSDUnxhOX22YL_sUm9l9RqkfY63KIKMmmdojQzVn_syF-MrsDIZj3zuTWBcUXCapF0MgwZFmuj8mHvaqd0Vg47a22qEULVBzD8354_oFxLfFpg/s400/winamp1.PNG" width="400" /></a></div><br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl-4vkOFd-q1TCYF7gVtHCSz_uIgSQpqNBoYF0z1g8BCFttf9bsBSMjs8154lk7qxgMfprFg8kHAj048mbs4sCfUoOqMv-i9sUZzfQTd4fX9VM-TUUDd3PggYcVCcx3Dw-N0XvMfLFUNw/s1600/winamp2.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="306" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjl-4vkOFd-q1TCYF7gVtHCSz_uIgSQpqNBoYF0z1g8BCFttf9bsBSMjs8154lk7qxgMfprFg8kHAj048mbs4sCfUoOqMv-i9sUZzfQTd4fX9VM-TUUDd3PggYcVCcx3Dw-N0XvMfLFUNw/s400/winamp2.PNG" width="400" /></a></div>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-90963350643711610082010-10-09T11:00:00.000-07:002011-01-04T22:03:17.263-08:00Perl one-liner, bumping a version stringThis takes a version string like "1.23f" and turns it into "1.23g" (or adds "a" if there's no trailing letter):<br />
<br />
<code>perl -lpe 's/([^a-z])$/$1a/ || substr($_, -1) =~ tr/a-z/b-za/'</code>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-18047742118153967472010-10-01T23:34:00.000-07:002011-05-04T00:51:18.073-07:00Some handy bash args functionsSee my entries at commandlinefu:<br />
<ul>
<li><a href="http://www.commandlinefu.com/commands/view/6711/outputs-each-arg-on-its-own-line">each() - </a><a href="http://www.commandlinefu.com/commands/view/6711/outputs-each-arg-on-its-own-line" title="Find out what others think of this command">Outputs each arg on its own line</a></li>
<li><a href="http://www.commandlinefu.com/commands/view/6710/joins-args-together-using-the-first-arg-as-glue">joinargs() - </a><a href="http://www.commandlinefu.com/commands/view/6710/joins-args-together-using-the-first-arg-as-glue" title="Find out what others think of this command">Joins args together using the first arg as glue</a></li>
<li><a href="http://www.commandlinefu.com/commands/view/6672/xargs-for-builtin-bash-commands">xargsb() - </a><a href="http://www.commandlinefu.com/commands/view/6672/xargs-for-builtin-bash-commands" title="Find out what others think of this command">xargs for builtin bash commands</a></li>
</ul>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-39316799926697592332010-02-24T21:18:00.000-08:002019-01-30T13:13:33.315-08:00Wordpress FailIf you have a wordpress blog, try the following:<br />
<br />
1) Create a new post<br />
2) In the visual editor, start a line with a few spaces followed by some text<br />
3) Click 'Preview', or click to the HTML tab then back to the Visual tab.<br />
<br />
You'll notice your leading spaces have disappeared. Ok, fine, just convert them to &nbsp's in the HTML editor. Now, switch back to the visual editor. Ahh, leading spaces at last. Let's just switch back to the HTML editor for one last tweak. And... the leading spaces are gone again. Welp.<br />
<br />
I found one <a href="http://www.undermyhat.org/blog/2009/07/fix-for-leading-whitespace-bug-in-syntaxhighlighter-evolved-for-wordpress/">attempt to fix this</a> - unfortunately it's just a bandaid and only works inside shorttags for a specific wordpress plugin.<br />
Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-77356078057023722372007-01-23T12:19:00.000-08:002010-02-20T19:23:42.984-08:00Embedding iTunes album art into MP3s<p>iTunes makes it really easy to download album art for an entire music library in one fell swoop (select-all, Advanced->Get Album Artwork). It's a little trickier to embed the artwork into the MP3s themselves (for use with other players like WinAmp). I found a perl script at <a href="http://home.comcast.net/%7Eteridon73/itunesscripts/index.html">Teridon's iTunes Scripts</a> called <strong>itunes_insert_artwork </strong>that does a nice job. </p> <p>While trying it out, I noticed that a lot of the jpegs from iTunes were ridiculously large. Some were over 800K, for a 600x600 image. Not quite sure why - resaving them even at 100% quality resulted in much smaller files. So, I tweaked the script to send the images through ImageMagick first. (At quality 85, those 800K images get down to 200K.)</p> <p> You'll need to have ImageMagick and PerlMagick installed. If you plan on installing ImageMagick/PerlMagick for ActivePerl, note that, currently, you'll need the older 5.8.x version to get it to work.</p><a href="http://dl.dropbox.com/u/2628560/download/itunes_insert_artwork.txt">Download the script</a>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-66158116999050281522006-11-25T08:58:00.000-08:002011-02-05T12:49:46.011-08:00KeyFix4000: Improve your MS Natural Keyboard 4000I'm loving the MS Natural Keyboard 4000, but it does have some issues.<br />
<br />
First, it is conspicuously missing a Windows key on the right side. Second, there is no way to remap the back and forward buttons to act as mouse buttons. After googling in futility for a solution, I decided to whip one up myself. (After all, this was nothing a little keyboard hooking couldn't solve.)<br />
<br />
The result? <a title="KeyFix4000 Executable" href="https://github.com/russelldavis/KeyFix4000">KeyFix4000</a>.<br />
<br />
The mouse button mapping is pretty straight-forward - it just translates a click on the back/forward button to a click on the left/right mouse button.<br />
<br />
The Windows key issue was a little tricky - how do you fix a key that doesn't exist? Well, the Apps key is pretty much where the Windows key should be, and I realized I could overload it. Now, when pressed by itself, it functions as the Apps key, and when pressed in combination with another key, it works as the Windows key. This dual usage works surprisingly well.<br />
<br />
<a href="https://github.com/downloads/russelldavis/KeyFix4000/KeyFix.exe">Download executable</a><br />
<a href="https://github.com/russelldavis/KeyFix4000">C++ source code at GitHub</a>Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com4tag:blogger.com,1999:blog-6235228183359468917.post-23508793970197951412006-11-12T11:05:00.000-08:002019-01-30T13:06:16.461-08:00Fun compiler bugs<code>void bar() {}<br />
<br />
namespace foo<br />
{<br />
using ::bar;<br />
}<br />
<br />
using namespace foo;<br />
// namespace {}<br />
<br />
int main(int argc, char * argv[])<br />
{<br />
bar();<br />
return 0;<br />
}<br />
</code><br />
In VC6, the preceding block of code produces<br />
<b>error C2668: 'bar' : ambiguous call to overloaded function</b><br />
and the error goes away when you uncomment "namespace {}". Yikes.Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com0tag:blogger.com,1999:blog-6235228183359468917.post-18815467723402412802006-08-27T06:13:00.000-07:002011-05-04T00:07:43.163-07:00Fixing GoogleA couple weeks ago, Google decided to <a href="http://www.searchenginejournal.com/?p=3717">yank the Groups link</a> from its search pages and hide it under a new "more »" link. This <a href="http://software.gurock.com/postings/google-hides-newsgroups/167/">pissed off</a> a <a href="http://groups.google.com/group/google.public.support.general/browse_frm/thread/18721e8a88ba8ed7/1384cf06fcc69269">few</a> <a href="http://groups.google.com/group/Accounts-Help-Troubleshooting/browse_frm/thread/61f641c579760e27">people</a> (including me), but given that this was a change to core search UI of Google, I'm surprised the reaction wasn't stronger. Maybe the extra mouse click just isn't a big deal for most people.<br />
<br />
For the rest of us, however, this was begging for a fix. My searching revealed a <a href="http://groups.csail.mit.edu/uid/chickenfoot/">Chickenfoot</a> script <a href="http://software.gurock.com/postings/unhiding-google-groups/174/">here</a> that looked promising. Unfortunately, I found that Chickenfoot isn't quite ready for primetime. When I set the script to run on *.google.com/*, then went to mail.google.com, Chickenfoot caused Firefox to freeze and consume 99% CPU.<br />
<br />
At that point I knew I knew it was time to break out good ol' <a href="http://greasemonkey.mozdev.org/">Greasemonkey</a>. A couple hours of hacking, and the problem was solved. <a href="https://github.com/russelldavis/MoveGoogleHeaderLinks/raw/master/MoveGoogleHeaderLinks.user.js">The script</a> is easily customizable, and by default also restores the Froogle and Books links. Let me know if you have any suggestions or feedback.<br />
<br />
<b>Update:</b> Google changed a few things that broke the script. I should have an update this weekend that fixes it and makes it more resistant to being broken by minor changes.<br />
<br />
<b>Update 2.0: </b>Made a few tweaks and got everything working again. As per David's request, the script also has two new functions. hideGoogleSearchLink moves a link off the main page and into the 'more »' popup. removeGoogleSearchLink gets rid of a link altogether. Enjoy...Russhttp://www.blogger.com/profile/06044594491166082413noreply@blogger.com3