-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathindex.html
More file actions
172 lines (118 loc) · 31.4 KB
/
index.html
File metadata and controls
172 lines (118 loc) · 31.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<!DOCTYPE html>
<html>
<head>
<title>Dan's stream of consciousness</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" type="text/css" href="lib/codemirror.css" />
<link rel="stylesheet" type="text/css" href="lib/sketchy.css" />
<link rel="stylesheet" type="text/css" href="stream.css" />
<script src="lib/head.js"></script>
<script><!--
head.js(
"lib/mousetrap.js",
"lib/mousetrap-global-bind.js",
"lib/codemirror.js",
"lib/mode/css.js",
"lib/mode/less.js",
"lib/mode/sass.js",
"lib/mode/clike.js",
"lib/mode/coffeescript.js",
"lib/mode/javascript.js",
"lib/mode/python.js",
"lib/mode/ruby.js",
"lib/less.js",
"lib/sass.js",
"lib/mustache.js",
"lib/base64.js",
"lib/underscore-min.js",
"lib/github.js",
"lib/lazy.js",
"lib/lazy.dom.js",
"lib/sketchy.js",
"stream.js",
function() {
document.body.removeAttribute('class');
}
);
--></script>
<style type="text/css" id="custom-styles"></style>
</head>
<body class="loading">
<nav>
<ul></ul>
</nav>
<aside id="notices">
<ul></ul>
</aside>
<article>
<h1>Dan's stream of consciousness<br></h1>
<h2>August 14, 2003</h2>
<p>When I was at <a href="http://www.cardpool.com/">Cardpool</a> one of my projects was a JavaScript library to parse the data from cards with magnetic strips (gift cards, credit cards, and driver's licenses). Before developing the library in-house, we did a research into commercial options available, one of which was a .NET product with a license-based business model.<br></p>
<p>I downloaded the DLL, opened it up with <a href="http://www.red-gate.com/products/dotnet-development/reflector/">Reflector</a>, and quickly figured out how to bypass their licensing restrictions by finding where the code replaced its output with "PURCHASE LICENSE" (or whatever the string was). With very little effort, I was able to whip up a little helper library that exposed the private methods this code called and use the product's full functionality without a license.<br></p>
<p>It was really just an experiment. We never had any intention of using the product without buying it (money wasn't an issue, so it would have been silly to break the law). But it taught me a few things, which don't really apply to my life but would if I were ever to work on some commercial .NET library:<br></p>
<ul><li contenteditable="true">If you're going to be offering a free trial download, you should probably have a separately compiled TRIAL build that doesn't include all of the product's functionality to begin with.<br></li><li contenteditable="true">If maintaining a separate trial build isn't an option (totally legit as this could be a lot of work), at least obfuscate your code before compiling the RELEASE build so that if/when it's decompiled it's still difficult to navigate (and therefore crack).<br></li><li contenteditable="true">Probably don't use literal strings in the code for things that are obviously related to hiding functionality in your trial version. That will make it easy to figure out where this logic is. (To be honest, though, I don't know what the alternative is. There's probably a way to encode the strings somehow is resources in the DLL without them being discoverable? Or maybe not. I've never had to worry about that before.)<br></li></ul>
<h1>Introduction</h1>
<p>So this is a work in progress. But so far I'm pretty pleased with how it's shaping up.</p>
<h2>What is it?</h2>
<p>I'm <a href="https://github.com/dtao">Dan</a>. Right now, I can edit this document, right in my browser, but nobody else can. That's because I have my GitHub credentials saved in my browser's <code>localStorage</code> (yeah, yeah, I know, <a href="http://stackoverflow.com/questions/3718349/html5-localstorage-security">bad practice</a>... I'll get to that in a minute). So this is kind of like a blogging platform, but just for me specifically.</p>
<h2>How does it work?</h2>
<p>Here's how it works. The content is editable--again, only by me--via the <code>contenteditable</code> attribute. I can do the following:</p>
<ul><li contenteditable="true">Insert a new element <em>after</em> the current one anywhere with <kbd>Enter</kbd></li><li contenteditable="true">Insert a new element <em>before</em> the current one with <kbd>Ctrl</kbd>+<kbd>Enter</kbd></li><li contenteditable="true">Change the current element to a heading (<code><h1></code> through <code><h3></code>) with <kbd>Ctrl</kbd>+<kbd>[number]</kbd></li><li contenteditable="true">Change the current element to a paragraph with <kbd>Ctrl</kbd>+<kbd>P</kbd></li><li contenteditable="true">Change the current element to a list item (<code><li></code>) with <kbd>Ctrl</kbd>+<kbd>L</kbd></li><li contenteditable="true">Change the current element to a blockquote (<code><blockquote></code>) with <kbd>Ctrl</kbd>+<kbd>Q</kbd></li><li contenteditable="true">Make the selected text <strong>bold</strong> with <kbd>Ctrl</kbd>+<kbd>B</kbd>, <em>italic</em> with <kbd>Ctrl</kbd>+<kbd>I</kbd>, as <code>code</code> with <kbd>Ctrl</kbd>+<kbd>`</kbd>, or <del>struck-through</del> with <kbd>Ctrl</kbd>+<kbd>Backspace</kbd></li><li contenteditable="true">Change the selected text to a <a href="http://en.wikipedia.org/wiki/Hyperlink">hyperlink</a> with <kbd>Ctrl</kbd>+<kbd>A</kbd> (which will prompt me for a URL and then update the selection to <code><a href="..."></code>)</li></ul>
<p>What's also really cool is that it dynamically updates the table of contents as I edit it (you can see it to the left of the content if you're browsing on a reasonably large device).</p>
<ul></ul>
<ul></ul>
<h2>More advanced features</h2>
<p>I can also modify the style of the page, using CSS, LESS, or SASS, by hitting <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>C</kbd>, which brings up a nice syntax-highlighted editor, dynamically updating the page as I type in it.</p>
<p>I can insert code snippets using <kbd>Ctrl</kbd>+<kbd>M</kbd> (I know: bad shortcut), which will open a pop-up prompting me to select a language mode and then insert a <a href="http://codemirror.net/">CodeMirror</a> editor with syntax highlighting, proper indentation, etc.</p>
<pre data-mode="ruby">class CodeSnippet
def initialize(code)
@code = code
end
def insert_into_page(page)
page.insert(self)
end
end</pre>
<p>I can even <strong>draw a picture</strong> using <a href="https://github.com/dtao/sketchy.js">Sketchy.js</a>, another little project I've started that lets you draw directly in an HTML5 canvas:</p>
<img src="data:image/png;base64,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" />
<p>At any point, I can save my work by hitting <kbd>Ctrl</kbd>+<kbd>S</kbd>. This will actually push a commit to the GitHub Pages branch where this page is hosted. So within minutes the change will be visible to anyone.</p>
<h2>Stuff you might be asking</h2>
<p>I can almost hear the criticism coming through already... (Or am I just a pessimist?)</p>
<h3>This seems like a rip-off of Medium.js</h3>
<p>Well, that's not a very nice thing to say! Seriously, though, I just started this project, like, a few days ago. And I didn't know about <a href="http://jakiestfu.github.io/Medium.js/docs/">Medium.js</a>. Also, I think it's pretty different. I'm really not aiming for a reusable component that developers can drop into their websites. Rather, my intention is to (eventually) provide a dead-simple way for a fairly code-savvy writer/blogger/etc. (read: <strong>me</strong>) to get a static site hosted somewhere and then be able to update it, whenever, very easily.</p>
<p>I will probably explain this in more detail later.</p>
<h3>What's up with Sketchy.js?</h3>
<p>Yes, I did know that <a href="http://intridea.github.io/sketch.js/">sketch.js</a> exists (and to be honest, it's pretty sweet and I'll probably end up using it eventually). BUT it requires jQuery, and I didn't feel like using that. Next question!</p>
<h3>What's this localStorage security thing?</h3>
<p>Yeah, so, here's the deal with that. One of my goals here was to make this thing work as a static site, using only JavaScript. So authenticating via some server-side mechanism wasn't an option. Obviously it's foolish to store credentials directly in source; but using <code>localStorage</code> lets you store credentials on a particular machine without exposing them to other JavaScript loaded from other websites.</p>
<p>This is hardly an airtight security solution; I realize that. But I think to therefore refuse to go that route would be overly dogmatic. In practice, at least at the moment, I am the sole user of this "app" from a security standpoint. If I make the mistake of logging in from a shared computer, that's on me. Same if I expose a security vulnerability by, oh I don't know, requiring a library that happens to maliciously steal me credentials? (That would be so weird.)</p>
<p>Basically what I'm saying is that I think it's fine in this case.</p>
<h2>How to use this yourself</h2>
<p>I would say that this isn't <em>quite</em> ready for that. But eventually, the idea is, you would <a href="https://github.com/dtao/stream">fork this project on GitHub</a>. Then, you'd either delete or replace the CNAME file (since you can't <em>also</em> host the project at stream.danieltao.com). And you'd make some very slight alterations to the JavaScript, basically changing the <code>GITHUB_REPOSITORY</code> variable to the name of your repo.</p>
<p>And... that's it. At this point, you would visit your site at you.github.io/repo (or your own custom domain), click on 'Are you me?' (now meaning you), enter your creds and get started.</p>
<p>Like I said, it isn't really ready yet. The code has some bugs, which I will hopefully take the time to iron out over the next few... uh, months or whatever. And it's a bit messy, on top of that. But anyway, that's the idea!</p>
</article>
<div id="toolbar">
<!-- Only visible when authenticated -->
<button id="save">Save</button>
<button id="logout">Log out</button>
<!-- Only visible when NOT authenticated -->
<button id="login">Are you me?</button>
</div>
<div id="modal-input" class="autohide">
<input type="text" placeholder="">
</div>
<div id="modal-password-input" class="autohide">
<input type="password" placeholder="">
</div>
<div id="modal-blob" class="autohide">
<textarea></textarea>
</div>
<div id="modal-list" class="autohide">
<h1></h1>
<ul></ul>
</div>
<aside id="shortcuts">
<table></table>
</aside>
</body>
</html>