MacBook, defective by design banner

Put the knife down and take a green herb, dude.

One feller's views on the state of everyday computer science & its application (and now, OTHER STUFF) who isn't rich enough to shell out for

Back-up your data and, when you bike, always wear white.
Friday, September 23, 2016

"At Least 500 Million Yahoo Accounts Hacked in Late 2014" via Macrumors.

Yahoo today confirmed that "at least" 500 million Yahoo accounts were compromised in an attack in late 2014, leaking customer information like names, email addresses, telephone numbers, birthdates, hashed passwords, and both encrypted and unencrypted security questions and answers.

Does this surprise anyone at this point?

You know, I think if I had a huge cloud company with hundreds of millions of users, I'd consider having at least three sets of teams writing at least the fascade of the software -- the server-side controller methods -- so I could rotate from one to another every sprint or so to throw off would-be hackers. As soon as they made progress hacking one, it'd be replaced by Team 2. By the time we got back around to Team 1, they'd have iterated once or twice, and the hackers would have to, if not start over, pivot. Or maybe any user would have an X% chance of bringing up Team 1, Y% 2, Z% 3 each time they started a session.

I'd likely do the same for the users' data, splitting them into into several different databases, and maybe rotating users back and forth. Several different architectures using several different databases, all pitching to a consistent UI and user experience. If you interface well, it's no problem.

I realize there are obvious downsides. Maybe Team 2 has a horrible design, and it's easily cracked. That is, I'm in some sense three times as likely to get hacked as before, even if it's a much smaller set of users that's compromised.

But even more importantly would seem to be to sniff your network traffic like heck to see when 500 million sets of birthdays had left the network. Bizarre.

Ultimately, though, RMS (hrm, apparently not Stallman) is on point: If it's on a computer, in a network, given enough time, it'll eventually be free to anyone else on that network. Networked zeroes and ones want to be free.

Labels: , , , ,

posted by ruffin at 9/23/2016 12:19:00 PM
Wednesday, September 21, 2016

From DaringFireball:

A new Rolex needs to look like a Rolex. A Leica needs to look like a Leica. A new Coca-Cola bottle needs to look like a Coca-Cola bottle.

I mean, I get the point that each is iconically designed, generally, but, um...

Put another way, Andy Warhol would've only included one of those in his pop-art series (mais quelle ironie, non?)

Labels: ,

posted by ruffin at 9/21/2016 08:38:00 AM
Monday, September 19, 2016

The only thing I can do is wish you a good luck as the situation totally unfolds on you.

They had me up until that poorly translated line.

(Okay, no, no they didn't. But it was a hilarious/horrible ending. If you're going to pay to robocall tons of people, you might as well translate your threat properly first.)

posted by ruffin at 9/19/2016 01:06:00 PM
Friday, September 16, 2016

I posted to Medium, so now I get a daily "newsletter". It's not super, but this morning I checked out Why Silicon Valley is all wrong about Apple’s AirPods by Chris Messina.

He starts, give or take, with this:

Last week, Apple did it again, but for some reason, nearly everyone in Silicon Valley is confused about what just happened. I mean, I understand the confusion, but do people really think that the most significant announcement was the removal of the 3.5mm analog headphone jack? I mean, it was, but not for the reasons everyone’s [in a tizzy].

Apple doesn’t give [two shakes] about neckbeard hipsters who spent thousands of dollars on expensive audiophile gear that rely on 100-year-old technology to transmit audio signals. They’ll readily drop them faster than Trump drops facts to make an argument in a televised debate.

Apple is securing its future, and to do that, it must continue to shrink the physical distance between its products and its customers’ conceptions of self. The Apple ᴡᴀᴛᴄʜ came first, busting our sidekick supercomputer out of our pockets and onto our skin. Apple’s next move will put its products literally within earshot of our minds.

