Sunday, April 30, 2017

Base64 macOS App Release

Released v1.0 of Base64 macOS app. It is a simple app for encoding and decoding base64 texts. It will encode texts as we type or paste. This program does not access any files or network and works offline. It is sandboxed as well.

Encode screen

Decode screen

Source code at GitHub. For downloads, check the release folder.

Saturday, April 29, 2017

Working with AppKit Delegates

Delegates are responders that acts to events that occurs in a program. AppKit delegates often work with Cocoa UI events. Here we will see two examples of handling events, one for NSTextField and another for NSTextView in conjunction with Interface Builder, rather than programatically.

1. Create a macOS Cocoa project from Xcode which will generate an AppDelegate and a ViewController as usual.
2. We will make the ViewController as the delegate to respond to events. For that we need to declare that the ViewController adopts the formal protocol defined by the delegates.
@interface ViewController : NSViewController<NSTextViewDelegate, NSTextFieldDelegate> {
3. Choose the Main.storyboard and choose the View Controller Scene, drag and drop Text View and Text Field components.
4. Choose the Text View from the Document Outline of the View Controller Scene, option click, and in the popup, connect the delegate outlet to the View Controller. Same for Text Field.

5. Now, in the ViewController.h header, declare two IBOutlets which will connect the components in the storyboard to the code.
@interface ViewController : NSViewController<NSTextViewDelegate, NSTextFieldDelegate> {
IBOutlet NSTextView *textView;
IBOutlet NSTextField *textField;
}
Since these interface builder outlets are not connected yet, the radio box is in unchecked state.
6. Go back to the interface builder (the storyboard file), choose Text View, option click, drag and connect the New Referencing Outlet to View Controller which brings the above IBOutlets. Choose textView to make the connection. Do the same for Text Field, but here we should choose textField as the referencing outlet.


7. Back to code, open ViewController.m implementation file and implement any of the delegated methods.
#pragma mark - delegates

/* NSTextView */
- (void)textDidChange:(NSNotification *)notification {
NSLog(@"text did change");
textView = [notification object];
NSLog(@"string: %@", [textView string]);
}

/* NSTextField */
- (void)controlTextDidChange:(NSNotification *)obj {
NSLog(@"control text did changed");
textField = [obj object];
NSLog(@"text: %@", [textField stringValue]);
}
The above methods are invoked when the text in a text view or text field changes. The same concept extends to Cocoa Touch and iOS development.

The sample project can be downloaded from github.

Wednesday, April 26, 2017

Call blocking in BlackBerry 10 for a known number

We do not need fancy app to block calls. By default, BB10 has option to block all incoming calls or none. Not individually. But there is a better way. Ideally, we should not be blocking calls, because the caller can identify that a call has been blocked or not. It will ring once and then get busy or some other tones. Better way is to just disable all notifications for a number. For that, first save the annoying number to your contacts and in the "Ringtones and Notifications" option for that contact, choose "Phone Calls" and turn off "All Notifications". That is all there is. Now the call gets received, but you would not know unless you look at the phone. No disturbance.

Monday, April 17, 2017

Slack for BlackBerry 10

There is no official Slack app for BlackBerry 10. Also, if we open a slack channel on the native BlackBerry 10 browser, it just takes to the team settings page. I have figured ways to make it work though, which in fact is quite simple. Quick way is to enable desktop mode in the BB10 browser and then channels load instead of seeing the settings page for the team. But it's not at all user friendly and unsupported browser message will be shown.

Another way is to install the Slack app for Android by sideloading the apk file. This works fine when the team uses email for login. But, when it's configured for SSO only, then we have to follow additional steps. The native browser can open apps that have deep linking registered. Slack does not seem to have this. In order to make this work, we need to use a browser which also runs on the Android runtime. So get the Aurora Browser installed, open the Slack app, choose SSO sign in and this time choose Aurora browser when the dialog pops up. After authentication, a page will be shown with a Download Slack app or Open in Slack app buttons. Choose the later and the Slack app launches, and you get logged in to the team. Enjoy all the awesomeness of the Android Slack app.

I have not checked whether notifications will get received. But I doubt that. So if you don't receive it, you can choose the send email notifications when away for five minutes option from the team settings. Though there is a slight delay in you getting notified, the problem is solved.

I have tried S10 app from BlackBerry World, but for some reasons, I don't get any notifications. Plus the app is rather minimal with text only interface. Kind of have an IRC feel to it.

2FA with SAP Authenticator for BlackBerry 10

The search for a decent 2FA app for BlackBerry 10 is over. SAP Authenticator works perfectly on BlackBerry 10 devices. This is a generic 2FA app and is not tied to any service like Duo Mobile for BlackBerry 10. As in Android, this app requires Barcode Scanner to be installed as well. Instead of Google Authenticator you can use this. It can be used for any 2FA that uses TOTP (Time-based OTP). Happy camper!

Tip: When a website provides options for 2FA app, choose Android as the platform which will display the QR code. Choosing BlackBerry will give the secret key which we have to enter in manually in the SAP Authenticator app for setup rather than scanning a QR code.

Sunday, April 16, 2017

youtube-dl for Muxing Streams

Let's say we need to download videos from youtube with the highest audio and video quality. Sometimes, the combination is not available with most downloaders. But youtube-dl can download separate audio and video streams and mux them together. Here are some commands to do that.
# List all available streams for a video
➜ youtube-dl -F "https://www.youtube.com/watch?v=abcd1234"
Outputs
[youtube] abcd1234: Downloading webpage
[youtube] abcd1234: Downloading video info webpage
[youtube] abcd1234: Extracting video information
[youtube] abcd1234: Downloading js player en_US-vfl5-0t5t
[youtube] abcd1234: Downloading js player en_US-vfl5-0t5t
[info] Available formats for abcd1234:
format code extension resolution note
249 webm audio only DASH audio 56k , opus @ 50k, 1.52MiB
250 webm audio only DASH audio 84k , opus @ 70k, 2.10MiB
171 webm audio only DASH audio 126k , vorbis@128k, 3.36MiB
140 m4a audio only DASH audio 127k , m4a_dash container, mp4a.40.2@128k, 3.69MiB
251 webm audio only DASH audio 161k , opus @160k, 4.03MiB
278 webm 256x144 144p 101k , webm container, vp9, 13fps, video only, 2.41MiB
160 mp4 256x144 144p 112k , avc1.4d400c, 25fps, video only, 3.19MiB
242 webm 426x240 240p 140k , vp9, 25fps, video only, 2.34MiB
243 webm 640x360 360p 234k , vp9, 25fps, video only, 3.98MiB
133 mp4 426x240 240p 248k , avc1.4d4015, 25fps, video only, 7.13MiB
134 mp4 640x360 360p 254k , avc1.4d401e, 25fps, video only, 6.49MiB
244 webm 854x480 480p 355k , vp9, 25fps, video only, 6.22MiB
135 mp4 854x480 480p 559k , avc1.4d401e, 25fps, video only, 13.74MiB
247 webm 1280x720 720p 601k , vp9, 25fps, video only, 11.70MiB
136 mp4 1280x720 720p 1171k , avc1.4d401f, 25fps, video only, 28.41MiB
248 webm 1920x1080 1080p 1220k , vp9, 25fps, video only, 23.32MiB
137 mp4 1920x1080 1080p 2258k , avc1.640028, 25fps, video only, 57.07MiB
17 3gp 176x144 small , mp4v.20.3, mp4a.40.2@ 24k
36 3gp 320x180 small , mp4v.20.3, mp4a.40.2
43 webm 640x360 medium , vp8.0, vorbis@128k
18 mp4 640x360 medium , avc1.42001E, mp4a.40.2@ 96k
22 mp4 1280x720 hd720 , avc1.64001F, mp4a.40.2@192k (best)

We can see that the highest quality video is 137 with 1080p 2258k and audio is 251 with 161k. But these are video only and audio only streams. Let's combine them.
➜ youtube-dl -f 137+251 "https://www.youtube.com/watch?v=abcd1234"
It will pick a compatible format when merging. If mp4 doesn't work it gets converted into mkv mostly.

Misc
Automatically choose best video and audio: -f bestvideo+bestaudio
Download subtitle if the video has one already uploaded: --write-srt --sub-lang en

Install BlackBerry Blend/Link under macOS Sierra

The installer Install BlackBerry 10 Desktop Software.app inside the BlackBerry 10 Desktop Software_1.2.0.58_B60.dmg image for BlackBerry Link/Blend does not start the installer under macOS Sierra. Running the binary inside the installer .app directly gives the following error:
➜  ~ /Volumes/BlackBerry\ 10\ Desktop\ Software/Install\ BlackBerry\ 10\ Desktop\ Software.app/Contents/MacOS/Install\ BlackBerry\ 10\ Desktop\ Software ; exit;
/Library/LaunchAgents/com.rim.BBLaunchAgent.plist: Could not find specified service
/Library/LaunchDaemons/com.rim.BBDaemon.plist: Could not find specified service
However under the Resources folder of the package content there is BlackBerry Blend.pkg installer. Running it brings up the installer window and the installation succeeds and everything works fine ever after.

Sunday, April 2, 2017

Fun with Hopper on OS X

It has be a while that I touched any assembly code. So I thought I will refresh, and have some fun while at it. Hopper is a disassembler for macOS. It has call flow graphs and pseudo code as in IDA Pro. Another awesome thing is the themes, which adds a modern touch, and is easy to use. This is more about using Hopper for disassemble and patching Mac OS X binaries. So let's get started. For that I will choose a real app. There was a case where I had to downgrade iTunes once. For that I had to use AppZapper. AppZapper is a paid software. When you open it you can see the nag screen. But removing the nag is simple.



Open the app in Hopper. The AppZapper package has only one binary file AppZapper. Proceed with the default choices, i.e., for the package the loader is FAT archive x86-64 bit and for the executable it is Mach-O 64 bits. It shows the entry point procedure at address 0000000100000f60. Before proceeding, enable "Show the HEX column" to easily see the hex of the instruction set, like in OllyDbg.

Now from the left symbols panel, under Proc. choose -[AZAppController applicationDidFinishLaunching:] the idx of which is 88. Alternatively you can directly go to the address of the proc at 000000010000a250. Choose the pseudo code mode from the toolbar to get an idea of what is happening.



What it does is that it loads the AZRegistrationWindowController and calls the validateExistingRegistrationInformation method whose return value is in rax register. Then it takes the lower bytes of the ax register and performs a bitwise and (the test instruction). If the result is 0, means al is 0, then the zero flag (ZF) is set. If zero flag is not set, then do a local jump to the address at loc_10000a6ac which is at 000000010000a6ac. What we need to do is to take that branch which will then skip loading the AZRegistrationWindowController window. To do that we need to change the jne instruction to je. So the easy way is to click on the jne line and click the hex mode, which will highlight the instruction. The hex for jne/jnz instruction is 85 and hex for je/jz is 84. So double click 85 in instruction 0F 85 FC 02 00 00 and replace it with 84. Go back to asm mode and you can see the updated instruction. Only that it is shown in bytes (db).



Now we need to export the binary. From File menu choose "Produce new executable" and save as AppZapper. Go to applications, control click AppZapper and choose "Show Package Contents" and navigate to MacOS. Now replace the executable with the patched one. If you want to preserve the original then, rename that to something else and copy the patched one as AppZapper. Open the app, and we are no more greeted with the nag screen!

But hey, we still got to register and have only 5 zaps, so we will have to purchase if we need to continue using :). The register option is available from the menu.