<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1546074471231747404</id><updated>2024-09-04T22:32:47.340-04:00</updated><category term="Python"/><category term="OS X"/><category term="C"/><category term="GoF Patterns"/><category term="Input Validation"/><category term="Linux"/><category term="Password Cracking"/><category term="UID"/><category term="UUID"/><category term="Usernames"/><category term="Visitor"/><category term="bash"/><category term="git"/><category term="mvn java gae xslt bash"/><category term="ssh"/><category term="svn"/><category term="unicode"/><title type='text'>Code Poetic</title><subtitle type='html'>Code poetic - Adjuring myself to design better, not claiming success. Writing on design and development in &amp;lt;various&amp;gt; within overlapping circles of security, web, &amp;amp; mobile. I hope these techniques, tactics, &amp;amp; snippets save readers time and trouble.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-3166667415532995180</id><published>2013-06-25T18:52:00.000-04:00</published><updated>2013-06-25T18:52:19.429-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Input Validation"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><category scheme="http://www.blogger.com/atom/ns#" term="UID"/><category scheme="http://www.blogger.com/atom/ns#" term="unicode"/><category scheme="http://www.blogger.com/atom/ns#" term="Usernames"/><category scheme="http://www.blogger.com/atom/ns#" term="UUID"/><title type='text'>Pitfalls of Unicode Usernames and Solutions in Canonical Form and UID </title><content type='html'>In a &lt;a href=&quot;http://labs.spotify.com/2013/06/18/creative-usernames/&quot; target=&quot;_blank&quot;&gt;blog entry&lt;/a&gt;,&amp;nbsp;&lt;a href=&quot;https://www.spotify.com/us/&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;Spotify&lt;/a&gt;&amp;nbsp;Labs recently shared their experience with difficulties supporting unicode usernames and differentiating them from their ascii homoglyphs. The entry describes, conceptually, how they isolated the problem&#39;s cause and worked around it.&lt;br /&gt;
&lt;br /&gt;
The blog entry is worth a read, it does a great job of outlining the problem, tracing symptoms to root cause, and positing conceptual fixes. Key design and implementation specifics, however, remain uncovered. Readers will continue to struggle to build a workable unicode aware username scheme. This post attempts to tackle those &#39;last mile&#39; design issues, providing a demonstrative stub implementation and test cases helpful in exploring particulars. &lt;br /&gt;
&lt;h3&gt;
Challenges&lt;/h3&gt;
Users may want fancy unicode usernames to differentiate themselves. The spotify blog provides an example: &quot;ᴮᴵᴳᴮᴵᴿᴰ&quot;.&amp;nbsp;❤❤ LuvYa❤❤ might be another. Site owners, on the other hand, want it to easily identify unique users and display their usernames in a variety of views. Site owners also want to make sure users can effectively differentiate those they know from those they don&#39;t. For instance, user Ohm (Ω) will be indistinguishable from user Omega (Ω). Users want this too--though they may not yet realize it. So, our requirements are:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Users may freely select fancy unicode usernames (or other profile elements);&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;The site can easily and consistently identify unique users;&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Sites can easily display fancy usernames in its many view contexts as intended (instead of escaped);&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Users can differentiate those users they know from those with which they&#39;re not familiar.&lt;/li&gt;
&lt;/ul&gt;
Recently, sites appear to be enforcing restrictive username and credential requirements rather than meeting the above challenges. This may be because of the difficulties involved or perhaps because security consultants and their standards/&quot;best-practices&quot; argue that &quot;special characters&quot; are dangerous.&amp;nbsp;Making matters worse for Spotify they appears to be using Python 2.x, a language known for its awkward and poor support for unicode.&lt;br /&gt;
&lt;br /&gt;
I find it deplorable when security professionals impact function or performance because they&#39;re too lazy to come up with a better solution; security should aim to ease user workflow and help performance where possible. As a user, I vote as such with my money: I closed my Discover credit account when they locked my account because my username used special characters--suddenly falling afoul of their new [WEAKER] security standards.&lt;br /&gt;
&lt;h3&gt;
Solution&lt;/h3&gt;
&lt;div&gt;
Solving for the above requirements involves two major components: a) consistent escaping and encoding of input from potentially different sources and b) universally unique identifier (UUID) creation. &amp;nbsp;Both solution elements end up presenting significant challenges in large enterprise systems--especially those already in place without them. To hedge against difficulty, this entry combines several heuristics and design elements:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Format data consistently;&lt;/li&gt;
&lt;li&gt;Decouple UID and freeform text;&lt;/li&gt;
&lt;li&gt;Encapsulate data and operations within strong types;&lt;/li&gt;
&lt;li&gt;Establish boundaries across which guarantees are enforced.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
The hope is that each is straightforward enough to easily complete and that when combined in a mutually reinforcing manner, they create a workable solution. &amp;nbsp;Let&#39;s start, in no particular order, with establishing boundaries with guarantees.&lt;br /&gt;
&lt;h2&gt;
Boundaries with Data Property Guarantees&lt;/h2&gt;
&lt;div&gt;
Where &amp;nbsp;possible define and enforce boundaries across which components, services, or clients can assert key properties about data&#39;s form. Some call these boundaries &quot;trust boundaries&quot;. Avoid this word because it&#39;s unclear what &quot;trust&quot; means. Be specific about what properties are being asserted across the boundary. Always design assertions around a provider asserting a guarantee rather than a consumer.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Candidate boundaries may be a) data stores, b) web services, c) transaction processors, d) rendering components, and other elements whose behavior or structure are well-specified. From a technology perspective, persistence frameworks, REST APIs, and message buses may represent candidates through which a façade, proxy, or similar design pattern could enforce such a boundary and its guarantees.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The attractiveness of such boundaries and their guarantees is clear: if we could assert the format and content of data at an interface, we&#39;d not be confused about whether or not its been escaped yet. We&#39;d know its encoding definitively. As with anything so attractive, achieving this goal is commonly impossible. These boundaries are like a Maginot line. Any break and the guarantee fails. So, inject data guarantee functionality into technologies that implement helpful patterns (like the façade). Watch for back-doors, chutes, and stovepipes around them. Meticulously document the format and content consumers can expect from these data sources. Now, onto those formatting guarantees. &amp;nbsp;&lt;/div&gt;
&lt;h2&gt;
Consistent Data Formatting&lt;/h2&gt;
&lt;div&gt;
A few common problems plague data formatting attempts. Some include:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Double escaping;&lt;/li&gt;
&lt;li&gt;Data destruction in transcoding (e.g. data loss between unicode and UTF-8)&lt;/li&gt;
&lt;li&gt;Unintended interpretation of formatted data in unexpected contexts:&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;e.g. by nest contexts such as HTML enclosing scripts&lt;/li&gt;
&lt;li&gt;e.g. by downstream processors such as SQL parsers&lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
In order to correctly and consistently format data, the design should:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Prefer idempotent formatting operations;&lt;/li&gt;
&lt;li&gt;Consistently apply non-idempotent formatting actions in a specific order-of-operations;&lt;/li&gt;
&lt;li&gt;Where possible, mark data as to current state of format;&lt;/li&gt;
&lt;li&gt;Explicitly document input format expectations, transforms, and output format.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
Idempotent transforms&lt;/h4&gt;
Ideally, any transform applied to data will be idempotent. In other words, the transform produces the same output regardless of how many times its applied to the input in succession. i.e.&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&amp;nbsp; &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;canonize(canonize(x)) == canonize(x)&lt;/span&gt;&lt;/blockquote&gt;
Failure to apply an idempotent transform causes the &#39;double escape&#39; problem described above. It&#39;s easy to see how escaping operations are not idempotent. &amp;nbsp; For example:&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; s=&#39;Ω&#39;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; s2 = s.encode(&#39;string-escape&#39;)&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; s&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&#39;\xe2\x84\xa6&#39;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; s2&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&#39;\\xe2\\x84\\xa6&#39;&lt;/span&gt;&lt;/blockquote&gt;
Each time the &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;encode()&lt;/span&gt; function is applied the result receives an additional level of escaping. This results in the following:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; print s&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Ω&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; print s2&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;\xe2\x84\xa6&lt;/span&gt;&lt;/blockquote&gt;
Luckily, in Python, the decode() function provides what perhaps some developers intend:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; print s.decode(&#39;string-escape&#39;)&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Ω&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;gt;&amp;gt;&amp;gt; print s2.decode(&#39;string-escape&#39;)&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;Ω&lt;/span&gt;&lt;/blockquote&gt;
The differences above can confuse even more experienced developers not familiar with Python&#39;s string handling and escaping. &amp;nbsp;In order to address these&amp;nbsp;idiosyncrasies&amp;nbsp;we use python&#39;s &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;unicodedata.normalize()&lt;/span&gt;(&lt;a href=&quot;http://docs.python.org/2/library/unicodedata.html&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;see docs&lt;/a&gt;) method. &lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;def canonize(clazz, unwashed):&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # do some stuff ...&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; washed = unicodedata.normalize(&#39;NFD&#39;, unwashed)&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # do other stuff...&lt;/span&gt;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return washed&lt;/span&gt;&lt;/blockquote&gt;
The above helps us exhibit idempotent behavior.&lt;br /&gt;
&lt;h4&gt;
Order of Operations&lt;/h4&gt;
&lt;div&gt;
Some of the operations we employ will destroy data (&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;truncate()&lt;/span&gt; for instance). For this reason and those discussed previously (escaping) formatting operations are not transitive. i.e.&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;A(B(x)) != B(A(x)&lt;/span&gt;&amp;nbsp;AND&amp;nbsp;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;escape(trunc(x)) != trunc(escape(x))&lt;/span&gt;&lt;/blockquote&gt;
Solutions, therefore, must pay very close attention to the the order in which operations are applied. In the past, the following order has worked well:&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Encode&lt;/li&gt;
&lt;li&gt;Substitute&lt;/li&gt;
&lt;li&gt;Truncate&lt;/li&gt;
&lt;li&gt;Escape&lt;/li&gt;
&lt;li&gt;Mark / Decorate&lt;/li&gt;
&lt;/ol&gt;
Plenty of reasons exist to change this order. For instance, some systems benefit from applying truncation first to avoid choking on large (malicious) inputs. In these cases, operations may have to be re-applied later because of the effect intermediate operations have (for instance, escaping may add to length after a previous truncation).&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
In some cases components need to reverse these operations. This is not always possible where a transform has destroyed data (like truncate(), strip(), and their ilk). When reversing operations, apply them in reverse order. &amp;nbsp;This works well when combined with object- or API-based boundaries:&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;class MyObject:&lt;br /&gt;&amp;nbsp; def __init__(self):&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;self.__stuff = Nonedef getStuff(self):  &lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;return self.__stuff.decode(&#39;unicode-escape&#39;)&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; def setStuff(self, stuff):&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;self.__stuff = stuff.encode(&#39;unicode-escape&#39;)&lt;br /&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/blockquote&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; def processStuff(self):  &lt;br /&gt;&amp;nbsp; &amp;nbsp; yum(self.__stuff)&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
&lt;br /&gt;
&lt;div class=&quot;p1&quot;&gt;
Encapsulation holds and we manipulate the object escaped within the type&#39;s bounds. When passed across the object&#39;s boundary (with the getter) we always tear escaping down. This, BTW, is not enough on its own--the object&#39;s &quot;yum()&quot; may not operate correctly under circumstances in which double-encoding has occurred. The goal here is &lt;i&gt;consistency.&lt;/i&gt;&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;
Data Marking&lt;/h4&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
Data formatting can not always be accomplished in one atomic operation, from the system&#39;s perspective. For instance, controller code may understand how to conduct certain input validation operations whereas only model code can properly encode and escape appropriately for storage. In these instances, components may mark data so that downstream processing understands the current state of format. Common methods for markup include:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Use of invalid characters (where possible) (e.g. marked_hex = 0x0126898U in which &#39;U&#39; might indicate unfiltered)&lt;/li&gt;
&lt;li&gt;Marks placed beyond range (e.g.&amp;nbsp;&lt;span style=&quot;background-color: #eeeeee; font-family: Consolas, Menlo, Monaco, &#39;Lucida Console&#39;, &#39;Liberation Mono&#39;, &#39;DejaVu Sans Mono&#39;, &#39;Bitstream Vera Sans Mono&#39;, &#39;Courier New&#39;, monospace, serif; font-size: 10px; line-height: 13px;&quot;&gt;$2a$10$KssILxWNR6k62B7yiX0GAe2Q7wwHlrzhF3LqtVvpyvHZf0MwvNfVu&amp;nbsp;&lt;/span&gt;in which &#39;$&#39; separates metadata)&lt;/li&gt;
&lt;li&gt;Markup languages (XML, JSON)&lt;/li&gt;
&lt;li&gt;Container types (e.g. &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;class SafeString&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;
Situations in which untrusted source provide data introduce the opportunity for exploit. For instance, there&#39;s no reason the attacker &lt;i&gt;has&lt;/i&gt; to match the metadata to the actual format of&amp;nbsp;the&amp;nbsp;underlying data. When operations are then applied unexpected results (collisions, double-encodings, etc.) may result to the attacker&#39;s benefit.&lt;/div&gt;
&lt;h2&gt;
Decouple UUID from Freeform Text&lt;/h2&gt;
&lt;div&gt;
The difficulties of getting freeform text formatting and storage correct (and an inability to force other developers&#39; and partners&#39; developers to use the types in which this text has been encapsulated rather than nekked strings has led me--in every case I can remember--to decouple UIDs from the username. Using UIDs as the basis for identification, equality, indexing/hashing, and other operations has other benefits (speed, ease) as well.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
There are many ways to create a UID. In python, the easiest way is perhaps &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;uuid.uuid4()&lt;/span&gt; (&lt;a href=&quot;http://docs.python.org/2/library/uuid.html&quot; target=&quot;_blank&quot;&gt;see docs&lt;/a&gt;). UUID4, defined by &lt;a href=&quot;http://tools.ietf.org/html/rfc4122.html&quot; target=&quot;_blank&quot;&gt;RFC 4122&lt;/a&gt;, &amp;nbsp;is random. In some circumstances, however, developers want distributed parties to be able to compute the uuid where it&#39;s not provided. In these circumstances&amp;nbsp;&lt;span style=&quot;font-family: &#39;Courier New&#39;, Courier, monospace;&quot;&gt;uuid.uuid3()&lt;/span&gt;may be appropriate. In the code provided with this blog entry, uuid3 is implemented &quot;manually&quot; for demonstrative purposes.&lt;br /&gt;
&lt;br /&gt;
When encapsulating UID and username within a type, strongly consider overloading pertinent operators (such as &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;__eq__()&lt;/span&gt;and&amp;nbsp;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;__ne__()&lt;/span&gt;) so that other developers&#39; conditionals don&#39;t surprise them with odd behavior:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;def __eq__(self, other):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (isinstance(other, UserName)):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (self.UID == other.UID):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return True&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; else:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return NotImplemented&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return False&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Also consider overriding &lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;__str__()&lt;/span&gt;. To be quite fancy, disable accessor / mutator methods to keep encapsulation and symmetric data formatting behaviors intact. **Note: Python&#39;s faux object orientation means that these steps can ultimately be subverted by a &amp;nbsp;clever developer. &lt;br /&gt;
&lt;h3&gt;
Considerations&lt;/h3&gt;
Though this entry has gotten more concrete than the good start provided by Spotify Labs&#39; entry, considerations remain.&lt;/div&gt;
&lt;h2&gt;
Homographic Attack&lt;/h2&gt;
In properly supporting display of fancy unicode characters, the system exposes users to &lt;a href=&quot;https://en.wikipedia.org/wiki/IDN_homograph_attack&quot; target=&quot;_blank&quot;&gt;homographic attack&lt;/a&gt;. Consider the following:&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
An Ohm --&amp;gt; &#39;Ω&#39; := \u2126&lt;/blockquote&gt;
&lt;div class=&quot;p1&quot;&gt;
Is the same character as another&lt;/div&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
An Omega --&amp;gt; &#39;Ω&#39; := \u03A9&lt;/blockquote&gt;
&lt;div class=&quot;p1&quot;&gt;
By overloading __str__() to return both the text and UID we can provide the programmer some visual cues:&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
[Ω bf59c742252007241ceddb9029d6baef] ?= [Ω a744dcc2e949c8bfc8bff101f9df38f9] --&amp;gt; False&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;p1&quot;&gt;
Note that the uname.UID handles are different. We should instruct view components to propagate such cues to their users. One way to do this, for user names, might be to show the user the visual form (unicode) but maintain a list of previously seen user names. When Omega shows up, having only seen Ohm, the UI might say, &quot;jOHN, [NEW] User Ω wants to connect with you. You&#39;ve not seen Ω before.&quot; This is not fool proof, but can be done cleverly.&amp;nbsp;&lt;/div&gt;
&lt;h2&gt;
Pickles&lt;/h2&gt;
&lt;div&gt;
&lt;div class=&quot;p1&quot;&gt;
Where you&#39;re able to build a strong type, I recommend baking pickling to popular formats into that object. You can also strongly associate custom externalization with common APIs (like Java&#39;s Externalizable interface). For instance, mindful that JSON has strong feelings about unicode characters, we&#39;d want to make sure that the UName class supported jsonpickle (and pickle for that matter) before we considered it done.&amp;nbsp;&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;import jsonpickle&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;m = UName(&#39;Ω&#39;)&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;m.text_name&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;u&#39;\u03a9&#39;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;jsonpickle.encode(m)&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&#39;{&quot;py/object&quot;: &quot;__main__.UName&quot;, &quot;text_name&quot;: &quot;&lt;a href=&quot;smb://u03a9&quot;&gt;&lt;span class=&quot;s1&quot;&gt;\\u03a9&lt;/span&gt;&lt;/a&gt;&quot;, &quot;user_number&quot;: &quot;0x7&quot;, &quot;UID&quot;: &quot;a744dcc2e949c8bfc8bff101f9df38f9&quot;}&#39;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div class=&quot;p1&quot;&gt;
&lt;/div&gt;
&lt;div class=&quot;p4&quot;&gt;
As you can see from the above example, failure to do so results in double escaping.&lt;/div&gt;
&lt;h2&gt;
UTF-8 and Source Files&lt;/h2&gt;
&lt;/div&gt;
&lt;div&gt;
Common guidance on forums (such as ActiveState and Stackoverflow) indicate that converting unicode to UTF-8 solves the challenges presented here. It may, but not always. Consider:&lt;/div&gt;
&lt;div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;str1 = some_unicode_str.encode(&#39;utf8&#39;)&lt;/span&gt;&lt;/blockquote&gt;
&lt;div class=&quot;p3&quot;&gt;
This only works in certain circumstances. For instance the following line can be stored UTF-8 (say, in a Python source file):&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;u2 = UName(&#39;ᴮᴵᴳᴮᴵᴿᴰ&#39;)&lt;/span&gt;&lt;/blockquote&gt;
&lt;div class=&quot;p3&quot;&gt;
Whereas if you try to store my aforementioned Omega and Ohm symbols:&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;h1 = UName(&#39;Ω&#39;) #u&#39;\u2126&#39;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&amp;nbsp;h2 = UName(&#39;Ω&#39;) #u&#39;\u03A9&#39;&lt;/span&gt;&lt;/blockquote&gt;
&lt;div class=&quot;p3&quot;&gt;
Both the above come back as \u03A9 when you put them back in unicode format. In essence, UTF-8 encoding the source file destroys data. To help solve this problem, preface your python source with:&lt;/div&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;# -*- coding: utf-8 -*-&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;from __future__ import unicode_literals&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;import unicodedata&amp;nbsp;&lt;/span&gt;&lt;/blockquote&gt;
In closing, Python 2.x sure does have trouble with unicode eh?&lt;br /&gt;
&lt;h3&gt;
Download&lt;/h3&gt;
Find demonstration material for this entry here: &lt;a href=&quot;https://code.google.com/p/code-poetic/source/browse/trunk/python/#python%2Fusername&quot; target=&quot;_blank&quot;&gt;username on Google code&lt;/a&gt;. Check this out using:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Courier New, Courier, monospace;&quot;&gt;svn checkout http://code-poetic.googlecode.com/svn/trunk/python/username username_demo
&lt;/span&gt;&lt;/div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/3166667415532995180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2013/06/pitfalls-of-unicode-usernames-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/3166667415532995180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/3166667415532995180'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2013/06/pitfalls-of-unicode-usernames-and.html' title='Pitfalls of Unicode Usernames and Solutions in Canonical Form and UID '/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-8573829480627293056</id><published>2011-05-06T17:28:00.000-04:00</published><updated>2011-05-06T17:28:40.541-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="bash"/><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="OS X"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh"/><title type='text'>Private GIT Repository Over SSH w/ SSH-KEY and git-shell</title><content type='html'>There&#39;s documentation out there on &lt;a href=&quot;http://www.kernel.org/pub/software/scm/git/docs/user-manual.html&quot;&gt;using git&lt;/a&gt;, on &lt;a href=&quot;http://blog.felipebalbi.com/2008/01/03/git-push-and-ssh-keys/&quot;&gt;git over SSH&lt;/a&gt;, and a wealth of information on using SSH keys for single-command purposes in &lt;a href=&quot;http://oreilly.com/catalog/sshtdg/chapter/ch08.html&quot;&gt;Chapter 8&lt;/a&gt; of O&#39;Reilly&#39;s SSH book. However, if you&#39;re trying to build a private git repository:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;On a Mac (OS X) server&lt;/li&gt;
&lt;li&gt;Want the user to maintain a normal shell (IE: don&#39;t want to use git-shell as the user&#39;s shell)&lt;/li&gt;
&lt;li&gt;Can&#39;t install &lt;a href=&quot;http://eagain.net/gitweb/?p=gitosis.git;a=summary&quot;&gt;gitosis &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;You&#39;re going to need to do things slightly different than are documented out there. ***if you read further I presume you have a good reason to forsake gitosis because all things considered it&#39;s a good solution: it&#39;s very easy to install, customize, or even extend as source code. Once set up it doesn&#39;t impose much in the way of dependencies, maintenance, or overhead.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Challenges&lt;/span&gt;&lt;br /&gt;
Apple seems to change command-line user addition commands on OS X between minor versions. Existing blog entries thus create silent failures when you follow their instructions. The reason is subtle: failing to create the correct user directory elements for a new user will result in clients attempting &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;git [fetch|pull] &lt;/span&gt;commands remotely to receive an error message:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;bash-3.2$ fatal: The remote end hung up unexpectedly
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
The following will be written to the OS X server system.log:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;sshd(28534) deny mach-per-user-lookup&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
I&#39;ve seen these errors result from the user lacking a home directory, from the git repository not having the correct group, and from other circumstances. Because no further error/debug information is given, this can be very frustrating to debug.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Solution&lt;/span&gt;&lt;br /&gt;
supporting ssh-based access to your private git repository through a single-use key requires work on both client and server. First server. git-shell allows you to support &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;cloning&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;push&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pull&lt;/span&gt;, and &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;fetch&lt;/span&gt; to and from a server, using an ssh-key, while still supporting normal user login on your sever for other purposes. Additionally, you need not open ports beyond what you&#39;ve already carved for SSH in your server.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Server Set-up&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Change directory to server-user&#39;s account:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; margin-left: 40px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt; [ -d ~/.ssh ] ||  mkdir ~/.ssh; chmod 700 ~/.ssh &amp;amp;&amp;amp; cd ~/.ssh/ &lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Create new SSH key (*Be sure to set parameters as your needs warrant)&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;ssh-keygen -b 2048 -f &quot;`whoami`@`hostname`-GIT-SHELL-`date &quot;+%Y-%m-%d&quot;`&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;li&gt;Add this new key as a &#39;single-use&#39; key to the authorized keys file:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
[ -e ./authorized_keys ] || touch authorized_keys &amp;amp;&amp;amp; chmod 600 authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;echo -n &quot;command=\&quot;/usr/bin/git-shell -c \\\&quot;\$SSH_ORIGINAL_COMMAND\\\&quot;\&quot;,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty &amp;gt;&amp;gt; authorized_keys&lt;/code&gt;&lt;/pre&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;cat ./`whoami`@`hostname`-GIT-SHELL-`date &quot;+%Y-%m-%d&quot;.pub` &amp;gt;&amp;gt; authorized_keys
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
In case you have trouble resolving the escaped characters in the above lines: the output should look something like this:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
bash-3.2$ more authorized_keys 
command=&quot;/usr/bin/git-shell -c \&quot;$SSH_ORIGINAL_COMMAND\&quot;&quot;,no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty ssh-rsa AAAAB3...KdeQ== bach@Sanguine.local
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Client Setup&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
Remember to use your&lt;i&gt; public&lt;/i&gt; key for your authorized keys file server-side, and then securely transport the&lt;i&gt; private&lt;/i&gt; key to your client users/machines. This represents a departure from what some administrators are used in other circumstances, and I&#39;ve seen keys compromised on more than one occasion as a result.&lt;br /&gt;
&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Validate the user&#39;s&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; ~/.ssh&lt;/span&gt; directory has permissions &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;700&lt;/span&gt; (IE: &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;drwx------&lt;/span&gt;)&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;If not, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;chmod 700 ~/.ssh&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Copy the private key created above into the user&#39;s &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;~/.ssh&lt;/span&gt; directory&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Verify the private key has permissions 600 (IE: &lt;/span&gt;-rw-------&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;)&lt;/span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;span style=&quot;font-family: inherit;&quot;&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;If not,&amp;nbsp;&lt;/span&gt; &lt;/span&gt;chmod 600 &lt;private file=&quot;&quot; key=&quot;&quot; path=&quot;&quot;&gt;&lt;/private&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Create a ~/.ssh/config file, if one doesn&#39;t exist:&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;[ -e ~/.ssh/config ] || touch ~/.ssh/config &amp;amp;&amp;amp; chmod 600 ~/.ssh/config&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;&amp;nbsp;Create a host configuration: (configure each host parameter to your needs)&lt;/li&gt;
&lt;ol&gt;&lt;li&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;host mySource
        HostName        myHost.org
        Port            22
        User            git
        Compression     yes
        Protocol        2
        IdentityFile    ~/.ssh/git@myHost.org-GIT-SHELL-2011-05-02&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;li&gt;Execute your clone, fetch, or pull commands, using the host specifier as the host name in the URL:&lt;/li&gt;
&lt;li&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;bash-3.2$ git clone ssh://mySource/repository_path/repository.git&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
The configuration file appears necessary for correct client operation. Specifying the username, host, and port on the command line to a git command such as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;bash-3.2$ git clone ssh://git@mySource:22/repository_path/repository.git&lt;/pre&gt;&lt;br /&gt;
does&lt;b&gt; not&lt;/b&gt; work, and produces the otherwise silent &quot;Fatal Error&quot; discussed earlier. The &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;git remote set-url&lt;/span&gt; or &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;git remote add&lt;/span&gt; commands can be used as well, their hostname element of the URL must only match the host specifier in the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;~/.ssh/config&lt;/span&gt; file (in our case mySource). For example, a user might execute the following command:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;git remote add repo ssh://mySource/repository_path/repository.git&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
so that they can issue commands as follows subsequently:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;git fetch repo master&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Considerations&lt;/span&gt;&lt;br /&gt;
The above solution allows you to allow git-shell access, through a single-use ssh-key to an otherwise normal system user. You can add separate ssh-keys for different client users, though each will adopt the UID of the user under which you install them for local server-side operations.&lt;br /&gt;
&lt;br /&gt;
If you need the capability to do directory-, repository-, or user-based access control, ssh-keys will not provide sufficient fine-grained resolution/control. In this case, you&#39;ll want to go directly to gitosis. &amp;nbsp;</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/8573829480627293056/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/05/private-git-repository-over-ssh-w-ssh.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/8573829480627293056'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/8573829480627293056'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/05/private-git-repository-over-ssh-w-ssh.html' title='Private GIT Repository Over SSH w/ SSH-KEY and git-shell'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-4834990709750034984</id><published>2011-04-15T17:06:00.001-04:00</published><updated>2011-05-06T15:57:41.783-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="mvn java gae xslt bash"/><title type='text'>Adding Maven Dependencies (for Google App-Engine)</title><content type='html'>Maven provides a decent system for managing builds involving gnarly dependencies. If you&#39;re starting from scratch with an app-engine project, just go &lt;a href=&quot;https://code.google.com/p/maven-gae-plugin/&quot;&gt;here&lt;/a&gt;.&amp;nbsp; However, newer developers and clients with which I work complain consistently that difficulty using maven increases substantially when an archetype is chosen but developers want to absorb another largish development or deployment framework into the same build. Prognosis for static analysis isn&#39;t good in these cases either.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Challenges&lt;/span&gt;&lt;br /&gt;
Though many SpringSource frameworks work well on Google&#39;s app-engine without change, I found blog postings on adding gae support to an existing Maven &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pom.xml&lt;/span&gt; lacking. I had to field emails when &quot;stuff didn&#39;t just work&quot;.&amp;nbsp; In particular, two nagging problems arouse: 1) which framework jars did builds depend on and 2) blog entries providing clean cut-and-paste solutions were all out of date.&lt;br /&gt;
&lt;br /&gt;
No sooner had I shown someone how to augment a maven POM than Google upgraded their app-engine. Sure enough, I passed them code and it didn&#39;t work. They had two versions of gae on their system but maven was building against the old version of the app-engine.&lt;br /&gt;
&lt;br /&gt;
Another individual fought an issue because they cut-and-paste a scheme from a well-formulated (but broken) blog entry on the topic. Specifically, maven&#39;s behavior, when groupId, artifactId tuples are repeated for multiple files, is to silently overwrite existing maven repository data with the newly supplied file. This means:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
mvn install:install-file -Dfile=${LIB}/appengine-tools-api.jar \
  -DgroupId=com.google \
  -DartifactId=appengine-tools \
  -Dversion=${VERS} \
  -Dpackaging=jar \
  -DgeneratePom=true
 
mvn install:install-file -Dfile=${LIB}/shared/appengine-local-runtime-shared.jar \
  -DgroupId=com.google \
  -DartifactId=appengine-tools \
  -Dversion=${VERS} \
  -Dpackaging=jar \
  -DgeneratePom=true
&lt;/code&gt;
&lt;/pre&gt;Does not do what you want it to. Instead of having two jars included in your build as part of the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;com.google.appengine-tools&lt;/span&gt; dependency, you get only the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;runtime-shared jar&lt;/span&gt;.&lt;br /&gt;
&lt;br /&gt;
Finally, those beset by the need to do things themselves often need to look up several XSLT syntactic constructs to get correct transforms capable of scraping a POM for all the dependencies that may need upgraded, removed, or otherwise tweaked. This is particularly the case because matching a POM dependency requires a multi-element match, governed in the case of my code by parameters passed to the sheet&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt; Solution&lt;/span&gt;&lt;br /&gt;
On the POM side of things, you want to look for scenarios where an old version of a dependency exists, such as below:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
 &amp;lt;groupid&amp;gt;com.google&amp;lt;/groupid&amp;gt;
 &amp;lt;artifactid&amp;gt;appengine-api&amp;lt;/artifactid&amp;gt;
 &amp;lt;version&amp;gt;1.4.2&amp;lt;/version&amp;gt;
 &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
Note the explicit version number. What&#39;s preferable, is managing your dependencies in a parametrized fashion. Comparing x.y.z-format version numbers is obnoxious. Chasing down each related dependency in a file to check version number is as well. Because of these (amongst other) reasons, a more maintainable idea involves parameterizing these as references and changing that single instance on upgrade.&lt;br /&gt;
&lt;br /&gt;
For instance:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
&amp;lt;dependency&amp;gt;
        &amp;lt;groupid&amp;gt;com.google&amp;lt;/groupid&amp;gt;
        &amp;lt;artifactid&amp;gt;appengine-api&amp;lt;/artifactid&amp;gt;
        &amp;lt;version&amp;gt;${google.app-engine.version}&amp;lt;/version&amp;gt;
        &amp;lt;scope&amp;gt;compile&amp;lt;/scope&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
Followed, of course, by:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
  &amp;lt;properties&amp;gt;
    &amp;lt;google.app-engine.version&amp;gt;1.4.3&amp;lt;/google.app-engine.version&amp;gt;
  &amp;lt;/properties&amp;gt;
&lt;/code&gt;
&lt;/pre&gt;&lt;br /&gt;
Since I&#39;m building kit to help security folk work with and inject secure snippets  into existing development projects, I decided to build a utility to help folk get things up and running on gae too (the average familiarity  with Maven in security isn&#39;t a high as developers&#39; typically)  by doing the above. The utility wrote to handle these situations does the following:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Parses an existing &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pom.xml&lt;/span&gt; looking for existing out-dated or half-working dependencies&lt;/li&gt;
&lt;li&gt;Iterates through specified dependencies, modifying the POM&lt;/li&gt;
&lt;ul&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&lt;li&gt;Adds unmentioned groupId, artifactId tuples&lt;/li&gt;
&lt;li&gt;Modifies existing groupId, artifactId tuples&lt;/li&gt;
&lt;li&gt;Comments out replaced collisions for later inspection&lt;/li&gt;
&lt;li&gt;Points out collisions for further inspection&lt;/li&gt;
&lt;li&gt;Controls version references using properties, which are also added/modified as necessary&lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;Installs listed dependency files in the user&#39;s local maven repository&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;Ideally, proper version parsing, comparison, and collision detection would be possible but that would take real time. The script supplied here can be used with any dependency, not just Google&#39;s app-engine. In fact, manage any dependency you expect to  change with regularity, if your project uses a different archetype  already. Prerequisites show how.&lt;br /&gt;
&lt;ol&gt;&lt;/ol&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Pre-Requisites&lt;/span&gt;&lt;br /&gt;
Pre-requisites are part of the problem here: a snag people run into when they&#39;re new to build configuration has always been that they&#39;re missing some tool they need to get things compiling. This was true of &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;gmake&lt;/span&gt; and &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;autoconf&lt;/span&gt; and it&#39;s true of maven builds nearly as often in my experience. So, when I wrote this utility, I purposefully used only &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;bash&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;mvn&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;xsltproc&lt;/span&gt;, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;javac&lt;/span&gt;, and &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;sed&lt;/span&gt;. All of these utilities are available on Linux and OS X out of the box.&lt;br /&gt;
&lt;br /&gt;
When gearing up to use inject-gae-dependency, simply:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Use an existing &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;pom.xml&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Modify the lists the dependencies (by editing the script&#39;s enumerations)&lt;/li&gt;
&lt;li&gt;Download &lt;a href=&quot;https://code.google.com/appengine/downloads.html&quot;&gt;Google&#39;s app-engine &lt;/a&gt;or &lt;whatever dependency=&quot;&quot; other=&quot;&quot;&gt; to be managed secondarily&lt;/whatever&gt;&lt;/li&gt;
&lt;li&gt;&lt;whatever dependency=&quot;&quot; other=&quot;&quot;&gt;Optionally salt-and-pepper to taste &lt;/whatever&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;span style=&quot;font-size: large;&quot;&gt;Running &lt;/span&gt;&lt;br /&gt;
Using the tool is straightforward. Usage works as follows:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;
./bin/install-google-appengine-dependencies.sh &amp;lt;path to Google app-engine Java SDK&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Status is printed to STDOUT and maven logging occurs to &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;./mvn.log&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Download&lt;/span&gt;&lt;br /&gt;
Download the current code base from its &lt;a href=&quot;http://code.google.com/p/code-poetic/source/browse/#svn%2Ftrunk%2Fmvn-inject-gae&quot;&gt;Google Code Repository&lt;/a&gt;&lt;a href=&quot;https://code.google.com/p/code-poetic/source/checkout&quot;&gt;&amp;nbsp;&lt;/a&gt; or use SVN to do a checkout using URL:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;svn checkout &lt;b&gt;http&lt;/b&gt;://code-poetic.googlecode.com/svn/trunk/mvn-inject-gae mvn-inject-gae read-only&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/4834990709750034984/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/04/adding-maven-dependencies-for-google.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4834990709750034984'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4834990709750034984'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/04/adding-maven-dependencies-for-google.html' title='Adding Maven Dependencies (for Google App-Engine)'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-4286180005139772678</id><published>2011-03-13T15:21:00.000-04:00</published><updated>2011-03-13T15:21:26.479-04:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="svn"/><title type='text'>Merging Branches with SVN</title><content type='html'>When I read things like &quot;the world&#39;s most popular open source version control system&quot; and (paraphrased) &quot;designed to fix to fix CVS&#39;s problems&quot; I don&#39;t think &quot;took important steps backwards&quot; but I find aspects of SVN have done just that. In particular, merging tags/branches becomes a challenge when the merge source has multiple revision anchors. &lt;br /&gt;
&lt;br /&gt;
As expected, one can accomplish simple merges quickly using explanation of commands available in the &lt;a href=&quot;http://svnbook.red-bean.com/nightly/en/svn.branchmerge.basicmerging.html&quot;&gt;SVN Red-bean Book&lt;/a&gt;. However, if you&#39;re working with multiple committors, or even one or two folk who liberally tag/branch, you&#39;ll run into unexpected results quickly. The problem stems from the fact that SVN&#39;s merge command does not automatically resolve the previous branch points for merge on a file-by-file basis. As such, when you give a &lt;br /&gt;
&lt;blockquote style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;svn merge -r&amp;lt;source&amp;gt;:&amp;lt;target&amp;gt; ...&amp;nbsp;&lt;/blockquote&gt;command, you may not be giving SVN enough information to do the correct thing. This is particularly the case if you or your fellow committors do things like merging in bulk from the project&#39;s root directory. &lt;br /&gt;
&lt;br /&gt;
Consider an example:&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;(*) &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - r1 User A
&amp;nbsp;|
(*)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; - r2 User A
&amp;nbsp;|&amp;nbsp; \
&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp; \ 
&amp;nbsp;|&amp;nbsp; &amp;nbsp;&amp;nbsp; (*)&amp;nbsp; - r3 User B
(*) &amp;nbsp;&amp;nbsp;  | &amp;nbsp; - r4 User C
&amp;nbsp;|&amp;nbsp;&amp;nbsp; \&amp;nbsp; |
&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (*)&amp;nbsp; - r5 User A 
&amp;nbsp;| &amp;nbsp;&amp;nbsp;&amp;nbsp; /
&amp;nbsp;| &amp;nbsp; /
&amp;nbsp;(?)
&lt;/pre&gt;&lt;br /&gt;
In the case visualized above, we have two users committing code to two branches. Remember, SVN uses a single global (to the repository, not the project) incrementally increasing value to represent revision. In the case represented, A user (A) commits twice (r1 and r2) and then a second user (B) branches (r3).&lt;br /&gt;
&lt;br /&gt;
Subsequent to that branch, A continues developing while C commits to what we&#39;ll refer to as the &#39;trunk&#39;. Then, maybe because of a bug fix or lunch discussion, A commits to the branch. What we have, in commit #5, is a situation in which the files/changes (r4) were drawn from the trunk before modifications were made.&lt;br /&gt;
&lt;br /&gt;
At question: how does A merge trunk and branch with 1) least amount of pain and 2) save the highest resolution of change meta-data (and thus make subsequent situations like the r4--&amp;gt;r5 merge less painful)?&lt;br /&gt;
&lt;br /&gt;
While SVN supports multiple approaches to branching/merging, I&#39;ve found the solution to this problem that optimizes #1 and #2 from above involves a crucial extra step. Consider the following method:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Make sure your own branch is up to date &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;Determine the revision from which source material forked from target&lt;/li&gt;
&lt;li&gt;Construct a merge command based on the computed source revision&lt;br /&gt;
&lt;/li&gt;
&lt;/ol&gt;&lt;br /&gt;
The step people skip is #2.&amp;nbsp; In our example above, merging from the branch represented by commits r3-4 require you to specify r3 as the source of merge material while merging files changed by commit r5 from the branch to the trunk requires specifying r5 to preserve the later merge meta-data (*1). To make this more concrete, imagine that A has a checkout of the trunk, currently at r1 that (s)he intends to update to r5 to reflect the branch&#39;s changes. Let&#39;s follow the process.&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Conducting an update will pull down files from r4, changed in the trunk &lt;/li&gt;
&lt;li&gt;Iterating through remaining files in the source tree, two sets of source anchors will be reported: Set X (r2) &amp;amp; Set Y (r5)&lt;/li&gt;
&lt;li&gt;Conducting the merge requires issuing two merge commands, each on its respective set from the previous bullet:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;svn merge -r2:HEAD &amp;lt;&#39;branch&#39; URL&amp;gt; &amp;lt;&#39;trunk&#39; path to Set X&amp;gt;
svn merge -r3:HEAD &amp;lt;&#39;branch&#39; URL&amp;gt; &amp;lt;&#39;trunk&#39; path to Set Y&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;If committors confine Set X to a single sub-directory, then the commands indicated in the last list item can be issued as they&#39;re parametrized: as single &amp;lt;&#39;branch&#39; src&amp;gt; &amp;lt;&#39;trunk&#39; target&amp;gt; tuples. However, if changed files spread across sub-directories, developers conducting merges will have to issue multiple commands, each specifying specific &#39;branch&#39; source URLs and target paths. Yes, this frustrates everybody involved. The up-shot? as the person conducting the merge, you move slowly and methodically through a merge, understanding changes to each file / directory explicitly (especially where changes have fractured themselves across directories). This has also caused me and my development lead to merge between branches more often than on previous projects--causing us to remain more in sync with each other.&lt;br /&gt;
&lt;br /&gt;
I provide two tools to make the process easier. First, a simple script to accomplish merge step #2: determine the revision at which the source material forked:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 98%;&quot;&gt;&lt;code&gt;
&amp;nbsp;#!/bin/sh


svn log --stop-on-copy | grep &#39;^r&#39; | tail -n 1 | cut -f 1 -d &#39; &#39; | cut -f 2- -d &#39;r&#39;
&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;
Name this file something like &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;SVN_determine_revision_anchor&lt;/span&gt; and pass it the file / directory of which you desire to know the last branch point.&lt;br /&gt;
If you don&#39;t like calling the merge command manually (long URL paths can make this a pain), use something like the following, which I named &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;merge.sh&lt;/span&gt;:&lt;br /&gt;
&lt;br /&gt;
&lt;pre id=&quot;line668&quot;&gt;&lt;code&gt;&lt;/code&gt;&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 98%;&quot;&gt;&lt;code&gt; 
&lt;/code&gt;#!/bin/sh


URL_PREFACE=&quot;https://svn.myorg.org/svn/repos/dev/myapp&quot;

URL_SUFFIX=&quot;current&quot;


TO_MERGE=&quot;${URL_PREFACE}/$1/${URL_SUFFIX}&quot;

TARGET=&quot;${URL_PREFACE}/$2/${URL_SUFFIX}&quot;

SUPPLYING_BRANCH_REV=&quot;`svn log --stop-on-copy ${TO_MERGE} | grep 
&quot;r[0-9]&quot; | tail -n 1 | cut -f 1 -d &#39;|&#39; | cut -f 2 -d &#39;r&#39; | sed &#39;s/ //&#39;`&quot;

TARGET_BRANCH_REV=&quot;`svn info ${TARGET} | grep Revision | cut -f 2- -d &#39;:&#39; |sed &#39;s/^[ ]*//&#39;`&quot;


echo &quot;Merging ${TO_MERGE}@${SUPPLYING_BRANCH_REV} with ${TARGET}@${TARGET_BRANCH_REV}&quot;

svn merge -r${SUPPLYING_BRANCH_REV}:${TARGET_BRANCH_REV} ${TO_MERGE}&lt;/pre&gt;&lt;/pre&gt;&lt;br /&gt;
Call this script with two parameters: first the source of the merge information and the second the target tag. You&#39;ll note, in essence, that this second script incapsulates the functionality of the first.&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;Summary&lt;/span&gt;&lt;br /&gt;
When conducting merges with SVN, please consider the source revision and forks carefully (on a file-by-file basis if necessary). While other mechanisms may work to merge things without this step, combining multiple forks later will likely create unexpected conflicts and difficulty.&lt;br /&gt;
&lt;br /&gt;
(*1) To me, this represents defeat on the part of the version control system. What purpose should a version control system serve if not to keep track of this very branch information for use in resolving merge scenarios?</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/4286180005139772678/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/03/merging-branches-with-svn.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4286180005139772678'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4286180005139772678'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/03/merging-branches-with-svn.html' title='Merging Branches with SVN'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-1409838690232431925</id><published>2011-03-01T06:20:00.000-05:00</published><updated>2011-03-01T06:20:58.966-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><title type='text'>Ensuring Super Class Initialization</title><content type='html'>Seemingly a very simple concept: how do you guarantee that when someone sub-classes your Python class that your constructor ( __init__() ) runs? The straightforward method contains a trap:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;&amp;nbsp; &lt;/code&gt;

class Base(object):&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp; def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;foo&quot;

class Sub(Base):
&amp;nbsp;&amp;nbsp; def __init__(self):&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;bar&quot;&lt;/pre&gt;When the Sub class&#39; initialize method is executed it squashes the Base class&#39;. What we want is for both to be called:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;&lt;code&gt;&amp;nbsp;&amp;nbsp;&lt;/code&gt;
class Sub(Base):
&amp;nbsp;&amp;nbsp; def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Base.__init__(self)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;bar&quot;&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Unfortunately, we can&#39;t &lt;i&gt;make&lt;/i&gt; the person extending our class call the super class. A poor man&#39;s factory pattern&amp;nbsp; alleviates the possibility of subtype implementers forgetting initialization. Consider:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;class AbstractClass(object):
&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;&#39;&#39;Abstract base class template, implementing factory pattern through 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; use of the __new__() initializer. Factory method supports trivial, 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; argumented, &amp;amp; keyword argument constructors of arbitrary length.&#39;&#39;&#39;

&amp;nbsp;&amp;nbsp; __slots__ = [&quot;baseProperty&quot;]
&amp;nbsp;&amp;nbsp; &#39;&#39;&#39;Slots define [template] abstract class attributes. No instance
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; __dict__ will be present unless subclasses create it through 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; implicit attribute definition in __init__() &#39;&#39;&#39;

&amp;nbsp;&amp;nbsp; def __new__(cls, *args, **kwargs):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;&#39;&#39;Factory method for base/subtype creation. Simply creates an
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (new-style class) object instance and sets a base property. &#39;&#39;&#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance = object.__new__(cls)

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance.baseProperty = &quot;Thingee&quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return instance&lt;/pre&gt;&lt;br /&gt;
This base class can be extended trivially, using only three (3) lines of code san-commment, as follows:&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;class Sub(AbstractClass):
&amp;nbsp;&amp;nbsp; &#39;&#39;&#39;Subtype template implements AbstractClass base type and adds
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; its own &#39;foo&#39; attribute. Note (though poor style, that __slots__
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; and __dict__ style attributes may be mixed.&#39;&#39;&#39;

&amp;nbsp;&amp;nbsp; def __init__(self):
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &#39;&#39;&#39;Subtype initializer. Sets &#39;foo&#39; attribute. &#39;&#39;&#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; self.foo = &quot;bar&quot;

&lt;/pre&gt;&lt;br /&gt;
Note that though we didn&#39;t call the super-class&#39; constructor, the baseProperty will be initialized:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) 
[GCC 4.2.1 (Apple Inc. build 5646)] on darwin
Type &quot;help&quot;, &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information.
&amp;gt;&amp;gt;&amp;gt; from TestFactory import *
&amp;gt;&amp;gt;&amp;gt; s = Sub()
&amp;gt;&amp;gt;&amp;gt; s.foo
&#39;bar&#39;
&amp;gt;&amp;gt;&amp;gt; s.baseProperty
&#39;Thingee&#39;
&amp;gt;&amp;gt;&amp;gt; 
&lt;/pre&gt;&lt;br /&gt;
As its comment indicates, the base class AbstractClass need not use slots, it could just as easily &#39;implicitly&#39; define attributes by setting them in its new() initializer. For instance:&lt;br /&gt;
&lt;br /&gt;
&lt;pre style=&quot;background-color: #eeeeee; border: 1px dashed rgb(153, 153, 153); color: black; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; font-size: 12px; line-height: 14px; overflow: auto; padding: 5px; width: 100%;&quot;&gt;instance.otherBaseProperty = &quot;Thingee2&quot;&lt;/pre&gt;&lt;br /&gt;
would work fine. Also note that the base class&#39; initializer supports trivial (no-arg) initializers in its subtypes, as well as variable-length arugmented and keyword argument initializers. I recommend always using this form as it doesn&#39;t impose syntax in the simplest (trivial constructor) case but allows for the more complex functionality without imposing maintenance.</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/1409838690232431925/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/03/ensuring-super-class-initialization.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/1409838690232431925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/1409838690232431925'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/03/ensuring-super-class-initialization.html' title='Ensuring Super Class Initialization'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-4943792914681631416</id><published>2011-01-31T10:53:00.000-05:00</published><updated>2011-01-31T10:53:01.861-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GoF Patterns"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><category scheme="http://www.blogger.com/atom/ns#" term="Visitor"/><title type='text'>Pythonic Extrinsic Visitor</title><content type='html'>Regardless of the language chosen to express it, the Visitor pattern remains one of the more basic behavioral patterns described by the &quot;Gang of Four&#39;s&quot; &lt;a href=&quot;http://www.amazon.com/Design-Patterns-Elements-Reusable-Object-Oriented/dp/0201633612&quot;&gt;Design Patterns Book&lt;/a&gt;. Herein I describe a Pythonic Visitor implementation that overcomes common language-based limitations of C, C++, Java, and C# Visitors and present a usable implementation that goes well beyond available sample/snippets. In particular, the implementation provided addresses two commonly omitted but crucial features &quot;left as an exercise to the reader&quot;: correct method resolution/dispatch of types within an inheritance hierarchy and caching method resolution results for performance&#39;s sake. More on those and other features later.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Challenges&lt;/span&gt; &lt;br /&gt;
Implementing a visitor pattern in practice poses challenges:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Applying visitors to existing type hierarchies demands &lt;b&gt;&lt;i&gt;refactoring&lt;/i&gt;&lt;/b&gt; potentially large sets of visitors&#39;&amp;nbsp; visited types to include accept() method&lt;/li&gt;
&lt;li&gt;Refactoring described by the previous bullet, in-effect&lt;b&gt;&lt;i&gt;, couples&lt;/i&gt;&lt;/b&gt; the visitor and visited hierarchy through the visitor&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; accept()&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;/ &lt;/span&gt;visit()&lt;/span&gt; interface. Additions to the visited type tree hierarchy thus commonly demand commensurate changes to the visitor API and potentially its implementation&lt;/li&gt;
&lt;li&gt;Behavior of language-specific polymorphic dispatch (in this case double-dispatch) often &lt;i&gt;&lt;b&gt;elude&lt;/b&gt;&lt;/i&gt; both junior and senior &lt;i&gt;&lt;b&gt;programmers&lt;/b&gt;&lt;/i&gt; alike.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;Visitors take different forms, actually. Spurred by problems resulting from bullets #1 and #2 above, some design and implement &lt;i&gt;&lt;b&gt;Extrinsic Visitors. &lt;/b&gt;&lt;/i&gt;Informally, an extrinsic visitor makes decisions about how to &#39;visit&#39; a visitable object without relying on double-dispatch. Put another way: the visitor need not call a method on the target visitable object itself to &#39;reclaim&#39; its specific type before selecting the applicable &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit()&lt;/span&gt; method.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Challenges to Extrinsic Visitation&lt;/span&gt; &lt;br /&gt;
When Developers choose languages such as Java or C# to implement an extrinsic visitor they must rely on reflection or introspection (respectively) in order to reclaim the visitable object&#39;s specific type without invoking a method of that object&#39;s instance. During code review, I&#39;ve observed sloppy implementations revert to a &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;switch/case&lt;/span&gt; statement failure mode--again introducing brittle dependence between the visitor implementation and the visited type hierarchy (#2 above). Bullet #3 (above) remains a problem, but challenges represented by bullets one and two are replaced with the following:&lt;br /&gt;
&amp;nbsp; &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Sandbox security policy (Applets, etc.) may prevent use of reflection/introspection in some environments&lt;/li&gt;
&lt;li&gt;Reflection/introspection can cause a costly speed hit depending on the language, and VM implementation (not nearly as much a problem with modern Java 1.5+)&lt;/li&gt;
&lt;li&gt;Depending on visitor design, visitor API may remain rigidly tied to visited hierarchy demanding an explicit concrete method for each visitable type (as in #2 above)&lt;/li&gt;
&lt;/ol&gt;Search for &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;Extrinsic Visitor in Python&lt;/span&gt; and Google will return plenty of results. Often, implementations provided express the problems described by the bullets above or leave their solutions as exercises to the reader. Unfortunately, many programmers I encounter simply do not possess the familiarity with Python&#39;s object model or method-resolution mechanics (mro) to quickly accomplish the goal. Having fought my own lack of Python knowledge (hard to un-seat understanding of Java), I can sympathize. &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Pythonic Extrinsic Visitor: Design&lt;/span&gt;&lt;br /&gt;
The design of my Pythonic visitor bear the following properties:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Extrinsic&lt;/li&gt;
&lt;ul&gt;&lt;li&gt;The visitor and its sub-classes require no invocation of visitable type methods (double-dispatch) in order to reclaim specific target type&lt;/li&gt;
&lt;li&gt;The visitable type requires no refactoring (IE: no &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;accept()&lt;/span&gt; method necessary) &lt;/li&gt;
&lt;/ul&gt;&lt;li&gt;The visitor employs Python mro for &quot;C++-style&quot; best-match &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit()&lt;/span&gt; method dispatch&lt;/li&gt;
&lt;li&gt;The first method resolution result is cached to avoid hit on subsequent all calls to the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit()&lt;/span&gt; method for a particular type&lt;/li&gt;
&lt;li&gt;Support for NoneType (IE: &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visitor.visit(None)&lt;/span&gt;) &lt;/li&gt;
&lt;/ul&gt;Sections below describe each design element above in turn.&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Extrinsic&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
At its heart, the visitor class has only two public methods:&lt;br /&gt;
&lt;ul&gt;&lt;li style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def visit(self, visitable)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def defaultVisitor(self, visitable)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;Along with the class&#39; constructor, these make up the visitor API. As with any extrinsic visitor, developers enjoy the follow the following simplified calling convention:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;fruit = grocerer.pick(&quot;Banana&quot;)&amp;nbsp;&lt;/blockquote&gt;&lt;blockquote style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visitor = MyVisitor()&lt;/blockquote&gt;&lt;blockquote style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visitor.visit(fruit) &lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;&lt;i&gt;Snippet - A - Simplest Visitor Test Driver&lt;/i&gt;&lt;/span&gt; &lt;/blockquote&gt;&lt;br /&gt;
Presume here that&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt; grocer.pick()&lt;/span&gt; represents a factory method capable of returning a variety of fruit sub-types based on their string name. The &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;defaultVisitor()&lt;/span&gt; method provides developers the ability to specify a &#39;catch-all&#39; visitation function, capable of handling any typed passed to &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit() &lt;/span&gt;as its parameter. Developers simply override the&amp;nbsp; &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;defaultVisitor()&lt;/span&gt;  method in their subclass. Thus, the following represents a &quot;Hello World&quot; attempt at extending the visitor provided:&lt;br /&gt;
&lt;blockquote&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;class MyVisitor(visitor):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def defaultVisitor(self, visitable):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &#39;%s&#39; %(visitable) &lt;/div&gt;&lt;/blockquote&gt;The visitor base class provides a defacto implementation for the &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;defaultVisitor()&lt;/span&gt; method so Developers need not override. The defacto implementation throws &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;TypeError&lt;/span&gt; when the implementation&#39;s method resolution can not resolve a specific handler match.&lt;br /&gt;
&lt;br /&gt;
The key feature of this visitor implementation is that those extending only need to implement those visit (handler) methods they desire explicitly. Developers do this by adding methods to their subclass in the form:&lt;br /&gt;
&lt;blockquote&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def visit&lt;typetohandle&gt;(self, visitable): pass&lt;/typetohandle&gt;&lt;/span&gt;&lt;/blockquote&gt;So,&amp;nbsp; from the example above, a Developer might choose to do the following:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;class MyVisitor(visitor):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def visitBanana(self, visitable):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &#39;%s&#39; %(visitable)&amp;nbsp;&lt;/div&gt;&lt;br /&gt;
Because this visitor employs a &#39;best match&#39; dispatch, the following would have the same effect in our test driver captioned &quot;Snippet A&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;class MyVisitor(visitor):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def visitFruit(self, visitable):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &#39;%s&#39; %(visitable) &lt;/div&gt;&lt;br /&gt;
More on how the implementation accomplishes this in the next section. &lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Best Match&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
The best match property is the key to overcoming brittle coupling and tedious visitor implementation update. As designed, the visitor described herein employs a &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;lookupVisitorMethod()&lt;/span&gt; method to accomplish this. Roughly, the algorithm employed follows:&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def visit(self, visitable):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;    clazz = visitable.__class__            &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;    for _type in clazz.mro():&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; handler =&amp;nbsp; &#39;visit%s&#39; %(_type.__name__&lt;/span&gt;)&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;            visit_method = getattr(self, handler, None)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;            if not (visit_method is None):&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;               return visit_method(visitable)&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;     return visit_method(visitable)&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Roughly, this algorithm iterates through the visitable objects&#39; class hierarchy and looks for a method in the visitor object named &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit&lt;typename&gt;()&lt;/typename&gt;&lt;/span&gt;. Remember, &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;mro()&lt;/span&gt; is an ordered list (Specific to most generic). &lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;Caching&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
Caching method resolution proved the most difficult task in creating the presented implementation. The critical decision: what scope in which to place the method resolution cache. Placed at a high level (class object, module scope, or similar) the performance will increase but the caching scheme need be more advanced to handle circumstances in which multiple visitor sub-classes visit overlapping visitable type trees. Seeking to avoid this complexity, I chose to place the method cache in the visitor object instance.&lt;br /&gt;
&lt;br /&gt;
&lt;pre&gt;&lt;blockquote&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def visit(self, visitable):
&amp;nbsp;&amp;nbsp;&amp;nbsp; clazz = visitable.__class__ &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 
&amp;nbsp; &amp;nbsp; try:
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visit_method = self._method_map_cache[clazz]
&amp;nbsp; &amp;nbsp; except KeyError:
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visit_method = self._lookupMethod(visitable, clazz)

&amp;nbsp; &amp;nbsp; return visit_method(visitable)
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;def _lookupMethod(self, target, clazz):&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; for _type in clazz.mro():&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; handler =&amp;nbsp; &#39;visit%s&#39; %(_type.__name__)&amp;nbsp;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visit_method = getattr(self, handler, None)&lt;/div&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if not (visit_method is None):&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; self._method_map_cache[clazz] = visit_method&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; return visit_method&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; self._method_map_cache[clazz] = self.defaultVisitor&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; return self.defaultVisitor&lt;/span&gt;&lt;/blockquote&gt;&lt;/pre&gt;This implementation&#39;s scheme performs sufficiently well for even tight-loop operations (such as AST, DOM, and other large tree visitations) but avoids visitor/visited type tree collision. For more information, see the test suite. While not perfect, the implementation strategy above avoids opaque error messages and some more odd stack-frame insertions that complicate debugging (as experienced with other visitor schemes).&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&lt;b&gt;NoneType&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;
The dispatching schemes as adopted by this algorithm (and other samples available online)&amp;nbsp;&lt;i&gt;&lt;b&gt; &lt;/b&gt;&lt;/i&gt;fall prey to a simple failure mode: a caller passing a None rather than a valid instance (IE: &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;v.visit(None)&lt;/span&gt;). Sample code available online almost always omits support for this corner case, despite how common it can be in tree visitations and collection iteration.&amp;nbsp; This implementation solves the problem of handling None types with a special case prefacing the lookup method:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;class dummy_lookup(object):&lt;br /&gt;
&amp;nbsp;&amp;nbsp; def mro():&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return [type(None)]&lt;br /&gt;
&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;br /&gt;
def _lookupMethod(self, target, clazz):&lt;br /&gt;
&amp;nbsp;&amp;nbsp; if clazz is None:&lt;br /&gt;
&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; clazz = dummy_lookup()&lt;br /&gt;
&lt;br /&gt;
&amp;nbsp;&amp;nbsp; ...&lt;/blockquote&gt;&lt;br /&gt;
The effect of the dummy lookup class is to serve the mro() iterator that follows in the lookup method.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Configurable Visit method&lt;/b&gt;&lt;br /&gt;
The implementation provided provides an addl. feature to avoid name-based collisions for existing visitation logic that an adopter may want to move to the visitor pattern. The implementation&#39;s constructor takes a &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;visit_method=&lt;/span&gt;&amp;nbsp; keyword parameter that defines what prefix visitor subclass definitions will use to define specific visit methods. Use this feature when defining your visitor as follows:&lt;br /&gt;
&lt;b&gt; &lt;/b&gt;&lt;br /&gt;
&lt;blockquote&gt;&lt;b&gt; &lt;/b&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;class myVisitor(visitor):&lt;/span&gt;&lt;br /&gt;
&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; def __init__(self, *args, **kwargs):&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; kwargs[&#39;visit_method&#39;] = &#39;handle&#39;&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; visitor.__init__(*args, **kwargs)&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; def handle(self, visitable): return self.visit(visitable)&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; def handleType1(self, visitable): pass&lt;/div&gt;&lt;div style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;&amp;nbsp;&amp;nbsp; def handleType2(Self, visitable): pass&lt;/div&gt;&lt;/blockquote&gt;&lt;br /&gt;
This mechanism allows developers to hide the visitor pattern&#39;s name from those calling it. Electing to call the visit method by another name (PrettyPrint, handle, &lt;whatever&gt;) can be more intuitive. &lt;/whatever&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Download&lt;/span&gt;&lt;br /&gt;
Download the current code base from its &lt;a href=&quot;http://code.google.com/p/code-poetic/source/browse/#svn%2Ftrunk%2Fpython%2Flib&quot;&gt;Google Code Repository&lt;/a&gt;&amp;nbsp; or use SVN to do a checkout using URL:&lt;br /&gt;
&lt;br /&gt;
&lt;tt id=&quot;checkoutcmd&quot;&gt;svn checkout &lt;strong&gt;&lt;em&gt;http&lt;/em&gt;&lt;/strong&gt;://code-poetic.googlecode.com/svn/trunk/python/lib code-poetic-read-only&lt;/tt&gt;  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Prerequisites&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Python 2.x&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Notes&lt;/span&gt;&lt;br /&gt;
N/A. &lt;br /&gt;
&lt;i&gt;&lt;b&gt; &lt;/b&gt;&lt;/i&gt;</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/4943792914681631416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/01/pythonic-extrinsic-visitor.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4943792914681631416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/4943792914681631416'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/01/pythonic-extrinsic-visitor.html' title='Pythonic Extrinsic Visitor'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1546074471231747404.post-2076674312181867266</id><published>2011-01-20T23:49:00.000-05:00</published><updated>2011-01-20T23:49:34.457-05:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="C"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="OS X"/><category scheme="http://www.blogger.com/atom/ns#" term="Password Cracking"/><title type='text'>Creating Dictionaries &amp; Cracking Passwords on Mac OS X</title><content type='html'>If you&#39;ve forgotten your password on a Mac OS X machine, for either a disk image (sparse bundle, sparse image, etc.) or keychain, you know a feeling of hopelessness. If you&#39;re going to attempt to break into your own encrypted store, you have two difficulties:&lt;br /&gt;
&lt;ol&gt;&lt;li&gt;Generating a &lt;i&gt;minimal&lt;/i&gt; password dictionary&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Adapting&lt;/i&gt; a dictionary password test driver to OS X password-checking&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;&lt;span style=&quot;font-size: x-large;&quot;&gt;Test Drivers: Simple Examples Rarely Suffice&amp;nbsp;&lt;/span&gt; &lt;br /&gt;
When, frantically, I realized that I was unable to manually guess my image password back in 2008, I wasn&#39;t satisfied with what image-cracking utilities Google search returned. The simplified-for-demonstration-purposes test drivers provided in forums didn&#39;t handle the kinds of characters my passwords contained (redirects &#39;&amp;lt;&#39;, &#39;&amp;gt;&#39; and pipes &#39;|&#39;). &lt;br /&gt;
&lt;br /&gt;
I created two Bash scripts to drive unlock attempts from a created password dictionary:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;unlock_image (using &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;hdiutil attach&lt;/span&gt;)&lt;/li&gt;
&lt;li&gt;unlock_keychain (using &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;security unlock-keychain&lt;/span&gt;)&lt;/li&gt;
&lt;/ul&gt;Each conforms to shell scripting norms, returning &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;0&lt;/span&gt; on success (and printing the successful password), returning &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;1&lt;/span&gt; on failure, and returning &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;2 &lt;/span&gt;on error. &amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Optimizing &lt;i&gt;Minimal &lt;/i&gt;Dictionary Creation&lt;/span&gt;&lt;br /&gt;
Worse, because my passwords typically use a large variety of character sets, I feared coming up with a minimal dictionary would prove too difficult. Back-of-the-napkin estimations on 1) cost per password attempt (time) and 2) dictionary size indicated success would demand some tricks. &lt;br /&gt;
&lt;br /&gt;
Generating an inclusive dictionary proved impossible quickly. The image I was trying to crack had a twelve (12) to fourteen (14) character password, containing (what I believe to be) some combination of fourteen (14) unique characters. This produced, without compression or clever storage solutions, a multi-hundred gigabyte dictionary that would require 48 years to exhaustively attempt using my four-machine set-up. &lt;br /&gt;
&lt;br /&gt;
Robust rule-based password dictionary creation utilities exist but I found these projects a false-optimization to cracking one&#39;s &lt;b&gt;own&lt;/b&gt; password. You &lt;b&gt;know&lt;/b&gt; some aspects of your passwords character set and structure but I found that including too many rules into dictionary creation (creating few-minute or few-hour) attempts always came up empty--my dictionaries were too restrictive.&lt;br /&gt;
&lt;br /&gt;
As a result, I created a simple dictionary creation utility that allowed its user to specify a few password qualities:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;User-specified password dictionary character set&lt;/li&gt;
&lt;li&gt;Minimum password length&lt;/li&gt;
&lt;li&gt;Maximum password length&lt;/li&gt;
&lt;li&gt;Are password characters unique (or may they be repeated?)&lt;/li&gt;
&lt;li&gt;Fixed password preface&lt;/li&gt;
&lt;li&gt;Fixed password suffix&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
With this utility I created dictionaries inclusive-enough to find the passwords I&#39;d forgotten while (I believe) striking a decent balance between complexity of dictionary specification and resulting password dictionary size.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Download&lt;/span&gt;&lt;br /&gt;
To download, build, and use the utilities, please go to its Google Code Repository:&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://code.google.com/p/code-poetic/source/browse/trunk/dmg_password_crack/&quot;&gt;Google Code - dmg_password_crack&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;Prerequisites&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Mac OS X&lt;/li&gt;
&lt;li&gt;Maven2&lt;/li&gt;
&lt;/ul&gt;&lt;span style=&quot;font-size: x-large;&quot;&gt;Notes&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;Implementation requires only modest memory, requiring 384K of RAM at steady-state under default settings&lt;/li&gt;
&lt;li&gt;Implementation appears I/O bound, not bound by syscalls (&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;malloc/free&lt;/span&gt;), memory, or computation&lt;/li&gt;
&lt;li&gt;Password dictionary creation code does not guard explicitly against bad or malicious input. Even careless values (such as negatives) create unexpected results.&lt;/li&gt;
&lt;li&gt;Recursion and memory allocation, as implemented, lessen LoC but will not perform as well as a well set-up fixed array and iteration&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;hdiutil attach&lt;/span&gt; remains the &#39;long pole&#39; (critical path, most onerous step, etc.) in utilities&lt;/li&gt;
&lt;li&gt;Code compiles error-/warning-free on Apple&#39;s &lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;gcc 4.2.1, i686&lt;/span&gt; and performs well on Valgrind leak check, but fails to conform to OOA/D and style conventions&lt;/li&gt;
&lt;li&gt;Code passes four included integration-level tests on OS=&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;OS X 10.6.6&lt;/span&gt; arch=&lt;span style=&quot;font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;&quot;&gt;x86_64&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;</content><link rel='replies' type='application/atom+xml' href='http://codepoetic.blogspot.com/feeds/2076674312181867266/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://codepoetic.blogspot.com/2011/01/creating-dictionaries-cracking.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/2076674312181867266'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1546074471231747404/posts/default/2076674312181867266'/><link rel='alternate' type='text/html' href='http://codepoetic.blogspot.com/2011/01/creating-dictionaries-cracking.html' title='Creating Dictionaries &amp; Cracking Passwords on Mac OS X'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/06101134324133086036</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>