He then goes on to recap my Medium post on AirPods (not actually my post, I don't think, but exactly the same ideas, all the way to deriding businessmen who wore Jawbones), but wasted words, less direction, and better pictures.

Labels: , , ,

posted by ruffin at 9/16/2016 08:33:00 AM
Wednesday, September 14, 2016

Note to self: Never create images for documentation until you're done with your release. No, no no. ALL the way done with your release. I thought I could "get started" on my docs a little early, so I did. Not the worst idea ever, but I recently added a new toolbar button or two. I got lucky, I think, and can use my old images, like this one:

help image

... since it's so tiny you can barely see what's in the toolbars. But if it'd shown one extra in the bottom or all of the top, I'd be remaking them now.

top command bar for MarkUpDown

See that header button way over on the right? That's new.

bottom command bar for MarkUpDown

And then for some strange reason I put the "Find" button on the bottom. Argh. That was close.

I won't say anything about that tab close "X" in the first image next to the "New 0" file tab. Except that if you'd been reading, you'd know I just added that. That may or may have been retroactively added to the original image. Ms. Paint, indeed.

Labels: , , , ,

posted by ruffin at 9/14/2016 10:03:00 AM
Tuesday, September 13, 2016


Ouch. "When not to buy a Macintosh." Seriously, it's well past time, folks.

Labels: , ,

posted by ruffin at 9/13/2016 02:15:00 PM
Friday, September 09, 2016

Oh, Pivots in UWP, you so crazy.

You may have heard that I'm writing a Markdown editor, MarkUpDown. It can have several files open at once, of course, and I'm using a UWP Pivot control to handle navigation.

As I got closer to releasing, it hit me that Ctrl-W, though common, isn't the most discoverable way to close those PivotItems. And now that I'm maintaining state between starts, so that whatever tabs you have open when you close the app are back on restart, closing each file "on purpose" is a lot more important than when they all closed on each restart.

That is, it looks like I need a UI for closeable tabs.

Not as easily said as done. You can customize the Header of the PivotItem pretty easily. In fact, a Header can be any object. You create a custom UserControl, throw in your favorite UI widgets, and you're golden.

In that UserControl, I put a TextArea and an icon of some sort, here a box with an X in it donated from Material Design Icons... Took a little experimenting to figure out exactly how to put text and an icon into the header presentably, though. I initially used a ViewBox, which seemed to scale the Path style image I'm using fairly well, no resizing necessary, but the ViewBox hated responding to clicks (or, in this case, "Taps" and "Presses"). Apparently you can manually set something called HandledEventsToo to make it catch events that are already caught by something with higher priority, but that strange Boolean reminds me of CSS' !important a little too much.

I replaced the ViewBox with a Button to be conventional, and then placed the Path style icon in there. I've got decent click event handling now, though it was difficult (well, at least "non-trivial") to get the icon to display centered. I went through the old process of using WPF Geometry Transformer to "Tansform" [sic] the Path into something smaller, and poof... -ish.


    <StackPanel Orientation="Horizontal">
        <TextBlock Margin="0,0,0,0" Name="txtHeader" FontSize="18">Test</TextBlock>
        <Button Background="White" Click="Button_Click">
                <PathIcon Data="M13.3000001907349,2.09999990463257L3.5,2.09999990463257 2.51005053520203,2.51005053520203 2.09999990463257,3.5 2.09999990463257,13.3000001907349 2.51005053520203,14.2899494171143 3.5,14.6999998092651 13.3000001907349,14.6999998092651 14.2899494171143,14.2899494171143 14.6999998092651,13.3000001907349 14.6999998092651,3.5 14.2899494171143,2.51005053520203 13.3000001907349,2.09999990463257 M13.3000001907349,13.3000001907349L3.5,13.3000001907349 3.5,3.5 13.3000001907349,3.5 13.3000001907349,13.3000001907349 M11.8999996185303,5.87999963760376L9.3799991607666,8.39999961853027 11.8999996185303,10.9200000762939 10.9200000762939,11.8999996185303 8.39999961853027,9.3799991607666 5.87999963760376,11.8999996185303 4.90000009536743,10.9200000762939 7.42000007629395,8.39999961853027 4.90000009536743,5.87999963760376 5.87999963760376,4.90000009536743 8.39999961853027,7.42000007629395 10.9200000762939,4.90000009536743 11.8999996185303,5.87999963760376z" />

That's fun, isn't it?

example of two closeable tabs

That looks okay, but there are still two problems.

  1. How do I set the Label (now placed in txtHeader) of my UserControl in XAML?
  2. How I do I remove the PivotItem once its button is clicked.

Okay, three problems -- I really should change the icon to a greyed-out version when the PivotItem's not active. That looks awful. Mark that down for version two.

Accessing a property in custom XAML from C

I found the answer to the first pretty easily: You have to use a Dependency Property, of course!

Dependency property values are not stored as fields on the class, they are stored by the xaml framework, and are referenced using a key, which is retrieved when the property is registered with the Windows Runtime property system by calling the DependencyProperty.Register method.

But wait! There's more!

Defining a dependency property can be thought of as a set of concepts. These concepts are not necessarily procedural steps, because several concepts can be addressed in a single line of code in the implementation. This list gives just a quick overview. We'll explain each concept in more detail later in this topic, and we'll show you example code in several languages.

  • Register the property name with the property system (call Register), specifying an owner type and the type of the property value.
  • There's a required parameter for Register that expects property metadata. Specify null for this, or if you want property-changed behavior, or a metadata-based default value that can be restored by calling ClearValue, specify an instance of PropertyMetadata.
  • Define a DependencyProperty identifier as a public static readonly property member on the owner type.
  • Define a wrapper property, following the property accessor model that's used in the language you are implementing. The wrapper property name should match the name string that you used in Register. Implement the get and set accessors to connect the wrapper with the dependency property that it wraps, by calling GetValue and SetValue and passing your own property's identifier as a parameter.
  • (Optional) Place attributes such as ContentPropertyAttribute on the wrapper.

Note If you are defining a custom attached property, you generally omit the wrapper. Instead, you write a different style of accessor that a XAML processor can use. See Custom attached properties.

... [Oh, but there's more... -mfn] ...

In some scenarios, you are defining dependency properties for objects that are used on more than one UI thread. This might be the case if you are defining a data object that is used by multiple apps, or a control that you use in more than one app. You can enable the exchange of the object between different UI threads by providing a CreateDefaultValueCallback implementation rather than a default value instance, which is tied to the thread that registered the property.

Tis a silly place

I feel like the Knights of the Round Table after they've considered whether to go to Camelot. Okay, nevermind. 'Tis a silly place. I won't make these new headers XAML-friendly for "version mvp".

Removing a PivotItem on custom UI click

My first bright idea, which I've used before, is to take the sender, cast to the appropriate widget, find its Parent, and just slowly climb my way back up the UI hierarchy until I find what I need. That is, I'll drill up, like a jQuery closest, until I have the PivotItem, then the Pivot, that I need. Then I can remove the PivotItem from the Pivot's Items collection. Easy, right? The best part is that this normally doesn't change, and you can have the PivotItem remove itself without any serious hooking in with what's around it. (I could probably do this more impressively with reflection, and essentially hook an extension method up for UIElement that parallels the jQuery closest method I references earlier.)

But crimminy. Here's the drill-up code I ended up with, originally in the UserControl's Button's Click event. Remember that this is just exploratory code at this point.

Button btn = (Button)sender;

var spam = (StackPanel)(btn.Parent);

var header = (CloseableTabHeader)(spam.Parent);
var headerItem = (PivotHeaderItem)(header.Parent);

PivotHeaderPanel headerPanel = (PivotHeaderPanel)(headerItem.Parent);
Grid weirdPiGrid = (Grid)headerPanel.Parent;

ContentControl contentControl = (ContentControl)weirdPiGrid.Parent;
Grid anotherGrid = (Grid)contentControl.Parent;
PivotPanel pivotPanel = (PivotPanel)anotherGrid.Parent;
ScrollViewer scrollViewer = (ScrollViewer)pivotPanel.Parent;
Grid yaGrid = (Grid)scrollViewer.Parent;
Grid yaGrid2 = (Grid)yaGrid.Parent;

That's interesting, right? Not only is it much more convoluted a design than I would've expected, we also never get a PivotItem or a Pivot -- yaGrid2 is the "root element" of the page, I think. And the stuff we do get, like PivotPanel, come with warnings like this:

PivotPanel isn't typically used for general XAML UI composition.

/sigh This was easy, wasn't it? My UI traversal has me lost in the funhouse rather than in a cleanly executed UI widget hierarchy that follows its own mental model. Feels like I went out of the back door and I'm seeing the outside of the house isn't finished quite yet. Unfortunately, I get the impression that UWP is held together by chicken wire and duct tape a lot more than I'm used to seeing in a Microsoft UI toolkit.

There's probably some easy way to save what I'm trying to do from the fire, but forget it. For version mvp, I'm changing the CloseableHeader constructor from this...

public CloseableTabHeader(string headerText) : base()
    txtHeader.Text = headerText;

... to this...

public PivotItem itemParent = null;
public Pivot pivotParent = null;

public CloseableTabHeader(string headerText, PivotItem itemParent, Pivot pivotParent) : base()
    txtHeader.Text = headerText;
    this.itemParent = itemParent;
    this.pivotParent = pivotParent;

I think you see where I'm going. Yes, I feel a little dirty too. Now I can remove it easily in the Button's Click event:

private void Button_Click(object sender, RoutedEventArgs e)
    if (null != this.itemParent && null != this.pivotParent)

Hrm. Perhaps "parentPivot" is better than "pivotParent", and same with itemParent. In any event, you want to bubble up to the closest PivotItem and Pivot, and this makes that stupidly straightforward, though I do wonder how much Dispose-ing I should be doing.

I don't love that set-up, and I really dislike the way the buttons' bounds "highlight" simply when you mouse over the icon, like this:

highlighted close button

... but overall, that's a workable solution that will make discovery for tab closure much more straightforward for non-keyboard addicts.

Labels: , , ,

posted by ruffin at 9/09/2016 08:56:00 AM

Support freedom
All posts can be accessed here:

Just the last year o' posts:

URLs I want to remember:
* Atari 2600 programming on your Mac
* joel on software (tip pt)
* Professional links: resume, github, paltry StackOverflow * Regular Expression Introduction (copy)
* The hex editor whose name I forget
* JSONLint to pretty-ify JSON
* Using CommonDialog in VB 6 * Free zip utils
* that hardware vendor review site I forget about is here * Regex Tester
* Read the bits about the zone * Find column in sql server db by name
* Giant ASCII Textifier in Stick Figures (in Ivrit) * Quick intro to Javascript
* Don't [over-]sweat "micro-optimization" * Parsing str's in VB6
* .ToString("yyyy-MM-dd HH:mm:ss.fff", CultureInfo.InvariantCulture); (src) * Break on a Lenovo T430: Fn+Alt+B
email if ya gotta, RSS if ya wanna RSS, ¢ & Δ if you're keypadless

Powered by Blogger Curmudgeon Gamer badge