-
Notifications
You must be signed in to change notification settings - Fork 0
/
atom.xml
2623 lines (1997 loc) · 169 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[PyTux]]></title>
<link href="https://filippo.io/atom.xml" rel="self"/>
<link href="https://filippo.io/"/>
<updated>2014-05-29T00:34:24+02:00</updated>
<id>https://filippo.io/</id>
<author>
<name><![CDATA[Filippo Valsorda]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Salt & Pepper, please: a note on password storage]]></title>
<link href="https://filippo.io/salt-and-pepper/"/>
<updated>2014-05-28T19:50:00+02:00</updated>
<id>https://filippo.io/salt-and-pepper</id>
<content type="html"><![CDATA[<p>Everyone will tell you that the best practice for password storage is [sb]crypt with random salt. Ok, we got that and even maybe got everyone to agree. But let me bump that up a notch: do you know what pepper is?</p>
<p>The concept of peppering is simple: <strong>add a extra fixed, hardcoded salt</strong>. (On top of what you are already doing, obviously.)</p>
<p>That is, do something like:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
</pre></td><td class="code"><pre><code class="python"><span class="line"><span class="n">salt</span> <span class="o">=</span> <span class="n">urandom</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
</span><span class="line"><span class="n">pepper</span> <span class="o">=</span> <span class="s">"oFMLjbFr2Bb3XR)aKKst@kBF}tHD9q"</span> <span class="c"># or, getenv('PEPPER')</span>
</span><span class="line"><span class="n">hashed_password</span> <span class="o">=</span> <span class="n">scrypt</span><span class="p">(</span><span class="n">password</span><span class="p">,</span> <span class="n">salt</span> <span class="o">+</span> <span class="n">pepper</span><span class="p">)</span>
</span><span class="line"><span class="n">store</span><span class="p">(</span><span class="n">hashed_password</span><span class="p">,</span> <span class="n">salt</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>Does this seem useless? Well if you think about it, most password leaks happen because of database leaks (SQL injection, DB credential compromise, DB auth bypass…) and attackers might not necessarily get access to the webserver. In that case, the hashes would be <em>completely useless</em>.</p>
<p>Yes, this is not sureproof, attackers might also get access to your webserver, but security is all about layers and raising cost, no? Who knows, maybe the eBay leaked hashes would have been useless to the attackers were they peppered.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[SQLAlchemy + MySQL + Python 3 + pip]]></title>
<link href="https://filippo.io/sqlalchemy-plus-mysql-plus-python-3-plus-pip/"/>
<updated>2014-05-02T00:40:00+02:00</updated>
<id>https://filippo.io/sqlalchemy-plus-mysql-plus-python-3-plus-pip</id>
<content type="html"><![CDATA[<p>A short PSA/reference blog post: how to make SQLAlchemy work with MySQL on Python 3, with requirements installable via pip.</p>
<p><strong>tl;dr</strong>: pip <code>https://launchpad.net/oursql/py3k/py3k-0.9.4/+download/oursql-0.9.4.zip</code>, connection string <code>mysql+oursql://</code> and Unicode everywhere.</p>
<p>This is a common pain of the Python 3 adopter: even if a project supports it, add-ons and testing are falling behind.</p>
<p>SQLAlchemy supports <a href="http://docs.sqlalchemy.org/en/rel_0_9/dialects/mysql.html">a number of MySQL interfaces</a>. Most of them don’t work on Python 3 (the common MySQLdb/mysql-python will error out with <code>ImportError: No module named 'ConfigParser'</code>) or only come as a DMG (mysql-connector – ugh).</p>
<!-- more -->
<p><a href="https://launchpad.net/oursql/">OurSQL</a> advertises Python 3 support, and seems an elegant/modern implementation, but installing it with pip will fail with an error that smells of Python 3 incompatibility:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class=""><span class="line">print "cython not found, using previously-cython'd .c file."
</span><span class="line"> ^
</span><span class="line">SyntaxError: invalid syntax</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>Turns out they maintain <a href="https://launchpad.net/oursql/py3k/">a branch</a> for Python 3 support, so pointing pip at the zip below will work.</p>
<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class=""><span class="line">https://launchpad.net/oursql/py3k/py3k-0.9.4/+download/oursql-0.9.4.zip</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>A note on Unicode: disabling Unicode or setting a charset simply won’t work (they do things as <code>'foo' in returned_value</code> that breaks with Python 3 strings). Just use Unicode, it’s what you should be doing on Python 3 anyway.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[On Keybase.io and encrypted private key uploading]]></title>
<link href="https://filippo.io/on-keybase-dot-io-and-encrypted-private-key-sharing/"/>
<updated>2014-03-31T21:15:00+02:00</updated>
<id>https://filippo.io/on-keybase-dot-io-and-encrypted-private-key-sharing</id>
<content type="html"><![CDATA[<p>One thing in particular of Keybase.io attracts a lot heat recently: they support uploading your encrypted key on their servers. This usually is pointed at as a mortal sin.</p>
<p>Well, here is my private key, the untouched output of <code>gpg --armor --export-secret-keys filippo.io | gpg --armor --clearsign</code>.</p>
<div class="bogus-wrapper short"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
<span class="line-number">16</span>
<span class="line-number">17</span>
<span class="line-number">18</span>
<span class="line-number">19</span>
<span class="line-number">20</span>
<span class="line-number">21</span>
<span class="line-number">22</span>
<span class="line-number">23</span>
<span class="line-number">24</span>
<span class="line-number">25</span>
<span class="line-number">26</span>
<span class="line-number">27</span>
<span class="line-number">28</span>
<span class="line-number">29</span>
<span class="line-number">30</span>
<span class="line-number">31</span>
<span class="line-number">32</span>
<span class="line-number">33</span>
<span class="line-number">34</span>
<span class="line-number">35</span>
<span class="line-number">36</span>
<span class="line-number">37</span>
<span class="line-number">38</span>
<span class="line-number">39</span>
<span class="line-number">40</span>
<span class="line-number">41</span>
<span class="line-number">42</span>
<span class="line-number">43</span>
<span class="line-number">44</span>
<span class="line-number">45</span>
<span class="line-number">46</span>
<span class="line-number">47</span>
<span class="line-number">48</span>
<span class="line-number">49</span>
<span class="line-number">50</span>
<span class="line-number">51</span>
<span class="line-number">52</span>
<span class="line-number">53</span>
<span class="line-number">54</span>
<span class="line-number">55</span>
<span class="line-number">56</span>
<span class="line-number">57</span>
<span class="line-number">58</span>
<span class="line-number">59</span>
<span class="line-number">60</span>
<span class="line-number">61</span>
<span class="line-number">62</span>
<span class="line-number">63</span>
<span class="line-number">64</span>
<span class="line-number">65</span>
<span class="line-number">66</span>
<span class="line-number">67</span>
<span class="line-number">68</span>
<span class="line-number">69</span>
<span class="line-number">70</span>
<span class="line-number">71</span>
<span class="line-number">72</span>
<span class="line-number">73</span>
<span class="line-number">74</span>
<span class="line-number">75</span>
<span class="line-number">76</span>
<span class="line-number">77</span>
<span class="line-number">78</span>
<span class="line-number">79</span>
<span class="line-number">80</span>
<span class="line-number">81</span>
<span class="line-number">82</span>
<span class="line-number">83</span>
<span class="line-number">84</span>
<span class="line-number">85</span>
<span class="line-number">86</span>
<span class="line-number">87</span>
<span class="line-number">88</span>
<span class="line-number">89</span>
<span class="line-number">90</span>
<span class="line-number">91</span>
<span class="line-number">92</span>
<span class="line-number">93</span>
<span class="line-number">94</span>
<span class="line-number">95</span>
<span class="line-number">96</span>
<span class="line-number">97</span>
<span class="line-number">98</span>
<span class="line-number">99</span>
<span class="line-number">100</span>
<span class="line-number">101</span>
<span class="line-number">102</span>
<span class="line-number">103</span>
<span class="line-number">104</span>
<span class="line-number">105</span>
<span class="line-number">106</span>
<span class="line-number">107</span>
<span class="line-number">108</span>
<span class="line-number">109</span>
<span class="line-number">110</span>
<span class="line-number">111</span>
<span class="line-number">112</span>
<span class="line-number">113</span>
<span class="line-number">114</span>
<span class="line-number">115</span>
<span class="line-number">116</span>
<span class="line-number">117</span>
<span class="line-number">118</span>
<span class="line-number">119</span>
<span class="line-number">120</span>
<span class="line-number">121</span>
<span class="line-number">122</span>
<span class="line-number">123</span>
<span class="line-number">124</span>
<span class="line-number">125</span>
<span class="line-number">126</span>
<span class="line-number">127</span>
<span class="line-number">128</span>
<span class="line-number">129</span>
<span class="line-number">130</span>
<span class="line-number">131</span>
<span class="line-number">132</span>
<span class="line-number">133</span>
<span class="line-number">134</span>
<span class="line-number">135</span>
<span class="line-number">136</span>
<span class="line-number">137</span>
<span class="line-number">138</span>
<span class="line-number">139</span>
<span class="line-number">140</span>
<span class="line-number">141</span>
<span class="line-number">142</span>
<span class="line-number">143</span>
<span class="line-number">144</span>
<span class="line-number">145</span>
<span class="line-number">146</span>
<span class="line-number">147</span>
<span class="line-number">148</span>
<span class="line-number">149</span>
<span class="line-number">150</span>
<span class="line-number">151</span>
<span class="line-number">152</span>
<span class="line-number">153</span>
<span class="line-number">154</span>
<span class="line-number">155</span>
<span class="line-number">156</span>
<span class="line-number">157</span>
<span class="line-number">158</span>
<span class="line-number">159</span>
<span class="line-number">160</span>
<span class="line-number">161</span>
<span class="line-number">162</span>
<span class="line-number">163</span>
<span class="line-number">164</span>
<span class="line-number">165</span>
<span class="line-number">166</span>
<span class="line-number">167</span>
<span class="line-number">168</span>
<span class="line-number">169</span>
<span class="line-number">170</span>
<span class="line-number">171</span>
<span class="line-number">172</span>
<span class="line-number">173</span>
<span class="line-number">174</span>
<span class="line-number">175</span>
<span class="line-number">176</span>
<span class="line-number">177</span>
<span class="line-number">178</span>
<span class="line-number">179</span>
<span class="line-number">180</span>
<span class="line-number">181</span>
<span class="line-number">182</span>
<span class="line-number">183</span>
<span class="line-number">184</span>
<span class="line-number">185</span>
<span class="line-number">186</span>
<span class="line-number">187</span>
<span class="line-number">188</span>
<span class="line-number">189</span>
<span class="line-number">190</span>
<span class="line-number">191</span>
<span class="line-number">192</span>
<span class="line-number">193</span>
<span class="line-number">194</span>
<span class="line-number">195</span>
<span class="line-number">196</span>
<span class="line-number">197</span>
<span class="line-number">198</span>
<span class="line-number">199</span>
<span class="line-number">200</span>
<span class="line-number">201</span>
<span class="line-number">202</span>
<span class="line-number">203</span>
<span class="line-number">204</span>
<span class="line-number">205</span>
<span class="line-number">206</span>
<span class="line-number">207</span>
</pre></td><td class="code"><pre><code class=""><span class="line">-----BEGIN PGP SIGNED MESSAGE-----
</span><span class="line">Hash: SHA512
</span><span class="line">
</span><span class="line">- -----BEGIN PGP PRIVATE KEY BLOCK-----
</span><span class="line">Version: GnuPG v1
</span><span class="line">
</span><span class="line">lQIVBFA/TqwBEACugv9eTIochvPlZAvL1D8qtVMgUodkZ9AfkYFHcFlRFktYHu+z
</span><span class="line">XQ8UDjGTpUcWix627ZzlxbYIowsUiGz0JE2E15KXpwyK/xLJstGLpnhXB2Wr9oUY
</span><span class="line">FEP0qUDDUDK9NBdsHvH1J6SvUCDFPloRZQih3En8b7WeafxFDp6lxDcWNRgOko3J
</span><span class="line">qDrwdvkNSjlXg9banE0bryWogCZuoqsGwkOWjXRccLM0e1yGHWvPRESd5pkK5F7t
</span><span class="line">eGdKxJGRsd4IFXkfCk4/h01XWLFUHpT3iWm8CS3hu5Rf6Fk/L4F1RUJSKHaH4G1Y
</span><span class="line">hvSw5UHJBuvHHHP76X+oPsUOpA+HzONhFf/hehqS859ocSwmuLWhUaIObN/liC+7
</span><span class="line">+LegRZLTSeDTYruq3CzI8Q2syN7gCjtpkqf3Xqg3WzFf+iJIgGR4u8sXLNmA2mi9
</span><span class="line">1qDSCXOZleqvOaphjI7/gAm/gBoIldh5fzmyhELDsxiUOs50C3tHO2RnEm87wVKB
</span><span class="line">cbgS3vhArvWc5O+ZVbSJRIlGVLHRKKbRB9qlewAsNrT8/v0sHRTS3kP5GGW9cHRu
</span><span class="line">DSTifBCXvwA59TNg72glWAFMJZ7U36wcKCL8Lycwuno63aH+l69fFQ0xlhe1/rJg
</span><span class="line">gd6OVIOs+N6lQLHLB3vCAfAqMVDoVdVxiI1K/LqO+68OtbwCOF3PgnIDVQARAQAB
</span><span class="line">/gNlAkdOVQG0LUZpbGlwcG8gVmFsc29yZGEgPGZpbGlwcG8udmFsc29yZGFAZ21h
</span><span class="line">aWwuY29tPokCOAQTAQIAIgUCUD9OrAIbLwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC
</span><span class="line">F4AACgkQ6/AYBLzwX2vOaQ/7BfycHTXAE/0Ehg5DIgEjUes15fhZwnPMl4XGFMeB
</span><span class="line">nf7tUlL4nrcNhgM3+YPLW4eqypylF6XbwVP7ruIeHJAS3jcVgZaHcc37jGdNLbCf
</span><span class="line">CxwasK9szuaTkZrIEZTcmYIdI0BBIJjE4Ry2Fel15KOVpoZkUYMHVT3k6jRC1dOB
</span><span class="line">s5FxCPSs7RBrNUbqSDcrb42WJuinvv58E6Mr5nlm5+b7Wxw7S6EJdL0tNlv7r8XN
</span><span class="line">tRwQb/b46TIFrZKW1libE8bfuXqRh7vVv+Ml1QHGvNoVEGaQKM9EbvnBiTsHuE9x
</span><span class="line">XBCIX5rmPBtYl+nejmeMHNuMTp4fYJk5SwcR6Cc7Ku+wDKzY1SUC9JRZlGDUeB5C
</span><span class="line">FwgVNSleDZDSLYbhqPk94oec3f5C7dgQtrYoO9ZIfOhdeDzrvlMJoWjlH1OzU9ET
</span><span class="line">5I9T4YXgAF0ILb3D2Wv65+2yD8AFo+1AbldHjnX2sX3kfjzuFbQqC/olPNEQyxqr
</span><span class="line">VQ8QiIvctR6O/PzAt771PwJnJ6cmVaH6Jl8QPXlShir3tu0VBUSYYP3u/iX8s/rh
</span><span class="line">qhcY0rGv2V8faLaCHmNsEghsIOhhaM445nVjO/JQbUlo2JfBgFpS1ZrCQ6t8kdS5
</span><span class="line">Ey9GwTyNxQFo/SiFuSwRuwHIOzfjc/YvIQn4tsWHFEqzYBHBCrZYP9SFhDhDtLAn
</span><span class="line">iK20LUZpbGlwcG8gVmFsc29yZGEgPGZpbG9zb3R0aWxlLndpa2lAZ21haWwuY29t
</span><span class="line">PokCOAQTAQIAIgUCURgF7AIbLwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ
</span><span class="line">6/AYBLzwX2vlSA//V6qMmRsDrfg4IAtoqJVuGrpDivuHjjgyPB7MPAgGhr6/q4Sr
</span><span class="line">b6oPPosP0L5VKLnr+k/4rNbZWCSvzeBEQdKhev+RxgwKPIYpUcvcLEtkDP7CDd3T
</span><span class="line">k/NCBr679lhireEJjpj+Q714PRuKahaJ/mSUD7fH2giE3gpXzNkEEKqTD3jJ7nhM
</span><span class="line">n/AsQSDE5cBYq3LLQG3DkuRumKT75P0Fiz6tMvQBLwpBml4c/Sigzy7Lpg85Tj7x
</span><span class="line">cmSNwSrbiYuuT9gev/7Qj2ulfoMzJwZuzls5T9KbBgaZ9LJ05XfGDdvFk7J3hVER
</span><span class="line">+YJsdgHgP0GC+iw55+9cSqkM00Igo9LPg4VH9rIcz2TbGdlI64XLoZk55J3bCWwF
</span><span class="line">a/2X64KABdaDBN8XI7jehi4Kykcniau3TAeC63aRGoXyeZwqwU+PkByApY9wGvVa
</span><span class="line">wRyisFLbvrOeIzOaUIKwzKIpZiFl8HOj8i+2H5YTFi0BuVDx5gq2pN6XR+fMYZci
</span><span class="line">IVHgpqIkyVdni0C40BGPmHX5eqqdiWtuQOgjPlxwrUxSBlCIT2Nn0PnwWD3QL/ct
</span><span class="line">XPqEmZ5Uxmmeu/AERgciR0CQOUu169fP4QulamGOc1oQWnN+eCGtzl+ntJR2Tl9a
</span><span class="line">g7FnNOMXOEV9jBzdFEJW4iwAhiR5GpE9AymZM/pUyKq4kJ+IsoZ5QojcjJu0IEZp
</span><span class="line">bGlwcG8gVmFsc29yZGEgPGZ2QGZpbGlwcG8uaW8+iQI4BBMBAgAiBQJSxCrbAhsv
</span><span class="line">BgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRDr8BgEvPBfayLcD/9WheYBmFEu
</span><span class="line">HOy5gARLaetGhxB1xPpsFqVTgKs1aSV8c+oiHxNc3dchhawazJqP2u9ecqYmuLzm
</span><span class="line">HTZOSVpTNeXTTDXJzJ1iyndkgkIOXR8JtGjPoyj/7XJ7uRvwoaXLHw91rTzks1dB
</span><span class="line">MLIrXKdey/8C/eMyiaENE+oIPaBtYwHo5ju+t3k0wu0nqIsQXN3J/GEPSzhZYL0x
</span><span class="line">xsAg+c6mI0i0qNJFfC0KloACVaFA9621nc1IuDW4/yGmrRmSoPSWOIgDotsPbOyO
</span><span class="line">Dnj5kSr6E6sH2ol4h6oLodtRRivZ83h24V2s4tW+rmHUx9UGMVQx5WS3BeI0RGrG
</span><span class="line">VSbit2qBPBdJIvb1C5Tdm3s0T7NVKi3KxeRftT5giXORP2zl6375ubijr2NF1zlC
</span><span class="line">pa1X73YIRESzjXRvUt2jYUSEZzlOuzBBKi0ZhDVmA6dSMv8JA51/P+5YZ2QHUmxG
</span><span class="line">ExU6dgadWNyS4xaskwhiNjKsh/ecpMMKDvzBy7Vm/NOnprAbqJahKIqI7wes8kTJ
</span><span class="line">oQylYiqUm2/94Udwjao1C5SYiE3MT6SoCpvtnIlos3AuHMaRLiqCd0W2ZXDOxfAb
</span><span class="line">5ZtXAMPSby2epkgZNmGGHF07ncpJkFZBX3cBXi8Hdg0B2M4crmjrPnNesFryOf4w
</span><span class="line">+0vhcas3REJ9on2N3MaHliP1wLmRO+q9t50DvgRRGAZtAQgA5yR7x4FHQ4ahh6S/
</span><span class="line">m7/vHUpi2C6i6Uzod1EOkERLY0bXDqKLtOCfRzG+XOYpX8YrxfEVAL9buz3IHHuu
</span><span class="line">ImIoljkSTSNcLB0/Xk2fS9HUtD55H9krAVJtmHb9NHJNBLzBbeAm1Khm1mSIpOFI
</span><span class="line">AaoCJ/fVLAWiP0lJeIJhX4y1oszb599cnU3qRbgXc+dSDG+mNGL65UzpT+nG9ubi
</span><span class="line">0hwsXffbZ4eHjAXmNGk/wJcIdFkxCdm9cvJoNsd2e6xRp11ZR7hF+HilnWocPzL2
</span><span class="line">yAQnQrb8bSFO8Wylwazngg4uCPbbYgBfbHxRPVWfwU2P0ErQMxIH351cYaP7fZJ/
</span><span class="line">jJ76mQARAQAB/gMDAsti2mE+O8u0YFW0ca5RohrFiWE6WE0tZDdCgvQdEzOC4QPg
</span><span class="line">kMlzPLSkihbJRAD8tcfs3gNYTxRR9qNJiY35Sl4A54m3Y9lTqr06leRQ6NHlrz3r
</span><span class="line">AfhZB6VUwM6K9Lr2vwXiVDsp+x71qvU0FQW3Ws+PCnGoMNpnGrM4ZNCJLotaI6dY
</span><span class="line">1c7alf1fS1vPxbBE5U/+UYdOhhXql1+n3iYWadMydhPmxAm0BkJiBK0gch5N5ZYv
</span><span class="line">OjrsDBZdP/tT3QX0qjMhuhBq/XGrRw0aCmpTpAJuvxz1bZH4lylI4sneOzfdowc+
</span><span class="line">YfnRTLs1aYLf/by5rfHbb5trbLuXewGzWT37FYBROLXJKsgPE1y009TLXATv/l9+
</span><span class="line">UhXuV64+DjwXGIJyU1wdnxgqAsrX34XuCNEkmfHpQF4JJfkxfS5ed5vrNHJ7kXKZ
</span><span class="line">O9yle1Kqj/oK8wVLck4AL204knZHEzETeVi5tX+r0gqsT8WYxAIRjXtVGFls0D4c
</span><span class="line">D61c1IJITBCQDnsY2PUYVi14p7cqB9i90ixz0OsBs8aO3TUdrqSFBgllwi+WEYkS
</span><span class="line">/8QT6tS/qggihRrpdMELsYnzjDi0hIKYR19l/Sl5O+GhKJeJ83g/NmqYr202/aX/
</span><span class="line">dF7DPo+KGUEIjL1Hx+AVBhfwBP1si217IbiEOAQag/BwxhGM+9wYOPUJE/Nfs4Yq
</span><span class="line">fqBNhWsUlvUd9gNj5unxow3fLsL8xE0mbzKg9gGqI1kq22tdt846/TzM5QpHkfIf
</span><span class="line">FK2pJR8K6xhd0eF4GO+Dv1ydoEIY57wxnD77m/EJQtM/0KKMuxYjsqE7BNht1yiJ
</span><span class="line">N/DVwqc4YswpkJ+M5seprCwwrykwjtYL4Sw/uxemmG6LJ5l+2bHSPDBPJuRZ8gMV
</span><span class="line">9ZoHHHjPAf3QUp+zFc8dOFZn30GilAGPvMGJA0QEGAECAA8FAlEYBm0CGwIFCQHh
</span><span class="line">M4ABKQkQ6/AYBLzwX2vAXSAEGQECAAYFAlEYBm0ACgkQUCI0JfFJqiVwGQf9Fvql
</span><span class="line">tfcJIKasSl6xDC83j3qxgKKUYdFj1jA3C2ZOtREPk8YyOSksHQjpCI51Y5gZ6uvG
</span><span class="line">4NKfPfN7sIyxCtvDnJtiDnGmqRmckub/RnxuOjU9hxejrkWTM3zQFMWa1ohbx/CZ
</span><span class="line">vYyqgNBUKc7IB8rgjK2190s6B6fDZ27xE5glfhy4rONBCvvVtF450+YX/mlgvMWr
</span><span class="line">daaENPNVK9cJ1Wb+rZFVmiZxo/OVSMhX8YMP7MVanSTCqixp8Ep8KO0YduIpMU3z
</span><span class="line">oOT4uMV94kE/kSXjk+XlQFeJmy97HkRbTxKjpFfYIekwrdUS9vI1HS5v9oApRsri
</span><span class="line">xN/DEwC9EQK6mNq7ulcfEACq+5BC9vBzdDsq2CwphhQdj2tcouGGBslc4AWHwN1F
</span><span class="line">jYif1/wIJgG6ykA5DvZvnsTzesgxKtZLKugINnyuNeGc7Ct1+3NEzUW+vpJhcFzk
</span><span class="line">iWTGThT8GGQ/g/QV0NXChGiOAr8f9cYdVcjNBfa0XjRJUQ7RAm9lg6EkBCIz8E/q
</span><span class="line">6r7nK3jYtRpLVqYd6Tg6HkY+7geP662CvQmNpe2pNraQOACxN79Uw272UpWLBOz9
</span><span class="line">4G5KZCxInu7L60yARsR/6+/OddmGhE4SImFwp1OIR/XP7oP16I9WtilXNgq/Oii+
</span><span class="line">InG0TimyrBj05CN3PFzs6lkmy49UTpfxYf5jyHh44xmUklLHbSMqp3GHUHDqzF3U
</span><span class="line">0xbYcb+Z+TPWX/0kvTeb22XjeXmsEhWfRHb78xeZwSR6YTaMsa85vmrbNqft26jS
</span><span class="line">GOLp4E1n1R431zIjlFIynYdH8ilwQLbpTCQ6UzDBnVMfRv1UefkurP6+msBtXnfH
</span><span class="line">HrSx1bDCIkcrLhg8Z4P9YnNpY5+gYrjIL9yrgHy/iGCAXF+3V050AfhcIzF21sOt
</span><span class="line">q1eS7aMX02+bU0bTC1zEWOxrws9PlTc2KyeSv/afLG7aKc1J/jaMEaUKp7fORCRP
</span><span class="line">SnkdwAH8HqIukHr3DQH6MuXz1w7sEQ4lCMcTf39/rJKMaGw52Sa3nEphhvhDA+m7
</span><span class="line">f50DvgRRGAcnAQgAxByki7KXBGn19S3IinMVEvOMD+OUWvxsuvUTe/r9siGCRkbp
</span><span class="line">qMxNzEJiWlSnfBfqKkkigT8HFflhydl+qYjRBk/yB9eG6pTZ34m4f+30S+GIFn9p
</span><span class="line">PwU3gJevE2z0OpeJn/vF1VsuQrd2t03OAyclhyNQ3mjjDPfIRQQOJ4sNRqYo6dZ0
</span><span class="line">IuN2tF9N74FEmNHu75+tgjZ4Sj8xuvTP8GIy88fC7YpxmcdxrA3WQkWXuessA52C
</span><span class="line">nEKDgDGRiSwLeTTgZFG3GY5PhAfYgmsyWzCCk363d1F68qN8t/1LtkZUwKWssBIi
</span><span class="line">u/dkRu2eRDMCYRywMqEU3C61jTKLXx/strEHowARAQAB/gMDAsti2mE+O8u0YE8m
</span><span class="line">U4iCCZGiy3JMCF3BD7AytlkHQsERwW9cd5bw0awyJ6H/EV5BmCNjFSjojHIOrFr6
</span><span class="line">F7mCHELJ725gcsMShuN2PtMvdoko201/NtsGLoMwBN5V+sfYKyhoX84qyDE0/nrQ
</span><span class="line">yba/ZChfA0mGKi30WdJcwPTiutBS9xhJJAVK8oJyl/u5qKB6LoPflUT7gpoM76WJ
</span><span class="line">x1p+L0OpsTpEFLORQGELkgQWYc4tIe3edtV8Bi1D/K7IpFrvxOdhw1B5f0Rppn67
</span><span class="line">UyVTe5E422q4AeU+rjeQa3NcmwukJffcVr2rqNszFQw2JChX38GEoQfyQNLfodYr
</span><span class="line">92WpGllwWamQf+ijNou8NIplAwoYpsUgT8pURwX3ajz7VBEk69zi4CO6yHXOMGJ9
</span><span class="line">4WI6M2EZ7B3Xe7DaemghjxIOY8WLy9b2qcFvsIQHCN9O1FN4oaR9N8faUV02LcI5
</span><span class="line">HdX9omFcVzJalYwPctZmXP7qhJWvw47VMywMc31khx7kV+rPHndyFL77jMS1IMtW
</span><span class="line">YEllwUmj3vRSEVgr1yNyqg70wZszuwBVuJJjyjZRDMXoOqq4lkmf2flRb39SKQ4j
</span><span class="line">n62NjSMZJuMeXkof58FNmJH2sCgoO56sS4ai/OVtc0Aqt3rPQ6iD7zLTNwx3nhmW
</span><span class="line">UJF/gEsfPD9vG6pmfaxvvXDn36bgI6FGBhk2TjUE65vM2DCURPPrLGCgCr9wHXwL
</span><span class="line">NoFrCGuWv3cZobS6VdVirWbbz2/mc9+bz4UzVsvNhidYMV8zKUDKXDjJLqilnC8t
</span><span class="line">VRR9TW0bVmNQXjsrRYX7il4O9jrexZCzZgFKltQOHgdF3xyz6v8HSNCx5UOdOj7E
</span><span class="line">WQmJzffEE7O3Oj4YjHw8LwV2Nwroo6mNCfw9gCoU1m44lDu+togi6cmisFm3WLbC
</span><span class="line">pzuJAiUEGAECAA8FAlEYBycCGwwFCQHhM4AACgkQ6/AYBLzwX2tsuw//dkHtBIHb
</span><span class="line">gUbij9gfZgGLQ9zRjprcxtIyWY6Y6oGkh4yCaNnW3+5Yg3Uh6sX14J9TUMX/mBc4
</span><span class="line">wcxq3kMfzon1Z+nlhVw/mNFlGj+04RFKoDen+/wxbmWIkPdqetAVFb+/7Jzpcldy
</span><span class="line">k86wjRBQ0TMw+16iqRZaLh3/8kyW6IQ06aEAoOdZVtRKUOaFgRv2bbJZq3K9x22R
</span><span class="line">LKeVemvpfVpUaOFUSE6pcHmPaBUTKtcCcz2DcL+E29jHuVCsO9SVQT0GVKYO1pkD
</span><span class="line">097Vgcp+IF5ZU0p7mA/7kwaPrgBtLLpGr+E1olUDcf8yn9uPjk3BrkXGlQH2cDsP
</span><span class="line">FB5m11futjcjbMp1aZ6i09UkmQW3ZqMCUEHXe0luqXAtHpCCkj/LP21QY8Vu1Ye9
</span><span class="line">NytNx1zjTRCUNG74BGG35IEHDb17XZUlIaxasvyWMtJT7KvBZCoCzY21vQKc+Yhk
</span><span class="line">U83KAexxV54HVc2hUapZLngSsTb2bExmgSeWb/gvXLcQJEBotUuinMhSruz0td85
</span><span class="line">daNZekkjQZrM6mxB/GFRsCkVQprnEghFk+URkxPCVEawC6Dzom8ZrJEkcIeuSyxn
</span><span class="line">7cKNJYF6+G4wY7U2VKO9tY4AMsfXtitTGsh7ipa+raMnXsvlGcBK+QvzNediGIWo
</span><span class="line">cEaTayTurc9v+tt1t0S7v5Fb1OkC2aPad3KdA74EUsQregEIALEMPqUx3m9l1ycS
</span><span class="line">5anJinv5NEM+Xjyrl5aTk853r1nrYjwEneOtvqxpNGL2vptQH0NhPx0RVOurhJQE
</span><span class="line">0ipaiPmgt7GnkP2e0FfqpZuBOKQvIt8YX3620Hv8ZgMmElWUlWnZdH0LJzuQ91PR
</span><span class="line">zxnmycd7EFhomnMeHroEkaSrfG7FN54DaGEG5mhbkqdGEMaVeLsA7M6bTj0CQhx3
</span><span class="line">TMBRUDY49NlYlD6Y0rxfS8oNJyoUj+Gkr7SSZcYYbDRWCO/hwd0jd8p5RN9/g08K
</span><span class="line">BAMTT5Qyb8su1iMPxqI6cdjol6VlXiExFhWxVYeFpiA74EuYAenbxDddGLHtYnSj
</span><span class="line">lhXZ+XkAEQEAAf4DAwLLYtphPjvLtGD/5wMK0kL127p0KT6/pxqfqYFrHYsgqmxE
</span><span class="line">MGN050gDaN70Xa9c5wFI6EozBSWdLJ8cyTK92QfFgNMLZzWDMqqi1CuTiG3AVJiw
</span><span class="line">lzkvpCMmX03BA7BbuwuJZNloMDMLeqxXPNc2utnp5Y8TNxIhVHJaAyRrfn8upTZ6
</span><span class="line">rzHdMFCZ76psp3smkvQ0ucJdZNgB4KIiasCQaaEQziLPyOfexkslHoAln59Lzbxu
</span><span class="line">jlFTnnttGtgv+BSi5VYvvqObKJVDmQhLCbuYom/0/tyUR04SYxlPicLFMkXpLJtF
</span><span class="line">bHo3wYCrEoznXYlRmBiKbi8FZqwrpyL4OOE/TtVhhHXuSMUQXcTFiyCGjxT+NgZr
</span><span class="line">PrHlukcbPZntYTQLTU44J7F0m6e2K0FLy40axLtwauzoJENhHFsePCeixg2f93ha
</span><span class="line">bVDja5uK5r5i9hKJWh4XfW0H7zkI/o+OQsiMtwsHNYKsgn4BxxUZUc5LP1PJZiQP
</span><span class="line">0F4Srsub61HCy6vpbNwjIS7nbvEq5GgcPmuls/XyUeJ78LHQ+XJgaBHf87kO+lSx
</span><span class="line">D6xj2k0pD5EgWQNJQJ/q0Sn7ZUQR0JWjwn1FhbpTmHadrUM+j6v67dxBTfYQnRmE
</span><span class="line">aVk1dPXVKhoCOUUgJDXfaNHX4fiAUv01FUDu9+qshor4491BLchAY+4tXqIGqSu0
</span><span class="line">5P1rGEBsJUAZxKV5o9JchEKFpfWA6nt7WYPPnwAOqQJza4mzOlPW7i7Fu2fLgN1p
</span><span class="line">hhzM257ZB6p82LcO/KC+OMcBf2ieTE1YYVHogLXS29ya9LBv4lVO/lCsBO8A2lSZ
</span><span class="line">5yAGn4BIdw3+80GAjYNOujYUWYR7Ng3nZGQ3g75WI144+Se5QeKvPFqAYmJWBeww
</span><span class="line">Q7oM99RT+g1EiEv/NObh8kod1zJAPLYCTUBNiQNEBBgBAgAPBQJSxCt6AhsCBQkB
</span><span class="line">4TOAASkJEOvwGAS88F9rwF0gBBkBAgAGBQJSxCt6AAoJECBNgkAQH1IW2TEIAJwY
</span><span class="line">09mxjxk8R4t5hd2U80Ua/MO/QMQzF8C1/hgkskSVT8AkHlOE73m/ipjoY6n/7aiP
</span><span class="line">Ev05MSgZHHWjED7yHBTdzZsDrMr1p6ykqKohhqPzNUEZ/1KFEIS0+LUTAMg7kIHk
</span><span class="line">/SKhP6GSVoGw/DhSTLgXiw/zRuByHTf3VbitA8X+4LQkwgqnit9SR0JgS013IqiH
</span><span class="line">811v+w3CTEuUypW3oN6T2AyzYh0qv0raO0Apd16999FqhDNRIrZJCmhBdrfNeu0C
</span><span class="line">JftDpgQiKmj+VoJgTDz0f0Jso6QeKCcbjiDArog74fBZzQhQXfV+U3hBj5YHM3KU
</span><span class="line">uQfaPt5zpPYCYMPFmG1TwBAAoRA4h0mxzKBJdOen0QiYHPnnXsJZxdKO4SJatAmB
</span><span class="line">agaxdelGQAwhbaRH91IuicZeUftZ+cWBTF2LYih/fdV5BWjAWVdddAzLBqSQkTKF
</span><span class="line">+8HCtg8ezTeEKvrYDWJUmtaETNX58lLbBd8TvqXEkKjII3DDYO5Au98vZATV+JxH
</span><span class="line">bLmoYHhYzcQOTMg6l7CMq/XXWksS1GJcPKJuJ6gLpYuZHM257vPjU1AfpukZfiP8
</span><span class="line">2P2GYY1BY9onPqe8x5Cllyr9zlgER7Pf2RjuuBPt2OW2L8uYD7+BsU6KlRb3Nx+o
</span><span class="line">b/JQLorI8yaNdtnHRlns8c/dtRCFydQGxOi1fMu+4JjaG72sYB74o5ifM98ar0Dw
</span><span class="line">5a9H5nrYwsdMfGuIacfEZwRK/zLsSMzRJ3R7zbS9g05hviP0DbwtN00vVXhHLQ1L
</span><span class="line">G/W/kY27KMVhgzOHH5uPRoqUA1vH79Oh7tZ8gcHFPCDQkvU4VpALmXmOn+hPwHWq
</span><span class="line">Uk60QiFg68Wp4S6U72poiefsz6VfO4a+hysDoArZWLK0lIWkT46t6q3NFLcYhqrI
</span><span class="line">eV3pK3CjCC8hzhsNaoJLS1jiAeIUYd7XPoQO9Oc/vn679unufYMQidNW0syF5P2r
</span><span class="line">ykrghzzcEZZRVLY1/gsnzOPGcj69hMlN6v10ofJRgts+ayHMW2Q7g5tAGDgsFYH+
</span><span class="line">xf6dA74EUsQr+QEIAK6sE8TOTJGp6HiOT9CTT8WBIh4okvpJAbzGM9hNdepIZWit
</span><span class="line">mDiAJXVU/uN+zCaQcekFe0qEe0RqLhJIGyMNyu0f8ibjkt6SIeACvuDoP+V7m+vw
</span><span class="line">2S5QMdR9mlMVRSq3ClfR5uiPy0qL/GMdWHCPaR207MO5saXm/0jxUtsra6t1FYn+
</span><span class="line">FRVMBevTvT1HVCTfpme6q6FzV9sQ9xiyAE7/g9oZoo1QIRiZxTBB/9k4e0MDGzW0
</span><span class="line">acT8I2BZ2K7UUFnXJTydvKwzUIEbQ3hQ6YxtNhpZw5uQAd/hnz7ZXr8YMTR6/jDB
</span><span class="line">FyOHWanX8qzMhu62ZSPGA9jZdVA8yy87YJccLoMAEQEAAf4DAwLLYtphPjvLtGD4
</span><span class="line">A2SG4sC5bTyjwkoUA4uNOBedh37+cXcKHCG4aPVHSjlzWvEyuQxYsoUIMQZYcQB5
</span><span class="line">u+sdNH4g1r6AwP7Xv1UU1pLzoFomQxdvAW3nhSAlEernnvsz+ndbTVBwzKfx1KGI
</span><span class="line">WsAp78IVK1o1kEkUy48lzqcnJ8qISlGH8dsX0R84NJiBdhOCIaPUqKljBnb3HZKO
</span><span class="line">S1LuW3B4T75C5C43vx9lMjSIkWwD5NoHTmzNPBz7nTWqTG90cnLIY22T3LShLF7z
</span><span class="line">TpZDhpv8n1gmRRv/+NMgKUVN98QffUBr6fTV9yg3ltwoP7x0Bsua+fmhresW2aY8
</span><span class="line">wAbIMwUSwYRshJ+Zbu5qub5fPPO3xHEukhrmcwy/g0a6phdDvkVMm6Wx3UvsGf06
</span><span class="line">DHvrN/LB95tkgaSCkbO76zX4VVxdeGU9s2mT+ZzDC9aPK6yj+K8dGqN3ltwHn9JA
</span><span class="line">JzA7Jxr9+2bafypnLJI5HXiWvx9yfR/q8M0PTpqOox/IMtURZzLvhdp4jlxKBoEd
</span><span class="line">0BRtRkFQOgotDophxmFBPWOBGi5Kbkq+t0txKo1qA9kmnAH3sARkWeELbmu3Bqwm
</span><span class="line">q7HFbi48T7NMX/ml6W1H3XJo3Mq8PY7jRAJoY5FkR9Ej4Bgm5OqBEXizvPEZayN1
</span><span class="line">xfj0gfJQHuc2qTeBeiFeeOhkaBlXWAPYgQbtrSmkkFE8lbdLmQ6coUypZ6QSZynJ
</span><span class="line">NclfWj8thS2dIHIMl60iRioCvhlH13RoZeQHyBfUar/COz9sPCnEdSZMKgrK8eGY
</span><span class="line">Elv0dNHw70xmS+j/9DzL4qf7Zw7akl3Y4b/RF6g6LYlNObpstNjXWaL5a8Y8+r6u
</span><span class="line">z52h4g9nj5wzwVtLLP83nvnbqxBMqUYsZMZbg0iVoCBPHms29oofb1s2/FRdEaMb
</span><span class="line">o4YGiQIlBBgBAgAPBQJSxCv5AhsMBQkB4TOAAAoJEOvwGAS88F9rnvUP/1qcSHDQ
</span><span class="line">E7CzMMhx9JRign7qkCHMHqtaRHKi8/vj9ww2XSZBlNl2mUmIKMWJEQeto6QZugAC
</span><span class="line">BHJF4PLpEHm7bcx3IYiMedHq4H0BVmq3qRTSdnXXDiCxYDjqX1tfJFPhx5+kyH2P
</span><span class="line">1j0dN9F7CxsmmfO610kItyOTBTNSUNLpKC3VcEJADu6xqNa+C8p4bN5BcRdmvYni
</span><span class="line">2yk5tNkIg+0byHUQfh1UhD8fEf6BtA8gnECjdJ2AIWV3Kx4p/K9GgvJUxLgdxyIq
</span><span class="line">XxNNcri4F4xFIrwArNi3iJAmgCBINfa/SnyJMdZAyPbZQsfmfLRaZwjwVFsgTpQN
</span><span class="line">a+xTPBXsdbEOBsyqxTbAieMM7peozScHDam/DfdbKtiSoshxuUnYhJ9qiTcauNWb
</span><span class="line">J9AEzwfbEBJ7nr53FleOwIi+1yEWPDqZ6x8AP2G/EPSlWfvlzDeafxAMA9vPP/Ca
</span><span class="line">JifhTgErrj/i4KaDecDtDgUOvJCjCrsNaQKm85zWrBWgvvmcIvCBwGAFsnY9C8v6
</span><span class="line">lTvmq9aZXKhVAeWAmfDKGVMt13ANhnxYU3+LB2CE+XE65e3aIC14R4w1Tr10Sx6V
</span><span class="line">cC8ETfMar0UrgGNCrQrTkDAP0alC4oodPBw7bNj3qymHjlE8dWaodF8v0dPFJ5HQ
</span><span class="line">roqkWuFinvGPsdX//BcJPMZyAGfCa577lT+Y
</span><span class="line">=ROzK
</span><span class="line">- -----END PGP PRIVATE KEY BLOCK-----
</span><span class="line">-----BEGIN PGP SIGNATURE-----
</span><span class="line">Version: GnuPG v1
</span><span class="line">
</span><span class="line">iQEcBAEBCgAGBQJTOcOhAAoJECBNgkAQH1IWD5gH/2lGtDIu3d5GWA+GRRc1mL1I
</span><span class="line">FA1w2jdB1m4RGDgQWi7xX38cx0/8J8b+OzYKxC0pYezoKBmWMEa/xCdKIwrDLcBg
</span><span class="line">bx89qYgbeyJYY3B0PrVMBa2NdkNr8J1RXv+GVOUpkhJiVJY9OSJKmjDbVnpL5jEZ
</span><span class="line">3+j3DXK+5c56LdsWAQ5x5ZPyDWL6vEAUTxwL89Uy7GQSmeA7yh2j+xrjd2wBgAzq
</span><span class="line">FC/2wKJZYDLLuFFqMwi8fsX1vfsll/eAlb++vbel4pdunqqG4eW0C69jqe+RMyNK
</span><span class="line">1+YkPzGAJf7KWMcYzk9bzpFBEHmNh+0ZWiXkfrOsOw+vQjHJbXN8wE5pszBD0og=
</span><span class="line">=2qD5
</span><span class="line">-----END PGP SIGNATURE-----</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>What you have now on me <strong>is what Keybase would have</strong> on anyone that uploaded their private key, and this is not even TripleSec’d, is just my very own, signed by many people, regular PGP key as it lives password protected on my laptop. And now on my blog. (Isn’t it Backup Day or something?)</p>
<p>If this is indeed dangerous you will shortly see messages signed by me saying that I stink, and immediately after me waving revocation certificates in the air. But it’s not going to happen, because decrypting the above is arguably as difficult as computing my secret key from the public one.</p>
<!-- more -->
<h2 id="the-sensible-argument">The sensible argument</h2>
<p>There is however a more informed point that is made against uploading your key: “<em>what if they start serving a keylogger on their site?</em>”</p>
<p>However here the issue <strong>is not</strong> having uploaded the private key to the Keybase servers <strong>but using the in-browser client</strong>. If the server turns malicious and you are doing crypto in the browser, you are pwn’d, otherwise you are not.</p>
<p>Let’s look at the threat models.</p>
<h4 id="keybase-is-compromised-you-use-the-website-to-do-crypto">Keybase is compromised; you use the website to do crypto</h4>
<p>The attacker does not need to upload any keylogger, they just modify the code to catch your decrypted private key while you use it and send it hidden in the next upload. The End.</p>
<h4 id="keybase-is-compromised-you-use-the-cli-client-uncompromised">Keybase is compromised; you use the CLI client (uncompromised)</h4>
<p>Here the attacker has only an encryption of the private key as the one above, you keep using your client happily and when he desperately upload a keylogger to the site you just go like “WTF!? I don’t do crypto in the browser, why is it asking me some password? MAX!”</p>
<h4 id="the-cli-client-is-compromised">The CLI client is compromised</h4>
<p>Goodbye. Your computer is compromised, don’t even try. But this holds true of any tool, even the very GnuPG.</p>
<hr />
<p><a href="https://news.ycombinator.com/item?id=7503931">Discuss (or post messages signed by me) on HN</a></p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Why Go is elegant and makes my code elegant]]></title>
<link href="https://filippo.io/why-go-is-elegant-and-makes-my-code-elegant/"/>
<updated>2014-03-26T18:16:00+01:00</updated>
<id>https://filippo.io/why-go-is-elegant-and-makes-my-code-elegant</id>
<content type="html"><![CDATA[<p>This is a enthusiast blog post. I’m not even gonna speak about how concurrency comes easy with Go. Honestly, I’m not good enough to speak about it. I’ll just speak about how using Go in my everyday programming makes me happy.</p>
<p>Go has elegance, good tools and has had the possibility to start designing from scratch.</p>
<p>The following should not be a list but a tree, since good design decisions enable other good design decision. But I’ll go over them as they come to my mind.</p>
<h3 id="every-package-has-a-unique-name-in-the-universe">Every package has a unique name in the universe</h3>
<p>If you write a package, it will have a name. A unique one. In all the universe. Like, <code>github.com/FiloSottile/TripleSec</code> or <code>filippo.io/foobar</code>.</p>
<p>This is <strong>awesome</strong>. First and most obviously, <code>import</code> statements are sure, clear things. You import packages by their full name and you know what you are importing. No need for <code>bundler</code> or <code>requirements.txt</code>.</p>
<p>Second, you can keep a tree of the packages you use or develop on your disk, and it remains tidy by itself. You just put them in <code>$GOPATH/THEIR/FULL/NAME</code> and both you and the toolkit always know where they are.</p>
<p>Finally, most of the times the name will tell you <em>and your toolkit</em> where to get that package. If the package name starts with <em>bitbucket.com</em>, <em>github.com</em> or <em>code.google.com</em> then you just need to run <code>go get NAME</code> and it will get downloaded for you. Automatically.</p>
<!-- more -->
<h3 id="godoc">GoDoc</h3>
<p>Go has a <a href="http://blog.golang.org/godoc-documenting-go-code">clear, easy, multi-output documentation style</a>. You just write comments and there’s a tool that will write txt, man pages and HTML for you.</p>
<p>Mix this and the above and you get <a href="http://godoc.org">godoc.org</a>. The site will index all the packages it can crawl, generate docs for them and provide them to you at <em>http://godoc.org/PACKAGE_NAME</em>. All of the docs, in the same place, automatically. <strong>You literally just have to write comments and push and it’s like you registered the package on PyPi, generated the docs and uploaded them</strong>.</p>
<h3 id="compiling-and-static-binaries--with-easy-cross-compiling">Compiling and static binaries (+ with easy cross-compiling)</h3>
<p>Go is compiled. This has a number of advantages, first being all the errors that can be detected by the compiler, and speed. But usually there’s a tradeoff: Makefiles get messy, dynamic libraries requirements on the target machines.</p>
<p>Go solves all these: there are no Makefiles at all (or requirements.txt or metadata whatsoever), just imports and at most build inclusion/exclusion statements at top of the file; the binaries are static.</p>
<p>You just compile a binary with the libraries you have on your system (see point 1) and ship it to the machine that runs it. No dependencies. No interpreter versions.</p>
<p>Or if you just want to solve that Project Euler problem, <code>go run solution.go</code>. I don’t miss Python anymore.</p>
<p>And by mixing good design, good tools and good community, you get <a href="https://github.com/laher/goxc">cross-compilation for free</a>.</p>
<h3 id="static-types-that-i-have-to-type-only-once">Static types, that I have to type only once</h3>
<p>Static types are good, if they don’t slow me down. Go simply figured out that you just have to define them for functions parameters and return values. Think about it, (almost) all variables are parameters, receive a return value from a function or are defined as an explicit value.</p>
<p>When I happen to explicitly define a type, I’m probably doing something complex enough that static types are only gonna be helpful anyway.</p>
<h3 id="a-unique-documented-style">A unique, documented style</h3>
<p>Go code has an official style. It’s part of the language. It’s documented. And patterns are made explicit in the <a href="http://blog.golang.org/">blog posts</a>, that are committed to the same repositories as the Go tools.</p>
<p>And also here there’s an awesome tool. <code>go fmt</code> will take your source code and format it according to the style. No more “personal preferences” and discussions.</p>
<p>This makes reading Go code easier, whoever wrote it and whatever the project.</p>
<!-- As Linus Torvalds put it in the kernel [`CodingStyle`][codingstyle]: -->
<h3 id="pleasant-conventions">Pleasant conventions</h3>
<p>Go has some conventions that affect the behavior of your programs. These are easy and natural, and simplify the language without adding confusion.</p>
<ul>
<li>Anything that starts with an upper case letter is exported. Everything else is not.</li>
<li>If you have tests and benchmarks (you better have them, Go makes it so easy to write them), you put them in <code>*_test.go</code>.</li>
<li>You write some Assembly, just put it in a file named like <code>*_amd64.s</code></li>
</ul>
<h3 id="control-flow-is-explicit-and-in-your-hands">Control flow is explicit and in your hands</h3>
<p>There are no exceptions that can traverse your code up to who knows where. Functions return a error, you handle it, or just return it.</p>
<p>Tests follow the same philosophy: you explicitly check for errors or expected states and <code>.Fail</code> the test if you want.</p>
<h3 id="even-if-its-young-it-has-a-decent-library">Even if it’s young it has a decent library</h3>
<p>I wrote <a href="https://github.com/FiloSottile/TripleSec/">Golang TripleSec</a> using only standard and <code>go.crypto</code> libraries. And they are fast and pretty. (Ok, I’m cheating, there’s Adam writing Go crypto libs, but also the rest is good!)</p>
<p>Also, thanks to point 1, it’s seamless to use external libraries, obviously.</p>
<h3 id="theres-no-pointer-arithmetics-but-no-flexibility-is-lost">There’s no pointer arithmetics but no flexibility is lost</h3>
<p>Go has no low-level memory arithmetics, but pointers, <code>&</code> and <code>*</code> are still there for your usual pass-by-pointer needs. This alone kills a lot of complexity and potential bugs.</p>
<p>However flexible array pointers are still there, on disguise: they are called <strong>slices</strong>, actually just a struct of a pointer, a own length and a length of the underlying allocated memory (<em>capacity</em>). The built-in length means that APIs don’t need to explicitly pass it around and built-in capacity means no more silent overflows and segfaults. A bunch of built-ins come bundled to seamlessly handle length, capacity, copying and reallocation.</p>
<p>It’s how C arrays should have always worked if performance wasn’t prioritized over simplicity, security… everything, actually.</p>
<h3 id="it-made-the-heartbleed-checker-possible">It made the Heartbleed checker possible</h3>
<p>A new one: thanks to the crypto/tls library I wrote <a href="http://filippo.io/Heartbleed/">the Heartbleed checker</a> in one hour, plus a couple for the web side (but I’m just a bad web developer).</p>
<p>Then rewriting the backed entirely in Go allowed me to scale to 12,000 requests a minute over 40 machines, each of them requiring me to open a HTTPS connection and potentially wait some seconds.</p>
<hr />
<p>So, this is a quick recap of what I loved about programming in Go. I probably missed something and will be adding things over time.</p>
<p>If you want to share your opinion on Go, I’m <a href="https://twitter.com/FiloSottile">@FiloSottile</a> on Twitter. And if you’ve never tried Go, give it a shot! It’s not only about concurrency!</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[My remote shell session setup]]></title>
<link href="https://filippo.io/my-remote-shell-session-setup/"/>
<updated>2014-03-18T04:08:00+01:00</updated>
<id>https://filippo.io/my-remote-shell-session-setup</id>
<content type="html"><![CDATA[<p>It’s 2014 and I feel entitled to a good experience connecting to a remote server, instead the default still feels like <code>telnet</code>.</p>
<p>After searching for quite a long time, I finally built my dream setup. These were the requirements:</p>
<ul>
<li>I want a single window/tab/panel of the terminal I’m using to be dedicated to the remote shell (without any new window, etc.)</li>
<li>I want the shell to survive unaffected with no context loss the following events
<ul>
<li>connection failure</li>
<li>route change (like, toggling the VPN or changing Wi-fi)</li>
<li>laptop sleep (like, me closing the lid)</li>
<li>local terminal restart or laptop reboot</li>
</ul>
</li>
<li>I want to be able to scroll back with my touchpad</li>
<li>I want to be able to copy-paste</li>
<li>I want colors</li>
<li>I want to launch it with a single command</li>
</ul>
<p>And a unicorn.</p>
<!-- more -->
<p>(Some fellow travelers in search for the same utopia are <a href="">here</a>)</p>
<h2 id="the-setup">The setup</h2>
<p>I managed to get this with the following combination: iTerm2 + mosh + tmux.</p>
<h3 id="iterm2">iTerm2</h3>
<p>The terminal.</p>
<p>I’m on the nightly, but stable should work the same. Just make sure to <em>Enable xterm mouse reporting</em> in the <em>Terminal</em> Profile settings, and set <em>Terminal Type</em> to <code>xterm-256color</code>.</p>
<h3 id="tmux">tmux</h3>
<p>The session manager.</p>
<p><code>tmux</code> is the new <code>screen</code>. It has a ton of features, but I’m using it here just to keep track of my session server side. On 1.8 right now, the one that comes in packages.</p>
<p><code>~/.tmux.conf</code>:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
</pre></td><td class="code"><pre><code class=""><span class="line">new-session
</span><span class="line">set-window-option -g mode-mouse on
</span><span class="line">set -g history-limit 30000</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>The first line makes sure that if I try to attach and no sessions are alive, one is created. This means that I can invoke it like this <code>tmux a</code> all the time.</p>
<p>The second enables mouse interactions. This will allow us to scroll with the touchpad! (See below)</p>
<p>NOTE: the key combination to detach is <code>C-b d</code>.</p>
<p><a href="https://superuser.com/questions/210125/scroll-shell-output-with-mouse-in-tmux">Here</a> a decent explanation of <code>tmux</code> and mouse scrolling.</p>
<h3 id="mosh">mosh</h3>
<p>The bridge.</p>
<p><code>mosh</code> is an awesome piece of software. All network-interacting software should behave like it. It will withstand whatever you throw at it from the network. It will even tell you when and since when your connection went down.</p>
<p>Sadly the latest release is ooooold, and doesn’t support mouse reporting. So no scrolling. Sigh.</p>
<p>So, you have to build from git.</p>
<p>On OS X: <code>brew install --HEAD mobile-shell</code></p>
<p>On the server:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
</pre></td><td class="code"><pre><code class=""><span class="line">git clone https://github.com/keithw/mosh.git
</span><span class="line">cd mosh/
</span><span class="line">sudo apt-get build-dep mosh
</span><span class="line">./autogen.sh && ./configure && make
</span><span class="line">sudo make install</span></code></pre></td></tr></table></div></figure></notextile></div>
<p><a href="https://github.com/keithw/mosh/issues/101">Here</a> the issue and <a href="https://github.com/keithw/mosh/pull/461">here</a> the PR about mouse reporting.</p>
<h2 id="result">Result</h2>
<p>The result is that I can type</p>
<div class="bogus-wrapper"><notextile><figure class="code"><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class=""><span class="line">mosh HOST -- tmux a</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>and get my motherfucking shell. Period.</p>
<p>iTerm2 will show me things, <code>mosh</code> will make sure that my connection stays up in all the aforementioned cases and <code>tmux</code> will keep my scrollback and allow me to detach and reattach. <code>mosh</code> and <code>tmux</code> collaborating, finally, will allow me to use my dear touchpad. Done.</p>
<p>NOTE: to select text “on the client side”, in order to copy/paste, you’ll have to hold the Option key.</p>
<h2 id="future-work">Future work</h2>
<ul>
<li>Scrolling is way less fluid than native. I have no idea how to fix this.</li>
<li>I’d like click+drag not to be relayed so that I don’t have to hold Option to select.</li>
</ul>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Native scrolling and iTerm2]]></title>
<link href="https://filippo.io/native-scrolling-and-iterm2/"/>
<updated>2014-03-13T03:15:00+01:00</updated>
<id>https://filippo.io/native-scrolling-and-iterm2</id>
<content type="html"><![CDATA[<p><strong>tl;dr</strong> See the bullet points for the supported programs and the last paragraph for installation.</p>
<p>Something I always wanted is native touchpad/mousewheel scrolling in all my terminal programs.</p>
<p><a href="https://bitheap.org/mouseterm/">MouseTerm</a> hacks that into the OS X Terminal, but I am a iTerm2 user.</p>
<p>I tried and gave up researching this a while ago, but today I got a notification from a Google Code bug I starred linking to <a href="https://code.google.com/p/iterm2/issues/detail?id=974">this</a>. Someone actually patched support for this a while ago, and someone else now updated the patch for current git!</p>
<!-- more -->
<p>The patch worked like a charm. It basically send arrow keystrokes on mousewheel when the terminal is in alternate mode. The actual logic amounts to this, reworked by me:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
<span class="line-number">8</span>
<span class="line-number">9</span>
<span class="line-number">10</span>
<span class="line-number">11</span>
<span class="line-number">12</span>
<span class="line-number">13</span>
<span class="line-number">14</span>
<span class="line-number">15</span>
</pre></td><td class="code"><pre><code class="obj-c"><span class="line"><span class="k">case</span> <span class="nl">MOUSE_REPORTING_NONE:</span>
</span><span class="line"> <span class="k">if</span> <span class="p">([[</span><span class="n">PreferencePanel</span> <span class="n">sharedInstance</span><span class="p">]</span> <span class="n">alternateMouseScroll</span><span class="p">]</span> <span class="o">&&</span>
</span><span class="line"> <span class="p">[</span><span class="n">_dataSource</span> <span class="n">isAlternate</span><span class="p">])</span> <span class="p">{</span>
</span><span class="line"> <span class="n">CGFloat</span> <span class="n">deltaY</span> <span class="o">=</span> <span class="p">[</span><span class="n">event</span> <span class="n">deltaY</span><span class="p">];</span>
</span><span class="line"> <span class="n">NSData</span><span class="o">*</span> <span class="n">keyMove</span><span class="p">;</span>
</span><span class="line"> <span class="k">if</span> <span class="p">(</span><span class="n">deltaY</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line"> <span class="n">keyMove</span> <span class="o">=</span> <span class="p">[</span><span class="n">terminal</span><span class="p">.</span><span class="n">output</span> <span class="nl">keyArrowUp:</span><span class="p">[</span><span class="n">event</span> <span class="n">modifierFlags</span><span class="p">]];</span>
</span><span class="line"> <span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="n">deltaY</span> <span class="o"><</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line"> <span class="n">keyMove</span> <span class="o">=</span> <span class="p">[</span><span class="n">terminal</span><span class="p">.</span><span class="n">output</span> <span class="nl">keyArrowDown:</span><span class="p">[</span><span class="n">event</span> <span class="n">modifierFlags</span><span class="p">]];</span>
</span><span class="line"> <span class="p">}</span>
</span><span class="line"> <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">ceil</span><span class="p">(</span><span class="n">fabs</span><span class="p">(</span><span class="n">deltaY</span><span class="p">));</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span><span class="line"> <span class="p">[</span><span class="n">_delegate</span> <span class="nl">writeTask:</span><span class="n">keyMove</span><span class="p">];</span>
</span><span class="line"> <span class="p">}</span>
</span><span class="line"> <span class="k">return</span><span class="p">;</span>
</span><span class="line"> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>I tested and confirmed compatibility with:</p>
<ul>
<li><code>less</code></li>
<li><code>vim</code></li>
<li><code>screen</code> (after the <code>C-a ESC</code> escape - <code>ESC</code> to exit)</li>
<li><code>tmux</code> (after the <code>C-b [</code> escape - <code>q</code> to exit)</li>
<li>all of the above over <code>ssh</code> and <code>mosh</code></li>
</ul>
<p>In particular the point about <code>mosh</code> and <code>screen</code> makes me happy, since this allows me to use them together to get session resuming and native scrollback - fixing <a href="https://github.com/keithw/mosh/issues/122">what annoyed me (and others) most of mosh</a>.</p>
<p>I took the patch, wrapped it in a hidden (not exposed) setting, and submitted as a <a href="https://github.com/gnachman/iTerm2/pull/164">Pull Request</a>. iTerm2 author was quick to suggest changes to the code and then to merge.</p>
<p>By the way, iTerm2 builds so pleasantly with a simple run of <code>xcodebuild</code>!</p>
<p>This means that it should be in the Nightly builds from tomorrow. To activate it just run</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class="bash"><span class="line"><span class="nv">$ </span>defaults write com.googlecode.iterm2 AlternateMouseScroll -bool <span class="nb">true</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Scraping the hell out of a more stubborn site]]></title>
<link href="https://filippo.io/scraping-a-video-out-of-a-more-stubborn-site/"/>
<updated>2014-02-03T03:47:00+01:00</updated>
<id>https://filippo.io/scraping-a-video-out-of-a-more-stubborn-site</id>
<content type="html"><![CDATA[<p><em>This is the second post speaking about writing <strong>youtube-dl IEs</strong>, all the basics are <a href="https://filippo.io/add-support-for-a-new-video-site-to-youtube-dl/">here</a>.</em></p>
<p>So as promised let’s have a look at something a bit more uncooperative: <strong>TopVideo.cc</strong>.</p>
<p>This is a kind of more shady site: it has changed gTLD at least once, it’s full of ads and fishy stuff and for our amazement, does not really like the idea of being scraped.</p>
<p>First of all: <strong>familiarize with the watch flow</strong>. I downloaded a CC-BY-SA video from YouTube (turns out you can filter for them!) and uploaded it to TopVideo. Here is it: <a href="http://www.topvideo.cc/4w1c85nzsbj0">http://www.topvideo.cc/4w1c85nzsbj0</a>.</p>
<p><em>Tip</em>: try first with an ad blocker, it will make everything (interacting with the site, inspecting requests…) far more pleasant, easy and secure. If it does not break your browser playback, it won’t break your reverse engineering.</p>
<p><em>Note</em>: this time writing the <code>_VALID_URL</code> regex and the like is left to the reader. Just consider that the filename or other stuff might be added to the URL and that they were <code>topvideo.tv</code> before. If this confuses you, check my <a href="https://filippo.io/add-support-for-a-new-video-site-to-youtube-dl/">previous post</a>. </p>
<p>Visiting the main link brings us to a page with no content except some scams and a <strong>“Proceed to video!” button</strong>.</p>
<p><img src="https://filippo.io/images/Watch Minecraft Timelapse Volcanic Island veu6DfOTNv0 mp4 2014-02-03 04-02-38.png" alt="The first page" class="center" /></p>
<p>So what is probably happening here is that they are having us <strong>acquire some sort of session ticket</strong> to see the video, or basically making us go through one more hop of ads/scraping deterrent.</p>
<p>Clicking on the button leads us to the real video page.</p>
<p><img src="https://filippo.io/images/Watch Minecraft Timelapse Volcanic Island veu6DfOTNv0 mp4 2014-02-03 04-12-55.png" alt="The video page" class="center" /></p>
<p>(Let’s take a note of that embed stuff below, if reversing this page turns out to be crazy difficult the embed html might be a softer target.)</p>
<p>So, a <strong>Flash player</strong>. If we are lucky (the norm) the video URL will be around in the source, in some <code><script></code> tag, under names like <em>player options</em>. (If we are not some logic will be embedded in the Flash swf and we will have to emulate that.)</p>
<p>To figure out what we should be looking for we kick open the <strong>Network tab</strong> of the Developer Tools, start the video, and watch what happens.</p>
<p><img src="https://filippo.io/images/Watch Minecraft Timelapse Volcanic Island veu6DfOTNv0 mp4 2014-02-03 04-25-46.png" alt="MP4 request" /></p>
<p><strong>No intermediate requests seem to be spawned, and this mp4 starts downloading. Nice.</strong> Now, where did it get the url from?</p>
<p>Let’s start grabbing pieces of that url and scouring the page source for them. The long alphanumeric string doesn’t disappoint us, and turns out an <strong>exact match</strong>. Got you!</p>
<p><img src="https://filippo.io/images/view-source-www.topvideo.cc-4w1c85nzsbj0 2014-02-03 04-33-03.png" alt="Match!" class="center" /></p>
<p><em>Tip</em>: <code>jwplayer</code> is a good ⌘F target for a lot of sites. </p>
<p>But… Hm. It’s not nice you know? At this point you can either spot that <code>eval</code> at the beginning, turn it to a <code>console.log</code> and <strong>have the code deobfuscate for you</strong> or be sleep-deprivated as I was at the time and start reversing the thing. (I stopped when <a href="http://jsbeautifier.org/">jsbeautifier.org</a> kindly deobfuscated it for me.)</p>
<p>Aaaaaand, there it is!</p>
<p><img src="https://filippo.io/images/Online JavaScript beautifier 2014-02-03 04-47-24.png" alt="De-obfuscated" /></p>
<p>Some Googling will reveal the obfuscator as an old version (?) of <a href="http://dean.edwards.name/packer/">dean.edwards.name/packer/</a> with “Base62 encode” turned on.</p>
<h2 id="ok-lets-write-some-code">Ok, let’s write some code</h2>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Add support for a new video site to youtube-dl]]></title>
<link href="https://filippo.io/add-support-for-a-new-video-site-to-youtube-dl/"/>
<updated>2014-01-27T02:12:00+01:00</updated>
<id>https://filippo.io/add-support-for-a-new-video-site-to-youtube-dl</id>
<content type="html"><![CDATA[<p><a href="https://github.com/rg3/youtube-dl">youtube-dl</a> is a very feature packed command line video downloader. Contrary to what the name might make you think, it supports way more sites than YouTube. <strong>240</strong> as of <a href="https://github.com/rg3/youtube-dl/tree/5700e7792aed45d6504ae957610d8254d5bb073f"><code>5700e77</code></a>.</p>
<p>What makes this possible is the structure of ytdl and its awesome community: all the common stuff (CLI, Downloading, Postprocessing) is in the core, and websites support is added in a plugin fashion (with a lot of helper functions available). So anyone can add support for its favorite video site by using another plugin as a template, with no need to understand the whole codebase. And a lot of people indeed did: <a href="https://github.com/rg3/youtube-dl/pulls">we’re nearing <strong>500 Pull Requests</strong></a>!</p>
<p>So, what I’m going to show you today is how to add support to ytdl for a simple site (I picked <a href="https://vine.co/">Vine</a> for the tutorial) and how to contribute to ytdl in general.</p>
<!-- more -->
<h2 id="how-ytdl-is-organized">How ytdl is organized</h2>
<p>The website plugins are called Information Extractors – IE – and their role is clear and simple:</p>
<ol>
<li>they describe what URLs they are able to interpret (with a regex)</li>
<li>they get a input URL, usually interact with the site and return a dictionary of information about the video, including its video file URL and its title <em>(over-simplified)</em></li>
</ol>
<p>You can find IEs in <code>youtube_dl/extractor</code>.</p>
<p>The rest of ytdl deals with parsing the input arguments (<code>youtube_dl/__init__.py</code>), downloading the file (<code>youtube_dl.downloader</code>) and post-processing (<code>youtube_dl.postprocessor</code>)</p>
<h2 id="lets-get-started">Let’s get started</h2>
<p>Of course, if you didn’t already <code>git clone</code> ytdl GitHub repository and make sure it’s up-to-date.</p>
<p>Remove the existing Vine IE if you want to follow along the tutorial step by step</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
</pre></td><td class="code"><pre><code class="bash"><span class="line">rm youtube_dl/extractor/vine.py
</span><span class="line">sed -i <span class="s1">'/VineIE/d'</span> youtube_dl/extractor/__init__.py
</span></code></pre></td></tr></table></div></figure></notextile></div>
<h2 id="anatomy-of-a-ie">Anatomy of a IE</h2>
<p>We already know that a IE is found in <code>youtube_dl/extractor</code>, but how does it look like?</p>
<p>Each site has its own file, named <code>lowercase_site.py</code>. Inside it, a subclass of <code>youtube_dl.extractor.common.InfoExtractor</code> named <code>CameCaseSiteIE</code> is defined.</p>
<p>That subclass has a property, <code>_VALID_URL</code>, a regex that defines what URLs will be handled by the IE (a <code>re.match</code> is performed) and is usually reused to extract for example the video id.</p>
<p>The only other thing needed is the <code>_real_extract</code> method. It takes a URL as its only argument and return a list of dicts, one for each video (usually just one), with <em>at least</em> the following fields:</p>
<ul>
<li><code>id</code>: a short video id, should be unique for the site, usually it is site-internal</li>
<li><code>url</code>: the URL of the actual downloadable video file</li>
<li><code>ext</code>: the extension of the video file</li>
<li><code>title</code>: the human-readable full title of the video, all characters allowed, Unicode possibly</li>
</ul>
<p>So, this is how our bare VineIE should start looking like:</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
<span class="line-number">2</span>
<span class="line-number">3</span>
<span class="line-number">4</span>
<span class="line-number">5</span>
<span class="line-number">6</span>
<span class="line-number">7</span>
</pre></td><td class="code"><pre><code class="python"><span class="line"><span class="kn">from</span> <span class="nn">.common</span> <span class="kn">import</span> <span class="n">InfoExtractor</span>
</span><span class="line">
</span><span class="line"><span class="k">class</span> <span class="nc">VineIE</span><span class="p">(</span><span class="n">InfoExtractor</span><span class="p">):</span>
</span><span class="line"> <span class="n">_VALID_URL</span> <span class="o">=</span> <span class="s">r'(?:https?://)?(?:www\.)?vine\.co/.*'</span>
</span><span class="line">
</span><span class="line"> <span class="k">def</span> <span class="nf">_real_extract</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">):</span>
</span><span class="line"> <span class="k">return</span> <span class="p">[]</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>Finally, each IE is imported inside <code>youtube_dl/extractor/__init__.py</code> to be exposed. So, you’ll want to add a line like this to that file (please note that the IEs are alphabetically sorted)</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class="python"><span class="line"><span class="kn">from</span> <span class="nn">.vine</span> <span class="kn">import</span> <span class="n">VineIE</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>Just this line will be enough.</p>
<p><strong>A note about syntax</strong>: ytdl is a Python2/3 double codebase – that means, it runs both on Python 2 and Python 3, so be careful to use features and statements that are cross-compatible. You’ll find all the compatibility imports already done for you in <code>youtube_dl.utils</code>.</p>
<h2 id="how-to-run-it">How to run it</h2>
<p>Before digging deeper, let’s see how to test-run our development ytdl.</p>
<p>Since youtube_dl is a executable Python package, you can run it from inside your working directory like this</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>
</pre></td><td class="code"><pre><code class="python"><span class="line"><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">youtube_dl</span> <span class="n">URL</span>
</span></code></pre></td></tr></table></div></figure></notextile></div>
<p>So to run our Vine IE we would use something like</p>
<div class="bogus-wrapper"><notextile><figure class="code"><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class="line-number">1</span>